From 089f2e9953baf51b836bac12620293f0f175fe8a Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 10 Apr 2019 15:29:23 +0200 Subject: [PATCH 1/2] locallab: dedup localcontrast code --- rtengine/improcfun.cc | 2 +- rtengine/improcfun.h | 4 +- rtengine/iplocalcontrast.cc | 48 ++----------- rtengine/iplocallab.cc | 137 +++++++++++++----------------------- 4 files changed, 60 insertions(+), 131 deletions(-) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 08891d926..d8effc87c 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3693,7 +3693,7 @@ void ImProcFunctions::rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer if (params->localContrast.enabled) { // Alberto's local contrast - localContrast(lab); + localContrast(lab, lab->L, params->localContrast, scale); } } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index bb2a4168b..fcb7ee235 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -46,6 +46,7 @@ class ProcParams; struct DehazeParams; struct DirPyrDenoiseParams; +struct LocalContrastParams; struct LocallabParams; struct SharpeningParams; struct SoftLightParams; @@ -404,8 +405,7 @@ public: void dehaze(Imagefloat *rgb, const DehazeParams &dehazeParams); void ToneMapFattal02(Imagefloat *rgb); - void localContrast(LabImage *lab); - void localContrastloc(LabImage *lab, int scale, int rad, float amo, float darkn, float lightn, float **loctemp); + void localContrast(LabImage *lab, float **destination, const LocalContrastParams &localContrastParams, double scale); void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread); // void shadowsHighlights(LabImage *lab); void shadowsHighlights(LabImage *lab, bool ena, int labmode, int hightli, int shado, int rad, int scal, int hltonal, int shtonal); diff --git a/rtengine/iplocalcontrast.cc b/rtengine/iplocalcontrast.cc index e57bba5c3..3e3a9690e 100644 --- a/rtengine/iplocalcontrast.cc +++ b/rtengine/iplocalcontrast.cc @@ -34,19 +34,19 @@ namespace rtengine { -void ImProcFunctions::localContrast(LabImage *lab) +void ImProcFunctions::localContrast(LabImage *lab, float **destination, const LocalContrastParams &localContrastParams, double scale) { - if (!params->localContrast.enabled) { + if (!localContrastParams.enabled) { return; } const int width = lab->W; const int height = lab->H; - const float a = params->localContrast.amount; - const float dark = params->localContrast.darkness; - const float light = params->localContrast.lightness; + const float a = localContrastParams.amount; + const float dark = localContrastParams.darkness; + const float light = localContrastParams.lightness; array2D buf(width, height); - const float sigma = params->localContrast.radius / scale; + const float sigma = localContrastParams.radius / scale; #ifdef _OPENMP #pragma omp parallel if(multiThread) @@ -65,41 +65,7 @@ void ImProcFunctions::localContrast(LabImage *lab) bufval *= (bufval > 0.f) ? light : dark; } - lab->L[y][x] = std::max(0.0001f, lab->L[y][x] + bufval); - } - } -} - -void ImProcFunctions::localContrastloc(LabImage *lab, int scale, int rad, float amo, float darkn, float lightn, float **loctemp) -{ - - const int width = lab->W; - const int height = lab->H; - const float a = amo; - const float dark = darkn; - const float light = lightn; - array2D buf(width, height); - const float sigma = (float)(rad) / scale; - -#ifdef _OPENMP - #pragma omp parallel if(multiThread) -#endif - gaussianBlur(lab->L, buf, width, height, sigma); - -#ifdef _OPENMP - #pragma omp parallel for if(multiThread) -#endif - - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - float bufval = (lab->L[y][x] - buf[y][x]) * a; - - if (dark != 1 || light != 1) { - bufval *= (bufval > 0.f) ? light : dark; - } - - loctemp[y][x] = std::max(0.0001f, lab->L[y][x] + bufval); - + destination[y][x] = std::max(0.0001f, lab->L[y][x] + bufval); } } } diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index f61a3c31d..29ab5e868 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -2092,71 +2092,62 @@ void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueref, co } -void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, const float hueref, const float chromaref, const float lumaref, const local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) +void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, const float hueref, const float chromaref, const float lumaref, const local_params &lp, LabImage *original, LabImage *transformed, int cx, int cy, int sk) { BENCHFUN - const float ach = (float)lp.trans / 100.f; - float varsens = lp.senssha; - - if (senstype == 0) { - varsens = lp.senssha; - - } else if (senstype == 1) { - varsens = lp.senslc; - } + const float ach = lp.trans / 100.f; + const float varsens = senstype == 1 ? lp.senslc : lp.senssha; //balance deltaE float kL = lp.balance; float kab = 1.f; balancedeltaE(kL, kab); + kab /= SQR(327.68f); + kL /= SQR(327.68f); - int GW = transformed->W; - int GH = transformed->H; + const int GW = transformed->W; + const int GH = transformed->H; - LabImage *origblur = new LabImage(GW, GH); - float refa = chromaref * cos(hueref); - float refb = chromaref * sin(hueref); + std::unique_ptr origblur(new LabImage(GW, GH)); + const float refa = chromaref * cos(hueref) * 327.68f; + const float refb = chromaref * sin(hueref) * 327.68f; + const float refL = lumaref * 327.68f; + const float radius = 3.f / sk; - - float radius = 3.f / sk; #ifdef _OPENMP - #pragma omp parallel + #pragma omp parallel if (multiThread) #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 { + const int begy = int (lp.yc - lp.lyT); + const int begx = int (lp.xc - lp.lxL); + const float mindE = 2.f + MINSCOPE * varsens * lp.thr; + const float maxdE = 5.f + MAXSCOPE * varsens * (1 + 0.1f * lp.thr); #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; } for (int x = 0; x < transformed->W; x++) { - int lox = cx + x; + const int lox = cx + x; int zone = 0; float localFactor = 1.f; - int begx = int (lp.xc - lp.lxL); - int begy = int (lp.yc - lp.lyT); if (lp.shapmet == 0) { calcTransition(lox, loy, ach, lp, zone, localFactor); @@ -2165,78 +2156,40 @@ void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, cons } if (zone == 0) { // outside selection and outside transition zone => no effect, keep original values - transformed->L[y][x] = original->L[y][x]; continue; } - float rL = origblur->L[y][x] / 327.68f; - float dE = sqrt(kab * SQR(refa - origblur->a[y][x] / 327.68f) + kab * SQR(refb - origblur->b[y][x] / 327.68f) + kL * SQR(lumaref - rL)); + const float dE = sqrt(kab * (SQR(refa - origblur->a[y][x]) + SQR(refb - origblur->b[y][x])) + kL * SQR(refL - origblur->L[y][x])); - float reducdE = 0.f; - float mindE = 2.f + MINSCOPE * varsens * lp.thr; - float maxdE = 5.f + MAXSCOPE * varsens * (1 + 0.1f * lp.thr); - - float ar = 1.f / (mindE - maxdE); - - float br = - ar * maxdE; - - if (dE > maxdE) { - reducdE = 0.f; - } - - if (dE > mindE && dE <= maxdE) { - reducdE = ar * dE + br; - } - - if (dE <= mindE) { - reducdE = 1.f; - } - - reducdE = pow(reducdE, lp.iterat); + float reducdE; if (varsens > 99) { reducdE = 1.f; + } else if (dE > maxdE) { + reducdE = 0.f; + } else if (dE > mindE && dE <= maxdE) { + const float ar = 1.f / (mindE - maxdE); + const float br = - ar * maxdE; + reducdE = ar * dE + br; + reducdE = pow(reducdE, lp.iterat); + } else { + reducdE = 1.f; } + reducdE *= localFactor; - switch (zone) { + float difL; - case 1: { // inside transition zone - float factorx = localFactor; - float difL; - - if (call == 2) { - difL = loctemp[loy - begy][lox - begx] - original->L[y][x]; - } else { - difL = loctemp[y][x] - original->L[y][x]; - - } - - difL *= factorx; - transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); - - break; - } - - case 2: { // inside selection => full effect, no transition - float difL; - - if (call == 2) { - difL = loctemp[loy - begy][lox - begx] - original->L[y][x]; - } else { - difL = loctemp[y][x] - original->L[y][x]; - } - - transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); - } + if (call == 2) { + difL = loctemp[loy - begy][lox - begx] - original->L[y][x]; + } else { + difL = loctemp[y][x] - original->L[y][x]; } + transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); } } } - delete origblur; } - - void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromaref, float lumaref, float sobelref, float meansobel, const struct local_params & lp, const LabImage * original, LabImage * transformed, const LabImage * rsv, const LabImage * reserv, int cx, int cy, int sk) { @@ -5810,12 +5763,22 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } } - ImProcFunctions::localContrastloc(bufloca, sk, params->locallab.spots.at(sp).lcradius, params->locallab.spots.at(sp).lcamount, params->locallab.spots.at(sp).lcdarkness, params->locallab.spots.at(sp).lightness, loctemp); + LocalContrastParams localContrastParams; + localContrastParams.enabled = true; + localContrastParams.radius = params->locallab.spots.at(sp).lcradius; + localContrastParams.amount = params->locallab.spots.at(sp).lcamount; + localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; + localContrastParams.lightness = params->locallab.spots.at(sp).lightness; + ImProcFunctions::localContrast(bufloca, loctemp, localContrastParams, sk); } else { //call from dcrop.cc - - ImProcFunctions::localContrastloc(original, sk, params->locallab.spots.at(sp).lcradius, params->locallab.spots.at(sp).lcamount, params->locallab.spots.at(sp).lcdarkness, params->locallab.spots.at(sp).lightness, loctemp); - + LocalContrastParams localContrastParams; + localContrastParams.enabled = true; + localContrastParams.radius = params->locallab.spots.at(sp).lcradius; + localContrastParams.amount = params->locallab.spots.at(sp).lcamount; + localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; + localContrastParams.lightness = params->locallab.spots.at(sp).lightness; + ImProcFunctions::localContrast(original, loctemp, localContrastParams, sk); } From 7294be47b9cffc740dd280a0eebf355c1f59560b Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 10 Apr 2019 15:58:06 +0200 Subject: [PATCH 2/2] locallab: further cleanup for localcontrast --- rtengine/iplocallab.cc | 48 ++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 29ab5e868..bd0633b9a 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -5738,10 +5738,11 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o int bfh = call == 2 ? int (lp.ly + lp.lyT) + del : original->H; //bfw bfh real size of square zone int bfw = call == 2 ? int (lp.lx + lp.lxL) + del : original->W; JaggedArray loctemp(bfw, bfh); - LabImage *bufloca = nullptr; + std::unique_ptr bufloca; + LabImage *localContrastSource; if (call == 2) { //call from simpleprocess - bufloca = new LabImage(bfw, bfh); + bufloca.reset(new LabImage(bfw, bfh)); // JaggedArray hbuffer(bfw, bfh); int begy = lp.yc - lp.lyT; @@ -5753,39 +5754,32 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o #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) { - bufloca->L[loy - begy][lox - begx] = original->L[y][x]; + for (int y = 0; y < transformed->H ; y++) { + const int loy = cy + y; + if (loy >= begy && loy < yEn) { + for (int x = 0; x < transformed->W; x++) { + const int lox = cx + x; + if (lox >= begx && lox < xEn) { + bufloca->L[loy - begy][lox - begx] = original->L[y][x]; + } } } + } - LocalContrastParams localContrastParams; - localContrastParams.enabled = true; - localContrastParams.radius = params->locallab.spots.at(sp).lcradius; - localContrastParams.amount = params->locallab.spots.at(sp).lcamount; - localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; - localContrastParams.lightness = params->locallab.spots.at(sp).lightness; - ImProcFunctions::localContrast(bufloca, loctemp, localContrastParams, sk); - + localContrastSource = bufloca.get(); } else { //call from dcrop.cc - LocalContrastParams localContrastParams; - localContrastParams.enabled = true; - localContrastParams.radius = params->locallab.spots.at(sp).lcradius; - localContrastParams.amount = params->locallab.spots.at(sp).lcamount; - localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; - localContrastParams.lightness = params->locallab.spots.at(sp).lightness; - ImProcFunctions::localContrast(original, loctemp, localContrastParams, sk); + localContrastSource = original; } - + LocalContrastParams localContrastParams; + localContrastParams.enabled = true; + localContrastParams.radius = params->locallab.spots.at(sp).lcradius; + localContrastParams.amount = params->locallab.spots.at(sp).lcamount; + localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; + localContrastParams.lightness = params->locallab.spots.at(sp).lightness; + ImProcFunctions::localContrast(localContrastSource, loctemp, localContrastParams, sk); //sharpen ellipse and transition Sharp_Local(call, loctemp, 1, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); - - delete bufloca; }