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
This commit is contained in:
parent
50a6a32f74
commit
11e7739a55
@ -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<float>(vMin), static_cast<float>(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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 ();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user