diff --git a/rtdata/languages/default b/rtdata/languages/default index 83262a3fc..c49205767 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -791,7 +791,8 @@ HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength HISTORY_MSG_TEMPOUT;CAM02 automatic temperature HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor HISTORY_MSG_TRANS_Method;Geometry - Method -HISTORY_MSG_WAVBALCHROM;Balance chroma +HISTORY_MSG_WAVBALCHROM;Equalizer chrominance +HISTORY_MSG_WAVBALLUM;Equalizer luminance HISTORY_MSG_WAVCHROMFI;Chroma fine HISTORY_MSG_WAVCHROMCO;Chroma coarse HISTORY_MSG_WAVCLARI;Clarity @@ -2145,7 +2146,8 @@ TP_WAVELET_BALANCE;Contrast balance d/v-h TP_WAVELET_BALANCE_TOOLTIP;Alters the balance between the wavelet directions: vertical-horizontal and diagonal.\nIf contrast, chroma or residual tone mapping are activated, the effect due to balance is amplified. TP_WAVELET_BALCHRO;Chrominance balance TP_WAVELET_BALCHRO_TOOLTIP;If enabled, the 'Contrast balance' curve or slider also modifies chroma balance. -TP_WAVELET_BALCHROM;Chrominance balance +TP_WAVELET_BALCHROM;Denoise Equalizer Blue-Red +TP_WAVELET_BALLUM;Denoise Equalizer White-Black TP_WAVELET_BANONE;None TP_WAVELET_BASLI;Slider TP_WAVELET_BATYPE;Contrast balance method diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index 34e7351b8..894c72ce2 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -2214,7 +2214,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5); const float eps = 0.01f; - if (edge == 1 || edge == 3) { + if (edge == 1 || edge == 3 || edge == 4) { maxlvl = 4; //for refine denoise edge wavelet } @@ -2294,7 +2294,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W } } - if (edge == 2) { + if (edge == 2 || edge == 4) { for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) { nvl[i] = vari[lvl] * SQR(noisevarlum[i]); } @@ -2721,7 +2721,7 @@ void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, f } } - if (edge == 2) { + if (edge == 2 || edge == 4) { for (int i = 0; i < W_L * H_L; ++i) { nvl[i] = vari[level] * SQR(noisevarlum[i]); } diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 43c5733db..a5dc1b7c6 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -138,6 +138,7 @@ struct cont_params { float edgampl; int neigh; bool lipp; + float ballum; float balchrom; float chromfi; float chromco; @@ -401,6 +402,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const cp.balchrom = waparams.balchrom; cp.chromfi = 0.1f * waparams.chromfi; cp.chromco = 0.1f * waparams.chromco; + cp.ballum = waparams.ballum; cp.conres = waparams.rescon; cp.conresH = waparams.resconH; @@ -884,16 +886,62 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const vari[1] = 8.f * SQR((cp.lev1n / 125.f) * (1.f + cp.lev1n / 25.f)); vari[2] = 8.f * SQR((cp.lev2n / 125.f) * (1.f + cp.lev2n / 25.f)); vari[3] = 8.f * SQR((cp.lev3n / 125.f) * (1.f + cp.lev3n / 25.f)); + float kr3 = 1.f; + if (cp.lev3n < 10.f) { + kr3 = 0.f; + } else if (cp.lev3n < 30.f) { + kr3 = 0.5f; + } else if (cp.lev3n < 70.f) { + kr3 = 0.7f; + } else { + kr3 = 1.f; + } if ((cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f) && cp.noiseena) { - int edge = 1; + int edge = 4; vari[0] = rtengine::max(0.0001f, vari[0]); vari[1] = rtengine::max(0.0001f, vari[1]); vari[2] = rtengine::max(0.0001f, vari[2]); - vari[3] = rtengine::max(0.0001f, vari[3]); - float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL + vari[3] = rtengine::max(0.0001f, kr3 * vari[3]); + // float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL + int GWL = labco->W; + int GHL = labco->H; + float* noisevarlum = new float[GHL * GWL]; + int GW2L = (GWL + 1) / 2; - WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1); + float nvlh[13] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.7f, 0.5f}; //high value + float nvll[13] = {0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.7f, 0.8f, 1.f, 1.f, 1.f}; //low value + + float seuillow = 3000.f;//low + float seuilhigh = 18000.f;//high + int i = 10 - cp.ballum; + float ac = (nvlh[i] - nvll[i]) / (seuillow - seuilhigh); + float bc = nvlh[i] - seuillow * ac; + +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int ir = 0; ir < GHL; ir++) + for (int jr = 0; jr < GWL; jr++) { + float lN = labco->L[ir][jr]; + + if (lN < seuillow) { + noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = nvlh[i]; + } else if (lN < seuilhigh) { + noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = ac * lN + bc; + } else { + noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = nvll[i]; + } + } + if (cp.lev3n < 0.5f) { + WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1); + } else { + WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL, vari, edge, 1); + + WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1); + } } //Flat curve for Contrast=f(H) in levels diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index b398cc729..b02f1970c 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2248,6 +2248,7 @@ WaveletParams::WaveletParams() : bluemed(0), greenhigh(0), bluehigh(0), + ballum(7.), balchrom(0.), chromfi(0.), chromco(0.), @@ -2361,6 +2362,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const && bluemed == other.bluemed && greenhigh == other.greenhigh && bluehigh == other.bluehigh + && ballum == other.ballum && balchrom == other.balchrom && chromfi == other.chromfi && chromco == other.chromco @@ -3526,6 +3528,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.bluehigh, "Wavelet", "CBbluehigh", wavelet.bluehigh, keyFile); saveToKeyfile(!pedited || pedited->wavelet.bluemed, "Wavelet", "CBbluemed", wavelet.bluemed, keyFile); saveToKeyfile(!pedited || pedited->wavelet.bluelow, "Wavelet", "CBbluelow", wavelet.bluelow, keyFile); + saveToKeyfile(!pedited || pedited->wavelet.ballum, "Wavelet", "Ballum", wavelet.ballum, keyFile); saveToKeyfile(!pedited || pedited->wavelet.balchrom, "Wavelet", "Balchrom", wavelet.balchrom, keyFile); saveToKeyfile(!pedited || pedited->wavelet.chromfi, "Wavelet", "Chromfine", wavelet.chromfi, keyFile); saveToKeyfile(!pedited || pedited->wavelet.chromco, "Wavelet", "Chromcoarse", wavelet.chromco, keyFile); @@ -4699,6 +4702,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Wavelet", "CBbluehigh", pedited, wavelet.bluehigh, pedited->wavelet.bluehigh); assignFromKeyfile(keyFile, "Wavelet", "CBbluemed", pedited, wavelet.bluemed, pedited->wavelet.bluemed); assignFromKeyfile(keyFile, "Wavelet", "CBbluelow", pedited, wavelet.bluelow, pedited->wavelet.bluelow); + assignFromKeyfile(keyFile, "Wavelet", "Ballum", pedited, wavelet.ballum, pedited->wavelet.ballum); assignFromKeyfile(keyFile, "Wavelet", "Balchrom", pedited, wavelet.balchrom, pedited->wavelet.balchrom); assignFromKeyfile(keyFile, "Wavelet", "Chromfine", pedited, wavelet.chromfi, pedited->wavelet.chromfi); assignFromKeyfile(keyFile, "Wavelet", "Chromcoarse", pedited, wavelet.chromco, pedited->wavelet.chromco); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index a6147ccc5..4e2b0c275 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1205,6 +1205,7 @@ struct WaveletParams { int bluemed; int greenhigh; int bluehigh; + double ballum; double balchrom; double chromfi; double chromco; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 0685e1471..0faee0fd3 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -486,6 +486,7 @@ void ParamsEdited::set(bool v) wavelet.bluemed = v; wavelet.bluelow = v; wavelet.lipst = v; + wavelet.ballum = v; wavelet.balchrom = v; wavelet.chromfi = v; wavelet.chromco = v; @@ -1096,6 +1097,7 @@ void ParamsEdited::initFrom(const std::vector& wavelet.bluelow = wavelet.bluelow && p.wavelet.bluelow == other.wavelet.bluelow; wavelet.lipst = wavelet.lipst && p.wavelet.lipst == other.wavelet.lipst; wavelet.bluehigh = wavelet.bluehigh && p.wavelet.bluehigh == other.wavelet.bluehigh; + wavelet.ballum = wavelet.ballum && p.wavelet.ballum == other.wavelet.ballum; wavelet.balchrom = wavelet.balchrom && p.wavelet.balchrom == other.wavelet.balchrom; wavelet.chromfi = wavelet.chromfi && p.wavelet.chromfi == other.wavelet.chromfi; wavelet.chromco = wavelet.chromco && p.wavelet.chromco == other.wavelet.chromco; @@ -2935,6 +2937,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.bluelow = mods.wavelet.bluelow; } + if (wavelet.ballum) { + toEdit.wavelet.ballum = mods.wavelet.ballum; + } + if (wavelet.balchrom) { toEdit.wavelet.balchrom = mods.wavelet.balchrom; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 4465d15b4..d1be2c57e 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -586,6 +586,7 @@ struct WaveletParamsEdited { bool bluemed; bool greenhigh; bool bluehigh; + bool ballum; bool balchrom; bool chromfi; bool chromco; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 23e526474..652774af4 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -130,6 +130,7 @@ Wavelet::Wavelet() : edgedetectthr2(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECTTHR2"), -10, 100, 1, 0))), edgesensi(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGESENSI"), 0, 100, 1, 60))), edgeampli(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEAMPLI"), 0, 100, 1, 10))), + ballum(Gtk::manage(new Adjuster(M("TP_WAVELET_BALLUM"), -2., 10., 0.5, 7., Gtk::manage(new RTImage("circle-white-small.png")), Gtk::manage(new RTImage("circle-black-small.png"))))), balchrom(Gtk::manage(new Adjuster(M("TP_WAVELET_BALCHROM"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-red-small.png"))))), chromfi(Gtk::manage(new Adjuster(M("TP_WAVELET_CHROMFI"), 0.0, 150., 0.01, 0.))), chromco(Gtk::manage(new Adjuster(M("TP_WAVELET_CHROMCO"), 0, 100., 0.01, 0.))), @@ -183,6 +184,7 @@ Wavelet::Wavelet() : auto m = ProcEventMapper::getInstance(); EvWavenaclari = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCLARI"); EvWavushamet = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVUSHAMET"); + EvWavballum = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVBALLUM"); EvWavbalchrom = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVBALCHROM"); EvWavchromfi = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCHROMFI"); EvWavchromco = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCHROMCO"); @@ -524,7 +526,9 @@ Wavelet::Wavelet() : level3noise->setAdjusterListener(this); level3noise->setUpdatePolicy(RTUP_DYNAMIC); + ballum->setAdjusterListener(this); + noiseBox->pack_start(*ballum); noiseBox->pack_start(*level0noise, Gtk::PACK_SHRINK, 0); noiseBox->pack_start(*level1noise, Gtk::PACK_SHRINK, 0); noiseBox->pack_start(*level2noise, Gtk::PACK_SHRINK, 0); @@ -1403,6 +1407,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) softrad->setValue(pp->wavelet.softrad); softradend->setValue(pp->wavelet.softradend); + ballum->setValue(pp->wavelet.ballum); balchrom->setValue(pp->wavelet.balchrom); chromfi->setValue(pp->wavelet.chromfi); chromco->setValue(pp->wavelet.chromco); @@ -1551,6 +1556,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) softrad->setEditedState(pedited->wavelet.softrad ? Edited : UnEdited); softradend->setEditedState(pedited->wavelet.softradend ? Edited : UnEdited); + ballum->setEditedState(pedited->wavelet.ballum ? Edited : UnEdited); balchrom->setEditedState(pedited->wavelet.balchrom ? Edited : UnEdited); chromfi->setEditedState(pedited->wavelet.chromfi ? Edited : UnEdited); chromco->setEditedState(pedited->wavelet.chromco ? Edited : UnEdited); @@ -1774,6 +1780,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.strength = (int) strength->getValue(); pp->wavelet.balance = (int) balance->getValue(); pp->wavelet.balchrom = balchrom->getValue(); + pp->wavelet.ballum = ballum->getValue(); pp->wavelet.chromfi = chromfi->getValue(); pp->wavelet.chromco = chromco->getValue(); @@ -1895,6 +1902,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.bluemed = bluemed->getEditedState(); pedited->wavelet.greenhigh = greenhigh->getEditedState(); pedited->wavelet.bluehigh = bluehigh->getEditedState(); + pedited->wavelet.ballum = ballum->getEditedState(); pedited->wavelet.balchrom = balchrom->getEditedState(); pedited->wavelet.chromfi = chromfi->getEditedState(); pedited->wavelet.chromco = chromco->getEditedState(); @@ -2129,6 +2137,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit level1noise->setDefault (defParams->wavelet.level1noise); level2noise->setDefault (defParams->wavelet.level2noise); level3noise->setDefault (defParams->wavelet.level3noise); + ballum->setDefault(defParams->wavelet.ballum); balchrom->setDefault(defParams->wavelet.balchrom); chromfi->setDefault(defParams->wavelet.chromfi); chromco->setDefault(defParams->wavelet.chromco); @@ -2155,6 +2164,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit mergeC->setDefaultEditedState(pedited->wavelet.mergeC ? Edited : UnEdited); softrad->setDefaultEditedState(pedited->wavelet.softrad ? Edited : UnEdited); softradend->setDefaultEditedState(pedited->wavelet.softradend ? Edited : UnEdited); + ballum->setDefaultEditedState(pedited->wavelet.ballum ? Edited : UnEdited); balchrom->setDefaultEditedState(pedited->wavelet.balchrom ? Edited : UnEdited); chromfi->setDefaultEditedState(pedited->wavelet.chromfi ? Edited : UnEdited); chromco->setDefaultEditedState(pedited->wavelet.chromco ? Edited : UnEdited); @@ -2951,6 +2961,8 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval) listener->panelChanged(EvWavgreenhigh, greenhigh->getTextValue()); } else if (a == bluehigh) { listener->panelChanged(EvWavbluehigh, bluehigh->getTextValue()); + } else if (a == ballum) { + listener->panelChanged(EvWavballum, ballum->getTextValue()); } else if (a == balchrom) { listener->panelChanged(EvWavbalchrom, balchrom->getTextValue()); } else if (a == chromfi) { diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index 07d2432ac..d1b4bb7c3 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -70,6 +70,7 @@ public: private: rtengine::ProcEvent EvWavenaclari; rtengine::ProcEvent EvWavushamet; + rtengine::ProcEvent EvWavballum; rtengine::ProcEvent EvWavbalchrom; rtengine::ProcEvent EvWavchromfi; rtengine::ProcEvent EvWavchromco; @@ -244,6 +245,7 @@ private: Adjuster* const edgedetectthr2; Adjuster* const edgesensi; Adjuster* const edgeampli; + Adjuster* const ballum; Adjuster* const balchrom; Adjuster* const chromfi; Adjuster* const chromco;