diff --git a/rtdata/languages/default b/rtdata/languages/default index 5098ba007..70748abcd 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -387,6 +387,7 @@ HISTORY_MSG_163;RGB Curves - R HISTORY_MSG_164;RGB Curves - G HISTORY_MSG_165;RGB Curves - B HISTORY_MSG_166;Neutral Levels +HISTORY_MSG_167;BW Toning HISTORY_NEWSNAPSHOTAS;As... HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSSDIALOGLABEL;Label of the snapshot: @@ -957,6 +958,8 @@ TP_IMPULSEDENOISE_LABEL;Impulse Noise Reduction TP_IMPULSEDENOISE_THRESH;Impulse NR Threshold TP_LABCURVE_AVOIDCOLORCLIP;Avoid color clipping TP_LABCURVE_BRIGHTNESS;Brightness +TP_LABCURVE_BWTONING;BW Toning +TP_LABCURVE_BWTONING_TIP;With BT Toning option enabled the Lab Saturation is not in effect.\nToning can be achieved using the a and b curves TP_LABCURVE_CONTRAST;Contrast TP_LABCURVE_CURVEEDITOR;Luminance Curve TP_LABCURVE_ENABLESATLIMITER;Enable saturation limiter diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index cf9930c9e..64e81720b 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -466,12 +466,20 @@ void ImProcFunctions::chrominanceCurve (LabImage* lold, LabImage* lnew, LUTf & a float atmp = acurve[lold->a[i][j]+32768.0f]-32768.0f; float btmp = bcurve[lold->b[i][j]+32768.0f]-32768.0f; - if (params->labCurve.saturation) { + // modulation of a and b curves with saturation + if (params->labCurve.saturation!=0 && !params->labCurve.bwtoning) { float chroma = sqrt(SQR(atmp)+SQR(btmp)+0.001); float satfactor = (satcurve[chroma+32768.0f]-32768.0f)/chroma; atmp *= satfactor; btmp *= satfactor; } + + // labCurve.bwtoning option allows to decouple modulation of a & b curves by saturation + // with bwtoning enabled the net effect of a & b curves is visible + if (params->labCurve.bwtoning) { + atmp -= lold->a[i][j]; + btmp -= lold->b[i][j]; + } if (params->labCurve.avoidclip) { //Luv limiter diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 10b5dfe31..080515a6e 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -188,7 +188,8 @@ enum ProcEvent { EvRGBgCurve=163, EvRGBbCurve=164, EvNeutralExp=165, - NUMOFEVENTS=166 + EvLBWtoning=166, + NUMOFEVENTS=167 }; } #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 1ce1cb4de..b36d35426 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -145,6 +145,7 @@ void ProcParams::setDefaults () { labCurve.avoidclip = false; labCurve.enable_saturationlimiter = false; labCurve.saturationlimit = 50; + labCurve.bwtoning = false; labCurve.lcurve.clear (); labCurve.lcurve.push_back(DCT_Linear); labCurve.acurve.clear (); @@ -405,6 +406,7 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, ParamsEdited* p if (!pedited || pedited->labCurve.avoidclip) keyFile.set_boolean ("Luminance Curve", "AvoidColorClipping", labCurve.avoidclip); if (!pedited || pedited->labCurve.enable_saturationlimiter) keyFile.set_boolean ("Luminance Curve", "SaturationLimiter", labCurve.enable_saturationlimiter); if (!pedited || pedited->labCurve.saturationlimit) keyFile.set_double ("Luminance Curve", "SaturationLimit", labCurve.saturationlimit); + if (!pedited || pedited->labCurve.avoidclip) keyFile.set_boolean ("Luminance Curve", "BWtoning", labCurve.bwtoning); if (!pedited || pedited->labCurve.lcurve) { Glib::ArrayHandle lcurve = labCurve.lcurve; keyFile.set_double_list("Luminance Curve", "LCurve", lcurve); @@ -774,8 +776,9 @@ if (keyFile.has_group ("Luminance Curve")) { if (keyFile.has_key ("Luminance Curve", "Contrast")) { labCurve.contrast = keyFile.get_integer ("Luminance Curve", "Contrast"); if (pedited) pedited->labCurve.contrast = true; } if (keyFile.has_key ("Luminance Curve", "Saturation")) { labCurve.saturation = keyFile.get_integer ("Luminance Curve", "Saturation"); if (pedited) pedited->labCurve.saturation = true; } if (keyFile.has_key ("Luminance Curve", "AvoidColorClipping")) { labCurve.avoidclip = keyFile.get_boolean ("Luminance Curve", "AvoidColorClipping"); if (pedited) pedited->labCurve.avoidclip = true; } - if (keyFile.has_key ("Luminance Curve", "SaturationLimiter")) { labCurve.enable_saturationlimiter = keyFile.get_boolean ("Luminance Curve", "SaturationLimiter"); if (pedited) pedited->labCurve.enable_saturationlimiter = true; } + if (keyFile.has_key ("Luminance Curve", "SaturationLimiter")) { labCurve.enable_saturationlimiter = keyFile.get_boolean ("Luminance Curve", "SaturationLimiter"); if (pedited) pedited->labCurve.enable_saturationlimiter = true; } if (keyFile.has_key ("Luminance Curve", "SaturationLimit")) { labCurve.saturationlimit = keyFile.get_double ("Luminance Curve", "SaturationLimit"); if (pedited) pedited->labCurve.saturationlimit = true; } + if (keyFile.has_key ("Luminance Curve", "BWtoning")) { labCurve.bwtoning = keyFile.get_boolean ("Luminance Curve", "BWtoning"); if (pedited) pedited->labCurve.bwtoning = true; } if (keyFile.has_key ("Luminance Curve", "LCurve")) { labCurve.lcurve = keyFile.get_double_list ("Luminance Curve", "LCurve"); if (pedited) pedited->labCurve.lcurve = true; } if (keyFile.has_key ("Luminance Curve", "aCurve")) { labCurve.acurve = keyFile.get_double_list ("Luminance Curve", "aCurve"); if (pedited) pedited->labCurve.acurve = true; } if (keyFile.has_key ("Luminance Curve", "bCurve")) { labCurve.bcurve = keyFile.get_double_list ("Luminance Curve", "bCurve"); if (pedited) pedited->labCurve.bcurve = true; } @@ -1171,7 +1174,8 @@ bool ProcParams::operator== (const ProcParams& other) { && labCurve.saturation == other.labCurve.saturation && labCurve.avoidclip == other.labCurve.avoidclip && labCurve.enable_saturationlimiter == other.labCurve.enable_saturationlimiter - && labCurve.saturationlimit == other.labCurve.saturationlimit + && labCurve.saturationlimit == other.labCurve.saturationlimit + && labCurve.bwtoning == other.labCurve.bwtoning && sharpenEdge.enabled == other.sharpenEdge.enabled && sharpenEdge.passes == other.sharpenEdge.passes && sharpenEdge.amount == other.sharpenEdge.amount diff --git a/rtengine/procparams.h b/rtengine/procparams.h index d5e198281..79d7434cc 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -61,6 +61,7 @@ class LCurveParams { bool avoidclip; bool enable_saturationlimiter; double saturationlimit; + bool bwtoning; }; /** diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 7229ff43a..9703571f0 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -185,7 +185,7 @@ SHARPENING, // EvEPDEnabled RGBCURVE, // EvRGBrCurve RGBCURVE, // EvRGBgCurve RGBCURVE, // EvRGBbCurve -RGBCURVE // EvNeutralExp - +RGBCURVE, // EvNeutralExp +LUMINANCECURVE // EvLBWtoning }; diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index fb6c62ec8..6a1c73e1d 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -44,6 +44,10 @@ LCurve::LCurve () : Gtk::VBox(), FoldableToolPanel(this) { //%%%%%%%%%%%%%%%%%% pack_start (*Gtk::manage (new Gtk::HSeparator())); + bwtoning = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_BWTONING"))); + bwtoning->set_tooltip_markup (M("TP_LABCURVE_BWTONING_TIP")); + pack_start (*bwtoning); + avoidclip = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_AVOIDCOLORCLIP"))); pack_start (*avoidclip); @@ -59,6 +63,7 @@ LCurve::LCurve () : Gtk::VBox(), FoldableToolPanel(this) { //saturation->setAdjusterListener (this); saturationlimiter->setAdjusterListener (this); + bwtconn= bwtoning->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::bwtoning_toggled) ); acconn = avoidclip->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::avoidclip_toggled) ); elconn = enablelimiter->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::enablelimiter_toggled) ); //%%%%%%%%%%%%%%%%%%% @@ -97,6 +102,7 @@ void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { //%%%%%%%%%%%%%%%%%%%%%% saturationlimiter->setEditedState (pedited->labCurve.saturationlimit ? Edited : UnEdited); + bwtoning->set_inconsistent (!pedited->labCurve.bwtoning); avoidclip->set_inconsistent (!pedited->labCurve.avoidclip); enablelimiter->set_inconsistent (!pedited->labCurve.enable_saturationlimiter); //%%%%%%%%%%%%%%%%%%%%%% @@ -114,6 +120,8 @@ void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { //%%%%%%%%%%%%%%%%%%%%%% saturationlimiter->setValue (pp->labCurve.saturationlimit); acconn.block (true); + bwtoning->set_active (pp->labCurve.bwtoning); + saturation->set_sensitive(!(bwtoning->get_active ())); //at bwtoning enabled saturation value has no effect avoidclip->set_active (pp->labCurve.avoidclip); acconn.block (false); elconn.block (true); @@ -124,6 +132,7 @@ void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { // if (enablelimiter->get_active () || enablelimiter->get_inconsistent()) // pack_start (*saturationlimiter); + lastBWTVal = pp->labCurve.bwtoning; lastACVal = pp->labCurve.avoidclip; lastELVal = pp->labCurve.enable_saturationlimiter; //%%%%%%%%%%%%%%%%%%%%%% @@ -147,6 +156,7 @@ void LCurve::write (ProcParams* pp, ParamsEdited* pedited) { pp->labCurve.saturation = (int)saturation->getValue (); //%%%%%%%%%%%%%%%%%%%%%% + pp->labCurve.bwtoning = bwtoning->get_active (); pp->labCurve.avoidclip = avoidclip->get_active (); pp->labCurve.enable_saturationlimiter = enablelimiter->get_active (); pp->labCurve.saturationlimit = saturationlimiter->getValue (); @@ -162,6 +172,7 @@ void LCurve::write (ProcParams* pp, ParamsEdited* pedited) { pedited->labCurve.saturation = saturation->getEditedState (); //%%%%%%%%%%%%%%%%%%%%%% + pedited->labCurve.bwtoning = !bwtoning->get_inconsistent(); pedited->labCurve.avoidclip = !avoidclip->get_inconsistent(); pedited->labCurve.enable_saturationlimiter = !enablelimiter->get_inconsistent(); pedited->labCurve.saturationlimit = saturationlimiter->getEditedState (); @@ -220,6 +231,33 @@ void LCurve::avoidclip_toggled () { } } +//%%%%%%%%%%%%%%%%%%%%%% +//BW toning control changed +void LCurve::bwtoning_toggled () { + + if (batchMode) { + if (bwtoning->get_inconsistent()) { + bwtoning->set_inconsistent (false); + bwtconn.block (true); + bwtoning->set_active (false); + bwtconn.block (false); + } + else if (lastBWTVal) + bwtoning->set_inconsistent (true); + + lastBWTVal = bwtoning->get_active (); + } + + saturation->set_sensitive(!(bwtoning->get_active ())); //at bwtoning enabled saturation value has no effect + + if (listener) { + if (bwtoning->get_active ()) + listener->panelChanged (EvLBWtoning, M("GENERAL_ENABLED")); + else + listener->panelChanged (EvLBWtoning, M("GENERAL_DISABLED")); + } +} + void LCurve::enablelimiter_toggled () { if (batchMode) { diff --git a/rtgui/labcurve.h b/rtgui/labcurve.h index bab721f31..2cbb786fc 100644 --- a/rtgui/labcurve.h +++ b/rtgui/labcurve.h @@ -39,11 +39,12 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPan //%%%%%%%%%%%%%%%% Gtk::CheckButton* avoidclip; - Gtk::CheckButton* enablelimiter; + Gtk::CheckButton* enablelimiter; + Gtk::CheckButton* bwtoning; Adjuster* saturationlimiter; bool cbAdd; - sigc::connection acconn, elconn; - bool lastACVal, lastELVal; + sigc::connection bwtconn, acconn, elconn; + bool lastBWTVal, lastACVal, lastELVal; //%%%%%%%%%%%%%%%% public: @@ -62,6 +63,7 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPan void adjusterChanged (Adjuster* a, double newval); void avoidclip_toggled (); void enablelimiter_toggled (); + void bwtoning_toggled(); void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma); virtual void colorForValue (double valX, double valY); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 9461b0a8e..4d4925643 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -52,6 +52,7 @@ void ParamsEdited::set (bool v) { labCurve.avoidclip = v; labCurve.enable_saturationlimiter = v; labCurve.saturationlimit = v; + labCurve.bwtoning =v; rgbCurves.rcurve = v; rgbCurves.gcurve = v; rgbCurves.bcurve = v; @@ -244,6 +245,7 @@ void ParamsEdited::initFrom (const std::vector labCurve.avoidclip = labCurve.avoidclip && p.labCurve.avoidclip == other.labCurve.avoidclip; labCurve.enable_saturationlimiter = labCurve.enable_saturationlimiter && p.labCurve.enable_saturationlimiter == other.labCurve.enable_saturationlimiter; labCurve.saturationlimit = labCurve.saturationlimit && p.labCurve.saturationlimit == other.labCurve.saturationlimit; + labCurve.bwtoning = labCurve.bwtoning && p.labCurve.bwtoning == other.labCurve.bwtoning; rgbCurves.rcurve = rgbCurves.rcurve && p.rgbCurves.rcurve == other.rgbCurves.rcurve; rgbCurves.gcurve = rgbCurves.gcurve && p.rgbCurves.gcurve == other.rgbCurves.gcurve; rgbCurves.bcurve = rgbCurves.bcurve && p.rgbCurves.bcurve == other.rgbCurves.bcurve; @@ -432,9 +434,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (labCurve.brightness) toEdit.labCurve.brightness = dontforceSet && options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.labCurve.brightness + mods.labCurve.brightness : mods.labCurve.brightness; if (labCurve.contrast) toEdit.labCurve.contrast = dontforceSet && options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.labCurve.contrast + mods.labCurve.contrast : mods.labCurve.contrast; if (labCurve.saturation) toEdit.labCurve.saturation = dontforceSet && options.baBehav[ADDSET_LC_SATURATION] ? toEdit.labCurve.saturation + mods.labCurve.saturation : mods.labCurve.saturation; - if (labCurve.avoidclip) toEdit.labCurve.avoidclip = mods.labCurve.avoidclip; + if (labCurve.enable_saturationlimiter) toEdit.labCurve.enable_saturationlimiter = mods.labCurve.enable_saturationlimiter; if (labCurve.saturationlimit) toEdit.labCurve.saturationlimit = mods.labCurve.saturationlimit; + if (labCurve.bwtoning) toEdit.labCurve.bwtoning = mods.labCurve.bwtoning; if (rgbCurves.rcurve) toEdit.rgbCurves.rcurve = mods.rgbCurves.rcurve; if (rgbCurves.gcurve) toEdit.rgbCurves.gcurve = mods.rgbCurves.gcurve; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index c4804333e..a27b2765f 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -60,6 +60,7 @@ class LCurveParamsEdited { bool lcurve; bool acurve; bool bcurve; + bool bwtoning; }; class RGBCurvesParamsEdited {