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 {