From 9382306fedf4a6db74bfce4a134ae1831531a4f8 Mon Sep 17 00:00:00 2001 From: Lawrence Lee Date: Wed, 5 Aug 2020 11:57:34 -0700 Subject: [PATCH] Add CIELAB lightness to waveform --- rtengine/improccoordinator.cc | 8 +++++++- rtengine/improccoordinator.h | 1 + rtengine/rtengine.h | 3 ++- rtgui/editorpanel.cc | 5 +++-- rtgui/editorpanel.h | 3 ++- rtgui/histogrampanel.cc | 31 +++++++++++++++++++++++++++---- rtgui/histogrampanel.h | 11 +++++++---- 7 files changed, 49 insertions(+), 13 deletions(-) diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 9c18d0fa2..a1648aeb4 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -1774,7 +1774,8 @@ void ImProcCoordinator::notifyHistogramChanged() waveformWidth, waveformRed.get(), waveformGreen.get(), - waveformBlue.get() + waveformBlue.get(), + waveformLuma.get() ); } } @@ -1905,18 +1906,22 @@ void ImProcCoordinator::updateWaveforms() waveformRed.reset(new int[waveformWidth][256]); waveformGreen.reset(new int[waveformWidth][256]); waveformBlue.reset(new int[waveformWidth][256]); + waveformLuma.reset(new int[waveformWidth][256]); } int (*red)[256] = waveformRed.get(); int (*green)[256] = waveformGreen.get(); int (*blue)[256] = waveformBlue.get(); + int (*luma)[256] = waveformLuma.get(); // Start with zero. const int waveformSize = 256 * waveformWidth; memset(waveformRed.get(), 0, waveformSize * sizeof(red[0][0])); memset(waveformGreen.get(), 0, waveformSize * sizeof(green[0][0])); memset(waveformBlue.get(), 0, waveformSize * sizeof(blue[0][0])); + memset(waveformLuma.get(), 0, waveformSize * sizeof(luma[0][0])); + constexpr float luma_factor = 255.f / 32768.f; for (int i = y1; i < y2; i++) { int ofs = (i * pW + x1) * 3; @@ -1924,6 +1929,7 @@ void ImProcCoordinator::updateWaveforms() red[j][workimg->data[ofs++]]++; green[j][workimg->data[ofs++]]++; blue[j][workimg->data[ofs++]]++; + luma[j][(int)(nprevl->L[i][j + x1] * luma_factor)]++; } } diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 14ee81934..5eeef3e9e 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -134,6 +134,7 @@ protected: std::unique_ptr waveformRed, waveformRedRaw; std::unique_ptr waveformGreen, waveformGreenRaw; std::unique_ptr waveformBlue, waveformBlueRaw; + std::unique_ptr waveformLuma; LUTf CAMBrightCurveJ, CAMBrightCurveQ; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 49f858cdc..aa5e6aed7 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -338,7 +338,8 @@ public: int waveformWidth, const int waveformRed[][256], const int waveformGreen[][256], - const int waveformBlue[][256] + const int waveformBlue[][256], + const int waveformLuma[][256] ) = 0; /** Tells which observable is notifying the listener. */ virtual void setObservable(HistogramObservable* observable) = 0; diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index e52c9f47a..2d3099727 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -2253,11 +2253,12 @@ void EditorPanel::histogramChanged( int waveformWidth, const int waveformRed[][256], const int waveformGreen[][256], - const int waveformBlue[][256] + const int waveformBlue[][256], + const int waveformLuma[][256] ) { if (histogramPanel) { - histogramPanel->histogramChanged(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw, vectorscopeScale, vectorscope, waveformScale, waveformWidth, waveformRed, waveformGreen, waveformBlue); + histogramPanel->histogramChanged(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw, vectorscopeScale, vectorscope, waveformScale, waveformWidth, waveformRed, waveformGreen, waveformBlue, waveformLuma); } tpc->updateCurveBackgroundHistogram(histToneCurve, histLCurve, histCCurve, histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma, histLRETI); diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index b9d196ccd..ed34c1931 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -134,7 +134,8 @@ public: int waveformWidth, const int waveformRed[][256], const int waveformGreen[][256], - const int waveformBlue[][256] + const int waveformBlue[][256], + const int waveformLuma[][256] ) override; void setObservable(rtengine::HistogramObservable* observable) override; bool updateHistogram(void) override; diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index 4519bd438..3c5fd4719 100644 --- a/rtgui/histogrampanel.cc +++ b/rtgui/histogrampanel.cc @@ -379,7 +379,7 @@ void HistogramPanel::type_changed() showRed->set_sensitive(); showGreen->set_sensitive(); showBlue->set_sensitive(); - showValue->set_sensitive(false); + showValue->set_sensitive(); showChro->set_sensitive(false); showRAW->set_sensitive(false); showMode->set_sensitive(false); @@ -663,7 +663,7 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin drawBar(cc, b, 255.0, winw, winh, s); } - if((needLuma || needChroma) && options.histogramScopeType == 0) { + if((needLuma || needChroma) && options.histogramScopeType <= 1) { float Lab_L, Lab_a, Lab_b; rtengine::Color::rgb2lab01(profile, profileW, r / 255.f, g / 255.f, b / 255.f, Lab_L, Lab_a, Lab_b, options.rtSettings.HistogramWorking); @@ -673,7 +673,7 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin drawBar(cc, Lab_L, 100.0, winw, winh, s); } - if (needChroma) { + if (needChroma && options.histogramScopeType == 0) { // Chroma double chromaval = sqrt(Lab_a * Lab_a + Lab_b * Lab_b) / 1.8; cc->set_source_rgb(0.9, 0.9, 0.0); @@ -960,7 +960,8 @@ void HistogramArea::update( int waveformWidth, const int waveformRed[][256], const int waveformGreen[][256], - const int waveformBlue[][256] + const int waveformBlue[][256], + const int waveformLuma[][256] ) { if (histRed) { @@ -980,13 +981,16 @@ void HistogramArea::update( rwave.reset(new int[waveformWidth][256]); gwave.reset(new int[waveformWidth][256]); bwave.reset(new int[waveformWidth][256]); + lwave.reset(new int[waveformWidth][256]); } int (* const rw)[256] = rwave.get(); int (* const gw)[256] = gwave.get(); int (* const bw)[256] = bwave.get(); + int (* const lw)[256] = lwave.get(); memcpy(rw, waveformRed, 256 * waveformWidth * sizeof(rw[0][0])); memcpy(gw, waveformGreen, 256 * waveformWidth * sizeof(gw[0][0])); memcpy(bw, waveformBlue, 256 * waveformWidth * sizeof(bw[0][0])); + memcpy(lw, waveformLuma, 256 * waveformWidth * sizeof(lw[0][0])); wave_buffer_dirty = true; } else if (scopeType >= 2) { vectorscope_scale = vectorscopeScale; @@ -1392,9 +1396,11 @@ void HistogramArea::drawWaveform(Cairo::RefPtr &cr, int w, int h if (wave_buffer_dirty) { wave_buffer.reset(new unsigned char[256 * cairo_stride]); + wave_buffer_luma.reset(new unsigned char[256 * cairo_stride]); // Clear waveform. memset(wave_buffer.get(), 0, 256 * cairo_stride); + memset(wave_buffer_luma.get(), 0, 256 * cairo_stride); // TODO: Optimize. for (int col = 0; col < waveform_width; col++) { @@ -1413,6 +1419,16 @@ void HistogramArea::drawWaveform(Cairo::RefPtr &cr, int w, int h } } + if (needLuma) { + for (int col = 0; col < waveform_width; col++) { + for (int val = 0; val < 256; val++) { + const unsigned char l = min(scale * lwave[col][val], 0xff); + *(uint32_t*)&(wave_buffer_luma[(255 - val) * cairo_stride + col * 4]) = + l | (l << 8) | (l << 16) | (l << 24); + } + } + } + wave_buffer_dirty = false; } @@ -1424,6 +1440,13 @@ void HistogramArea::drawWaveform(Cairo::RefPtr &cr, int w, int h cr->set_source(surface, 0, 0); cr->set_operator(Cairo::OPERATOR_OVER); cr->paint(); + if (needLuma) { + surface = Cairo::ImageSurface::create( + wave_buffer_luma.get(), Cairo::FORMAT_ARGB32, waveform_width, 256, cairo_stride); + cr->set_source(surface, 0, 0); + cr->set_operator(Cairo::OPERATOR_OVER); + cr->paint(); + } surface->finish(); cr->set_matrix(orig_matrix); } diff --git a/rtgui/histogrampanel.h b/rtgui/histogrampanel.h index 864fc3fb6..227001845 100644 --- a/rtgui/histogrampanel.h +++ b/rtgui/histogrampanel.h @@ -167,8 +167,9 @@ protected: bool vect_buffer_dirty; int waveform_scale; int waveform_width; - std::unique_ptr rwave, gwave, bwave; + std::unique_ptr rwave, gwave, bwave, lwave; std::unique_ptr wave_buffer; + std::unique_ptr wave_buffer_luma; bool wave_buffer_dirty; bool valid; @@ -206,7 +207,8 @@ public: int waveformWidth, const int waveformRed[][256], const int waveformGreen[][256], - const int waveformBlue[][256] + const int waveformBlue[][256], + const int waveformLuma[][256] ); void updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, int mode, int type); void on_realize() override; @@ -309,10 +311,11 @@ public: int waveformWidth, const int waveformRed[][256], const int waveformGreen[][256], - const int waveformBlue[][256] + const int waveformBlue[][256], + const int waveformLuma[][256] ) { - histogramArea->update(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw, vectorscopeScale, vectorscope, waveformScale, waveformWidth, waveformRed, waveformGreen, waveformBlue); + histogramArea->update(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw, vectorscopeScale, vectorscope, waveformScale, waveformWidth, waveformRed, waveformGreen, waveformBlue, waveformLuma); } // pointermotionlistener interface void pointerMoved (bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int x, int y, int r, int g, int b, bool isRaw = false) override;