Merge pull request #5887 from Beep6581/waveform

Waveform, RGB parade, and vectorscopes
This commit is contained in:
Lawrence37
2020-10-23 09:57:40 -07:00
committed by GitHub
22 changed files with 2616 additions and 265 deletions

View File

@@ -21,6 +21,7 @@
#include <iostream>
#include "../rtengine/array2D.h"
#include "../rtengine/imagesource.h"
#include "../rtengine/iccstore.h"
#include "batchqueue.h"
@@ -47,6 +48,8 @@
using namespace rtengine::procparams;
using ScopeType = Options::ScopeType;
namespace
{
@@ -470,7 +473,8 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
iBeforeLockON (nullptr), iBeforeLockOFF (nullptr), previewHandler (nullptr), beforePreviewHandler (nullptr),
beforeIarea (nullptr), beforeBox (nullptr), afterBox (nullptr), beforeLabel (nullptr), afterLabel (nullptr),
beforeHeaderBox (nullptr), afterHeaderBox (nullptr), parent (nullptr), parentWindow (nullptr), openThm (nullptr),
selectedFrame(0), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false)
selectedFrame(0), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false),
histogram_observable(nullptr), histogram_scope_type(ScopeType::NONE)
{
epih = new EditorPanelIdleHelper;
@@ -2245,16 +2249,94 @@ void EditorPanel::histogramChanged(
const LUTu& histGreenRaw,
const LUTu& histBlueRaw,
const LUTu& histChroma,
const LUTu& histLRETI
const LUTu& histLRETI,
int vectorscopeScale,
const array2D<int>& vectorscopeHC,
const array2D<int>& vectorscopeHS,
int waveformScale,
const array2D<int>& waveformRed,
const array2D<int>& waveformGreen,
const array2D<int>& waveformBlue,
const array2D<int>& waveformLuma
)
{
if (histogramPanel) {
histogramPanel->histogramChanged(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw);
histogramPanel->histogramChanged(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw, vectorscopeScale, vectorscopeHC, vectorscopeHS, waveformScale, waveformRed, waveformGreen, waveformBlue, waveformLuma);
}
tpc->updateCurveBackgroundHistogram(histToneCurve, histLCurve, histCCurve, histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma, histLRETI);
}
void EditorPanel::setObservable(rtengine::HistogramObservable* observable)
{
histogram_observable = observable;
}
bool EditorPanel::updateHistogram(void) const
{
return histogram_scope_type == ScopeType::HISTOGRAM
|| histogram_scope_type == ScopeType::NONE;
}
bool EditorPanel::updateHistogramRaw(void) const
{
return histogram_scope_type == ScopeType::HISTOGRAM_RAW
|| histogram_scope_type == ScopeType::NONE;
}
bool EditorPanel::updateVectorscopeHC(void) const
{
return
histogram_scope_type == ScopeType::VECTORSCOPE_HC
|| histogram_scope_type == ScopeType::NONE;
}
bool EditorPanel::updateVectorscopeHS(void) const
{
return
histogram_scope_type == ScopeType::VECTORSCOPE_HS
|| histogram_scope_type == ScopeType::NONE;
}
bool EditorPanel::updateWaveform(void) const
{
return histogram_scope_type == ScopeType::WAVEFORM
|| histogram_scope_type == ScopeType::PARADE
|| histogram_scope_type == ScopeType::NONE;
}
void EditorPanel::scopeTypeChanged(ScopeType new_type)
{
histogram_scope_type = new_type;
if (!histogram_observable) {
return;
}
// Make sure the new scope is updated since we only actively update the
// current scope.
switch (new_type) {
case ScopeType::HISTOGRAM:
histogram_observable->requestUpdateHistogram();
break;
case ScopeType::HISTOGRAM_RAW:
histogram_observable->requestUpdateHistogramRaw();
break;
case ScopeType::VECTORSCOPE_HC:
histogram_observable->requestUpdateVectorscopeHC();
break;
case ScopeType::VECTORSCOPE_HS:
histogram_observable->requestUpdateVectorscopeHS();
break;
case ScopeType::PARADE:
case ScopeType::WAVEFORM:
histogram_observable->requestUpdateWaveform();
break;
case ScopeType::NONE:
break;
}
}
bool EditorPanel::CheckSidePanelsVisibility()
{
if (tbTopPanel_1) {
@@ -2371,6 +2453,10 @@ void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition)
break;
}
if (histogramPanel) {
histogramPanel->setPanelListener(this);
}
iareapanel->imageArea->setPointerMotionHListener (histogramPanel);
}

