From 11e7739a557365f726e40712f0a33fc1924a5309 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 20 Sep 2018 14:41:29 +0200 Subject: [PATCH 1/2] Added option to use a non-linear response for Adjuster sliders Some of the RT parameters that are currently associated to Adjusters are very hard to edit precisely by dragging the sliders, because small changes to the default produce quite visible results. Prominent examples include black level, WB tint, raw black and white points, and lens correction parameters (distortion, CA, vignetting, perspective). The problem is made worse for those settings in which not only small changes are significant, but also the associated Adjusters have a very large range (again, think of black point and WB tint). This is due to the fact that the current Adjusters have a linear response. This commit adds an option to use a non-linear (specifically logarithmic) response, which causes the sliders to move "slowly" around a designated pivot point, and progressively faster the further you move away from the pivot. Besides adding the functionality to the Adjuster class, this changeset also enables this behaviour for the following adjusters: - exposure compensation - black point - lightness/contrast/saturation/chromaticity (both in exposure and in L*a*b*) - WB tint - channel mixer - lens corrections (perspective, distortion, CA) - rotation - raw black and white points - raw CA correction --- rtgui/adjuster.cc | 97 +++++++++++++++++++++++++++++++++++--- rtgui/adjuster.h | 9 ++++ rtgui/bayerrawexposure.cc | 5 ++ rtgui/cacorrection.cc | 3 ++ rtgui/chmixer.cc | 4 ++ rtgui/distortion.cc | 3 ++ rtgui/labcurve.cc | 4 ++ rtgui/perspective.cc | 3 ++ rtgui/rawcacorrection.cc | 3 ++ rtgui/rawexposure.cc | 2 + rtgui/rotate.cc | 2 + rtgui/tonecurve.cc | 6 +++ rtgui/whitebalance.cc | 5 ++ rtgui/xtransrawexposure.cc | 4 ++ 14 files changed, 143 insertions(+), 7 deletions(-) diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc index 6260314b1..e0eb62a1f 100644 --- a/rtgui/adjuster.cc +++ b/rtgui/adjuster.cc @@ -46,6 +46,10 @@ Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep grid = NULL; imageIcon1 = imgIcon1; + logBase = 0; + logPivot = 0; + logAnchorMiddle = false; + if (imageIcon1) { setExpandAlignProperties(imageIcon1, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); } @@ -289,13 +293,13 @@ void Adjuster::resetValue (bool toInitial) if (toInitial) { // resetting to the initial editing value, when the image has been loaded - slider->set_value (addMode ? defaultVal : value2slider(defaultVal)); + setSliderValue(addMode ? defaultVal : value2slider(defaultVal)); } else { // resetting to the slider default value if (addMode) { - slider->set_value (0.); + setSliderValue(0.); } else { - slider->set_value (value2slider(ctorDefaultVal)); + setSliderValue(value2slider(ctorDefaultVal)); } } } @@ -333,7 +337,7 @@ void Adjuster::setLimits (double vmin, double vmax, double vstep, double vdefaul slider->set_digits (digits); slider->set_increments (vstep, 2.0 * vstep); slider->set_range (addMode ? vmin : value2slider(vmin), addMode ? vmax : value2slider(vmax)); - slider->set_value (addMode ? shapeValue(vdefault) : value2slider(shapeValue(vdefault))); + setSliderValue(addMode ? shapeValue(vdefault) : value2slider(shapeValue(vdefault))); //defaultVal = shapeValue (vdefault); sliderChange.block (false); spinChange.block (false); @@ -369,7 +373,7 @@ void Adjuster::spinChanged () } sliderChange.block (true); - slider->set_value (addMode ? spin->get_value () : value2slider(spin->get_value ())); + setSliderValue(addMode ? spin->get_value () : value2slider(spin->get_value ())); sliderChange.block (false); if (delay == 0) { @@ -409,7 +413,8 @@ void Adjuster::sliderChanged () } spinChange.block (true); - spin->set_value (addMode ? slider->get_value () : slider2value(slider->get_value ())); + double v = getSliderValue(); + spin->set_value (addMode ? v : slider2value(v)); spinChange.block (false); if (delay == 0 || afterReset) { @@ -447,7 +452,7 @@ void Adjuster::setValue (double a) spinChange.block (true); sliderChange.block (true); spin->set_value (shapeValue (a)); - slider->set_value (addMode ? shapeValue(a) : value2slider(shapeValue (a))); + setSliderValue(addMode ? shapeValue(a) : value2slider(shapeValue (a))); sliderChange.block (false); spinChange.block (false); afterReset = false; @@ -608,3 +613,81 @@ void Adjuster::trimValue (float &val) val = rtengine::LIM(val, static_cast(vMin), static_cast(vMax)); } + + +inline double Adjuster::getSliderValue() +{ + double val = slider->get_value(); + if (logBase) { + if (logAnchorMiddle) { + double mid = (vMax - vMin) / 2; + double mmid = vMin + mid; + if (val >= mmid) { + double range = vMax - mmid; + double x = (val - mmid) / range; + val = logPivot + (pow(logBase, x) - 1.0) / (logBase - 1.0) * (vMax - logPivot); + } else { + double range = mmid - vMin; + double x = (mmid - val) / range; + val = logPivot - (pow(logBase, x) - 1.0) / (logBase - 1.0) * (logPivot - vMin); + } + } else { + if (val >= logPivot) { + double range = vMax - logPivot; + double x = (val - logPivot) / range; + val = logPivot + (pow(logBase, x) - 1.0) / (logBase - 1.0) * range; + } else { + double range = logPivot - vMin; + double x = (logPivot - val) / range; + val = logPivot - (pow(logBase, x) - 1.0) / (logBase - 1.0) * range; + } + } + } + return val; +} + + +inline void Adjuster::setSliderValue(double val) +{ + if (logBase) { + if (logAnchorMiddle) { + double mid = (vMax - vMin) / 2; + if (val >= logPivot) { + double range = vMax - logPivot; + double x = (val - logPivot) / range; + val = (vMin + mid) + log(x * (logBase - 1.0) + 1.0) / log(logBase) * mid; + } else { + double range = logPivot - vMin; + double x = (logPivot - val) / range; + val = (vMin + mid) - log(x * (logBase - 1.0) + 1.0) / log(logBase) * mid; + } + } else { + if (val >= logPivot) { + double range = vMax - logPivot; + double x = (val - logPivot) / range; + val = logPivot + log(x * (logBase - 1.0) + 1.0) / log(logBase) * range; + } else { + double range = logPivot - vMin; + double x = (logPivot - val) / range; + val = logPivot - log(x * (logBase - 1.0) + 1.0) / log(logBase) * range; + } + } + } + slider->set_value(val); +} + + +void Adjuster::setLogScale(double base, double pivot, bool anchorMiddle) +{ + spinChange.block (true); + sliderChange.block (true); + + double cur = getSliderValue(); + logBase = base; + logPivot = pivot; + logAnchorMiddle = anchorMiddle; + setSliderValue(cur); + + sliderChange.block (false); + spinChange.block (false); +} diff --git a/rtgui/adjuster.h b/rtgui/adjuster.h index 768406a33..5b4d6f46d 100644 --- a/rtgui/adjuster.h +++ b/rtgui/adjuster.h @@ -71,10 +71,17 @@ protected: double vMax; double vStep; + double logBase; + double logPivot; + bool logAnchorMiddle; + double shapeValue (double a); void refreshLabelStyle (); double2double_fun value2slider, slider2value; + double getSliderValue(); + void setSliderValue(double val); + public: int delay; @@ -173,6 +180,8 @@ public: void trimValue (double &val); void trimValue (float &val); void trimValue (int &val); + + void setLogScale(double base, double pivot, bool anchorMiddle=false); }; #endif diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index 2194d1639..7a8f32389 100644 --- a/rtgui/bayerrawexposure.cc +++ b/rtgui/bayerrawexposure.cc @@ -65,6 +65,11 @@ BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, "bayerrawexposur pack_start( *PexBlack3, Gtk::PACK_SHRINK, 0);//black G2 pack_start( *PexBlack2, Gtk::PACK_SHRINK, 0);//black B pack_start( *PextwoGreen, Gtk::PACK_SHRINK, 0);//black 2 green + + PexBlack0->setLogScale(100, 0); + PexBlack1->setLogScale(100, 0); + PexBlack2->setLogScale(100, 0); + PexBlack3->setLogScale(100, 0); } void BayerRAWExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) diff --git a/rtgui/cacorrection.cc b/rtgui/cacorrection.cc index ffaa57c34..485a5e1cf 100644 --- a/rtgui/cacorrection.cc +++ b/rtgui/cacorrection.cc @@ -40,6 +40,9 @@ CACorrection::CACorrection () : FoldableToolPanel(this, "cacorrection", M("TP_CA pack_start (*red); pack_start (*blue); + red->setLogScale(10, 0); + blue->setLogScale(10, 0); + show_all(); } diff --git a/rtgui/chmixer.cc b/rtgui/chmixer.cc index 1e3bb395e..1a122ef6f 100644 --- a/rtgui/chmixer.cc +++ b/rtgui/chmixer.cc @@ -84,6 +84,10 @@ ChMixer::ChMixer (): FoldableToolPanel(this, "chmixer", M("TP_CHMIXER_LABEL"), f red[i]->setAdjusterListener (this); green[i]->setAdjusterListener (this); blue[i]->setAdjusterListener (this); + + red[i]->setLogScale(10, red[i]->getValue()); + green[i]->setLogScale(10, green[i]->getValue()); + blue[i]->setLogScale(10, blue[i]->getValue()); } pack_start (*blabel); diff --git a/rtgui/distortion.cc b/rtgui/distortion.cc index c181ed479..b6ad7cc03 100644 --- a/rtgui/distortion.cc +++ b/rtgui/distortion.cc @@ -41,6 +41,9 @@ Distortion::Distortion (): FoldableToolPanel(this, "distortion", M("TP_DISTORTIO distor = Gtk::manage (new Adjuster (M("TP_DISTORTION_AMOUNT"), -0.5, 0.5, 0.001, 0, idistL, idistR)); distor->setAdjusterListener (this); + + distor->setLogScale(2, 0); + distor->show(); pack_start (*distor); } diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index 1cde4262d..2669079ab 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -47,6 +47,10 @@ LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), contrast->setAdjusterListener (this); chromaticity->setAdjusterListener (this); + brightness->setLogScale(2, 0, true); + contrast->setLogScale(2, 0, true); + chromaticity->setLogScale(2, 0, true); + //%%%%%%%%%%%%%%%%%% Gtk::HSeparator *hsep2 = Gtk::manage (new Gtk::HSeparator()); hsep2->show (); diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index 1ca6e54b6..4bfcc1d7b 100644 --- a/rtgui/perspective.cc +++ b/rtgui/perspective.cc @@ -39,6 +39,9 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M(" pack_start (*horiz); pack_start (*vert); + horiz->setLogScale(2, 0); + vert->setLogScale(2, 0); + show_all(); } diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index bdcc13442..fd338a445 100644 --- a/rtgui/rawcacorrection.cc +++ b/rtgui/rawcacorrection.cc @@ -63,6 +63,9 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_CHROM caBlue->show(); + caRed->setLogScale(10, 0); + caBlue->setLogScale(10, 0); + pack_start( *caAutocorrect, Gtk::PACK_SHRINK, 4); pack_start( *caAutoiterations, Gtk::PACK_SHRINK, 4); pack_start( *caRed, Gtk::PACK_SHRINK, 4); diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc index 56fcf7ec9..a705ed4ca 100644 --- a/rtgui/rawexposure.cc +++ b/rtgui/rawexposure.cc @@ -45,6 +45,8 @@ RAWExposure::RAWExposure () : FoldableToolPanel(this, "rawexposure", M("TP_EXPOS pack_start( *PexPos, Gtk::PACK_SHRINK, 4);//exposi // raw highlight exposure setting is obsolete, removing from GUI //pack_start( *PexPreser, Gtk::PACK_SHRINK, 4); + + PexPos->setLogScale(100, 0); } void RAWExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) diff --git a/rtgui/rotate.cc b/rtgui/rotate.cc index 802519d8d..481b65139 100644 --- a/rtgui/rotate.cc +++ b/rtgui/rotate.cc @@ -44,6 +44,8 @@ Rotate::Rotate () : FoldableToolPanel(this, "rotate", M("TP_ROTATE_LABEL")) selectStraight->signal_pressed().connect( sigc::mem_fun(*this, &Rotate::selectStraightPressed) ); + degree->setLogScale(2, 0); + show_all (); } diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index 5205d6f18..19326be26 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -106,6 +106,7 @@ ToneCurve::ToneCurve () : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LA pack_start (*Gtk::manage (new Gtk::HSeparator())); expcomp = Gtk::manage (new Adjuster (M("TP_EXPOSURE_EXPCOMP"), -5, 12, 0.05, 0)); + expcomp->setLogScale(2, 0, true); pack_start (*expcomp); //----------- Highlight recovery & threshold ------------- @@ -116,6 +117,7 @@ ToneCurve::ToneCurve () : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LA //----------- Black Level & Compression ------------------- black = Gtk::manage (new Adjuster (M("TP_EXPOSURE_BLACKLEVEL"), -16384, 32768, 50, 0)); + black->setLogScale(10, 0, true); pack_start (*black); shcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRSHADOWS"), 0, 100, 1, 50)); pack_start (*shcompr); @@ -130,6 +132,10 @@ ToneCurve::ToneCurve () : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LA saturation = Gtk::manage (new Adjuster (M("TP_EXPOSURE_SATURATION"), -100, 100, 1, 0)); pack_start (*saturation); + brightness->setLogScale(2, 0, true); + contrast->setLogScale(2, 0, true); + saturation->setLogScale(2, 0, true); + //----------- Curve 1 ------------------------------ pack_start (*Gtk::manage (new Gtk::HSeparator())); diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index 99a564a85..681ac16c2 100644 --- a/rtgui/whitebalance.cc +++ b/rtgui/whitebalance.cc @@ -315,6 +315,7 @@ WhiteBalance::WhiteBalance () : FoldableToolPanel(this, "whitebalance", M("TP_WB temp = Gtk::manage (new Adjuster (M("TP_WBALANCE_TEMPERATURE"), MINTEMP, MAXTEMP, 5, CENTERTEMP, itempL, itempR, &wbSlider2Temp, &wbTemp2Slider)); green = Gtk::manage (new Adjuster (M("TP_WBALANCE_GREEN"), MINGREEN, MAXGREEN, 0.001, 1.0, igreenL, igreenR)); + green->setLogScale(10, 1, true); equal = Gtk::manage (new Adjuster (M("TP_WBALANCE_EQBLUERED"), MINEQUAL, MAXEQUAL, 0.001, 1.0, iblueredL, iblueredR)); tempBias = Gtk::manage (new Adjuster(M("TP_WBALANCE_TEMPBIAS"), -0.5, 0.5, 0.01, 0.0, itempbiasL, itempbiasR)); cache_customTemp (0); @@ -689,6 +690,8 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) set_inconsistent(multiImage && !pedited->wb.enabled); } + green->setLogScale(10, green->getValue(), true); + methconn.block (false); enableListener (); } @@ -794,6 +797,8 @@ void WhiteBalance::setWB (int vtemp, double vgreen) if (listener) { listener->panelChanged (EvWBTemp, Glib::ustring::compose("%1, %2", (int)temp->getValue(), Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(3), green->getValue()))); } + + green->setLogScale(10, vgreen, true); } void WhiteBalance::setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd, bool tempbiasadd) diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index 84fae9032..480112537 100644 --- a/rtgui/xtransrawexposure.cc +++ b/rtgui/xtransrawexposure.cc @@ -53,6 +53,10 @@ XTransRAWExposure::XTransRAWExposure () : FoldableToolPanel(this, "xtransrawexpo pack_start( *PexBlackRed, Gtk::PACK_SHRINK, 0);//black pack_start( *PexBlackGreen, Gtk::PACK_SHRINK, 0);//black pack_start( *PexBlackBlue, Gtk::PACK_SHRINK, 0);//black + + PexBlackRed->setLogScale(100, 0); + PexBlackGreen->setLogScale(100, 0); + PexBlackBlue->setLogScale(100, 0); } void XTransRAWExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) From 6e6c0b8235de0d154a336d70fb64c07160373025 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 21 Sep 2018 14:17:57 +0200 Subject: [PATCH 2/2] Fix empty spinbox bug, #4823 --- rtgui/adjuster.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc index e0eb62a1f..3f12b0cfb 100644 --- a/rtgui/adjuster.cc +++ b/rtgui/adjuster.cc @@ -317,8 +317,8 @@ void Adjuster::resetPressed (GdkEventButton* event) double Adjuster::shapeValue (double a) { - - return round(a * pow(double(10), digits)) / pow(double(10), digits); + double val = round(a * pow(double(10), digits)) / pow(double(10), digits); + return val == -0.0 ? 0.0 : val; } void Adjuster::setLimits (double vmin, double vmax, double vstep, double vdefault) @@ -413,7 +413,7 @@ void Adjuster::sliderChanged () } spinChange.block (true); - double v = getSliderValue(); + double v = shapeValue(getSliderValue()); spin->set_value (addMode ? v : slider2value(v)); spinChange.block (false);