diff --git a/rtdata/languages/default b/rtdata/languages/default index fe6ddaa7c..e957a5e2a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -802,6 +802,10 @@ HISTORY_MSG_WAVSIGMA;Sigma HISTORY_MSG_WAVSOFTRAD;Soft radius clarity HISTORY_MSG_WAVSOFTRADEND;Soft radius final HISTORY_MSG_WAVUSHAMET;Clarity method +HISTORY_MSG_THRESWAV;Balance threshold +HISTORY_MSG_SOFTWAV;Soft radius +HISTORY_MSG_TMSHAPE;Compression by level +HISTORY_MSG_WAVTM;Tone mapping wavelet HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -2267,6 +2271,7 @@ TP_WAVELET_SKIN_TOOLTIP;At -100 skin-tones are targetted.\nAt 0 all tones are tr TP_WAVELET_SKY;Sky targetting/protection TP_WAVELET_SKY_TOOLTIP;At -100 sky-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 sky-tones are protected while all other tones are affected. TP_WAVELET_SOFTRAD;Soft Radius +TP_WAVELET_SOFWAV;Soft Radius TP_WAVELET_STREN;Strength TP_WAVELET_STRENGTH;Strength TP_WAVELET_SUPE;Extra @@ -2275,17 +2280,20 @@ TP_WAVELET_THRESHOLD;Highlight levels TP_WAVELET_THRESHOLD2;Shadow levels TP_WAVELET_THRESHOLD2_TOOLTIP;Only levels between 9 and 9 minus the value will be affected by the shadow luminance range. Other levels will be fully treated. The highest level possible is limited by the highlight level value (9 minus highlight level value). TP_WAVELET_THRESHOLD_TOOLTIP;Only levels beyond the chosen value will be affected by the highlight luminance range. Other levels will be fully treated. The chosen value here limits the highest possible value of the shadow levels. +TP_WAVELET_THRESWAV;Balance Threshold TP_WAVELET_THRH;Highlights threshold TP_WAVELET_TILESBIG;Big tiles TP_WAVELET_TILESFULL;Full image TP_WAVELET_TILESIZE;Tiling method TP_WAVELET_TILESLIT;Little tiles TP_WAVELET_TILES_TOOLTIP;Processing the full image leads to better quality and is the recommended option, while using tiles is a fall-back solution for users with little RAM. Refer to RawPedia for memory requirements. +TP_WAVELET_TM;Tone mapping wavelet TP_WAVELET_TMEDGS;Edge stopping TP_WAVELET_TMSCALE;Scale TP_WAVELET_TMSTRENGTH;Compression strength TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. -TP_WAVELET_TMTYPE;Compression method +TP_WAVELET_TMEDGS;Edge stopping +TP_WAVELET_TMURVE;(un)Compression by Level TP_WAVELET_TON;Toning TP_WAVELET_USH;None TP_WAVELET_USHARP;Clarity method diff --git a/rtengine/curves.cc b/rtengine/curves.cc index a2b5d1d2b..a3e327dbf 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -1209,6 +1209,41 @@ void WavCurve::Set(const std::vector &curvePoints) } } +WavtmCurve::WavtmCurve() {} + +void WavtmCurve::Reset() +{ + luttmCurve.reset(); +} + +void WavtmCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + luttmCurve(501); // raise this value if the quality suffers from this number of samples + + for (int i = 0; i < 501; i++) { + luttmCurve[i] = pCurve.getVal(double(i) / 500.); + } +} + +void WavtmCurve::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(); + } + +} + + + WavOpacityCurveRG::WavOpacityCurveRG() {} diff --git a/rtengine/curves.h b/rtengine/curves.h index c5bb0c18f..380bad9d6 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -627,6 +627,30 @@ public: } }; +class WavtmCurve +{ +private: + LUTf luttmCurve; // 0xffff range + void Set(const Curve &pCurve); +public: + virtual ~WavtmCurve() {}; + WavtmCurve(); + + void Reset(); + // void Set(const std::vector &curvePoints, bool &opautili); + void Set(const std::vector &curvePoints); + float operator[](float index) const + { + return luttmCurve[index]; + } + + operator bool (void) const + { + return luttmCurve; + } +}; + + class WavOpacityCurveRG { private: diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 640d78b0e..c2de5e0c5 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -967,13 +967,14 @@ void Crop::update(int todo) } WavCurve wavCLVCurve; + WavtmCurve wavtmCurve; WavOpacityCurveRG waOpacityCurveRG; WavOpacityCurveBY waOpacityCurveBY; WavOpacityCurveW waOpacityCurveW; WavOpacityCurveWL waOpacityCurveWL; LUTf wavclCurve; - params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); + params.wavelet.getCurves(wavCLVCurve, wavtmCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); LabImage *unshar = nullptr; Glib::ustring provis; LabImage *provradius = nullptr; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 9bef5b502..682b26410 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -867,7 +867,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) if ((params->wavelet.enabled)) { WaveletParams WaveParams = params->wavelet; - WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); + WaveParams.getCurves(wavCLVCurve, wavtmCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); int kall = 0; LabImage *unshar = nullptr; Glib::ustring provis; @@ -885,8 +885,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } if (WaveParams.softrad > 0.f) { + printf("s1\n"); provradius = new LabImage(pW, pH); provradius->CopyFrom(nprevl); + printf("s2\n"); } @@ -922,10 +924,14 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) WaveParams.expnoise = pronois; if (WaveParams.softrad > 0.f) { + printf("s3\n"); + array2D ble(pW, pH); array2D guid(pW, pH); Imagefloat *tmpImage = nullptr; tmpImage = new Imagefloat(pW, pH); + printf("s4\n"); + #ifdef _OPENMP #pragma omp parallel for #endif @@ -948,6 +954,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) tmpImage->b(ir, jr) = Z; ble[ir][jr] = Y / 32768.f; } + printf("s5\n"); + double epsilmax = 0.0001; double epsilmin = 0.00001; double aepsil = (epsilmax - epsilmin) / 90.f; @@ -957,6 +965,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) float blur = 10.f / scale * (0.0001f + 0.8f * WaveParams.softrad); // rtengine::guidedFilter(guid, ble, ble, blur, 0.001, multiTh); rtengine::guidedFilter(guid, ble, ble, blur, epsil, false); + printf("s6\n"); @@ -973,7 +982,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) Color::XYZ2Lab(X, Y, Z, L, a, b); nprevl->L[ir][jr] = L; } + printf("s7\n"); + delete tmpImage; + printf("s8\n"); } @@ -1063,8 +1075,12 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } */ if (WaveParams.softrad > 0.f) { + printf("s9\n"); + delete provradius; provradius = NULL; + printf("s10\n"); + } diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 454294beb..c797986e5 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -139,6 +139,7 @@ protected: NoiseCurve noiseLCurve; NoiseCurve noiseCCurve; WavCurve wavCLVCurve; + WavtmCurve wavtmCurve; WavOpacityCurveRG waOpacityCurveRG; WavOpacityCurveBY waOpacityCurveBY; WavOpacityCurveW waOpacityCurveW; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index e795d9bd9..cf5a693f8 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2164,6 +2164,17 @@ WaveletParams::WaveletParams() : 0.35, 0.35 }, + tmcurve{ + static_cast(FCT_MinMaxCPoints), + 0.0, + 0.75, + 0.35, + 0.35, + 1.0, + 0.75, + 0.35, + 0.35 + }, opacityCurveRG{ static_cast(FCT_MinMaxCPoints), 0.0, @@ -2252,6 +2263,7 @@ WaveletParams::WaveletParams() : c{}, ch{}, expedge(false), + exptm(false), expresid(false), expfinal(false), exptoning(false), @@ -2300,6 +2312,8 @@ WaveletParams::WaveletParams() : thrH(70), radius(40), skinprotect(0.0), + threswav(1.4), + softwav(1.0), hueskin(-5, 25, 170, 120, false), hueskin2(-260, -250, -130, -140, false), hllev(50, 75, 100, 98, false), @@ -2318,6 +2332,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const { return ccwcurve == other.ccwcurve + && tmcurve == other.tmcurve && opacityCurveRG == other.opacityCurveRG && opacityCurveBY == other.opacityCurveBY && opacityCurveW == other.opacityCurveW @@ -2359,6 +2374,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const return true; }() && expedge == other.expedge + && exptm == other.exptm && expresid == other.expresid && expfinal == other.expfinal && expclari == other.expclari @@ -2407,6 +2423,8 @@ bool WaveletParams::operator ==(const WaveletParams& other) const && thrH == other.thrH && radius == other.radius && skinprotect == other.skinprotect + && threswav == other.threswav + && softwav == other.softwav && hueskin == other.hueskin && hueskin2 == other.hueskin2 && hllev == other.hllev @@ -2427,6 +2445,7 @@ bool WaveletParams::operator !=(const WaveletParams& other) const void WaveletParams::getCurves( WavCurve& cCurve, + WavtmCurve& tCurve, WavOpacityCurveRG& opacityCurveLUTRG, WavOpacityCurveBY& opacityCurveLUTBY, WavOpacityCurveW& opacityCurveLUTW, @@ -2434,6 +2453,7 @@ void WaveletParams::getCurves( ) const { cCurve.Set(this->ccwcurve); + tCurve.Set(this->tmcurve); opacityCurveLUTRG.Set(this->opacityCurveRG); opacityCurveLUTBY.Set(this->opacityCurveBY); opacityCurveLUTW.Set(this->opacityCurveW); @@ -3494,6 +3514,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.expcontrast, "Wavelet", "Expcontrast", wavelet.expcontrast, keyFile); saveToKeyfile(!pedited || pedited->wavelet.expchroma, "Wavelet", "Expchroma", wavelet.expchroma, keyFile); saveToKeyfile(!pedited || pedited->wavelet.expedge, "Wavelet", "Expedge", wavelet.expedge, keyFile); + saveToKeyfile(!pedited || pedited->wavelet.exptm, "Wavelet", "Exptm", wavelet.exptm, keyFile); saveToKeyfile(!pedited || pedited->wavelet.expresid, "Wavelet", "Expresid", wavelet.expresid, keyFile); saveToKeyfile(!pedited || pedited->wavelet.expfinal, "Wavelet", "Expfinal", wavelet.expfinal, keyFile); saveToKeyfile(!pedited || pedited->wavelet.exptoning, "Wavelet", "Exptoning", wavelet.exptoning, keyFile); @@ -3541,6 +3562,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.TMmethod, "Wavelet", "TMMethod", wavelet.TMmethod, keyFile); saveToKeyfile(!pedited || pedited->wavelet.chro, "Wavelet", "ChromaLink", wavelet.chro, keyFile); saveToKeyfile(!pedited || pedited->wavelet.ccwcurve, "Wavelet", "ContrastCurve", wavelet.ccwcurve, keyFile); + saveToKeyfile(!pedited || pedited->wavelet.tmcurve, "Wavelet", "TMCurve", wavelet.tmcurve, keyFile); saveToKeyfile(!pedited || pedited->wavelet.pastlev, "Wavelet", "Pastlev", wavelet.pastlev.toVector(), keyFile); saveToKeyfile(!pedited || pedited->wavelet.satlev, "Wavelet", "Satlev", wavelet.satlev.toVector(), keyFile); saveToKeyfile(!pedited || pedited->wavelet.opacityCurveRG, "Wavelet", "OpacityCurveRG", wavelet.opacityCurveRG, keyFile); @@ -3556,6 +3578,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.cbenab, "Wavelet", "CBenab", wavelet.cbenab, keyFile); saveToKeyfile(!pedited || pedited->wavelet.lipst, "Wavelet", "Lipst", wavelet.lipst, keyFile); saveToKeyfile(!pedited || pedited->wavelet.skinprotect, "Wavelet", "Skinprotect", wavelet.skinprotect, keyFile); + saveToKeyfile(!pedited || pedited->wavelet.threswav, "Wavelet", "Threswav", wavelet.threswav, keyFile); + saveToKeyfile(!pedited || pedited->wavelet.softwav, "Wavelet", "Softwav", wavelet.softwav, keyFile); saveToKeyfile(!pedited || pedited->wavelet.hueskin, "Wavelet", "Hueskin", wavelet.hueskin.toVector(), keyFile); saveToKeyfile(!pedited || pedited->wavelet.edgrad, "Wavelet", "Edgrad", wavelet.edgrad, keyFile); saveToKeyfile(!pedited || pedited->wavelet.edgval, "Wavelet", "Edgval", wavelet.edgval, keyFile); @@ -4710,6 +4734,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Wavelet", "ThresholdResidHighLight", pedited, wavelet.thrH, pedited->wavelet.thrH); assignFromKeyfile(keyFile, "Wavelet", "Residualradius", pedited, wavelet.radius, pedited->wavelet.radius); assignFromKeyfile(keyFile, "Wavelet", "ContrastCurve", pedited, wavelet.ccwcurve, pedited->wavelet.ccwcurve); + assignFromKeyfile(keyFile, "Wavelet", "TMCurve", pedited, wavelet.tmcurve, pedited->wavelet.tmcurve); assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveRG", pedited, wavelet.opacityCurveRG, pedited->wavelet.opacityCurveRG); assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveBY", pedited, wavelet.opacityCurveBY, pedited->wavelet.opacityCurveBY); assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveW", pedited, wavelet.opacityCurveW, pedited->wavelet.opacityCurveW); @@ -4851,6 +4876,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } assignFromKeyfile(keyFile, "Wavelet", "Skinprotect", pedited, wavelet.skinprotect, pedited->wavelet.skinprotect); + assignFromKeyfile(keyFile, "Wavelet", "Threswav", pedited, wavelet.threswav, pedited->wavelet.threswav); + assignFromKeyfile(keyFile, "Wavelet", "Softwav", pedited, wavelet.softwav, pedited->wavelet.softwav); assignFromKeyfile(keyFile, "Wavelet", "Expcontrast", pedited, wavelet.expcontrast, pedited->wavelet.expcontrast); assignFromKeyfile(keyFile, "Wavelet", "Expchroma", pedited, wavelet.expchroma, pedited->wavelet.expchroma); @@ -4881,6 +4908,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } assignFromKeyfile(keyFile, "Wavelet", "Expedge", pedited, wavelet.expedge, pedited->wavelet.expedge); + assignFromKeyfile(keyFile, "Wavelet", "Exptm", pedited, wavelet.exptm, pedited->wavelet.exptm); assignFromKeyfile(keyFile, "Wavelet", "Expresid", pedited, wavelet.expresid, pedited->wavelet.expresid); assignFromKeyfile(keyFile, "Wavelet", "Expfinal", pedited, wavelet.expfinal, pedited->wavelet.expfinal); assignFromKeyfile(keyFile, "Wavelet", "Exptoning", pedited, wavelet.exptoning, pedited->wavelet.exptoning); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index aabe1e7ae..9bfdaab13 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -40,6 +40,7 @@ class OpacityCurve; class RetinexgaintransmissionCurve; class RetinextransmissionCurve; class WavCurve; +class WavtmCurve; class WavOpacityCurveBY; class WavOpacityCurveRG; class WavOpacityCurveW; @@ -1185,6 +1186,7 @@ private: struct WaveletParams { std::vector ccwcurve; + std::vector tmcurve; std::vector opacityCurveRG; std::vector opacityCurveBY; std::vector opacityCurveW; @@ -1220,6 +1222,7 @@ struct WaveletParams { int c[9]; int ch[9]; bool expedge; + bool exptm; bool expresid; bool expfinal; bool exptoning; @@ -1269,6 +1272,8 @@ struct WaveletParams { int thrH; int radius; double skinprotect; + double threswav; + double softwav; Threshold hueskin; Threshold hueskin2; Threshold hllev; @@ -1288,6 +1293,7 @@ struct WaveletParams { void getCurves( WavCurve& cCurve, + WavtmCurve& tCurve, WavOpacityCurveRG& opacityCurveLUTRG, WavOpacityCurveBY& opacityCurveLUTBY, diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 6b9d86baf..e519d5a56 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1120,6 +1120,7 @@ private: bool wavcontlutili = false; WaveletParams WaveParams = params.wavelet; WavCurve wavCLVCurve; + WavtmCurve wavtmCurve; WavOpacityCurveRG waOpacityCurveRG; WavOpacityCurveBY waOpacityCurveBY; WavOpacityCurveW waOpacityCurveW; @@ -1143,7 +1144,7 @@ private: provradius->CopyFrom(labView); } - params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); + params.wavelet.getCurves(wavCLVCurve, wavtmCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 48ba4c341..f954a171a 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -541,11 +541,14 @@ void ParamsEdited::set(bool v) wavelet.hllev = v; wavelet.bllev = v; wavelet.edgcont = v; + wavelet.threswav = v; + wavelet.softwav = v; wavelet.level0noise = v; wavelet.level1noise = v; wavelet.level2noise = v; wavelet.level3noise = v; wavelet.ccwcurve = v; + wavelet.tmcurve = v; wavelet.opacityCurveRG = v; wavelet.opacityCurveBY = v; wavelet.opacityCurveW = v; @@ -565,6 +568,7 @@ void ParamsEdited::set(bool v) wavelet.expcontrast = v; wavelet.expchroma = v; wavelet.expedge = v; + wavelet.exptm = v; wavelet.expresid = v; wavelet.exptoning = v; wavelet.expnoise = v; @@ -1136,6 +1140,8 @@ void ParamsEdited::initFrom(const std::vector& wavelet.hllev = wavelet.hllev && p.wavelet.hllev == other.wavelet.hllev; wavelet.bllev = wavelet.bllev && p.wavelet.bllev == other.wavelet.bllev; wavelet.edgcont = wavelet.edgcont && p.wavelet.edgcont == other.wavelet.edgcont; + wavelet.threswav = wavelet.threswav && p.wavelet.threswav == other.wavelet.threswav; + wavelet.softwav = wavelet.softwav && p.wavelet.softwav == other.wavelet.softwav; wavelet.level0noise = wavelet.level0noise && p.wavelet.level0noise == other.wavelet.level0noise; wavelet.level1noise = wavelet.level1noise && p.wavelet.level1noise == other.wavelet.level1noise; wavelet.level2noise = wavelet.level2noise && p.wavelet.level2noise == other.wavelet.level2noise; @@ -1143,6 +1149,7 @@ void ParamsEdited::initFrom(const std::vector& wavelet.pastlev = wavelet.pastlev && p.wavelet.pastlev == other.wavelet.pastlev; wavelet.satlev = wavelet.satlev && p.wavelet.satlev == other.wavelet.satlev; wavelet.ccwcurve = wavelet.ccwcurve && p.wavelet.ccwcurve == other.wavelet.ccwcurve; + wavelet.tmcurve = wavelet.tmcurve && p.wavelet.tmcurve == other.wavelet.tmcurve; wavelet.opacityCurveRG = wavelet.opacityCurveRG && p.wavelet.opacityCurveRG == other.wavelet.opacityCurveRG; wavelet.opacityCurveBY = wavelet.opacityCurveBY && p.wavelet.opacityCurveBY == other.wavelet.opacityCurveBY; wavelet.opacityCurveW = wavelet.opacityCurveW && p.wavelet.opacityCurveW == other.wavelet.opacityCurveW; @@ -1155,6 +1162,7 @@ void ParamsEdited::initFrom(const std::vector& wavelet.expcontrast = wavelet.expcontrast && p.wavelet.expcontrast == other.wavelet.expcontrast; wavelet.expchroma = wavelet.expchroma && p.wavelet.expchroma == other.wavelet.expchroma; wavelet.expedge = wavelet.expedge && p.wavelet.expedge == other.wavelet.expedge; + wavelet.exptm = wavelet.exptm && p.wavelet.exptm == other.wavelet.exptm; wavelet.expresid = wavelet.expresid && p.wavelet.expresid == other.wavelet.expresid; wavelet.expfinal = wavelet.expfinal && p.wavelet.expfinal == other.wavelet.expfinal; wavelet.exptoning = wavelet.exptoning && p.wavelet.exptoning == other.wavelet.exptoning; @@ -3037,6 +3045,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.edgcont = mods.wavelet.edgcont; } + if (wavelet.threswav) { + toEdit.wavelet.threswav = mods.wavelet.threswav; + } + + if (wavelet.softwav) { + toEdit.wavelet.softwav = mods.wavelet.softwav; + } + if (wavelet.level0noise) { toEdit.wavelet.level0noise = mods.wavelet.level0noise; } @@ -3065,6 +3081,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve; } + if (wavelet.tmcurve) { + toEdit.wavelet.tmcurve = mods.wavelet.tmcurve; + } + if (wavelet.opacityCurveRG) { toEdit.wavelet.opacityCurveRG = mods.wavelet.opacityCurveRG; } @@ -3106,6 +3126,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.expedge = mods.wavelet.expedge; } + if (wavelet.exptm) { + toEdit.wavelet.exptm = mods.wavelet.exptm; + } + if (wavelet.expresid) { toEdit.wavelet.expresid = mods.wavelet.expresid; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index d2707ec11..619521c05 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -557,11 +557,14 @@ struct WaveletParamsEdited { bool hllev; bool bllev; bool edgcont; + bool threswav; + bool softwav; bool level0noise; bool level1noise; bool level2noise; bool level3noise; bool ccwcurve; + bool tmcurve; bool opacityCurveBY; bool opacityCurveRG; bool opacityCurveW; @@ -584,6 +587,7 @@ struct WaveletParamsEdited { bool expcontrast; bool expchroma; bool expedge; + bool exptm; bool expresid; bool expfinal; bool exptoning; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 7d9a65f2a..a65e3c789 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -63,6 +63,7 @@ Wavelet::Wavelet() : FoldableToolPanel(this, "wavelet", M("TP_WAVELET_LABEL"), true, true), curveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CONTEDIT"))), CCWcurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CCURVE"))), + curveEditortm(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_TMURVE"))), curveEditorRES(new CurveEditorGroup(options.lastWaveletCurvesDir)), curveEditorGAM(new CurveEditorGroup(options.lastWaveletCurvesDir)), separatorNeutral(Gtk::manage(new Gtk::HSeparator())), @@ -126,6 +127,8 @@ Wavelet::Wavelet() : mergeC(Gtk::manage(new Adjuster(M("TP_WAVELET_MERGEC"), -50, 100, 1, 20))), softrad(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 100., 0.5, 0.))), softradend(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 100., 0.5, 0.))), + threswav(Gtk::manage(new Adjuster(M("TP_WAVELET_THRESWAV"), 0.9, 2., 0.01, 1.4))), + softwav(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFWAV"), -10.0, 1000.0, 0.5, 1.))), Lmethod(Gtk::manage(new MyComboBoxText())), CHmethod(Gtk::manage(new MyComboBoxText())), CHSLmethod(Gtk::manage(new MyComboBoxText())), @@ -159,6 +162,7 @@ Wavelet::Wavelet() : expsettings(Gtk::manage(new MyExpander(false, M("TP_WAVELET_SETTINGS")))), exptoning(Gtk::manage(new MyExpander(true, M("TP_WAVELET_TON")))), expclari(Gtk::manage(new MyExpander(true, M("TP_WAVELET_CLARI")))), + exptm(Gtk::manage(new MyExpander(true, M("TP_WAVELET_TM")))), neutrHBox(Gtk::manage(new Gtk::HBox())), usharpHBox(Gtk::manage(new Gtk::HBox())) { @@ -175,6 +179,10 @@ Wavelet::Wavelet() : EvWavscale = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSCALE"); EvWavradius = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVRADIUS"); EvWavsigma = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSIGMA"); + EvWavenatm = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVTM"); + EvWavthreswav = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_THRESWAV"); + EvWavsoftwav = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_SOFTWAV"); + EvWavtmshape = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_TMSHAPE"); expsettings->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings)); @@ -193,6 +201,9 @@ Wavelet::Wavelet() : expedge->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expedge)); enableEdgeConn = expedge->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Wavelet::enableToggled), expedge)); + exptm->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), exptm)); + enabletmConn = exptm->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Wavelet::enableToggled), exptm)); + expgamut->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expgamut)); expresid->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expresid)); @@ -623,6 +634,31 @@ Wavelet::Wavelet() : edgBox->pack_start(*ctboxES); +//TM Wavelet + ToolParamBlock* const tmBox = Gtk::manage(new ToolParamBlock()); + + curveEditortm->setCurveListener(this); + + tmshape = static_cast(curveEditortm->addCurve(CT_Flat, "", nullptr, false, false)); + + tmshape->setIdentityValue(0.); + tmshape->setResetCurve(FlatCurveType(default_params.tmcurve.at(0)), default_params.tmcurve); + tmshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CC_TOOLTIP")); + + curveEditortm->curveListComplete(); + curveEditortm->show(); + + tmBox->pack_start(*curveEditortm, Gtk::PACK_SHRINK, 4); + + + threswav->setAdjusterListener(this); + tmBox->pack_start(*threswav); + + softwav->setLogScale(10, -10); + softwav->setAdjusterListener(this); + tmBox->pack_start(*softwav); + + // Gamut ToolParamBlock* const conBox = Gtk::manage(new ToolParamBlock()); @@ -939,6 +975,10 @@ Wavelet::Wavelet() : expedge->setLevel(2); pack_start(*expedge); + exptm->add(*tmBox, false); + exptm->setLevel(2); + pack_start(*exptm); + expclari->add(*clariBox, false); expclari->setLevel(2); pack_start(*expclari); @@ -959,6 +999,7 @@ Wavelet::~Wavelet() delete opaCurveEditorG; delete opacityCurveEditorG; + delete curveEditortm; delete CCWcurveEditorG; delete curveEditorRES; delete curveEditorGAM; @@ -1177,6 +1218,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) Lmethod->set_active(selectedLevel == -1 ? 4 : selectedLevel); ccshape->setCurve(pp->wavelet.ccwcurve); + tmshape->setCurve(pp->wavelet.tmcurve); opacityShapeRG->setCurve(pp->wavelet.opacityCurveRG); opacityShapeBY->setCurve(pp->wavelet.opacityCurveBY); opacityShape->setCurve(pp->wavelet.opacityCurveW); @@ -1187,6 +1229,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) expcontrast->setEnabled(pp->wavelet.expcontrast); expchroma->setEnabled(pp->wavelet.expchroma); expedge->setEnabled(pp->wavelet.expedge); + exptm->setEnabled(pp->wavelet.exptm); expresid->setEnabled(pp->wavelet.expresid); expfinal->setEnabled(pp->wavelet.expfinal); exptoning->setEnabled(pp->wavelet.exptoning); @@ -1266,6 +1309,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) pastlev->setValue(pp->wavelet.pastlev); satlev->setValue(pp->wavelet.satlev); edgcont->setValue(pp->wavelet.edgcont); + threswav->setValue(pp->wavelet.threswav); + softwav->setValue(pp->wavelet.softwav); greenlow->setValue(pp->wavelet.greenlow); bluelow->setValue(pp->wavelet.bluelow); @@ -1363,9 +1408,11 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) set_inconsistent(multiImage && !pedited->wavelet.enabled); ccshape->setUnChanged(!pedited->wavelet.ccwcurve); + tmshape->setUnChanged(!pedited->wavelet.tmcurve); expcontrast->set_inconsistent(!pedited->wavelet.expcontrast); expchroma->set_inconsistent(!pedited->wavelet.expchroma); expedge->set_inconsistent(!pedited->wavelet.expedge); + exptm->set_inconsistent(!pedited->wavelet.exptm); expresid->set_inconsistent(!pedited->wavelet.expresid); expfinal->set_inconsistent(!pedited->wavelet.expfinal); expclari->set_inconsistent(!pedited->wavelet.expclari); @@ -1437,6 +1484,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) satlev->setEditedState(pedited->wavelet.satlev ? Edited : UnEdited); strength->setEditedState(pedited->wavelet.strength ? Edited : UnEdited); edgcont->setEditedState(pedited->wavelet.edgcont ? Edited : UnEdited); + threswav->setEditedState(pedited->wavelet.threswav ? Edited : UnEdited); + softwav->setEditedState(pedited->wavelet.softwav ? Edited : UnEdited); level0noise->setEditedState(pedited->wavelet.level0noise ? Edited : UnEdited); level1noise->setEditedState(pedited->wavelet.level1noise ? Edited : UnEdited); level2noise->setEditedState(pedited->wavelet.level2noise ? Edited : UnEdited); @@ -1542,6 +1591,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) void Wavelet::setEditProvider(EditDataProvider *provider) { ccshape->setEditProvider(provider); + tmshape->setEditProvider(provider); opacityShapeRG->setEditProvider(provider); opacityShapeBY->setEditProvider(provider); opacityShape->setEditProvider(provider); @@ -1554,6 +1604,7 @@ void Wavelet::setEditProvider(EditDataProvider *provider) void Wavelet::autoOpenCurve() { ccshape->openIfNonlinear(); + tmshape->openIfNonlinear(); //opacityShapeRG->openIfNonlinear(); //opacityShapeBY->openIfNonlinear(); } @@ -1604,11 +1655,14 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.hllev = hllev->getValue (); pp->wavelet.bllev = bllev->getValue (); pp->wavelet.edgcont = edgcont->getValue (); + pp->wavelet.threswav = threswav->getValue(); + pp->wavelet.softwav = softwav->getValue(); pp->wavelet.level0noise = level0noise->getValue (); pp->wavelet.level1noise = level1noise->getValue (); pp->wavelet.level2noise = level2noise->getValue (); pp->wavelet.level3noise = level3noise->getValue (); pp->wavelet.ccwcurve = ccshape->getCurve(); + pp->wavelet.tmcurve = tmshape->getCurve(); pp->wavelet.opacityCurveRG = opacityShapeRG->getCurve(); pp->wavelet.opacityCurveBY = opacityShapeBY->getCurve(); pp->wavelet.opacityCurveW = opacityShape->getCurve(); @@ -1633,6 +1687,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.expcontrast = expcontrast->getEnabled(); pp->wavelet.expchroma = expchroma->getEnabled(); pp->wavelet.expedge = expedge->getEnabled(); + pp->wavelet.exptm = exptm->getEnabled(); pp->wavelet.expresid = expresid->getEnabled(); pp->wavelet.expfinal = expfinal->getEnabled(); pp->wavelet.exptoning = exptoning->getEnabled(); @@ -1707,7 +1762,10 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.skinprotect = skinprotect->getEditedState(); pedited->wavelet.hllev = hllev->getEditedState(); pedited->wavelet.ccwcurve = !ccshape->isUnChanged(); + pedited->wavelet.tmcurve = !tmshape->isUnChanged(); pedited->wavelet.edgcont = edgcont->getEditedState(); + pedited->wavelet.threswav = threswav->getEditedState(); + pedited->wavelet.softwav = softwav->getEditedState(); pedited->wavelet.level0noise = level0noise->getEditedState(); pedited->wavelet.level1noise = level1noise->getEditedState(); pedited->wavelet.level2noise = level2noise->getEditedState(); @@ -1738,6 +1796,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.expcontrast = !expcontrast->get_inconsistent(); pedited->wavelet.expchroma = !expchroma->get_inconsistent(); pedited->wavelet.expedge = !expedge->get_inconsistent(); + pedited->wavelet.exptm = !exptm->get_inconsistent(); pedited->wavelet.expresid = !expresid->get_inconsistent(); pedited->wavelet.expfinal = !expfinal->get_inconsistent(); pedited->wavelet.exptoning = !exptoning->get_inconsistent(); @@ -1879,6 +1938,8 @@ void Wavelet::curveChanged(CurveEditor* ce) if (listener && getEnabled()) { if (ce == ccshape) { listener->panelChanged(EvWavCCCurve, M("HISTORY_CUSTOMCURVE")); + } else if (ce == tmshape) { + listener->panelChanged(EvWavtmshape, M("HISTORY_CUSTOMCURVE")); } else if (ce == opacityShapeRG) { listener->panelChanged(EvWavColor, M("HISTORY_CUSTOMCURVE")); } else if (ce == opacityShapeBY) { @@ -1945,6 +2006,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit pastlev->setDefault (defParams->wavelet.pastlev); satlev->setDefault (defParams->wavelet.satlev); edgcont->setDefault (defParams->wavelet.edgcont); + threswav->setDefault(defParams->wavelet.threswav); + softwav->setDefault(defParams->wavelet.softwav); level0noise->setDefault (defParams->wavelet.level0noise); level1noise->setDefault (defParams->wavelet.level1noise); level2noise->setDefault (defParams->wavelet.level2noise); @@ -2008,6 +2071,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit pastlev->setDefaultEditedState(pedited->wavelet.pastlev ? Edited : UnEdited); satlev->setDefaultEditedState(pedited->wavelet.satlev ? Edited : UnEdited); edgcont->setDefaultEditedState(pedited->wavelet.edgcont ? Edited : UnEdited); + threswav->setDefaultEditedState(pedited->wavelet.threswav ? Edited : UnEdited); + softwav->setDefaultEditedState(pedited->wavelet.softwav ? Edited : UnEdited); strength->setDefaultEditedState(pedited->wavelet.strength ? Edited : UnEdited); balance->setDefaultEditedState(pedited->wavelet.balance ? Edited : UnEdited); iter->setDefaultEditedState(pedited->wavelet.iter ? Edited : UnEdited); @@ -2057,6 +2122,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit hllev->setDefaultEditedState(Irrelevant); bllev->setDefaultEditedState(Irrelevant); edgcont->setDefaultEditedState(Irrelevant); + threswav->setDefaultEditedState(Irrelevant); + softwav->setDefaultEditedState(Irrelevant); level0noise->setDefaultEditedState(Irrelevant); level1noise->setDefaultEditedState(Irrelevant); level2noise->setDefaultEditedState(Irrelevant); @@ -2550,6 +2617,7 @@ void Wavelet::setBatchMode(bool batchMode) opacityCurveEditorG->setBatchMode(batchMode); opacityCurveEditorW->setBatchMode(batchMode); opacityCurveEditorWL->setBatchMode(batchMode); + curveEditortm->setBatchMode(batchMode); curveEditorRES->setBatchMode(batchMode); curveEditorGAM->setBatchMode(batchMode); sigma->showEditedCB(); @@ -2587,6 +2655,8 @@ void Wavelet::setBatchMode(bool batchMode) pastlev->showEditedCB(); satlev->showEditedCB(); edgcont->showEditedCB(); + threswav->showEditedCB(); + softwav->showEditedCB(); strength->showEditedCB(); balance->showEditedCB(); iter->showEditedCB(); @@ -2749,6 +2819,10 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval) listener->panelChanged(EvWavgreenlow, greenlow->getTextValue()); } else if (a == bluelow) { listener->panelChanged(EvWavbluelow, bluelow->getTextValue()); + } else if (a == threswav) { + listener->panelChanged(EvWavthreswav, threswav->getTextValue()); + } else if (a == softwav) { + listener->panelChanged(EvWavsoftwav, softwav->getTextValue()); } if ((a == correction[0] || a == correction[1] || a == correction[2] || a == correction[3] || a == correction[4] || a == correction[5] || a == correction[6] || a == correction[7] || a == correction[8])) { @@ -3270,6 +3344,7 @@ void Wavelet::foldAllButMe(GdkEventButton* event, MyExpander *expander) exptoning->set_expanded(exptoning == expander); expnoise->set_expanded(expnoise == expander); expedge->set_expanded(expedge == expander); + exptm->set_expanded(exptm == expander); expgamut->set_expanded(expgamut == expander); expresid->set_expanded(expresid == expander); expfinal->set_expanded(expfinal == expander); @@ -3292,6 +3367,8 @@ void Wavelet::enableToggled(MyExpander *expander) event = EvWavenanoise; } else if (expander == expedge) { event = EvWavenaedge; + } else if (expander == exptm) { + event = EvWavenatm; } else if (expander == expresid) { event = EvWavenares; } else if (expander == expfinal) { @@ -3354,6 +3431,7 @@ void Wavelet::writeOptions(std::vector &tpOpen) tpOpen.push_back(exptoning->get_expanded()); tpOpen.push_back(expnoise->get_expanded()); tpOpen.push_back(expedge->get_expanded()); + tpOpen.push_back(exptm->get_expanded()); tpOpen.push_back(expgamut->get_expanded()); tpOpen.push_back(expresid->get_expanded()); tpOpen.push_back(expfinal->get_expanded()); @@ -3369,6 +3447,7 @@ void Wavelet::updateToolState(const std::vector& tpOpen) exptoning->set_expanded(false); expnoise->set_expanded(false); expedge->set_expanded(false); + exptm->set_expanded(false); expgamut->set_expanded(false); expresid->set_expanded(false); expfinal->set_expanded(false); @@ -3376,17 +3455,18 @@ void Wavelet::updateToolState(const std::vector& tpOpen) return; } - if (tpOpen.size() >= 10) { + if (tpOpen.size() >= 11) { expsettings->set_expanded(tpOpen[0]); expcontrast->set_expanded(tpOpen[1]); expchroma->set_expanded(tpOpen[2]); exptoning->set_expanded(tpOpen[3]); expnoise->set_expanded(tpOpen[4]); expedge->set_expanded(tpOpen[5]); - expgamut->set_expanded(tpOpen[6]); - expresid->set_expanded(tpOpen[7]); - expfinal->set_expanded(tpOpen[8]); - expclari->set_expanded(tpOpen.at(9)); + exptm->set_expanded(tpOpen[6]); + expgamut->set_expanded(tpOpen[7]); + expresid->set_expanded(tpOpen[8]); + expfinal->set_expanded(tpOpen[9]); + expclari->set_expanded(tpOpen[10]); } } diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index d3b66657e..356241fa0 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -79,6 +79,10 @@ private: rtengine::ProcEvent EvWavscale; rtengine::ProcEvent EvWavradius; rtengine::ProcEvent EvWavsigma; + rtengine::ProcEvent EvWavenatm; + rtengine::ProcEvent EvWavthreswav; + rtengine::ProcEvent EvWavsoftwav; + rtengine::ProcEvent EvWavtmshape; void foldAllButMe(GdkEventButton* event, MyExpander *expander); @@ -140,6 +144,7 @@ private: CurveEditorGroup* const curveEditorG; CurveEditorGroup* const CCWcurveEditorG; + CurveEditorGroup* const curveEditortm; CurveEditorGroup* const curveEditorRES; CurveEditorGroup* const curveEditorGAM; Gtk::HSeparator* const separatorNeutral; @@ -158,6 +163,7 @@ private: DiagonalCurveEditor* clshape; FlatCurveEditor* ccshape; + FlatCurveEditor* tmshape; Gtk::CheckButton* const median; Gtk::CheckButton* const medianlev; Gtk::CheckButton* const linkedg; @@ -194,6 +200,7 @@ private: Adjuster* const strength; Adjuster* const balance; Adjuster* const iter; + Adjuster* greenlow; Adjuster* bluelow; Adjuster* greenmed; @@ -224,6 +231,8 @@ private: Adjuster* const mergeC; Adjuster* const softrad; Adjuster* const softradend; + Adjuster* const threswav; + Adjuster* const softwav; MyComboBoxText* const Lmethod; sigc::connection Lmethodconn; @@ -275,11 +284,12 @@ private: MyExpander* const expsettings; MyExpander* const exptoning; MyExpander* const expclari; + MyExpander* const exptm; Gtk::HBox* const neutrHBox; Gtk::HBox* const usharpHBox; - sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enableFinalConn, enableclariConn; + sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enabletmConn, enableFinalConn, enableclariConn; sigc::connection enableNoiseConn, enableResidConn, enableToningConn; sigc::connection medianConn, avoidConn, tmrConn, medianlevConn, linkedgConn, lipstConn, cbenabConn, neutralconn, showmaskConn; sigc::connection neutralPressedConn;