diff --git a/rtdata/languages/default b/rtdata/languages/default index dc7e19769..458d17a3f 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -956,7 +956,10 @@ HISTORY_MSG_711;Local - TM mask radius HISTORY_MSG_712;Local - TM mask chroma HISTORY_MSG_713;Local - TM mask gamma HISTORY_MSG_714;Local - TM mask slope - +HISTORY_MSG_716;Local - Local method +HISTORY_MSG_717;Local - Local contrast +HISTORY_MSG_718;Local - Local contrast levels +HISTORY_MSG_719;Local - Local contrast residual HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction @@ -2073,6 +2076,7 @@ TP_LOCALLAB_EXCLUF;Excluding TP_LOCALLAB_EXCLUF_TOOLTIP;Can be used to exclude this part of datas - move Scope to extend color.\n You can apply all settings to this RT-spot. TP_LOCALLAB_LABGRID_VALUES;High(a)=%1 High(b)=%2\nLow(a)=%3 Low(b)=%4 TP_LOCALLAB_LABGRID;Color correction grid +TP_LOCALLAB_LEVELWAV_TOOLTIP;The Level is automatically adapted to the size of the spot and the preview.\nFrom level 8 size max 512 to level 1 size max = 4 TP_LOCALLAB_SATUR;Saturation TP_LOCALLAB_SENSIDEN;Scope TP_LOCALLAB_SENSIEXCLU;Scope @@ -2188,6 +2192,11 @@ TP_LOCALLAB_STYPE;Shape method TP_LOCALLAB_STYPE_TOOLTIP;You can choose between:\nSymmetrical - left handle linked to right, top handle linked to bottom.\nIndependent - all handles are independent. TP_LOCALLAB_SYMSL;Symmetrical (mouse + sliders) TP_LOCALLAB_SYM;Symmetrical (mouse) +TP_LOCALLAB_WAVE;Wavelet +TP_LOCALLAB_LOCCONT;Unsharp Mask +TP_LOCALLAB_WAV;Levels local contrast +TP_LOCALLAB_LEVELWAV;Wavelets Levels +TP_LOCALLAB_RESIDCONT;Residual image contrast TP_LOCALLAB_CURVEEDITOR_TONES_LABEL;Tone curve TP_LOCALLAB_TM_MASK;Use transmission map TP_LOCALLAB_TRANSIT;Transition Gradient diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 81c46bcac..9d10c4c0e 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -2599,6 +2599,49 @@ void LocLHCurve::Set(const std::vector &curvePoints, bool &LHutili) } } +LocwavCurve::LocwavCurve() : sum(0.f) {}; + +void LocwavCurve::Reset() +{ + lutLocwavCurve.reset(); + sum = 0.f; +} + +void LocwavCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutLocwavCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutLocwavCurve[i] = pCurve.getVal(double (i) / 500.); + + if (lutLocwavCurve[i] < 0.02f) { + lutLocwavCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value + } + + sum += lutLocwavCurve[i]; + } + + //lutLocCurve.dump("wav"); +} +void LocwavCurve::Set(const std::vector &curvePoints) +{ + + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } +} + + LocretigainCurve::LocretigainCurve() : sum(0.f) {}; diff --git a/rtengine/curves.h b/rtengine/curves.h index a5ddcfc84..fa8cd079e 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -1229,6 +1229,36 @@ public: } }; + +class LocwavCurve +{ +private: + LUTf lutLocwavCurve; // 0xffff range + void Set(const Curve &pCurve); + +public: + float sum; + + virtual ~LocwavCurve() {}; + LocwavCurve(); + void Reset(); + void Set(const std::vector &curvePoints); + float getSum() const + { + return sum; + } + + float operator[](float index) const + { + return lutLocwavCurve[index]; + } + operator bool (void) const + { + return lutLocwavCurve; + } +}; + + class LocretigainCurverab { private: diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 73ba7d964..5a181618a 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -938,6 +938,7 @@ void Crop::update(int todo) LocCCmasktmCurve locccmastmCurve; LocLLmasktmCurve locllmastmCurve; LocHHmasktmCurve lochhmastmCurve; + LocwavCurve locwavCurve; LocretigainCurverab locRETgainCurverab; locallutili = false; @@ -969,6 +970,7 @@ void Crop::update(int todo) locccmastmCurve.Set(params.locallab.spots.at(sp).CCmasktmcurve, lcmastmutili); locllmastmCurve.Set(params.locallab.spots.at(sp).LLmasktmcurve, llmastmutili); lochhmastmCurve.Set(params.locallab.spots.at(sp).HHmasktmcurve, lhmastmutili); + locwavCurve.Set(params.locallab.spots.at(sp).locwavcurve); locallutili = false; CurveFactory::curveLocal(locallutili, params.locallab.spots.at(sp).llcurve, lllocalcurve2, sca); localcutili = false; @@ -1005,6 +1007,7 @@ void Crop::update(int todo) locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locwavCurve, LHutili, HHutili, cclocalcurve2, localcutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, parent->locallColorMask, parent->locallExpMask, parent->locallSHMask, parent->locallcbMask, parent->locallretiMask, parent->locallsoftMask, parent->localltmMask); } else { parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop, cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, lllocalcurve2,locallutili, @@ -1013,6 +1016,7 @@ void Crop::update(int todo) locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locwavCurve, LHutili, HHutili, cclocalcurve2, localcutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, 0, 0, 0, 0, 0, 0, 0); } lllocalcurve2.clear(); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 9bd043eba..1bda60307 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -927,6 +927,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) locllmastmCurve.Set(params->locallab.spots.at(sp).LLmasktmcurve, llmastmutili); locccmastmCurve.Set(params->locallab.spots.at(sp).CCmasktmcurve, lcmastmutili); lochhmastmCurve.Set(params->locallab.spots.at(sp).HHmasktmcurve, lhmastmutili); + locwavCurve.Set(params->locallab.spots.at(sp).locwavcurve); CurveFactory::curveLocal(locallutili, params->locallab.spots.at(sp).llcurve, lllocalcurve, sca); CurveFactory::curveCCLocal(localcutili, params->locallab.spots.at(sp).cccurve, cclocalcurve, sca); CurveFactory::curveexLocal(localexutili, params->locallab.spots.at(sp).excurve, exlocalcurve, sca); @@ -976,6 +977,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locwavCurve, LHutili, HHutili, cclocalcurve, localcutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, locallColorMask, locallExpMask, locallSHMask, locallcbMask, locallretiMask, locallsoftMask, localltmMask); } else { ipf.Lab_Local(3, sp, (float**)shbuffer, nprevl, nprevl, reserv, 0, 0, pW, pH, scale, locRETgainCurve, lllocalcurve, locallutili, loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, @@ -983,6 +985,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locwavCurve, LHutili, HHutili, cclocalcurve, localcutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, 0, 0, 0, 0, 0, 0, 0); } //recalculate references after diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 12446b85b..120aad1af 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -254,6 +254,7 @@ protected: LocCCmasktmCurve locccmastmCurve; LocLLmasktmCurve locllmastmCurve; LocHHmasktmCurve lochhmastmCurve; + LocwavCurve locwavCurve; bool locallutili; bool localcutili; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 2c6386af0..17eb2642a 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -315,6 +315,7 @@ public: const LocCCmaskcbCurve & locccmascbCurve, bool &lcmascbutili, const LocLLmaskcbCurve & locllmascbCurve, bool &llmascbutili, const LocHHmaskcbCurve & lochhmascbCurve, bool & lhmascbutili, const LocCCmaskretiCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskretiCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskretiCurve & lochhmasretiCurve, bool & lhmasretiutili, const LocCCmasktmCurve & locccmastmCurve, bool &lcmastmutili, const LocLLmasktmCurve & locllmastmCurve, bool &llmastmutili, const LocHHmasktmCurve & lochhmastmCurve, bool & lhmastmutili, + const LocwavCurve & locwavCurve, bool &LHutili, bool &HHutili, LUTf & cclocalcurve, bool & localcutili, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & lightCurveloc, double & huerefblur, double &chromarefblur, double & lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, int llColorMask, int llExpMask, int llSHMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask); void addGaNoise(LabImage *lab, LabImage *dst, const float mean, const float variance, const int sk); void BlurNoise_Localold(int call, const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy); diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 64285fe4d..4c2081cf3 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -272,6 +272,7 @@ struct local_params { int expmet; int softmet; int blurmet; + int locmet; float noiself; float noiself0; float noiself2; @@ -484,6 +485,12 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.expmet = 1; } + if (locallab.spots.at(sp).localcontMethod == "loc") { + lp.locmet = 0; + } else if (locallab.spots.at(sp).localcontMethod == "wav") { + lp.locmet = 1; + } + lp.laplacexp = locallab.spots.at(sp).laplacexp; lp.balanexp = locallab.spots.at(sp).balanexp; lp.linear = locallab.spots.at(sp).linear; @@ -917,6 +924,7 @@ static void calcTransition(const float lox, const float loy, const float ach, co } + void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab) { //be carefull quasi duplicate with branch cat02wb @@ -4897,6 +4905,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o const LocCCmaskcbCurve & locccmascbCurve, bool &lcmascbutili, const LocLLmaskcbCurve & locllmascbCurve, bool &llmascbutili, const LocHHmaskcbCurve & lochhmascbCurve, bool & lhmascbutili, const LocCCmaskretiCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskretiCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskretiCurve & lochhmasretiCurve, bool & lhmasretiutili, const LocCCmasktmCurve & locccmastmCurve, bool &lcmastmutili, const LocLLmasktmCurve & locllmastmCurve, bool &llmastmutili, const LocHHmasktmCurve & lochhmastmCurve, bool & lhmastmutili, + const LocwavCurve & locwavCurve, bool & LHutili, bool & HHutili, LUTf & cclocalcurve, bool & localcutili, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & lightCurveloc, double & huerefblur, double &chromarefblur, double & lumarefblur, double & hueref, double & chromaref, double & lumaref, double & sobelref, int llColorMask, int llExpMask, int llSHMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask) { /* comment on processus deltaE @@ -6997,7 +7006,15 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o //local contrast - if (lp.lcamount > 0.f && call < 3 && lp.lcena) { + bool wavcurve = false; + if (lp.locmet == 1) { + for (int i = 0; i < 500; i++) { + if (locwavCurve[i] != 0.5) { + wavcurve = true; + } + } + } + if ((lp.lcamount > 0.f || wavcurve || params->locallab.spots.at(sp).residcont != 0.f) && call < 3 && lp.lcena) { int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); @@ -7097,45 +7114,235 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } } - LocalContrastParams localContrastParams; - LocallabParams locallabparams; - localContrastParams.enabled = true; - localContrastParams.radius = params->locallab.spots.at(sp).lcradius; - localContrastParams.amount = params->locallab.spots.at(sp).lcamount; - localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; - localContrastParams.lightness = params->locallab.spots.at(sp).lightness; - bool fftwlc = false; + if (lp.locmet == 0) { + LocalContrastParams localContrastParams; + LocallabParams locallabparams; + localContrastParams.enabled = true; + localContrastParams.radius = params->locallab.spots.at(sp).lcradius; + localContrastParams.amount = params->locallab.spots.at(sp).lcamount; + localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; + localContrastParams.lightness = params->locallab.spots.at(sp).lightness; + bool fftwlc = false; - if (!lp.ftwlc) { - ImProcFunctions::localContrast(tmp1.get(), tmp1->L, localContrastParams, fftwlc, sk); - } else { - std::unique_ptr tmpfftw(new LabImage(bfwr, bfhr)); + if (!lp.ftwlc) { + ImProcFunctions::localContrast(tmp1.get(), tmp1->L, localContrastParams, fftwlc, sk); + } else { + std::unique_ptr tmpfftw(new LabImage(bfwr, bfhr)); #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = 0; y < bfhr; y++) { - for (int x = 0; x < bfwr; x++) { - tmpfftw->L[y][x] = tmp1->L[y][x]; - tmpfftw->a[y][x] = tmp1->a[y][x]; - tmpfftw->b[y][x] = tmp1->b[y][x]; + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + tmpfftw->L[y][x] = tmp1->L[y][x]; + tmpfftw->a[y][x] = tmp1->a[y][x]; + tmpfftw->b[y][x] = tmp1->b[y][x]; + } + } + + fftwlc = true; + ImProcFunctions::localContrast(tmpfftw.get(), tmpfftw->L, localContrastParams, fftwlc, sk); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + tmp1->L[y][x] = tmpfftw->L[y][x]; + tmp1->a[y][x] = tmpfftw->a[y][x]; + tmp1->b[y][x] = tmpfftw->b[y][x]; + } + } + + } + } else if (lp.locmet == 1) { //wavelet + int wavelet_level = params->locallab.spots.at(sp).levelwav; + + int minwin = min(bfwr, bfhr); + int maxlevelspot = 8; + // adap maximum level wavelet to size of RT-spot + + if (minwin * sk < 512) { + maxlevelspot = 8; //sampling wavelet 256 + } + + if (minwin * sk < 256) { + maxlevelspot = 7; //sampling 128 + } + + if (minwin * sk < 128) { + maxlevelspot = 6; + } + + if (minwin * sk < 64) { + maxlevelspot = 5; + } + + if (minwin * sk < 32) { + maxlevelspot = 4; + } + + if (minwin * sk < 16) { + maxlevelspot = 3; + } + + if (minwin * sk < 8) { + maxlevelspot = 2; + } + + if (minwin * sk < 4) { + maxlevelspot = 1; + } + + if (minwin * sk < 2) { + maxlevelspot = 0; + } + + wavelet_level = min(wavelet_level, maxlevelspot); + + wavelet_decomposition wdspot(tmp1->data, bfw, bfh, wavelet_level, 1, sk); + + if (wdspot.memoryAllocationFailed) { + return; + } + + const float contrast = params->locallab.spots.at(sp).residcont; + int maxlvl = wdspot.maxlevel(); + + // printf("maxlev=%i \n", maxlvl); + if (contrast != 0) { + int W_L = wdspot.level_W(0); + int H_L = wdspot.level_H(0); + float *wl0 = wdspot.coeff0; + + float maxh = 2.5f; //amplification contrast above mean + float maxl = 2.5f; //reduction contrast under mean + float multL = contrast * (maxl - 1.f) / 100.f + 1.f; + float multH = contrast * (maxh - 1.f) / 100.f + 1.f; + double avedbl = 0.0; // use double precision for large summations + +#ifdef _OPENMP + #pragma omp parallel for reduction(+:avedbl) if (multiThread) +#endif + + for (int i = 0; i < W_L * H_L; i++) { + avedbl += wl0[i]; + } + + float min0 = wl0[0]; + float max0 = min0; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:max0) reduction(min:min0) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < W_L * H_L; ir++) { + min0 = rtengine::min(min0, wl0[ir]); + max0 = rtengine::max(max0, wl0[ir]); + } + + + max0 /= 327.68f; + min0 /= 327.68f; + float ave = avedbl / double(W_L * H_L); + float av = ave / 327.68f; + float ah = (multH - 1.f) / (av - max0); + float bh = 1.f - max0 * ah; + float al = (multL - 1.f) / (av - min0); + float bl = 1.f - min0 * al; + + if (max0 > 0.0) { +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + + for (int i = 0; i < W_L * H_L; i++) { + if (wl0[i] < 32768.f) { + float prov; + + if (wl0[i] > ave) { + float kh = ah * (wl0[i] / 327.68f) + bh; + prov = wl0[i]; + wl0[i] = ave + kh * (wl0[i] - ave); + } else { + float kl = al * (wl0[i] / 327.68f) + bl; + prov = wl0[i]; + wl0[i] = ave - kl * (ave - wl0[i]); + } + + float diflc = wl0[i] - prov; + wl0[i] = prov + diflc; + } + } } } - fftwlc = true; - ImProcFunctions::localContrast(tmpfftw.get(), tmpfftw->L, localContrastParams, fftwlc, sk); + + float mean[10]; + float meanN[10]; + float sigma[10]; + float sigmaN[10]; + float MaxP[10]; + float MaxN[10]; + Evaluate2(wdspot, mean, meanN, sigma, sigmaN, MaxP, MaxN); + // printf("mean=%f sig=%f\n", mean[3], sigma[3]); + + for (int dir = 1; dir < 4; dir++) { + for (int level = 0; level < maxlvl; ++level) { + int W_L = wdspot.level_W(level); + int H_L = wdspot.level_H(level); + float **wl = wdspot.level_coeffs(level); + + if (MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { + float insigma = 0.666f; //SD + float logmax = log(MaxP[level]); //log Max + float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max + float inx = log(insigma); + float iny = log(rapX); + float rap = inx / iny; //koef + float asig = 0.166f / sigma[level]; + float bsig = 0.5f - asig * mean[level]; + float amean = 0.5f / mean[level]; + #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for if (multiThread) #endif - for (int y = 0; y < bfhr; y++) { - for (int x = 0; x < bfwr; x++) { - tmp1->L[y][x] = tmpfftw->L[y][x]; - tmp1->a[y][x] = tmpfftw->a[y][x]; - tmp1->b[y][x] = tmpfftw->b[y][x]; + for (int i = 0; i < W_L * H_L; i++) { + float absciss; + float &val = wl[dir][i]; + + if (std::isnan(val)) { // ALB -- TODO: this can happen in + // wavelet_decomposition, find out + // why + continue; + } + + if (fabsf(val) >= (mean[level] + sigma[level])) { //for max + float valcour = xlogf(fabsf(val)); + float valc = valcour - logmax; + float vald = valc * rap; + absciss = xexpf(vald); + } else if (fabsf(val) >= mean[level]) { + absciss = asig * fabsf(val) + bsig; + } else { + absciss = amean * fabsf(val); + } + + float kc = locwavCurve[absciss * 500.f] - 0.5f; + float reduceeffect = kc <= 0.f ? 1.f : 1.5f; + + float kinterm = 1.f + reduceeffect * kc; + kinterm = kinterm <= 0.f ? 0.01f : kinterm; + + val *= kinterm; + } + } } } + wdspot.reconstruct(tmp1->data, 1.f); + + } float minL = tmp1->L[0][0] - bufgb->L[0][0]; diff --git a/rtengine/procevents.h b/rtengine/procevents.h index c93f11ce7..c294d27f4 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -742,6 +742,10 @@ enum ProcEventCode { Evlocallabgammasktm = 712, Evlocallabslomasktm = 713, EvlocallabshowmasktmMethod = 714, + EvlocallablocalcontMethod = 715, + EvlocallabwavCurve = 716, + Evlocallablevelwav = 717, + Evlocallabresidcont = 718, NUMOFEVENTS }; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 49a153610..80beba688 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2527,8 +2527,12 @@ LocallabParams::LocallabSpot::LocallabSpot() : lcamount(0.0), lcdarkness(1.0), lclightness(1.0), + levelwav(4), + residcont(0.0), sensilc(19), fftwlc(false), + localcontMethod("loc"), + locwavcurve{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}, // Contrast by detail levels expcbdl(false), mult{1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, @@ -2760,8 +2764,12 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && lcamount == other.lcamount && lcdarkness == other.lcdarkness && lclightness == other.lclightness + && levelwav == other.levelwav + && residcont == other.residcont && sensilc == other.sensilc && fftwlc == other.fftwlc + && localcontMethod == other.localcontMethod + && locwavcurve == other.locwavcurve // Constrast by detail levels && expcbdl == other.expcbdl && [this, &other]()->bool { @@ -3971,11 +3979,15 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // Local Contrast saveToKeyfile(!pedited || pedited->locallab.spots.at(i).expcontrast, "Locallab", "Expcontrast_" + std::to_string(i), spot.expcontrast, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lcradius, "Locallab", "Lcradius_" + std::to_string(i), spot.lcradius, keyFile); - saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lcradius, "Locallab", "Lcamount_" + std::to_string(i), spot.lcamount, keyFile); - saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lcradius, "Locallab", "Lcdarkness_" + std::to_string(i), spot.lcdarkness, keyFile); - saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lcradius, "Locallab", "Lclightness_" + std::to_string(i), spot.lclightness, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lcamount, "Locallab", "Lcamount_" + std::to_string(i), spot.lcamount, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lcdarkness, "Locallab", "Lcdarkness_" + std::to_string(i), spot.lcdarkness, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lclightness, "Locallab", "Lclightness_" + std::to_string(i), spot.lclightness, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).levelwav, "Locallab", "Levelwav_" + std::to_string(i), spot.levelwav, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).residcont, "Locallab", "Residcont_" + std::to_string(i), spot.residcont, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensilc, "Locallab", "Sensilc_" + std::to_string(i), spot.sensilc, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fftwlc, "Locallab", "Fftwlc_" + std::to_string(i), spot.fftwlc, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).localcontMethod, "Locallab", "localcontMethod_" + std::to_string(i), spot.localcontMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).locwavcurve, "Locallab", "LocwavCurve_" + std::to_string(i), spot.locwavcurve, keyFile); // Contrast by detail levels saveToKeyfile(!pedited || pedited->locallab.spots.at(i).expcbdl, "Locallab", "Expcbdl_" + std::to_string(i), spot.expcbdl, keyFile); @@ -5310,8 +5322,12 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Lcamount_" + std::to_string(i), pedited, spot.lcamount, spotEdited.lcamount); assignFromKeyfile(keyFile, "Locallab", "Lcdarkness_" + std::to_string(i), pedited, spot.lcdarkness, spotEdited.lcdarkness); assignFromKeyfile(keyFile, "Locallab", "Lclightness_" + std::to_string(i), pedited, spot.lclightness, spotEdited.lclightness); + assignFromKeyfile(keyFile, "Locallab", "Levelwav_" + std::to_string(i), pedited, spot.levelwav, spotEdited.levelwav); + assignFromKeyfile(keyFile, "Locallab", "Residcont_" + std::to_string(i), pedited, spot.residcont, spotEdited.residcont); assignFromKeyfile(keyFile, "Locallab", "Sensilc_" + std::to_string(i), pedited, spot.sensilc, spotEdited.sensilc); assignFromKeyfile(keyFile, "Locallab", "Fftwlc_" + std::to_string(i), pedited, spot.fftwlc, spotEdited.fftwlc); + assignFromKeyfile(keyFile, "Locallab", "localcontMethod_" + std::to_string(i), pedited, spot.localcontMethod, spotEdited.localcontMethod); + assignFromKeyfile(keyFile, "Locallab", "LocwavCurve_" + std::to_string(i), pedited, spot.locwavcurve, spotEdited.locwavcurve); // Contrast by detail levels assignFromKeyfile(keyFile, "Locallab", "Expcbdl_" + std::to_string(i), pedited, spot.expcbdl, spotEdited.expcbdl); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index bd264e453..9bb7d4ece 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1128,8 +1128,12 @@ struct LocallabParams { double lcamount; double lcdarkness; double lclightness; + int levelwav; + double residcont; int sensilc; bool fftwlc; + Glib::ustring localcontMethod; + std::vector locwavcurve; // Contrast by detail levels bool expcbdl; double mult[6]; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 2c328bf36..632f27075 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -741,7 +741,12 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, //Evlocallabchromasktm LUMINANCECURVE, //Evlocallabgammasktm LUMINANCECURVE, //Evlocallabslomasktm - LUMINANCECURVE //EvlocallabshowmasktmMethod + LUMINANCECURVE, //EvlocallabshowmasktmMethod + LUMINANCECURVE, //EvlocallablocalcontMethod + LUMINANCECURVE, //Evlocallabwavcurve + LUMINANCECURVE, //Evlocallablevelwav + LUMINANCECURVE //Evlocallabresidcont + }; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index ea790c79e..304b08f49 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1109,6 +1109,7 @@ private: LocCCmasktmCurve locccmastmCurve; LocLLmasktmCurve locllmastmCurve; LocHHmasktmCurve lochhmastmCurve; + LocwavCurve locwavCurve; LUTf lllocalcurve(65536, 0); LUTf cclocalcurve(65536, 0); LUTf hltonecurveloc(65536, 0); @@ -1204,6 +1205,7 @@ private: locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locwavCurve, LHutili, HHutili, cclocalcurve, localcutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, 0, 0, 0, 0, 0, 0, 0); diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index b88df03fe..1824110a3 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -165,6 +165,9 @@ Locallab::Locallab(): // Retinex LocalcurveEditorgainT(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_TRANSMISSIONGAIN"))), maskretiCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + //Local contrast + LocalcurveEditorwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAV"))), + //CBDL maskcbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), @@ -276,6 +279,8 @@ Locallab::Locallab(): lcamount(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_AMOUNT"), 0, 1.0, 0.01, 0))), lcdarkness(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_DARKNESS"), 0, 3.0, 0.01, 1.0))), lclightness(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_LIGHTNESS"), 0, 3.0, 0.01, 1.0))), + levelwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LEVELWAV"), 3, 8, 1, 4))), + residcont(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDCONT"), -100, 100, 1, 0))), sensilc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIS"), 0, 100, 1, 19))), // Contrast by detail levels chromacbdl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMACBDL"), 0., 1.5, 0.01, 0.))), @@ -357,6 +362,8 @@ Locallab::Locallab(): // Retinex retinexMethod(Gtk::manage(new MyComboBoxText())), showmaskretiMethod(Gtk::manage(new MyComboBoxText())), + //Local contrast + localcontMethod(Gtk::manage(new MyComboBoxText())), //CBDL showmaskcbMethod(Gtk::manage(new MyComboBoxText())), @@ -1434,6 +1441,27 @@ Locallab::Locallab(): if (showtooltip) { fftwlc->set_tooltip_text(M("TP_LOCALLAB_LC_FFTW_TOOLTIP")); } + LocalcurveEditorwav->setCurveListener(this); + + wavshape = static_cast(LocalcurveEditorwav->addCurve(CT_Flat, "", nullptr, false, false)); + wavshape->setIdentityValue(0.); + wavshape->setResetCurve(FlatCurveType(defSpot.locwavcurve.at(0)), defSpot.locwavcurve); + + if (showtooltip) { + wavshape->setTooltip(M("TP_RETINEX_WAV_TOOLTIP")); + } + + LocalcurveEditorwav->curveListComplete(); + + localcontMethod->append(M("TP_LOCALLAB_LOCCONT")); + localcontMethod->append(M("TP_LOCALLAB_WAVE")); + localcontMethod->set_active(0); + + if (showtooltip) { + // localcontMethod->set_tooltip_markup(M("TP_LOCALLAB_LOCMETHOD_TOOLTIP")); + } + + localcontMethodConn = localcontMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::localcontMethodChanged)); lcradius->setAdjusterListener(this); @@ -1442,14 +1470,24 @@ Locallab::Locallab(): lcdarkness->setAdjusterListener(this); lclightness->setAdjusterListener(this); + levelwav->setAdjusterListener(this); + if (showtooltip) { + levelwav->set_tooltip_markup(M("TP_LOCALLAB_LEVELWAV_TOOLTIP")); + } + + residcont->setAdjusterListener(this); sensilc->setAdjusterListener(this); ToolParamBlock* const contrastBox = Gtk::manage(new ToolParamBlock()); + contrastBox->pack_start(*localcontMethod); contrastBox->pack_start(*lcradius); contrastBox->pack_start(*lcamount); contrastBox->pack_start(*lcdarkness); contrastBox->pack_start(*lclightness); + contrastBox->pack_start(*LocalcurveEditorwav, Gtk::PACK_SHRINK, 4); + contrastBox->pack_start(*levelwav); + contrastBox->pack_start(*residcont); contrastBox->pack_start(*sensilc); contrastBox->pack_start(*fftwlc); expcontrast->add(*contrastBox, false); @@ -1705,6 +1743,7 @@ Locallab::~Locallab() delete maskSHCurveEditorG; delete curveEditorGG; delete LocalcurveEditorgainT; + delete LocalcurveEditorwav; delete masktmCurveEditorG; delete maskretiCurveEditorG; delete maskcbCurveEditorG; @@ -2691,8 +2730,18 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pp->locallab.spots.at(pp->locallab.selspot).lcamount = lcamount->getValue(); pp->locallab.spots.at(pp->locallab.selspot).lcdarkness = lcdarkness->getValue(); pp->locallab.spots.at(pp->locallab.selspot).lclightness = lclightness->getValue(); + pp->locallab.spots.at(pp->locallab.selspot).levelwav = levelwav->getIntValue(); + pp->locallab.spots.at(pp->locallab.selspot).residcont = residcont->getValue(); pp->locallab.spots.at(pp->locallab.selspot).sensilc = sensilc->getIntValue(); pp->locallab.spots.at(pp->locallab.selspot).fftwlc = fftwlc->get_active(); + pp->locallab.spots.at(pp->locallab.selspot).locwavcurve = wavshape->getCurve(); + + if (localcontMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(pp->locallab.selspot).localcontMethod = "loc"; + } else if (localcontMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(pp->locallab.selspot).localcontMethod = "wav"; + } + // Contrast by detail levels pp->locallab.spots.at(pp->locallab.selspot).expcbdl = expcbdl->getEnabled(); @@ -2926,8 +2975,12 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pe->locallab.spots.at(pp->locallab.selspot).lcamount = pe->locallab.spots.at(pp->locallab.selspot).lcamount || lcamount->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).lcdarkness = pe->locallab.spots.at(pp->locallab.selspot).lcdarkness || lcdarkness->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).lclightness = pe->locallab.spots.at(pp->locallab.selspot).lclightness || lclightness->getEditedState(); + pe->locallab.spots.at(pp->locallab.selspot).levelwav = pe->locallab.spots.at(pp->locallab.selspot).levelwav || levelwav->getEditedState(); + pe->locallab.spots.at(pp->locallab.selspot).residcont = pe->locallab.spots.at(pp->locallab.selspot).residcont || residcont->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).sensilc = pe->locallab.spots.at(pp->locallab.selspot).sensilc || sensilc->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).fftwlc = pe->locallab.spots.at(pp->locallab.selspot).fftwlc || !fftwlc->get_inconsistent(); + pe->locallab.spots.at(pp->locallab.selspot).localcontMethod = pe->locallab.spots.at(pp->locallab.selspot).localcontMethod || localcontMethod->get_active_text() != M("GENERAL_UNCHANGED"); + pe->locallab.spots.at(pp->locallab.selspot).locwavcurve = pe->locallab.spots.at(pp->locallab.selspot).locwavcurve || !wavshape->isUnChanged(); // Contrast by detail levels pe->locallab.spots.at(pp->locallab.selspot).expcbdl = pe->locallab.spots.at(pp->locallab.selspot).expcbdl || !expcbdl->get_inconsistent(); @@ -3165,8 +3218,11 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pedited->locallab.spots.at(pp->locallab.selspot).lcamount = pedited->locallab.spots.at(pp->locallab.selspot).lcamount || lcamount->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).lcdarkness = pedited->locallab.spots.at(pp->locallab.selspot).lcdarkness || lcdarkness->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).lclightness = pedited->locallab.spots.at(pp->locallab.selspot).lclightness || lclightness->getEditedState(); + pedited->locallab.spots.at(pp->locallab.selspot).levelwav = pedited->locallab.spots.at(pp->locallab.selspot).levelwav || levelwav->getEditedState(); + pedited->locallab.spots.at(pp->locallab.selspot).residcont = pedited->locallab.spots.at(pp->locallab.selspot).residcont || residcont->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).sensilc = pedited->locallab.spots.at(pp->locallab.selspot).sensilc || sensilc->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).fftwlc = pedited->locallab.spots.at(pp->locallab.selspot).fftwlc || !fftwlc->get_inconsistent(); + pedited->locallab.spots.at(pp->locallab.selspot).locwavcurve = pedited->locallab.spots.at(pp->locallab.selspot).locwavcurve || !wavshape->isUnChanged(); // Contrast by detail levels pedited->locallab.spots.at(pp->locallab.selspot).expcbdl = pedited->locallab.spots.at(pp->locallab.selspot).expcbdl || !expcbdl->get_inconsistent(); @@ -3484,8 +3540,49 @@ void Locallab::curveChanged(CurveEditor* ce) } } + + // Local contrast + if (getEnabled() && expcontrast->getEnabled()) { + if (ce == wavshape) { + if (listener) { + listener->panelChanged(EvlocallabwavCurve, M("HISTORY_CUSTOMCURVE")); + } + } + } + } +void Locallab::localcontMethodChanged() +{ + if (localcontMethod->get_active_row_number() == 0) { + levelwav->hide(); + residcont->hide(); + lcradius->show(); + lcamount->show(); + lcdarkness->show(); + lclightness->show(); + LocalcurveEditorwav->hide(); + fftwlc->show(); + } else if (localcontMethod->get_active_row_number() == 1) { + levelwav->show(); + residcont->show(); + lcradius->hide(); + lcamount->hide(); + lcdarkness->hide(); + lclightness->hide(); + LocalcurveEditorwav->show(); + fftwlc->hide(); + } + + // printf("localcontMethodChanged\n"); + if (getEnabled() && expcontrast->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallablocalcontMethod, localcontMethod->get_active_text()); + } + } +} + + void Locallab::retinexMethodChanged() { // printf("retinexMethodChanged\n"); @@ -4504,6 +4601,8 @@ void Locallab::setDefaults(const ProcParams * defParams, const ParamsEdited * pe lcamount->setDefault(defSpot->lcamount); lcdarkness->setDefault(defSpot->lcdarkness); lclightness->setDefault(defSpot->lclightness); + levelwav->setDefault(defSpot->levelwav); + residcont->setDefault(defSpot->residcont); sensilc->setDefault((double)defSpot->sensilc); // Contrast by detail levels @@ -4647,6 +4746,8 @@ void Locallab::setDefaults(const ProcParams * defParams, const ParamsEdited * pe lcamount->setDefaultEditedState(Irrelevant); lcdarkness->setDefaultEditedState(Irrelevant); lclightness->setDefaultEditedState(Irrelevant); + levelwav->setDefaultEditedState(Irrelevant); + residcont->setDefaultEditedState(Irrelevant); sensilc->setDefaultEditedState(Irrelevant); // Contrast by detail levels @@ -4794,6 +4895,8 @@ void Locallab::setDefaults(const ProcParams * defParams, const ParamsEdited * pe lcamount->setDefaultEditedState(defSpotState->lcamount ? Edited : UnEdited); lcdarkness->setDefaultEditedState(defSpotState->lcdarkness ? Edited : UnEdited); lclightness->setDefaultEditedState(defSpotState->lclightness ? Edited : UnEdited); + levelwav->setDefaultEditedState(defSpotState->levelwav ? Edited : UnEdited); + residcont->setDefaultEditedState(defSpotState->residcont ? Edited : UnEdited); sensilc->setDefaultEditedState(defSpotState->sensilc ? Edited : UnEdited); // Contrast by detail levels @@ -5509,6 +5612,18 @@ void Locallab::adjusterChanged(Adjuster * a, double newval) } } + if (a == levelwav) { + if (listener) { + listener->panelChanged(Evlocallablevelwav, levelwav->getTextValue()); + } + } + + if (a == residcont) { + if (listener) { + listener->panelChanged(Evlocallabresidcont, residcont->getTextValue()); + } + } + if (a == sensilc) { if (listener) { listener->panelChanged(Evlocallabsensilc, sensilc->getTextValue()); @@ -5818,6 +5933,8 @@ void Locallab::setBatchMode(bool batchMode) lcamount->showEditedCB(); lcdarkness->showEditedCB(); lclightness->showEditedCB(); + levelwav->showEditedCB(); + residcont->showEditedCB(); sensilc->showEditedCB(); // Contrast by detail levels @@ -5864,6 +5981,9 @@ void Locallab::setBatchMode(bool batchMode) // Retinex retinexMethod->append(M("GENERAL_UNCHANGED")); + //Local contrast + localcontMethod->append(M("GENERAL_UNCHANGED")); + // In batch mode, being able to change mask visibility is useless showmaskcolMethod->hide(); showmaskexpMethod->hide(); @@ -6057,6 +6177,7 @@ void Locallab::enableListener() inversshaConn.block(false); // Local Contrast enablecontrastConn.block(false); + localcontMethodConn.block(false); fftwlcConn.block(false); // Contrast by detail levels enablecbdlConn.block(false); @@ -6122,6 +6243,7 @@ void Locallab::disableListener() inversshaConn.block(true); // Local Contrast enablecontrastConn.block(true); + localcontMethodConn.block(true); fftwlcConn.block(true); // Contrast by detail levels enablecbdlConn.block(true); @@ -6162,11 +6284,9 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con if (pp->locallab.spots.at(index).scalereti == 1) { - // limd->hide(); LocalcurveEditorgainT->hide(); retinexMethod->hide(); } else { - // limd->show(); LocalcurveEditorgainT->show(); retinexMethod->show(); } @@ -6357,8 +6477,16 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con lcamount->setValue(pp->locallab.spots.at(index).lcamount); lcdarkness->setValue(pp->locallab.spots.at(index).lcdarkness); lclightness->setValue(pp->locallab.spots.at(index).lclightness); + levelwav->setValue(pp->locallab.spots.at(index).levelwav); + residcont->setValue(pp->locallab.spots.at(index).residcont); sensilc->setValue(pp->locallab.spots.at(index).sensilc); fftwlc->set_active(pp->locallab.spots.at(index).fftwlc); + if (pp->locallab.spots.at(index).localcontMethod == "loc") { + localcontMethod->set_active(0); + } else if (pp->locallab.spots.at(index).localcontMethod == "wav") { + localcontMethod->set_active(1); + } + wavshape->setCurve(pp->locallab.spots.at(index).locwavcurve); // Contrast by detail levels expcbdl->setEnabled(pp->locallab.spots.at(index).expcbdl); @@ -6633,8 +6761,14 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con lcamount->setEditedState(spotState->lcamount ? Edited : UnEdited); lcdarkness->setEditedState(spotState->lcdarkness ? Edited : UnEdited); lclightness->setEditedState(spotState->lclightness ? Edited : UnEdited); + levelwav->setEditedState(spotState->levelwav ? Edited : UnEdited); + residcont->setEditedState(spotState->residcont ? Edited : UnEdited); sensilc->setEditedState(spotState->sensilc ? Edited : UnEdited); fftwlc->set_inconsistent(multiImage && !spotState->fftwlc); + wavshape->setUnChanged(!spotState->locwavcurve); + if (!spotState->retinexMethod) { + localcontMethod->set_active_text(M("GENERAL_UNCHANGED")); + } // Contrast by detail levels expcbdl->set_inconsistent(!spotState->expcbdl); @@ -6822,6 +6956,26 @@ void Locallab::updateSpecificGUIState() softradiusret->show(); } + if (localcontMethod->get_active_row_number() == 0) { + levelwav->hide(); + residcont->hide(); + lcradius->show(); + lcamount->show(); + lcdarkness->show(); + lclightness->show(); + LocalcurveEditorwav->hide(); + fftwlc->show(); + } else if (localcontMethod->get_active_row_number() == 1) { + levelwav->show(); + residcont->show(); + lcradius->hide(); + lcamount->hide(); + lcdarkness->hide(); + lclightness->hide(); + LocalcurveEditorwav->show(); + fftwlc->hide(); + } + // Update Sharpening GUI according to inverssha button state (to be compliant with inversshaChanged function) sensisha->show(); } diff --git a/rtgui/locallab.h b/rtgui/locallab.h index 4898d718b..bd5cdf8f9 100644 --- a/rtgui/locallab.h +++ b/rtgui/locallab.h @@ -107,6 +107,10 @@ private: FlatCurveEditor* CCmaskretishape; FlatCurveEditor* LLmaskretishape; FlatCurveEditor* HHmaskretishape; + //local contrast + CurveEditorGroup* const LocalcurveEditorwav; + FlatCurveEditor* wavshape; + //Cbdl CurveEditorGroup* const maskcbCurveEditorG; FlatCurveEditor* CCmaskcbshape; @@ -221,6 +225,8 @@ private: Adjuster* const lcamount; Adjuster* const lcdarkness; Adjuster* const lclightness; + Adjuster* const levelwav; + Adjuster* const residcont; Adjuster* const sensilc; // Contrast by detail levels Adjuster* multiplier[6]; @@ -334,6 +340,9 @@ private: sigc::connection retinexMethodConn; MyComboBoxText* const showmaskretiMethod; sigc::connection showmaskretiMethodConn; + //local contrast + MyComboBoxText* const localcontMethod; + sigc::connection localcontMethodConn; //CBDL MyComboBoxText* const showmaskcbMethod; sigc::connection showmaskcbMethodConn; @@ -425,6 +434,8 @@ private: // Retinex void retinexMethodChanged(); void showmaskretiMethodChanged(); + //Local contrast + void localcontMethodChanged(); //CBDL void showmaskcbMethodChanged(); // Other widgets event functions diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index e3f331879..ada34b8ad 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -1121,8 +1121,12 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).lcamount = locallab.spots.at(j).lcamount && pSpot.lcamount == otherSpot.lcamount; locallab.spots.at(j).lcdarkness = locallab.spots.at(j).lcdarkness && pSpot.lcdarkness == otherSpot.lcdarkness; locallab.spots.at(j).lclightness = locallab.spots.at(j).lclightness && pSpot.lclightness == otherSpot.lclightness; + locallab.spots.at(j).levelwav = locallab.spots.at(j).levelwav && pSpot.levelwav == otherSpot.levelwav; + locallab.spots.at(j).residcont = locallab.spots.at(j).residcont && pSpot.residcont == otherSpot.residcont; locallab.spots.at(j).sensilc = locallab.spots.at(j).sensilc && pSpot.sensilc == otherSpot.sensilc; locallab.spots.at(j).fftwlc = locallab.spots.at(j).fftwlc && pSpot.fftwlc == otherSpot.fftwlc; + locallab.spots.at(j).localcontMethod = locallab.spots.at(j).localcontMethod && pSpot.localcontMethod == otherSpot.localcontMethod; + locallab.spots.at(j).locwavcurve = locallab.spots.at(j).locwavcurve && pSpot.locwavcurve == otherSpot.locwavcurve; // Contrast by detail levels locallab.spots.at(j).expcbdl = locallab.spots.at(j).expcbdl && pSpot.expcbdl == otherSpot.expcbdl; @@ -3316,6 +3320,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).lclightness = mods.locallab.spots.at(i).lclightness; } + if (locallab.spots.at(i).levelwav) { + toEdit.locallab.spots.at(i).levelwav = mods.locallab.spots.at(i).levelwav; + } + + if (locallab.spots.at(i).residcont) { + toEdit.locallab.spots.at(i).residcont = mods.locallab.spots.at(i).residcont; + } + if (locallab.spots.at(i).sensilc) { toEdit.locallab.spots.at(i).sensilc = mods.locallab.spots.at(i).sensilc; } @@ -3324,6 +3336,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).fftwlc = mods.locallab.spots.at(i).fftwlc; } + if (locallab.spots.at(i).localcontMethod) { + toEdit.locallab.spots.at(i).localcontMethod = mods.locallab.spots.at(i).localcontMethod; + } + + if (locallab.spots.at(i).locwavcurve) { + toEdit.locallab.spots.at(i).locwavcurve = mods.locallab.spots.at(i).locwavcurve; + } + // Contrast by detail levels if (locallab.spots.at(i).expcbdl) { toEdit.locallab.spots.at(i).expcbdl = mods.locallab.spots.at(i).expcbdl; @@ -4606,8 +4626,11 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : lcamount(v), lcdarkness(v), lclightness(v), + levelwav(v), + residcont(v), sensilc(v), fftwlc(v), + localcontMethod(v), // Contrast by detail levels expcbdl(v), mult{v, v, v, v, v, v}, @@ -4836,8 +4859,13 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) lcamount = v; lcdarkness = v; lclightness = v; + levelwav = v; + residcont = v; sensilc = v; fftwlc = v; + localcontMethod = v; + locwavcurve = v; + locwavcurve = v; // Contrast by detail levels expcbdl = v; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index e5dbfce78..4f9595006 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -544,8 +544,12 @@ public: bool lcamount; bool lcdarkness; bool lclightness; + bool levelwav; + bool residcont; bool sensilc; bool fftwlc; + bool localcontMethod; + bool locwavcurve; // Contrast by detail levels bool expcbdl; bool mult[6];