diff --git a/rtdata/languages/default b/rtdata/languages/default index 4a419e736..ec2e32d95 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -803,7 +803,7 @@ HISTORY_MSG_WAVSOFTRAD;Soft radius clarity HISTORY_MSG_WAVSOFTRADEND;Soft radius final HISTORY_MSG_WAVUSHAMET;Clarity method HISTORY_MSG_THRESWAV;Balance threshold -HISTORY_MSG_BLUWAV;Maximum blur +HISTORY_MSG_BLUWAV;Effects HISTORY_MSG_WAVOLDSH;Old algorithm HISTORY_MSG_WAVOFFSET;Offset HISTORY_MSG_WAVLOWTHR;Threshold low contrast @@ -2146,7 +2146,7 @@ TP_WAVELET_BASLI;Slider TP_WAVELET_BATYPE;Contrast balance method TP_WAVELET_BLCURVE;Blur by levels TP_WAVELET_BLURFRAME;Blur -TP_WAVELET_BLUWAV;Maximum Blur +TP_WAVELET_BLUWAV;Effects TP_WAVELET_CBENAB;Toning and Color Balance TP_WAVELET_CB_TOOLTIP;For strong values product color-toning by combining it or not with levels decomposition 'toning'\nFor low values you can change the white balance of the background (sky, ...) without changing that of the front plane, generally more contrasted TP_WAVELET_CCURVE;Local contrast diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 424084b8c..affa33640 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -208,7 +208,7 @@ public: struct cont_params &cp, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili); void WaveletcontAllLfinal(const wavelet_decomposition &WaveletCoeffs_L, const cont_params &cp, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL); void WaveletcontAllAB(LabImage * lab, float **varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_a, const Wavblcurve & wavblcurve, const WavOpacityCurveW & waOpacityCurveW, - struct cont_params &cp, const bool useChannelA, int skip); + struct cont_params &cp, const bool useChannelA, int skip, float *meanab, float *sigmaab); void WaveletAandBAllAB(const wavelet_decomposition &WaveletCoeffs_a, const wavelet_decomposition &WaveletCoeffs_b, const cont_params &cp, FlatCurve* hhcurve, bool hhutili); void ContAllL(float **koeLi, float *maxkoeLi, bool lipschitz, int maxlvl, LabImage * lab, float **varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp, @@ -222,6 +222,8 @@ public: void Eval2(float ** WavCoeffs_L, int level, int W_L, int H_L, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN); + void calceffect(int level, float *mean, float *sigma, float *mea, float effect, float offs); + void Aver(float * HH_Coeffs, int datalen, float &averagePlus, float &averageNeg, float &max, float &min); void Sigma(float * HH_Coeffs, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg); void calckoe(float ** WavCoeffs_LL, const cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr); diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index d5b642aaa..e7f6083e6 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -400,7 +400,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const cp.oldsh = waparams.oldsh; cp.blurres = waparams.resblur; cp.blurcres = waparams.resblurc; - cp.bluwav = 0.01f * waparams.bluwav; + cp.bluwav = waparams.bluwav; //cp.hueres=waparams.reshue; cp.hueres = 2.f; cp.th = float(waparams.thr); @@ -643,6 +643,13 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const float MaxP[10]; float MaxN[10]; + float meanab[10]; + float meanNab[10]; + float sigmaab[10]; + float sigmaNab[10]; + float MaxPab[10]; + float MaxNab[10]; + array2D varchro(tilewidth, tileheight); float** varhue = new float*[tileheight]; @@ -924,7 +931,8 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const const std::unique_ptr adecomp(new wavelet_decomposition(labco->data + datalen, labco->W, labco->H, levwava, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen)); if (!adecomp->memoryAllocationFailed) { - WaveletcontAllAB(labco, varhue, varchro, *adecomp, wavblcurve, waOpacityCurveW, cp, true, skip); + Evaluate2(*adecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab); + WaveletcontAllAB(labco, varhue, varchro, *adecomp, wavblcurve, waOpacityCurveW, cp, true, skip, meanab, sigmaab); adecomp->reconstruct(labco->data + datalen, cp.strength); } } @@ -941,7 +949,8 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavb, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen)); if (!bdecomp->memoryAllocationFailed) { - WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip); + Evaluate2(*bdecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab); + WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip, meanab, sigmaab); bdecomp->reconstruct(labco->data + 2 * datalen, cp.strength); } } @@ -959,8 +968,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavab, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen)); if (!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) { - WaveletcontAllAB(labco, varhue, varchro, *adecomp,wavblcurve, waOpacityCurveW, cp, true, skip); - WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip); + Evaluate2(*adecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab); + WaveletcontAllAB(labco, varhue, varchro, *adecomp,wavblcurve, waOpacityCurveW, cp, true, skip, meanab, sigmaab); + Evaluate2(*bdecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab); + WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip, meanab, sigmaab); WaveletAandBAllAB(*adecomp, *bdecomp, cp, hhCurve, hhutili); adecomp->reconstruct(labco->data + datalen, cp.strength); @@ -1227,6 +1238,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const } + void ImProcFunctions::Aver(float * RESTRICT DataList, int datalen, float &averagePlus, float &averageNeg, float &max, float &min) { @@ -1333,6 +1345,56 @@ void ImProcFunctions::Evaluate2(const wavelet_decomposition &WaveletCoeffs_L, } } + +void ImProcFunctions::calceffect(int level, float *mean, float *sigma, float *mea, float effect, float offs) +{ + float rap = 0.f; + float sig = 1.f; + if(effect < 1.f) { + sig = effect; + } + + if(effect <= 1.f) { + rap = offs * mean[level] - sig * sigma[level]; + } + + if (rap > 0.f) { + mea[0] = rap; + } else { + mea[0] = mean[level] / 6.f; + } + + rap = 0.f; + if(effect <= 1.f) { + rap = offs * mean[level] - 0.5f * sig * sigma[level]; + } + + if (rap > 0.f) { + mea[1] = rap; + } else { + mea[1] = mean[level] / 4.f; + } + + rap = 0.f; + if(effect <= 1.f) { + rap = offs * mean[level] - 0.2f * sig * sigma[level]; + } + + if (rap > 0.f) { + mea[2] = rap; + } else { + mea[2] = mean[level] / 2.f; + } + + mea[3] = offs * mean[level]; // 50% data + mea[4] = offs * mean[level] + effect * sigma[level] / 2.f; + mea[5] = offs * mean[level] + effect * sigma[level]; //66% + mea[6] = offs * mean[level] + effect * 1.2f * sigma[level]; + mea[7] = offs * mean[level] + effect * 1.5f * sigma[level]; // + mea[8] = offs * mean[level] + effect * 2.f * sigma[level]; //95% + mea[9] = offs * mean[level] + effect * 2.5f * sigma[level]; //99% +} + void ImProcFunctions::Eval2(float ** WavCoeffs_L, int level, int W_L, int H_L, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN) { @@ -1953,20 +2015,53 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * ContAllL(koeLi, maxkoeLi, true, maxlvl, labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili); //blur level float klev = 1.f; - if(wavblcurve && wavcurvecomp && cp.blena && cp.bluwav > 0.f) { + if(wavblcurve && wavcurvecomp && cp.blena) { + float mea[10]; + float effect = cp.bluwav; + float beta = 0.f; + float offs = 1.f; + + calceffect(lvl, mean, sigma, mea, effect, offs); float * bef = new float[Wlvl_L * Hlvl_L]; float * aft = new float[Wlvl_L * Hlvl_L]; for (int co = 0; co < Hlvl_L * Wlvl_L; co++) { - bef[co] = WavCoeffs_L[dir][co]; + bef[co] = WavCoeffs_L[dir][co]; + float WavCL = std::fabs(WavCoeffs_L[dir][co]); + + if (WavCL < mea[0]) { + beta = 0.05f; + } else if (WavCL < mea[1]) { + beta = 0.2f; + } else if (WavCL < mea[2]) { + beta = 0.7f; + } else if (WavCL < mea[3]) { + beta = 1.f; //standard + } else if (WavCL < mea[4]) { + beta = 1.f; + } else if (WavCL < mea[5]) { + beta = 0.8f; //+sigma + } else if (WavCL < mea[6]) { + beta = 0.6f; + } else if (WavCL < mea[7]) { + beta = 0.4f; + } else if (WavCL < mea[8]) { + beta = 0.2f; // + 2 sigma + } else if (WavCL < mea[9]) { + beta = 0.1f; + } else { + beta = 0.0f; + } + + } klev = (wavblcurve[lvl * 55.5f]); float lvr = lvl; if(lvr == 0) { lvr = 1; } - klev *= cp.bluwav * lvr * 10.f / skip; + klev *= beta * lvr * 100.f / skip; boxblur(bef, aft, klev, Wlvl_L, Hlvl_L, false); for (int co = 0; co < Hlvl_L * Wlvl_L; co++) { @@ -2053,7 +2148,7 @@ void ImProcFunctions::WaveletAandBAllAB(const wavelet_decomposition &WaveletCoef } void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_ab, const Wavblcurve & wavblcurve, const WavOpacityCurveW & waOpacityCurveW, - struct cont_params &cp, const bool useChannelA, int skip) + struct cont_params &cp, const bool useChannelA, int skip, float *meanab, float *sigmaab) { int maxlvl = WaveletCoeffs_ab.maxlevel(); @@ -2219,20 +2314,54 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl); ContAllAB(labco, maxlvl, varhue, varchrom, WavCoeffs_ab, WavCoeffs_ab0, lvl, dir, waOpacityCurveW, cp, Wlvl_ab, Hlvl_ab, useChannelA); - if(wavblcurve && wavcurvecomp && cp.blena && cp.chrwav > 0.f && cp.bluwav > 0.f) { + if(wavblcurve && wavcurvecomp && cp.blena && cp.chrwav > 0.f) { + float mea[10]; + float effect = cp.bluwav; + float beta = 0.f; + float offs = 1.f; + + calceffect(lvl, meanab, sigmaab, mea, effect, offs); + float * bef = new float[Wlvl_ab * Hlvl_ab]; float * aft = new float[Wlvl_ab * Hlvl_ab]; float klev; for (int co = 0; co < Hlvl_ab * Wlvl_ab; co++) { bef[co] = WavCoeffs_ab[dir][co]; + float WavCab = std::fabs(WavCoeffs_ab[dir][co]); + + if (WavCab < mea[0]) { + beta = 0.05f; + } else if (WavCab < mea[1]) { + beta = 0.2f; + } else if (WavCab < mea[2]) { + beta = 0.7f; + } else if (WavCab < mea[3]) { + beta = 1.f; //standard + } else if (WavCab < mea[4]) { + beta = 1.f; + } else if (WavCab < mea[5]) { + beta = 0.8f; //+sigma + } else if (WavCab < mea[6]) { + beta = 0.6f; + } else if (WavCab < mea[7]) { + beta = 0.4f; + } else if (WavCab < mea[8]) { + beta = 0.2f; // + 2 sigma + } else if (WavCab < mea[9]) { + beta = 0.1f; + } else { + beta = 0.0f; + } + + } klev = (wavblcurve[lvl * 55.5f]); float lvr = lvl; if(lvr == 0) { lvr = 1; } - - klev *= cp.bluwav * cp.chrwav * lvr * 20.f / skip; + + klev *= beta * cp.chrwav * lvr * 200.f / skip; boxblur(bef, aft, klev, Wlvl_ab, Hlvl_ab, false); @@ -3003,57 +3132,11 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz const float factorHard = (1.f - skinprotneg / 100.f); const float offs = params->wavelet.offset; const float lowthr = params->wavelet.lowthr; - - //to adjust increase contrast with local contrast - - //for each pixel and each level - float beta; float mea[10]; - float rap = 0.f; - float sig = 1.f; - if(cp.sigm < 1.f) { - sig = cp.sigm; - } + float effect = cp.sigm; + float beta; - if(cp.sigm <= 1.f) { - rap = offs * mean[level] - sig * sigma[level]; - } - - if (rap > 0.f) { - mea[0] = rap; - } else { - mea[0] = mean[level] / 6.f; - } - - rap = 0.f; - if(cp.sigm <= 1.f) { - rap = offs * mean[level] - 0.5f * sig * sigma[level]; - } - - if (rap > 0.f) { - mea[1] = rap; - } else { - mea[1] = mean[level] / 4.f; - } - - rap = 0.f; - if(cp.sigm <= 1.f) { - rap = offs * mean[level] - 0.2f * sig * sigma[level]; - } - - if (rap > 0.f) { - mea[2] = rap; - } else { - mea[2] = mean[level] / 2.f; - } - - mea[3] = offs * mean[level]; // 50% data - mea[4] = offs * mean[level] + cp.sigm * sigma[level] / 2.f; - mea[5] = offs * mean[level] + cp.sigm * sigma[level]; //66% - mea[6] = offs * mean[level] + cp.sigm * 1.2f * sigma[level]; - mea[7] = offs * mean[level] + cp.sigm * 1.5f * sigma[level]; // - mea[8] = offs * mean[level] + cp.sigm * 2.f * sigma[level]; //95% - mea[9] = offs * mean[level] + cp.sigm * 2.5f * sigma[level]; //99% + calceffect(level, mean, sigma, mea, effect, offs); bool useChromAndHue = (skinprot != 0.f || cp.HSmet); float modchro; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index b23143c6c..afedf750c 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -90,7 +90,7 @@ Wavelet::Wavelet() : reschro(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0))), resblur(Gtk::manage(new Adjuster(M("TP_WAVELET_RESBLUR"), 0, 100, 1, 0))), resblurc(Gtk::manage(new Adjuster(M("TP_WAVELET_RESBLURC"), 0, 100, 1, 0))), - bluwav(Gtk::manage(new Adjuster(M("TP_WAVELET_BLUWAV"), 0.0, 100.0, 0.5, 50.))), + bluwav(Gtk::manage(new Adjuster(M("TP_WAVELET_BLUWAV"), 0.05, 2.5, 0.01, 1.))), 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))), scale(Gtk::manage(new Adjuster(M("TP_WAVELET_TMSCALE"), 0.1, 10.0, 0.01, 1.0))),