Merge pull request #5275 from Beep6581/newlocallab-dedup-localcontrast

locallab: dedup localcontrast code
This commit is contained in:
Ingo Weyrich 2019-04-10 16:17:51 +02:00 committed by GitHub
commit a72ea75580
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 123 deletions

View File

@ -3693,7 +3693,7 @@ void ImProcFunctions::rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer
if (params->localContrast.enabled) { if (params->localContrast.enabled) {
// Alberto's local contrast // Alberto's local contrast
localContrast(lab); localContrast(lab, lab->L, params->localContrast, scale);
} }
} }

View File

@ -46,6 +46,7 @@ class ProcParams;
struct DehazeParams; struct DehazeParams;
struct DirPyrDenoiseParams; struct DirPyrDenoiseParams;
struct LocalContrastParams;
struct LocallabParams; struct LocallabParams;
struct SharpeningParams; struct SharpeningParams;
struct SoftLightParams; struct SoftLightParams;
@ -404,8 +405,7 @@ public:
void dehaze(Imagefloat *rgb, const DehazeParams &dehazeParams); void dehaze(Imagefloat *rgb, const DehazeParams &dehazeParams);
void ToneMapFattal02(Imagefloat *rgb); void ToneMapFattal02(Imagefloat *rgb);
void localContrast(LabImage *lab); void localContrast(LabImage *lab, float **destination, const LocalContrastParams &localContrastParams, double scale);
void localContrastloc(LabImage *lab, int scale, int rad, float amo, float darkn, float lightn, float **loctemp);
void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread); void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread);
// void shadowsHighlights(LabImage *lab); // void shadowsHighlights(LabImage *lab);
void shadowsHighlights(LabImage *lab, bool ena, int labmode, int hightli, int shado, int rad, int scal, int hltonal, int shtonal); void shadowsHighlights(LabImage *lab, bool ena, int labmode, int hightli, int shado, int rad, int scal, int hltonal, int shtonal);

View File

@ -34,19 +34,19 @@
namespace rtengine 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; return;
} }
const int width = lab->W; const int width = lab->W;
const int height = lab->H; const int height = lab->H;
const float a = params->localContrast.amount; const float a = localContrastParams.amount;
const float dark = params->localContrast.darkness; const float dark = localContrastParams.darkness;
const float light = params->localContrast.lightness; const float light = localContrastParams.lightness;
array2D<float> buf(width, height); array2D<float> buf(width, height);
const float sigma = params->localContrast.radius / scale; const float sigma = localContrastParams.radius / scale;
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel if(multiThread) #pragma omp parallel if(multiThread)
@ -65,41 +65,7 @@ void ImProcFunctions::localContrast(LabImage *lab)
bufval *= (bufval > 0.f) ? light : dark; bufval *= (bufval > 0.f) ? light : dark;
} }
lab->L[y][x] = std::max(0.0001f, lab->L[y][x] + bufval); destination[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<float> 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);
} }
} }
} }

View File

