From c8508a95bdac872efe64d7c71aee015eea4ce9dc Mon Sep 17 00:00:00 2001 From: Ingo Date: Sun, 17 May 2015 22:19:59 +0200 Subject: [PATCH] Speedup for ImProcFunctions::chromiLuminanceCurve, Issue 2772 --- rtengine/color.cc | 125 ++++++---- rtengine/color.h | 20 +- rtengine/improcfun.cc | 531 +++++++++++++++++++++--------------------- 3 files changed, 344 insertions(+), 332 deletions(-) diff --git a/rtengine/color.cc b/rtengine/color.cc index 7612c471a..3791b0e6e 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -21,7 +21,8 @@ #include "color.h" #include "iccmatrices.h" #include "mytime.h" -#include "sleef.c" +#include "sleef.c" +#include "opthelper.h" using namespace std; @@ -1113,7 +1114,7 @@ namespace rtengine { - void Color::scalered ( float rstprotection, float param, float limit, float HH, float deltaHH, float &scale,float &scaleext) + void Color::scalered ( const float rstprotection, const float param, const float limit, const float HH, const float deltaHH, float &scale, float &scaleext) { if(rstprotection<99.9999f) { if(param > limit) @@ -1129,7 +1130,7 @@ namespace rtengine { } } - void Color::transitred (float HH, float Chprov1, float dred, float factorskin, float protect_red, float factorskinext, float deltaHH, float factorsat, float &factor) + void Color::transitred (const float HH, float const Chprov1, const float dred, const float factorskin, const float protect_red, const float factorskinext, const float deltaHH, const float factorsat, float &factor) { if(HH>=0.15f && HH<1.3f) { if (Chprov1maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); * it can be used before and after treatment (saturation, gamma, luminance, ...) * * Parameters: - * Labimage *lab : RT Lab data - * float *Lold : luminance before - data: i*width + j - * float *Cold : chrominance before - data: i*width + j - * bool corMuns : performs Munsell correction + * float *labL : RT Lab L channel data + * float *laba : RT Lab a channel data + * float *labb : RT Lab b channel data + * bool corMunsell : performs Munsell correction * bool lumaMuns : (used only if corMuns=true) * true: apply luma + chroma Munsell correction if delta L > 10; * false: only chroma correction only * bool gamut : performs gamutLch - * Glib::ustring &working: working profile's name + * const double wip[3][3]: matrix for working profile * bool multiThread : parallelize the loop */ - void Color::LabGamutMunsell(LabImage *lab, float *Lold, float *Cold, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const Glib::ustring &working, bool multiThread ) { +SSEFUNCTION void Color::LabGamutMunsell(float *labL, float *laba, float *labb, const int N, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const double wip[3][3], bool multiThread ) { #ifdef _DEBUG MyTime t1e,t2e; t1e.set(); @@ -1514,42 +1515,58 @@ munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); MunsellDebugInfo* MunsDebugInfo=NULL; if (corMunsell) MunsDebugInfo = new MunsellDebugInfo(); - - #pragma omp parallel default(shared) firstprivate(MunsDebugInfo) reduction(+: negat, moreRGB) if (multiThread) -#else - #pragma omp parallel default(shared) if (multiThread) #endif - { - - //unsigned int N = lab->W*lab->H; - int width = lab->W, height = lab->H; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (working); - double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; - float correctlum=0.0; - float correctionHuechroma=0.0; - -#pragma omp for schedule(dynamic, 10) - for (int i=0; ib[i][j],lab->a[i][j]); - float Chprov1=sqrt(SQR(lab->a[i][j]/327.68f) + SQR(lab->b[i][j]/327.68f)); - float Lprov1=lab->L[i][j]/327.68f; - float Loldd, Coldd; + float correctlum = 0.f; + float correctionHuechroma = 0.f; +#ifdef __SSE2__ + // precalculate H and C using SSE + float HHBuffer[N]; + float CCBuffer[N]; + __m128 c327d68v = _mm_set1_ps(327.68f); + __m128 av,bv; + int k; + for (k=0; kmaxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); #endif } - Loldd = Lold[i*width + j]; - Coldd = Cold[i*width + j]; - lab->L[i][j] = Lprov1*327.68f; - correctionHuechroma = 0.0; - correctlum = 0.0; + labL[j] = Lprov1*327.68f; + correctionHuechroma = 0.f; + correctlum = 0.f; if(corMunsell) #ifdef _DEBUG @@ -1570,16 +1585,24 @@ munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); #else AllMunsellLch(lumaMuns, Lprov1, Loldd, HH, Chprov1, Coldd, correctionHuechroma, correctlum); #endif - - HH+=correctlum; //hue Munsell luminance correction - - correctlum = 0.0f; - float2 sincosval = xsincosf(HH+correctionHuechroma); - lab->a[i][j] = Chprov1*sincosval.y*327.68f; - lab->b[i][j] = Chprov1*sincosval.x*327.68f; - - } - } // end of parallelization + if(correctlum == 0.f && correctionHuechroma == 0.f) { + if(!gamut) { + if(Coldd == 0.f) { + sincosval.y = 1.f; + sincosval.x = 0.f; + } else { + sincosval.y = laba[j]/(Coldd*327.68f); + sincosval.x = labb[j]/(Coldd*327.68f); + } + } + + } else { + HH+=correctlum; //hue Munsell luminance correction + sincosval = xsincosf(HH+correctionHuechroma); + } + laba[j] = Chprov1*sincosval.y*327.68f; + labb[j] = Chprov1*sincosval.x*327.68f; + } #ifdef _DEBUG t2e.set(); diff --git a/rtengine/color.h b/rtengine/color.h index 5a41f7e29..7e5d8688f 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -1000,24 +1000,24 @@ public: * @brief Munsell gamut correction * * This function is the overall Munsell's corrections, but only on global statement. It may be better to use local statement with AllMunsellLch. - * Not for use in a "for" or "do while" loop * They are named accordingly : gamutLchonly and AllMunsellLch * It can be used before and after treatment (saturation, gamma, luminance, ...) * - * @param lab input and output image + * @param labL L channel input and output image * L channel's usual range is [0 ; 100], but values can be negative or >100 - * a and b channel's range is usually [-128 ; +128], but values can be >128 - * @param Lold luminance before [same range than lab.L] - * @param Cold chrominance before [0 ; 180 (can be superior)] - * @param corMuns performs Munsell correction + * @param laba a channel input and output image + * @param labb b channel input and output image + * a and b channel's range is usually [-128 ; +128], but values can be >128 + * @param N Number of pixels to process + * @param corMunsell performs Munsell correction * @param lumaMuns whether to apply luma correction or not (used only if corMuns=true) * true: apply luma + chroma Munsell correction if delta L > 10; * false: leaves luma untouched * @param gamut performs gamutLch - * @param working working profile's name + * @param wip matrix for working profile * @param multiThread whether to parallelize the loop or not */ - static void LabGamutMunsell (LabImage *lab, float *Lold, float *Cold, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const Glib::ustring &working, bool multiThread ); + static void LabGamutMunsell (float *labL, float *laba, float *labb, const int N, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const double wip[3][3], bool multiThread ); /* @@ -1053,8 +1053,8 @@ public: // -------------------------------- end Munsell - static void scalered ( float rstprotection, float param, float limit, float HH, float deltaHH, float &scale, float &scaleext); - static void transitred (float HH, float Chprov1, float dred, float factorskin, float protect_red, float factorskinext, float deltaHH, float factorsat, float &factor); + static void scalered ( const float rstprotection, const float param, const float limit, const float HH, const float deltaHH, float &scale, float &scaleext); + static void transitred (const float HH, const float Chprov1, const float dred, const float factorskin, const float protect_red, const float factorskinext, const float deltaHH, const float factorsat, float &factor); static void skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s); static void skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s); // static void scaleredcdbl ( float skinprot, float param, float limit, float HH, float deltaHH, float &scale,float &scaleext); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 7ebb31c12..aa01ac203 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -4286,7 +4286,7 @@ void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, LUTf & cur -void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve,LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) { +SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve,LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) { int W = lold->W; int H = lold->H; // lhskcurve.dump("lh_curve"); @@ -4297,9 +4297,11 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI LabImage* editLab = NULL; PlanarWhateverData* editWhatever = NULL; EditUniqueID editID = EUID_None; + bool editPipette = false; if (editBuffer) { editID = editBuffer->getEditID(); if (editID != EUID_None) { + editPipette = true; switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) { case (BT_IMAGEFLOAT): editImgFloat = editBuffer->getImgFloatBuffer(); @@ -4359,38 +4361,25 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI LUTf dLcurve; LUTu hist16Clad; -// LUTu hist16CLlad; -// LUTu hist16LLClad; LUTu hist16Llad; - bool chrop=false; - float val; //preparate for histograms CIECAM if(pW!=1){//only with improccoordinator - dCcurve(65536,0); + dCcurve(48000,0); dLcurve(65536,0); hist16Clad(65536); -// hist16CLlad(65536); -// hist16LLClad(65536); hist16Llad(65536); - - chrop = true; + float val; for (int i=0; i<48000; i++) { //# 32768*1.414 approximation maxi for chroma val = (double)i / 47999.0; dCcurve[i] = CLIPD(val); } - // for (int i=0; i<65535; i++) { // a - // val = (double)i / 65534.0; - // dLcurve[i] = CLIPD(val); - // } for (int i=0; i<65535; i++) { // a val = (double)i / 65534.0; dLcurve[i] = CLIPD(val); } hist16Clad.clear(); - // hist16CLlad.clear(); - // hist16LLClad.clear(); hist16Llad.clear(); } @@ -4401,68 +4390,56 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo(); #endif - - float adjustr=1.0f, adjustbg=1.0f; + float adjustr=1.0f; // if(params->labCurve.avoidclip ){ // parameter to adapt curve C=f(C) to gamut - if (params->icm.working=="ProPhoto") {adjustr = adjustbg = 1.2f;}// 1.2 instead 1.0 because it's very rare to have C>170.. - else if (params->icm.working=="Adobe RGB") {adjustr = 1.8f; adjustbg = 1.4f;} - else if (params->icm.working=="sRGB") {adjustr = 2.0f; adjustbg = 1.7f;} - else if (params->icm.working=="WideGamut") {adjustr = adjustbg = 1.2f;} - else if (params->icm.working=="Beta RGB") {adjustr = adjustbg = 1.4f;} - else if (params->icm.working=="BestRGB") {adjustr = adjustbg = 1.4f;} - else if (params->icm.working=="BruceRGB") {adjustr = 1.8f; adjustbg = 1.5f;} - - //adjustr=1.f; + if (params->icm.working=="ProPhoto") {adjustr = 1.2f;}// 1.2 instead 1.0 because it's very rare to have C>170.. + else if (params->icm.working=="Adobe RGB") {adjustr = 1.8f;} + else if (params->icm.working=="sRGB") {adjustr = 2.0f;} + else if (params->icm.working=="WideGamut") {adjustr = 1.2f;} + else if (params->icm.working=="Beta RGB") {adjustr = 1.4f;} + else if (params->icm.working=="BestRGB") {adjustr = 1.4f;} + else if (params->icm.working=="BruceRGB") {adjustr = 1.8f;} // reference to the params structure has to be done outside of the parallelization to avoid CPU cache problem - bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated - int chromaticity = params->labCurve.chromaticity; - bool bwonly = params->blackwhite.enabled && !params->colorToning.enabled; - bool bwToning = params->labCurve.chromaticity==-100 /*|| params->blackwhite.method=="Ch" || params->blackwhite.enabled */ || bwonly; + const bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated + const int chromaticity = params->labCurve.chromaticity; + const float chromapro = (chromaticity + 100.0f)/100.0f; + const bool bwonly = params->blackwhite.enabled && !params->colorToning.enabled; + const bool bwToning = params->labCurve.chromaticity ==- 100 /*|| params->blackwhite.method=="Ch" || params->blackwhite.enabled */ || bwonly; //if(chromaticity==-100) chromaticity==-99; - bool LCredsk = params->labCurve.lcredsk; - bool ccut = ccutili; - bool clut = clcutili; - bool aut = autili; - bool but = butili; - double rstprotection = 100.-params->labCurve.rstprotection; // Red and Skin Tones Protection + const bool LCredsk = params->labCurve.lcredsk; + const bool ccut = ccutili; + const bool clut = clcutili; + const double rstprotection = 100.-params->labCurve.rstprotection; // Red and Skin Tones Protection // avoid color shift is disabled when bwToning is activated and enabled if gamut is true in colorappearanace - bool avoidColorShift = (params->labCurve.avoidcolorshift || (params->colorappearance.gamut && params->colorappearance.enabled)) && !bwToning ; - int protectRed = settings->protectred; - double protectRedH = settings->protectredh; - bool gamutLch = settings->gamutLch; - float amountchroma = (float) settings->amchroma; - // only if user activate Lab adjustements - if (avoidColorShift) { - if(autili || butili || ccutili || cclutili || chutili || lhutili || hhutili || clcutili || utili || chromaticity) { - unsigned int N = W*H; - float *L = lold->L[0]; - float *a= lold->a[0]; - float *b= lold->b[0]; - float* Lold = new float [N];//to save L before any used - float* Cold = new float [N];//to save C before any used -#ifdef _OPENMP -#pragma omp parallel for if (multiThread) -#endif // _OPENMP - for (unsigned int j=0; jtoneCurve.hrenabled, /*gamut*/true, params->icm.working, multiThread); - delete [] Lold; - delete [] Cold; - } - } + const bool avoidColorShift = (params->labCurve.avoidcolorshift || (params->colorappearance.gamut && params->colorappearance.enabled)) && !bwToning ; + const float protectRed = (float)settings->protectred; + const double protectRedH = settings->protectredh; + float protect_red,protect_redh; + protect_red = protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160 + if(protect_red < 20.0f) protect_red=20.0; // avoid too low value + if(protect_red > 180.0f) protect_red=180.0; // avoid too high value + protect_redh=float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 + if(protect_redh<0.1f) protect_redh=0.1f;//avoid divide by 0 and negatives values + if(protect_redh>1.0f) protect_redh=1.0f;//avoid too big values + float protect_redhcur = protectRedH;//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1 + if(protect_redhcur<0.1f) protect_redhcur=0.1f;//avoid divide by 0 and negatives values:minimal protection for transition + if(protect_redhcur>3.5f) protect_redhcur=3.5f;//avoid too big values -#ifdef _DEBUG -#pragma omp parallel default(shared) firstprivate(highlight, ccut, clut, chromaticity, bwToning, rstprotection, avoidColorShift, LCredsk, protectRed, protectRedH, gamutLch, lold, lnew, MunsDebugInfo, pW) if (multiThread) -#else -#pragma omp parallel default(shared) firstprivate(highlight, ccut, clut, chromaticity, bwToning, rstprotection, avoidColorShift, LCredsk, protectRed, protectRedH, gamutLch, lold, lnew, pW) if (multiThread) -#endif -{ + //increase saturation after denoise : ...approximation + float factnoise=1.f; + if(params->dirpyrDenoise.enabled) { + factnoise=(1.f+params->dirpyrDenoise.chroma/500.f);//levels=5 +// if(yyyy) factnoise=(1.f+params->dirpyrDenoise.chroma/100.f);//levels=7 + } + const float scaleConst = 100.0f/100.1f; + + + const bool gamutLch = settings->gamutLch; + const float amountchroma = (float) settings->amchroma; TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); double wip[3][3] = { @@ -4470,96 +4447,148 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, {wiprof[2][0],wiprof[2][1],wiprof[2][2]} }; - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); - double wp[3][3] = { {wprof[0][0],wprof[0][1],wprof[0][2]}, {wprof[1][0],wprof[1][1],wprof[1][2]}, {wprof[2][0],wprof[2][1],wprof[2][2]}}; +#ifdef _DEBUG +#pragma omp parallel default(shared) firstprivate(highlight, ccut, clut, chromaticity, bwToning, rstprotection, avoidColorShift, LCredsk, protectRed, protectRedH, gamutLch, lold, lnew, MunsDebugInfo, pW) if (multiThread) +#else +#pragma omp parallel if (multiThread) +#endif +{ +#ifdef __SSE2__ + float HHBuffer[W] ALIGNED16; + float CCBuffer[W] ALIGNED16; +#endif #pragma omp for schedule(dynamic, 16) - for (int i=0; iL[i],lold->a[i], lold->b[i], W, /*corMunsell*/true, /*lumaMuns*/false, params->toneCurve.hrenabled, /*gamut*/true, wip, multiThread); + } +#ifdef __SSE2__ + // precalculate some values using SSE + if(bwToning || (!autili && !butili)) { + __m128 c327d68v = _mm_set1_ps(327.68f); + __m128 av,bv; + int k; + for (k=0; ka[i][k]); + bv = LVFU(lold->b[i][k]); + STVF(HHBuffer[k],xatan2f(bv,av)); + STVF(CCBuffer[k],_mm_sqrt_ps(SQRV(av)+SQRV(bv))/c327d68v); + } + for(;kb[i][k],lold->a[i][k]); + CCBuffer[k] = sqrt(SQR(lold->a[i][k]) + SQR(lold->b[i][k]))/327.68f; + } + } +#endif // __SSE2__ for (int j=0; jL[i][j]/327.68f; + const float Lin=lold->L[i][j]; + float LL=Lin/327.68f; float CC; - CC=sqrt(SQR(lold->a[i][j]) + SQR(lold->b[i][j]))/327.68f; float HH; - HH=xatan2f(lold->b[i][j],lold->a[i][j]); - // According to mathematical laws we can get the sin and cos of HH by simple operations - float2 sincosval; - if(CC==0.0f) { - sincosval.y = 1.0f; - sincosval.x = 0.0f; - } else { - sincosval.y = lold->a[i][j]/(CC*327.68f); - sincosval.x = lold->b[i][j]/(CC*327.68f); - } + float Chprov; + float Chprov1; + float memChprov; + float2 sincosval; + if(bwToning) { // this values will be also set when bwToning is false some lines down +#ifdef __SSE2__ + // use precalculated values from above + HH = HHBuffer[j]; + CC = CCBuffer[j]; +#else + HH=xatan2f(lold->b[i][j],lold->a[i][j]); + CC=sqrt(SQR(lold->a[i][j]) + SQR(lold->b[i][j]))/327.68f; +#endif + // According to mathematical laws we can get the sin and cos of HH by simple operations + if(CC==0.0f) { + sincosval.y = 1.0f; + sincosval.x = 0.0f; + } else { + sincosval.y = lold->a[i][j]/(CC*327.68f); + sincosval.x = lold->b[i][j]/(CC*327.68f); + } - float Chprov=CC; - float Chprov1=CC; - float memChprov=Chprov; - - float Lin=lold->L[i][j]; - float Lprov2=Lin/327.68f; + Chprov=CC; + Chprov1=CC; + memChprov=Chprov; + } - if (editID == EUID_Lab_LCurve) + if (editPipette && editID == EUID_Lab_LCurve) editWhatever->v(i,j) = LIM01(Lin/32768.0f);// Lab L pipette lnew->L[i][j] = curve[Lin]; float Lprov1=(lnew->L[i][j])/327.68f; - float chromaChfactor=1.0f; - if (editID == EUID_Lab_aCurve){ - float chromapipa =lold->a[i][j]+(32768.f*1.28f); - editWhatever->v(i,j) = LIM01((chromapipa)/(65536.f*1.28f));}// Lab a pipette - if (editID == EUID_Lab_bCurve){ - float chromapipb =lold->b[i][j]+(32768.f*1.28f); - editWhatever->v(i,j) = LIM01((chromapipb)/(65536.f*1.28f));}//Lab b pipette - + + if(editPipette) { + if (editID == EUID_Lab_aCurve) { // Lab a pipette + float chromapipa =lold->a[i][j]+(32768.f*1.28f); + editWhatever->v(i,j) = LIM01((chromapipa)/(65536.f*1.28f)); + } else if (editID == EUID_Lab_bCurve) { //Lab b pipette + float chromapipb =lold->b[i][j]+(32768.f*1.28f); + editWhatever->v(i,j) = LIM01((chromapipb)/(65536.f*1.28f)); + } + } + float atmp, btmp; - atmp = acurve[lold->a[i][j]+32768.0f]-32768.0f;// curves Lab a - btmp = bcurve[lold->b[i][j]+32768.0f]-32768.0f;// curves Lab b + + atmp = lold->a[i][j]; + if(autili) + atmp = acurve[atmp+32768.0f]-32768.0f;// curves Lab a + + btmp = lold->b[i][j]; + if(butili) + btmp = bcurve[btmp+32768.0f]-32768.0f;// curves Lab b + if(!bwToning) { //take into account modification of 'a' and 'b' - lold->a[i][j]=atmp; - lold->b[i][j]=btmp; - CC=sqrt(SQR(lold->a[i][j]) + SQR(lold->b[i][j]))/327.68f; - HH=xatan2f(lold->b[i][j],lold->a[i][j]); +#ifdef __SSE2__ + if(!autili && !butili) { + // use precalculated values from above + HH = HHBuffer[j]; + CC = CCBuffer[j]; + } else { + CC = sqrt(SQR(atmp) + SQR(btmp))/327.68f; + HH = xatan2f(btmp,atmp); + } +#else + CC=sqrt(SQR(atmp) + SQR(btmp))/327.68f; + HH=xatan2f(btmp,atmp); +#endif // According to mathematical laws we can get the sin and cos of HH by simple operations //float2 sincosval; - if(CC==0.0f) { - sincosval.y = 1.0f; - sincosval.x = 0.0f; + if(CC == 0.f) { + sincosval.y = 1.f; + sincosval.x = 0.f; } else { - sincosval.y = lold->a[i][j]/(CC*327.68f); - sincosval.x = lold->b[i][j]/(CC*327.68f); + sincosval.y = atmp/(CC*327.68f); + sincosval.x = btmp/(CC*327.68f); } Chprov=CC; Chprov1=CC; memChprov=Chprov; } // now new values of lold with 'a' and 'b' - float Chprov2=Chprov1; - int poscc,posp,posl; - bool inRGB; - const float ClipLevel = 65535.0f; - if (editID == EUID_Lab_LHCurve || editID == EUID_Lab_CHCurve || editID == EUID_Lab_HHCurve) {//H pipette - float valpar =Color::huelab_to_huehsv2(HH); - editWhatever->v(i,j) = valpar; - } - - - + if(editPipette) + if (editID == EUID_Lab_LHCurve || editID == EUID_Lab_CHCurve || editID == EUID_Lab_HHCurve) {//H pipette + float valpar =Color::huelab_to_huehsv2(HH); + editWhatever->v(i,j) = valpar; + } + if (lhutili) { // L=f(H) + const float ClipLevel = 65535.f; float l_r;//Luminance Lab in 0..1 l_r = Lprov1/100.f; { - double lr; float khue=1.9f;//in reserve in case of! - float valparam = float((lhCurve->getVal(lr=Color::huelab_to_huehsv2(HH))-0.5f));//get l_r=f(H) + float valparam = float((lhCurve->getVal(Color::huelab_to_huehsv2(HH))-0.5f));//get l_r=f(H) float valparamneg; valparamneg=valparam; float kcc=(CC/amountchroma);//take Chroma into account...40 "middle low" of chromaticity (arbitrary and simple), one can imagine other algorithme @@ -4575,8 +4604,9 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI Lprov1=l_r*100.f; - Chprov2 = sqrt(SQR(atmp/327.68f)+SQR(btmp/327.68f)); + float Chprov2 = sqrt(SQR(atmp)+SQR(btmp))/327.68f; //Gamut control especialy fot negative values slightly different of gamutlchonly + bool inRGB; do { inRGB=true; float aprov1=Chprov2*sincosval.y; @@ -4602,9 +4632,8 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI inRGB = false; } } - while (!inRGB) ; - -// float2 sincosval = xsincosf(HH); + while (!inRGB); + atmp=327.68f*Chprov2*sincosval.y; btmp=327.68f*Chprov2*sincosval.x; } @@ -4613,87 +4642,59 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI if (chutili) { double hr = Color::huelab_to_huehsv2(HH); float chparam = float((chCurve->getVal(hr)-0.5f) * 2.0f);//get C=f(H) - chromaChfactor=1.0f+chparam; + float chromaChfactor=1.0f+chparam; + atmp *= chromaChfactor;//apply C=f(H) + btmp *= chromaChfactor; } - - atmp *= chromaChfactor;//apply C=f(H) - btmp *= chromaChfactor; - + if (hhutili) { // H=f(H) //hue Lab in -PI +PI - double hr; - float valparam = float((hhCurve->getVal(hr=Color::huelab_to_huehsv2(HH))-0.5f) * 1.7f) +HH;//get H=f(H) 1.7 optimisation ! + float valparam = float((hhCurve->getVal(Color::huelab_to_huehsv2(HH))-0.5f) * 1.7f) +HH;//get H=f(H) 1.7 optimisation ! HH = valparam; sincosval = xsincosf(HH); } - - //simulate very approximative gamut f(L) : with pyramid transition - float dred=55.0f;//C red value limit - if (Lprov1<25.0f) dred = 40.0f; - else if(Lprov1<30.0f) dred = 3.0f*Lprov1 -35.0f; - else if(Lprov1<70.0f) dred = 55.0f; - else if(Lprov1<75.0f) dred = -3.0f*Lprov1 +265.0f; - else dred = 40.0f; - // end pyramid - // if(params->dirpyrDenoise.enabled && chromaticity ==0) chromaticity = 0.5f; - + if(!bwToning){ - float factorskin, factorsat, factor, factorskinext, interm; - float scale = 100.0f/100.1f;//reduction in normal zone - float scaleext=1.0f;//reduction in transition zone - float protect_red,protect_redh; - float deltaHH;//HH value transition - protect_red=float(protectRed);//default=60 chroma: one can put more or less if necessary...in 'option' 40...160 - if(protect_red < 20.0f) protect_red=20.0; // avoid too low value - if(protect_red > 180.0f) protect_red=180.0; // avoid too high value - protect_redh=float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 - if(protect_redh<0.1f) protect_redh=0.1f;//avoid divide by 0 and negatives values - if(protect_redh>1.0f) protect_redh=1.0f;//avoid too big values + float factorskin, factorsat, factorskinext; + if(chromapro > 1.f) { + float scale = scaleConst;//reduction in normal zone + float scaleext = 1.f;//reduction in transition zone + Color::scalered ( rstprotection, chromapro, 0.0, HH, protect_redh, scale, scaleext);//1.0 + float interm = (chromapro - 1.f); + factorskin = 1.f + (interm*scale); + factorskinext = 1.f+ (interm*scaleext); + } else { + factorskin = chromapro ; // +(chromapro)*scale; + factorskinext = chromapro ;// +(chromapro)*scaleext; + } + factorsat = chromapro * factnoise; + + //simulate very approximative gamut f(L) : with pyramid transition + float dred /*=55.f*/;//C red value limit + if (Lprov1<25.f) dred = 40.f; + else if(Lprov1<30.f) dred = 3.f * Lprov1 -35.f; + else if(Lprov1<70.f) dred = 55.f; + else if(Lprov1<75.f) dred = -3.f * Lprov1 + 265.f; + else dred = 40.f; + // end pyramid - deltaHH=protect_redh;//transition hue - float chromapro = (chromaticity + 100.0f)/100.0f; - if(chromapro>0.0) Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//1.0 - if(chromapro>1.0) { - interm=(chromapro-1.0f)*100.0f; - factorskin= 1.0f+(interm*scale)/100.0f; - factorskinext=1.0f+(interm*scaleext)/100.0f; - } - else { - //factorskin= chromapro*scale; - //factorskinext= chromapro*scaleext; - factorskin= chromapro ; // +(chromapro)*scale; - factorskinext= chromapro ;// +(chromapro)*scaleext; - - } - factorsat=chromapro; - //increase saturation after denoise : ...approximation - float factnoise=1.f; - if(params->dirpyrDenoise.enabled) { - factnoise=(1.f+params->dirpyrDenoise.chroma/500.f);//levels=5 - - - // if(yyyy) factnoise=(1.f+params->dirpyrDenoise.chroma/100.f);//levels=7 - } - factorsat*=factnoise; - - factor=factorsat; // Test if chroma is in the normal range first - Color::transitred ( HH, Chprov1, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); - atmp *= factor; - btmp *= factor; - if (editID == EUID_Lab_CLCurve) - editWhatever->v(i,j) = LIM01(Lprov2/100.f);// Lab C=f(L) pipette + Color::transitred ( HH, Chprov1, dred, factorskin, protect_red, factorskinext, protect_redh, factorsat, factorsat); + atmp *= factorsat; + btmp *= factorsat; + + if (editPipette && editID == EUID_Lab_CLCurve) + editWhatever->v(i,j) = LIM01(LL/100.f);// Lab C=f(L) pipette if (clut) { // begin C=f(L) float factorskin,factorsat,factor,factorskinext,interm; - float chroma = sqrt(SQR(atmp)+SQR(btmp)+0.001f); - float chromaCfactor=(clcurve[Lprov2*655.35f])/(Lprov2*655.35f);//apply C=f(L) + float chromaCfactor=(clcurve[LL*655.35f])/(LL*655.35f);//apply C=f(L) float curf=0.7f;//empirical coeff because curve is more progressive float scale = 100.0f/100.1f;//reduction in normal zone for curve C float scaleext=1.0f;//reduction in transition zone for curve C float protect_redcur,protect_redhcur;//perhaps the same value than protect_red and protect_redh float deltaHH;//HH value transition for C curve - protect_redcur=curf*float(protectRed);//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive + protect_redcur=curf*protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive if(protect_redcur < 20.0f) protect_redcur=20.0; // avoid too low value if(protect_redcur > 180.0f) protect_redcur=180.0; // avoid too high value protect_redhcur=curf*float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 ==> curf =because curve is more progressive @@ -4723,7 +4724,7 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI // editWhatever->v(i,j) = LIM01(Lprov2/100.f);// Lab C=f(L) pipette // I have placed C=f(C) after all C treatments to assure maximum amplitude of "C" - if (editID == EUID_Lab_CCurve){ + if (editPipette && editID == EUID_Lab_CCurve){ float chromapip = sqrt(SQR(atmp)+SQR(btmp)+0.001f); editWhatever->v(i,j) = LIM01((chromapip)/(48000.f));}//Lab C=f(C) pipette @@ -4736,7 +4737,7 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI float scaleext=1.0f;//reduction in transition zone for curve CC float protect_redcur,protect_redhcur;//perhaps the same value than protect_red and protect_redh float deltaHH;//HH value transition for CC curve - protect_redcur=curf*float(protectRed);//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive + protect_redcur=curf*protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive if(protect_redcur < 20.0f) protect_redcur=20.0; // avoid too low value if(protect_redcur > 180.0f) protect_redcur=180.0; // avoid too high value protect_redhcur=curf*float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 ==> curf =because curve is more progressive @@ -4764,38 +4765,27 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI atmp *= factor; btmp *= factor; } - // if (editID == EUID_Lab_CCurve){ - // float chromapip = sqrt(SQR(atmp)+SQR(btmp)+0.001f); - // editWhatever->v(i,j) = LIM01((chromapip)/(48000.f));}//Lab C=f(C) pipette - } // end chroma C=f(C) //update histogram C if(pW!=1){//only with improccoordinator - posp=CLIP((int)sqrt((atmp*atmp + btmp*btmp))); + int posp=CLIP((int)sqrt((atmp*atmp + btmp*btmp))); hist16Clad[posp]++; - // hist16CLlad[posp]++; - // hist16LLClad[posp]++; - } - if (editID == EUID_Lab_LCCurve){ - float chromapiplc = sqrt(SQR(atmp)+SQR(btmp)+0.001f); - editWhatever->v(i,j) = LIM01((chromapiplc)/(48000.f));}//Lab L=f(C) pipette + if (editPipette && editID == EUID_Lab_LCCurve){ + float chromapiplc = sqrt(SQR(atmp)+SQR(btmp)+0.001f); + editWhatever->v(i,j) = LIM01((chromapiplc)/(48000.f)); + }//Lab L=f(C) pipette - if (!bwToning) { //apply curve L=f(C) for skin and rd...but also for extended color ==> near green and blue (see 'curf') + if (cclutili && !bwToning) { //apply curve L=f(C) for skin and rd...but also for extended color ==> near green and blue (see 'curf') const float xx=0.25f;//soft : between 0.2 and 0.4 - float protect_redhcur; - float curf=1.0f; - float deltaHH; - protect_redhcur=curf*float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1 - if(protect_redhcur<0.1f) protect_redhcur=0.1f;//avoid divide by 0 and negatives values:minimal protection for transition - if(protect_redhcur>3.5f) protect_redhcur=3.5f;//avoid too big values + float skdeltaHH; - deltaHH=protect_redhcur;//transition hue + skdeltaHH=protect_redhcur;//transition hue float skbeg=-0.05f;//begin hue skin float skend=1.60f;//end hue skin @@ -4803,28 +4793,39 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI float aa,bb; float zz=0.0f; float yy=0.0f; - if(Chprov1 < chrmin) yy=(Chprov1/chrmin)*(Chprov1/chrmin)*xx;else yy=xx;//avoid artifact for low C - if(!LCredsk) {skbeg=-3.1415; skend=3.14159; deltaHH=0.001f;} - if(HH>skbeg && HH < skend ) zz=yy; - else if(HH>skbeg-deltaHH && HH<=skbeg) {aa=yy/deltaHH;bb=-aa*(skbeg-deltaHH); zz=aa*HH+bb;}//transition - else if(HH>=skend && HH < skend+deltaHH) {aa=-yy/deltaHH;bb=-aa*(skend+deltaHH);zz=aa*HH+bb;}//transition + if(Chprov1 < chrmin) + yy=SQR(Chprov1/chrmin)*xx; + else + yy=xx;//avoid artifact for low C + if(!LCredsk) { + skbeg=-3.1415; + skend=3.14159; + skdeltaHH=0.001f; + } + if(HH>skbeg && HH < skend ) { + zz=yy; + } else if(HH>skbeg-skdeltaHH && HH<=skbeg) { //transition + aa=yy/skdeltaHH; + bb=-aa*(skbeg-skdeltaHH); + zz=aa*HH+bb; + } else if(HH>=skend && HH < skend+skdeltaHH) { //transition + aa=-yy/skdeltaHH; + bb=-aa*(skend+skdeltaHH); + zz=aa*HH+bb; + } float chroma=sqrt(SQR(atmp)+SQR(btmp)+0.001f); float Lc = (lhskcurve[chroma*adjustr])/(chroma*adjustr);//apply L=f(C) Lc=(Lc-1.0f)*zz+1.0f;//reduct action Lprov1*=Lc;//adjust luminance - } - //update histo LC - if(pW!=1){//only with improccoordinator - posl=CLIP((int(Lprov1*327.68f))); - int posll=CLIP((int(Chprov1*327.68f))); - - //hist16LLClad[posll]++; - hist16Llad[posl]++; - - } + } + //update histo LC + if(pW!=1){//only with improccoordinator + int posl=CLIP((int(Lprov1*327.68f))); + hist16Llad[posl]++; + } - Chprov1 = sqrt(SQR(atmp/327.68f)+SQR(btmp/327.68f)); + Chprov1 = sqrt(SQR(atmp)+SQR(btmp))/327.68f; // labCurve.bwtoning option allows to decouple modulation of a & b curves by saturation // with bwtoning enabled the net effect of a & b curves is visible @@ -4842,17 +4843,16 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI bool neg=false; bool more_rgb=false; //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); + Color::gamutLchonly(HH, sincosval, Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); #else //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); + Color::gamutLchonly(HH, sincosval,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); #endif lnew->L[i][j]=Lprov1*327.68f; // float2 sincosval = xsincosf(HH); lnew->a[i][j]=327.68f*Chprov1*sincosval.y; lnew->b[i][j]=327.68f*Chprov1*sincosval.x; - } - else { + } else { //use gamutbdy //Luv limiter float Y,u,v; @@ -4862,32 +4862,32 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI } if (utili || autili || butili || ccut || clut || cclutili || chutili || lhutili || hhutili || clcutili || chromaticity) { - float correctionHue=0.0f; // Munsell's correction - float correctlum=0.0f; + float correctionHue=0.f; // Munsell's correction + float correctlum=0.f; Lprov1=lnew->L[i][j]/327.68f; - Chprov=sqrt(SQR(lnew->a[i][j]/327.68f)+ SQR(lnew->b[i][j]/327.68f)); + Chprov=sqrt(SQR(lnew->a[i][j])+ SQR(lnew->b[i][j]))/327.68f; #ifdef _DEBUG - Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,Lprov2,HH,Chprov,memChprov,correctionHue,correctlum, MunsDebugInfo); + Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,LL,HH,Chprov,memChprov,correctionHue,correctlum, MunsDebugInfo); #else - Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,Lprov2,HH,Chprov,memChprov,correctionHue,correctlum); + Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,LL,HH,Chprov,memChprov,correctionHue,correctlum); #endif - - if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little. - /* if((HH>0.0f && HH < 1.6f) && memChprov < 70.0f) HH+=correctlum;//skin correct - else if(fabs(correctionHue) < 0.3f) HH+=0.08f*correctlum; - else if(fabs(correctionHue) < 0.2f) HH+=0.25f*correctlum; - else if(fabs(correctionHue) < 0.1f) HH+=0.35f*correctlum; - else if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little. - */ - float2 sincosval = xsincosf(HH+correctionHue); - + if(correctionHue != 0.f || correctlum != 0.f) { + if(fabs(correctionHue) < 0.015f) + HH+=correctlum; // correct only if correct Munsell chroma very little. + /* if((HH>0.0f && HH < 1.6f) && memChprov < 70.0f) HH+=correctlum;//skin correct + else if(fabs(correctionHue) < 0.3f) HH+=0.08f*correctlum; + else if(fabs(correctionHue) < 0.2f) HH+=0.25f*correctlum; + else if(fabs(correctionHue) < 0.1f) HH+=0.35f*correctlum; + else if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little. + */ + sincosval = xsincosf(HH+correctionHue); + } lnew->a[i][j]=327.68f*Chprov*sincosval.y;// apply Munsell lnew->b[i][j]=327.68f*Chprov*sincosval.x; } - } - else { + } else { // if(Lprov1 > maxlp) maxlp=Lprov1; // if(Lprov1 < minlp) minlp=Lprov1; if(!bwToning){ @@ -4902,34 +4902,23 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI lnew->b[i][j] = btmp; } } - // } } - + } } // end of parallelization //update histogram C with data chromaticity and not with CC curve if(pW!=1){//only with improccoordinator for (int i=0; i<48000; i++) {//32768*1.414 + ... - if (chrop) { - float hval = dCcurve[i]; - int hi = (int)(255.0*CLIPD(hval)); // - histCCurve[hi] += hist16Clad[i] ; - // histCLurve[hi] += hist16CLlad[i] ; - // histLLCurve[hi] += hist16LLClad[i] ; - - } + float hval = dCcurve[i]; + int hi = (int)(255.0*CLIPD(hval)); // + histCCurve[hi] += hist16Clad[i] ; } //update histogram L with data luminance for (int i=0; i<65535; i++) { - if (chrop) { - float hlval = dLcurve[i]; - int hli = (int)(255.0*CLIPD(hlval)); - histLCurve[hli] += hist16Llad[i] ; - // histLLCurve[hli] += hist16LLClad[i] ; - - } - } - + float hlval = dLcurve[i]; + int hli = (int)(255.0*CLIPD(hlval)); + histLCurve[hli] += hist16Llad[i] ; + } } #ifdef _DEBUG