diff --git a/rtengine/curves.cc b/rtengine/curves.cc index e64a3275d..c9b549896 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -51,19 +51,19 @@ bool sanitizeCurve(std::vector& curve) // 2) Number of curve entries is > 3 and odd // 3) curve[0] == DCT_Parametric and curve size is >= 8 and curve[1] .. curve[3] are ordered ascending and are distinct if (curve.empty()) { - curve.push_back (DCT_Linear); + curve.push_back(DCT_Linear); return true; - } else if(curve.size() == 1 && curve[0] != DCT_Linear) { + } else if (curve.size() == 1 && curve[0] != DCT_Linear) { curve[0] = DCT_Linear; return true; - } else if((curve.size() % 2 == 0 || curve.size() < 5) && curve[0] != DCT_Parametric) { + } else if ((curve.size() % 2 == 0 || curve.size() < 5) && curve[0] != DCT_Parametric) { curve.clear(); - curve.push_back (DCT_Linear); + curve.push_back(DCT_Linear); return true; - } else if(curve[0] == DCT_Parametric) { + } else if (curve[0] == DCT_Parametric) { if (curve.size() < 8) { curve.clear(); - curve.push_back (DCT_Linear); + curve.push_back(DCT_Linear); return true; } else { // curve[1] to curve[3] must be ordered ascending and distinct @@ -77,6 +77,7 @@ bool sanitizeCurve(std::vector& curve) } } } + return false; } @@ -1066,7 +1067,7 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr, const float add = 0.0954f; float maxran = 65536.f; //65536 - // ecomp /= 100.; +// ecomp /= 100.; // check if brightness curve is needed if (br > 0.00001 || br < -0.00001) { @@ -1121,12 +1122,13 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr, // check if contrast curve is needed if (cont > 0.00001 || cont < -0.00001) { - + int k = avg * 32768; avg = lightCurveloc[k]; // printf("avg=%f lumaref=%f\n", avg, lumare/100.f); std::vector contrastcurvePoints; bool lumm = true; + if (lumm) { //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% contrastcurvePoints.resize(9); @@ -1169,11 +1171,11 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr, } - lightCurveloc *= 32767.f; + lightCurveloc *= 32767.f; - for (int i = 32768; i < 32770; i++) { // set last two elements of lut to 32768 and 32769 to allow linear interpolation - lightCurveloc[i] = (float)i; - } + for (int i = 32768; i < 32770; i++) { // set last two elements of lut to 32768 and 32769 to allow linear interpolation + lightCurveloc[i] = (float)i; + } // a: slope of the curve, black: starting point at the x axis @@ -1561,6 +1563,154 @@ void LocretigainCurverab::Set(const std::vector &curvePoints) } } +LocHHmaskSHCurve::LocHHmaskSHCurve() : sum(0.f) {}; + +void LocHHmaskSHCurve::Reset() +{ + lutLocHHmaskSHCurve.reset(); + sum = 0.f; +} + + +void LocHHmaskSHCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutLocHHmaskSHCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutLocHHmaskSHCurve[i] = pCurve.getVal(double (i) / 500.); + + if (lutLocHHmaskSHCurve[i] < 0.02f) { + lutLocHHmaskSHCurve[i] = 0.02f; + } + + sum += lutLocHHmaskSHCurve[i]; + } + + //lutLocHHCurve.dump("wav"); +} + + + +void LocHHmaskSHCurve::Set(const std::vector &curvePoints, bool & lhmasSHutili) +{ + // if (HHutili && !curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve ttcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + ttcurve.setIdentityValue(0.); + lhmasSHutili = true; + Set(ttcurve); + } else { + Reset(); + } +} + + + +LocLLmaskSHCurve::LocLLmaskSHCurve() : sum(0.f) {}; + +void LocLLmaskSHCurve::Reset() +{ + lutLocLLmaskSHCurve.reset(); + sum = 0.f; +} + +void LocLLmaskSHCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutLocLLmaskSHCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutLocLLmaskSHCurve[i] = pCurve.getVal(double (i) / 500.); + + if (lutLocLLmaskSHCurve[i] < 0.02f) { + lutLocLLmaskSHCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value + } + + sum += lutLocLLmaskSHCurve[i]; + } + + //lutLocHHCurve.dump("wav"); +} + + + +void LocLLmaskSHCurve::Set(const std::vector &curvePoints, bool & llmasSHutili) +{ + // if (HHutili && !curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve ttcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + ttcurve.setIdentityValue(0.); + llmasSHutili = true; + Set(ttcurve); + } else { + Reset(); + } +} + + + + +LocCCmaskSHCurve::LocCCmaskSHCurve() : sum(0.f) {}; + +void LocCCmaskSHCurve::Reset() +{ + lutLocCCmaskSHCurve.reset(); + sum = 0.f; +} + +void LocCCmaskSHCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutLocCCmaskSHCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutLocCCmaskSHCurve[i] = pCurve.getVal(double (i) / 500.); + + if (lutLocCCmaskSHCurve[i] < 0.02f) { + lutLocCCmaskSHCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value + } + + sum += lutLocCCmaskSHCurve[i]; + } + + //lutLocHHCurve.dump("wav"); +} + + + +void LocCCmaskSHCurve::Set(const std::vector &curvePoints, bool & lcmasSHutili) +{ + // if (HHutili && !curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve ttcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + ttcurve.setIdentityValue(0.); + lcmasSHutili = true; + Set(ttcurve); + } else { + Reset(); + } +} + + + + + LocHHmaskexpCurve::LocHHmaskexpCurve() : sum(0.f) {}; void LocHHmaskexpCurve::Reset() @@ -1584,7 +1734,7 @@ void LocHHmaskexpCurve::Set(const Curve &pCurve) lutLocHHmaskexpCurve[i] = pCurve.getVal(double (i) / 500.); if (lutLocHHmaskexpCurve[i] < 0.02f) { - lutLocHHmaskexpCurve[i] = 0.02f; + lutLocHHmaskexpCurve[i] = 0.02f; } sum += lutLocHHmaskexpCurve[i]; @@ -1728,7 +1878,7 @@ void LocHHmaskCurve::Set(const Curve &pCurve) lutLocHHmaskCurve[i] = pCurve.getVal(double (i) / 500.); if (lutLocHHmaskCurve[i] < 0.02f) { - lutLocHHmaskCurve[i] = 0.02f; + lutLocHHmaskCurve[i] = 0.02f; } sum += lutLocHHmaskCurve[i]; @@ -2851,7 +3001,7 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float if (oog_r && oog_g && oog_b) { continue; } - + float r = CLIP(rc[i]); float g = CLIP(gc[i]); float b = CLIP(bc[i]); @@ -2874,17 +3024,35 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float if (ar >= 65535.f && ag >= 65535.f && ab >= 65535.f) { // clip fast path, will also avoid strange colours of clipped highlights //rc[i] = gc[i] = bc[i] = 65535.f; - if (!oog_r) rc[i] = 65535.f; - if (!oog_g) gc[i] = 65535.f; - if (!oog_b) bc[i] = 65535.f; + if (!oog_r) { + rc[i] = 65535.f; + } + + if (!oog_g) { + gc[i] = 65535.f; + } + + if (!oog_b) { + bc[i] = 65535.f; + } + continue; } if (ar <= 0.f && ag <= 0.f && ab <= 0.f) { //rc[i] = gc[i] = bc[i] = 0; - if (!oog_r) rc[i] = 0.f; - if (!oog_g) gc[i] = 0.f; - if (!oog_b) bc[i] = 0.f; + if (!oog_r) { + rc[i] = 0.f; + } + + if (!oog_g) { + gc[i] = 0.f; + } + + if (!oog_b) { + bc[i] = 0.f; + } + continue; } @@ -2924,9 +3092,18 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float g = newg; b = newb; } - if (!oog_r) rc[i] = r; - if (!oog_g) gc[i] = g; - if (!oog_b) bc[i] = b; + + if (!oog_r) { + rc[i] = r; + } + + if (!oog_g) { + gc[i] = g; + } + + if (!oog_b) { + bc[i] = b; + } continue; } @@ -3021,7 +3198,7 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float Ciecam02::jch2xyz_ciecam02float(x, y, z, J, C, h, xw, yw, zw, - c, nc, pow1, nbb, ncb, fl, cz, d, aw ); + c, nc, pow1, nbb, ncb, fl, cz, d, aw); if (!isfinite(x) || !isfinite(y) || !isfinite(z)) { // can happen for colours on the rim of being outside gamut, that worked without chroma scaling but not with. Then we return only the curve's result. @@ -3034,9 +3211,17 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float b = newb; } - if (!oog_r) rc[i] = r; - if (!oog_g) gc[i] = g; - if (!oog_b) bc[i] = b; + if (!oog_r) { + rc[i] = r; + } + + if (!oog_g) { + gc[i] = g; + } + + if (!oog_b) { + bc[i] = b; + } continue; } @@ -3097,9 +3282,18 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float g = newg; b = newb; } - if (!oog_r) rc[i] = r; - if (!oog_g) gc[i] = g; - if (!oog_b) bc[i] = b; + + if (!oog_r) { + rc[i] = r; + } + + if (!oog_g) { + gc[i] = g; + } + + if (!oog_b) { + bc[i] = b; + } } } float PerceptualToneCurve::cf_range[2]; diff --git a/rtengine/curves.h b/rtengine/curves.h index 9b54b9112..3446e982d 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -76,7 +76,8 @@ inline void setUnlessOOG(vfloat &r, vfloat &g, vfloat &b, const vfloat rr, const bool sanitizeCurve(std::vector& curve); -namespace curves { +namespace curves +{ inline void setLutVal(const LUTf &lut, float &val) { @@ -488,11 +489,11 @@ protected: public: DiagonalCurve(const std::vector& points, int ppn = CURVES_MIN_POLY_POINTS); - ~DiagonalCurve () override; + ~DiagonalCurve() override; - double getVal (double t) const override; - void getVal (const std::vector& t, std::vector& res) const override; - bool isIdentity () const override + double getVal(double t) const override; + void getVal(const std::vector& t, std::vector& res) const override; + bool isIdentity() const override { return kind == DCT_Empty; }; @@ -513,12 +514,12 @@ private: public: FlatCurve(const std::vector& points, bool isPeriodic = true, int ppn = CURVES_MIN_POLY_POINTS); - ~FlatCurve () override; + ~FlatCurve() override; - double getVal (double t) const override; - void getVal (const std::vector& t, std::vector& res) const override; + double getVal(double t) const override; + void getVal(const std::vector& t, std::vector& res) const override; bool setIdentityValue(double iVal); - bool isIdentity () const override + bool isIdentity() const override { return kind == FCT_Empty; }; @@ -732,6 +733,95 @@ public: } }; + +class LocHHmaskSHCurve +{ +private: + LUTf lutLocHHmaskSHCurve; // 0xffff range + void Set(const Curve &pCurve); + +public: + float sum; + + virtual ~LocHHmaskSHCurve() {}; + LocHHmaskSHCurve(); + void Reset(); + void Set(const std::vector &curvePoints, bool & lhmasSHutili); + float getSum() const + { + return sum; + } + + float operator[](float index) const + { + return lutLocHHmaskSHCurve[index]; + } + operator bool (void) const + { + return lutLocHHmaskSHCurve; + } +}; + + +class LocCCmaskSHCurve +{ +private: + LUTf lutLocCCmaskSHCurve; // 0xffff range + void Set(const Curve &pCurve); + +public: + float sum; + + virtual ~LocCCmaskSHCurve() {}; + LocCCmaskSHCurve(); + void Reset(); + void Set(const std::vector &curvePoints, bool & lcmasSHutili); + float getSum() const + { + return sum; + } + + float operator[](float index) const + { + return lutLocCCmaskSHCurve[index]; + } + operator bool (void) const + { + return lutLocCCmaskSHCurve; + } +}; + +class LocLLmaskSHCurve +{ +private: + LUTf lutLocLLmaskSHCurve; // 0xffff range + void Set(const Curve &pCurve); + +public: + float sum; + + virtual ~LocLLmaskSHCurve() {}; + LocLLmaskSHCurve(); + void Reset(); + void Set(const std::vector &curvePoints, bool & llmasSHutili); + float getSum() const + { + return sum; + } + + float operator[](float index) const + { + return lutLocLLmaskSHCurve[index]; + } + operator bool (void) const + { + return lutLocLLmaskSHCurve; + } +}; + + + + class LocHHmaskCurve { private: @@ -1286,11 +1376,13 @@ inline void StandardToneCurve::BatchApply( break; #endif } + setUnlessOOG(r[i], g[i], b[i], lutToneCurve[r[i]], lutToneCurve[g[i]], lutToneCurve[b[i]]); i++; } #ifdef __SSE2__ + for (; i + 3 < end; i += 4) { vfloat r_val = LVF(r[i]); vfloat g_val = LVF(g[i]); @@ -1312,7 +1404,7 @@ inline void StandardToneCurve::BatchApply( // Tone curve according to Adobe's reference implementation // values in 0xffff space // inlined to make sure there will be no cache flush when used -inline void AdobeToneCurve::Apply (float& ir, float& ig, float& ib) const +inline void AdobeToneCurve::Apply(float& ir, float& ig, float& ib) const { assert(lutToneCurve); @@ -1396,18 +1488,18 @@ inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const #ifdef __SSE2__ inline vfloat WeightedStdToneCurve::Triangle(vfloat a, vfloat a1, vfloat b) const { - vmask eqmask = vmaskf_eq(b, a); + vmask eqmask = vmaskf_eq(b, a); vfloat a2 = a1 - a; vmask cmask = vmaskf_lt(b, a); vfloat b3 = vself(cmask, b, F2V(65535.f) - b); vfloat a3 = vself(cmask, a, F2V(65535.f) - a); - return vself(eqmask, a1, b + a2 * b3 / a3); + return vself(eqmask, a1, b + a2 * b3 / a3); } #endif // Tone curve modifying the value channel only, preserving hue and saturation // values in 0xffff space -inline void WeightedStdToneCurve::Apply (float& ir, float& ig, float& ib) const +inline void WeightedStdToneCurve::Apply(float& ir, float& ig, float& ib) const { assert(lutToneCurve); @@ -1506,7 +1598,7 @@ inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t en // Tone curve modifying the value channel only, preserving hue and saturation // values in 0xffff space -inline void SatAndValueBlendingToneCurve::Apply (float& ir, float& ig, float& ib) const +inline void SatAndValueBlendingToneCurve::Apply(float& ir, float& ig, float& ib) const { assert(lutToneCurve); diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 945feaf52..1c06cab8d 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -900,6 +900,9 @@ void Crop::update(int todo) bool lhmasexputili = parent->lhmasexputili; bool lcmasexputili = parent->lcmasexputili; bool llmasexputili = parent->llmasexputili; + bool lhmasSHutili = parent->lhmasSHutili; + bool lcmasSHutili = parent->lcmasSHutili; + bool llmasSHutili = parent->llmasSHutili; float avg = parent->avg; LUTu dummy; @@ -913,6 +916,9 @@ void Crop::update(int todo) LocCCmaskexpCurve locccmasexpCurve; LocLLmaskexpCurve locllmasexpCurve; LocHHmaskexpCurve lochhmasexpCurve; + LocCCmaskSHCurve locccmasSHCurve; + LocLLmaskSHCurve locllmasSHCurve; + LocHHmaskSHCurve lochhmasSHCurve; LocretigainCurverab locRETgainCurverab; locallutili = false; @@ -932,6 +938,9 @@ void Crop::update(int todo) locccmasexpCurve.Set(params.locallab.spots.at(sp).CCmaskexpcurve, lcmasexputili); locllmasexpCurve.Set(params.locallab.spots.at(sp).LLmaskexpcurve, llmasexputili); lochhmasexpCurve.Set(params.locallab.spots.at(sp).HHmaskexpcurve, lhmasexputili); + locccmasSHCurve.Set(params.locallab.spots.at(sp).CCmaskSHcurve, lcmasSHutili); + locllmasSHCurve.Set(params.locallab.spots.at(sp).LLmaskSHcurve, llmasSHutili); + lochhmasSHCurve.Set(params.locallab.spots.at(sp).HHmaskSHcurve, lhmasSHutili); locallutili = false; CurveFactory::curveLocal(locallutili, params.locallab.spots.at(sp).llcurve, lllocalcurve2, sca); localcutili = false; @@ -963,10 +972,14 @@ void Crop::update(int todo) // Locallab mask are only shown for selected spot if (sp == parent->params.locallab.selspot) { 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, - loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, LHutili, HHutili, cclocalcurve2, localcutili, localskutili, sklocalcurve2, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, parent->locallColorMask, parent->locallExpMask); + loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + LHutili, HHutili, cclocalcurve2, localcutili, localskutili, sklocalcurve2, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, parent->locallColorMask, parent->locallExpMask, parent->locallSHMask); } 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, - loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, LHutili, HHutili, cclocalcurve2, localcutili, localskutili, sklocalcurve2, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, 0, 0); + loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + LHutili, HHutili, cclocalcurve2, localcutili, localskutili, sklocalcurve2, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, 0, 0, 0); } lllocalcurve2.clear(); cclocalcurve2.clear(); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 7a43bac14..aeb91ce3f 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -126,6 +126,7 @@ ImProcCoordinator::ImProcCoordinator() lastspotdup(false), locallColorMask(0), locallExpMask(0), + locallSHMask(0), avg(0), retistrsav(nullptr) {} @@ -794,6 +795,9 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) lcmasexputili = false; lhmasexputili = false; llmasexputili = false; + lcmasSHutili = false; + lhmasSHutili = false; + llmasSHutili = false; lhmasutili = false; lcmasutili = false; locRETgainCurve.Set(params.locallab.spots.at(sp).localTgaincurve); @@ -805,6 +809,9 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) locllmasexpCurve.Set(params.locallab.spots.at(sp).LLmaskexpcurve, llmasexputili); locccmasexpCurve.Set(params.locallab.spots.at(sp).CCmaskexpcurve, lcmasexputili); lochhmasexpCurve.Set(params.locallab.spots.at(sp).HHmaskexpcurve, lhmasexputili); + locllmasSHCurve.Set(params.locallab.spots.at(sp).LLmaskSHcurve, llmasSHutili); + locccmasSHCurve.Set(params.locallab.spots.at(sp).CCmaskSHcurve, lcmasSHutili); + lochhmasSHCurve.Set(params.locallab.spots.at(sp).HHmaskSHcurve, lhmasSHutili); CurveFactory::curveLocal(locallutili, params.locallab.spots.at(sp).llcurve, lllocalcurve, sca); CurveFactory::curveCCLocal(localcutili, params.locallab.spots.at(sp).cccurve, cclocalcurve, sca); CurveFactory::curveskLocal(localskutili, params.locallab.spots.at(sp).skintonescurve, sklocalcurve, sca); @@ -848,10 +855,12 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) // Locallab mask are only shown for selected spot if (sp == params.locallab.selspot) { 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, - LHutili, HHutili, cclocalcurve, localcutili, localskutili, sklocalcurve, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, locallColorMask, locallExpMask); + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + LHutili, HHutili, cclocalcurve, localcutili, localskutili, sklocalcurve, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, locallColorMask, locallExpMask, locallSHMask); } 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, - LHutili, HHutili, cclocalcurve, localcutili, localskutili, sklocalcurve, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, 0, 0); + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + LHutili, HHutili, cclocalcurve, localcutili, localskutili, sklocalcurve, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, 0, 0, 0); } //recalculate references after if (params.locallab.spots.at(sp).spotMethod == "exc") { diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index daeb70fd6..9059be851 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -241,6 +241,9 @@ protected: LocCCmaskexpCurve locccmasexpCurve; LocLLmaskexpCurve locllmasexpCurve; LocHHmaskexpCurve lochhmasexpCurve; + LocCCmaskSHCurve locccmasSHCurve; + LocLLmaskSHCurve locllmasSHCurve; + LocHHmaskSHCurve lochhmasSHCurve; ProcParams nextParams2; bool locallutili; bool localcutili; @@ -252,6 +255,9 @@ protected: bool lcmasexputili; bool lhmasexputili; bool llmasexputili; + bool lcmasSHutili; + bool lhmasSHutili; + bool llmasSHutili; bool LHutili; bool HHutili; LUTf huerefs; @@ -265,6 +271,7 @@ protected: bool lastspotdup; int locallColorMask; int locallExpMask; + int locallSHMask; float avg; public: @@ -337,10 +344,11 @@ public: updaterThreadStart.unlock(); } - void setLocallabMaskVisibility (int locallColorMask, int locallExpMask) override + void setLocallabMaskVisibility (int locallColorMask, int locallExpMask, int locallSHMask) override { this->locallColorMask = locallColorMask; this->locallExpMask = locallExpMask; + this->locallSHMask = locallSHMask; } void setProgressListener (ProgressListener* pl) override diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index d21fbfada..a97c15722 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -288,7 +288,9 @@ public: void calc_ref(int sp, LabImage* original, LabImage* transformed, int cx, int cy, int oW, int oH, int sk, double &huerefblur, double &chromarefblur, double &lumarefblur, double &huere, double &chromare, double &lumare, double &sobelref, float &avg); void copy_ref(LabImage* spotbuffer, LabImage* original, LabImage* transformed, int cx, int cy, int sk, const struct local_params & lp, double &huerefspot, double &chromarefspot, double &lumarefspot); void paste_ref(LabImage* spotbuffer, LabImage* transformed, int cx, int cy, int sk, const struct local_params & lp); - void Lab_Local(int call, int sp, float** shbuffer, LabImage* original, LabImage* transformed, LabImage* reserved, int cx, int cy, int oW, int oH, int sk, const LocretigainCurve & locRETgainCcurve, LUTf & lllocalcurve, bool & locallutili, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, const LocLLmaskCurve & locllmasCurve, bool & llmasutili, const LocHHmaskCurve & lochhmasCurve, bool & lhmasutili, const LocCCmaskexpCurve & locccmasexpCurve, bool &lcmasexputili, const LocLLmaskexpCurve & locllmasexpCurve, bool &llmasexputili, const LocHHmaskexpCurve & lochhmasexpCurve, bool & lhmasexputili, bool &LHutili, bool &HHutili, LUTf & cclocalcurve, bool & localcutili, bool & localskutili, LUTf & sklocalcurve, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, LUTf & lightCurveloc, double & huerefblur, double &chromarefblur, double & lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, int llColorMask, int llExpMask); + void Lab_Local(int call, int sp, float** shbuffer, LabImage* original, LabImage* transformed, LabImage* reserved, int cx, int cy, int oW, int oH, int sk, const LocretigainCurve & locRETgainCcurve, LUTf & lllocalcurve, bool & locallutili, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, const LocLLmaskCurve & locllmasCurve, bool & llmasutili, const LocHHmaskCurve & lochhmasCurve, bool & lhmasutili, const LocCCmaskexpCurve & locccmasexpCurve, bool &lcmasexputili, const LocLLmaskexpCurve & locllmasexpCurve, bool &llmasexputili, const LocHHmaskexpCurve & lochhmasexpCurve, bool & lhmasexputili, + const LocCCmaskSHCurve & locccmasSHCurve, bool &lcmasSHutili, const LocLLmaskSHCurve & locllmasSHCurve, bool &llmasSHutili, const LocHHmaskSHCurve & lochhmasSHCurve, bool & lhmasSHutili, + bool &LHutili, bool &HHutili, LUTf & cclocalcurve, bool & localcutili, bool & localskutili, LUTf & sklocalcurve, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, LUTf & lightCurveloc, double & huerefblur, double &chromarefblur, double & lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, int llColorMask, int llExpMask, int llSHMask); 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); void InverseBlurNoise_Local(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 1865146aa..e90beb46a 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -147,6 +147,8 @@ struct local_params { float radmacol; float radmaexp; float blendmaexp; + float radmaSH; + float blendmaSH; float struexp; float blurexp; float blurcol; @@ -176,6 +178,7 @@ struct local_params { int gridmet; int showmaskcolmet; int showmaskexpmet; + int showmaskSHmet; int blurmet; float noiself; float noiseldetail; @@ -222,6 +225,7 @@ struct local_params { bool enaColorMask; bool enaExpMask; bool enaColMask; + bool enaSHMask; int highlihs; int shadowhs; int radiushs; @@ -342,7 +346,7 @@ static void SobelCannyLuma(float **sobelL, float **luma, int bfw, int bfh, float -static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locallab, struct local_params& lp, int llColorMask, int llExpMask) +static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locallab, struct local_params& lp, int llColorMask, int llExpMask, int llSHMask) { int w = oW; int h = oH; @@ -403,8 +407,16 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.showmaskcolmet = llColorMask; lp.showmaskexpmet = llExpMask; + lp.showmaskSHmet = llSHMask; +// lp.enaColorMask = locallab.spots.at(sp).enaColorMask && llColorMask == 0 && llExpMask == 0 && llSHMask == 0; // Color & Light mask is deactivated if Exposure mask is visible +// lp.enaExpMask = locallab.spots.at(sp).enaExpMask && llExpMask == 0 && llColorMask == 0 && llSHMask == 0; // Exposure mask is deactivated if Color & Light mask is visible + // lp.enaSHMask = locallab.spots.at(sp).enaSHMask && llSHMask == 0 && llColorMask == 0 && llExpMask == 0; // SH mask is deactivated if Color & Light mask is visible lp.enaColorMask = locallab.spots.at(sp).enaColorMask && llColorMask == 0 && llExpMask == 0; // Color & Light mask is deactivated if Exposure mask is visible lp.enaExpMask = locallab.spots.at(sp).enaExpMask && llExpMask == 0 && llColorMask == 0; // Exposure mask is deactivated if Color & Light mask is visible + lp.enaSHMask = locallab.spots.at(sp).enaSHMask && llSHMask == 0 && llColorMask == 0; // SH mask is deactivated if Color & Light mask is visible + +// lp.enaColorMask = locallab.spots.at(sp).enaColorMask && llColorMask == 0 && llExpMask == 0; // Color & Light mask is deactivated if Exposure mask is visible +// lp.enaExpMask = locallab.spots.at(sp).enaExpMask && llExpMask == 0 && llColorMask == 0; // Exposure mask is deactivated if Color & Light mask is visible if (locallab.spots.at(sp).blurMethod == "norm") { lp.blurmet = 0; @@ -469,6 +481,8 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall float radmaskcolor = ((float) locallab.spots.at(sp).radmaskcol); float blendmaskexpo = ((float) locallab.spots.at(sp).blendmaskexp) / 100.f ; float radmaskexpo = ((float) locallab.spots.at(sp).radmaskexp); + float blendmaskSH = ((float) locallab.spots.at(sp).blendmaskSH) / 100.f ; + float radmaskSH = ((float) locallab.spots.at(sp).radmaskSH); float structexpo = (float) locallab.spots.at(sp).structexp; float blurexpo = (float) locallab.spots.at(sp).blurexpde; float blurcolor = (float) locallab.spots.at(sp).blurcolde; @@ -520,6 +534,9 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.radmaexp = radmaskexpo; lp.struexc = structexclude; lp.blendmaexp = blendmaskexpo; + lp.blendmaSH = blendmaskSH; + lp.radmaSH = radmaskSH; + lp.struexp = structexpo; lp.blurexp = blurexpo; lp.blurcol = blurcolor; @@ -590,7 +607,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.threshol = thresho; lp.chromacb = chromcbdl; - lp.colorena = locallab.spots.at(sp).expcolor && llExpMask == 0; // Color & Light tool is deactivated if Exposure mask is visible + lp.colorena = locallab.spots.at(sp).expcolor && llExpMask == 0;// && llSHMask == 0; // Color & Light tool is deactivated if Exposure mask is visible lp.blurena = locallab.spots.at(sp).expblur; lp.tonemapena = locallab.spots.at(sp).exptonemap; lp.retiena = locallab.spots.at(sp).expreti; @@ -604,7 +621,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.past = chromaPastel; lp.satur = chromaSatur; - lp.exposena = locallab.spots.at(sp).expexpose && llColorMask == 0; // Exposure tool is deactivated if Color & Light mask is visible + lp.exposena = locallab.spots.at(sp).expexpose && llColorMask == 0;// && llSHMask == 0; // Exposure tool is deactivated if Color & Light mask is visible lp.cut_past = cupas; lp.blac = locallab.spots.at(sp).black; lp.shcomp = locallab.spots.at(sp).shcompr; @@ -615,7 +632,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.sensex = local_sensiex; // lp.strucc = local_struc; lp.war = local_warm; - lp.hsena = locallab.spots.at(sp).expshadhigh; + lp.hsena = locallab.spots.at(sp).expshadhigh && llColorMask == 0; //&& llExpMask == 0; lp.highlihs = highhs; lp.shadowhs = shadhs; lp.radiushs = radhs; @@ -2607,6 +2624,36 @@ static void calclight(float lum, float koef, float & lumnew, LUTf & lightCurvel } +static void showmask(const local_params& lp, int begx, int begy, int cx, int cy, int xEn, int yEn, LabImage* bufexporig, LabImage* transformed, LabImage* bufmaskorigSH) +{ +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < transformed->H ; y++) //{ + for (int x = 0; x < transformed->W; x++) { + int lox = cx + x; + int loy = cy + y; + int zone = 0; + float localFactor = 1.f; + const float achm = (float)lp.trans / 100.f; + + if (lp.shapmet == 0) { + calcTransition(lox, loy, achm, lp, zone, localFactor); + } else if (lp.shapmet == 1) { + calcTransitionrect(lox, loy, achm, lp, zone, localFactor); + } + + if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { + if (zone > 0) { + transformed->L[y][x] = 6000.f + CLIPLOC(bufmaskorigSH->L[loy - begy][lox - begx]); + transformed->a[y][x] = bufexporig->a[loy - begy][lox - begx] * (bufmaskorigSH->a[loy - begy][lox - begx]); + transformed->b[y][x] = bufexporig->b[loy - begy][lox - begx] * (bufmaskorigSH->b[loy - begy][lox - begx]); + } + } + } +} + void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueref, const float lumaref, const float chromaref, const local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) { @@ -3266,6 +3313,7 @@ void ImProcFunctions::transit_shapedetect(int senstype, LabImage * bufexporig, L bool expshow = ((lp.showmaskexpmet == 1 || lp.showmaskexpmet == 2) && senstype == 1); bool colshow = ((lp.showmaskcolmet == 1 || lp.showmaskcolmet == 2) && senstype == 0); + bool SHshow = ((lp.showmaskSHmet == 1 || lp.showmaskSHmet == 2) && senstype == 9); LabImage *origblur = nullptr; @@ -3287,8 +3335,9 @@ void ImProcFunctions::transit_shapedetect(int senstype, LabImage * bufexporig, L bool usemask = (lp.showmaskexpmet == 2 || lp.enaExpMask) && senstype == 1; bool usemaskcol = (lp.showmaskcolmet == 2 || lp.enaColorMask) && senstype == 0; + bool usemaskSH = (lp.showmaskSHmet == 2 || lp.enaSHMask) && senstype == 9; - if (usemask || usemaskcol) + if (usemask || usemaskcol || usemaskSH) { origblurmask = new LabImage(GW, GH); @@ -3406,13 +3455,13 @@ void ImProcFunctions::transit_shapedetect(int senstype, LabImage * bufexporig, L if (lp.struexp > 0.f && rs > 0.f && senstype == 1) { rsob = 1.1f * lp.struexp * rs; - } + } if (lp.struco > 0.f && rs > 0.f && senstype == 0) { rsob = 1.1f * lp.struco * rs; } - if (usemask || usemaskcol) { + if (usemask || usemaskcol || usemaskSH) { dE = rsob + sqrt(SQR(refa - origblurmask->a[y][x] / 327.68f) + SQR(refb - origblurmask->b[y][x] / 327.68f) + SQR(lumaref - origblurmask->L[y][x] / 327.68f)); } else { dE = rsob + sqrt(SQR(refa - origblur->a[y][x] / 327.68f) + SQR(refb - origblur->b[y][x] / 327.68f) + SQR(lumaref - rL)); @@ -3573,9 +3622,9 @@ void ImProcFunctions::transit_shapedetect(int senstype, LabImage * bufexporig, L transformed->b[y][x] = CLIPC(chromhr * sincosval.x * facb); difa = transformed->a[y][x] - tempa; difb = transformed->b[y][x] - tempb; - } + } - if (expshow || colshow) { + if (expshow || colshow || SHshow) { transformed->L[y][x] = CLIP(12000.f + diflc); transformed->a[y][x] = CLIPC(difa); transformed->b[y][x] = CLIPC(difb); @@ -3664,7 +3713,7 @@ void ImProcFunctions::transit_shapedetect(int senstype, LabImage * bufexporig, L difb = transformed->b[y][x] - tempb; } - if (expshow || colshow) { + if (expshow || colshow || SHshow) { transformed->L[y][x] = CLIP(12000.f + diflc); transformed->a[y][x] = CLIPC(difa); transformed->b[y][x] = CLIPC(difb); @@ -4161,7 +4210,7 @@ void ImProcFunctions::calc_ref(int sp, LabImage * original, LabImage * transform if (params->locallab.enabled) { //always calculate hueref, chromaref, lumaref before others operations use in normal mode for all modules exceprt denoise struct local_params lp; - calcLocalParams(sp, oW, oH, params->locallab, lp, 0, 0); + calcLocalParams(sp, oW, oH, params->locallab, lp, 0, 0, 0); int begy = lp.yc - lp.lyT; int begx = lp.xc - lp.lxL; int yEn = lp.yc + lp.ly; @@ -4592,7 +4641,8 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * original, LabImage * transformed, LabImage * reserved, int cx, int cy, int oW, int oH, int sk, const LocretigainCurve & locRETgainCcurve, LUTf & lllocalcurve, bool & locallutili, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, const LocLLmaskCurve & locllmasCurve, bool & llmasutili, const LocHHmaskCurve & lochhmasCurve, bool &lhmasutili, const LocCCmaskexpCurve & locccmasexpCurve, bool &lcmasexputili, const LocLLmaskexpCurve & locllmasexpCurve, bool &llmasexputili, const LocHHmaskexpCurve & lochhmasexpCurve, bool & lhmasexputili, - bool & LHutili, bool & HHutili, LUTf & cclocalcurve, bool & localcutili, bool & localskutili, LUTf & sklocalcurve, 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) + const LocCCmaskSHCurve & locccmasSHCurve, bool &lcmasSHutili, const LocLLmaskSHCurve & locllmasSHCurve, bool &llmasSHutili, const LocHHmaskSHCurve & lochhmasSHCurve, bool & lhmasSHutili, + bool & LHutili, bool & HHutili, LUTf & cclocalcurve, bool & localcutili, bool & localskutili, LUTf & sklocalcurve, 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) { //general call of others functions : important return hueref, chromaref, lumaref if (params->locallab.enabled) { @@ -4607,7 +4657,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o int del = 3; // to avoid crash with [loy - begy] and [lox - begx] and bfh bfw // with gtk2 [loy - begy-1] [lox - begx -1 ] and del = 1 struct local_params lp; - calcLocalParams(sp, oW, oH, params->locallab, lp, llColorMask, llExpMask); + calcLocalParams(sp, oW, oH, params->locallab, lp, llColorMask, llExpMask, llSHMask); const float radius = lp.rad / (sk * 1.4f); //0 to 70 ==> see skip int strred = 1;//(lp.strucc - 1); @@ -6473,9 +6523,12 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o //shadow highlight - if ((lp.highlihs > 0.f || lp.shadowhs > 0.f) && call < 3 && lp.hsena) { + if ((lp.highlihs > 0.f || lp.shadowhs > 0.f || lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3) && call < 3 && lp.hsena) { LabImage *bufexporig = nullptr; LabImage *bufexpfin = nullptr; + LabImage *bufmaskorigSH = nullptr; + LabImage *bufmaskblurSH = nullptr; + LabImage *originalmaskSH = nullptr; int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone int bfw = int (lp.lx + lp.lxL) + del; @@ -6485,9 +6538,16 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o if (call <= 3) { //simpleprocess, dcrop, improccoordinator - bufexporig = new LabImage(bfw, bfh); //buffer for data in zone limit bufexpfin = new LabImage(bfw, bfh); //buffer for data in zone limit + + if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3) { + int GWm = transformed->W; + int GHm = transformed->H; + bufmaskorigSH = new LabImage(bfw, bfh); + bufmaskblurSH = new LabImage(bfw, bfh); + originalmaskSH = new LabImage(GWm, GHm); + } #ifdef _OPENMP @@ -6499,6 +6559,15 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o bufexporig->L[ir][jr] = 0.f; bufexporig->a[ir][jr] = 0.f; bufexporig->b[ir][jr] = 0.f; + if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3) { + bufmaskorigSH->L[ir][jr] = 0.f; + bufmaskorigSH->a[ir][jr] = 0.f; + bufmaskorigSH->b[ir][jr] = 0.f; + bufmaskblurSH->L[ir][jr] = 0.f; + bufmaskblurSH->a[ir][jr] = 0.f; + bufmaskblurSH->b[ir][jr] = 0.f; + } + bufexpfin->L[ir][jr] = 0.f; bufexpfin->a[ir][jr] = 0.f; bufexpfin->b[ir][jr] = 0.f; @@ -6512,6 +6581,234 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o int begx = lp.xc - lp.lxL; int yEn = lp.yc + lp.ly; int xEn = lp.xc + lp.lx; + + array2D ble(bfw, bfh); + array2D guid(bfw, bfh); + float meanfab = 0.f; + int nbfab = 0; + + for (int y = 0; y < transformed->H ; y++) //{ + for (int x = 0; x < transformed->W; x++) { + int lox = cx + x; + int loy = cy + y; + + if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { + bufexporig->a[loy - begy][lox - begx] = original->a[y][x]; + bufexporig->b[loy - begy][lox - begx] = original->b[y][x]; + meanfab += fabs(bufexporig->a[loy - begy][lox - begx]); + meanfab += fabs(bufexporig->b[loy - begy][lox - begx]); + nbfab++; + } + } + + meanfab = meanfab / (2.f * nbfab); + float stddv = 0.f; + float som = 0.f; + + for (int y = 0; y < transformed->H ; y++) //{ + for (int x = 0; x < transformed->W; x++) { + int lox = cx + x; + int loy = cy + y; + + if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { + som += SQR(fabs(bufexporig->a[loy - begy][lox - begx]) - meanfab) + SQR(fabs(bufexporig->b[loy - begy][lox - begx]) - meanfab); + } + } + + stddv = sqrt(som / nbfab); + float fab = meanfab + 1.5f * stddv; + + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < transformed->H ; y++) //{ + for (int x = 0; x < transformed->W; x++) { + int lox = cx + x; + int loy = cy + y; + + if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { + if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3) { + bufmaskorigSH->L[loy - begy][lox - begx] = original->L[y][x]; + bufmaskorigSH->a[loy - begy][lox - begx] = original->a[y][x]; + bufmaskorigSH->b[loy - begy][lox - begx] = original->b[y][x]; + bufmaskblurSH->L[loy - begy][lox - begx] = original->L[y][x]; + bufmaskblurSH->a[loy - begy][lox - begx] = original->a[y][x]; + bufmaskblurSH->b[loy - begy][lox - begx] = original->b[y][x]; + } + + bufexporig->L[loy - begy][lox - begx] = original->L[y][x]; + + float valLLexp = 0.f; + float valCC = 0.f; + float valHH = 0.f; + float kmaskLexp = 0; + float kmaskCa = 0; + float kmaskCb = 0; + + float kmaskHL = 0; + float kmaskHa = 0; + float kmaskHb = 0; + + + if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3) { + + if (locllmasSHCurve && llmasSHutili) { + float ligh = (bufexporig->L[loy - begy][lox - begx]) / 32768.f; + valLLexp = (float)(locllmasSHCurve[500.f * ligh]); + valLLexp = LIM01(1.f - valLLexp); + kmaskLexp = 32768.f * valLLexp; + } + + if (locccmasSHCurve && lcmasSHutili) { + float chromask = 0.0001f + sqrt(SQR((bufexporig->a[loy - begy][lox - begx]) / fab) + SQR((bufexporig->b[loy - begy][lox - begx]) / fab)); + float chromaskr = chromask; + valCC = float (locccmasSHCurve[500.f * chromaskr]); + valCC = LIM01(1.f - valCC); + kmaskCa = valCC; + kmaskCb = valCC; + } + + + if (lochhmasSHCurve && lhmasSHutili) { + float huema = xatan2f(bufexporig->b[loy - begy][lox - begx], bufexporig->a[loy - begy][lox - begx]); + float h = Color::huelab_to_huehsv2(huema); + h += 1.f / 6.f; + + if (h > 1.f) { + h -= 1.f; + } + + valHH = float (lochhmasSHCurve[500.f * h]); + valHH = LIM01(1.f - valHH); + kmaskHa = valHH; + kmaskHb = valHH; + kmaskHL = 32768.f * valHH; + } + + bufmaskblurSH->L[loy - begy][lox - begx] = CLIPLOC(kmaskLexp + kmaskHL); + bufmaskblurSH->a[loy - begy][lox - begx] = (kmaskCa + kmaskHa); + bufmaskblurSH->b[loy - begy][lox - begx] = (kmaskCb + kmaskHb); + ble[loy - begy][lox - begx] = bufmaskblurSH->L[loy - begy][lox - begx] / 32768.f; + guid[loy - begy][lox - begx] = bufexporig->L[loy - begy][lox - begx] / 32768.f; + } + + } + } + + if ((lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3) && lp.radmaSH > 0.f) { + + guidedFilter(guid, ble, ble, lp.radmaSH * 10.f / sk, 0.075, multiThread, 4); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < transformed->H ; y++) //{ + for (int x = 0; x < transformed->W; x++) { + int lox = cx + x; + int loy = cy + y; + + if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { + bufmaskblurSH->L[loy - begy][lox - begx] = LIM01(ble[loy - begy][lox - begx]) * 32768.f; + } + } + } + + float radiusb = 1.f / sk; + + if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3) { + + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(bufmaskblurSH->L, bufmaskorigSH->L, bfw, bfh, radiusb); + gaussianBlur(bufmaskblurSH->a, bufmaskorigSH->a, bfw, bfh, 1.f + (0.5f * lp.radmaSH) / sk); + gaussianBlur(bufmaskblurSH->b, bufmaskorigSH->b, bfw, bfh, 1.f + (0.5f * lp.radmaSH) / sk); + } + + delete bufmaskblurSH; + + + if (lp.showmaskSHmet != 3 || lp.enaSHMask) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < transformed->H ; y++) //{ + for (int x = 0; x < transformed->W; x++) { + int lox = cx + x; + int loy = cy + y; + int zone = 0; + + float localFactor = 1.f; + const float achm = (float)lp.trans / 100.f; + + if (lp.shapmet == 0) { + calcTransition(lox, loy, achm, lp, zone, localFactor); + } else if (lp.shapmet == 1) { + calcTransitionrect(lox, loy, achm, lp, zone, localFactor); + } + + if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { + if (zone > 0) { + bufexporig->L[loy - begy][lox - begx] += (lp.blendmaSH * bufmaskorigSH->L[loy - begy][lox - begx]); + bufexporig->a[loy - begy][lox - begx] *= (1.f + lp.blendmaSH * bufmaskorigSH->a[loy - begy][lox - begx]); + bufexporig->b[loy - begy][lox - begx] *= (1.f + lp.blendmaSH * bufmaskorigSH->b[loy - begy][lox - begx]); + + bufexporig->L[loy - begy][lox - begx] = CLIP(bufexporig->L[loy - begy][lox - begx]); + bufexporig->a[loy - begy][lox - begx] = CLIPC(bufexporig->a[loy - begy][lox - begx]); + bufexporig->b[loy - begy][lox - begx] = CLIPC(bufexporig->b[loy - begy][lox - begx]); + + originalmaskSH->L[y][x] = CLIP(bufexporig->L[loy - begy][lox - begx] - bufmaskorigSH->L[loy - begy][lox - begx]); + originalmaskSH->a[y][x] = CLIPC(bufexporig->a[loy - begy][lox - begx] * (1.f - bufmaskorigSH->a[loy - begy][lox - begx])); + originalmaskSH->b[y][x] = CLIPC(bufexporig->b[loy - begy][lox - begx] * (1.f - bufmaskorigSH->b[loy - begy][lox - begx])); + + switch (zone) { + + case 1: { + original->L[y][x] += (lp.blendmaSH * localFactor * bufmaskorigSH->L[loy - begy][lox - begx]); + original->a[y][x] *= (1.f + lp.blendmaSH * localFactor * bufmaskorigSH->a[loy - begy][lox - begx]); + original->b[y][x] *= (1.f + lp.blendmaSH * localFactor * bufmaskorigSH->b[loy - begy][lox - begx]); + original->L[y][x] = CLIP(original->L[y][x]); + original->a[y][x] = CLIPC(original->a[y][x]); + original->b[y][x] = CLIPC(original->b[y][x]); + break; + } + + case 2: { + + original->L[y][x] = bufexporig->L[loy - begy][lox - begx]; + original->a[y][x] = bufexporig->a[loy - begy][lox - begx]; + original->b[y][x] = bufexporig->b[loy - begy][lox - begx]; + + } + + } + } + + + } + } + + delete bufmaskorigSH; + + } else if (lp.showmaskSHmet == 3) { + showmask(lp,begx, begy, cx, cy, xEn, yEn, bufexporig, transformed, bufmaskorigSH); + delete bufmaskorigSH; + delete bufexporig; + + return; + } + } + + + if (lp.showmaskSHmet == 0 || lp.showmaskSHmet == 1 || lp.showmaskSHmet == 2 || lp.enaSHMask) { + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -6559,8 +6856,8 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } } - - transit_shapedetect(9, bufexpfin, nullptr, buflight, bufl_ab, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + } + transit_shapedetect(9, bufexpfin, originalmaskSH, buflight, bufl_ab, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); } @@ -6569,6 +6866,9 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o delete bufexporig; delete bufexpfin; + if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3) { + delete originalmaskSH; + } } } @@ -7506,32 +7806,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o delete bufmaskorigexp; } else if (lp.showmaskexpmet == 3) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < transformed->H ; y++) //{ - for (int x = 0; x < transformed->W; x++) { - int lox = cx + x; - int loy = cy + y; - int zone = 0; - float localFactor = 1.f; - const float achm = (float)lp.trans / 100.f; - - if (lp.shapmet == 0) { - calcTransition(lox, loy, achm, lp, zone, localFactor); - } else if (lp.shapmet == 1) { - calcTransitionrect(lox, loy, achm, lp, zone, localFactor); - } - - if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { - if (zone > 0) { - transformed->L[y][x] = 6000.f + CLIPLOC(bufmaskorigexp->L[loy - begy][lox - begx]); - transformed->a[y][x] = bufexporig->a[loy - begy][lox - begx] * (bufmaskorigexp->a[loy - begy][lox - begx]); - transformed->b[y][x] = bufexporig->b[loy - begy][lox - begx] * (bufmaskorigexp->b[loy - begy][lox - begx]); - } - } - } + showmask(lp,begx, begy, cx, cy, xEn, yEn, bufexporig, transformed, bufmaskorigexp); delete bufmaskorigexp; delete bufexporig; @@ -8137,32 +8412,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o delete bufmaskorigcol; } else if (lp.showmaskcolmet == 3) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < transformed->H ; y++) //{ - for (int x = 0; x < transformed->W; x++) { - int lox = cx + x; - int loy = cy + y; - int zone = 0; - float localFactor = 1.f; - const float achm = (float)lp.trans / 100.f; - - if (lp.shapmet == 0) { - calcTransition(lox, loy, achm, lp, zone, localFactor); - } else if (lp.shapmet == 1) { - calcTransitionrect(lox, loy, achm, lp, zone, localFactor); - } - - if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { - if (zone > 0) { - transformed->L[y][x] = 6000.f + CLIPLOC(bufmaskorigcol->L[loy - begy][lox - begx]); - transformed->a[y][x] = bufcolorig->a[loy - begy][lox - begx] * (bufmaskorigcol->a[loy - begy][lox - begx]); - transformed->b[y][x] = bufcolorig->b[loy - begy][lox - begx] * (bufmaskorigcol->b[loy - begy][lox - begx]); - } - } - } + showmask(lp,begx, begy, cx, cy, xEn, yEn, bufcolorig, transformed, bufmaskorigcol); delete bufmaskorigcol; delete bufcolorig; diff --git a/rtengine/procevents.h b/rtengine/procevents.h index abe87e704..9538b4ec2 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -662,6 +662,13 @@ enum ProcEventCode { Evlocallabsensihs = 632, Evlocallabradmaskcol = 633, Evlocallabradmaskexp = 634, + EvlocallabshowmaskSHMethod = 635, + EvlocallabCCmaskSHshape = 636, + EvlocallabLLmaskSHshape = 637, + EvlocallabHHmaskSHshape = 638, + EvlocallabblendmaskSH = 639, + EvLocallabEnaSHMask = 640, + EvlocallabradmaskSH = 641, NUMOFEVENTS }; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 71a971adb..4e300ffde 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2412,6 +2412,12 @@ LocallabParams::LocallabSpot::LocallabSpot() : s_tonalwidth(30), sh_radius(40), sensihs(15), + enaSHMask(false), + CCmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35 }, + LLmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + blendmaskSH(0), + radmaskSH(10.0), // Vibrance expvibrance(false), saturated(0), @@ -2571,6 +2577,12 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && s_tonalwidth == other.s_tonalwidth && sh_radius == other.sh_radius && sensihs == other.sensihs + && enaSHMask == other.enaSHMask + && CCmaskSHcurve == other.CCmaskSHcurve + && LLmaskSHcurve == other.LLmaskSHcurve + && HHmaskSHcurve == other.HHmaskSHcurve + && blendmaskSH == other.blendmaskSH + && radmaskSH == other.radmaskSH // Vibrance && expvibrance == other.expvibrance && saturated == other.saturated @@ -3687,6 +3699,12 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).s_tonalwidth, "Locallab", "s_tonalwidth_" + std::to_string(i), spot.s_tonalwidth, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sh_radius, "Locallab", "sh_radius_" + std::to_string(i), spot.sh_radius, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensihs, "Locallab", "sensihs_" + std::to_string(i), spot.sensihs, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enaSHMask, "Locallab", "EnaSHMask_" + std::to_string(i), spot.enaSHMask, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).CCmaskSHcurve, "Locallab", "CCmaskSHCurve_" + std::to_string(i), spot.CCmaskSHcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmaskSHcurve, "Locallab", "LLmaskSHCurve_" + std::to_string(i), spot.LLmaskSHcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHmaskSHcurve, "Locallab", "HHmaskSHCurve_" + std::to_string(i), spot.HHmaskSHcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blendmaskSH, "Locallab", "BlendmaskSH_" + std::to_string(i), spot.blendmaskSH, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radmaskSH, "Locallab", "RadmaskSH_" + std::to_string(i), spot.radmaskSH, keyFile); // Vibrance saveToKeyfile(!pedited || pedited->locallab.spots.at(i).expvibrance, "Locallab", "Expvibrance_" + std::to_string(i), spot.expvibrance, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).saturated, "Locallab", "Saturated_" + std::to_string(i), spot.saturated, keyFile); @@ -4931,6 +4949,12 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "s_tonalwidth_" + std::to_string(i), pedited, spot.s_tonalwidth, spotEdited.s_tonalwidth); assignFromKeyfile(keyFile, "Locallab", "sh_radius_" + std::to_string(i), pedited, spot.sh_radius, spotEdited.sh_radius); assignFromKeyfile(keyFile, "Locallab", "sensihs_" + std::to_string(i), pedited, spot.sensihs, spotEdited.sensihs); + assignFromKeyfile(keyFile, "Locallab", "EnaSHMask_" + std::to_string(i), pedited, spot.enaSHMask, spotEdited.enaSHMask); + assignFromKeyfile(keyFile, "Locallab", "CCmaskSHCurve_" + std::to_string(i), pedited, spot.CCmaskSHcurve, spotEdited.CCmaskSHcurve); + assignFromKeyfile(keyFile, "Locallab", "LLmaskSHCurve_" + std::to_string(i), pedited, spot.LLmaskSHcurve, spotEdited.LLmaskSHcurve); + assignFromKeyfile(keyFile, "Locallab", "HHmaskSHCurve_" + std::to_string(i), pedited, spot.HHmaskSHcurve, spotEdited.HHmaskSHcurve); + assignFromKeyfile(keyFile, "Locallab", "BlendmaskSH_" + std::to_string(i), pedited, spot.blendmaskSH, spotEdited.blendmaskSH); + assignFromKeyfile(keyFile, "Locallab", "RadmaskSH_" + std::to_string(i), pedited, spot.radmaskSH, spotEdited.radmaskSH); // Vibrance assignFromKeyfile(keyFile, "Locallab", "Expvibrance_" + std::to_string(i), pedited, spot.expvibrance, spotEdited.expvibrance); assignFromKeyfile(keyFile, "Locallab", "Saturated_" + std::to_string(i), pedited, spot.saturated, spotEdited.saturated); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 9b2006209..758b7f6cb 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -489,7 +489,7 @@ struct ColorToningParams { }; std::vector labregions; int labregionsShowMask; - + ColorToningParams(); bool operator ==(const ColorToningParams& other) const; @@ -986,7 +986,7 @@ struct LocallabParams { std::vector HHmaskcurve; // Exposure bool expexpose; - // int expcomp; + // int expcomp; double expcomp; int hlcompr; int hlcomprthresh; @@ -1013,6 +1013,12 @@ struct LocallabParams { int s_tonalwidth; int sh_radius; int sensihs; + bool enaSHMask; + std::vector CCmaskSHcurve; + std::vector LLmaskSHcurve; + std::vector HHmaskSHcurve; + int blendmaskSH; + double radmaskSH; // Vibrance bool expvibrance; int saturated; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index b2db8accb..e14cfdfb4 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -661,7 +661,15 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, //EvLocallabsh_radius LUMINANCECURVE, //EvLocallabsensihs LUMINANCECURVE, //Evlocallabradmaskcol - LUMINANCECURVE //Evlocallabradmaskexp + LUMINANCECURVE, //Evlocallabradmaskexp + LUMINANCECURVE, //EvlocallabshowmaskSHMethod + LUMINANCECURVE, //EvlocallabCCmaskSHshape + LUMINANCECURVE, //EvlocallabLLmaskSHshape + LUMINANCECURVE, //EvlocallabHHmaskSHshape + LUMINANCECURVE, //EvlocallabblendmaskSH + LUMINANCECURVE, //EvLocallabEnaSHMask + LUMINANCECURVE //EvlocallabradmaskSH + }; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index cded632e1..80124d69d 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -484,7 +484,7 @@ public: virtual void updateUnLock() = 0; - virtual void setLocallabMaskVisibility(int locallColorMask, int locallExpMask) = 0; + virtual void setLocallabMaskVisibility(int locallColorMask, int locallExpMask, int locallSHMask) = 0; /** Creates and returns a Crop instance that acts as a window on the image * @param editDataProvider pointer to the EditDataProvider that communicates with the EditSubscriber diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 782055a24..7915e22ef 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1091,6 +1091,9 @@ private: LocCCmaskexpCurve locccmasexpCurve; LocLLmaskexpCurve locllmasexpCurve; LocHHmaskexpCurve lochhmasexpCurve; + LocCCmaskSHCurve locccmasSHCurve; + LocLLmaskSHCurve locllmasSHCurve; + LocHHmaskSHCurve lochhmasSHCurve; LUTf lllocalcurve(65536, 0); LUTf cclocalcurve(65536, 0); LUTf sklocalcurve(65536, 0); @@ -1123,6 +1126,9 @@ private: bool lcmasexputili = false; bool lhmasexputili = false; bool llmasexputili = false; + bool lcmasSHutili = false; + bool lhmasSHutili = false; + bool llmasSHutili = false; bool lcmasutili = false; bool lhmasutili = false; locRETgainCurve.Set(params.locallab.spots.at(sp).localTgaincurve); @@ -1134,6 +1140,9 @@ private: locccmasexpCurve.Set(params.locallab.spots.at(sp).CCmaskexpcurve, lcmasexputili); locllmasexpCurve.Set(params.locallab.spots.at(sp).LLmaskexpcurve, llmasexputili); lochhmasexpCurve.Set(params.locallab.spots.at(sp).HHmaskexpcurve, lhmasexputili); + locccmasSHCurve.Set(params.locallab.spots.at(sp).CCmaskSHcurve, lcmasSHutili); + locllmasSHCurve.Set(params.locallab.spots.at(sp).LLmaskSHcurve, llmasSHutili); + lochhmasSHCurve.Set(params.locallab.spots.at(sp).HHmaskSHcurve, lhmasSHutili); CurveFactory::curveLocal(locallutili, params.locallab.spots.at(sp).llcurve, lllocalcurve, 1); CurveFactory::curveCCLocal(localcutili, params.locallab.spots.at(sp).cccurve, cclocalcurve, 1); CurveFactory::curveskLocal(localskutili, params.locallab.spots.at(sp).skintonescurve, sklocalcurve, 1); @@ -1161,7 +1170,9 @@ private: // No Locallab mask is shown in exported picture ipf.Lab_Local(2, sp, (float**)shbuffer, labView, labView, reservView, 0, 0, fw, fh, 1, locRETgainCurve, lllocalcurve, locallutili, loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, - LHutili, HHutili, cclocalcurve, localcutili, localskutili, sklocalcurve, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, 0, 0); + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + LHutili, HHutili, cclocalcurve, localcutili, localskutili, sklocalcurve, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, 0, 0, 0); + // Clear local curves lllocalcurve.clear(); diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index 5d61604be..61a7d6d05 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -68,6 +68,8 @@ Locallab::Locallab(): // Exposure curveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_CURVEEDITOR_TONES_LABEL"))), maskexpCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + //Shadows Highlight + maskSHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), // Vibrance curveEditorGG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL"))), // Retinex @@ -104,6 +106,8 @@ Locallab::Locallab(): s_tonalwidth(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_SHTONALW"), 10, 100, 1, 30))), sh_radius(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_RADIUS"), 0, 100, 1, 40))), sensihs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), + blendmaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + radmaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), 0.0, 100.0, 0.1, 10.))), // Vibrance saturated(Gtk::manage(new Adjuster(M("TP_VIBRANCE_SATURATED"), -100., 100., 1., 0.))), pastels(Gtk::manage(new Adjuster(M("TP_VIBRANCE_PASTELS"), -100., 100., 1., 0.))), @@ -167,6 +171,8 @@ Locallab::Locallab(): // Exposure enaExpMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), inversex(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))), + //Shadows Highlight + enaSHMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), // Vibrance protectSkins(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_PROTECTSKINS")))), avoidColorShift(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_AVOIDCOLORSHIFT")))), @@ -187,6 +193,8 @@ Locallab::Locallab(): showmaskcolMethod(Gtk::manage(new MyComboBoxText())), //Exposure showmaskexpMethod(Gtk::manage(new MyComboBoxText())), + //Shadows Highlight + showmaskSHMethod(Gtk::manage(new MyComboBoxText())), // Blur & Noise blurMethod(Gtk::manage(new MyComboBoxText())), // Retinex @@ -203,6 +211,7 @@ Locallab::Locallab(): lumacontrastPlusButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS")))), maskcolFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_SHOW")))), maskexpFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_SHOW")))), + maskSHFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_SHOW")))), gridFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABGRID")))), // Others @@ -516,6 +525,43 @@ Locallab::Locallab(): s_tonalwidth->setAdjusterListener(this); sh_radius->setAdjusterListener(this); sensihs->setAdjusterListener(this); + blendmaskSH->setAdjusterListener(this); + radmaskSH->setAdjusterListener(this); + + enaSHMaskConn = enaSHMask->signal_toggled().connect(sigc::mem_fun(*this, &Locallab::enaSHMaskChanged)); + + showmaskSHMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskSHMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskSHMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskSHMethod->append(M("TP_LOCALLAB_SHOWMASK")); +// showmaskSHMethod->append(M("TP_LOCALLAB_SHOWSTRUC")); + + showmaskSHMethod->set_active(0); + showmaskSHMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + showmaskSHMethodConn = showmaskSHMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::showmaskSHMethodChanged)); + + maskSHCurveEditorG->setCurveListener(this); + + CCmaskSHshape = static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false)); + CCmaskSHshape->setIdentityValue(0.); + CCmaskSHshape->setResetCurve(FlatCurveType(defSpot.CCmaskSHcurve.at(0)), defSpot.CCmaskSHcurve); + CCmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + CCmaskSHshape->setBottomBarColorProvider(this, 7); + + LLmaskSHshape = static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false)); + LLmaskSHshape->setIdentityValue(0.); + LLmaskSHshape->setResetCurve(FlatCurveType(defSpot.LLmaskSHcurve.at(0)), defSpot.LLmaskSHcurve); + LLmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + LLmaskSHshape->setBottomBarBgGradient(mllshape); + + HHmaskSHshape = static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true)); + HHmaskSHshape->setIdentityValue(0.); + HHmaskSHshape->setResetCurve(FlatCurveType(defSpot.HHmaskSHcurve.at(0)), defSpot.HHmaskSHcurve); + HHmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + HHmaskSHshape->setCurveColorProvider(this, 6); + HHmaskSHshape->setBottomBarColorProvider(this, 6); + + maskSHCurveEditorG->curveListComplete(); ToolParamBlock* const shadhighBox = Gtk::manage(new ToolParamBlock()); shadhighBox->pack_start(*highlights); @@ -524,6 +570,16 @@ Locallab::Locallab(): shadhighBox->pack_start(*s_tonalwidth); shadhighBox->pack_start(*sh_radius); shadhighBox->pack_start(*sensihs); + maskSHFrame->set_label_align(0.025, 0.5); + + ToolParamBlock* const maskSHBox = Gtk::manage(new ToolParamBlock()); + maskSHBox->pack_start(*showmaskSHMethod, Gtk::PACK_SHRINK, 4); + maskSHBox->pack_start(*enaSHMask, Gtk::PACK_SHRINK, 0); + maskSHBox->pack_start(*maskSHCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskSHBox->pack_start(*blendmaskSH, Gtk::PACK_SHRINK, 0); + maskSHBox->pack_start(*radmaskSH, Gtk::PACK_SHRINK, 0); + maskSHFrame->add(*maskSHBox); + shadhighBox->pack_start(*maskSHFrame); expshadhigh->add(*shadhighBox); expshadhigh->setLevel(2); @@ -666,7 +722,7 @@ Locallab::Locallab(): retiLabel->set_markup(Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_RETI")) + Glib::ustring("")); retiLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); retiTitleHBox->pack_start(*retiLabel, Gtk::PACK_EXPAND_WIDGET, 0); - RTImage *retiImage = Gtk::manage (new RTImage("one-to-one-small.png")); + RTImage *retiImage = Gtk::manage(new RTImage("one-to-one-small.png")); retiImage->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); retiTitleHBox->pack_end(*retiImage, Gtk::PACK_SHRINK, 0); expreti->setLabel(retiTitleHBox); @@ -725,11 +781,11 @@ Locallab::Locallab(): sharpLabel->set_markup(Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_SHARP")) + Glib::ustring("")); sharpLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); sharpTitleHBox->pack_start(*sharpLabel, Gtk::PACK_EXPAND_WIDGET, 0); - RTImage *sharpImage = Gtk::manage (new RTImage("one-to-one-small.png")); + RTImage *sharpImage = Gtk::manage(new RTImage("one-to-one-small.png")); sharpImage->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); sharpTitleHBox->pack_end(*sharpImage, Gtk::PACK_SHRINK, 0); expsharp->setLabel(sharpTitleHBox); - + expsharp->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Locallab::foldAllButMe), expsharp)); enablesharpConn = expsharp->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Locallab::enableToggled), expsharp)); @@ -795,10 +851,10 @@ Locallab::Locallab(): cbdlLabel->set_markup(Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_CBDL")) + Glib::ustring("")); cbdlLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); cbdlTitleHBox->pack_start(*cbdlLabel, Gtk::PACK_EXPAND_WIDGET, 0); - RTImage *cbdlImage = Gtk::manage (new RTImage("one-to-one-small.png")); + RTImage *cbdlImage = Gtk::manage(new RTImage("one-to-one-small.png")); cbdlImage->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); cbdlTitleHBox->pack_end(*cbdlImage, Gtk::PACK_SHRINK, 0); - expcbdl->setLabel(cbdlTitleHBox); + expcbdl->setLabel(cbdlTitleHBox); expcbdl->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Locallab::foldAllButMe), expcbdl)); enablecbdlConn = expcbdl->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Locallab::enableToggled), expcbdl)); expcbdl->set_tooltip_text(M("TP_LOCALLAB_EXPCBDL_TOOLTIP")); @@ -855,7 +911,7 @@ Locallab::Locallab(): denoiLabel->set_markup(Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_DENOIS")) + Glib::ustring("")); denoiLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); denoiTitleHBox->pack_start(*denoiLabel, Gtk::PACK_EXPAND_WIDGET, 0); - RTImage *denoiImage = Gtk::manage (new RTImage("one-to-one-small.png")); + RTImage *denoiImage = Gtk::manage(new RTImage("one-to-one-small.png")); denoiImage->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); denoiTitleHBox->pack_end(*denoiImage, Gtk::PACK_SHRINK, 0); expdenoi->setLabel(denoiTitleHBox); @@ -1030,16 +1086,18 @@ void Locallab::writeOptions(std::vector &tpOpen) } -void Locallab::refChanged (double huer, double lumar, double chromar) +void Locallab::refChanged(double huer, double lumar, double chromar) { if (!batchMode) { // Hue reference normalization (between 0 and 1) double normHuer = huer; float h = Color::huelab_to_huehsv2(normHuer); - h += 1.f/6.f; + h += 1.f / 6.f; + if (h > 1.f) { h -= 1.f; } + normHuer = h; // Luma reference normalization (between 0 and 1) @@ -1051,22 +1109,26 @@ void Locallab::refChanged (double huer, double lumar, double chromar) // printf("nh=%f nl=%f nc=%f\n", normHuer, normLumar, normChromar); idle_register.add( - [this, normHuer, normLumar, normChromar]() -> bool - { - GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected - // Update Color & Light mask background - CCmaskshape->updateLocallabBackground(normChromar); - LLmaskshape->updateLocallabBackground(normLumar); - HHmaskshape->updateLocallabBackground(normHuer); + // Update Color & Light mask background + CCmaskshape->updateLocallabBackground(normChromar); + LLmaskshape->updateLocallabBackground(normLumar); + HHmaskshape->updateLocallabBackground(normHuer); - // Update Exposure mask background - CCmaskexpshape->updateLocallabBackground(normChromar); - LLmaskexpshape->updateLocallabBackground(normLumar); - HHmaskexpshape->updateLocallabBackground(normHuer); + // Update Exposure mask background + CCmaskexpshape->updateLocallabBackground(normChromar); + LLmaskexpshape->updateLocallabBackground(normLumar); + HHmaskexpshape->updateLocallabBackground(normHuer); - return false; - } + // Update Shadow Highlight mask background + CCmaskSHshape->updateLocallabBackground(normChromar); + LLmaskSHshape->updateLocallabBackground(normLumar); + HHmaskSHshape->updateLocallabBackground(normHuer); + + return false; + } ); } } @@ -1637,6 +1699,12 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pp->locallab.spots.at(pp->locallab.selspot).s_tonalwidth = s_tonalwidth->getIntValue(); pp->locallab.spots.at(pp->locallab.selspot).sh_radius = sh_radius->getIntValue(); pp->locallab.spots.at(pp->locallab.selspot).sensihs = sensihs->getIntValue(); + pp->locallab.spots.at(pp->locallab.selspot).enaSHMask = enaSHMask->get_active(); + pp->locallab.spots.at(pp->locallab.selspot).LLmaskSHcurve = LLmaskSHshape->getCurve(); + pp->locallab.spots.at(pp->locallab.selspot).CCmaskSHcurve = CCmaskSHshape->getCurve(); + pp->locallab.spots.at(pp->locallab.selspot).HHmaskSHcurve = HHmaskSHshape->getCurve(); + pp->locallab.spots.at(pp->locallab.selspot).blendmaskSH = blendmaskSH->getIntValue(); + pp->locallab.spots.at(pp->locallab.selspot).radmaskSH = radmaskSH->getValue(); // Vibrance pp->locallab.spots.at(pp->locallab.selspot).expvibrance = expvibrance->getEnabled(); @@ -1812,6 +1880,13 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pe->locallab.spots.at(pp->locallab.selspot).s_tonalwidth = pe->locallab.spots.at(pp->locallab.selspot).s_tonalwidth || s_tonalwidth->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).sh_radius = pe->locallab.spots.at(pp->locallab.selspot).sh_radius || sh_radius->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).sensihs = pe->locallab.spots.at(pp->locallab.selspot).sensihs || sensihs->getEditedState(); + + pe->locallab.spots.at(pp->locallab.selspot).enaSHMask = pe->locallab.spots.at(pp->locallab.selspot).enaSHMask || !enaSHMask->get_inconsistent(); + pe->locallab.spots.at(pp->locallab.selspot).CCmaskSHcurve = pe->locallab.spots.at(pp->locallab.selspot).CCmaskSHcurve || !CCmaskSHshape->isUnChanged(); + pe->locallab.spots.at(pp->locallab.selspot).LLmaskSHcurve = pe->locallab.spots.at(pp->locallab.selspot).LLmaskSHcurve || !LLmaskSHshape->isUnChanged(); + pe->locallab.spots.at(pp->locallab.selspot).HHmaskSHcurve = pe->locallab.spots.at(pp->locallab.selspot).HHmaskSHcurve || !HHmaskSHshape->isUnChanged(); + pe->locallab.spots.at(pp->locallab.selspot).blendmaskSH = pe->locallab.spots.at(pp->locallab.selspot).blendmaskSH || blendmaskSH->getEditedState(); + pe->locallab.spots.at(pp->locallab.selspot).radmaskSH = pe->locallab.spots.at(pp->locallab.selspot).radmaskSH || radmaskSH->getEditedState(); // Vibrance pe->locallab.spots.at(pp->locallab.selspot).expvibrance = pe->locallab.spots.at(pp->locallab.selspot).expvibrance || !expvibrance->get_inconsistent(); pe->locallab.spots.at(pp->locallab.selspot).saturated = pe->locallab.spots.at(pp->locallab.selspot).saturated || saturated->getEditedState(); @@ -1972,6 +2047,13 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pedited->locallab.spots.at(pp->locallab.selspot).s_tonalwidth = pedited->locallab.spots.at(pp->locallab.selspot).s_tonalwidth || s_tonalwidth->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).sh_radius = pedited->locallab.spots.at(pp->locallab.selspot).sh_radius || sh_radius->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).sensihs = pedited->locallab.spots.at(pp->locallab.selspot).sensihs || sensihs->getEditedState(); + + pedited->locallab.spots.at(pp->locallab.selspot).enaSHMask = pedited->locallab.spots.at(pp->locallab.selspot).enaSHMask || !enaSHMask->get_inconsistent(); + pedited->locallab.spots.at(pp->locallab.selspot).CCmaskSHcurve = pedited->locallab.spots.at(pp->locallab.selspot).CCmaskSHcurve || !CCmaskSHshape->isUnChanged(); + pedited->locallab.spots.at(pp->locallab.selspot).LLmaskSHcurve = pedited->locallab.spots.at(pp->locallab.selspot).LLmaskSHcurve || !LLmaskSHshape->isUnChanged(); + pedited->locallab.spots.at(pp->locallab.selspot).HHmaskSHcurve = pedited->locallab.spots.at(pp->locallab.selspot).HHmaskSHcurve || !HHmaskSHshape->isUnChanged(); + pedited->locallab.spots.at(pp->locallab.selspot).blendmaskSH = pedited->locallab.spots.at(pp->locallab.selspot).blendmaskSH || blendmaskSH->getEditedState(); + pedited->locallab.spots.at(pp->locallab.selspot).radmaskSH = pedited->locallab.spots.at(pp->locallab.selspot).radmaskSH || radmaskSH->getEditedState(); // Vibrance pedited->locallab.spots.at(pp->locallab.selspot).expvibrance = pedited->locallab.spots.at(pp->locallab.selspot).expvibrance || !expvibrance->get_inconsistent(); pedited->locallab.spots.at(pp->locallab.selspot).saturated = pedited->locallab.spots.at(pp->locallab.selspot).saturated || saturated->getEditedState(); @@ -2227,6 +2309,27 @@ void Locallab::curveChanged(CurveEditor* ce) } } + //Shadows Highlight + if (getEnabled() && expshadhigh->getEnabled()) { + + if (ce == CCmaskSHshape) { + if (listener) { + listener->panelChanged(EvlocallabCCmaskSHshape, M("HISTORY_CUSTOMCURVE")); + } + } + + if (ce == LLmaskSHshape) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskSHshape, M("HISTORY_CUSTOMCURVE")); + } + } + + if (ce == HHmaskSHshape) { + if (listener) { + listener->panelChanged(EvlocallabHHmaskSHshape, M("HISTORY_CUSTOMCURVE")); + } + } + } // Vibrance if (getEnabled() && expvibrance->getEnabled()) { @@ -2334,6 +2437,20 @@ void Locallab::showmaskexpMethodChanged() } } +void Locallab::showmaskSHMethodChanged() +{ + // printf("showmaskSHMethodChanged\n"); + + // When one mask state is changed, other masks are deactivated + disableListener(); + showmaskcolMethod->set_active(0); + enableListener(); + + if (listener) { + listener->panelChanged(EvlocallabshowmaskSHMethod, ""); + } +} + void Locallab::resetMaskVisibility() { // printf("resetMaskVisibility\n"); @@ -2341,6 +2458,7 @@ void Locallab::resetMaskVisibility() disableListener(); showmaskcolMethod->set_active(0); showmaskexpMethod->set_active(0); + showmaskSHMethod->set_active(0); enableListener(); } @@ -2349,7 +2467,7 @@ Locallab::llMaskVisibility* Locallab::getMaskVisibility() llMaskVisibility* maskStruct = new llMaskVisibility(); maskStruct->colorMask = showmaskcolMethod->get_active_row_number(); maskStruct->expMask = showmaskexpMethod->get_active_row_number(); - + maskStruct->SHMask = showmaskSHMethod->get_active_row_number(); return maskStruct; } @@ -2401,6 +2519,30 @@ void Locallab::enaExpMaskChanged() } } +void Locallab::enaSHMaskChanged() +{ + // printf("enaSHMaskChanged\n"); + + if (multiImage) { + if (enaSHMask->get_inconsistent()) { + enaSHMask->set_inconsistent(false); + enaSHMaskConn.block(true); + enaSHMask->set_active(false); + enaSHMaskConn.block(false); + } + } + + if (getEnabled() && expshadhigh->getEnabled()) { + if (listener) { + if (enaSHMask->get_active()) { + listener->panelChanged(EvLocallabEnaSHMask, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvLocallabEnaSHMask, M("GENERAL_DISABLED")); + } + } + } +} + void Locallab::inversChanged() { // printf("inversChanged\n"); @@ -2739,6 +2881,8 @@ void Locallab::setDefaults(const ProcParams * defParams, const ParamsEdited * pe s_tonalwidth->setDefault((double)defSpot->s_tonalwidth); sh_radius->setDefault((double)defSpot->sh_radius); sensihs->setDefault((double)defSpot->sensihs); + blendmaskSH->setDefault((double)defSpot->blendmaskSH); + radmaskSH->setDefault(defSpot->radmaskSH); // Vibrance saturated->setDefault((double)defSpot->saturated); pastels->setDefault((double)defSpot->pastels); @@ -2833,6 +2977,8 @@ void Locallab::setDefaults(const ProcParams * defParams, const ParamsEdited * pe s_tonalwidth->setDefaultEditedState(Irrelevant); sh_radius->setDefaultEditedState(Irrelevant); sensihs->setDefaultEditedState(Irrelevant); + blendmaskSH->setDefaultEditedState(Irrelevant); + radmaskSH->setDefaultEditedState(Irrelevant); // Vibrance saturated->setDefaultEditedState(Irrelevant); pastels->setDefaultEditedState(Irrelevant); @@ -2931,6 +3077,8 @@ void Locallab::setDefaults(const ProcParams * defParams, const ParamsEdited * pe s_tonalwidth->setDefaultEditedState(defSpotState->s_tonalwidth ? Edited : UnEdited); sh_radius->setDefaultEditedState(defSpotState->sh_radius ? Edited : UnEdited); sensihs->setDefaultEditedState(defSpotState->sensihs ? Edited : UnEdited); + blendmaskSH->setDefaultEditedState(defSpotState->blendmaskSH ? Edited : UnEdited); + radmaskSH->setDefaultEditedState(defSpotState->radmaskSH ? Edited : UnEdited); // Vibrance saturated->setDefaultEditedState(defSpotState->saturated ? Edited : UnEdited); pastels->setDefaultEditedState(defSpotState->pastels ? Edited : UnEdited); @@ -3214,6 +3362,19 @@ void Locallab::adjusterChanged(Adjuster * a, double newval) } } + if (a == blendmaskSH) { + if (listener) { + listener->panelChanged(EvlocallabblendmaskSH, blendmaskSH->getTextValue()); + } + } + + if (a == radmaskSH) { + if (listener) { + listener->panelChanged(EvlocallabradmaskSH, radmaskSH->getTextValue()); + } + } + + } // Vibrance @@ -3613,6 +3774,8 @@ void Locallab::setBatchMode(bool batchMode) s_tonalwidth->showEditedCB(); sh_radius->showEditedCB(); sensihs->showEditedCB(); + blendmaskSH->showEditedCB(); + radmaskSH->showEditedCB(); // Vibrance saturated->showEditedCB(); pastels->showEditedCB(); @@ -3685,6 +3848,7 @@ void Locallab::setBatchMode(bool batchMode) // In batch mode, being able to change mask visibility is useless showmaskcolMethod->hide(); showmaskexpMethod->hide(); + showmaskSHMethod->hide(); } std::vector Locallab::getCurvePoints(ThresholdSelector* tAdjuster) const @@ -3833,6 +3997,8 @@ void Locallab::enableListener() enaExpMaskConn.block(false); // Shadow highlight enableshadhighConn.block(false); + showmaskSHMethodConn.block(false); + enaSHMaskConn.block(false); // Vibrance enablevibranceConn.block(false); pskinsconn.block(false); @@ -3882,6 +4048,8 @@ void Locallab::disableListener() enaExpMaskConn.block(true); // Shadow highlight enableshadhighConn.block(true); + showmaskSHMethodConn.block(true); + enaSHMaskConn.block(true); // Vibrance enablevibranceConn.block(true); pskinsconn.block(true); @@ -3981,6 +4149,13 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con s_tonalwidth->setValue(pp->locallab.spots.at(index).s_tonalwidth); sh_radius->setValue(pp->locallab.spots.at(index).sh_radius); sensihs->setValue(pp->locallab.spots.at(index).sensihs); + + enaSHMask->set_active(pp->locallab.spots.at(index).enaSHMask); + CCmaskSHshape->setCurve(pp->locallab.spots.at(index).CCmaskSHcurve); + LLmaskSHshape->setCurve(pp->locallab.spots.at(index).LLmaskSHcurve); + HHmaskSHshape->setCurve(pp->locallab.spots.at(index).HHmaskSHcurve); + blendmaskSH->setValue(pp->locallab.spots.at(index).blendmaskSH); + radmaskSH->setValue(pp->locallab.spots.at(index).radmaskSH); // Vibrance expvibrance->setEnabled(pp->locallab.spots.at(index).expvibrance); saturated->setValue(pp->locallab.spots.at(index).saturated); @@ -4185,6 +4360,12 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con s_tonalwidth->setEditedState(spotState->s_tonalwidth ? Edited : UnEdited); sh_radius->setEditedState(spotState->sh_radius ? Edited : UnEdited); sensihs->setEditedState(spotState->sensihs ? Edited : UnEdited); + enaSHMask->set_inconsistent(multiImage && !spotState->enaSHMask); + CCmaskSHshape->setUnChanged(!spotState->CCmaskSHcurve); + LLmaskSHshape->setUnChanged(!spotState->LLmaskSHcurve); + HHmaskSHshape->setUnChanged(!spotState->HHmaskSHcurve); + blendmaskSH->setEditedState(spotState->blendmaskSH ? Edited : UnEdited); + radmaskSH->setEditedState(spotState->radmaskSH ? Edited : UnEdited); // Vibrance expvibrance->set_inconsistent(!spotState->expvibrance); diff --git a/rtgui/locallab.h b/rtgui/locallab.h index 79b7d7fbc..f6a9a3796 100644 --- a/rtgui/locallab.h +++ b/rtgui/locallab.h @@ -43,7 +43,7 @@ class Locallab : public ThresholdAdjusterListener { -private: +private: IdleRegister idle_register; // Expander widgets @@ -81,6 +81,11 @@ private: FlatCurveEditor* CCmaskexpshape; FlatCurveEditor* LLmaskexpshape; FlatCurveEditor* HHmaskexpshape; + //Shadows Highlight + CurveEditorGroup* const maskSHCurveEditorG; + FlatCurveEditor* CCmaskSHshape; + FlatCurveEditor* LLmaskSHshape; + FlatCurveEditor* HHmaskSHshape; // Vibrance CurveEditorGroup* const curveEditorGG; DiagonalCurveEditor* skinTonesCurve; @@ -119,6 +124,8 @@ private: Adjuster* const s_tonalwidth; Adjuster* const sh_radius; Adjuster* const sensihs; + Adjuster* const blendmaskSH; + Adjuster* const radmaskSH; // Vibrance Adjuster* const saturated; Adjuster* const pastels; @@ -142,7 +149,7 @@ private: Adjuster* const chrrt; Adjuster* const neigh; Adjuster* const vart; - Adjuster* const dehaz; + Adjuster* const dehaz; Adjuster* const sensih; // Sharpening Adjuster* const sharcontrast; @@ -185,7 +192,10 @@ private: Gtk::CheckButton* const enaExpMask; sigc::connection enaExpMaskConn; Gtk::CheckButton* const inversex; - sigc::connection inversexConn; + sigc::connection inversexConn; + //Shadows highlight + Gtk::CheckButton* const enaSHMask; + sigc::connection enaSHMaskConn; // Vibrance Gtk::CheckButton* const protectSkins; Gtk::CheckButton* const avoidColorShift; @@ -215,6 +225,9 @@ private: //Exposure MyComboBoxText* const showmaskexpMethod; sigc::connection showmaskexpMethodConn; + //Shadows Highlight + MyComboBoxText* const showmaskSHMethod; + sigc::connection showmaskSHMethodConn; // Blur & Noise MyComboBoxText* const blurMethod; sigc::connection blurMethodConn; @@ -236,8 +249,9 @@ private: // Gtk::Label* transLabels2; Gtk::Frame* maskcolFrame; Gtk::Frame* maskexpFrame; + Gtk::Frame* maskSHFrame; Gtk::Frame* gridFrame; - LabGrid *labgrid; + LabGrid *labgrid; // Others /** * Used to store the default ProcParams when setDefaults function is called @@ -267,6 +281,8 @@ private: // Exposure void enaExpMaskChanged(); void inversexChanged(); + //Shadows Highlight + void enaSHMaskChanged(); // Vibrance void protectskins_toggled(); void avoidcolorshift_toggled(); @@ -287,6 +303,8 @@ private: void showmaskcolMethodChanged(); //Exposure void showmaskexpMethodChanged(); + //Shadows Highlight + void showmaskSHMethodChanged(); // Blur & Noise void blurMethodChanged(); // Retinex @@ -325,6 +343,7 @@ public: struct llMaskVisibility { int colorMask; int expMask; + int SHMask; }; void resetMaskVisibility(); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index ac1354bc7..632b172df 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -993,10 +993,16 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).expshadhigh = locallab.spots.at(j).expshadhigh && pSpot.expshadhigh == otherSpot.expshadhigh; locallab.spots.at(j).highlights = locallab.spots.at(j).highlights && pSpot.highlights == otherSpot.highlights; locallab.spots.at(j).h_tonalwidth = locallab.spots.at(j).h_tonalwidth && pSpot.h_tonalwidth == otherSpot.h_tonalwidth; - locallab.spots.at(j).shadows = locallab.spots.at(j).shadows&& pSpot.shadows == otherSpot.shadows; + locallab.spots.at(j).shadows = locallab.spots.at(j).shadows && pSpot.shadows == otherSpot.shadows; locallab.spots.at(j).s_tonalwidth = locallab.spots.at(j).s_tonalwidth && pSpot.s_tonalwidth == otherSpot.s_tonalwidth; locallab.spots.at(j).sh_radius = locallab.spots.at(j).sh_radius && pSpot.sh_radius == otherSpot.sh_radius; locallab.spots.at(j).sensihs = locallab.spots.at(j).sensihs && pSpot.sensihs == otherSpot.sensihs; + locallab.spots.at(j).enaSHMask = locallab.spots.at(j).enaSHMask && pSpot.enaSHMask == otherSpot.enaSHMask; + locallab.spots.at(j).CCmaskSHcurve = locallab.spots.at(j).CCmaskSHcurve && pSpot.CCmaskSHcurve == otherSpot.CCmaskSHcurve; + locallab.spots.at(j).LLmaskSHcurve = locallab.spots.at(j).LLmaskSHcurve && pSpot.LLmaskSHcurve == otherSpot.LLmaskSHcurve; + locallab.spots.at(j).HHmaskSHcurve = locallab.spots.at(j).HHmaskSHcurve && pSpot.HHmaskSHcurve == otherSpot.HHmaskSHcurve; + locallab.spots.at(j).blendmaskSH = locallab.spots.at(j).blendmaskSH && pSpot.blendmaskSH == otherSpot.blendmaskSH; + locallab.spots.at(j).radmaskSH = locallab.spots.at(j).radmaskSH && pSpot.radmaskSH == otherSpot.radmaskSH; // Vibrance locallab.spots.at(j).expvibrance = locallab.spots.at(j).expvibrance && pSpot.expvibrance == otherSpot.expvibrance; locallab.spots.at(j).saturated = locallab.spots.at(j).saturated && pSpot.saturated == otherSpot.saturated; @@ -1036,7 +1042,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).dehaz = locallab.spots.at(j).dehaz && pSpot.dehaz == otherSpot.dehaz; locallab.spots.at(j).sensih = locallab.spots.at(j).sensih && pSpot.sensih == otherSpot.sensih; locallab.spots.at(j).localTgaincurve = locallab.spots.at(j).localTgaincurve && pSpot.localTgaincurve == otherSpot.localTgaincurve; - locallab.spots.at(j).inversret = locallab.spots.at(j).inversret &&pSpot.inversret == otherSpot.inversret; + locallab.spots.at(j).inversret = locallab.spots.at(j).inversret && pSpot.inversret == otherSpot.inversret; // Sharpening locallab.spots.at(j).expsharp = locallab.spots.at(j).expsharp && pSpot.expsharp == otherSpot.expsharp; locallab.spots.at(j).sharcontrast = locallab.spots.at(j).sharcontrast && pSpot.sharcontrast == otherSpot.sharcontrast; @@ -1782,7 +1788,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng if (colorToning.labregionsShowMask) { toEdit.colorToning.labregionsShowMask = mods.colorToning.labregionsShowMask; } - + if (sharpenEdge.enabled) { toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; } @@ -2477,6 +2483,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng // Removing all spots in toEdit and recreating spots based on mods id toEdit.locallab.spots.clear(); + for (size_t i = 0; i < mods.locallab.spots.size(); i++) { LocallabParams::LocallabSpot *newSpot = new LocallabParams::LocallabSpot(); newSpot->id = mods.locallab.spots.at(i).id; @@ -2602,12 +2609,15 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng if (locallab.spots.at(i).labgridALow) { toEdit.locallab.spots.at(i).labgridALow = mods.locallab.spots.at(i).labgridALow; } + if (locallab.spots.at(i).labgridBLow) { toEdit.locallab.spots.at(i).labgridBLow = mods.locallab.spots.at(i).labgridBLow; } + if (locallab.spots.at(i).labgridAHigh) { toEdit.locallab.spots.at(i).labgridAHigh = mods.locallab.spots.at(i).labgridAHigh; } + if (locallab.spots.at(i).labgridBHigh) { toEdit.locallab.spots.at(i).labgridBHigh = mods.locallab.spots.at(i).labgridBHigh; } @@ -2704,7 +2714,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng if (locallab.spots.at(i).expchroma) { toEdit.locallab.spots.at(i).expchroma = mods.locallab.spots.at(i).expchroma; } - + if (locallab.spots.at(i).warm) { toEdit.locallab.spots.at(i).warm = mods.locallab.spots.at(i).warm; } @@ -2783,6 +2793,30 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).sensihs = mods.locallab.spots.at(i).sensihs; } + if (locallab.spots.at(i).enaSHMask) { + toEdit.locallab.spots.at(i).enaSHMask = mods.locallab.spots.at(i).enaSHMask; + } + + if (locallab.spots.at(i).CCmaskSHcurve) { + toEdit.locallab.spots.at(i).CCmaskSHcurve = mods.locallab.spots.at(i).CCmaskSHcurve; + } + + if (locallab.spots.at(i).LLmaskSHcurve) { + toEdit.locallab.spots.at(i).LLmaskSHcurve = mods.locallab.spots.at(i).LLmaskSHcurve; + } + + if (locallab.spots.at(i).HHmaskSHcurve) { + toEdit.locallab.spots.at(i).HHmaskSHcurve = mods.locallab.spots.at(i).HHmaskSHcurve; + } + + if (locallab.spots.at(i).blendmaskSH) { + toEdit.locallab.spots.at(i).blendmaskSH = mods.locallab.spots.at(i).blendmaskSH; + } + + if (locallab.spots.at(i).radmaskSH) { + toEdit.locallab.spots.at(i).radmaskSH = mods.locallab.spots.at(i).radmaskSH; + } + // Vibrance if (locallab.spots.at(i).expvibrance) { toEdit.locallab.spots.at(i).expvibrance = mods.locallab.spots.at(i).expvibrance; @@ -3947,7 +3981,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng if (dehaze.strength) { toEdit.dehaze.strength = dontforceSet && options.baBehav[ADDSET_DEHAZE_STRENGTH] ? toEdit.dehaze.strength + mods.dehaze.strength : mods.dehaze.strength; } - + if (dehaze.depth) { toEdit.dehaze.depth = mods.dehaze.depth; } @@ -4078,6 +4112,12 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : s_tonalwidth(v), sh_radius(v), sensihs(v), + enaSHMask(v), + CCmaskSHcurve(v), + LLmaskSHcurve(v), + HHmaskSHcurve(v), + blendmaskSH(v), + radmaskSH(v), // Vibrance expvibrance(v), saturated(v), @@ -4234,6 +4274,12 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) s_tonalwidth = v; sh_radius = v; sensihs = v; + enaSHMask = v; + CCmaskSHcurve = v; + LLmaskSHcurve = v; + HHmaskSHcurve = v; + blendmaskSH = v; + radmaskSH = v; // Vibrance expvibrance = v; saturated = v; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index b7cc65fb6..73c826855 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -536,6 +536,12 @@ public: bool s_tonalwidth; bool sh_radius; bool sensihs; + bool enaSHMask; + bool CCmaskSHcurve; + bool LLmaskSHcurve; + bool HHmaskSHcurve; + bool blendmaskSH; + bool radmaskSH; // Vibrance bool expvibrance; bool saturated; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index debb4ac16..1f8988c03 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -458,9 +458,9 @@ void ToolPanelCoordinator::panelChanged(const rtengine::ProcEvent& event, const } // Manage Locallab mask visibility - if (event == rtengine::EvlocallabshowmaskcolMethod || event == rtengine::EvlocallabshowmaskexpMethod) { + if (event == rtengine::EvlocallabshowmaskcolMethod || event == rtengine::EvlocallabshowmaskexpMethod || event == rtengine::EvlocallabshowmaskSHMethod) { Locallab::llMaskVisibility* maskStruc = locallab->getMaskVisibility(); - ipc->setLocallabMaskVisibility(maskStruc->colorMask, maskStruc->expMask); + ipc->setLocallabMaskVisibility(maskStruc->colorMask, maskStruc->expMask, maskStruc->SHMask); } ipc->endUpdateParams(changeFlags); // starts the IPC processing @@ -568,7 +568,7 @@ void ToolPanelCoordinator::profileChange( // Reset Locallab mask visibility when a picture is loaded if (event == rtengine::EvPhotoLoaded) { locallab->resetMaskVisibility(); - ipc->setLocallabMaskVisibility(0, 0); + ipc->setLocallabMaskVisibility(0, 0, 0); } // start the IPC processing