diff --git a/rtdata/languages/default b/rtdata/languages/default index fe6ddaa7c..3229e1015 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -802,6 +802,7 @@ HISTORY_MSG_WAVSIGMA;Sigma HISTORY_MSG_WAVSOFTRAD;Soft radius clarity HISTORY_MSG_WAVSOFTRADEND;Soft radius final HISTORY_MSG_WAVUSHAMET;Clarity method +HISTORY_MSG_WAVOLDSH;Old algorithm HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -2243,6 +2244,7 @@ TP_WAVELET_NPLOW;Low TP_WAVELET_NPNONE;None TP_WAVELET_NPTYPE;Neighboring pixels TP_WAVELET_NPTYPE_TOOLTIP;This algorithm uses the proximity of a pixel and eight of its neighbors. If less difference, edges are reinforced. +TP_WAVELET_OLDSH;Old 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 diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 758a9147b..54d103b7b 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -63,6 +63,7 @@ struct cont_params { float conresH; float radius; float chrores; + bool oldsh; float hueres; float sky; float b_l, t_l, b_r, t_r; @@ -387,6 +388,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const cp.conresH = waparams.resconH; cp.radius = waparams.radius; cp.chrores = waparams.reschro; + cp.oldsh = waparams.oldsh; //cp.hueres=waparams.reshue; cp.hueres = 2.f; cp.th = float(waparams.thr); @@ -1689,7 +1691,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * } } - if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena) { // 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 @@ -1721,6 +1723,50 @@ 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 +#ifdef _OPENMP + #pragma omp for nowait +#endif + + for (int i = 0; i < W_L * H_L; i++) { + float LL = WavCoeffs_L0[i]; + float LL100 = LL / 327.68f; + float tran = 5.f;//transition + //shadow + float alp = 3.f; //increase contrast sahdow in lowlights between 1 and ?? + + if(cp.th > (100.f - tran)) { + tran = 100.f - cp.th; + } + + if(LL100 < cp.th) { + float aalp = (1.f - alp) / cp.th; //no changes for LL100 = cp.th + float kk = aalp * LL100 + alp; + WavCoeffs_L0[i] *= (1.f + kk * cp.conres / 200.f); + } else if(LL100 < cp.th + tran) { + float ath = -cp.conres / tran; + float bth = cp.conres - ath * cp.th; + WavCoeffs_L0[i] *= (1.f + (LL100 * ath + bth) / 200.f); + } + + //highlight + tran = 5.f; + + if(cp.thH < (tran)) { + tran = cp.thH; + } + + if(LL100 > cp.thH) { + WavCoeffs_L0[i] *= (1.f + cp.conresH / 200.f); + } else if(LL100 > (cp.thH - tran)) { + float athH = cp.conresH / tran; + float bthH = cp.conresH - athH * cp.thH; + WavCoeffs_L0[i] *= (1.f + (LL100 * athH + bthH) / 200.f); + } + } + } + + #ifdef _OPENMP #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index e795d9bd9..879423961 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2243,6 +2243,7 @@ WaveletParams::WaveletParams() : lipst(false), avoid(false), showmask(false), + oldsh(true), tmr(false), strength(100), balance(0), @@ -2343,6 +2344,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const && lipst == other.lipst && avoid == other.avoid && showmask == other.showmask + && oldsh == other.oldsh && tmr == other.tmr && strength == other.strength && balance == other.balance @@ -3562,6 +3564,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.edgthresh, "Wavelet", "ThrEdg", wavelet.edgthresh, keyFile); saveToKeyfile(!pedited || pedited->wavelet.avoid, "Wavelet", "AvoidColorShift", wavelet.avoid, keyFile); saveToKeyfile(!pedited || pedited->wavelet.showmask, "Wavelet", "Showmask", wavelet.showmask, keyFile); + 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.rescon, "Wavelet", "ResidualcontShadow", wavelet.rescon, keyFile); @@ -4654,6 +4657,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Wavelet", "Lipst", pedited, wavelet.lipst, pedited->wavelet.lipst); assignFromKeyfile(keyFile, "Wavelet", "AvoidColorShift", pedited, wavelet.avoid, pedited->wavelet.avoid); assignFromKeyfile(keyFile, "Wavelet", "Showmask", pedited, wavelet.showmask, pedited->wavelet.showmask); + assignFromKeyfile(keyFile, "Wavelet", "Oldsh", pedited, wavelet.oldsh, pedited->wavelet.oldsh); assignFromKeyfile(keyFile, "Wavelet", "TMr", pedited, wavelet.tmr, pedited->wavelet.tmr); if (ppVersion < 331) { // wavelet.Lmethod was a string before version 331 diff --git a/rtengine/procparams.h b/rtengine/procparams.h index aabe1e7ae..2eb18781d 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1211,6 +1211,7 @@ struct WaveletParams { bool lipst; bool avoid; bool showmask; + bool oldsh; bool tmr; int strength; int balance; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 48ba4c341..66a302f55 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -494,6 +494,7 @@ void ParamsEdited::set(bool v) wavelet.ushamethod = v; wavelet.avoid = v; wavelet.showmask = v; + wavelet.oldsh = v; wavelet.tmr = v; wavelet.Lmethod = v; wavelet.CLmethod = v; @@ -1090,6 +1091,7 @@ void ParamsEdited::initFrom(const std::vector& wavelet.ushamethod = wavelet.ushamethod && p.wavelet.ushamethod == other.wavelet.ushamethod; wavelet.avoid = wavelet.avoid && p.wavelet.avoid == other.wavelet.avoid; wavelet.showmask = wavelet.showmask && p.wavelet.showmask == other.wavelet.showmask; + wavelet.oldsh = wavelet.oldsh && p.wavelet.oldsh == other.wavelet.oldsh; wavelet.tmr = wavelet.tmr && p.wavelet.tmr == other.wavelet.tmr; wavelet.Lmethod = wavelet.Lmethod && p.wavelet.Lmethod == other.wavelet.Lmethod; wavelet.CLmethod = wavelet.CLmethod && p.wavelet.CLmethod == other.wavelet.CLmethod; @@ -2945,6 +2947,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.showmask = mods.wavelet.showmask; } + if (wavelet.oldsh) { + toEdit.wavelet.oldsh = mods.wavelet.oldsh; + } + if (wavelet.tmr) { toEdit.wavelet.tmr = mods.wavelet.tmr; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index d2707ec11..9e50031fb 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -508,6 +508,7 @@ struct WaveletParamsEdited { bool ushamethod; bool avoid; bool showmask; + bool oldsh; bool tmr; bool c[9]; bool ch[9]; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 7d9a65f2a..e314ee018 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -79,10 +79,11 @@ Wavelet::Wavelet() : avoid(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_AVOID")))), tmr(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_BALCHRO")))), showmask(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_SHOWMASK")))), + 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.))), - 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))), + 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))), tmrs(Gtk::manage(new Adjuster(M("TP_WAVELET_TMSTRENGTH"), -1.0, 2.0, 0.01, 0.0))), edgs(Gtk::manage(new Adjuster(M("TP_WAVELET_TMEDGS"), 0.1, 4.0, 0.01, 1.4))), @@ -175,6 +176,7 @@ Wavelet::Wavelet() : EvWavscale = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSCALE"); EvWavradius = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVRADIUS"); EvWavsigma = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSIGMA"); + EvWavoldsh = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVOLDSH"); expsettings->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings)); @@ -675,6 +677,9 @@ Wavelet::Wavelet() : // Residual Image ToolParamBlock* const resBox = Gtk::manage(new ToolParamBlock()); + oldsh->set_active(true); + oldshConn = oldsh->signal_toggled().connect(sigc::mem_fun(*this, &Wavelet::oldshToggled)); + resBox->pack_start(*oldsh); rescon->setAdjusterListener(this); resBox->pack_start(*rescon, Gtk::PACK_SHRINK); @@ -1200,6 +1205,9 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) showmaskConn.block(true); showmask->set_active(pp->wavelet.showmask); showmaskConn.block(false); + oldshConn.block(true); + oldsh->set_active(pp->wavelet.oldsh); + oldshConn.block(false); tmrConn.block(true); tmr->set_active(pp->wavelet.tmr); tmrConn.block(false); @@ -1230,6 +1238,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) lastlipst = pp->wavelet.lipst; lastavoid = pp->wavelet.avoid; lastshowmask = pp->wavelet.showmask; + lastoldsh = pp->wavelet.oldsh; lasttmr = pp->wavelet.tmr; sigma->setValue(pp->wavelet.sigma); rescon->setValue(pp->wavelet.rescon); @@ -1380,6 +1389,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) clshape->setUnChanged(!pedited->wavelet.wavclCurve); avoid->set_inconsistent(!pedited->wavelet.avoid); showmask->set_inconsistent(!pedited->wavelet.showmask); + oldsh->set_inconsistent(!pedited->wavelet.oldsh); tmr->set_inconsistent(!pedited->wavelet.tmr); edgthresh->setEditedState(pedited->wavelet.edgthresh ? Edited : UnEdited); rescon->setEditedState(pedited->wavelet.rescon ? Edited : UnEdited); @@ -1564,6 +1574,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.enabled = getEnabled(); pp->wavelet.avoid = avoid->get_active(); pp->wavelet.showmask = showmask->get_active(); + pp->wavelet.oldsh = oldsh->get_active(); pp->wavelet.tmr = tmr->get_active(); pp->wavelet.sigma = sigma->getValue(); pp->wavelet.rescon = rescon->getValue(); @@ -1654,6 +1665,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.enabled = !get_inconsistent(); pedited->wavelet.avoid = !avoid->get_inconsistent(); pedited->wavelet.showmask = !showmask->get_inconsistent(); + pedited->wavelet.oldsh = !oldsh->get_inconsistent(); pedited->wavelet.tmr = !tmr->get_inconsistent(); pedited->wavelet.median = !median->get_inconsistent(); pedited->wavelet.medianlev = !medianlev->get_inconsistent(); @@ -3120,6 +3132,32 @@ void Wavelet::showmaskToggled() } } +void Wavelet::oldshToggled() +{ + if (multiImage) { + if (oldsh->get_inconsistent()) { + oldsh->set_inconsistent(false); + oldshConn.block(true); + oldsh->set_active(false); + oldshConn.block(false); + } else if (lastoldsh) { + oldsh->set_inconsistent(true); + } + + lastoldsh = oldsh->get_active(); + } + + if (listener && (multiImage || getEnabled())) { + if (oldsh->get_inconsistent()) { + listener->panelChanged(EvWavoldsh, M("GENERAL_UNCHANGED")); + } else if (oldsh->get_active()) { + listener->panelChanged(EvWavoldsh, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvWavoldsh, M("GENERAL_DISABLED")); + } + } +} + void Wavelet::tmrToggled() { diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index d3b66657e..7aede083f 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -79,6 +79,7 @@ private: rtengine::ProcEvent EvWavscale; rtengine::ProcEvent EvWavradius; rtengine::ProcEvent EvWavsigma; + rtengine::ProcEvent EvWavoldsh; void foldAllButMe(GdkEventButton* event, MyExpander *expander); @@ -98,6 +99,7 @@ private: void TilesmethodChanged(); void avoidToggled(); void showmaskToggled (); + void oldshToggled (); void cbenabToggled(); void contrastMinusPressed(); void contrastPlusPressed(); @@ -166,6 +168,7 @@ private: Gtk::CheckButton* const avoid; Gtk::CheckButton* const tmr; Gtk::CheckButton* const showmask; + Gtk::CheckButton* const oldsh; Gtk::Button* const neutralchButton; Adjuster* correction[9]; @@ -281,13 +284,13 @@ private: sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enableFinalConn, enableclariConn; sigc::connection enableNoiseConn, enableResidConn, enableToningConn; - sigc::connection medianConn, avoidConn, tmrConn, medianlevConn, linkedgConn, lipstConn, cbenabConn, neutralconn, showmaskConn; + sigc::connection medianConn, avoidConn, tmrConn, medianlevConn, linkedgConn, lipstConn, cbenabConn, neutralconn, showmaskConn, oldshConn; sigc::connection neutralPressedConn; sigc::connection contrastPlusPressedConn; sigc::connection contrastMinusPressedConn; sigc::connection neutralchPressedConn; - bool lastmedian, lastmedianlev, lastlinkedg, lastavoid, lastlipst, lasttmr, lastcbenab, lastshowmask; + bool lastmedian, lastmedianlev, lastlinkedg, lastavoid, lastlipst, lasttmr, lastcbenab, lastshowmask, lastoldsh; int nextnlevel; IdleRegister idle_register;