View File

@@ -32,6 +32,12 @@
#include "../rtengine/noncopyable.h"
#include "../rtengine/rtengine.h"
namespace rtengine
{
template<typename T>
class array2D;
}
class BatchQueueEntry;
class EditorPanel;
class FilePanel;
@@ -55,6 +61,7 @@ class EditorPanel final :
public ThumbnailListener,
public HistoryBeforeLineListener,
public rtengine::HistogramListener,
public HistogramPanelListener,
public rtengine::NonCopyable
{
public:
@@ -126,8 +133,25 @@ public:
const LUTu& histGreenRaw,
const LUTu& histBlueRaw,
const LUTu& histChroma,
const LUTu& histLRETI
const LUTu& histLRETI,
int vectorscopeScale,
const array2D<int>& vectorscopeHC,
const array2D<int>& vectorscopeHS,
int waveformScale,
const array2D<int>& waveformRed,
const array2D<int>& waveformGreen,
const array2D<int>& waveformBlue,
const array2D<int>& waveformLuma
) override;
void setObservable(rtengine::HistogramObservable* observable) override;
bool updateHistogram(void) const override;
bool updateHistogramRaw(void) const override;
bool updateVectorscopeHC(void) const override;
bool updateVectorscopeHS(void) const override;
bool updateWaveform(void) const override;
// HistogramPanelListener
void scopeTypeChanged(Options::ScopeType new_type) override;
// event handlers
void info_toggled ();
@@ -260,4 +284,7 @@ private:
bool isProcessing;
IdleRegister idle_register;
rtengine::HistogramObservable* histogram_observable;
Options::ScopeType histogram_scope_type;
};

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,8 @@
*/
#pragma once
#include <vector>
#include <gtkmm.h>
#include <glibmm/ustring.h>
@@ -26,8 +28,10 @@
#include "delayed.h"
#include "guiutils.h"
#include "options.h"
#include "pointermotionlistener.h"
#include "../rtengine/array2D.h"
#include "../rtengine/LUT.h"
#include "../rtengine/noncopyable.h"
@@ -54,7 +58,7 @@ public:
double log (double vsize, double val);
};
class HistogramRGBArea final : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling, public rtengine::NonCopyable
class HistogramRGBArea : public Gtk::DrawingArea, public BackBuffer, protected HistogramScaling, public rtengine::NonCopyable
{
private:
typedef const double (*TMatrix)[3];
@@ -74,7 +78,6 @@ protected:
bool needBlue;
bool needLuma;
bool needChroma;
bool rawMode;
bool showMode;
bool barDisplayed;
@@ -84,32 +87,58 @@ protected:
HistogramRGBAreaIdleHelper* harih;
/** Draw an indicator bar for the value. */
virtual void drawBar(Cairo::RefPtr<Cairo::Context> cc, double value, double max_value, int winw, int winh, double scale) = 0;
void getPreferredThickness(int& min_thickness, int& natural_length) const;
void getPreferredLength(int& min_length, int& natural_length) const;
void getPreferredThicknessForLength(int length, int& min_thickness, int& natural_length) const;
void getPreferredLengthForThickness(int thickness, int& min_length, int& natural_length) const;
public:
HistogramRGBArea();
~HistogramRGBArea() override;
void updateBackBuffer (int r, int g, int b, const Glib::ustring &profile = "", const Glib::ustring &profileW = "");
bool getShow ();
void setShow(bool show);
void setParent (Gtk::Grid* p)
{
parent = p;
};
void update (int val, int rh, int gh, int bh);
void updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, bool show);
void updateOptions (bool r, bool g, bool b, bool l, bool c, bool show);
void on_realize() override;
bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override;
bool on_button_press_event (GdkEventButton* event) override;
void factorChanged (double newFactor);
};
class HistogramRGBAreaHori final : public HistogramRGBArea
{
private:
void drawBar(Cairo::RefPtr<Cairo::Context> cc, double value, double max_value, int winw, int winh, double scale) override;
Gtk::SizeRequestMode get_request_mode_vfunc () const override;
void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override;
void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override;
void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const override;
void get_preferred_width_for_height_vfunc (int h, int &minimum_width, int &natural_width) const override;
};
class HistogramRGBAreaVert final : public HistogramRGBArea
{
private:
void drawBar(Cairo::RefPtr<Cairo::Context> cc, double value, double max_value, int winw, int winh, double scale) override;
Gtk::SizeRequestMode get_request_mode_vfunc () const override;
void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override;
void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override;
void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const override;
void get_preferred_width_for_height_vfunc (int h, int &minimum_width, int &natural_width) const override;
};
class DrawModeListener
@@ -123,7 +152,10 @@ class HistogramArea final : public Gtk::DrawingArea, public BackBuffer, private
{
public:
typedef sigc::signal<void, double> type_signal_factor_changed;
typedef sigc::signal<void, float> SignalBrightnessChanged;
static constexpr float MIN_BRIGHT = 0.1;
static constexpr float MAX_BRIGHT = 3;
private:
IdleRegister idle_register;
type_signal_factor_changed sigFactorChanged;
@@ -131,26 +163,49 @@ private:
protected:
LUTu rhist, ghist, bhist, lhist, chist;
LUTu rhistRaw, ghistRaw, bhistRaw, lhistRaw; //lhistRaw is unused?
int vectorscope_scale;
array2D<int> vect_hc, vect_hs;
std::vector<unsigned char> vect_hc_buffer, vect_hs_buffer;
bool vect_hc_buffer_dirty, vect_hs_buffer_dirty;
int waveform_scale;
array2D<int> rwave, gwave, bwave, lwave;
std::vector<unsigned char> parade_buffer_r;
std::vector<unsigned char> parade_buffer_g;
std::vector<unsigned char> parade_buffer_b;
bool parade_buffer_r_dirty, parade_buffer_g_dirty, parade_buffer_b_dirty;
std::vector<unsigned char> wave_buffer;
std::vector<unsigned char> wave_buffer_luma;
bool wave_buffer_dirty, wave_buffer_luma_dirty;
bool valid;
int drawMode;
DrawModeListener *myDrawModeListener;
Options::ScopeType scopeType;
int oldwidth, oldheight;
/// Intensity of waveform and vectorscope trace.
float trace_brightness;
bool needRed, needGreen, needBlue, needLuma, needChroma;
bool rawMode;
bool isPressed;
double movingPosition;
bool needPointer;
double padding = 5.0;
HistogramAreaIdleHelper* haih;
int pointer_red, pointer_green, pointer_blue;
float pointer_a, pointer_b;
SignalBrightnessChanged signal_brightness_changed;
public:
explicit HistogramArea(DrawModeListener *fml = nullptr);
~HistogramArea() override;
void updateBackBuffer ();
/// Update pointer values. Returns true if widget needs redrawing.
bool updatePointer(int r, int g, int b, const Glib::ustring &profile = "", const Glib::ustring &profileW = "");
void update(
const LUTu& histRed,
const LUTu& histGreen,
@@ -159,19 +214,35 @@ public:
const LUTu& histChroma,
const LUTu& histRedRaw,
const LUTu& histGreenRaw,
const LUTu& histBlueRaw
const LUTu& histBlueRaw,
int vectorscopeScale,
const array2D<int>& vectorscopeHC,
const array2D<int>& vectorscopeHS,
int waveformScale,
const array2D<int>& waveformRed,
const array2D<int>& waveformGreen,
const array2D<int>& waveformBlue,
const array2D<int>& waveformLuma
);
void updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, int mode);
void updateOptions (bool r, bool g, bool b, bool l, bool c, int mode, Options::ScopeType type, bool pointer);
bool updatePending();
void on_realize() override;
bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override;
bool on_button_press_event (GdkEventButton* event) override;
bool on_button_release_event (GdkEventButton* event) override;
bool on_motion_notify_event (GdkEventMotion* event) override;
float getBrightness(void);
/** Set the trace brightness, with 1 being normal. */
void setBrightness(float brightness);
SignalBrightnessChanged getBrighnessChangedSignal(void);
type_signal_factor_changed signal_factor_changed();
private:
void drawCurve(Cairo::RefPtr<Cairo::Context> &cr, const LUTu & data, double scale, int hsize, int vsize);
void drawMarks(Cairo::RefPtr<Cairo::Context> &cr, const LUTu & data, double scale, int hsize, int & ui, int & oi);
void drawParade(Cairo::RefPtr<Cairo::Context> &cr, int hsize, int vsize);
void drawVectorscope(Cairo::RefPtr<Cairo::Context> &cr, int hsize, int vsize);
void drawWaveform(Cairo::RefPtr<Cairo::Context> &cr, int hsize, int vsize);
Gtk::SizeRequestMode get_request_mode_vfunc () const override;
void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override;
void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override;
@@ -179,6 +250,12 @@ private:
void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override;
};
class HistogramPanelListener
{
public:
virtual void scopeTypeChanged(Options::ScopeType new_type) = 0;
};
class HistogramPanel final : public Gtk::Grid, public PointerMotionListener, public DrawModeListener, public rtengine::NonCopyable
{
private:
@@ -188,22 +265,33 @@ protected:
Gtk::Grid* gfxGrid;
Gtk::Grid* buttonGrid;
Gtk::Box* persistentButtons;
Gtk::Box* optionButtons;
HistogramArea* histogramArea;
HistogramRGBArea* histogramRGBArea;
std::unique_ptr<HistogramRGBAreaHori> histogramRGBAreaHori;
std::unique_ptr<HistogramRGBAreaVert> histogramRGBAreaVert;
Gtk::ToggleButton* showRed;
Gtk::ToggleButton* showGreen;
Gtk::ToggleButton* showBlue;
Gtk::ToggleButton* showValue;
Gtk::ToggleButton* showRAW;
Gtk::ToggleButton* showBAR;
Gtk::ToggleButton* showChro;
Gtk::Button* showMode;
Gtk::ToggleButton* scopeOptions;
Gtk::Scale* brightnessWidget;
Gtk::RadioButton* scopeHistBtn;
Gtk::RadioButton* scopeHistRawBtn;
Gtk::RadioButton* scopeParadeBtn;
Gtk::RadioButton* scopeWaveBtn;
Gtk::RadioButton* scopeVectHcBtn;
Gtk::RadioButton* scopeVectHsBtn;
Gtk::Image *redImage;
Gtk::Image *greenImage;
Gtk::Image *blueImage;
Gtk::Image *valueImage;
Gtk::Image *rawImage;
Gtk::Image *barImage;
Gtk::Image *chroImage;
@@ -211,7 +299,6 @@ protected:
Gtk::Image *greenImage_g;
Gtk::Image *blueImage_g;
Gtk::Image *valueImage_g;
Gtk::Image *rawImage_g;
Gtk::Image *barImage_g;
Gtk::Image *chroImage_g;
@@ -219,8 +306,14 @@ protected:
Gtk::Image *mode1Image;
Gtk::Image *mode2Image;
HistogramPanelListener* panel_listener;
sigc::connection brightness_changed_connection;
sigc::connection rconn;
void setHistInvalid ();
void showRGBBar();
void updateHistAreaOptions();
void updateHistRGBAreaOptions();
public:
@@ -235,9 +328,18 @@ public:
const LUTu& histChroma,
const LUTu& histRedRaw,
const LUTu& histGreenRaw,
const LUTu& histBlueRaw)
const LUTu& histBlueRaw,
int vectorscopeScale,
const array2D<int>& vectorscopeHC,
const array2D<int>& vectorscopeHS,
int waveformScale,
const array2D<int>& waveformRed,
const array2D<int>& waveformGreen,
const array2D<int>& waveformBlue,
const array2D<int>& waveformLuma
)
{
histogramArea->update(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw);
histogramArea->update(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw, vectorscopeScale, vectorscopeHC, vectorscopeHS, waveformScale, 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;
@@ -250,13 +352,19 @@ public:
void green_toggled ();
void blue_toggled ();
void value_toggled ();
void raw_toggled ();
void chro_toggled ();
void bar_toggled ();
void mode_released ();
void brightnessWidgetValueChanged();
void brightnessUpdated(float brightness);
void scopeOptionsToggled();
void type_selected(Gtk::RadioButton* button);
void type_changed ();
void rgbv_toggled ();
void resized (Gtk::Allocation& req);
// drawModeListener interface
void toggleButtonMode () override;
void setPanelListener(HistogramPanelListener* listener);
};

View File

@@ -446,10 +446,12 @@ void Options::setDefaults()
histogramBlue = true;
histogramLuma = false;
histogramChroma = false;
histogramRAW = false;
histogramBar = true;
histogramHeight = 200;
histogramDrawMode = 0;
histogramScopeType = ScopeType::HISTOGRAM;
histogramShowOptionButtons = false;
histogramTraceBrightness = 1;
curvebboxpos = 1;
complexity = 2;
prevdemo = PD_Sidecar;
@@ -1417,7 +1419,10 @@ void Options::readFromFile(Glib::ustring fname)
}
if (keyFile.has_key("GUI", "HistogramRAW")) {
histogramRAW = keyFile.get_boolean("GUI", "HistogramRAW");
// Legacy option, replaced by HistogramScopeType.
if (keyFile.get_boolean("GUI", "HistogramRAW")) {
histogramScopeType = ScopeType::HISTOGRAM_RAW;
}
}
if (keyFile.has_key("GUI", "HistogramBar")) {
@@ -1432,6 +1437,18 @@ void Options::readFromFile(Glib::ustring fname)
histogramDrawMode = keyFile.get_integer("GUI", "HistogramDrawMode");
}
if (keyFile.has_key("GUI", "HistogramScopeType")) {
histogramScopeType = static_cast<ScopeType>(keyFile.get_integer("GUI", "HistogramScopeType"));
}
if (keyFile.has_key("GUI", "HistogramShowOptionButtons")) {
histogramShowOptionButtons = keyFile.get_boolean("GUI", "HistogramShowOptionButtons");
}
if (keyFile.has_key("GUI", "HistogramTraceBrightness")) {
histogramTraceBrightness = keyFile.get_double("GUI", "HistogramTraceBrightness");
}
if (keyFile.has_key("GUI", "NavigatorRGBUnit")) {
navRGBUnit = (NavigatorUnit)keyFile.get_integer("GUI", "NavigatorRGBUnit");
}
@@ -2251,10 +2268,12 @@ void Options::saveToFile(Glib::ustring fname)
keyFile.set_boolean("GUI", "HistogramBlue", histogramBlue);
keyFile.set_boolean("GUI", "HistogramLuma", histogramLuma);
keyFile.set_boolean("GUI", "HistogramChroma", histogramChroma);
keyFile.set_boolean("GUI", "HistogramRAW", histogramRAW);
keyFile.set_boolean("GUI", "HistogramBar", histogramBar);
keyFile.set_integer("GUI", "HistogramHeight", histogramHeight);
keyFile.set_integer("GUI", "HistogramDrawMode", histogramDrawMode);
keyFile.set_integer("GUI", "HistogramScopeType", rtengine::toUnderlying(histogramScopeType));
keyFile.set_boolean("GUI", "HistogramShowOptionButtons", histogramShowOptionButtons);
keyFile.set_double("GUI", "HistogramTraceBrightness", histogramTraceBrightness);
keyFile.set_integer("GUI", "NavigatorRGBUnit", (int)navRGBUnit);
keyFile.set_integer("GUI", "NavigatorHSVUnit", (int)navHSVUnit);
keyFile.set_boolean("GUI", "ShowFilmStripToolBar", showFilmStripToolBar);

View File

@@ -168,13 +168,23 @@ private:
const Glib::ustring& entryName, Glib::ustring& destination);
public:
enum class NavigatorUnit {
PERCENT,
R0_255,
R0_1,
_COUNT
};
enum class ScopeType {
NONE = -1,
HISTOGRAM,
HISTOGRAM_RAW,
PARADE,
VECTORSCOPE_HC,
VECTORSCOPE_HS,
WAVEFORM
};
bool savesParamsAtExit;
SaveFormat saveFormat, saveFormatBatch;
Glib::ustring savePathTemplate;
@@ -308,10 +318,13 @@ public:
int histogramPosition; // 0=disabled, 1=left pane, 2=right pane
bool histogramRed, histogramGreen, histogramBlue;
bool histogramLuma, histogramChroma, histogramRAW;
bool histogramLuma, histogramChroma;
bool histogramBar;
int histogramHeight;
int histogramDrawMode;
ScopeType histogramScopeType;
bool histogramShowOptionButtons;
float histogramTraceBrightness;
bool FileBrowserToolbarSingleRow;
bool hideTPVScrollbar;
int whiteBalanceSpotSize;