From cdf8d8ec7f3741af1299b9d524a97bb69858404c Mon Sep 17 00:00:00 2001 From: Desmis Date: Wed, 25 Mar 2020 07:15:27 +0100 Subject: [PATCH] Wavelet - added offset to contrast levels --- rtdata/languages/default | 2 ++ rtengine/ipwavelet.cc | 21 +++++++++++---------- rtengine/procparams.cc | 4 ++++ rtengine/procparams.h | 1 + rtgui/paramsedited.cc | 8 +++++++- rtgui/paramsedited.h | 1 + rtgui/wavelet.cc | 14 ++++++++++++++ rtgui/wavelet.h | 2 ++ 8 files changed, 42 insertions(+), 11 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 3229e1015..f8cf543d6 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -803,6 +803,7 @@ HISTORY_MSG_WAVSOFTRAD;Soft radius clarity HISTORY_MSG_WAVSOFTRADEND;Soft radius final HISTORY_MSG_WAVUSHAMET;Clarity method HISTORY_MSG_WAVOLDSH;Old algorithm +HISTORY_MSG_WAVOFFSET;Offset HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -2293,6 +2294,7 @@ TP_WAVELET_USH;None TP_WAVELET_USHARP;Clarity method TP_WAVELET_USHARP_TOOLTIP;Origin : the source file is the file before Wavelet.\nWavelet : the source file is the file including wavelet threatment TP_WAVELET_USH_TOOLTIP;If you select Sharp-mask, wavelet settings will be automatically positioned :\nBackground=black, Process=below, level=3...you can change level between 1 and 4.\n\nIf you select Clarity, wavelet settings will be automatically positioned :\nBackground=residual, Process=above, level=7..you can change level between 5 and 10 and wavelet levels. +TP_WAVELET_WAVOFFSET;Offset TP_WBALANCE_AUTO;Auto TP_WBALANCE_AUTOITCGREEN;Auto iterate temperature correlation TP_WBALANCE_AUTOOLD;Auto RGB grey diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index a899f5a9a..9177db0cc 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -1691,7 +1691,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * } } - if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step LabImage *temp = nullptr; temp = new LabImage(W_L, H_L); #ifdef _OPENMP @@ -2894,13 +2894,14 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz const float skinprot = params->wavelet.skinprotect; const float skinprotneg = -skinprot; const float factorHard = (1.f - skinprotneg / 100.f); + const float offs = params->wavelet.offset; //to adjust increase contrast with local contrast //for each pixel and each level float beta; float mea[9]; - float rap = mean[level] - 2.f * cp.sigm * sigma[level]; + float rap = offs * mean[level] - 2.f * cp.sigm * sigma[level]; if (rap > 0.f) { mea[0] = rap; @@ -2908,7 +2909,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz mea[0] = mean[level] / 6.f; } - rap = mean[level] - cp.sigm * sigma[level]; + rap = offs * mean[level] - cp.sigm * sigma[level]; if (rap > 0.f) { mea[1] = rap; @@ -2916,13 +2917,13 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz mea[1] = mean[level] / 2.f; } - mea[2] = mean[level]; // 50% data - 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% + mea[2] = offs * mean[level]; // 50% data + mea[3] = offs * mean[level] + cp.sigm * sigma[level] / 2.f; + mea[4] = offs * mean[level] + cp.sigm * sigma[level]; //66% + mea[5] = offs * mean[level] + cp.sigm * 1.2f * sigma[level]; + mea[6] = offs * mean[level] + cp.sigm * 1.5f * sigma[level]; // + mea[7] = offs * mean[level] + cp.sigm * 2.f * sigma[level]; //95% + mea[8] = offs * 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 879423961..96d2302c8 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2274,6 +2274,7 @@ WaveletParams::WaveletParams() : Dirmethod("all"), HSmethod("with"), sigma(1.0), + offset(1.0), rescon(0), resconH(0), reschro(0), @@ -2382,6 +2383,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const && Dirmethod == other.Dirmethod && HSmethod == other.HSmethod && sigma == other.sigma + && offset == other.offset && rescon == other.rescon && resconH == other.resconH && reschro == other.reschro @@ -3567,6 +3569,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.oldsh, "Wavelet", "Oldsh", wavelet.oldsh, 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.offset, "Wavelet", "Offset", wavelet.offset, 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); @@ -4687,6 +4690,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) 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", "Offset", pedited, wavelet.offset, pedited->wavelet.offset); 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 2eb18781d..feee0391a 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1243,6 +1243,7 @@ struct WaveletParams { Glib::ustring Dirmethod; Glib::ustring HSmethod; double sigma; + double offset; int rescon; int resconH; int reschro; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 66a302f55..d80d98361 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -510,7 +510,8 @@ void ParamsEdited::set(bool v) wavelet.HSmethod = v; wavelet.Dirmethod = v; wavelet.sigma = v; - wavelet.rescon = v; + wavelet.sigma = v; + wavelet.offset = v; wavelet.resconH = v; wavelet.reschro = v; wavelet.tmrs = v; @@ -1107,6 +1108,7 @@ void ParamsEdited::initFrom(const std::vector& 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.offset = wavelet.offset && p.wavelet.offset == other.wavelet.offset; 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; @@ -3168,6 +3170,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.sigma = mods.wavelet.sigma; } + if (wavelet.offset) { + toEdit.wavelet.offset = mods.wavelet.offset; + } + 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 9e50031fb..8cd8e25f0 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -526,6 +526,7 @@ struct WaveletParamsEdited { bool daubcoeffmethod; bool Dirmethod; bool sigma; + bool offset; bool rescon; bool resconH; bool reschro; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 63eb7743e..956c52738 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -82,6 +82,7 @@ Wavelet::Wavelet() : oldsh(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_OLDSH")))), 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.))), + offset(Gtk::manage(new Adjuster(M("TP_WAVELET_WAVOFFSET"), 0.33, 1.66, 0.01, 1., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), rescon(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCON"), -100, 100, 1, 0))), resconH(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCONH"), -100, 100, 1, 0))), reschro(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0))), @@ -177,6 +178,7 @@ Wavelet::Wavelet() : EvWavradius = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVRADIUS"); EvWavsigma = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSIGMA"); EvWavoldsh = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVOLDSH"); + EvWavoffset = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVOFFSET"); expsettings->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings)); @@ -331,6 +333,8 @@ Wavelet::Wavelet() : sigma->setAdjusterListener(this); levBox->pack_start(*sigma, Gtk::PACK_SHRINK); + offset->setAdjusterListener(this); + levBox->pack_start(*offset, Gtk::PACK_SHRINK); levBox->pack_start(*sup); sup->setAdjusterListener(this); @@ -1241,6 +1245,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) lastoldsh = pp->wavelet.oldsh; lasttmr = pp->wavelet.tmr; sigma->setValue(pp->wavelet.sigma); + offset->setValue(pp->wavelet.offset); rescon->setValue(pp->wavelet.rescon); resconH->setValue(pp->wavelet.resconH); reschro->setValue(pp->wavelet.reschro); @@ -1394,6 +1399,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) edgthresh->setEditedState(pedited->wavelet.edgthresh ? Edited : UnEdited); rescon->setEditedState(pedited->wavelet.rescon ? Edited : UnEdited); sigma->setEditedState(pedited->wavelet.sigma ? Edited : UnEdited); + offset->setEditedState(pedited->wavelet.offset ? Edited : UnEdited); resconH->setEditedState(pedited->wavelet.resconH ? Edited : UnEdited); reschro->setEditedState(pedited->wavelet.reschro ? Edited : UnEdited); tmrs->setEditedState(pedited->wavelet.tmrs ? Edited : UnEdited); @@ -1577,6 +1583,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.oldsh = oldsh->get_active(); pp->wavelet.tmr = tmr->get_active(); pp->wavelet.sigma = sigma->getValue(); + pp->wavelet.offset = offset->getValue(); pp->wavelet.rescon = rescon->getValue(); pp->wavelet.resconH = resconH->getValue(); pp->wavelet.reschro = reschro->getValue(); @@ -1689,6 +1696,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.Dirmethod = Dirmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.edgthresh = edgthresh->getEditedState(); pedited->wavelet.sigma = sigma->getEditedState(); + pedited->wavelet.offset = offset->getEditedState(); pedited->wavelet.rescon = rescon->getEditedState(); pedited->wavelet.resconH = resconH->getEditedState(); pedited->wavelet.reschro = reschro->getEditedState(); @@ -1924,6 +1932,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit balance->setDefault(defParams->wavelet.balance); iter->setDefault(defParams->wavelet.iter); sigma->setDefault(defParams->wavelet.sigma); + offset->setDefault(defParams->wavelet.offset); rescon->setDefault(defParams->wavelet.rescon); resconH->setDefault(defParams->wavelet.resconH); reschro->setDefault(defParams->wavelet.reschro); @@ -1986,6 +1995,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit softradend->setDefaultEditedState(pedited->wavelet.softradend ? Edited : UnEdited); sigma->setDefault(defParams->wavelet.sigma); + offset->setDefault(defParams->wavelet.offset); rescon->setDefault(defParams->wavelet.rescon); resconH->setDefault(defParams->wavelet.resconH); reschro->setDefault(defParams->wavelet.reschro); @@ -2037,6 +2047,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit } } else { sigma->setDefaultEditedState(Irrelevant); + offset->setDefaultEditedState(Irrelevant); rescon->setDefaultEditedState(Irrelevant); resconH->setDefaultEditedState(Irrelevant); reschro->setDefaultEditedState(Irrelevant); @@ -2565,6 +2576,7 @@ void Wavelet::setBatchMode(bool batchMode) curveEditorRES->setBatchMode(batchMode); curveEditorGAM->setBatchMode(batchMode); sigma->showEditedCB(); + offset->showEditedCB(); rescon->showEditedCB(); resconH->showEditedCB(); reschro->showEditedCB(); @@ -2648,6 +2660,8 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval) listener->panelChanged(EvWavrescon, rescon->getTextValue()); } else if (a == sigma) { listener->panelChanged(EvWavsigma, sigma->getTextValue()); + } else if (a == offset) { + listener->panelChanged(EvWavoffset, offset->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 7aede083f..94b88fd5c 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -80,6 +80,7 @@ private: rtengine::ProcEvent EvWavradius; rtengine::ProcEvent EvWavsigma; rtengine::ProcEvent EvWavoldsh; + rtengine::ProcEvent EvWavoffset; void foldAllButMe(GdkEventButton* event, MyExpander *expander); @@ -174,6 +175,7 @@ private: Adjuster* correction[9]; Adjuster* correctionch[9]; Adjuster* const sigma; + Adjuster* const offset; Adjuster* const rescon; Adjuster* const resconH; Adjuster* const reschro;