diff --git a/rtdata/languages/default b/rtdata/languages/default
index b200a2ad7..a5cd7746e 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -816,6 +816,7 @@ HISTORY_MSG_WAVBL;Blur levels
HISTORY_MSG_BLURWAV;Blur luminance
HISTORY_MSG_BLURCWAV;Blur chroma
HISTORY_MSG_EDGEFFECT;Edge Damper
+HISTORY_MSG_SIGMAFIN;Final contrast Damper
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -2227,6 +2228,7 @@ TP_WAVELET_EDSL;Threshold Sliders
TP_WAVELET_EDTYPE;Local contrast method
TP_WAVELET_EDVAL;Strength
TP_WAVELET_FINAL;Final Touchup
+TP_WAVELET_FINCFRAME;Final Local Contrast
TP_WAVELET_FINEST;Finest
TP_WAVELET_HIGHLIGHT;Highlight luminance range
TP_WAVELET_HS1;Whole luminance range
@@ -2273,7 +2275,7 @@ TP_WAVELET_NPTYPE_TOOLTIP;This algorithm uses the proximity of a pixel and eight
TP_WAVELET_OLDSH;Algorithm using negatives values
TP_WAVELET_OPACITY;Opacity Blue-Yellow
TP_WAVELET_OPACITYW;Contrast balance d/v-h curve
-TP_WAVELET_OPACITYWL;Final local contrast
+TP_WAVELET_OPACITYWL;Local contrast
TP_WAVELET_OPACITYWL_TOOLTIP;Modify the final local contrast at the end of the wavelet treatment.\n\nThe left side represents the smallest local contrast, progressing to the largest local contrast on the right.
TP_WAVELET_PASTEL;Pastel chroma
TP_WAVELET_PROC;Process
@@ -2294,6 +2296,7 @@ TP_WAVELET_SHA;Sharp mask
TP_WAVELET_SHFRAME;Shadows/Highlights
TP_WAVELET_SHOWMASK;Show wavelet 'mask'
TP_WAVELET_SIGMA;Damper
+TP_WAVELET_SIGMAFIN;Damper
TP_WAVELET_SIGMA_TOOLTIP;The effect of the contrast sliders is stronger in medium contrast details, and weaker in high and low contrast details.\n With this slider you can control how quickly the effect dampens towards the extreme contrasts.\n The higher the slider is set, the wider the range of contrasts which will get a strong change, and the higher the risk to generate artifacts.\n The lower it is, the more pinpoint will the effect be applied to a narrow range of contrast values.
TP_WAVELET_SKIN;Skin targetting/protection
TP_WAVELET_SKIN_TOOLTIP;At -100 skin-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 skin-tones are protected while all other tones are affected.
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index 948b76f2b..157fb6239 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -113,6 +113,7 @@ struct cont_params {
int TMmeth;
float tmstrength;
float balan;
+ float sigmafin;
int ite;
int contmet;
bool opaW;
@@ -191,6 +192,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.ite = params->wavelet.iter;
cp.tonemap = params->wavelet.tmrs != 0;
cp.bam = false;
+ cp.sigmafin = params->wavelet.sigmafin;
if (params->wavelet.TMmethod == "cont") {
cp.contmet = 1;
@@ -2955,11 +2957,11 @@ void ImProcFunctions::finalContAllL(float ** WavCoeffs_L, float * WavCoeffs_L0,
if (cp.diagcurv && cp.finena && MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { //curve
float insigma = 0.666f; //SD
float logmax = log(MaxP[level]); //log Max
- float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max
+ float rapX = (mean[level] + cp.sigmafin * sigma[level]) / MaxP[level]; //rapport between sD / max
float inx = log(insigma);
float iny = log(rapX);
float rap = inx / iny; //koef
- float asig = 0.166f / sigma[level];
+ float asig = 0.166f / (sigma[level] * cp.sigmafin);
float bsig = 0.5f - asig * mean[level];
float amean = 0.5f / mean[level];
@@ -2970,7 +2972,7 @@ void ImProcFunctions::finalContAllL(float ** WavCoeffs_L, float * WavCoeffs_L0,
for (int i = 0; i < W_L * H_L; i++) {
float absciss;
- if (std::fabs(WavCoeffs_L[dir][i]) >= (mean[level] + sigma[level])) { //for max
+ if (std::fabs(WavCoeffs_L[dir][i]) >= (mean[level] + cp.sigmafin * sigma[level])) { //for max
float valcour = xlogf(std::fabs(WavCoeffs_L[dir][i]));
float valc = valcour - logmax;
float vald = valc * rap;
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index b02f1970c..0d8324d4e 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -2263,6 +2263,7 @@ WaveletParams::WaveletParams() :
tmr(false),
strength(100),
balance(0),
+ sigmafin(1.0),
iter(0),
expcontrast(false),
expchroma(false),
@@ -2377,6 +2378,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& tmr == other.tmr
&& strength == other.strength
&& balance == other.balance
+ && sigmafin == other.sigmafin
&& iter == other.iter
&& expcontrast == other.expcontrast
&& expchroma == other.expchroma
@@ -3514,6 +3516,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.enabled, "Wavelet", "Enabled", wavelet.enabled, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.strength, "Wavelet", "Strength", wavelet.strength, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.balance, "Wavelet", "Balance", wavelet.balance, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.sigmafin, "Wavelet", "Sigmafin", wavelet.sigmafin, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.iter, "Wavelet", "Iter", wavelet.iter, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.thres, "Wavelet", "MaxLev", wavelet.thres, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.Tilesmethod, "Wavelet", "TilesMethod", wavelet.Tilesmethod, keyFile);
@@ -4691,6 +4694,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "Enabled", pedited, wavelet.enabled, pedited->wavelet.enabled);
assignFromKeyfile(keyFile, "Wavelet", "Strength", pedited, wavelet.strength, pedited->wavelet.strength);
assignFromKeyfile(keyFile, "Wavelet", "Balance", pedited, wavelet.balance, pedited->wavelet.balance);
+ assignFromKeyfile(keyFile, "Wavelet", "Sigmafin", pedited, wavelet.sigmafin, pedited->wavelet.sigmafin);
assignFromKeyfile(keyFile, "Wavelet", "Iter", pedited, wavelet.iter, pedited->wavelet.iter);
assignFromKeyfile(keyFile, "Wavelet", "Median", pedited, wavelet.median, pedited->wavelet.median);
assignFromKeyfile(keyFile, "Wavelet", "Medianlev", pedited, wavelet.medianlev, pedited->wavelet.medianlev);
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 4e2b0c275..c26b02de4 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -1221,6 +1221,7 @@ struct WaveletParams {
bool tmr;
int strength;
int balance;
+ double sigmafin;
int iter;
bool expcontrast;
bool expchroma;
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 0faee0fd3..9eff3c4ce 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -475,6 +475,7 @@ void ParamsEdited::set(bool v)
wavelet.strength = v;
wavelet.balance = v;
wavelet.iter = v;
+ wavelet.sigmafin = v;
wavelet.median = v;
wavelet.medianlev = v;
wavelet.linkedg = v;
@@ -1085,6 +1086,7 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.strength = wavelet.strength && p.wavelet.strength == other.wavelet.strength;
wavelet.balance = wavelet.balance && p.wavelet.balance == other.wavelet.balance;
wavelet.iter = wavelet.iter && p.wavelet.iter == other.wavelet.iter;
+ wavelet.sigmafin = wavelet.sigmafin && p.wavelet.sigmafin == other.wavelet.sigmafin;
wavelet.median = wavelet.median && p.wavelet.median == other.wavelet.median;
wavelet.medianlev = wavelet.medianlev && p.wavelet.medianlev == other.wavelet.medianlev;
wavelet.linkedg = wavelet.linkedg && p.wavelet.linkedg == other.wavelet.linkedg;
@@ -2893,6 +2895,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.balance = mods.wavelet.balance;
}
+ if (wavelet.sigmafin) {
+ toEdit.wavelet.sigmafin = mods.wavelet.sigmafin;
+ }
+
if (wavelet.iter) {
toEdit.wavelet.iter = mods.wavelet.iter;
}
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index d1be2c57e..351096a7e 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -499,6 +499,7 @@ struct WaveletParamsEdited {
bool strength;
bool balance;
bool iter;
+ bool sigmafin;
bool median;
bool medianlev;
bool linkedg;
diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc
index 17689be50..c12e216cf 100644
--- a/rtgui/wavelet.cc
+++ b/rtgui/wavelet.cc
@@ -112,6 +112,7 @@ Wavelet::Wavelet() :
strength(Gtk::manage(new Adjuster(M("TP_WAVELET_STRENGTH"), 0, 100, 1, 100))),
balance(Gtk::manage(new Adjuster(M("TP_WAVELET_BALANCE"), -30, 100, 1, 0))),
iter(Gtk::manage(new Adjuster(M("TP_WAVELET_ITER"), -3, 3, 1, 0))),
+ sigmafin(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMAFIN"), 0.025, 2.5, 0.01, 1.))),
hueskin(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_HUESKIN"), -314., 314., -5., 25., 170., 120., 0, false))),
hueskin2(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_HUESKY"), -314., 314., -260., -250, -130., -140., 0, false))),
hllev(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_HIGHLIGHT"), 0., 100., 50., 75., 100., 98., 0, false))),
@@ -162,6 +163,7 @@ Wavelet::Wavelet() :
blurFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_BLURFRAME")))),
chromaFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_CHROMAFRAME")))),
chroFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_CHROFRAME")))),
+ fincFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_FINCFRAME")))),
wavLabels(Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER))),
labmC(Gtk::manage(new Gtk::Label(M("TP_WAVELET_CTYPE") + ":"))),
labmNP(Gtk::manage(new Gtk::Label(M("TP_WAVELET_NPTYPE") + ":"))),
@@ -207,6 +209,8 @@ Wavelet::Wavelet() :
EvWavresblur = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLURWAV");
EvWavresblurc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLURCWAV");
EvWavedgeffect = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_EDGEFFECT");
+ EvWavsigmafin = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_SIGMAFIN");
+
expsettings->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings));
expcontrast->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expcontrast));
@@ -978,7 +982,7 @@ Wavelet::Wavelet() :
iter->setAdjusterListener(this);
iter->set_tooltip_text(M("TP_WAVELET_ITER_TOOLTIP"));
- Gtk::HSeparator* const separatorbalend = Gtk::manage(new Gtk::HSeparator());
+// Gtk::HSeparator* const separatorbalend = Gtk::manage(new Gtk::HSeparator());
opacityCurveEditorWL->setCurveListener(this);
@@ -986,6 +990,7 @@ Wavelet::Wavelet() :
opacityShapeWL->setIdentityValue(0.);
opacityShapeWL->setResetCurve(FlatCurveType(default_params.opacityCurveWL.at(0)), default_params.opacityCurveWL);
opacityShapeWL->setTooltip(M("TP_WAVELET_OPACITYWL_TOOLTIP"));
+ sigmafin->setAdjusterListener(this);
// This will add the reset button at the end of the curveType buttons
opacityCurveEditorWL->curveListComplete();
@@ -1004,6 +1009,13 @@ Wavelet::Wavelet() :
tmr->set_tooltip_text(M("TP_WAVELET_BALCHRO_TOOLTIP"));
tmrConn = tmr->signal_toggled().connect(sigc::mem_fun(*this, &Wavelet::tmrToggled));
+ fincFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const fincBox = Gtk::manage(new ToolParamBlock());
+ fincBox->pack_start(*opacityCurveEditorWL, Gtk::PACK_SHRINK, 2);
+ fincBox->pack_start(*sigmafin);
+ fincFrame->add(*fincBox);
+
+
ToolParamBlock* const finalBox = Gtk::manage(new ToolParamBlock());
finalBox->pack_start(*ctboxBA);
@@ -1014,9 +1026,10 @@ Wavelet::Wavelet() :
finalBox->pack_start(*iter);
finalBox->pack_start(*tmr);
- finalBox->pack_start(*separatorbalend, Gtk::PACK_SHRINK, 2);
- finalBox->pack_start(*opacityCurveEditorWL, Gtk::PACK_SHRINK, 2);
-
+// finalBox->pack_start(*separatorbalend, Gtk::PACK_SHRINK, 2);
+// finalBox->pack_start(*opacityCurveEditorWL, Gtk::PACK_SHRINK, 2);
+// finalBox->pack_start(*sigmafin);
+ finalBox->pack_start(*fincFrame);
finalBox->pack_start(*curveEditorG, Gtk::PACK_SHRINK, 4);
finalBox->pack_start(*softradend);
@@ -1420,6 +1433,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
strength->setValue(pp->wavelet.strength);
balance->setValue(pp->wavelet.balance);
iter->setValue(pp->wavelet.iter);
+ sigmafin->setValue(pp->wavelet.sigmafin);
for (int i = 0; i < 9; i++) {
correction[i]->setValue(pp->wavelet.c[i]);
@@ -1537,6 +1551,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
thres->setEditedState(pedited->wavelet.thres ? Edited : UnEdited);
balance->setEditedState(pedited->wavelet.balance ? Edited : UnEdited);
iter->setEditedState(pedited->wavelet.iter ? Edited : UnEdited);
+ sigmafin->setEditedState(pedited->wavelet.sigmafin ? Edited : UnEdited);
threshold->setEditedState(pedited->wavelet.threshold ? Edited : UnEdited);
threshold2->setEditedState(pedited->wavelet.threshold2 ? Edited : UnEdited);
edgedetect->setEditedState(pedited->wavelet.edgedetect ? Edited : UnEdited);
@@ -1808,6 +1823,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.iter = (int) iter->getValue();
pp->wavelet.wavclCurve = clshape->getCurve();
+ pp->wavelet.sigmafin = sigmafin->getValue();
for (int i = 0; i < 9; i++) {
pp->wavelet.c[i] = (int) correction[i]->getValue();
@@ -1914,6 +1930,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.softradend = softradend->getEditedState();
pedited->wavelet.balance = balance->getEditedState();
pedited->wavelet.iter = iter->getEditedState();
+ pedited->wavelet.sigmafin = sigmafin->getEditedState();
pedited->wavelet.wavclCurve = !clshape->isUnChanged();
pedited->wavelet.expcontrast = !expcontrast->get_inconsistent();
pedited->wavelet.expchroma = !expchroma->get_inconsistent();
@@ -2094,6 +2111,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
strength->setDefault(defParams->wavelet.strength);
balance->setDefault(defParams->wavelet.balance);
iter->setDefault(defParams->wavelet.iter);
+ sigmafin->setDefault(defParams->wavelet.sigmafin);
sigma->setDefault(defParams->wavelet.sigma);
offset->setDefault(defParams->wavelet.offset);
lowthr->setDefault(defParams->wavelet.lowthr);
@@ -2216,6 +2234,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
strength->setDefaultEditedState(pedited->wavelet.strength ? Edited : UnEdited);
balance->setDefaultEditedState(pedited->wavelet.balance ? Edited : UnEdited);
iter->setDefaultEditedState(pedited->wavelet.iter ? Edited : UnEdited);
+ sigmafin->setDefaultEditedState(pedited->wavelet.sigmafin ? Edited : UnEdited);
level0noise->setDefaultEditedState(pedited->wavelet.level0noise ? Edited : UnEdited);
level1noise->setDefaultEditedState(pedited->wavelet.level1noise ? Edited : UnEdited);
level2noise->setDefaultEditedState(pedited->wavelet.level2noise ? Edited : UnEdited);
@@ -2278,6 +2297,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
strength->setDefaultEditedState(Irrelevant);
balance->setDefaultEditedState(Irrelevant);
iter->setDefaultEditedState(Irrelevant);
+ sigmafin->setDefaultEditedState(Irrelevant);
for (int i = 0; i < 9; i++) {
correction[i]->setDefaultEditedState(Irrelevant);
@@ -2810,6 +2830,7 @@ void Wavelet::setBatchMode(bool batchMode)
strength->showEditedCB();
balance->showEditedCB();
iter->showEditedCB();
+ sigmafin->showEditedCB();
level0noise->showEditedCB();
level1noise->showEditedCB();
level2noise->showEditedCB();
@@ -2959,6 +2980,8 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval)
listener->panelChanged(EvWavbalance, balance->getTextValue());
} else if (a == iter) {
listener->panelChanged(EvWaviter, iter->getTextValue());
+ } else if (a == sigmafin) {
+ listener->panelChanged(EvWavsigmafin, sigmafin->getTextValue());
} else if (a == greenhigh) {
listener->panelChanged(EvWavgreenhigh, greenhigh->getTextValue());
} else if (a == bluehigh) {
diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h
index d1b4bb7c3..271aea5b2 100644
--- a/rtgui/wavelet.h
+++ b/rtgui/wavelet.h
@@ -93,6 +93,7 @@ private:
rtengine::ProcEvent EvWavresblur;
rtengine::ProcEvent EvWavresblurc;
rtengine::ProcEvent EvWavedgeffect;
+ rtengine::ProcEvent EvWavsigmafin;
void foldAllButMe(GdkEventButton* event, MyExpander *expander);
@@ -218,6 +219,7 @@ private:
Adjuster* const strength;
Adjuster* const balance;
Adjuster* const iter;
+ Adjuster* const sigmafin;
Adjuster* greenlow;
Adjuster* bluelow;
@@ -294,6 +296,7 @@ private:
Gtk::Frame* const blurFrame;
Gtk::Frame* const chromaFrame;
Gtk::Frame* const chroFrame;
+ Gtk::Frame* const fincFrame;
Gtk::Label* const wavLabels;
Gtk::Label* const labmC;