From 025f444d7eef0de4d2d8a7884ff3ac7ed04c9f0b Mon Sep 17 00:00:00 2001 From: Desmis Date: Sun, 15 Dec 2019 08:21:41 +0100 Subject: [PATCH] Improve contrast levels with sigma --- rtdata/languages/default | 2 ++ rtengine/ipwavelet.cc | 32 ++++++++++++++++++++++++-------- rtengine/procparams.cc | 4 ++++ rtengine/procparams.h | 1 + rtgui/paramsedited.cc | 6 ++++++ rtgui/paramsedited.h | 1 + rtgui/wavelet.cc | 15 +++++++++++++++ rtgui/wavelet.h | 2 ++ 8 files changed, 55 insertions(+), 8 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 9cc354323..5fa474dd6 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -790,6 +790,7 @@ HISTORY_MSG_WAVCLARI;Clarity HISTORY_MSG_WAVUSHAMET;Clarity method HISTORY_MSG_WAVMERGEL;Merge L HISTORY_MSG_WAVMERGEC;Merge C +HISTORY_MSG_WAVSIGMA;Sigma HISTORY_MSG_WAVSOFTRAD;Soft radius clarity HISTORY_MSG_WAVSOFTRADEND;Soft radius final HISTORY_MSG_WAVSHOWMASK;Show wavelet mask @@ -2236,6 +2237,7 @@ TP_WAVELET_RESCONH;Highlights TP_WAVELET_RESID;Residual Image TP_WAVELET_SAT;Saturated chroma TP_WAVELET_SETTINGS;Wavelet Settings +TP_WAVELET_SIGMA;Sigma 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. TP_WAVELET_SKY;Sky targetting/protection diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index f45b21f28..f2c8c8182 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -63,6 +63,7 @@ namespace rtengine struct cont_params { float mul[10]; + float sigm; int chrom; int chro; int contrast; @@ -224,6 +225,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const if (params->wavelet.BAmethod == "cur") { cp.BAmet = 2; } + cp.sigm = params->wavelet.sigma; cp.tmstrength = params->wavelet.tmrs; //cp.tonemap = params->wavelet.tmr; @@ -2997,15 +2999,29 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz //for each pixel and each level float beta; float mea[9]; - mea[0] = mean[level] / 6.f; - mea[1] = mean[level] / 2.f; + float rap = mean[level] - 2.f * cp.sigm * sigma[level]; + + if (rap > 0.f) { + mea[0] = rap; + } else { + mea[0] = mean[level] / 6.f; + } + + rap = mean[level] - cp.sigm * sigma[level]; + + if (rap > 0.f) { + mea[1] = rap; + } else { + mea[1] = mean[level] / 2.f; + } + mea[2] = mean[level]; // 50% data - mea[3] = mean[level] + sigma[level] / 2.f; - mea[4] = mean[level] + sigma[level]; //66% - mea[5] = mean[level] + 1.2f * sigma[level]; - mea[6] = mean[level] + 1.5f * sigma[level]; // - mea[7] = mean[level] + 2.f * sigma[level]; //95% - mea[8] = mean[level] + 2.5f * sigma[level]; //99% + mea[3] = mean[level] + cp.sigm * sigma[level] / 2.f; + mea[4] = mean[level] + cp.sigm * sigma[level]; //66% + mea[5] = mean[level] + cp.sigm * 1.2f * sigma[level]; + mea[6] = mean[level] + cp.sigm * 1.5f * sigma[level]; // + mea[7] = mean[level] + cp.sigm * 2.f * sigma[level]; //95% + mea[8] = mean[level] + cp.sigm * 2.5f * sigma[level]; //99% bool useChromAndHue = (skinprot != 0.f || cp.HSmet); float modchro; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index f92b40191..1822a81c7 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2263,6 +2263,7 @@ WaveletParams::WaveletParams() : TMmethod("cont"), Dirmethod("all"), HSmethod("with"), + sigma(1.0), rescon(0), resconH(0), reschro(0), @@ -2369,6 +2370,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const && TMmethod == other.TMmethod && Dirmethod == other.Dirmethod && HSmethod == other.HSmethod + && sigma == other.sigma && rescon == other.rescon && resconH == other.resconH && reschro == other.reschro @@ -3548,6 +3550,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.avoid, "Wavelet", "AvoidColorShift", wavelet.avoid, keyFile); saveToKeyfile(!pedited || pedited->wavelet.showmask, "Wavelet", "Showmask", wavelet.showmask, keyFile); saveToKeyfile(!pedited || pedited->wavelet.tmr, "Wavelet", "TMr", wavelet.tmr, keyFile); + saveToKeyfile(!pedited || pedited->wavelet.sigma, "Wavelet", "Sigma", wavelet.sigma, keyFile); saveToKeyfile(!pedited || pedited->wavelet.rescon, "Wavelet", "ResidualcontShadow", wavelet.rescon, keyFile); saveToKeyfile(!pedited || pedited->wavelet.resconH, "Wavelet", "ResidualcontHighlight", wavelet.resconH, keyFile); saveToKeyfile(!pedited || pedited->wavelet.thr, "Wavelet", "ThresholdResidShadow", wavelet.thr, keyFile); @@ -4655,6 +4658,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Wavelet", "TMMethod", pedited, wavelet.TMmethod, pedited->wavelet.TMmethod); assignFromKeyfile(keyFile, "Wavelet", "HSMethod", pedited, wavelet.HSmethod, pedited->wavelet.HSmethod); assignFromKeyfile(keyFile, "Wavelet", "DirMethod", pedited, wavelet.Dirmethod, pedited->wavelet.Dirmethod); + assignFromKeyfile(keyFile, "Wavelet", "Sigma", pedited, wavelet.sigma, pedited->wavelet.sigma); assignFromKeyfile(keyFile, "Wavelet", "ResidualcontShadow", pedited, wavelet.rescon, pedited->wavelet.rescon); assignFromKeyfile(keyFile, "Wavelet", "ResidualcontHighlight", pedited, wavelet.resconH, pedited->wavelet.resconH); assignFromKeyfile(keyFile, "Wavelet", "Residualchroma", pedited, wavelet.reschro, pedited->wavelet.reschro); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 839872e77..7ad99b594 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1237,6 +1237,7 @@ struct WaveletParams { Glib::ustring TMmethod; Glib::ustring Dirmethod; Glib::ustring HSmethod; + double sigma; int rescon; int resconH; int reschro; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index d4e2bd759..c915685bc 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -504,6 +504,7 @@ void ParamsEdited::set(bool v) wavelet.TMmethod = v; wavelet.HSmethod = v; wavelet.Dirmethod = v; + wavelet.sigma = v; wavelet.rescon = v; wavelet.resconH = v; wavelet.reschro = v; @@ -1095,6 +1096,7 @@ void ParamsEdited::initFrom(const std::vector& wavelet.TMmethod = wavelet.TMmethod && p.wavelet.TMmethod == other.wavelet.TMmethod; wavelet.HSmethod = wavelet.HSmethod && p.wavelet.HSmethod == other.wavelet.HSmethod; wavelet.Dirmethod = wavelet.Dirmethod && p.wavelet.Dirmethod == other.wavelet.Dirmethod; + wavelet.sigma = wavelet.sigma && p.wavelet.sigma == other.wavelet.sigma; wavelet.rescon = wavelet.rescon && p.wavelet.rescon == other.wavelet.rescon; wavelet.resconH = wavelet.resconH && p.wavelet.resconH == other.wavelet.resconH; wavelet.reschro = wavelet.reschro && p.wavelet.reschro == other.wavelet.reschro; @@ -3132,6 +3134,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.edgeampli = mods.wavelet.edgeampli; } + if (wavelet.sigma) { + toEdit.wavelet.sigma = mods.wavelet.sigma; + } + if (wavelet.resconH) { toEdit.wavelet.resconH = dontforceSet && options.baBehav[ADDSET_WA_RESCONH] ? toEdit.wavelet.resconH + mods.wavelet.resconH : mods.wavelet.resconH; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index d166e7ccc..4f7fabd1a 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -520,6 +520,7 @@ struct WaveletParamsEdited { bool Tilesmethod; bool daubcoeffmethod; bool Dirmethod; + bool sigma; bool rescon; bool resconH; bool reschro; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index c95736a80..252ed0abe 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -80,6 +80,7 @@ Wavelet::Wavelet() : tmr(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_BALCHRO")))), showmask(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_SHOWMASK")))), neutralchButton(Gtk::manage(new Gtk::Button(M("TP_WAVELET_NEUTRAL")))), + sigma(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMA"), 0.2, 2.5, 0.01, 1.))), rescon(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCON"), 0, 100, 1, 0))), resconH(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCONH"), 0, 100, 1, 0))), reschro(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0))), @@ -173,6 +174,7 @@ Wavelet::Wavelet() : EvWavedgs = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVEDGS"); EvWavscale = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSCALE"); EvWavradius = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVRADIUS"); + EvWavsigma = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSIGMA"); expsettings->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings)); @@ -325,6 +327,9 @@ Wavelet::Wavelet() : levBox->pack_start(*correction[i]); } + sigma->setAdjusterListener(this); + levBox->pack_start(*sigma, Gtk::PACK_SHRINK); + levBox->pack_start(*sup); sup->setAdjusterListener(this); wavLabels->show(); @@ -1226,6 +1231,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) lastavoid = pp->wavelet.avoid; lastshowmask = pp->wavelet.showmask; lasttmr = pp->wavelet.tmr; + sigma->setValue(pp->wavelet.sigma); rescon->setValue(pp->wavelet.rescon); resconH->setValue(pp->wavelet.resconH); reschro->setValue(pp->wavelet.reschro); @@ -1377,6 +1383,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) tmr->set_inconsistent(!pedited->wavelet.tmr); edgthresh->setEditedState(pedited->wavelet.edgthresh ? Edited : UnEdited); rescon->setEditedState(pedited->wavelet.rescon ? Edited : UnEdited); + sigma->setEditedState(pedited->wavelet.sigma ? Edited : UnEdited); resconH->setEditedState(pedited->wavelet.resconH ? Edited : UnEdited); reschro->setEditedState(pedited->wavelet.reschro ? Edited : UnEdited); tmrs->setEditedState(pedited->wavelet.tmrs ? Edited : UnEdited); @@ -1558,6 +1565,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.avoid = avoid->get_active(); pp->wavelet.showmask = showmask->get_active(); pp->wavelet.tmr = tmr->get_active(); + pp->wavelet.sigma = sigma->getValue(); pp->wavelet.rescon = rescon->getValue(); pp->wavelet.resconH = resconH->getValue(); pp->wavelet.reschro = reschro->getValue(); @@ -1668,6 +1676,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.HSmethod = HSmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.Dirmethod = Dirmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.edgthresh = edgthresh->getEditedState(); + pedited->wavelet.sigma = sigma->getEditedState(); pedited->wavelet.rescon = rescon->getEditedState(); pedited->wavelet.resconH = resconH->getEditedState(); pedited->wavelet.reschro = reschro->getEditedState(); @@ -1902,6 +1911,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); + sigma->setDefault(defParams->wavelet.sigma); rescon->setDefault(defParams->wavelet.rescon); resconH->setDefault(defParams->wavelet.resconH); reschro->setDefault(defParams->wavelet.reschro); @@ -1963,6 +1973,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit softrad->setDefaultEditedState(pedited->wavelet.softrad ? Edited : UnEdited); softradend->setDefaultEditedState(pedited->wavelet.softradend ? Edited : UnEdited); + sigma->setDefault(defParams->wavelet.sigma); rescon->setDefault(defParams->wavelet.rescon); resconH->setDefault(defParams->wavelet.resconH); reschro->setDefault(defParams->wavelet.reschro); @@ -2013,6 +2024,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit correctionch[i]->setDefaultEditedState(pedited->wavelet.ch[i] ? Edited : UnEdited); } } else { + sigma->setDefaultEditedState(Irrelevant); rescon->setDefaultEditedState(Irrelevant); resconH->setDefaultEditedState(Irrelevant); reschro->setDefaultEditedState(Irrelevant); @@ -2540,6 +2552,7 @@ void Wavelet::setBatchMode(bool batchMode) opacityCurveEditorWL->setBatchMode(batchMode); curveEditorRES->setBatchMode(batchMode); curveEditorGAM->setBatchMode(batchMode); + sigma->showEditedCB(); rescon->showEditedCB(); resconH->showEditedCB(); reschro->showEditedCB(); @@ -2621,6 +2634,8 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval) listener->panelChanged(EvWavtiles, edgthresh->getTextValue()); } else if (a == rescon) { listener->panelChanged(EvWavrescon, rescon->getTextValue()); + } else if (a == sigma) { + listener->panelChanged(EvWavsigma, sigma->getTextValue()); } else if (a == resconH) { listener->panelChanged(EvWavresconH, resconH->getTextValue()); } else if (a == reschro) { diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index b18ac668b..9d9502670 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -76,6 +76,7 @@ private: rtengine::ProcEvent EvWavedgs; rtengine::ProcEvent EvWavscale; rtengine::ProcEvent EvWavradius; + rtengine::ProcEvent EvWavsigma; void foldAllButMe (GdkEventButton* event, MyExpander *expander); @@ -167,6 +168,7 @@ private: Gtk::Button* const neutralchButton; Adjuster* correction[9]; Adjuster* correctionch[9]; + Adjuster* const sigma; Adjuster* const rescon; Adjuster* const resconH; Adjuster* const reschro;