@ -2064,47 +2064,43 @@ 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 BENCHFUN
const float ach = (float)lp.trans / 100.f; const float ach = lp.trans / 100.f;
float varsens = lp.senssha; const float varsens = senstype == 1 ? lp.senslc : lp.senssha;
if (senstype == 0) {
varsens = lp.senssha;
} else if (senstype == 1) {
varsens = lp.senslc;
}
//balance deltaE //balance deltaE
float kL = lp.balance; float kL = lp.balance;
float kab = 1.f; float kab = 1.f;
balancedeltaE(kL, kab); balancedeltaE(kL, kab);
kab /= SQR(327.68f);
kL /= SQR(327.68f);
int GW = transformed->W; const int GW = transformed->W;
int GH = transformed->H; const int GH = transformed->H;
LabImage *origblur = new LabImage(GW, GH); std::unique_ptr<LabImage> origblur(new LabImage(GW, GH));
float refa = chromaref * cos(hueref); const float refa = chromaref * cos(hueref) * 327.68f;
float refb = chromaref * sin(hueref); 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 #ifdef _OPENMP
#pragma omp parallel #pragma omp parallel if (multiThread)
#endif #endif
{ {
gaussianBlur(original->L, origblur->L, GW, GH, radius); gaussianBlur(original->L, origblur->L, GW, GH, radius);
gaussianBlur(original->a, origblur->a, GW, GH, radius); gaussianBlur(original->a, origblur->a, GW, GH, radius);
gaussianBlur(original->b, origblur->b, GW, GH, radius); gaussianBlur(original->b, origblur->b, GW, GH, radius);
} }
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel if (multiThread) #pragma omp parallel if (multiThread)
#endif #endif
{ {
const int begy = int (lp.yc - lp.lyT);
const int begx = int (lp.xc - lp.lxL);
const int limscope = 80; const int limscope = 80;
const float mindE = 2.f + MINSCOPE * varsens * lp.thr; const float mindE = 2.f + MINSCOPE * varsens * lp.thr;
const float maxdE = 5.f + MAXSCOPE * varsens * (1 + 0.1f * lp.thr); const float maxdE = 5.f + MAXSCOPE * varsens * (1 + 0.1f * lp.thr);
@ -2116,24 +2112,17 @@ void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, cons
#endif #endif
for (int y = 0; y < transformed->H; y++) { for (int y = 0; y < transformed->H; y++) {
const int loy = cy + 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 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 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; continue;
} }
for (int x = 0; x < transformed->W; x++) { for (int x = 0; x < transformed->W; x++) {
int lox = cx + x; const int lox = cx + x;
int zone = 0; int zone = 0;
float localFactor = 1.f; float localFactor = 1.f;
int begx = int (lp.xc - lp.lxL);
int begy = int (lp.yc - lp.lyT);
if (lp.shapmet == 0) { if (lp.shapmet == 0) {
calcTransition(lox, loy, ach, lp, zone, localFactor); calcTransition(lox, loy, ach, lp, zone, localFactor);
@ -2142,36 +2131,15 @@ 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 if (zone == 0) { // outside selection and outside transition zone => no effect, keep original values
transformed->L[y][x] = original->L[y][x];
continue; continue;
} }
float rL = origblur->L[y][x] / 327.68f; 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 dE = sqrt(kab * SQR(refa - origblur->a[y][x] / 327.68f) + kab * SQR(refb - origblur->b[y][x] / 327.68f) + kL * SQR(lumaref - rL));
float reducdE = 0.f; float reducdE = 0.f;
calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, varsens , reducdE); calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, varsens , reducdE);
reducdE *= localFactor;
switch (zone) {
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; float difL;
if (call == 2) { if (call == 2) {
@ -2179,18 +2147,12 @@ void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, cons
} else { } else {
difL = loctemp[y][x] - original->L[y][x]; difL = loctemp[y][x] - original->L[y][x];
} }
transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); 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) 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)
{ {
@ -5626,10 +5588,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 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; int bfw = call == 2 ? int (lp.lx + lp.lxL) + del : original->W;
JaggedArray<float> loctemp(bfw, bfh); JaggedArray<float> loctemp(bfw, bfh);
LabImage *bufloca = nullptr; std::unique_ptr<LabImage> bufloca;
LabImage *localContrastSource;
if (call == 2) { //call from simpleprocess if (call == 2) { //call from simpleprocess
bufloca = new LabImage(bfw, bfh); bufloca.reset(new LabImage(bfw, bfh));
// JaggedArray<float> hbuffer(bfw, bfh); // JaggedArray<float> hbuffer(bfw, bfh);
int begy = lp.yc - lp.lyT; int begy = lp.yc - lp.lyT;
@ -5641,29 +5604,32 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o
#pragma omp parallel for schedule(dynamic,16) #pragma omp parallel for schedule(dynamic,16)
#endif #endif
for (int y = 0; y < transformed->H ; y++) //{ 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++) { for (int x = 0; x < transformed->W; x++) {
int lox = cx + x; const int lox = cx + x;
int loy = cy + y; if (lox >= begx && lox < xEn) {
if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) {
bufloca->L[loy - begy][lox - begx] = original->L[y][x]; bufloca->L[loy - begy][lox - begx] = original->L[y][x];
} }
} }
}
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);
} 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);
} }
localContrastSource = bufloca.get();
} else { //call from dcrop.cc
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 //sharpen ellipse and transition
Sharp_Local(call, loctemp, 1, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); Sharp_Local(call, loctemp, 1, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
delete bufloca;
} }