diff --git a/rtdata/languages/default b/rtdata/languages/default index 08ec56725..4ee726803 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -857,6 +857,8 @@ HISTORY_MSG_600;Local - Soft Light enable HISTORY_MSG_601;Local - Soft Light strength HISTORY_MSG_602;Local - Soft Light scope HISTORY_MSG_603;Local - Sh Blur radius +HISTORY_MSG_605;Local - Color Modifications +HISTORY_MSG_606;Local - Exp Modifications HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction @@ -2019,6 +2021,10 @@ TP_LOCALLAB_SENSICB;Scope TP_LOCALLAB_SENSIBN;Scope TP_LOCALLAB_SENSIS_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm. TP_LOCALLAB_SETTINGS;Settings +TP_LOCALLAB_SHOW;Show modifications +TP_LOCALLAB_SHOWMASKCOL_TOOLTIP;Display modifications.\nBeware, you can only view one modification (color and light or Exposure).\nYou must put 'Show modification' to none to enabled the other show +TP_LOCALLAB_SHOWMNONE;None +TP_LOCALLAB_SHOWMAK1;Show modifications TP_LOCALLAB_SOFT;Soft Light TP_LOCALLAB_STRENG;Strength TP_LOCALLAB_STRENGTH;Noise diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 9fc0f4418..fef80121c 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -1054,7 +1054,7 @@ void CurveFactory::complexCurve(double ecomp, double black, double hlcompr, doub //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr, double hlcomprthresh, - double shcompr, double br, + double shcompr, double br, double cont, LUTu & histogram, LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, LUTf & lightCurveloc, int skip) { @@ -1114,18 +1114,75 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr, lightCurveloc[i] = CLIPD(val); } - 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; - } } else { lightCurveloc.makeIdentity(32767.f); } + // check if contrast curve is needed + if (cont > 0.00001 || cont < -0.00001) { + // compute mean luminance of the image with the curve applied + int sum = 0; + float avg = 0; + + for (int i = 0; i < 32768; i++) { + avg += lightCurveloc[i] * histogram[i]; + sum += histogram[i]; + } + + std::vector contrastcurvePoints; + + if (sum) { + avg /= sum; + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + contrastcurvePoints.resize(9); + contrastcurvePoints.at(0) = double (DCT_NURBS); + + contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range + contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range + + contrastcurvePoints.at(3) = avg - avg * (0.6 - cont / 250.0); // toe point + contrastcurvePoints.at(4) = avg - avg * (0.6 + cont / 250.0); // value at toe point + + contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - cont / 250.0); // shoulder point + contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + cont / 250.0); // value at shoulder point + + contrastcurvePoints.at(7) = 1.; // white point + contrastcurvePoints.at(8) = 1.; // value at white point + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + } else { + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image + contrastcurvePoints.resize(5); + contrastcurvePoints.at(0) = double (DCT_NURBS); + + contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range + contrastcurvePoints.at(2) = 1.; // black point. Value in [0 ; 1] range + + contrastcurvePoints.at(3) = 1.; // white point + contrastcurvePoints.at(4) = 1.; // value at white point + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + } + + DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip); + + // apply contrast enhancement + for (int i = 0; i < 32768; i++) { + lightCurveloc[i] = contrastcurve.getVal(lightCurveloc[i]); + } + + } + + 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; + } // a: slope of the curve, black: starting point at the x axis diff --git a/rtengine/curves.h b/rtengine/curves.h index dece79471..5c8f920e6 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -345,7 +345,7 @@ public: int skip = 1); - static void complexCurvelocal(double ecomp, double black, double hlcompr, double hlcomprthresh, double shcompr, double br, + static void complexCurvelocal(double ecomp, double black, double hlcompr, double hlcomprthresh, double shcompr, double br, double cont, LUTu & histogram, LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, LUTf & lightCurveloc, int skip = 1); diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index adf8d430d..2c22157be 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -892,6 +892,7 @@ void Crop::update(int todo) LUTf shtonecurveloc2(65536, 0); LUTf tonecurveloc2(65536, 0); LUTf lightCurveloc2(32770, 0); + LUTu lhist16loc2(32770, 0); bool LHutili = parent->LHutili; bool HHutili = parent->HHutili; @@ -929,16 +930,17 @@ void Crop::update(int todo) double shcompr = params.locallab.spots.at(sp).shcompr; double br = params.locallab.spots.at(sp).lightness; - CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, - hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, - sca); - + double cont = params.locallab.spots.at(sp).contrast; + lhist16loc2 = parent->lhist16loc; double huere, chromare, lumare, huerefblu, sobelre; huerefblu = parent->huerefblurs[sp]; huere = parent->huerefs[sp]; chromare = parent->chromarefs[sp]; lumare = parent->lumarefs[sp]; sobelre = parent->sobelrefs[sp]; + CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lhist16loc2, + hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, + sca); parent->ipf.Lab_Local(1, sp, parent->sobelrefs, (float**)shbuffer, labnCrop, labnCrop, reservCrop, cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, lllocalcurve2, loclhCurve, lochhCurve, LHutili, HHutili, cclocalcurve2, localskutili, sklocalcurve2, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, huere, chromare, lumare, sobelre); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 49a04f96d..3a6982ca3 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -107,6 +107,7 @@ ImProcCoordinator::ImProcCoordinator() shtonecurveloc(65536, 0), tonecurveloc(65536, 0), lightCurveloc(32770, 0), + lhist16loc(32770, 0), locallutili(false), localcutili(false), localskutili(false), localexutili(false), LHutili(false), HHutili(false), huerefs(500, -100000.f), huerefblurs(500, -100000.f), @@ -693,7 +694,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } readyphase++; - lhist16(32768); +// lhist16(32768); if (todo & (M_LUMACURVE | M_CROP)) { LUTu lhist16(32768); @@ -792,19 +793,23 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) double hlcomprthresh = params.locallab.spots.at(sp).hlcomprthresh; double shcompr = params.locallab.spots.at(sp).shcompr; double br = params.locallab.spots.at(sp).lightness; - CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, - hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, - sca); + double cont = params.locallab.spots.at(sp).contrast; + lhist16loc.clear(); + // Reference parameters computation double huere, chromare, lumare, huerefblu, sobelre; if (params.locallab.spots.at(sp).spotMethod == "exc") { - ipf.calc_ref(sp, reserv, reserv, 0, 0, pW, pH, scale, huerefblu, huere, chromare, lumare, sobelre); + ipf.calc_ref(sp, reserv, reserv, 0, 0, pW, pH, scale, huerefblu, huere, chromare, lumare, sobelre, lhist16loc); } else { - ipf.calc_ref(sp, nprevl, nprevl, 0, 0, pW, pH, scale, huerefblu, huere, chromare, lumare, sobelre); + ipf.calc_ref(sp, nprevl, nprevl, 0, 0, pW, pH, scale, huerefblu, huere, chromare, lumare, sobelre, lhist16loc); } + CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lhist16loc, + hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, + sca); + huerblu = huerefblurs[sp] = huerefblu; huer = huerefs[sp] = huere; chromar = chromarefs[sp] = chromare; diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 8551e6e19..45d9862aa 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -229,7 +229,7 @@ protected: LUTf shtonecurveloc; LUTf tonecurveloc; LUTf lightCurveloc; - LUTu lhist16; + LUTu lhist16loc; LocretigainCurve locRETgainCurve; LocretigainCurverab locRETgainCurverab; LocLHCurve loclhCurve; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 58431d8a9..4fda11f1b 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -286,7 +286,7 @@ public: //locallab void MSRLocal(int sp, float** luminance, float** templ, const float* const *originalLuminance, const int width, const int height, const LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); // void calc_ref (LabImage* original, LabImage* transformed, int cx, int cy, int oW, int oH, int sk, double &huere, double &chromare, double &lumare, double &sobelref); - void calc_ref(int sp, LabImage* original, LabImage* transformed, int cx, int cy, int oW, int oH, int sk, double &huerefblur, double &huere, double &chromare, double &lumare, double &sobelref); + void calc_ref(int sp, LabImage* original, LabImage* transformed, int cx, int cy, int oW, int oH, int sk, double &huerefblur, double &huere, double &chromare, double &lumare, double &sobelref, LUTu & histogram); 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, LUTf & sobelrefs, float** shbuffer, LabImage* original, LabImage* transformed, LabImage* reserved, int cx, int cy, int oW, int oH, int sk, const LocretigainCurve & locRETgainCcurve, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, bool &LHutili, bool &HHutili, LUTf & cclocalcurve, bool & localskutili, LUTf & sklocalcurve, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, LUTf & lightCurveloc, double & huerefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref); @@ -295,29 +295,24 @@ public: void InverseBlurNoise_Local(const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy); void Reti_Local(float moddE, float powdE, float ** buflight, float **bufchro, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int chro, int sk); void InverseReti_Local(const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int chro); - void Contrast_Local(float powdE, int call, float ** buflightc, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, float pm, struct local_contra &lco, float lumaref, const struct local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); void cbdl_Local(float moddE, float powdE, float ** buflight, float ** bufchrom, float **loctemp, float **loctempch, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int chro, int sk); void BlurNoise_Local(float moddE, float powdE, int call, LabImage* tmp1, LabImage* tmp2, float ** buflight, float ** bufchro, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); void TM_Local(float moddE, float powdE, LabImage* tmp1, float ** buflight, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); static void strcurv_data(std::string retistr, int *s_datc, int &siz); - void InverseContrast_Local(float ave, struct local_contra & lco, const struct local_params & lp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, LabImage * original, LabImage * transformed, int cx, int cy, int sk); void vibrancelocal(int sp, int bfw, int bfh, LabImage* lab, LabImage* dest, bool & localskutili, LUTf & sklocalcurve); - void Expo_vibr_Local(float moddE, float powdE, int senstype, float **buflight, float **bufchro, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int sk); +// void Expo_vibr_Local(float moddE, float powdE, int senstype, float **buflight, float **bufchro, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int sk); + void Expo_vibr_Local(float moddE, float powdE, int senstype, float **buflight, float **bufchro, float **buf_a_cat, float ** buf_b_cat, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, LabImage * difLab, const LabImage * const tmp1, int cx, int cy, int sk); void exlabLocal(const local_params& lp, int bfh, int bfw, LabImage* bufexporig, LabImage* lab, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve); void Exclude_Local(float moddE, float powdE, int sen, float **deltaso, float **buflight, float **bufchro, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, LabImage * rsv, LabImage * reserv, int cx, int cy, int sk); -// void vibrance_Local(float **buflight, float **bufchro, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int sk); -// void ColorLight_Local(int call, LabImage * bufcolorig, float **buflight, float **bufchro, float **bufchroslid, float ** bufhh, float ** buflightslid, bool &LHutili, bool &HHutili, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy); void DeNoise_Local(int call, const struct local_params& lp, int levred, float hueplus, float huemoins, float hueref, float dhueden, LabImage* original, LabImage* transformed, LabImage &tmp1, int cx, int cy, int sk); -// void DeNoise_Local_imp(int call, const struct local_params& lp, int levred, float hueplus, float huemoins, float hueref, float dhueden, LabImage* original, LabImage* transformed, LabImage* tmp1, int cx, int cy, int sk); void fftw_denoise(int GW, int GH, int max_numblox_W, int min_numblox_W, float **tmp1, array2D *Lin, int numThreads, const struct local_params & lp, int chrom); void ColorLight_Local(float moddE, float powdE, int call, LabImage * bufcolorig, float **buflight, float **bufchro, float **bufchroslid, float ** bufhh, float ** buflightslid, bool &LHutili, bool &HHutili, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, LUTf & lightCurveloc, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); void InverseColorLight_Local(const struct local_params& lp, LUTf & lightCurveloc, LabImage* original, LabImage* transformed, int cx, int cy, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, int sk); - void cat02_Local(float moddE, float powdE, float **buflightcat, float **buf_a_cat, float ** buf_b_cat, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int sk); void Sharp_Local(int call, float **loctemp, int senstype, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); void InverseSharp_Local(float **loctemp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 75c1e575f..09668b5ed 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -48,6 +48,7 @@ #define BENCHMARK #include "StopWatch.h" #include "rt_algo.h" +#include "guidedfilter.h" #define cliploc( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) @@ -171,10 +172,13 @@ struct local_params { bool invrad; bool invret; bool invshar; + bool showmaskexpo; bool actsp; float str; int qualmet; int qualcurvemet; + int showmaskcolmet; + int showmaskexpmet; int blurmet; float noiself; float noiseldetail; @@ -385,6 +389,18 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.qualcurvemet = 5; } + if (locallab.spots.at(sp).showmaskcolMethod == "none") { + lp.showmaskcolmet = 0; + } else if (locallab.spots.at(sp).showmaskcolMethod == "color") { + lp.showmaskcolmet = 1; + } + + if (locallab.spots.at(sp).showmaskexpMethod == "none") { + lp.showmaskexpmet = 0; + } else if (locallab.spots.at(sp).showmaskexpMethod == "expo") { + lp.showmaskexpmet = 1; + } + if (locallab.spots.at(sp).blurMethod == "norm") { lp.blurmet = 0; } else if (locallab.spots.at(sp).blurMethod == "inv") { @@ -456,6 +472,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall bool inversesha = locallab.spots.at(sp).inverssha; double strength = (double) locallab.spots.at(sp).strength; float str = (float)locallab.spots.at(sp).str; +// lp.showmaskexpo = showmexp; lp.cir = circr; lp.actsp = acti; @@ -829,7 +846,7 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab, LabImage* dest) float yb = 18.f; float d, dj; - // const int gamu = 0; //(params->colorappearance.gamut) ? 1 : 0; + // const int gamu = 0; //(params->colorappearance.gamut) ? 1 : 0; xw = 100.0f * Xw; yw = 100.0f * Yw; zw = 100.0f * Zw; @@ -2112,469 +2129,6 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in } -void ImProcFunctions::cat02_Local(float moddE, float powdE, float **buflightcat, float **buf_a_cat, float ** buf_b_cat, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int sk) -{ - -//local cat02 - BENCHFUN { - const float ach = (float)lp.trans / 100.f; - float varsens = lp.sensex; - - - //chroma - constexpr float amplchsens = 2.5f; - constexpr float achsens = (amplchsens - 1.f) / (100.f - 20.f); //20. default locallab.sensih - constexpr float bchsens = 1.f - 20.f * achsens; - const float multchro = varsens * achsens + bchsens; - - //luma - - //skin - constexpr float amplchsensskin = 1.6f; - constexpr float achsensskin = (amplchsensskin - 1.f) / (100.f - 20.f); //20. default locallab.sensih - constexpr float bchsensskin = 1.f - 20.f * achsensskin; - const float multchroskin = varsens * achsensskin + bchsensskin; - - //transition = difficult to avoid artifact with scope on flat area (sky...) - - constexpr float delhu = 0.05f; //between 0.05 and 0.2 - - const float apl = (-1.f) / delhu; - const float bpl = - apl * hueplus; - const float amo = 1.f / delhu; - const float bmo = - amo * huemoins; - - - const float pb = 4.f; - const float pa = (1.f - pb) / 40.f; - float refa = chromaref * cos(hueref); - float refb = chromaref * sin(hueref); - - const float ahu = 1.f / (2.8f * varsens - 280.f); - const float bhu = 1.f - ahu * 2.8f * varsens; - - const float alum = 1.f / (varsens - 100.f); - const float blum = 1.f - alum * varsens; - - int GW = transformed->W; - int GH = transformed->H; - - LabImage *origblur = nullptr; - - origblur = new LabImage(GW, GH); - - float radius = 3.f / sk; -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(original->L, origblur->L, GW, GH, radius); - gaussianBlur(original->a, origblur->a, GW, GH, radius); - gaussianBlur(original->b, origblur->b, GW, GH, radius); - - } - -#ifdef _OPENMP - #pragma omp parallel if (multiThread) -#endif - { -#ifdef __SSE2__ - float atan2Buffer[transformed->W] ALIGNED16; - float sqrtBuffer[transformed->W] ALIGNED16; - vfloat c327d68v = F2V(327.68f); -#endif - -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for (int y = 0; y < transformed->H; y++) - { - - const int loy = cy + y; - const bool isZone0 = loy > lp.yc + lp.ly || loy < lp.yc - lp.lyT; // whole line is zone 0 => we can skip a lot of processing - - if (isZone0) { // outside selection and outside transition zone => no effect, keep original values - for (int x = 0; x < transformed->W; x++) { - transformed->L[y][x] = original->L[y][x]; - } - - continue; - } - -#ifdef __SSE2__ - int i = 0; - - for (; i < transformed->W - 3; i += 4) { - vfloat av = LVFU(origblur->a[y][i]); - vfloat bv = LVFU(origblur->b[y][i]); - STVF(atan2Buffer[i], xatan2f(bv, av)); - STVF(sqrtBuffer[i], _mm_sqrt_ps(SQRV(bv) + SQRV(av)) / c327d68v); - } - - for (; i < transformed->W; i++) { - atan2Buffer[i] = xatan2f(origblur->b[y][i], origblur->a[y][i]); - sqrtBuffer[i] = sqrt(SQR(origblur->b[y][i]) + SQR(origblur->a[y][i])) / 327.68f; - } - -#endif - - for (int x = 0; x < transformed->W; x++) { - int lox = cx + x; - int begx = int (lp.xc - lp.lxL); - int begy = int (lp.yc - lp.lyT); - - int zone = 0; - float localFactor = 1.f; - - if (lp.shapmet == 0) { - calcTransition(lox, loy, ach, lp, zone, localFactor); - } else if (lp.shapmet == 1) { - calcTransitionrect(lox, loy, ach, lp, zone, localFactor); - } - - - if (zone == 0) { // outside selection and outside transition zone => no effect, keep original values - transformed->L[y][x] = original->L[y][x]; - continue; - } - -#ifdef __SSE2__ - float rhue = atan2Buffer[x]; - float rchro = sqrtBuffer[x]; -#else - float rhue = xatan2f(origblur->b[y][x], origblur->a[y][x]); - float rchro = sqrt(SQR(origblur->b[y][x]) + SQR(origblur->a[y][x])) / 327.68f; -#endif - float rL = origblur->L[y][x] / 327.68f; - float dE = sqrt(SQR(refa - origblur->a[y][x] / 327.68f) + SQR(refb - origblur->b[y][x] / 327.68f) + SQR(lumaref - rL)); - - float cli = 1.f; - float cla = 1.f; - float clb = 1.f; - - cli = buflightcat[loy - begy][lox - begx]; - cla = buf_a_cat[loy - begy][lox - begx]; - clb = buf_b_cat[loy - begy][lox - begx]; - - - float aplus = (1.f - cli) / delhu; - float bplus = 1.f - aplus * hueplus; - float amoins = (cli - 1.f) / delhu; - float bmoins = 1.f - amoins * huemoins; - - float aplusa = (1.f - cla) / delhu; - float bplusa = 1.f - aplusa * hueplus; - float amoinsa = (cla - 1.f) / delhu; - float bmoinsa = 1.f - amoinsa * huemoins; - - float aplusb = (1.f - clb) / delhu; - float bplusb = 1.f - aplusb * hueplus; - float amoinsb = (clb - 1.f) / delhu; - float bmoinsb = 1.f - amoinsb * huemoins; - - float realstr = 1.f; - float realstra = 1.f; - float realstrb = 1.f; - - //prepare shape detection - float deltachro = fabs(rchro - chromaref); - float deltahue = fabs(rhue - hueref); - - if (deltahue > rtengine::RT_PI) { - deltahue = - (deltahue - 2.f * rtengine::RT_PI); - } - - float deltaE = 20.f * deltahue + deltachro; //between 0 and 280 - float deltaL = fabs(lumaref - rL); //between 0 and 100 - - float kch = 1.f; - float khu = 0.f; - float fach = 1.f; - float falu = 1.f; - - if (deltachro < 160.f * SQR(varsens / 100.f)) { - kch = 1.f; - } else { - float ck = 160.f * SQR(varsens / 100.f); - float ak = 1.f / (ck - 160.f); - float bk = -160.f * ak; - kch = ak * deltachro + bk; - } - - float kkch = 1.f; - float kchchro = 1.f; - kkch = pa * varsens + pb; - float kch0 = kch; - - if (varsens < 40.f) { - kch = kchchro = pow(kch0, kkch); //increase under 40 - float dEsens = moddE * varsens; - float kdE = 1.f; - - if (dE > dEsens) { - kdE = 1.f; - } else { - kdE = SQR(SQR(dE / dEsens)); - } - - if (deltahue < 0.3f && settings->detectshape == true) { - kchchro = kch = pow(kch0, (1.f + kdE * moddE * (3.f - 10.f * deltahue)) * kkch); - } - } - - float dEsensall = varsens; - float kD = 1.f; - - if (settings->detectshape == true) { - if (dE < dEsensall) { - kD = 1.f; - } else { - kD = pow(dEsensall / dE, powdE); - } - } - - /* - if (varsens < 40.f) { - kch = pow(kch, pa * varsens + pb); //increase under 40 - } - */ - bool kzon = false; - - //transition = difficult to avoid artifact with scope on flat area (sky...) - //hue detection - if ((hueref + dhue) < rtengine::RT_PI && rhue < hueplus && rhue > huemoins) { //transition are good - if (rhue >= hueplus - delhu) { - realstr = aplus * rhue + bplus; - realstra = aplusa * rhue + bplusa; - realstrb = aplusb * rhue + bplusb; - khu = apl * rhue + bpl; - - } else if (rhue < huemoins + delhu) { - realstr = amoins * rhue + bmoins; - realstra = amoinsa * rhue + bmoinsa; - realstrb = amoinsb * rhue + bmoinsb; - khu = amo * rhue + bmo; - - } else { - realstr = cli; - khu = 1.f; - realstra = cla; - realstrb = clb; - - } - - kzon = true; - } else if ((hueref + dhue) >= rtengine::RT_PI && (rhue > huemoins || rhue < hueplus)) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - realstr = aplus * rhue + bplus; - realstra = aplusa * rhue + bplusa; - realstrb = aplusb * rhue + bplusb; - khu = apl * rhue + bpl; - - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - realstr = amoins * rhue + bmoins; - realstra = amoinsa * rhue + bmoinsa; - realstrb = amoinsb * rhue + bmoinsb; - khu = amo * rhue + bmo; - - } else { - realstr = cli; - khu = 1.f; - realstra = cla; - realstrb = clb; - } - - kzon = true; - } - - if ((hueref - dhue) > -rtengine::RT_PI && rhue < hueplus && rhue > huemoins) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - realstr = aplus * rhue + bplus; - realstra = aplusa * rhue + bplusa; - realstrb = aplusb * rhue + bplusb; - khu = apl * rhue + bpl; - - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - realstr = amoins * rhue + bmoins; - realstra = amoinsa * rhue + bmoinsa; - realstrb = amoinsb * rhue + bmoinsb; - khu = amo * rhue + bmo; - - } else { - realstr = cli; - khu = 1.f; - realstra = cla; - realstrb = clb; - } - - kzon = true; - } else if ((hueref - dhue) <= -rtengine::RT_PI && (rhue > huemoins || rhue < hueplus)) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - realstr = aplus * rhue + bplus; - realstra = aplusa * rhue + bplusa; - realstrb = aplusb * rhue + bplusb; - khu = apl * rhue + bpl; - - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - realstr = amoins * rhue + bmoins; - realstra = amoinsa * rhue + bmoinsa; - realstrb = amoinsb * rhue + bmoinsb; - khu = amo * rhue + bmo; - - } else { - realstr = cli; - khu = 1.f; - realstra = cla; - realstrb = clb; - } - - kzon = true; - } - - realstr *= kD; - realstra *= kD; - realstrb *= kD; - - //shape detection for hue chroma and luma - - if (settings->detectshape == false) { - if (varsens <= 20.f) { //to try... - - if (deltaE < 2.8f * varsens) { - fach = khu; - } else { - fach = khu * (ahu * deltaE + bhu); - } - - float kcr = 10.f; - - if (rchro < kcr) { - fach *= (1.f / (kcr * kcr)) * rchro * rchro; - } - - if (lp.qualmet >= 1) { - } else { - fach = 1.f; - } - - if (deltaL < varsens) { - falu = 1.f; - } else { - falu = alum * deltaL + blum; - } - - } - } - - // float kdiff = 0.f; - // I add these functions...perhaps not good - if (kzon) { - if (varsens < 60.f) { //arbitrary value - if (hueref < -1.1f && hueref > -2.8f) { // detect blue sky - if (chromaref > 0.f && chromaref < 35.f * multchro) { // detect blue sky - if ((rhue > -2.79f && rhue < -1.11f) && (rchro < 35.f * multchro)) { - realstr *= 0.9f; - } else { - realstr = 1.f; - } - } - } else { - realstr = cli; - } - - if (varsens < 50.f) { //&& lp.chro > 0.f - if (hueref > -0.1f && hueref < 1.6f) { // detect skin - if (chromaref > 0.f && chromaref < 55.f * multchroskin) { // detect skin - if ((rhue > -0.09f && rhue < 1.59f) && (rchro < 55.f * multchroskin)) { - realstr *= 0.7f; - } else { - realstr = 1.f; - } - } - } else { - realstr = cli; - } - } - } - - } - - float kcr = 100.f * lp.thr; - float falL = 1.f; - - if (rchro < kcr && chromaref > kcr) { // reduce artifacts in grey tones near hue spot and improve algorithm - falL *= pow(rchro / kcr, lp.iterat / 10.f); - } - - if (rL > 0.1f) { //to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9 - switch (zone) { - case 0: { // outside selection and outside transition zone => no effect, keep original values - transformed->L[y][x] = original->L[y][x]; - transformed->a[y][x] = original->a[y][x]; - transformed->b[y][x] = original->b[y][x]; - - break; - } - - case 1: { // inside transition zone - float factorx = localFactor; - - float difL; - difL = tmp1->L[loy - begy][lox - begx] - original->L[y][x]; - difL *= factorx * (100.f + realstr * falL) / 100.f; - difL *= kch * fach; - - transformed->L[y][x] = original->L[y][x] + difL; - float difa, difb; - - difa = tmp1->a[loy - begy][lox - begx] - original->a[y][x]; - difb = tmp1->b[loy - begy][lox - begx] - original->b[y][x]; - difa *= factorx * (100.f + realstra * falu * falL) / 100.f; - difb *= factorx * (100.f + realstrb * falu * falL) / 100.f; - difa *= kch * fach; - difb *= kch * fach; - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); - - - break; - - } - - case 2: { // inside selection => full effect, no transition - float difL; - - difL = tmp1->L[loy - begy][lox - begx] - original->L[y][x]; - difL *= (100.f + realstr * falL) / 100.f; - difL *= kch * fach; - transformed->L[y][x] = original->L[y][x] + difL; - float difa, difb; - - difa = tmp1->a[loy - begy][lox - begx] - original->a[y][x]; - difb = tmp1->b[loy - begy][lox - begx] - original->b[y][x]; - difa *= (100.f + realstra * falu * falL) / 100.f; - difb *= (100.f + realstrb * falu * falL) / 100.f; - difa *= kch * fach; - difb *= kch * fach; - - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); - - } - } - - } - } - } - - } - delete origblur; - - } -} - - void ImProcFunctions::cbdl_Local(float moddE, float powdE, float ** buflight, float ** bufchrom, float **loctemp, float **loctempch, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int chro, int sk) { //local CBDL @@ -4472,722 +4026,16 @@ struct local_contra { float al, bl; }; -void ImProcFunctions::Contrast_Local(float powdE, int call, float ** buflightc, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, float pm, struct local_contra & lco, float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) -{ - BENCHFUN -// contrast - perhaps for 4 areas if need -// I tried shmap adaptaed to Lab, but no real gain and artifacts - const float localtype = lumaref; // always spot area - const float ach = (float)lp.trans / 100.f; - float reducac; - - //constant and variable to prepare shape detection - if (lp.sens < 30.f) { - reducac = 0.2f * (lp.sens / 100.f); - } else { - float areduc = 0.6285714f; //0.44f/0.7f; - float breduc = 0.5f - areduc; - reducac = areduc * (lp.sens / 100.f) + breduc; - } - - const float realcox = lco.dx, realcoy = lco.dy; - - lco.alsup = (-realcox) / (localtype / 2.f); - lco.blsup = -lco.alsup * localtype; - lco.alsup2 = (realcoy) / (50.f - localtype / 2.f); - lco.blsup2 = -lco.alsup2 * localtype; - lco.alsup3 = (realcoy) / (localtype / 2.f - 50.f); - lco.blsup3 = -lco.alsup3 * 100.f; - lco.aDY = realcoy; - - - constexpr float delhu = 0.1f; //between 0.05 and 0.2 - - const float apl = (-1.f) / delhu; - const float bpl = - apl * hueplus; - const float amo = 1.f / delhu; - const float bmo = - amo * huemoins; - - - const float pb = 4.f; - const float pa = (1.f - pb) / 40.f; - float refa = chromaref * cos(hueref); - float refb = chromaref * sin(hueref); - - //const float moddE = 2.f; - - const float ahu = 1.f / (2.8f * lp.sens - 280.f); - const float bhu = 1.f - ahu * 2.8f * lp.sens; - - lco.alinf = realcox / (localtype / 2.f); - const float vi = (localtype / 2.f) / 100.f; - const float vinf = (50.f + localtype / 2.f) / 100.f; - ImProcFunctions::secondeg_begin(reducac, vi, lco.aa, lco.bb); //parabolic - ImProcFunctions::secondeg_end(reducac, vinf, lco.aaa, lco.bbb, lco.ccc); //parabolic - - int GW = transformed->W; - int GH = transformed->H; - - LabImage *origblur = nullptr; - - origblur = new LabImage(GW, GH); - - float radius = 3.f / sk; -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(original->L, origblur->L, GW, GH, radius); - gaussianBlur(original->a, origblur->a, GW, GH, radius); - gaussianBlur(original->b, origblur->b, GW, GH, radius); - - } - - - if (call <= 3) { -#ifdef _OPENMP - #pragma omp parallel if (multiThread) -#endif - { - //Todo optimization in this first part with something equivalent to bufcolorig and bufcoltra in colorlight_local -#ifdef __SSE2__ - float atan2Buffer[transformed->W] ALIGNED16; - float sqrtBuffer[transformed->W] ALIGNED16; - vfloat c327d68v = F2V(327.68f); -#endif - -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for (int y = 0; y < transformed->H; y++) - { - const int loy = cy + y; - const bool isZone0 = loy > lp.yc + lp.ly || loy < lp.yc - lp.lyT; // whole line is zone 0 => we can skip a lot of processing - - if (isZone0) { // outside selection and outside transition zone => no effect, keep original values - continue; - } - -#ifdef __SSE2__ - int i = 0; - - for (; i < transformed->W - 3; i += 4) { - vfloat av = LVFU(origblur->a[y][i]); - vfloat bv = LVFU(origblur->b[y][i]); - STVF(atan2Buffer[i], xatan2f(bv, av)); - STVF(sqrtBuffer[i], _mm_sqrt_ps(SQRV(bv) + SQRV(av)) / c327d68v); - } - - for (; i < transformed->W; i++) { - atan2Buffer[i] = xatan2f(origblur->b[y][i], origblur->a[y][i]); - sqrtBuffer[i] = sqrt(SQR(origblur->b[y][i]) + SQR(origblur->a[y][i])) / 327.68f; - } - -#endif - - for (int x = 0; x < transformed->W; x++) { - const int lox = cx + x; - - float rL; - - if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && (rL = origblur->L[y][x]) > 3.2768f) { - // rL > 3.2768f to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9 - int zone = 0; - - float localFactor = 1.f; - - if (lp.shapmet == 0) { - calcTransition(lox, loy, ach, lp, zone, localFactor); - } else if (lp.shapmet == 1) { - calcTransitionrect(lox, loy, ach, lp, zone, localFactor); - } - - // calcTransition(lox, loy, ach, lp, zone, localFactor); - - if (zone == 0) { - continue; - } - -#ifdef __SSE2__ - float rhue = atan2Buffer[x]; - float rchro = sqrtBuffer[x]; -#else - float rhue = xatan2f(origblur->b[y][x], origblur->a[y][x]); - float rchro = sqrt(SQR(origblur->b[y][x]) + SQR(origblur->a[y][x])) / 327.68f; -#endif - rL = origblur->L[y][x] / 327.68f; - - float dE = sqrt(SQR(refa - origblur->a[y][x] / 327.68f) + SQR(refb - origblur->b[y][x] / 327.68f) + SQR(lumaref - rL)); - - //prepare shape detection - float khu = 0.f; - float kch = 1.f; - float fach = 1.f; - - float cli = 1.f; - - const int begx = lp.xc - lp.lxL; - const int begy = lp.yc - lp.lyT; - - if (lp.curvact) { - - cli = buflightc[loy - begy][lox - begx]; - - if (cli == 0.0f) { - cli = 0.01f; - } - } - - //parameters for linear interpolation in function of real hue - float apluscligh = (1.f - cli) / delhu; - float bpluscligh = 1.f - apluscligh * hueplus; - float amoinscligh = (cli - 1.f) / delhu; - float bmoinscligh = 1.f - amoinscligh * huemoins; - float realcligh = 1.f; - float deltachro = fabs(rchro - chromaref); - float deltahue = fabs(rhue - hueref); - - if (deltahue > rtengine::RT_PI) { - deltahue = - (deltahue - 2.f * rtengine::RT_PI); - } - - float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280 - - //kch to modulate action with chroma - if (deltachro < 160.f * SQR(lp.sens / 100.f)) { // TODOPRECOMPUTE - kch = 1.f; - } else { - float ck = 160.f * SQR(lp.sens / 100.f); - float ak = 1.f / (ck - 160.f); - float bk = -160.f * ak; - kch = ak * deltachro + bk; - - if (lp.sens < 40.f) { - kch = pow_F(kch, pa * lp.sens + pb); //increase under 40 - } - } - - float dEsensall = lp.sens; - float kD = 1.f; - - if (settings->detectshape == true) { - if (dE < dEsensall) { - kD = 1.f; - } else { - kD = pow(dEsensall / dE, powdE); - } - } - - // algo with detection of hue ==> artifacts for noisy images ==> denoise before - if (lp.sens < 100.f && lp.qualmet >= 1) { //to try... - //hue detection - if ((hueref + dhue) < rtengine::RT_PI && rhue < hueplus && rhue > huemoins) { //transition are good - if (rhue >= hueplus - delhu) { - realcligh = apluscligh * rhue + bpluscligh; - - khu = apl * rhue + bpl; - } else if (rhue < huemoins + delhu) { - realcligh = amoinscligh * rhue + bmoinscligh; - - khu = amo * rhue + bmo; - } else { - realcligh = cli; - - khu = 1.f; - } - - - } else if ((hueref + dhue) >= rtengine::RT_PI && (rhue > huemoins || rhue < hueplus)) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - realcligh = apluscligh * rhue + bpluscligh; - - khu = apl * rhue + bpl; - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - realcligh = amoinscligh * rhue + bmoinscligh; - - khu = amo * rhue + bmo; - } else { - realcligh = cli; - - khu = 1.f; - } - - } - - if ((hueref - dhue) > -rtengine::RT_PI && rhue < hueplus && rhue > huemoins) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - realcligh = apluscligh * rhue + bpluscligh; - - khu = apl * rhue + bpl; - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - realcligh = amoinscligh * rhue + bmoinscligh; - khu = amo * rhue + bmo; - } else { - realcligh = cli; - - khu = 1.f; - } - - } else if ((hueref - dhue) <= -rtengine::RT_PI && (rhue > huemoins || rhue < hueplus)) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - realcligh = apluscligh * rhue + bpluscligh; - - khu = apl * rhue + bpl; - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - realcligh = amoinscligh * rhue + bmoinscligh; - - khu = amo * rhue + bmo; - } else { - realcligh = cli; - - khu = 1.f; - } - - } - - realcligh *= kD; - - if (deltaE < 2.8f * lp.sens) { - fach = khu; - } else { - fach = khu * (ahu * deltaE + bhu); - } - - constexpr float kcr = 10.f; - - if (rchro < kcr) { - fach *= SQR(rchro) / SQR(kcr); - } - } - - float kcr = 100.f * lp.thr; - float falL = 1.f; - - if (rchro < kcr && chromaref > kcr) { // reduce artifacts in grey tones near hue spot and improve algorithm - falL *= pow_F(rchro / kcr, lp.iterat / 10.f); - } - - float modu = 1.f ;//realclig / cli; - float localty = localtype; - - switch (zone) { - - case 1: { // inside transition zone - if (!lp.curvact) { - modu = 1.f; - } else { - modu = CLIP1(realcligh / cli); - - } - - - if (original->L[y][x] < 32768.f) { - float factorx = localFactor; - float prov100 = original->L[y][x] / 32768.f; - float prov = prov100 * 100.f; - - if (prov > localty) { - if (prov >= localty && prov < 50.f + localty / 2.f) { - float core = (lco.alsup2 * prov + lco.blsup2) ; - core *= factorx; - - transformed->L[y][x] = 327.68f * (prov + pm * (prov - localty) * (core) * kch * fach * falL * modu); - } else { - float core = lco.aDY * (lco.aaa * prov100 * prov100 + lco.bbb * prov100 + lco.ccc); - - core *= factorx; - - transformed->L[y][x] = 327.68f * (prov + pm * (prov - localty) * (core) * kch * fach * falL * modu); - } - } else { //inferior - if (2.f * prov > localty && prov < localty) { - float core = (lco.alsup * prov + lco.blsup) ; - core *= factorx; - - transformed->L[y][x] = 327.68f * (prov - pm * (localty - prov) * core * kch * fach * falL * modu); - } else if (2.f * prov <= localtype) { - float core = prov * lco.alinf * (lco.aa * prov100 * prov100 + lco.bb * prov100); - - core *= factorx; - - transformed->L[y][x] = 327.68f * (prov - pm * (localty - prov) * core * kch * fach * falL * modu); - } - } - } - - break; - } - - case 2: { // inside selection => full effect, no transition - if (!lp.curvact) { - modu = 1.f; - } else { - modu = CLIP1(realcligh / cli); - - } - - if (original->L[y][x] < 32768.f) { - float prov100 = original->L[y][x] / 32768.f; - float prov = prov100 * 100.f; - - if (prov > localty) { - if (prov >= localty && prov < 50.f + localty / 2.f) { - float core = (lco.alsup2 * prov + lco.blsup2) ; - transformed->L[y][x] = 327.68f * (prov + pm * (prov - localty) * core * kch * fach * falL * modu); - } else { - float core = lco.aDY * (lco.aaa * prov100 * prov100 + lco.bbb * prov100 + lco.ccc); - transformed->L[y][x] = 327.68f * (prov + pm * (prov - localty) * core * kch * fach * falL * modu); - } - } else { //inferior - if (2.f * prov > localty && prov < localty) { - float core = (lco.alsup * prov + lco.blsup) ; - transformed->L[y][x] = 327.68f * (prov - pm * (localty - prov) * core * kch * fach * falL * modu); - } else if (2.f * prov <= localtype) { - float core = prov * lco.alinf * (lco.aa * prov100 * prov100 + lco.bb * prov100); - transformed->L[y][x] = 327.68f * (prov - pm * (localty - prov) * core * kch * fach * falL * modu); - } - } - } - } - } - } - } - } - } - } - - delete origblur; -} - -void ImProcFunctions::InverseContrast_Local(float ave, struct local_contra & lco, const struct local_params & lp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, LabImage * original, LabImage * transformed, int cx, int cy, int sk) - -{ - // BENCHFUN - // float ach = (float)lp.trans / 100.f; - const float localtype = lumaref; // always spot area - const float ach = (float)lp.trans / 100.f; - float reducac; - - //constant and variable to prepare shape detection - if (lp.sens < 30.f) { - reducac = 0.2f * (lp.sens / 100.f); - } else { - float areduc = 0.6285714f; //0.44f/0.7f; - float breduc = 0.5f - areduc; - reducac = areduc * (lp.sens / 100.f) + breduc; - } - - const float realcox = lco.dx, realcoy = lco.dy; - - lco.alsup = (-realcox) / (localtype / 2.f); - lco.blsup = -lco.alsup * localtype; - lco.alsup2 = (realcoy) / (50.f - localtype / 2.f); - lco.blsup2 = -lco.alsup2 * localtype; - lco.alsup3 = (realcoy) / (localtype / 2.f - 50.f); - lco.blsup3 = -lco.alsup3 * 100.f; - lco.aDY = realcoy; - - - constexpr float delhu = 0.1f; //between 0.05 and 0.2 - - const float apl = (-1.f) / delhu; - const float bpl = - apl * hueplus; - const float amo = 1.f / delhu; - const float bmo = - amo * huemoins; - - - const float pb = 4.f; - const float pa = (1.f - pb) / 40.f; - - const float ahu = 1.f / (2.8f * lp.sens - 280.f); - const float bhu = 1.f - ahu * 2.8f * lp.sens; - - lco.alinf = realcox / (localtype / 2.f); - const float vi = (localtype / 2.f) / 100.f; - const float vinf = (50.f + localtype / 2.f) / 100.f; - ImProcFunctions::secondeg_begin(reducac, vi, lco.aa, lco.bb); //parabolic - ImProcFunctions::secondeg_end(reducac, vinf, lco.aaa, lco.bbb, lco.ccc); //parabolic - - int GW = transformed->W; - int GH = transformed->H; - - LabImage *origblur = nullptr; - - origblur = new LabImage(GW, GH); - - float radius = 3.f / sk; -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(original->L, origblur->L, GW, GH, radius); - gaussianBlur(original->a, origblur->a, GW, GH, radius); - gaussianBlur(original->b, origblur->b, GW, GH, radius); - - } - -#ifdef _OPENMP - #pragma omp parallel if (multiThread) -#endif - { - //Todo optimization in this first part with something equivalent to bufcolorig and bufcoltra in colorlight_local -#ifdef __SSE2__ - float atan2Buffer[transformed->W] ALIGNED16; - float sqrtBuffer[transformed->W] ALIGNED16; - vfloat c327d68v = F2V(327.68f); -#endif - -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for (int y = 0; y < transformed->H; y++) { - const int loy = cy + y; - -#ifdef __SSE2__ - int i = 0; - - for (; i < transformed->W - 3; i += 4) { - vfloat av = LVFU(origblur->a[y][i]); - vfloat bv = LVFU(origblur->b[y][i]); - STVF(atan2Buffer[i], xatan2f(bv, av)); - STVF(sqrtBuffer[i], _mm_sqrt_ps(SQRV(bv) + SQRV(av)) / c327d68v); - } - - for (; i < transformed->W; i++) { - atan2Buffer[i] = xatan2f(origblur->b[y][i], origblur->a[y][i]); - sqrtBuffer[i] = sqrt(SQR(origblur->b[y][i]) + SQR(origblur->a[y][i])) / 327.68f; - } - -#endif - - for (int x = 0; x < transformed->W; x++) { - const int lox = cx + x; - - // float rL; - - // rL > 3.2768f to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9 - int zone = 0; - - float localFactor = 1.f; - - if (lp.shapmet == 0) { - calcTransition(lox, loy, ach, lp, zone, localFactor); - } else if (lp.shapmet == 1) { - calcTransitionrect(lox, loy, ach, lp, zone, localFactor); - } - - - -#ifdef __SSE2__ - float rhue = atan2Buffer[x]; - float rchro = sqrtBuffer[x]; -#else - float rhue = xatan2f(origblur->b[y][x], origblur->a[y][x]); - float rchro = sqrt(SQR(origblur->b[y][x]) + SQR(origblur->a[y][x])) / 327.68f; -#endif - //prepare shape detection - float khu = 0.f; - float kch = 1.f; - float fach = 1.f; - - float deltachro = fabs(rchro - chromaref); - float deltahue = fabs(rhue - hueref); - - if (deltahue > rtengine::RT_PI) { - deltahue = - (deltahue - 2.f * rtengine::RT_PI); - } - - float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280 - - //kch to modulate action with chroma - if (deltachro < 160.f * SQR(lp.sens / 100.f)) { // TODOPRECOMPUTE - kch = 1.f; - } else { - float ck = 160.f * SQR(lp.sens / 100.f); - float ak = 1.f / (ck - 160.f); - float bk = -160.f * ak; - kch = ak * deltachro + bk; - - if (lp.sens < 40.f) { - kch = pow_F(kch, pa * lp.sens + pb); //increase under 40 - } - } - - // algo with detection of hue ==> artifacts for noisy images ==> denoise before - if (lp.sens < 100.f && lp.qualmet >= 1) { //to try... - //hue detection - if ((hueref + dhue) < rtengine::RT_PI && rhue < hueplus && rhue > huemoins) { //transition are good - if (rhue >= hueplus - delhu) { - - khu = apl * rhue + bpl; - } else if (rhue < huemoins + delhu) { - - khu = amo * rhue + bmo; - } else { - - khu = 1.f; - } - - - } else if ((hueref + dhue) >= rtengine::RT_PI && (rhue > huemoins || rhue < hueplus)) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - - khu = apl * rhue + bpl; - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - - khu = amo * rhue + bmo; - } else { - - khu = 1.f; - } - - } - - if ((hueref - dhue) > -rtengine::RT_PI && rhue < hueplus && rhue > huemoins) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - - khu = apl * rhue + bpl; - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - khu = amo * rhue + bmo; - } else { - - khu = 1.f; - } - - } else if ((hueref - dhue) <= -rtengine::RT_PI && (rhue > huemoins || rhue < hueplus)) { - if (rhue >= hueplus - delhu && rhue < hueplus) { - - khu = apl * rhue + bpl; - } else if (rhue >= huemoins && rhue < huemoins + delhu) { - - khu = amo * rhue + bmo; - } else { - - khu = 1.f; - } - - } - - if (deltaE < 2.8f * lp.sens) { - fach = khu; - } else { - fach = khu * (ahu * deltaE + bhu); - } - - constexpr float kcr = 10.f; - - if (rchro < kcr) { - fach *= SQR(rchro) / SQR(kcr); - } - } - - float kcr = 100.f * lp.thr; - float falL = 1.f; - - if (rchro < kcr && chromaref > kcr) { // reduce artifacts in grey tones near hue spot and improve algorithm - falL *= pow_F(rchro / kcr, lp.iterat / 10.f); - } - - if (lp.sens > 75.f) { - fach = 1.f; - kch = 1.f; - falL = 1.f; - } - - switch (zone) { - case 0: { // - if (original->L[y][x] < 32768.f) { - float prov = original->L[y][x]; - - if (original->L[y][x] > ave) { - float kh = lco.ah * (original->L[y][x] / 327.68f) + lco.bh; - original->L[y][x] = ave + kh * (original->L[y][x] - ave); - } else { - float kl = lco.al * (original->L[y][x] / 327.68f) + 1.f; - original->L[y][x] = ave - kl * (ave - original->L[y][x]); - } - - float diflc = original->L[y][x] - prov; - transformed->L[y][x] = prov + diflc * fach * kch * falL; - } else { - transformed->L[y][x] = original->L[y][x]; - } - - break; - } - - case 1: { // inside transition zone - - if (original->L[y][x] < 32768.f) { - float factorx = localFactor; - factorx = 1.f - factorx; - float prov = original->L[y][x]; - - if (original->L[y][x] > ave) { - float kh = lco.ah * (original->L[y][x] / 327.68f) + lco.bh; - original->L[y][x] = ave + kh * (original->L[y][x] - ave); - } else { - float kl = lco.al * (original->L[y][x] / 327.68f) + 1.f; - original->L[y][x] = ave - kl * (ave - original->L[y][x]); - } - - float diflc = original->L[y][x] - prov; - diflc *= factorx; - transformed->L[y][x] = prov + diflc * fach * kch * falL; - - } else { - transformed->L[y][x] = original->L[y][x]; - } - - break; - } - - case 2: { // inside selection => no effect, keep original values - transformed->L[y][x] = original->L[y][x]; - } - } - } - } - } - delete origblur; -} - - static void calclight(float lum, float koef, float & lumnew, LUTf & lightCurveloc) //replace L-curve that does not work in local or bad { - /* - float blac = 0.3f; - - if (inv == false) { - blac = 0.99f; - } else { - if (koef < -90.f) { - blac = -0.069f * koef - 5.91f; - } - } - */ if (koef >= 0.f) { - // lumnew = lum + 0.2f * (33000.f - lum) * koef / 100.f; lumnew = lightCurveloc[lum]; } if (koef < 0.f) { lumnew = lightCurveloc[lum]; - /* - lumnew = lum + blac * lum * koef / 100.f;//0.999 instead of 0.2 - - if (lumnew < 0.f) { - float kc = lum / (lum - lumnew); - lumnew = lum + kc * 0.2f * lum * koef / 100.f; - - } - - // if (inv == false && koef == -100.f) { - */ if (koef == -100.f) { lumnew = 0.f; } @@ -5198,6 +4046,7 @@ static void calclight(float lum, float koef, float & lumnew, LUTf & lightCurvel } + void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) { //local sharp @@ -6176,7 +5025,7 @@ void ImProcFunctions::Exclude_Local(float moddE, float powdE, int sen, float **d } -void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, float **buflight, float **bufchro, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int sk) +void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, float **buflight, float **bufchro, float **buf_a_cat, float ** buf_b_cat, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, LabImage * difLab, const LabImage * const tmp1, int cx, int cy, int sk) { //local exposure and vibrance @@ -6238,6 +5087,8 @@ void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, fl int GW = transformed->W; int GH = transformed->H; + + LabImage *origblur = nullptr; origblur = new LabImage(GW, GH); @@ -6331,11 +5182,18 @@ void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, fl float cli = 1.f; float clc = 1.f; + float cla = 1.f; + float clb = 1.f; // if (lp.curvact == true) { cli = (buflight[loy - begy][lox - begx]); clc = (bufchro[loy - begy][lox - begx]); + if (senstype == 1) { + cla = buf_a_cat[loy - begy][lox - begx]; + clb = buf_b_cat[loy - begy][lox - begx]; + } + float aplus = (1.f - cli) / delhu; float bplus = 1.f - aplus * hueplus; float amoins = (cli - 1.f) / delhu; @@ -6346,8 +5204,21 @@ void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, fl float amoinsch = (clc - 1.f) / delhu; float bmoinsch = 1.f - amoinsch * huemoins; + float aplusa = (1.f - cla) / delhu; + float bplusa = 1.f - aplusa * hueplus; + float amoinsa = (cla - 1.f) / delhu; + float bmoinsa = 1.f - amoinsa * huemoins; + + float aplusb = (1.f - clb) / delhu; + float bplusb = 1.f - aplusb * hueplus; + float amoinsb = (clb - 1.f) / delhu; + float bmoinsb = 1.f - amoinsb * huemoins; + float realstr = 1.f; float realstrch = 1.f; + float realstra = 1.f; + float realstrb = 1.f; + //prepare shape detection float deltachro = fabs(rchro - chromaref); float deltahue = fabs(rhue - hueref); @@ -6420,17 +5291,23 @@ void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, fl if (rhue >= hueplus - delhu) { realstr = aplus * rhue + bplus; realstrch = aplusch * rhue + bplusch; + realstra = aplusa * rhue + bplusa; + realstrb = aplusb * rhue + bplusb; khu = apl * rhue + bpl; } else if (rhue < huemoins + delhu) { realstr = amoins * rhue + bmoins; realstrch = amoinsch * rhue + bmoinsch; + realstra = amoinsa * rhue + bmoinsa; + realstrb = amoinsb * rhue + bmoinsb; khu = amo * rhue + bmo; } else { realstr = cli; khu = 1.f; realstrch = clc; + realstra = cla; + realstrb = clb; } @@ -6439,17 +5316,23 @@ void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, fl if (rhue >= hueplus - delhu && rhue < hueplus) { realstr = aplus * rhue + bplus; realstrch = aplusch * rhue + bplusch; + realstra = aplusa * rhue + bplusa; + realstrb = aplusb * rhue + bplusb; khu = apl * rhue + bpl; } else if (rhue >= huemoins && rhue < huemoins + delhu) { realstr = amoins * rhue + bmoins; realstrch = amoinsch * rhue + bmoinsch; + realstra = amoinsa * rhue + bmoinsa; + realstrb = amoinsb * rhue + bmoinsb; khu = amo * rhue + bmo; } else { realstr = cli; khu = 1.f; realstrch = clc; + realstra = cla; + realstrb = clb; } @@ -6460,17 +5343,23 @@ void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, fl if (rhue >= hueplus - delhu && rhue < hueplus) { realstr = aplus * rhue + bplus; realstrch = aplusch * rhue + bplusch; + realstra = aplusa * rhue + bplusa; + realstrb = aplusb * rhue + bplusb; khu = apl * rhue + bpl; } else if (rhue >= huemoins && rhue < huemoins + delhu) { realstr = amoins * rhue + bmoins; realstrch = amoinsch * rhue + bmoinsch; + realstra = amoinsa * rhue + bmoinsa; + realstrb = amoinsb * rhue + bmoinsb; khu = amo * rhue + bmo; } else { realstr = cli; khu = 1.f; realstrch = clc; + realstra = cla; + realstrb = clb; } @@ -6479,17 +5368,23 @@ void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, fl if (rhue >= hueplus - delhu && rhue < hueplus) { realstr = aplus * rhue + bplus; realstrch = aplusch * rhue + bplusch; + realstra = aplusa * rhue + bplusa; + realstrb = aplusb * rhue + bplusb; khu = apl * rhue + bpl; } else if (rhue >= huemoins && rhue < huemoins + delhu) { realstr = amoins * rhue + bmoins; realstrch = amoinsch * rhue + bmoinsch; + realstra = amoinsa * rhue + bmoinsa; + realstrb = amoinsb * rhue + bmoinsb; khu = amo * rhue + bmo; } else { realstr = cli; khu = 1.f; realstrch = clc; + realstra = cla; + realstrb = clb; } @@ -6590,55 +5485,81 @@ void ImProcFunctions::Expo_vibr_Local(float moddE, float powdE, int senstype, fl case 1: { // inside transition zone float factorx = localFactor; - float difL; - difL = tmp1->L[loy - begy][lox - begx] - original->L[y][x]; - difL *= factorx * (100.f + realstr * falL) / 100.f; + // float difL; + difLab->L[loy - begy][lox - begx] = tmp1->L[loy - begy][lox - begx] - original->L[y][x]; + difLab->L[loy - begy][lox - begx] *= factorx * (100.f + realstr * falL) / 100.f; // difL *= kch * fach; - difL *= kch ; + difLab->L[loy - begy][lox - begx] *= kch ; - transformed->L[y][x] = original->L[y][x] + difL; - float difa, difb; + transformed->L[y][x] = original->L[y][x] + difLab->L[loy - begy][lox - begx]; + // float difa, difb; - difa = tmp1->a[loy - begy][lox - begx] - original->a[y][x]; - difb = tmp1->b[loy - begy][lox - begx] - original->b[y][x]; - difa *= factorx * (100.f + realstrch * falu * falL) / 100.f; - difb *= factorx * (100.f + realstrch * falu * falL) / 100.f; - difa *= kch * fach; - difb *= kch * fach; - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); + difLab->a[loy - begy][lox - begx] = tmp1->a[loy - begy][lox - begx] - original->a[y][x]; + difLab->b[loy - begy][lox - begx] = tmp1->b[loy - begy][lox - begx] - original->b[y][x]; + if (senstype != 1) { + difLab->a[loy - begy][lox - begx] *= factorx * (100.f + realstrch * falu * falL) / 100.f; + difLab->b[loy - begy][lox - begx] *= factorx * (100.f + realstrch * falu * falL) / 100.f; + } else { + difLab->a[loy - begy][lox - begx] *= factorx * (100.f + realstra * falu * falL) / 100.f; + difLab->b[loy - begy][lox - begx] *= factorx * (100.f + realstrb * falu * falL) / 100.f; + } + + difLab->a[loy - begy][lox - begx] *= kch * fach; + difLab->b[loy - begy][lox - begx] *= kch * fach; + transformed->a[y][x] = CLIPC(original->a[y][x] + difLab->a[loy - begy][lox - begx]); + transformed->b[y][x] = CLIPC(original->b[y][x] + difLab->b[loy - begy][lox - begx]); + + if (lp.showmaskexpmet == 1 && senstype == 1) { + transformed->a[y][x] = difLab->a[loy - begy][lox - begx]; + transformed->b[y][x] = difLab->b[loy - begy][lox - begx]; + transformed->L[y][x] = 12000.f + difLab->L[loy - begy][lox - begx]; + } break; } case 2: { // inside selection => full effect, no transition - float difL; + // float difL; - difL = tmp1->L[loy - begy][lox - begx] - original->L[y][x]; - difL *= (100.f + realstr * falL) / 100.f; + difLab->L[loy - begy][lox - begx] = tmp1->L[loy - begy][lox - begx] - original->L[y][x]; + difLab->L[loy - begy][lox - begx] *= (100.f + realstr * falL) / 100.f; // difL *= kch * fach; - difL *= kch; - transformed->L[y][x] = original->L[y][x] + difL; - float difa, difb; + difLab->L[loy - begy][lox - begx] *= kch; + transformed->L[y][x] = original->L[y][x] + difLab->L[loy - begy][lox - begx]; + // float difa, difb; - difa = tmp1->a[loy - begy][lox - begx] - original->a[y][x]; - difb = tmp1->b[loy - begy][lox - begx] - original->b[y][x]; - difa *= (100.f + realstrch * falu * falL) / 100.f; - difb *= (100.f + realstrch * falu * falL) / 100.f; - difa *= kch * fach; - difb *= kch * fach; + difLab->a[loy - begy][lox - begx] = tmp1->a[loy - begy][lox - begx] - original->a[y][x]; + difLab->b[loy - begy][lox - begx] = tmp1->b[loy - begy][lox - begx] - original->b[y][x]; - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); + if (senstype != 1) { + difLab->a[loy - begy][lox - begx] *= (100.f + realstrch * falu * falL) / 100.f; + difLab->b[loy - begy][lox - begx] *= (100.f + realstrch * falu * falL) / 100.f; + } else { + difLab->a[loy - begy][lox - begx] *= (100.f + realstra * falu * falL) / 100.f; + difLab->b[loy - begy][lox - begx] *= (100.f + realstrb * falu * falL) / 100.f; + } + difLab->a[loy - begy][lox - begx] *= kch * fach; + difLab->b[loy - begy][lox - begx] *= kch * fach; + + transformed->a[y][x] = CLIPC(original->a[y][x] + difLab->a[loy - begy][lox - begx]); + transformed->b[y][x] = CLIPC(original->b[y][x] + difLab->b[loy - begy][lox - begx]); + + if (lp.showmaskexpmet == 1 && senstype == 1) { + transformed->a[y][x] = difLab->a[loy - begy][lox - begx]; + transformed->b[y][x] = difLab->b[loy - begy][lox - begx]; + transformed->L[y][x] = 12000.f + difLab->L[loy - begy][lox - begx]; + } } } //} } + + } } @@ -6969,7 +5890,6 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm kdE = SQR(SQR(dE / dEsens)); } - // if (deltahue < 0.3f && (lp.qualcurvemet == 3 || lp.qualcurvemet == 5)) {//for very low differences with smal values of scope if (deltahue < 0.3f) {//for very low differences with smal values of scope kchchro = kch = pow(kch0, (1.f + kdE * moddE * (3.f - 10.f * deltahue)) * kkch); } @@ -7326,7 +6246,7 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm } - if (lp.ligh != 0.f && lp.curvact == false) { + if ((lp.ligh != 0.f || lp.cont != 0) && lp.curvact == false) { calclight(lumnew, lp.ligh, lumnew, lightCurveloc); //replace L-curve lightcont = lumnew; @@ -7340,40 +6260,37 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm // float flichrosl = 1.f; - if (lp.curvact && lp.ligh != 0.f) { + if (lp.curvact && (lp.ligh != 0.f || lp.cont != 0)) { flisl = ((100.f + realclighsl * falL * kchchro) / 100.f); //luma transition - // flisl = ((100.f + realclighsl) / 100.f); //luma transition } if (lp.curvact && lp.chro != 0.f) { realchro = realchroslid;//chroma transition - //realchro = 1.f; } if (lp.qualcurvemet >= 2) { fli = ((100.f + realcligh * falL) / 100.f); //luma transition - // fli = ((100.f + realcligh) / 100.f); //luma transition } float flicur = 1.f; if (lp.qualcurvemet != 0) { flicur = ((100.f + realcurv * factorx * falu * falL * kchchro) / 100.f); - // flicur = ((100.f + realcurv * factorx) / 100.f); } float fac = flicur * (100.f + factorx * realchro * falu * falL) / 100.f; //chroma factor transition - // float fac = flicur * (100.f + factorx * realchro) / 100.f; //chroma factor transition - //if(fac < 0.2f) fac = 0.2f; + float diflc = lightcont * fli * flisl - original->L[y][x]; - // float diflc = lightcont - original->L[y][x]; kdiff *= fach * kch; diflc *= kdiff ; diflc *= kch ; diflc *= factorx; //transition lightness - transformed->L[y][x] = CLIPL(1.f * (original->L[y][x] + diflc)); + transformed->L[y][x] = CLIPL((original->L[y][x] + diflc)); + if (lp.showmaskcolmet == 1) { + transformed->L[y][x] = 12000.f + diflc; //CLIPL((original->L[y][x] + diflc)); + } if (lochhCurve && lp.qualcurvemet >= 1 && HHutili) { float addh = 0.f; @@ -7391,7 +6308,6 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm if (lp.qualcurvemet >= 2) { addh = 0.01f * realhh * factorx; - } float newhr = rhue + addh; @@ -7406,10 +6322,19 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm transformed->a[y][x] = CLIPC(chromhr * sincosval.y * fac) ; transformed->b[y][x] = CLIPC(chromhr * sincosval.x * fac); + if (lp.showmaskcolmet == 1) { + transformed->a[y][x] = chromhr * sincosval.y * (fac - 1.f) ; + transformed->b[y][x] = chromhr * sincosval.x * (fac - 1.f); + } } else { transformed->a[y][x] = CLIPC(original->a[y][x] * fac) ; transformed->b[y][x] = CLIPC(original->b[y][x] * fac); + + if (lp.showmaskcolmet == 1) { + transformed->a[y][x] = original->a[y][x] * (fac - 1.f) ; + transformed->b[y][x] = original->b[y][x] * (fac - 1.f); + } } break; @@ -7452,7 +6377,7 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm } - if (lp.ligh != 0.f && lp.curvact == false) { + if ((lp.ligh != 0.f || lp.cont != 0.f) && lp.curvact == false) { calclight(lumnew, lp.ligh, lumnew, lightCurveloc); //replace L-curve lightcont = lumnew; @@ -7463,7 +6388,7 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm float fli = 1.f; float flisl = 1.f; - if (lp.curvact && lp.ligh != 0.f) { + if (lp.curvact && (lp.ligh != 0.f || lp.cont != 0)) { flisl = ((100.f + realclighsl * falL) / 100.f); //luma transition // flisl = ((100.f + realclighsl) / 100.f); //luma transition } @@ -7482,22 +6407,21 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm if (lp.qualcurvemet != 0) { flicur = ((100.f + realcurv * falu * falL * kchchro) / 100.f); - // flicur = ((100.f + realcurv) / 100.f); } float fac = flicur * (100.f + realchro * falu * falL) / 100.f; //chroma factor transition7 - // float fac = flicur * (100.f + realchro) / 100.f; //chroma factor transition7 - //if(fac < 0.2f) fac = 0.2f; float diflc = lightcont * fli * flisl - original->L[y][x]; - // float diflc = lightcont - original->L[y][x]; kdiff *= fach * kch; diflc *= kdiff ; diflc *= kch ; - transformed->L[y][x] = CLIPL(1.f * (original->L[y][x] + diflc)); + transformed->L[y][x] = CLIPL((original->L[y][x] + diflc)); + + if (lp.showmaskcolmet == 1) { + transformed->L[y][x] = 12000.f + diflc; //CLIPL((original->L[y][x] + diflc)); + } - // float newchro = sqrt (SQR (original->a[y][x]) + SQR (original->b[y][x])); if (lochhCurve && lp.qualcurvemet >= 1 && HHutili) { float addh = 0.f; @@ -7528,11 +6452,19 @@ void ImProcFunctions::ColorLight_Local(float moddE, float powdE, int call, LabIm transformed->a[y][x] = CLIPC(chromhr * sincosval.y * fac) ; transformed->b[y][x] = CLIPC(chromhr * sincosval.x * fac); + if (lp.showmaskcolmet == 1) { + transformed->a[y][x] = chromhr * sincosval.y * (fac - 1.f) ; + transformed->b[y][x] = chromhr * sincosval.x * (fac - 1.f); + } + } else { - - transformed->a[y][x] = CLIPC(original->a[y][x] * fac) ; transformed->b[y][x] = CLIPC(original->b[y][x] * fac); + + if (lp.showmaskcolmet == 1) { + transformed->a[y][x] = original->a[y][x] * (fac - 1.f) ; + transformed->b[y][x] = original->b[y][x] * (fac - 1.f); + } } @@ -7949,7 +6881,7 @@ void ImProcFunctions::InverseColorLight_Local(const struct local_params & lp, LU if (lp.sens < 75.f) { float lightcont; - if (lp.ligh != 0.f) { + if ((lp.ligh != 0.f || lp.cont != 0)) { calclight(lumnew, lp.ligh, lumnew, lightCurveloc); //replace L-curve lightcont = lumnew; @@ -7976,7 +6908,7 @@ void ImProcFunctions::InverseColorLight_Local(const struct local_params & lp, LU float fac = (100.f + factorx * lp.chro) / 100.f; //chroma factor transition float lumnew = original->L[y][x]; - if (lp.ligh != 0.f) { + if ((lp.ligh != 0.f || lp.cont != 0)) { calclight(original->L[y][x], lp.ligh, lumnew, lightCurveloc); } @@ -8001,7 +6933,7 @@ void ImProcFunctions::InverseColorLight_Local(const struct local_params & lp, LU float lightcont; - if (lp.ligh != 0.f) { + if ((lp.ligh != 0.f || lp.cont != 0)) { calclight(lumnew, lp.ligh, lumnew, lightCurveloc); //replace L-curve lightcont = lumnew; @@ -8025,7 +6957,7 @@ void ImProcFunctions::InverseColorLight_Local(const struct local_params & lp, LU } else { - if (lp.ligh != 0.f) { + if ((lp.ligh != 0.f || lp.cont != 0)) { calclight(original->L[y][x], lp.ligh, lumnew, lightCurveloc); } @@ -8046,12 +6978,48 @@ void ImProcFunctions::InverseColorLight_Local(const struct local_params & lp, LU } -void ImProcFunctions::calc_ref(int sp, LabImage * original, LabImage * transformed, int cx, int cy, int oW, int oH, int sk, double & huerefblur, double & hueref, double & chromaref, double & lumaref, double & sobelref) +void ImProcFunctions::calc_ref(int sp, LabImage * original, LabImage * transformed, int cx, int cy, int oW, int oH, int sk, double & huerefblur, double & hueref, double & chromaref, double & lumaref, double & sobelref, LUTu & histogram) { 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); + int del = 3; + int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone + int bfw = int (lp.lx + lp.lxL) + del; + int begy = lp.yc - lp.lyT; + int begx = lp.xc - lp.lxL; + int yEn = lp.yc + lp.ly; + int xEn = lp.xc + lp.lx; +//claculate histogram for area selected +#ifdef _OPENMP + const int numThreads = min(max(transformed->W * transformed->H / (int)histogram.getSize(), 1), omp_get_max_threads()); + #pragma omp parallel num_threads(numThreads) if(numThreads>1) +#endif + { + LUTu lhist16thrloc(histogram.getSize()); + lhist16thrloc.clear(); +#ifdef _OPENMP + #pragma omp for nowait +#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) { + int pos = (int)(original->L[y][x]); + lhist16thrloc[pos]++; + } + } + + +#ifdef _OPENMP + #pragma omp critical +#endif + histogram += lhist16thrloc; + } // double precision for large summations double aveA = 0.; @@ -8636,7 +7604,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu float dhuelc = ared * lp.senslc + bred; //delta hue local contrast float dhuesf = ared * lp.senssf + bred; //delta hue soft light - + float dhuecb = ared * lp.senscb + bred; //delta hue cbdl float dhueexclu = ared * lp.sensexclu + bred; //delta hue exclude @@ -9834,7 +8802,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu // but with qualmet = 2 (default for best quality) we must denoise chroma with little values to prevent artifacts due to variations of Hue // but if user select volontary denoise, it is that choice the good (prioritary) bool execdenoi = false ; - bool execcolor = (lp.chro != 0.f || lp.ligh != 0.f || lp.cont != 0.f); // only if one slider ore more is engaged + bool execcolor = (lp.chro != 0.f || lp.ligh != 0.f || lp.cont != 0); // only if one slider ore more is engaged bool execbdl = (lp.mulloc[0] != 1.f || lp.mulloc[1] != 1.f || lp.mulloc[2] != 1.f || lp.mulloc[3] != 1.f || lp.mulloc[4] != 1.f) ;//only if user want cbdl execdenoi = noiscfactiv && ((lp.colorena && execcolor) || (lp.tonemapena && lp.strengt != 0.f) || (lp.cbdlena && execbdl) || (lp.sfena && lp.strng > 0.f) || (lp.lcena && lp.lcamount > 0.f) || (lp.sharpena && lp.shrad > 0.42) || (lp.retiena && lp.str > 0.f) || (lp.exposena && lp.expcomp != 0.f) || (lp.expvib && lp.past != 0.f)); @@ -10854,628 +9822,8 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu } - - -//local color and light - - if (!lp.inv && (lp.chro != 0 || lp.ligh != 0.f || lp.qualcurvemet != 0 || lp.war != 0) && lp.colorena) { // || lllocalcurve)) { //interior ellipse renforced lightness and chroma //locallutili - // double huerefspot = 0., chromarefspot = 0., lumarefspot = 0.; - // int spotSi = 1 + 2 * max (1, lp.cir / sk); - /* - if (!lastcutpast && loc.cutpast) { - spotbuffer = new LabImage (spotSi, spotSi);//buffer for data in zone limit - - - copy_ref (call, 1, spotbuffer, original, transformed, sx, sy, cx, cy, oW, oH, fw, fh, sk, lp, huerefspot, chromarefspot, lumarefspot); - loc.centerXbuf = loc.centerX; - loc.centerYbuf = loc.centerY; - lastcutpast = true; - } - */ - /* - if (lastcutpast && !loc.cutpast) { - - paste_ref (call, 1, spotbuffer, original, transformed, sx, sy, cx, cy, oW, oH, fw, fh, sk, lp, huerefspot, chromarefspot, lumarefspot); - loc.centerXbuf = 0 ; - loc.centerYbuf = 0 ; - lastcutpast = false; - delete spotbuffer; - - } - */ - float hueplus = hueref + dhue; - float huemoins = hueref - dhue; - // float ddhue = 0.f; - - //printf("hueplus=%f huemoins=%f dhu=%f\n", hueplus, huemoins, dhue); - if (hueplus > rtengine::RT_PI) { - hueplus = hueref + dhue - 2.f * rtengine::RT_PI; - } - - if (huemoins < -rtengine::RT_PI) { - huemoins = hueref - dhue + 2.f * rtengine::RT_PI; - } - - LabImage *bufcolorig = nullptr; - - float chpro = 1.f; - float cligh = 1.f; - float clighL = 1.f; - - int bfh = 0.f, bfw = 0.f; - bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone - bfw = int (lp.lx + lp.lxL) + del; - JaggedArray buflight(bfw, bfh); - JaggedArray bufchro(bfw, bfh); - JaggedArray buflightslid(bfw, bfh); - JaggedArray bufchroslid(bfw, bfh); - JaggedArray bufhh(bfw, bfh); - - float adjustr = 1.0f; - -//adapt chroma to working profile - if (params->icm.workingProfile == "ProPhoto") { - adjustr = 1.2f; // 1.2 instead 1.0 because it's very rare to have C>170.. - } else if (params->icm.workingProfile == "Adobe RGB") { - adjustr = 1.8f; - } else if (params->icm.workingProfile == "sRGB") { - adjustr = 2.0f; - } else if (params->icm.workingProfile == "WideGamut") { - adjustr = 1.2f; - } else if (params->icm.workingProfile == "Beta RGB") { - adjustr = 1.4f; - } else if (params->icm.workingProfile == "BestRGB") { - adjustr = 1.4f; - } else if (params->icm.workingProfile == "BruceRGB") { - adjustr = 1.8f; - } - - - - - if (call <= 3) { //simpleprocess, dcrop, improccoordinator - bufcolorig = new LabImage(bfw, bfh); //buffer for data in zone limit - - - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int ir = 0; ir < bfh; ir++) //fill with 0 - for (int jr = 0; jr < bfw; jr++) { - bufcolorig->L[ir][jr] = 0.f; - bufcolorig->a[ir][jr] = 0.f; - bufcolorig->b[ir][jr] = 0.f; - bufchro[ir][jr] = 0.f; - bufchroslid[ir][jr] = 0.f; - buflightslid[ir][jr] = 0.f; - buflight[ir][jr] = 0.f; - bufhh[ir][jr] = 0.f; - } - - /* - int yStart = lp.yc - lp.lyT - cy; - int yEnd = lp.yc + lp.ly - cy; - int xStart = lp.xc - lp.lxL - cx; - int xEnd = lp.xc + lp.lx - cx; - - // int begx = int (lp.xc - lp.lxL); - // int begy = int (lp.yc - lp.lyT); - - */ - - int begy = lp.yc - lp.lyT; - int begx = lp.xc - lp.lxL; - int yEn = lp.yc + lp.ly; - int xEn = lp.xc + lp.lx; - /* - int yStart = lp.yc - lp.lyT - cy; - int yEnd = lp.yc + lp.ly - cy; - int xStart = lp.xc - lp.lxL - cx; - int xEnd = lp.xc + lp.lx - cx; - //there is a bug in calculation==> outof limits ==> crash - printf("cy=%i cx=%i begy=%i begx=%i yS=%i yE=%i xS=%i xE=%i tH=%i tW=%i\n", cy, cx, begy, begx, yStart, yEnd, xStart, xEnd, transformed->H, transformed->W ); - int ymax = min(transformed->H, yEnd); - int xmax = min(transformed->W, xEnd); - - #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) - #endif - - for (int y = yStart; y < ymax ; y++) { - int loy = cy + y; - - for (int x = xStart, lox = cx + x; x < xmax; x++, lox++) { - bufcolorig->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas - bufcolorig->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas - bufcolorig->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas - } - } - */ - - /* - printf("Pastbef \n"); - - if (lastcutpast && !loc.cutpast) { - - printf("Past \n"); - int nab = 0; - int spotSize = max (1, lp.cir / sk); - - for (int y = max (cy, (int) (lp.yc - spotSize)); y < min (transformed->H + cy, (int) (lp.yc + spotSize + 1)); y++) { - for (int x = max (cx, (int) (lp.xc - spotSize)); x < min (transformed->W + cx, (int) (lp.xc + spotSize + 1)); x++) { - int yb = max (cy, (int) (lp.yc - spotSize)); - int ye = min (transformed->H + cy, (int) (lp.yc + spotSize + 1)); - int xb = max (cx, (int) (lp.xc - spotSize)); - int xe = min (transformed->W + cx, (int) (lp.xc + spotSize + 1)); - int z = y - yb; - int u = x - xb; - original->L[y - cy][x - cx] = spotbuffer->L[z][u]; - original->a[y - cy][x - cx] = spotbuffer->a[z][u]; - original->b[y - cy][x - cx] = spotbuffer->b[z][u]; - - nab++; - } - } - - // loc.centerXbuf = 0 ; - // loc.centerYbuf = 0 ; - lastcutpast = false; - - delete spotbuffer; - } - printf("PastAft \n"); - - - int spotSize = max (1, lp.cir / sk); - */ - -#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 yb = max (cy, (int) (lp.yc - spotSize)); - // int xb = max (cx, (int) (lp.xc - spotSize)); - // int z = y - yb; - // int u = x - xb; - - if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { - bufcolorig->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas - bufcolorig->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas - bufcolorig->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas - chpro = 0.f; - - //Chroma curve - if (cclocalcurve && lp.qualcurvemet != 0) { // C=f(C) curve - float chromat = sqrt(SQR(bufcolorig->a[loy - begy][lox - begx]) + SQR(bufcolorig->b[loy - begy][lox - begx])); - float ch; - float ampli = 25.f; - ch = (cclocalcurve[chromat * adjustr ]) / ((chromat + 0.00001f) * adjustr); //ch between 0 and 0 50 or more - - // if (ch <= 1.f) {//convert data curve near values of slider -100 + 100, to be used after to detection shape - // chpro = 99.f * ch - 99.f; - // } else { - chpro = CLIPCHRO(ampli * ch - ampli); //ampli = 25.f arbitrary empirical coefficient between 5 and 50 - // } - - bufchro[loy - begy][lox - begx] = chpro; - - } - - chpro = 0.f; - - - if (lp.chro != 0.f && lp.curvact) { - // process to improve eg same as in Lab adjustements - float ch; - float ampli = 70.f; - // ch = (1.f + 0.01f * lp.chro) * (chromat * adjustr) / ((chromat + 0.00001f) * adjustr); //ch between 0 and 0 50 or more - ch = (1.f + 0.01f * lp.chro) ; //* (chromat * adjustr) / ((chromat + 0.00001f) * adjustr); //ch between 0 and 0 50 or more - - if (ch <= 1.f) {//convert data curve near values of slider -100 + 100, to be used after to detection shape - chpro = 99.f * ch - 99.f; - } else { - chpro = CLIPCHRO(ampli * ch - ampli); //ampli = 25.f arbitrary empirical coefficient between 5 and 50 - } - - bufchroslid[loy - begy][lox - begx] = chpro; - - } - - if (lochhCurve && lp.qualcurvemet >= 2 && HHutili) { - float hhforcurv = xatan2f(bufcolorig->b[loy - begy][lox - begx], bufcolorig->a[loy - begy][lox - begx]); - - float valparam = float ((lochhCurve[500.f * Color::huelab_to_huehsv2(hhforcurv)] - 0.5f)); //get H=f(H) 1.7 optimisation ! - float ddhue = CLIPRET(200.f * valparam); - bufhh[loy - begy][lox - begx] = ddhue;//valparamdh; // - - } - - //slider lightness - clighL = 0.f; - - if (lp.ligh != 0.f && lp.curvact) { - float lL; - float lighLnew; - float amplil = 140.f; - float lighL = bufcolorig->L[loy - begy][lox - begx]; - calclight(lighL, lp.ligh, lighLnew, lightCurveloc); //replace L-curve - lL = lighLnew / lighL; - - if (lL <= 1.f) {//convert data curve near values of slider -100 + 100, to be used after to detection shape - clighL = 99.f * lL - 99.f; - } else { - clighL = CLIPLIG(amplil * lL - amplil); //ampli = 25.f arbitrary empirical coefficient between 5 and 150 - } - - buflightslid[loy - begy][lox - begx] = clighL; - // printf("cl=%f ", clighL); - - } - - cligh = 0.f; - - //luma curve - if (lllocalcurve && lp.qualcurvemet >= 2) {// L=f(L) curve enhanced - float lh; - float amplil = 25.f; - float lighn = bufcolorig->L[loy - begy][lox - begx]; - lh = (lllocalcurve[lighn * 1.9f]) / ((lighn + 0.00001f) * 1.9f) ; // / ((lighn) / 1.9f) / 3.61f; //lh between 0 and 0 50 or more - - // printf("lh=%f ", lh); - // if (lh <= 1.f) {//convert data curve near values of slider -100 + 100, to be used after to detection shape - // cligh = 0.3f * (100.f * lh - 100.f);//0.3 reduce sensibility - // } else { - // cligh = CLIPLIG(amplil * lh - amplil); - cligh = CLIPLIG(amplil * lh - amplil); - // } - - buflight[loy - begy][lox - begx] = cligh; - // printf("cli=%f ", cligh); - } - } - } - - if (lp.qualcurvemet >= 4) { - JaggedArray blend(bfw, bfh); - float contrastf = lp.sensexclu / 100.f; - //LabImage * tmpsob; - // tmpsob = new LabImage(bfw, bfh); - // SobelCannyLuma(tmpsob->L, bufcolorig->L, bfw, bfh, 1.f); - - buildBlendMask(bufcolorig->L, blend, bfw, bfh, contrastf, 1.f, true); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < bfh; ++i) { - for (int j = 0; j < bfw; ++j) { - if (blend[i][j] > 0.05f) { - blend[i][j] = 1.22361f * sqrt(blend[i][j]) - 0.22361f; - } - - buflight[i][j] = intp(blend[i][j], buflight[i][j], 0.f);// tmpsob->L[i][j]); - bufchro[i][j] = intp(blend[i][j], bufchro[i][j], 0.f); //tmpsob->L[i][j] ); - } - } - - // delete tmpsob; - } - - - } - - // printf("callCOLOR= %i sp=%i hueref=%f chromaref=%f lumaref=%f\n", call, sp, hueref, chromaref, lumaref); - - ColorLight_Local(moddE, powdE, call, bufcolorig, buflight, bufchro, bufchroslid, bufhh, buflightslid, LHutili, HHutili, hueplus, huemoins, hueref, dhue, chromaref, lumaref, lllocalcurve, loclhCurve, lochhCurve, lightCurveloc, lp, original, transformed, cx, cy, sk); - - if (call <= 3) { - - delete bufcolorig; - - // delete bufcoltra; - - } - } -//inverse - else if (lp.inv && (lp.chro != 0 || lp.ligh != 0.f) && lp.colorena) { - float hueplus = hueref + dhue; - float huemoins = hueref - dhue; - // float ddhue = 0.f; - - //printf("hueplus=%f huemoins=%f dhu=%f\n", hueplus, huemoins, dhue); - if (hueplus > rtengine::RT_PI) { - hueplus = hueref + dhue - 2.f * rtengine::RT_PI; - } - - if (huemoins < -rtengine::RT_PI) { - huemoins = hueref - dhue + 2.f * rtengine::RT_PI; - } - - InverseColorLight_Local(lp, lightCurveloc, original, transformed, cx, cy, hueplus, huemoins, hueref, dhue, chromaref, lumaref, sk); - } - - - if (!lp.inv && lp.cont != 0 && lp.colorena && lp.ligh > -99) { //contrast interior ellipse - const float pm = lp.cont < 0.f ? -1.f : 1.f; - float hueplus = hueref + dhue; - float huemoins = hueref - dhue; - - if (hueplus > rtengine::RT_PI) { - hueplus = hueref + dhue - 2.f * rtengine::RT_PI; - } - - if (huemoins < -rtengine::RT_PI) { - huemoins = hueref - dhue + 2.f * rtengine::RT_PI; - } - - LabImage *bufcontorig = nullptr; - int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone - int bfw = int (lp.lx + lp.lxL) + del; - JaggedArray buflightc(bfw, bfh); - - float clighc = 0.f; - const float localtype = lumaref; - // const float localtype = ave; - float reducac; - float corered; - - if (lp.sens < 30.f) { - reducac = 0.2f * (lp.sens / 100.f); - } else { - float areduc = 0.6285714f; //0.44f/0.7f; - float breduc = 0.5f - areduc; - reducac = areduc * (lp.sens / 100.f) + breduc; - } - - const float realcox = lco.dx, realcoy = lco.dy; - - lco.alsup = (-realcox) / (localtype / 2.f); - lco.blsup = -lco.alsup * localtype; - lco.alsup2 = (realcoy) / (50.f - localtype / 2.f); - lco.blsup2 = -lco.alsup2 * localtype; - lco.alsup3 = (realcoy) / (localtype / 2.f - 50.f); - lco.blsup3 = -lco.alsup3 * 100.f; - lco.aDY = realcoy; - - lco.alinf = realcox / (localtype / 2.f); - const float vi = (localtype / 2.f) / 100.f; - const float vinf = (50.f + localtype / 2.f) / 100.f; - ImProcFunctions::secondeg_begin(reducac, vi, lco.aa, lco.bb); //parabolic - ImProcFunctions::secondeg_end(reducac, vinf, lco.aaa, lco.bbb, lco.ccc); //parabolic - - if (call <= 3) { //simpleprocess, dcrop, improccoordinator - bufcontorig = new LabImage(bfw, bfh); //buffer for data in zone limit - - - - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int ir = 0; ir < bfh; ir++) //fill with 0 - for (int jr = 0; jr < bfw; jr++) { - bufcontorig->L[ir][jr] = 0.f; - // bufcontorig->a[ir][jr] = 0.f; - // bufcontorig->b[ir][jr] = 0.f; - buflightc[ir][jr] = 0.f; - - - } - - float localty; - localty = localtype; - - int begy = lp.yc - lp.lyT; - int begx = lp.xc - lp.lxL; - int yEn = lp.yc + lp.ly; - int xEn = lp.xc + lp.lx; - -#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) { - bufcontorig->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas - - //slider contrast - clighc = 1.f; - corered = 0.f; - - - if (lp.cont != 0.f && lp.curvact) { - - float cL; - float amplil = 150.f; - float prov100 = bufcontorig->L[loy - begy][lox - begx] / 32768.f; - float prov = prov100 * 100.f; - cL = 1.f; - - if (prov > localty) { - if (prov >= localty && prov < 50.f + localty / 2.f) { - float core = (lco.alsup2 * prov + lco.blsup2) ; - corered = prov + pm * (prov - localty) * (core); - } else { - float core = lco.aDY * (lco.aaa * prov100 * prov100 + lco.bbb * prov100 + lco.ccc); - corered = prov + pm * (prov - localty) * (core); - - } - } else { - if (2.f * prov > localty && prov < localty) { - float core = (lco.alsup * prov + lco.blsup) ; - corered = prov - pm * (localty - prov) * core; - } else if (2.f * prov <= localty) { - float core = prov * lco.alinf * (lco.aa * prov100 * prov100 + lco.bb * prov100); - corered = prov - pm * (localty - prov) * core; - - } - } - - cL = corered / prov; - - if (cL <= 1.f) {//convert data curve near values of slider -100 + 100, to be used after to detection shape - clighc = 99.f * cL - 99.f; - } else { - clighc = CLIPLIG(amplil * cL - amplil); //arbitrary empirical coefficient between 5 and 150 - } - - buflightc[loy - begy][lox - begx] = clighc; - - } - } - } - - } - - Contrast_Local(powdE, call, buflightc, hueplus, huemoins, hueref, dhue, chromaref, pm, lco, lumaref, lp, original, transformed, cx, cy, sk); - - if (call <= 3) { - - delete bufcontorig; - } - - - } else if (lp.inv && lp.cont != 0 && lp.colorena && lp.ligh > -99) { - float hueplus = hueref + dhue; - float huemoins = hueref - dhue; - - if (hueplus > rtengine::RT_PI) { - hueplus = hueref + dhue - 2.f * rtengine::RT_PI; - } - - if (huemoins < -rtengine::RT_PI) { - huemoins = hueref - dhue + 2.f * rtengine::RT_PI; - } - - float multL = (float)lp.cont * (maxl - 1.f) / 100.f + 1.f; - float multH = (float) lp.cont * (maxh - 1.f) / 100.f + 1.f; - - lco.ah = (multH - 1.f) / (av - 100.f); //av ==> lumaref - lco.bh = 1.f - 100.f * lco.ah; - lco.al = (multL - 1.f) / av; - lco.bl = 1.f; - InverseContrast_Local(ave, lco, lp, hueplus, huemoins, hueref, dhue, chromaref, lumaref, original, transformed, cx, cy, sk); - - } - - -// end contrast interior and exterior - -//exposure and cat02 - if (lp.war != 0 && lp.exposena) {//move cat02WB to exposure ==> reduce color artifacts - float hueplus = hueref + dhueex; - float huemoins = hueref - dhueex; - // float ddhue = 0.f; - - if (hueplus > rtengine::RT_PI) { - hueplus = hueref + dhueex - 2.f * rtengine::RT_PI; - } - - if (huemoins < -rtengine::RT_PI) { - huemoins = hueref - dhueex + 2.f * rtengine::RT_PI; - } - - int bfh = 0.f, bfw = 0.f; - bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone - bfw = int (lp.lx + lp.lxL) + del; - - LabImage *bufcat02 = nullptr; - LabImage *bufcat02fin = nullptr; - - JaggedArray buflightcat(bfw, bfh, true); - JaggedArray buf_a_cat(bfw, bfh, true); - JaggedArray buf_b_cat(bfw, bfh, true); - - bufcat02 = new LabImage(bfw, bfh); //buffer for data in zone limit - bufcat02fin = new LabImage(bfw, bfh); //buffer for data in zone limit - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int ir = 0; ir < bfh; ir++) //fill with 0 - for (int jr = 0; jr < bfw; jr++) { - bufcat02->L[ir][jr] = 0.f; - bufcat02->a[ir][jr] = 0.f; - bufcat02->b[ir][jr] = 0.f; - bufcat02fin->L[ir][jr] = 0.f; - bufcat02fin->a[ir][jr] = 0.f; - bufcat02fin->b[ir][jr] = 0.f; - } - - int begy = lp.yc - lp.lyT; - int begx = lp.xc - lp.lxL; - int yEn = lp.yc + lp.ly; - int xEn = lp.xc + lp.lx; - -#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) { - bufcat02->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas - bufcat02->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas - bufcat02->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas - } - } - - ImProcFunctions::ciecamloc_02float(sp, bufcat02, bufcat02fin); - -#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) { - float rL; - rL = CLIPRET((bufcat02fin->L[loy - begy][lox - begx] - bufcat02->L[loy - begy][lox - begx]) / 328.f); - buflightcat[loy - begy][lox - begx] = rL; - - float rA; - rA = CLIPRET((bufcat02fin->a[loy - begy][lox - begx] - bufcat02->a[loy - begy][lox - begx]) / 328.f); - buf_a_cat[loy - begy][lox - begx] = rA; - - - float rB; - rB = CLIPRET((bufcat02fin->b[loy - begy][lox - begx] - bufcat02->b[loy - begy][lox - begx]) / 328.f); - buf_b_cat[loy - begy][lox - begx] = rB; - - } - } - - cat02_Local(moddE, powdE, buflightcat, buf_a_cat, buf_b_cat, hueplus, huemoins, hueref, dhueex, chromaref, lumaref, lp, original, transformed, bufcat02fin, cx, cy, sk); - - - - delete bufcat02; - delete bufcat02fin; - - } - - - - if (lp.exposena && (lp.expcomp != 0.f || (exlocalcurve && localexutili))) { //interior ellipse renforced lightness and chroma //locallutili +/* + if (lp.exposena && (lp.expcomp != 0.f || lp.war != 0 || (exlocalcurve && localexutili))) { //interior ellipse renforced lightness and chroma //locallutili float hueplus = hueref + dhuev; float huemoins = hueref - dhuev; @@ -11491,6 +9839,8 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu LabImage *bufexporig = nullptr; LabImage *bufexpfin = nullptr; LabImage *bufexptemp = nullptr; + LabImage *difLab = nullptr; + LabImage *bufcat02fin = nullptr; int bfh = 0.f, bfw = 0.f; bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone @@ -11498,6 +9848,8 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu JaggedArray buflight(bfw, bfh); JaggedArray bufl_ab(bfw, bfh); JaggedArray buflightcurv(bfw, bfh); + JaggedArray buf_a_cat(bfw, bfh, true); + JaggedArray buf_b_cat(bfw, bfh, true); if (call <= 3) { //simpleprocess, dcrop, improccoordinator @@ -11506,6 +9858,8 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu bufexporig = new LabImage(bfw, bfh); //buffer for data in zone limit bufexpfin = new LabImage(bfw, bfh); //buffer for data in zone limit bufexptemp = new LabImage(bfw, bfh); //buffer for data in zone limit + difLab = new LabImage(bfw, bfh); //buffer for data in zone limit + bufcat02fin = new LabImage(bfw, bfh); //buffer for data in zone limit #ifdef _OPENMP @@ -11523,17 +9877,21 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu bufexpfin->L[ir][jr] = 0.f; bufexpfin->a[ir][jr] = 0.f; bufexpfin->b[ir][jr] = 0.f; + bufcat02fin->L[ir][jr] = 0.f; + bufcat02fin->a[ir][jr] = 0.f; + bufcat02fin->b[ir][jr] = 0.f; buflight[ir][jr] = 0.f; bufl_ab[ir][jr] = 0.f; buflightcurv[ir][jr] = 0.f; - - + buf_a_cat[ir][jr] = 0.f; + buf_b_cat[ir][jr] = 0.f; } int begy = lp.yc - lp.lyT; int begx = lp.xc - lp.lxL; int yEn = lp.yc + lp.ly; int xEn = lp.xc + lp.lx; + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -11551,11 +9909,13 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu bufexptemp->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas bufexptemp->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas bufexptemp->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas - + bufexpfin->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas + bufexpfin->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas + bufexpfin->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas } } - +//to do Modulate bufexporig and bufexptemp with blend L, H, C and masks if (exlocalcurve && localexutili) {// L=f(L) curve enhanced @@ -11590,6 +9950,24 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu ImProcFunctions::exlabLocal(lp, bfh, bfw, bufexporig, bufexpfin, hltonecurveloc, shtonecurveloc, tonecurveloc); } + //cat02 + if (params->locallab.spots.at(sp).warm != 0) { + ImProcFunctions::ciecamloc_02float(sp, bufexpfin, bufcat02fin); + } else { +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + bufcat02fin->L[ir][jr] = bufexpfin->L[ir][jr]; + bufcat02fin->a[ir][jr] = bufexpfin->a[ir][jr]; + bufcat02fin->b[ir][jr] = bufexpfin->b[ir][jr]; + } + } + + + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -11602,16 +9980,24 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { float rL; - rL = CLIPRET((bufexpfin->L[loy - begy][lox - begx] - bufexporig->L[loy - begy][lox - begx]) / 328.f); + rL = CLIPRET((bufcat02fin->L[loy - begy][lox - begx] - bufexporig->L[loy - begy][lox - begx]) / 328.f); buflight[loy - begy][lox - begx] = rL; + float rA; + rA = CLIPRET((bufcat02fin->a[loy - begy][lox - begx] - bufexporig->a[loy - begy][lox - begx]) / 328.f); + buf_a_cat[loy - begy][lox - begx] = rA; + + + float rB; + rB = CLIPRET((bufcat02fin->b[loy - begy][lox - begx] - bufexporig->b[loy - begy][lox - begx]) / 328.f); + buf_b_cat[loy - begy][lox - begx] = rB; } } - Expo_vibr_Local(moddE, powdE, 1, buflight, bufl_ab, hueplus, huemoins, hueref, dhueex, chromaref, lumaref, lp, original, transformed, bufexpfin, cx, cy, sk); - //call Expo_vibr_Local with first parameter = 1 for exposure + Expo_vibr_Local(moddE, powdE, 1, buflight, bufl_ab, buf_a_cat, buf_b_cat, hueplus, huemoins, hueref, dhueex, chromaref, lumaref, lp, original, transformed, difLab, bufcat02fin, cx, cy, sk); + //view mask } if (call <= 3) { @@ -11619,10 +10005,12 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu delete bufexporig; delete bufexpfin; delete bufexptemp; + delete difLab; + delete bufcat02fin; } } - +*/ //vibrance @@ -11644,6 +10032,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu LabImage *bufexporig = nullptr; LabImage *bufexpfin = nullptr; + LabImage *difLab = nullptr; int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone int bfw = int (lp.lx + lp.lxL) + del; @@ -11657,6 +10046,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu bufexporig = new LabImage(bfw, bfh); //buffer for data in zone limit bufexpfin = new LabImage(bfw, bfh); //buffer for data in zone limit + difLab = new LabImage(bfw, bfh); //buffer for data in zone limit #ifdef _OPENMP @@ -11730,7 +10120,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu } } - Expo_vibr_Local(moddE, powdE, 2, buflight, bufl_ab, hueplus, huemoins, hueref, dhuev, chromaref, lumaref, lp, original, transformed, bufexpfin, cx, cy, sk); + Expo_vibr_Local(moddE, powdE, 2, buflight, bufl_ab, nullptr, nullptr, hueplus, huemoins, hueref, dhuev, chromaref, lumaref, lp, original, transformed, difLab, bufexpfin, cx, cy, sk); //call Expo_vibr_Local with first parameter = 2 for vibrance } @@ -11739,6 +10129,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu delete bufexporig; delete bufexpfin; + delete difLab; } @@ -12001,7 +10392,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu //end cbdl_Local // soft light - if (lp.strng > 0.f && call < 3 && lp.sfena) { + if (lp.strng > 0.f && call < 3 && lp.sfena) { float hueplus = hueref + dhuesf; float huemoins = hueref - dhuesf; @@ -12016,6 +10407,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu LabImage *bufexporig = nullptr; LabImage *bufexpfin = nullptr; + LabImage *difLab = nullptr; int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone int bfw = int (lp.lx + lp.lxL) + del; @@ -12029,6 +10421,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu bufexporig = new LabImage(bfw, bfh); //buffer for data in zone limit bufexpfin = new LabImage(bfw, bfh); //buffer for data in zone limit + difLab = new LabImage(bfw, bfh); //buffer for data in zone limit #ifdef _OPENMP @@ -12100,7 +10493,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu } } - Expo_vibr_Local(moddE, powdE, 3, buflight, bufl_ab, hueplus, huemoins, hueref, dhuesf, chromaref, lumaref, lp, original, transformed, bufexpfin, cx, cy, sk); + Expo_vibr_Local(moddE, powdE, 3, buflight, bufl_ab, nullptr, nullptr, hueplus, huemoins, hueref, dhuesf, chromaref, lumaref, lp, original, transformed, difLab, bufexpfin, cx, cy, sk); } @@ -12108,6 +10501,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu delete bufexporig; delete bufexpfin; + delete difLab; } @@ -12204,10 +10598,10 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu // } //sharpen only square area instaed of all image - ImProcFunctions::deconvsharpeningloc(bufsh, hbuffer, bfw, bfh, loctemp, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius / 100., params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast,(double)params->locallab.spots.at(sp).sharblur / 100.); + ImProcFunctions::deconvsharpeningloc(bufsh, hbuffer, bfw, bfh, loctemp, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius / 100., params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast, (double)params->locallab.spots.at(sp).sharblur / 100.); } else { //call from dcrop.cc - ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, bfw, bfh, loctemp, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius / 100., params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast,(double)params->locallab.spots.at(sp).sharblur / 100.); + ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, bfw, bfh, loctemp, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius / 100., params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast, (double)params->locallab.spots.at(sp).sharblur / 100.); } @@ -12230,7 +10624,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu int GH = original->H; JaggedArray loctemp(GW, GH); - ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, GW, GH, loctemp, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius / 100., params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast,(double)params->locallab.spots.at(sp).sharblur / 100.); + ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, GW, GH, loctemp, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius / 100., params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast, (double)params->locallab.spots.at(sp).sharblur / 100.); float hueplus = hueref + dhuesha; float huemoins = hueref - dhuesha; @@ -12315,11 +10709,12 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu //calc dehaze Imagefloat *tmpImage = nullptr; - if(lp.dehaze > 0) { + + if (lp.dehaze > 0) { tmpImage = new Imagefloat(bfw, bfh); lab2rgb(*bufreti, *tmpImage, params->icm.workingProfile); - float deha = LIM01(float(0.9f * lp.dehaze + 0.3f*lp.str) / 100.f * 0.9f); - float depthcombi = 0.3f*params->locallab.spots.at(sp).neigh + 0.15f * (500.f - params->locallab.spots.at(sp).vart); + float deha = LIM01(float(0.9f * lp.dehaze + 0.3f * lp.str) / 100.f * 0.9f); + float depthcombi = 0.3f * params->locallab.spots.at(sp).neigh + 0.15f * (500.f - params->locallab.spots.at(sp).vart); float depth = -LIM01(depthcombi / 100.f); dehazeloc(tmpImage, deha, depth); @@ -12327,7 +10722,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu rgb2lab(*tmpImage, *bufreti, params->icm.workingProfile); delete tmpImage; - } + } } float *orig[Hd] ALIGNED16; @@ -12363,7 +10758,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu tmpl = new LabImage(Wd, Hd); } else { - + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) @@ -12506,6 +10901,395 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu } } +//local color and light + + if (!lp.inv && (lp.chro != 0 || lp.ligh != 0.f || lp.cont != 0 || lp.qualcurvemet != 0) && lp.colorena) { // || lllocalcurve)) { //interior ellipse renforced lightness and chroma //locallutili + float hueplus = hueref + dhue; + float huemoins = hueref - dhue; + + if (hueplus > rtengine::RT_PI) { + hueplus = hueref + dhue - 2.f * rtengine::RT_PI; + } + + if (huemoins < -rtengine::RT_PI) { + huemoins = hueref - dhue + 2.f * rtengine::RT_PI; + } + + LabImage *bufcolorig = nullptr; + + float chpro = 1.f; + float cligh = 1.f; + float clighL = 1.f; + + int bfh = 0.f, bfw = 0.f; + bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone + bfw = int (lp.lx + lp.lxL) + del; + JaggedArray buflight(bfw, bfh); + JaggedArray bufchro(bfw, bfh); + JaggedArray buflightslid(bfw, bfh); + JaggedArray bufchroslid(bfw, bfh); + JaggedArray bufhh(bfw, bfh); + + float adjustr = 1.0f; + +//adapt chroma to working profile + if (params->icm.workingProfile == "ProPhoto") { + adjustr = 1.2f; // 1.2 instead 1.0 because it's very rare to have C>170.. + } else if (params->icm.workingProfile == "Adobe RGB") { + adjustr = 1.8f; + } else if (params->icm.workingProfile == "sRGB") { + adjustr = 2.0f; + } else if (params->icm.workingProfile == "WideGamut") { + adjustr = 1.2f; + } else if (params->icm.workingProfile == "Beta RGB") { + adjustr = 1.4f; + } else if (params->icm.workingProfile == "BestRGB") { + adjustr = 1.4f; + } else if (params->icm.workingProfile == "BruceRGB") { + adjustr = 1.8f; + } + + if (call <= 3) { //simpleprocess, dcrop, improccoordinator + bufcolorig = new LabImage(bfw, bfh); //buffer for data in zone limit + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < bfh; ir++) //fill with 0 + for (int jr = 0; jr < bfw; jr++) { + bufcolorig->L[ir][jr] = 0.f; + bufcolorig->a[ir][jr] = 0.f; + bufcolorig->b[ir][jr] = 0.f; + bufchro[ir][jr] = 0.f; + bufchroslid[ir][jr] = 0.f; + buflightslid[ir][jr] = 0.f; + buflight[ir][jr] = 0.f; + bufhh[ir][jr] = 0.f; + } + + int begy = lp.yc - lp.lyT; + int begx = lp.xc - lp.lxL; + int yEn = lp.yc + lp.ly; + int xEn = lp.xc + lp.lx; +#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) { + bufcolorig->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas + bufcolorig->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas + bufcolorig->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas + chpro = 0.f; + + //Chroma curve + if (cclocalcurve && lp.qualcurvemet != 0) { // C=f(C) curve + float chromat = sqrt(SQR(bufcolorig->a[loy - begy][lox - begx]) + SQR(bufcolorig->b[loy - begy][lox - begx])); + float ch; + float ampli = 25.f; + ch = (cclocalcurve[chromat * adjustr ]) / ((chromat + 0.00001f) * adjustr); //ch between 0 and 0 50 or more + chpro = CLIPCHRO(ampli * ch - ampli); //ampli = 25.f arbitrary empirical coefficient between 5 and 50 + bufchro[loy - begy][lox - begx] = chpro; + } + chpro = 0.f; + + if (lp.chro != 0.f && lp.curvact) { + // process to improve eg same as in Lab adjustements + float ch; + float ampli = 70.f; + ch = (1.f + 0.01f * lp.chro) ; //* (chromat * adjustr) / ((chromat + 0.00001f) * adjustr); //ch between 0 and 0 50 or more + if (ch <= 1.f) {//convert data curve near values of slider -100 + 100, to be used after to detection shape + chpro = 99.f * ch - 99.f; + } else { + chpro = CLIPCHRO(ampli * ch - ampli); //ampli = 25.f arbitrary empirical coefficient between 5 and 50 + } + bufchroslid[loy - begy][lox - begx] = chpro; + } + + if (lochhCurve && lp.qualcurvemet >= 2 && HHutili) { + float hhforcurv = xatan2f(bufcolorig->b[loy - begy][lox - begx], bufcolorig->a[loy - begy][lox - begx]); + + float valparam = float ((lochhCurve[500.f * Color::huelab_to_huehsv2(hhforcurv)] - 0.5f)); //get H=f(H) 1.7 optimisation ! + float ddhue = CLIPRET(200.f * valparam); + bufhh[loy - begy][lox - begx] = ddhue;//valparamdh; // + } + + //slider lightness + clighL = 0.f; + + if ((lp.ligh != 0.f || lp.cont != 0) && lp.curvact) { + float lL; + float lighLnew; + float amplil = 140.f; + float lighL = bufcolorig->L[loy - begy][lox - begx]; + calclight(lighL, lp.ligh, lighLnew, lightCurveloc); //replace L-curve + lL = lighLnew / lighL; + if (lL <= 1.f) {//convert data curve near values of slider -100 + 100, to be used after to detection shape + clighL = 99.f * lL - 99.f; + } else { + clighL = CLIPLIG(amplil * lL - amplil); //ampli = 25.f arbitrary empirical coefficient between 5 and 150 + } + buflightslid[loy - begy][lox - begx] = clighL; + // printf("cl=%f ", clighL); + } + cligh = 0.f; + + //luma curve + if (lllocalcurve && lp.qualcurvemet >= 2) {// L=f(L) curve enhanced + float lh; + float amplil = 25.f; + float lighn = bufcolorig->L[loy - begy][lox - begx]; + lh = (lllocalcurve[lighn * 1.9f]) / ((lighn + 0.00001f) * 1.9f) ; // / ((lighn) / 1.9f) / 3.61f; //lh between 0 and 0 50 or more + cligh = CLIPLIG(amplil * lh - amplil); + buflight[loy - begy][lox - begx] = cligh; + } + } + } + + if (lp.qualcurvemet >= 4) { + JaggedArray blend(bfw, bfh); + float contrastf = lp.sensexclu / 100.f; + buildBlendMask(bufcolorig->L, blend, bfw, bfh, contrastf, 1.f, true); + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < bfh; ++i) { + for (int j = 0; j < bfw; ++j) { + if (blend[i][j] > 0.05f) { + blend[i][j] = 1.22361f * sqrt(blend[i][j]) - 0.22361f; + } + buflight[i][j] = intp(blend[i][j], buflight[i][j], 0.f);// tmpsob->L[i][j]); + bufchro[i][j] = intp(blend[i][j], bufchro[i][j], 0.f); //tmpsob->L[i][j] ); + } + } + } + } + + ColorLight_Local(moddE, powdE, call, bufcolorig, buflight, bufchro, bufchroslid, bufhh, buflightslid, LHutili, HHutili, hueplus, huemoins, hueref, dhue, chromaref, lumaref, lllocalcurve, loclhCurve, lochhCurve, lightCurveloc, lp, original, transformed, cx, cy, sk); + + if (call <= 3) { + + delete bufcolorig; + + + } + } +//inverse + else if (lp.inv && (lp.chro != 0 || lp.ligh != 0) && lp.colorena) { + float hueplus = hueref + dhue; + float huemoins = hueref - dhue; + // float ddhue = 0.f; + + //printf("hueplus=%f huemoins=%f dhu=%f\n", hueplus, huemoins, dhue); + if (hueplus > rtengine::RT_PI) { + hueplus = hueref + dhue - 2.f * rtengine::RT_PI; + } + + if (huemoins < -rtengine::RT_PI) { + huemoins = hueref - dhue + 2.f * rtengine::RT_PI; + } + + InverseColorLight_Local(lp, lightCurveloc, original, transformed, cx, cy, hueplus, huemoins, hueref, dhue, chromaref, lumaref, sk); + } + + + + if (lp.exposena && (lp.expcomp != 0.f || lp.war != 0 || (exlocalcurve && localexutili))) { //interior ellipse renforced lightness and chroma //locallutili + float hueplus = hueref + dhuev; + float huemoins = hueref - dhuev; + + + if (hueplus > rtengine::RT_PI) { + hueplus = hueref + dhuev - 2.f * rtengine::RT_PI; + } + + if (huemoins < -rtengine::RT_PI) { + huemoins = hueref - dhuev + 2.f * rtengine::RT_PI; + } + + LabImage *bufexporig = nullptr; + LabImage *bufexpfin = nullptr; + LabImage *bufexptemp = nullptr; + LabImage *difLab = nullptr; + LabImage *bufcat02fin = nullptr; + + int bfh = 0.f, bfw = 0.f; + bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone + bfw = int (lp.lx + lp.lxL) + del; + JaggedArray buflight(bfw, bfh); + JaggedArray bufl_ab(bfw, bfh); + JaggedArray buflightcurv(bfw, bfh); + JaggedArray buf_a_cat(bfw, bfh, true); + JaggedArray buf_b_cat(bfw, bfh, true); + + + 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 + bufexptemp = new LabImage(bfw, bfh); //buffer for data in zone limit + difLab = new LabImage(bfw, bfh); //buffer for data in zone limit + bufcat02fin = new LabImage(bfw, bfh); //buffer for data in zone limit + + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < bfh; ir++) //fill with 0 + for (int jr = 0; jr < bfw; jr++) { + bufexporig->L[ir][jr] = 0.f; + bufexporig->a[ir][jr] = 0.f; + bufexporig->b[ir][jr] = 0.f; + bufexptemp->L[ir][jr] = 0.f; + bufexptemp->a[ir][jr] = 0.f; + bufexptemp->b[ir][jr] = 0.f; + bufexpfin->L[ir][jr] = 0.f; + bufexpfin->a[ir][jr] = 0.f; + bufexpfin->b[ir][jr] = 0.f; + bufcat02fin->L[ir][jr] = 0.f; + bufcat02fin->a[ir][jr] = 0.f; + bufcat02fin->b[ir][jr] = 0.f; + buflight[ir][jr] = 0.f; + bufl_ab[ir][jr] = 0.f; + buflightcurv[ir][jr] = 0.f; + buf_a_cat[ir][jr] = 0.f; + buf_b_cat[ir][jr] = 0.f; + } + + int begy = lp.yc - lp.lyT; + int begx = lp.xc - lp.lxL; + int yEn = lp.yc + lp.ly; + int xEn = lp.xc + lp.lx; + +#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) { + + bufexporig->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas + bufexporig->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas + bufexporig->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas + bufexptemp->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas + bufexptemp->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas + bufexptemp->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas + bufexpfin->L[loy - begy][lox - begx] = original->L[y][x];//fill square buffer with datas + bufexpfin->a[loy - begy][lox - begx] = original->a[y][x];//fill square buffer with datas + bufexpfin->b[loy - begy][lox - begx] = original->b[y][x];//fill square buffer with datas + } + } + +//to do Modulate bufexporig and bufexptemp with blend L, H, C and masks + + + if (exlocalcurve && localexutili) {// L=f(L) curve enhanced +#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) { + + float lighn = bufexporig->L[loy - begy][lox - begx]; + + float lh; + lh = 0.5f * exlocalcurve[2.f * lighn]; // / ((lighn) / 1.9f) / 3.61f; //lh between 0 and 0 50 or more + bufexptemp->L[loy - begy][lox - begx] = lh; + } + } + + if (lp.expcomp == 0.f) { + lp.expcomp = 0.1f; // to enabled + } + + ImProcFunctions::exlabLocal(lp, bfh, bfw, bufexptemp, bufexpfin, hltonecurveloc, shtonecurveloc, tonecurveloc); + + + } else { + + ImProcFunctions::exlabLocal(lp, bfh, bfw, bufexporig, bufexpfin, hltonecurveloc, shtonecurveloc, tonecurveloc); + } + + //cat02 + if (params->locallab.spots.at(sp).warm != 0) { + ImProcFunctions::ciecamloc_02float(sp, bufexpfin, bufcat02fin); + } else { +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + bufcat02fin->L[ir][jr] = bufexpfin->L[ir][jr]; + bufcat02fin->a[ir][jr] = bufexpfin->a[ir][jr]; + bufcat02fin->b[ir][jr] = bufexpfin->b[ir][jr]; + } + } + + + +#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) { + + float rL; + rL = CLIPRET((bufcat02fin->L[loy - begy][lox - begx] - bufexporig->L[loy - begy][lox - begx]) / 328.f); + + buflight[loy - begy][lox - begx] = rL; + float rA; + rA = CLIPRET((bufcat02fin->a[loy - begy][lox - begx] - bufexporig->a[loy - begy][lox - begx]) / 328.f); + buf_a_cat[loy - begy][lox - begx] = rA; + + + float rB; + rB = CLIPRET((bufcat02fin->b[loy - begy][lox - begx] - bufexporig->b[loy - begy][lox - begx]) / 328.f); + buf_b_cat[loy - begy][lox - begx] = rB; + + + } + } + + Expo_vibr_Local(moddE, powdE, 1, buflight, bufl_ab, buf_a_cat, buf_b_cat, hueplus, huemoins, hueref, dhueex, chromaref, lumaref, lp, original, transformed, difLab, bufcat02fin, cx, cy, sk); + //view mask + } + + if (call <= 3) { + + delete bufexporig; + delete bufexpfin; + delete bufexptemp; + delete difLab; + delete bufcat02fin; + } + + } + + // Gamut and Munsell control - very important do not desactivated to avoid crash if (params->locallab.spots.at(sp).avoid) { diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 4b0cae7ff..11c70b076 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -631,6 +631,8 @@ enum ProcEventCode { Evlocallabsensisf = 601, Evlocallabsharblur = 602, EvLocenalabregion = 603, + EvlocallabshowmaskcolMethod = 604, + EvlocallabshowmaskexpMethod = 605, NUMOFEVENTS }; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 3f22ba00d..767bcb8a8 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2363,6 +2363,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : chroma(0), sensi(19), qualitycurveMethod("none"), + showmaskcolMethod("none"), llcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, cccurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, LHcurve{(double)FCT_MinMaxCPoints, 0.0, 0.50, 0.35, 0.35, 0.166, 0.50, 0.35, 0.35, 0.333, 0.50, 0.35, 0.35, 0.50, 0.50, 0.35, 0.35, 0.666, 0.50, 0.35, 0.35, 0.833, 0.50, 0.35, 0.35}, @@ -2378,6 +2379,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : warm(0), sensiex(19), excurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + showmaskexpMethod("none"), // Vibrance expvibrance(false), saturated(0), @@ -2491,6 +2493,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && chroma == other.chroma && sensi == other.sensi && qualitycurveMethod == other.qualitycurveMethod + && showmaskcolMethod == other.showmaskcolMethod && llcurve == other.llcurve && cccurve == other.cccurve && LHcurve == other.LHcurve @@ -2506,6 +2509,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && warm == other.warm && sensiex == other.sensiex && excurve == other.excurve + && showmaskexpMethod == other.showmaskexpMethod // Vibrance && expvibrance == other.expvibrance && saturated == other.saturated @@ -3572,6 +3576,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chroma, "Locallab", "Chroma_" + std::to_string(i), spot.chroma, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensi, "Locallab", "Sensi_" + std::to_string(i), spot.sensi, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).qualitycurveMethod, "Locallab", "QualityCurveMethod_" + std::to_string(i), spot.qualitycurveMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).showmaskcolMethod, "Locallab", "ShowmaskcolMethod_" + std::to_string(i), spot.showmaskcolMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).llcurve, "Locallab", "LLCurve_" + std::to_string(i), spot.llcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).cccurve, "Locallab", "CCCurve_" + std::to_string(i), spot.cccurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LHcurve, "Locallab", "LHCurve_" + std::to_string(i), spot.LHcurve, keyFile); @@ -3587,6 +3592,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).warm, "Locallab", "Warm_" + std::to_string(i), spot.warm, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensiex, "Locallab", "Sensiex_" + std::to_string(i), spot.sensiex, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).excurve, "Locallab", "ExCurve_" + std::to_string(i), spot.excurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).showmaskexpMethod, "Locallab", "ShowmaskexpMethod_" + std::to_string(i), spot.showmaskexpMethod, 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); @@ -4780,6 +4786,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Chroma_" + std::to_string(i), pedited, spot.chroma, spotEdited.chroma); assignFromKeyfile(keyFile, "Locallab", "Sensi_" + std::to_string(i), pedited, spot.sensi, spotEdited.sensi); assignFromKeyfile(keyFile, "Locallab", "QualityCurveMethod_" + std::to_string(i), pedited, spot.qualitycurveMethod, spotEdited.qualitycurveMethod); + assignFromKeyfile(keyFile, "Locallab", "ShowmaskcolMethod_" + std::to_string(i), pedited, spot.showmaskcolMethod, spotEdited.showmaskcolMethod); assignFromKeyfile(keyFile, "Locallab", "LLCurve_" + std::to_string(i), pedited, spot.llcurve, spotEdited.llcurve); assignFromKeyfile(keyFile, "Locallab", "CCCurve_" + std::to_string(i), pedited, spot.cccurve, spotEdited.cccurve); assignFromKeyfile(keyFile, "Locallab", "LHCurve_" + std::to_string(i), pedited, spot.LHcurve, spotEdited.LHcurve); @@ -4795,6 +4802,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Warm_" + std::to_string(i), pedited, spot.warm, spotEdited.warm); assignFromKeyfile(keyFile, "Locallab", "Sensiex_" + std::to_string(i), pedited, spot.sensiex, spotEdited.sensiex); assignFromKeyfile(keyFile, "Locallab", "ExCurve_" + std::to_string(i), pedited, spot.excurve, spotEdited.excurve); + assignFromKeyfile(keyFile, "Locallab", "ShowmaskexpMethod_" + std::to_string(i), pedited, spot.showmaskexpMethod, spotEdited.showmaskexpMethod); // 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 dfb5922b0..690c59d6d 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -957,6 +957,7 @@ struct LocallabParams { int chroma; int sensi; Glib::ustring qualitycurveMethod; + Glib::ustring showmaskcolMethod; std::vector llcurve; std::vector cccurve; std::vector LHcurve; @@ -972,6 +973,7 @@ struct LocallabParams { int warm; int sensiex; std::vector excurve; + Glib::ustring showmaskexpMethod; // Vibrance bool expvibrance; int saturated; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index f731116df..b23e8f0aa 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -630,7 +630,9 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, //EvLocallabstreng LUMINANCECURVE, //EvLocallabsensisf LUMINANCECURVE, //Evlocallabsharblur - LUMINANCECURVE //EvLocenalabregion + LUMINANCECURVE, //EvLocenalabregion + LUMINANCECURVE, //EvlocallabshowmaskcolMethod + LUMINANCECURVE //EvlocallabshowmaskexpMethod }; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 475cf64dd..7f7bf0401 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1081,6 +1081,7 @@ private: LUTf shtonecurveloc(65536, 0); LUTf tonecurveloc(65536, 0); LUTf lightCurveloc(32770, 0); + LUTu lhist16loc(32768, 0); LUTf exlocalcurve(65536, 0); // int maxspot = 1; @@ -1116,19 +1117,19 @@ private: double hlcomprthresh = params.locallab.spots.at(sp).hlcomprthresh; double shcompr = params.locallab.spots.at(sp).shcompr; double br = params.locallab.spots.at(sp).lightness; - CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, - hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, - 1); + double cont = params.locallab.spots.at(sp).contrast; // Reference parameters computation double huere, chromare, lumare, huerefblu, sobelre; if (params.locallab.spots.at(sp).spotMethod == "exc") { - ipf.calc_ref(sp, reservView, reservView, 0, 0, fw, fh, 1, huerefblu, huere, chromare, lumare, sobelre); + ipf.calc_ref(sp, reservView, reservView, 0, 0, fw, fh, 1, huerefblu, huere, chromare, lumare, sobelre, lhist16loc); } else { - ipf.calc_ref(sp, labView, labView, 0, 0, fw, fh, 1, huerefblu, huere, chromare, lumare, sobelre); - + ipf.calc_ref(sp, labView, labView, 0, 0, fw, fh, 1, huerefblu, huere, chromare, lumare, sobelre, lhist16loc); } + CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lhist16loc, + hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, + 1); ipf.Lab_Local(2, sp, sobelrefs, (float**)shbuffer, labView, labView, reservView, 0, 0, fw, fh, 1, locRETgainCurve, lllocalcurve, loclhCurve, lochhCurve, LHutili, HHutili, cclocalcurve, localskutili, sklocalcurve, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerefblu, huere, chromare, lumare, sobelre); diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index b45e37155..1c34ecb43 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -157,6 +157,9 @@ Locallab::Locallab(): // ComboBox widgets // Color & Light qualitycurveMethod(Gtk::manage(new MyComboBoxText())), + showmaskcolMethod(Gtk::manage(new MyComboBoxText())), + //Exposure + showmaskexpMethod(Gtk::manage(new MyComboBoxText())), // Blur & Noise blurMethod(Gtk::manage(new MyComboBoxText())), // Retinex @@ -217,6 +220,13 @@ Locallab::Locallab(): qualitycurveMethod->set_tooltip_markup(M("TP_LOCALLAB_CURVEMETHOD_TOOLTIP")); qualitycurveMethodConn = qualitycurveMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::qualitycurveMethodChanged)); + showmaskcolMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskcolMethod->append(M("TP_LOCALLAB_SHOWMAK1")); + + showmaskcolMethod->set_active(0); + showmaskcolMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + showmaskcolMethodConn = showmaskcolMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::showmaskcolMethodChanged)); + llCurveEditorG->setCurveListener(this); llshape = static_cast(llCurveEditorG->addCurve(CT_Diagonal, "L(L)")); @@ -291,6 +301,14 @@ Locallab::Locallab(): colorBox->pack_start(*qualcurvbox); colorBox->pack_start(*llCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor colorBox->pack_start(*invers); + maskcolFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_SHOW"))); + maskcolFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const maskcolBox = Gtk::manage(new ToolParamBlock()); + maskcolBox->pack_start(*showmaskcolMethod, Gtk::PACK_SHRINK, 0); + + maskcolFrame->add(*maskcolBox); + colorBox->pack_start(*maskcolFrame); + expcolor->add(*colorBox); expcolor->setLevel(2); @@ -328,7 +346,20 @@ Locallab::Locallab(): shapeexpos->setLeftBarBgGradient(mshapeexpos); curveEditorG->curveListComplete(); + showmaskexpMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskexpMethod->append(M("TP_LOCALLAB_SHOWMAK1")); + showmaskexpMethod->set_active(0); + showmaskexpMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + showmaskexpMethodConn = showmaskexpMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::showmaskexpMethodChanged)); + + maskexpFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_SHOW"))); + maskexpFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const maskexpBox = Gtk::manage(new ToolParamBlock()); + maskexpBox->pack_start(*showmaskexpMethod, Gtk::PACK_SHRINK, 0); + + maskexpFrame->add(*maskexpBox); + ToolParamBlock* const exposeBox = Gtk::manage(new ToolParamBlock()); exposeBox->pack_start(*expcomp); exposeBox->pack_start(*hlcompr); @@ -338,6 +369,8 @@ Locallab::Locallab(): exposeBox->pack_start(*warm); exposeBox->pack_start(*sensiex); exposeBox->pack_start(*curveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + exposeBox->pack_start(*maskexpFrame); + expexpose->add(*exposeBox); expexpose->setLevel(2); @@ -1337,6 +1370,12 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pp->locallab.spots.at(pp->locallab.selspot).qualitycurveMethod = "enh"; } + if (showmaskcolMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(pp->locallab.selspot).showmaskcolMethod = "none"; + } else if (showmaskcolMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(pp->locallab.selspot).showmaskcolMethod = "color"; + } + pp->locallab.spots.at(pp->locallab.selspot).llcurve = llshape->getCurve(); pp->locallab.spots.at(pp->locallab.selspot).cccurve = ccshape->getCurve(); pp->locallab.spots.at(pp->locallab.selspot).LHcurve = LHshape->getCurve(); @@ -1352,6 +1391,12 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pp->locallab.spots.at(pp->locallab.selspot).warm = warm->getIntValue(); pp->locallab.spots.at(pp->locallab.selspot).sensiex = sensiex->getIntValue(); pp->locallab.spots.at(pp->locallab.selspot).excurve = shapeexpos->getCurve(); + if (showmaskexpMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(pp->locallab.selspot).showmaskexpMethod = "none"; + } else if (showmaskexpMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(pp->locallab.selspot).showmaskexpMethod = "expo"; + } + // Vibrance pp->locallab.spots.at(pp->locallab.selspot).expvibrance = expvibrance->getEnabled(); pp->locallab.spots.at(pp->locallab.selspot).saturated = saturated->getIntValue(); @@ -1483,6 +1528,7 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pe->locallab.spots.at(pp->locallab.selspot).chroma = pe->locallab.spots.at(pp->locallab.selspot).chroma || chroma->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).sensi = pe->locallab.spots.at(pp->locallab.selspot).sensi || sensi->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).qualitycurveMethod = pe->locallab.spots.at(pp->locallab.selspot).qualitycurveMethod || qualitycurveMethod->get_active_text() != M("GENERAL_UNCHANGED"); + pe->locallab.spots.at(pp->locallab.selspot).showmaskcolMethod = pe->locallab.spots.at(pp->locallab.selspot).showmaskcolMethod || showmaskcolMethod->get_active_text() != M("GENERAL_UNCHANGED"); pe->locallab.spots.at(pp->locallab.selspot).llcurve = pe->locallab.spots.at(pp->locallab.selspot).llcurve || !llshape->isUnChanged(); pe->locallab.spots.at(pp->locallab.selspot).cccurve = pe->locallab.spots.at(pp->locallab.selspot).cccurve || !ccshape->isUnChanged(); pe->locallab.spots.at(pp->locallab.selspot).LHcurve = pe->locallab.spots.at(pp->locallab.selspot).LHcurve || !LHshape->isUnChanged(); @@ -1498,6 +1544,7 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pe->locallab.spots.at(pp->locallab.selspot).warm = pe->locallab.spots.at(pp->locallab.selspot).warm || warm->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).sensiex = pe->locallab.spots.at(pp->locallab.selspot).sensiex || sensiex->getEditedState(); pe->locallab.spots.at(pp->locallab.selspot).excurve = pe->locallab.spots.at(pp->locallab.selspot).excurve || !shapeexpos->isUnChanged(); + pe->locallab.spots.at(pp->locallab.selspot).showmaskexpMethod = pe->locallab.spots.at(pp->locallab.selspot).showmaskexpMethod || showmaskexpMethod->get_active_text() != M("GENERAL_UNCHANGED"); // 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(); @@ -1616,6 +1663,7 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pedited->locallab.spots.at(pp->locallab.selspot).chroma = pedited->locallab.spots.at(pp->locallab.selspot).chroma || chroma->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).sensi = pedited->locallab.spots.at(pp->locallab.selspot).sensi || sensi->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).qualitycurveMethod = pedited->locallab.spots.at(pp->locallab.selspot).qualitycurveMethod || qualitycurveMethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->locallab.spots.at(pp->locallab.selspot).showmaskcolMethod = pedited->locallab.spots.at(pp->locallab.selspot).showmaskcolMethod || showmaskcolMethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->locallab.spots.at(pp->locallab.selspot).llcurve = pedited->locallab.spots.at(pp->locallab.selspot).llcurve || !llshape->isUnChanged(); pedited->locallab.spots.at(pp->locallab.selspot).cccurve = pedited->locallab.spots.at(pp->locallab.selspot).cccurve || !ccshape->isUnChanged(); pedited->locallab.spots.at(pp->locallab.selspot).LHcurve = pedited->locallab.spots.at(pp->locallab.selspot).LHcurve || !LHshape->isUnChanged(); @@ -1631,6 +1679,7 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pedited->locallab.spots.at(pp->locallab.selspot).warm = pedited->locallab.spots.at(pp->locallab.selspot).warm || warm->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).sensiex = pedited->locallab.spots.at(pp->locallab.selspot).sensiex || sensiex->getEditedState(); pedited->locallab.spots.at(pp->locallab.selspot).excurve = pedited->locallab.spots.at(pp->locallab.selspot).excurve || !shapeexpos->isUnChanged(); + pedited->locallab.spots.at(pp->locallab.selspot).showmaskexpMethod = pedited->locallab.spots.at(pp->locallab.selspot).showmaskexpMethod || showmaskexpMethod->get_active_text() != M("GENERAL_UNCHANGED"); // 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(); @@ -1920,6 +1969,35 @@ void Locallab::qualitycurveMethodChanged() } } +void Locallab::showmaskcolMethodChanged() +{ + if(showmaskcolMethod->get_active_row_number() == 1 && expcolor->getEnabled()) { + showmaskexpMethod->set_active(0); + expexpose->setEnabled(false); + } + + if (getEnabled() && expcolor->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabshowmaskcolMethod , showmaskcolMethod->get_active_text()); + } + } +} + +void Locallab::showmaskexpMethodChanged() +{ + + if(showmaskexpMethod->get_active_row_number() == 1 && expexpose->getEnabled()) { + showmaskcolMethod->set_active(0); + expcolor->setEnabled(false); + } + + if (getEnabled() && expexpose->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabshowmaskexpMethod , showmaskexpMethod->get_active_text()); + } + } +} + void Locallab::inversChanged() { // printf("inversChanged\n"); @@ -1940,18 +2018,21 @@ void Locallab::inversChanged() curvactiv->show(); qualitycurveMethod->show(); labqualcurv->show(); + maskcolFrame->show(); } else if (invers->get_active()) { sensi->show(); llCurveEditorG->hide(); curvactiv->hide(); qualitycurveMethod->hide(); labqualcurv->hide(); + maskcolFrame->hide(); } else { sensi->show(); llCurveEditorG->show(); curvactiv->show(); qualitycurveMethod->show(); labqualcurv->show(); + maskcolFrame->show(); } if (getEnabled() && expcolor->getEnabled()) { @@ -2952,6 +3033,9 @@ void Locallab::setBatchMode(bool batchMode) // Set batch mode for comboBoxText // Color & Light qualitycurveMethod->append(M("GENERAL_UNCHANGED")); + showmaskcolMethod->append(M("GENERAL_UNCHANGED")); + //Exposure + showmaskexpMethod->append(M("GENERAL_UNCHANGED")); // Blur & Noise blurMethod->append(M("GENERAL_UNCHANGED")); // Retinex @@ -3080,8 +3164,10 @@ void Locallab::enableListener() curvactivConn.block(false); qualitycurveMethodConn.block(false); inversConn.block(false); + showmaskcolMethodConn.block(false); // Exposure enableexposeConn.block(false); + showmaskexpMethodConn.block(false); // Vibrance enablevibranceConn.block(false); pskinsconn.block(false); @@ -3122,9 +3208,11 @@ void Locallab::disableListener() enablecolorConn.block(true); curvactivConn.block(true); qualitycurveMethodConn.block(true); + showmaskcolMethodConn.block(true); inversConn.block(true); // Exposure enableexposeConn.block(true); + showmaskexpMethodConn.block(true); // Vibrance enablevibranceConn.block(true); pskinsconn.block(true); @@ -3184,6 +3272,11 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con qualitycurveMethod->set_active(5); } + if (pp->locallab.spots.at(index).showmaskcolMethod == "none") { + showmaskcolMethod->set_active(0); + } else if (pp->locallab.spots.at(index).showmaskcolMethod == "color") { + showmaskcolMethod->set_active(1); + } llshape->setCurve(pp->locallab.spots.at(index).llcurve); ccshape->setCurve(pp->locallab.spots.at(index).cccurve); LHshape->setCurve(pp->locallab.spots.at(index).LHcurve); @@ -3200,6 +3293,11 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con warm->setValue(pp->locallab.spots.at(index).warm); sensiex->setValue(pp->locallab.spots.at(index).sensiex); shapeexpos->setCurve(pp->locallab.spots.at(index).excurve); + if (pp->locallab.spots.at(index).showmaskexpMethod == "none") { + showmaskexpMethod->set_active(0); + } else if (pp->locallab.spots.at(index).showmaskexpMethod == "expo") { + showmaskexpMethod->set_active(1); + } // Vibrance expvibrance->setEnabled(pp->locallab.spots.at(index).expvibrance); @@ -3356,6 +3454,9 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con if (!spotState->qualitycurveMethod) { qualitycurveMethod->set_active_text(M("GENERAL_UNCHANGED")); } + if (!spotState->showmaskcolMethod) { + showmaskcolMethod->set_active_text(M("GENERAL_UNCHANGED")); + } llshape->setUnChanged(!spotState->llcurve); ccshape->setUnChanged(!spotState->cccurve); @@ -3373,6 +3474,9 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con shcompr->setEditedState(spotState->shcompr ? Edited : UnEdited); sensiex->setEditedState(spotState->sensiex ? Edited : UnEdited); shapeexpos->setUnChanged(!spotState->excurve); + if (!spotState->showmaskexpMethod) { + showmaskexpMethod->set_active_text(M("GENERAL_UNCHANGED")); + } // Vibrance expvibrance->set_inconsistent(!spotState->expvibrance); @@ -3489,11 +3593,13 @@ void Locallab::updateSpecificGUIState() curvactiv->show(); qualitycurveMethod->show(); labqualcurv->show(); + maskcolFrame->show(); } else if (invers->get_active()) { sensi->show(); llCurveEditorG->hide(); curvactiv->hide(); qualitycurveMethod->hide(); + maskcolFrame->hide(); labqualcurv->hide(); } else { sensi->show(); @@ -3501,6 +3607,7 @@ void Locallab::updateSpecificGUIState() curvactiv->show(); qualitycurveMethod->show(); labqualcurv->show(); + maskcolFrame->show(); } // Update Exposure GUI according to black adjuster state (to be compliant with adjusterChanged function) @@ -3539,6 +3646,22 @@ void Locallab::updateSpecificGUIState() } else { strength->show(); } + + //update showmethod + if (multiImage && showmaskcolMethod->get_active_text() == M("GENERAL_UNCHANGED")) { + showmaskexpMethod->set_active(0); + } else if(showmaskcolMethod->get_active_row_number() == 1) { + showmaskexpMethod->set_active(0); + expexpose->setEnabled(false); + } + + if (multiImage && showmaskexpMethod->get_active_text() == M("GENERAL_UNCHANGED")) { + showmaskcolMethod->set_active(0); + } else if(showmaskexpMethod->get_active_row_number() == 1) { + showmaskcolMethod->set_active(0); + expcolor->setEnabled(false); + } + // Update Retinex GUI according to inversret button state (to be compliant with inversretChanged function) if (multiImage && inversret->get_inconsistent()) { diff --git a/rtgui/locallab.h b/rtgui/locallab.h index fba739b74..0673f9874 100644 --- a/rtgui/locallab.h +++ b/rtgui/locallab.h @@ -172,6 +172,12 @@ private: // Color & Light MyComboBoxText* const qualitycurveMethod; sigc::connection qualitycurveMethodConn; + MyComboBoxText* const showmaskcolMethod; + sigc::connection showmaskcolMethodConn; + //Exposure + MyComboBoxText* const showmaskexpMethod; + sigc::connection showmaskexpMethodConn; + // Blur & Noise MyComboBoxText* const blurMethod; sigc::connection blurMethodConn; @@ -190,6 +196,10 @@ private: Gtk::Button* const lumacontrastPlusButton; sigc::connection lumacontrastMinusPressedConn, lumaneutralPressedConn, lumacontrastPlusPressedConn; + //Frame + Gtk::Frame* maskcolFrame; + Gtk::Frame* maskexpFrame; + // Others /** * Used to store the default ProcParams when setDefaults function is called @@ -215,6 +225,10 @@ private: // Color & Light void curvactivChanged(); void inversChanged(); + void showmaskcolMethodChanged(); + //Exposure + void showmaskexpMethodChanged(); + // Vibrance void protectskins_toggled(); void avoidcolorshift_toggled(); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index cb5152810..dbb741b36 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -949,6 +949,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).chroma = locallab.spots.at(j).chroma && pSpot.chroma == otherSpot.chroma; locallab.spots.at(j).sensi = locallab.spots.at(j).sensi && pSpot.sensi == otherSpot.sensi; locallab.spots.at(j).qualitycurveMethod = locallab.spots.at(j).qualitycurveMethod && pSpot.qualitycurveMethod == otherSpot.qualitycurveMethod; + locallab.spots.at(j).showmaskcolMethod = locallab.spots.at(j).showmaskcolMethod && pSpot.showmaskcolMethod == otherSpot.showmaskcolMethod; locallab.spots.at(j).llcurve = locallab.spots.at(j).llcurve && pSpot.llcurve == otherSpot.llcurve; locallab.spots.at(j).cccurve = locallab.spots.at(j).cccurve && pSpot.cccurve == otherSpot.cccurve; locallab.spots.at(j).LHcurve = locallab.spots.at(j).LHcurve && pSpot.LHcurve == otherSpot.LHcurve; @@ -964,6 +965,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).warm = locallab.spots.at(j).warm && pSpot.warm == otherSpot.warm; locallab.spots.at(j).sensiex = locallab.spots.at(j).sensiex && pSpot.sensiex == otherSpot.sensiex; locallab.spots.at(j).excurve = locallab.spots.at(j).excurve && pSpot.excurve == otherSpot.excurve; + locallab.spots.at(j).showmaskexpMethod = locallab.spots.at(j).showmaskexpMethod && pSpot.showmaskexpMethod == otherSpot.showmaskexpMethod; // 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; @@ -2572,6 +2574,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).qualitycurveMethod = mods.locallab.spots.at(i).qualitycurveMethod; } + if (locallab.spots.at(i).showmaskcolMethod) { + toEdit.locallab.spots.at(i).showmaskcolMethod = mods.locallab.spots.at(i).showmaskcolMethod; + } + if (locallab.spots.at(i).llcurve) { toEdit.locallab.spots.at(i).llcurve = mods.locallab.spots.at(i).llcurve; } @@ -2629,6 +2635,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).excurve = mods.locallab.spots.at(i).excurve; } + if (locallab.spots.at(i).showmaskexpMethod) { + toEdit.locallab.spots.at(i).showmaskexpMethod = mods.locallab.spots.at(i).showmaskexpMethod; + } + // Vibrance if (locallab.spots.at(i).expvibrance) { toEdit.locallab.spots.at(i).expvibrance = mods.locallab.spots.at(i).expvibrance; @@ -3881,6 +3891,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : chroma(v), sensi(v), qualitycurveMethod(v), + showmaskcolMethod(v), llcurve(v), cccurve(v), LHcurve(v), @@ -3896,6 +3907,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : warm(v), sensiex(v), excurve(v), + showmaskexpMethod(v), // Vibrance expvibrance(v), saturated(v), @@ -4006,6 +4018,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) chroma = v; sensi = v; qualitycurveMethod = v; + showmaskcolMethod = v; llcurve = v; cccurve = v; LHcurve = v; @@ -4021,6 +4034,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) warm = v; sensiex = v; excurve = v; + showmaskexpMethod = v; // Vibrance expvibrance = v; saturated = v; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index ef6470026..2500a75b2 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -488,6 +488,7 @@ public: bool chroma; bool sensi; bool qualitycurveMethod; + bool showmaskcolMethod; bool llcurve; bool cccurve; bool LHcurve; @@ -503,6 +504,7 @@ public: bool warm; bool sensiex; bool excurve; + bool showmaskexpMethod; // Vibrance bool expvibrance; bool saturated;