From 882f14f7dcaa6bf6be1f29c31d3d7e4293fd6ac2 Mon Sep 17 00:00:00 2001 From: Desmis Date: Wed, 14 Aug 2019 09:46:30 +0200 Subject: [PATCH] Change Mask Blur to be used by Denoise --- rtdata/languages/default | 3 +- rtengine/improcfun.h | 2 +- rtengine/iplocallab.cc | 842 +++++++++++++++++++++------------------ rtgui/locallab.cc | 322 +++++++-------- 4 files changed, 615 insertions(+), 554 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index fe5f3ee05..28fa864b5 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2172,7 +2172,7 @@ TP_LOCALLAB_VART;Contrast (variance) TP_LOCALLAB_SENSI;Scope TP_LOCALLAB_SENSI_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_SENSIH;Scope -TP_LOCALLAB_SENSIH_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_SENSIH_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_SHAPETYPE;Shape RT-spot area TP_LOCALLAB_SHAPE_TOOLTIP;Rectangle is only in normal mode. TP_LOCALLAB_ELI;Elipse @@ -2191,6 +2191,7 @@ TP_LOCALLAB_SENSIS_TOOLTIP;Adjust scope of action:\nSmall values limit action to TP_LOCALLAB_SETTINGS;Settings TP_LOCALLAB_ENABLE_MASK;Enable mask TP_LOCALLAB_SHOW;Mask and modifications +TP_LOCALLAB_SHOWPLUS;Mask and modifications - Smooth-Blur & Denoise TP_LOCALLAB_SHOWMASKCOL_TOOLTIP;Display modifications.\nBeware, you can only view one modification (color and light or Exposure or Shadows-Highlight or TM or CBDL or Retinex MSR or Blur).\n\nUse Mask is before algorihtm shape detection TP_LOCALLAB_SHOWMNONE;None TP_LOCALLAB_SHOWMODIF;Show modifications whithout mask diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index f20de4fea..5ffdf59b5 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -333,7 +333,7 @@ public: void exlabLocal(const local_params& lp, int bfh, int bfw, LabImage* bufexporig, LabImage* lab, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, float mean); void 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 DeNoise_Local(int call, const struct local_params& lp, int levred, float hueref, float lumaref, float chromaref, LabImage* original, LabImage* transformed, LabImage &tmp1, int cx, int cy, int sk); + void DeNoise_Local(int call, const struct local_params& lp, LabImage * originalmask, int levred, float hueref, float lumaref, float chromaref, 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); diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 2684d126f..0e4ebe84b 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -1486,7 +1486,7 @@ static void calcreducdE(float dE, float maxdE, float mindE, float maxdElim, flo } } } -void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, int levred, float hueref, float lumaref, float chromaref, LabImage* original, LabImage* transformed, LabImage &tmp1, int cx, int cy, int sk) +void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, LabImage*originalmask, int levred, float hueref, float lumaref, float chromaref, LabImage* original, LabImage* transformed, LabImage &tmp1, int cx, int cy, int sk) { //warning, but I hope used it next // local denoise and impulse @@ -1502,10 +1502,29 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in const int GH = transformed->H; const float refa = chromaref * cos(hueref); const float refb = chromaref * sin(hueref); + const bool usemaskbl = (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 4); + const bool usemaskall = (usemaskbl); + const bool blshow = ((lp.showmaskblmet == 1 || lp.showmaskblmet == 2)); + const bool previewbl = ((lp.showmaskblmet == 4)); std::unique_ptr origblur(new LabImage(GW, GH)); + std::unique_ptr origblurmask; const float radius = 3.f / sk; + + if (usemaskall) { + origblurmask.reset(new LabImage(GW, GH)); + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + gaussianBlur(originalmask->L, origblurmask->L, GW, GH, radius); + gaussianBlur(originalmask->a, origblurmask->a, GW, GH, radius); + gaussianBlur(originalmask->b, origblurmask->b, GW, GH, radius); + } + } + #ifdef _OPENMP #pragma omp parallel #endif @@ -1522,6 +1541,7 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in #pragma omp parallel if (multiThread) #endif { + const LabImage *maskptr = usemaskall ? origblurmask.get() : origblur.get(); const int limscope = 80; const float mindE = 2.f + MINSCOPE * lp.sensden * lp.thr; const float maxdE = 5.f + MAXSCOPE * lp.sensden * (1 + 0.1f * lp.thr); @@ -1556,10 +1576,10 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in continue; } - float rL = original->L[y][x] / 327.6f; - float dEL = sqrt(0.9f * SQR(refa - origblur->a[y][x] / 327.6f) + 0.9f * SQR(refb - origblur->b[y][x] / 327.8f) + 1.2f * SQR(lumaref - rL)); - float dEa = sqrt(1.2f * SQR(refa - origblur->a[y][x] / 327.6f) + 1.f * SQR(refb - origblur->b[y][x] / 327.8f) + 0.8f * SQR(lumaref - rL)); - float dEb = sqrt(1.f * SQR(refa - origblur->a[y][x] / 327.6f) + 1.2f * SQR(refb - origblur->b[y][x] / 327.8f) + 0.8f * SQR(lumaref - rL)); +// float rL = original->L[y][x] / 327.6f; + float dEL = sqrt(0.9f * SQR(refa - maskptr->a[y][x] / 327.6f) + 0.9f * SQR(refb - maskptr->b[y][x] / 327.8f) + 1.2f * SQR(lumaref - maskptr->L[y][x] / 327.8f)); + float dEa = sqrt(1.2f * SQR(refa - maskptr->a[y][x] / 327.6f) + 1.f * SQR(refb - maskptr->b[y][x] / 327.8f) + 0.8f * SQR(lumaref - maskptr->L[y][x] / 327.8f)); + float dEb = sqrt(1.f * SQR(refa - maskptr->a[y][x] / 327.6f) + 1.2f * SQR(refb - maskptr->b[y][x] / 327.8f) + 0.8f * SQR(lumaref - maskptr->L[y][x] / 327.8f)); float reducdEL = 1.f; float reducdEa = 1.f; @@ -1596,6 +1616,16 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in transformed->L[y][x] = CLIP(original->L[y][x] + difL); transformed->a[y][x] = CLIPC((original->a[y][x] + difa) * factnoise); transformed->b[y][x] = CLIPC((original->b[y][x] + difb) * factnoise) ; + + if (blshow) { + transformed->L[y][x] = CLIP(12000.f + 10.f * difL);// * 10.f empirical to can visualize modifications + transformed->a[y][x] = CLIPC(10.f * difa);// * 10.f empirical to can visualize modifications + transformed->b[y][x] = CLIPC(10.f * difb);// * 10.f empirical to can visualize modifications + } else if (previewbl) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = (10.f * difb);// * 10.f empirical to can visualize modifications + } + break; } @@ -1620,6 +1650,15 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in transformed->L[y][x] = CLIP(original->L[y][x] + difL); transformed->a[y][x] = CLIPC((original->a[y][x] + difa) * factnoise); transformed->b[y][x] = CLIPC((original->b[y][x] + difb) * factnoise); + + if (blshow) { + transformed->L[y][x] = CLIP(12000.f + 10.f * difL);// * 10.f empirical to can visualize modifications + transformed->a[y][x] = CLIPC(10.f * difa);// * 10.f empirical to can visualize modifications + transformed->b[y][x] = CLIPC(10.f * difb);// * 10.f empirical to can visualize modifications + } else if (previewbl) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = (10.f * difb);// * 10.f empirical to can visualize modifications + } } } @@ -5383,6 +5422,409 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } +//Prepare mask for Blur and noise and Denoise + bool denoiz = false; + + if (((lp.noiself > 0.f || lp.noiself0 > 0.f || lp.noiself2 > 0.f || lp.noiselc > 0.f || lp.noisecf > 0.f || lp.noisecc > 0.f || lp.bilat > 0.f) && lp.denoiena)) { + denoiz = true; + } + + bool blurz = false; + + if (((radius >= 1.5 * GAUSS_SKIP && lp.rad > 1.) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 1 || lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) && lp.blurena) { + blurz = true; + } + + const int GW = transformed->W; + const int GH = transformed->H; + + std::unique_ptr bufmaskorigbl; + std::unique_ptr bufmaskblurbl; + std::unique_ptr originalmaskbl; + std::unique_ptr bufgb; //(new LabImage(GW, GH)); + + if (denoiz || blurz || lp.denoiena || lp.blurena) { + bufgb.reset(new LabImage(GW, GH)); + + if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { + bufmaskorigbl.reset(new LabImage(GW, GH)); + bufmaskblurbl.reset(new LabImage(GW, GH)); + originalmaskbl.reset(new LabImage(GW, GH)); + } + + array2D ble(GW, GH); + array2D guid(GW, GH); + float meanfab, fab; + mean_fab(0, 0, GW, GH, bufgb.get(), original, fab, meanfab, lp.chromabl); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH; y++) { + for (int x = 0; x < GW; x++) { + bufgb->L[y][x] = original->L[y][x]; + bufgb->a[y][x] = original->a[y][x]; + bufgb->b[y][x] = original->b[y][x]; + } + } + + if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) { + for (int jr = 0; jr < GW; jr++) { + float kmaskLexp = 0; + float kmaskCH = 0; + + if (locllmasblCurve && llmasblutili) { + float ligh = bufgb->L[ir][jr] / 32768.f; + kmaskLexp = 32768.f * LIM01(1.f - locllmasblCurve[500.f * ligh]); + } + + if (lp.showmaskblmet != 4) { + if (locccmasblCurve && lcmasblutili) { + float chromask = 0.0001f + sqrt(SQR((bufgb->a[ir][jr]) / fab) + SQR((bufgb->b[ir][jr]) / fab)); + kmaskCH = LIM01(1.f - locccmasblCurve[500.f * chromask]); + } + } + + if (lochhmasblCurve && lhmasblutili) { + float huema = xatan2f(bufgb->b[ir][jr], bufgb->a[ir][jr]); + float h = Color::huelab_to_huehsv2(huema); + h += 1.f / 6.f; + + if (h > 1.f) { + h -= 1.f; + } + + float valHH = LIM01(1.f - lochhmasblCurve[500.f * h]); + + if (lp.showmaskblmet != 4) { + kmaskCH += valHH; + } + + kmaskLexp += 32768.f * valHH; + } + + bufmaskblurbl->L[ir][jr] = CLIPLOC(kmaskLexp); + bufmaskblurbl->a[ir][jr] = kmaskCH; + bufmaskblurbl->b[ir][jr] = kmaskCH; + ble[ir][jr] = bufmaskblurbl->L[ir][jr] / 32768.f; + guid[ir][jr] = bufgb->L[ir][jr] / 32768.f; + + } + } + + if (lp.radmabl > 0.f) { + guidedFilter(guid, ble, ble, lp.radmabl * 10.f / sk, 0.001, multiThread, 4); + } + + LUTf lutTonemaskbl(65536); + calcGammaLut(lp.gammabl, lp.slomabl, lutTonemaskbl); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) + for (int jr = 0; jr < GW; jr++) { + float L_; + bufmaskblurbl->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f; + L_ = 2.f * bufmaskblurbl->L[ir][jr]; + bufmaskblurbl->L[ir][jr] = lutTonemaskbl[L_]; + } + + } + + float radiusb = 1.f / sk; + + if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { + int invers = 0; + + if (lp.blurmet == 0) { + invers = 0; + } else if (lp.blurmet == 1) { + invers = 1; + } + + //printf("lp.showmasktmmet=%i\n",lp.showmasktmmet); +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(bufmaskblurbl->L, bufmaskorigbl->L, GW, GH, radiusb); + gaussianBlur(bufmaskblurbl->a, bufmaskorigbl->a, GW, GH, 1.f + (0.5f * lp.radmabl) / sk); + gaussianBlur(bufmaskblurbl->b, bufmaskorigbl->b, GW, GH, 1.f + (0.5f * lp.radmabl) / sk); + } + + if (lp.showmaskblmet == 0 || lp.showmaskblmet == 1 || lp.showmaskblmet == 2 || lp.showmaskblmet == 4 || lp.enablMask) { + blendmask(lp, 0, 0, cx, cy, GW, GH, bufgb.get(), original, bufmaskorigbl.get(), originalmaskbl.get(), lp.blendmabl, invers); + + } else if (lp.showmaskblmet == 3) { + showmask(lp, 0, 0, cx, cy, GW, GH, bufgb.get(), transformed, bufmaskorigbl.get(), invers); + return; + } + } + +//end mask + + + + } + + if (((radius >= 1.5 * GAUSS_SKIP && lp.rad > 1.) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 1 || lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) && lp.blurena) { // radius < GAUSS_SKIP means no gauss, just copy of original image + std::unique_ptr tmp1; + std::unique_ptr tmp2; + const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + const int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + const int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + const int bfh = yend - ystart; + const int bfw = xend - xstart; + // const int GW = transformed->W; + //const int GH = transformed->H; + JaggedArray bufchroi(GW, GH); + std::unique_ptr bufgbi(new LabImage(GW, GH)); + JaggedArray bufchro(bfw, bfh); + + //here mask is used with plein image for normal and inverse + //if it is possible to optimze with maskcalccol(), I don't to preserv lisibility + if (lp.showmaskblmet == 0 || lp.showmaskblmet == 1 || lp.showmaskblmet == 2 || lp.showmaskblmet == 4 || lp.enablMask) { + + if (lp.blurmet == 0) { + if (bfw > 0 && bfh > 0) { + tmp1.reset(new LabImage(bfw, bfh)); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend ; y++) { + for (int x = xstart; x < xend; x++) { + tmp1->L[y - ystart][x - xstart] = original->L[y][x]; + tmp1->a[y - ystart][x - xstart] = original->a[y][x]; + tmp1->b[y - ystart][x - xstart] = original->b[y][x]; + } + } + + } + } else if (lp.blurmet == 1) { + tmp1.reset(new LabImage(transformed->W, transformed->H)); + tmp2.reset(new LabImage(transformed->W, transformed->H)); + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + tmp2->L[y][x] = original->L[y][x]; + tmp2->a[y][x] = original->a[y][x]; + tmp2->b[y][x] = original->b[y][x]; + bufgbi->L[y][x] = original->L[y][x]; + bufgbi->a[y][x] = original->a[y][x]; + bufgbi->b[y][x] = original->b[y][x]; + } + } + + } + + + if (lp.blurmet == 0 && lp.blmet == 0) { +#ifdef _OPENMP + #pragma omp parallel +#endif + + { + gaussianBlur(tmp1->L, tmp1->L, bfw, bfh, radius); + gaussianBlur(tmp1->a, tmp1->a, bfw, bfh, radius); + gaussianBlur(tmp1->b, tmp1->b, bfw, bfh, radius); + } + + } else if (lp.blurmet == 1 && lp.blmet == 0) { + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(original->L, tmp1->L, GW, GH, radius); + gaussianBlur(original->a, tmp1->a, GW, GH, radius); + gaussianBlur(original->b, tmp1->b, GW, GH, radius); + } + } + + + + if (tmp1.get() && lp.stren > 0.1f && lp.blmet == 0) { + float mean = 0.f;//0 best result + float variance = lp.stren ; + addGaNoise(tmp1.get(), tmp1.get(), mean, variance, sk) ; + } + + Median medianTypeL = Median::TYPE_3X3_STRONG; + Median medianTypeAB = Median::TYPE_3X3_STRONG; + + if (lp.medmet == 0) { + medianTypeL = medianTypeAB = Median::TYPE_3X3_STRONG; + } else if (lp.medmet == 1) { + medianTypeL = medianTypeAB = Median::TYPE_5X5_STRONG; + } else if (lp.medmet == 2) { + medianTypeL = medianTypeAB = Median::TYPE_7X7; + } else if (lp.medmet == 3) { + medianTypeL = medianTypeAB = Median::TYPE_9X9; + } + + if (lp.blurmet == 0 && lp.blmet == 1) { + float** tmL; + int wid = bfw; + int hei = bfh; + tmL = new float*[hei]; + + for (int i = 0; i < hei; ++i) { + tmL[i] = new float[wid]; + } + + Median_Denoise(tmp1->L, tmp1->L, bfw, bfh, medianTypeL, lp.it, multiThread, tmL); + + if (!lp.actsp) { + Median_Denoise(tmp1->a, tmp1->a, bfw, bfh, medianTypeAB, lp.it, multiThread, tmL); + Median_Denoise(tmp1->b, tmp1->b, bfw, bfh, medianTypeAB, lp.it, multiThread, tmL); + } + + for (int i = 0; i < hei; ++i) { + delete[] tmL[i]; + } + + delete[] tmL; + + } else if (lp.blurmet == 1 && lp.blmet == 1) { + float** tmL; + int wid = GW; + int hei = GH; + tmL = new float*[hei]; + + for (int i = 0; i < hei; ++i) { + tmL[i] = new float[wid]; + } + + Median_Denoise(tmp2->L, tmp1->L, GW, GH, medianTypeL, lp.it, multiThread, tmL); + + if (!lp.actsp) { + Median_Denoise(tmp2->a, tmp1->a, GW, GH, medianTypeAB, lp.it, multiThread, tmL); + Median_Denoise(tmp2->b, tmp1->b, GW, GH, medianTypeAB, lp.it, multiThread, tmL); + } + + for (int i = 0; i < hei; ++i) { + delete[] tmL[i]; + } + + delete[] tmL; + } + + if (lp.blurmet == 0 && lp.blmet == 2) { + if (lp.guidb > 1) { + lp.actsp = true; +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend ; y++) { + for (int x = xstart; x < xend; x++) { + tmp1->L[y - ystart][x - xstart] = original->L[y][x]; + bufgb->L[y - ystart][x - xstart] = original->L[y][x]; + } + } + + double thresM = 0.05 * lp.epsb; + double thresm = 0.01 * lp.epsb; + softproc(bufgb.get(), tmp1.get(), 3.f * lp.guidb, bfh, bfw, thresM, thresm, 0.0001f, sk, multiThread); + } + + } else if (lp.blurmet == 1 && lp.blmet == 2) { + if (lp.guidb > 1) { + lp.actsp = true; +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GH; x++) { + tmp1->L[y][x] = original->L[y][x]; + tmp2->L[y][x] = original->L[y][x]; + } + } + + double thresM = 0.05 * lp.epsb; + double thresm = 0.01 * lp.epsb; + softproc(tmp2.get(), tmp1.get(), 3.f * lp.guidb, GH, GW, thresM, thresm, 0.0001f, sk, multiThread); + } + + } + + if (lp.blurmet == 0) { + float minC = sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - sqrt(SQR(bufgb->a[0][0]) + SQR(bufgb->b[0][0])); + float maxC = minC; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) { + for (int jr = 0; jr < bfw; jr++) { + bufchro[ir][jr] = sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - sqrt(SQR(bufgb->a[ir][jr]) + SQR(bufgb->b[ir][jr])); + minC = rtengine::min(minC, bufchro[ir][jr]); + maxC = rtengine::max(maxC, bufchro[ir][jr]); + } + } + + float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < bfh; y++) { + for (int x = 0; x < bfw; x++) { + bufchro[y][x] /= coefC; + } + } + + } else if (lp.blurmet == 1) { + float minC = sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - sqrt(SQR(bufgbi->a[0][0]) + SQR(bufgbi->b[0][0])); + float maxC = minC; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) { + for (int jr = 0; jr < GW; jr++) { + bufchroi[ir][jr] = sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - sqrt(SQR(bufgbi->a[ir][jr]) + SQR(bufgbi->b[ir][jr])); + minC = rtengine::min(minC, bufchroi[ir][jr]); + maxC = rtengine::max(maxC, bufchroi[ir][jr]); + } + } + + float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < GH; y++) { + for (int x = 0; x < GW; x++) { + bufchroi[y][x] /= coefC; + } + } + + } + + if (lp.blurmet == 0) { //blur and noise (center) + + if (tmp1.get()) { + BlurNoise_Local(tmp1.get(), originalmaskbl.get(), bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + } + } else if (lp.blurmet == 1) { + if (tmp1.get()) { + InverseBlurNoise_Local(originalmaskbl.get(), bufchroi, lp, hueref, chromaref, lumaref, original, transformed, tmp1.get(), cx, cy, sk); + } + } + } + } //local impulse @@ -5425,7 +5867,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o ImProcFunctions::impulse_nr(bufwv.get(), threshold); } - DeNoise_Local(call, lp, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *(bufwv.get()), cx, cy, sk); + DeNoise_Local(call, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *(bufwv.get()), cx, cy, sk); } //local denoise @@ -5937,7 +6379,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } - DeNoise_Local(call, lp, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, tmp1, cx, cy, sk); + DeNoise_Local(call, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, tmp1, cx, cy, sk); } else if (call == 2 /* || call == 1 || call == 3 */) { //simpleprocess @@ -6391,7 +6833,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o bdecomp.reconstruct(bufwv.b[0]); } - DeNoise_Local(call, lp, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, bufwv, cx, cy, sk); + DeNoise_Local(call, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, bufwv, cx, cy, sk); } } @@ -6595,390 +7037,6 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o //end cbdl_Local - -//Blur and noise - - if (((radius >= 1.5 * GAUSS_SKIP && lp.rad > 1.) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 1 || lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) && lp.blurena) { // radius < GAUSS_SKIP means no gauss, just copy of original image - std::unique_ptr tmp1; - std::unique_ptr tmp2; - const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); - const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); - const int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); - const int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); - const int bfh = yend - ystart; - const int bfw = xend - xstart; - const int GW = transformed->W; - const int GH = transformed->H; - JaggedArray bufchroi(GW, GH); - std::unique_ptr bufgbi(new LabImage(GW, GH)); - JaggedArray bufchro(bfw, bfh); - - //here mask is used with plein image for normal and inverse - //if it is possible to optimze with maskcalccol(), I don't to preserv lisibility - std::unique_ptr bufmaskorigbl; - std::unique_ptr bufmaskblurbl; - std::unique_ptr originalmaskbl; - std::unique_ptr bufgb(new LabImage(GW, GH)); - - if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { - bufmaskorigbl.reset(new LabImage(GW, GH)); - bufmaskblurbl.reset(new LabImage(GW, GH)); - originalmaskbl.reset(new LabImage(GW, GH)); - } - - array2D ble(GW, GH); - array2D guid(GW, GH); - float meanfab, fab; - mean_fab(0, 0, GW, GH, bufgb.get(), original, fab, meanfab, lp.chromabl); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < GH; y++) { - for (int x = 0; x < GW; x++) { - bufgb->L[y][x] = original->L[y][x]; - bufgb->a[y][x] = original->a[y][x]; - bufgb->b[y][x] = original->b[y][x]; - } - } - - if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < GH; ir++) { - for (int jr = 0; jr < GW; jr++) { - float kmaskLexp = 0; - float kmaskCH = 0; - - if (locllmasblCurve && llmasblutili) { - float ligh = bufgb->L[ir][jr] / 32768.f; - kmaskLexp = 32768.f * LIM01(1.f - locllmasblCurve[500.f * ligh]); - } - - if (lp.showmaskblmet != 4) { - if (locccmasblCurve && lcmasblutili) { - float chromask = 0.0001f + sqrt(SQR((bufgb->a[ir][jr]) / fab) + SQR((bufgb->b[ir][jr]) / fab)); - kmaskCH = LIM01(1.f - locccmasblCurve[500.f * chromask]); - } - } - - if (lochhmasblCurve && lhmasblutili) { - float huema = xatan2f(bufgb->b[ir][jr], bufgb->a[ir][jr]); - float h = Color::huelab_to_huehsv2(huema); - h += 1.f / 6.f; - - if (h > 1.f) { - h -= 1.f; - } - - float valHH = LIM01(1.f - lochhmasblCurve[500.f * h]); - - if (lp.showmaskblmet != 4) { - kmaskCH += valHH; - } - - kmaskLexp += 32768.f * valHH; - } - - bufmaskblurbl->L[ir][jr] = CLIPLOC(kmaskLexp); - bufmaskblurbl->a[ir][jr] = kmaskCH; - bufmaskblurbl->b[ir][jr] = kmaskCH; - ble[ir][jr] = bufmaskblurbl->L[ir][jr] / 32768.f; - guid[ir][jr] = bufgb->L[ir][jr] / 32768.f; - - } - } - - if (lp.radmabl > 0.f) { - guidedFilter(guid, ble, ble, lp.radmabl * 10.f / sk, 0.001, multiThread, 4); - } - - LUTf lutTonemaskbl(65536); - calcGammaLut(lp.gammabl, lp.slomabl, lutTonemaskbl); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < GH; ir++) - for (int jr = 0; jr < GW; jr++) { - float L_; - bufmaskblurbl->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f; - L_ = 2.f * bufmaskblurbl->L[ir][jr]; - bufmaskblurbl->L[ir][jr] = lutTonemaskbl[L_]; - } - - } - - float radiusb = 1.f / sk; - - if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { - int invers = 0; - - if (lp.blurmet == 0) { - invers = 0; - } else if (lp.blurmet == 1) { - invers = 1; - } - - //printf("lp.showmasktmmet=%i\n",lp.showmasktmmet); -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(bufmaskblurbl->L, bufmaskorigbl->L, GW, GH, radiusb); - gaussianBlur(bufmaskblurbl->a, bufmaskorigbl->a, GW, GH, 1.f + (0.5f * lp.radmabl) / sk); - gaussianBlur(bufmaskblurbl->b, bufmaskorigbl->b, GW, GH, 1.f + (0.5f * lp.radmabl) / sk); - } - - if (lp.showmaskblmet == 0 || lp.showmaskblmet == 1 || lp.showmaskblmet == 2 || lp.showmaskblmet == 4 || lp.enablMask) { - blendmask(lp, 0, 0, cx, cy, GW, GH, bufgb.get(), original, bufmaskorigbl.get(), originalmaskbl.get(), lp.blendmabl, invers); - - } else if (lp.showmaskblmet == 3) { - showmask(lp, 0, 0, cx, cy, GW, GH, bufgb.get(), transformed, bufmaskorigbl.get(), invers); - return; - } - } - -//end mask - - if (lp.showmaskblmet == 0 || lp.showmaskblmet == 1 || lp.showmaskblmet == 2 || lp.showmaskblmet == 4 || lp.enablMask) { - - if (lp.blurmet == 0) { - if (bfw > 0 && bfh > 0) { - tmp1.reset(new LabImage(bfw, bfh)); -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = ystart; y < yend ; y++) { - for (int x = xstart; x < xend; x++) { - tmp1->L[y - ystart][x - xstart] = original->L[y][x]; - tmp1->a[y - ystart][x - xstart] = original->a[y][x]; - tmp1->b[y - ystart][x - xstart] = original->b[y][x]; - } - } - - } - } else if (lp.blurmet == 1) { - tmp1.reset(new LabImage(transformed->W, transformed->H)); - tmp2.reset(new LabImage(transformed->W, transformed->H)); - - for (int y = 0; y < GH ; y++) { - for (int x = 0; x < GW; x++) { - tmp2->L[y][x] = original->L[y][x]; - tmp2->a[y][x] = original->a[y][x]; - tmp2->b[y][x] = original->b[y][x]; - bufgbi->L[y][x] = original->L[y][x]; - bufgbi->a[y][x] = original->a[y][x]; - bufgbi->b[y][x] = original->b[y][x]; - } - } - - } - - - if (lp.blurmet == 0 && lp.blmet == 0) { -#ifdef _OPENMP - #pragma omp parallel -#endif - - { - gaussianBlur(tmp1->L, tmp1->L, bfw, bfh, radius); - gaussianBlur(tmp1->a, tmp1->a, bfw, bfh, radius); - gaussianBlur(tmp1->b, tmp1->b, bfw, bfh, radius); - } - - } else if (lp.blurmet == 1 && lp.blmet == 0) { - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(original->L, tmp1->L, GW, GH, radius); - gaussianBlur(original->a, tmp1->a, GW, GH, radius); - gaussianBlur(original->b, tmp1->b, GW, GH, radius); - } - } - - - - if (tmp1.get() && lp.stren > 0.1f && lp.blmet == 0) { - float mean = 0.f;//0 best result - float variance = lp.stren ; - addGaNoise(tmp1.get(), tmp1.get(), mean, variance, sk) ; - } - - Median medianTypeL = Median::TYPE_3X3_STRONG; - Median medianTypeAB = Median::TYPE_3X3_STRONG; - - if (lp.medmet == 0) { - medianTypeL = medianTypeAB = Median::TYPE_3X3_STRONG; - } else if (lp.medmet == 1) { - medianTypeL = medianTypeAB = Median::TYPE_5X5_STRONG; - } else if (lp.medmet == 2) { - medianTypeL = medianTypeAB = Median::TYPE_7X7; - } else if (lp.medmet == 3) { - medianTypeL = medianTypeAB = Median::TYPE_9X9; - } - - if (lp.blurmet == 0 && lp.blmet == 1) { - float** tmL; - int wid = bfw; - int hei = bfh; - tmL = new float*[hei]; - - for (int i = 0; i < hei; ++i) { - tmL[i] = new float[wid]; - } - - Median_Denoise(tmp1->L, tmp1->L, bfw, bfh, medianTypeL, lp.it, multiThread, tmL); - - if (!lp.actsp) { - Median_Denoise(tmp1->a, tmp1->a, bfw, bfh, medianTypeAB, lp.it, multiThread, tmL); - Median_Denoise(tmp1->b, tmp1->b, bfw, bfh, medianTypeAB, lp.it, multiThread, tmL); - } - - for (int i = 0; i < hei; ++i) { - delete[] tmL[i]; - } - - delete[] tmL; - - } else if (lp.blurmet == 1 && lp.blmet == 1) { - float** tmL; - int wid = GW; - int hei = GH; - tmL = new float*[hei]; - - for (int i = 0; i < hei; ++i) { - tmL[i] = new float[wid]; - } - - Median_Denoise(tmp2->L, tmp1->L, GW, GH, medianTypeL, lp.it, multiThread, tmL); - - if (!lp.actsp) { - Median_Denoise(tmp2->a, tmp1->a, GW, GH, medianTypeAB, lp.it, multiThread, tmL); - Median_Denoise(tmp2->b, tmp1->b, GW, GH, medianTypeAB, lp.it, multiThread, tmL); - } - - for (int i = 0; i < hei; ++i) { - delete[] tmL[i]; - } - - delete[] tmL; - } - - if (lp.blurmet == 0 && lp.blmet == 2) { - if (lp.guidb > 1) { - lp.actsp = true; -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = ystart; y < yend ; y++) { - for (int x = xstart; x < xend; x++) { - tmp1->L[y - ystart][x - xstart] = original->L[y][x]; - bufgb->L[y - ystart][x - xstart] = original->L[y][x]; - } - } - - double thresM = 0.05 * lp.epsb; - double thresm = 0.01 * lp.epsb; - softproc(bufgb.get(), tmp1.get(), 3.f * lp.guidb, bfh, bfw, thresM, thresm, 0.0001f, sk, multiThread); - } - - } else if (lp.blurmet == 1 && lp.blmet == 2) { - if (lp.guidb > 1) { - lp.actsp = true; -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < GH ; y++) { - for (int x = 0; x < GH; x++) { - tmp1->L[y][x] = original->L[y][x]; - tmp2->L[y][x] = original->L[y][x]; - } - } - - double thresM = 0.05 * lp.epsb; - double thresm = 0.01 * lp.epsb; - softproc(tmp2.get(), tmp1.get(), 3.f * lp.guidb, GH, GW, thresM, thresm, 0.0001f, sk, multiThread); - } - - } - - if (lp.blurmet == 0) { - float minC = sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - sqrt(SQR(bufgb->a[0][0]) + SQR(bufgb->b[0][0])); - float maxC = minC; -#ifdef _OPENMP - #pragma omp parallel for reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) { - for (int jr = 0; jr < bfw; jr++) { - bufchro[ir][jr] = sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - sqrt(SQR(bufgb->a[ir][jr]) + SQR(bufgb->b[ir][jr])); - minC = rtengine::min(minC, bufchro[ir][jr]); - maxC = rtengine::max(maxC, bufchro[ir][jr]); - } - } - - float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int y = 0; y < bfh; y++) { - for (int x = 0; x < bfw; x++) { - bufchro[y][x] /= coefC; - } - } - - } else if (lp.blurmet == 1) { - float minC = sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - sqrt(SQR(bufgbi->a[0][0]) + SQR(bufgbi->b[0][0])); - float maxC = minC; -#ifdef _OPENMP - #pragma omp parallel for reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) -#endif - - for (int ir = 0; ir < GH; ir++) { - for (int jr = 0; jr < GW; jr++) { - bufchroi[ir][jr] = sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - sqrt(SQR(bufgbi->a[ir][jr]) + SQR(bufgbi->b[ir][jr])); - minC = rtengine::min(minC, bufchroi[ir][jr]); - maxC = rtengine::max(maxC, bufchroi[ir][jr]); - } - } - - float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int y = 0; y < GH; y++) { - for (int x = 0; x < GW; x++) { - bufchroi[y][x] /= coefC; - } - } - - } - - if (lp.blurmet == 0) { //blur and noise (center) - - if (tmp1.get()) { - BlurNoise_Local(tmp1.get(), originalmaskbl.get(), bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); - } - } else if (lp.blurmet == 1) { - if (tmp1.get()) { - InverseBlurNoise_Local(originalmaskbl.get(), bufchroi, lp, hueref, chromaref, lumaref, original, transformed, tmp1.get(), cx, cy, sk); - } - } - } - } - //vibrance if (lp.expvib && (lp.past != 0.f || lp.satur != 0.f)) { //interior ellipse renforced lightness and chroma //locallutili diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index 4a5ef9438..cfab46a92 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -147,7 +147,7 @@ Locallab::Locallab(): expmaskcb(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOW")))), expmaskreti(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOW")))), expmasktm(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOW")))), - expmaskbl(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOW")))), + expmaskbl(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWPLUS")))), // CurveEditorGroup widgets // Color & Light @@ -1077,165 +1077,6 @@ Locallab::Locallab(): panel->pack_start(*expsoft, false, false); - - // Blur & Noise - Gtk::HBox* const BLTitleHBox = Gtk::manage(new Gtk::HBox()); - Gtk::Label* const BLLabel = Gtk::manage(new Gtk::Label()); - BLLabel->set_markup(Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_BLUFR")) + Glib::ustring("")); - BLLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - BLTitleHBox->pack_start(*BLLabel, Gtk::PACK_EXPAND_WIDGET, 0); - RTImage *BLImage = Gtk::manage(new RTImage("one-to-one-small.png")); - - if (showtooltip) { - BLImage->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); - } - - BLTitleHBox->pack_end(*BLImage, Gtk::PACK_SHRINK, 0); - expblur->setLabel(BLTitleHBox); - - expblur->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Locallab::foldAllButMe), expblur)); - enableblurConn = expblur->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Locallab::enableToggled), expblur)); - - blMethod->append(M("TP_LOCALLAB_BLUR")); - blMethod->append(M("TP_LOCALLAB_BLMED")); - blMethod->append(M("TP_LOCALLAB_BLGUID")); - blMethod->set_active(0); - - if (showtooltip) { -// blMethod->set_tooltip_markup(M("TP_LOCALLAB_BLUMETHOD_TOOLTIP")); - } - - blMethodConn = blMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::blMethodChanged)); - - - radius->setAdjusterListener(this); - - strength->setAdjusterListener(this); - - if (showtooltip) { - sensibn->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); - } - - sensibn->setAdjusterListener(this); - - itera->setAdjusterListener(this); - guidbl->setAdjusterListener(this); - epsbl->setAdjusterListener(this); - - setExpandAlignProperties(expmaskbl, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - expmaskbl->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Locallab::foldAllButMe), expmaskbl)); - expmaskbl->setLevel(2); - - maskblCurveEditorG->setCurveListener(this); - - CCmaskblshape = static_cast(maskblCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false)); - CCmaskblshape->setIdentityValue(0.); - CCmaskblshape->setResetCurve(FlatCurveType(defSpot.CCmaskblcurve.at(0)), defSpot.CCmaskblcurve); - - if (showtooltip) { - CCmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); - } - - CCmaskblshape->setBottomBarColorProvider(this, 7); - - LLmaskblshape = static_cast(maskblCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false)); - LLmaskblshape->setIdentityValue(0.); - LLmaskblshape->setResetCurve(FlatCurveType(defSpot.LLmaskblcurve.at(0)), defSpot.LLmaskblcurve); - - if (showtooltip) { - LLmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); - } - - LLmaskblshape->setBottomBarBgGradient(mllshape); - - HHmaskblshape = static_cast(maskblCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true)); - HHmaskblshape->setIdentityValue(0.); - HHmaskblshape->setResetCurve(FlatCurveType(defSpot.HHmaskblcurve.at(0)), defSpot.HHmaskblcurve); - - if (showtooltip) { - HHmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); - } - - HHmaskblshape->setCurveColorProvider(this, 6); - HHmaskblshape->setBottomBarColorProvider(this, 6); - - maskblCurveEditorG->curveListComplete(); - enablMaskConn = enablMask->signal_toggled().connect(sigc::mem_fun(*this, &Locallab::enablMaskChanged)); - - showmaskblMethod->append(M("TP_LOCALLAB_SHOWMNONE")); - showmaskblMethod->append(M("TP_LOCALLAB_SHOWMODIF")); - showmaskblMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); - showmaskblMethod->append(M("TP_LOCALLAB_SHOWMASK")); - showmaskblMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); - - - showmaskblMethod->set_active(0); - - if (showtooltip) { - showmaskblMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); - } - - showmaskblMethodConn = showmaskblMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::showmaskblMethodChanged)); - - medMethod->append(M("TP_DIRPYRDENOISE_TYPE_3X3")); - medMethod->append(M("TP_DIRPYRDENOISE_TYPE_5X5")); - medMethod->append(M("TP_DIRPYRDENOISE_TYPE_7X7")); - medMethod->append(M("TP_DIRPYRDENOISE_TYPE_9X9")); - - medMethod->set_active(0); - - if (showtooltip) { -// medMethod->set_tooltip_markup(M("TP_LOCALLAB_MEDMETHOD_TOOLTIP")); - } - - medMethodConn = medMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::medMethodChanged)); - - - blurMethod->append(M("TP_LOCALLAB_BLNORM")); - blurMethod->append(M("TP_LOCALLAB_BLINV")); - blurMethod->set_active(0); - - if (showtooltip) { - blurMethod->set_tooltip_markup(M("TP_LOCALLAB_BLMETHOD_TOOLTIP")); - } - - blurMethodConn = blurMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::blurMethodChanged)); - - activlumConn = activlum->signal_toggled().connect(sigc::mem_fun(*this, &Locallab::activlumChanged)); - blendmaskbl->setAdjusterListener(this); - radmaskbl->setAdjusterListener(this); - chromaskbl->setAdjusterListener(this); - gammaskbl->setAdjusterListener(this); - slomaskbl->setAdjusterListener(this); - - ToolParamBlock* const maskblBox = Gtk::manage(new ToolParamBlock()); - maskblBox->pack_start(*showmaskblMethod, Gtk::PACK_SHRINK, 4); - maskblBox->pack_start(*enablMask, Gtk::PACK_SHRINK, 0); - maskblBox->pack_start(*maskblCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor - maskblBox->pack_start(*blendmaskbl, Gtk::PACK_SHRINK, 0); - maskblBox->pack_start(*radmaskbl, Gtk::PACK_SHRINK, 0); - maskblBox->pack_start(*chromaskbl, Gtk::PACK_SHRINK, 0); - maskblBox->pack_start(*gammaskbl, Gtk::PACK_SHRINK, 0); - maskblBox->pack_start(*slomaskbl, Gtk::PACK_SHRINK, 0); - expmaskbl->add(*maskblBox, false); - - ToolParamBlock* const blurrBox = Gtk::manage(new ToolParamBlock()); - blurrBox->pack_start(*blMethod); - blurrBox->pack_start(*radius); - blurrBox->pack_start(*strength); - blurrBox->pack_start(*medMethod); - blurrBox->pack_start(*itera); - blurrBox->pack_start(*guidbl); - blurrBox->pack_start(*epsbl); - blurrBox->pack_start(*sensibn); - blurrBox->pack_start(*blurMethod); - blurrBox->pack_start(*activlum); - blurrBox->pack_start(*expmaskbl); - expblur->add(*blurrBox, false); - expblur->setLevel(2); - - panel->pack_start(*expblur, false, false); - // Tone Mapping Gtk::HBox* const TMTitleHBox = Gtk::manage(new Gtk::HBox()); Gtk::Label* const TMLabel = Gtk::manage(new Gtk::Label()); @@ -1835,6 +1676,167 @@ Locallab::Locallab(): panel->pack_start(*expcbdl, false, false); + // Blur & Noise + Gtk::HBox* const BLTitleHBox = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const BLLabel = Gtk::manage(new Gtk::Label()); + BLLabel->set_markup(Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_BLUFR")) + Glib::ustring("")); + BLLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + BLTitleHBox->pack_start(*BLLabel, Gtk::PACK_EXPAND_WIDGET, 0); + RTImage *BLImage = Gtk::manage(new RTImage("one-to-one-small.png")); + + if (showtooltip) { + BLImage->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); + } + + BLTitleHBox->pack_end(*BLImage, Gtk::PACK_SHRINK, 0); + expblur->setLabel(BLTitleHBox); + + expblur->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Locallab::foldAllButMe), expblur)); + enableblurConn = expblur->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Locallab::enableToggled), expblur)); + + blMethod->append(M("TP_LOCALLAB_BLUR")); + blMethod->append(M("TP_LOCALLAB_BLMED")); + blMethod->append(M("TP_LOCALLAB_BLGUID")); + blMethod->set_active(0); + + if (showtooltip) { +// blMethod->set_tooltip_markup(M("TP_LOCALLAB_BLUMETHOD_TOOLTIP")); + } + + blMethodConn = blMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::blMethodChanged)); + + + radius->setAdjusterListener(this); + + strength->setAdjusterListener(this); + + if (showtooltip) { + sensibn->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); + } + + sensibn->setAdjusterListener(this); + + itera->setAdjusterListener(this); + guidbl->setAdjusterListener(this); + epsbl->setAdjusterListener(this); + + setExpandAlignProperties(expmaskbl, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + expmaskbl->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Locallab::foldAllButMe), expmaskbl)); + expmaskbl->setLevel(2); + + maskblCurveEditorG->setCurveListener(this); + + CCmaskblshape = static_cast(maskblCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false)); + CCmaskblshape->setIdentityValue(0.); + CCmaskblshape->setResetCurve(FlatCurveType(defSpot.CCmaskblcurve.at(0)), defSpot.CCmaskblcurve); + + if (showtooltip) { + CCmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmaskblshape->setBottomBarColorProvider(this, 7); + + LLmaskblshape = static_cast(maskblCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false)); + LLmaskblshape->setIdentityValue(0.); + LLmaskblshape->setResetCurve(FlatCurveType(defSpot.LLmaskblcurve.at(0)), defSpot.LLmaskblcurve); + + if (showtooltip) { + LLmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmaskblshape->setBottomBarBgGradient(mllshape); + + HHmaskblshape = static_cast(maskblCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true)); + HHmaskblshape->setIdentityValue(0.); + HHmaskblshape->setResetCurve(FlatCurveType(defSpot.HHmaskblcurve.at(0)), defSpot.HHmaskblcurve); + + if (showtooltip) { + HHmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskblshape->setCurveColorProvider(this, 6); + HHmaskblshape->setBottomBarColorProvider(this, 6); + + maskblCurveEditorG->curveListComplete(); + enablMaskConn = enablMask->signal_toggled().connect(sigc::mem_fun(*this, &Locallab::enablMaskChanged)); + + showmaskblMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskblMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskblMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskblMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskblMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + + + showmaskblMethod->set_active(0); + + if (showtooltip) { + showmaskblMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskblMethodConn = showmaskblMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::showmaskblMethodChanged)); + + medMethod->append(M("TP_DIRPYRDENOISE_TYPE_3X3")); + medMethod->append(M("TP_DIRPYRDENOISE_TYPE_5X5")); + medMethod->append(M("TP_DIRPYRDENOISE_TYPE_7X7")); + medMethod->append(M("TP_DIRPYRDENOISE_TYPE_9X9")); + + medMethod->set_active(0); + + if (showtooltip) { +// medMethod->set_tooltip_markup(M("TP_LOCALLAB_MEDMETHOD_TOOLTIP")); + } + + medMethodConn = medMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::medMethodChanged)); + + + blurMethod->append(M("TP_LOCALLAB_BLNORM")); + blurMethod->append(M("TP_LOCALLAB_BLINV")); + blurMethod->set_active(0); + + if (showtooltip) { + blurMethod->set_tooltip_markup(M("TP_LOCALLAB_BLMETHOD_TOOLTIP")); + } + + blurMethodConn = blurMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::blurMethodChanged)); + + activlumConn = activlum->signal_toggled().connect(sigc::mem_fun(*this, &Locallab::activlumChanged)); + blendmaskbl->setAdjusterListener(this); + radmaskbl->setAdjusterListener(this); + chromaskbl->setAdjusterListener(this); + gammaskbl->setAdjusterListener(this); + slomaskbl->setAdjusterListener(this); + + ToolParamBlock* const maskblBox = Gtk::manage(new ToolParamBlock()); + maskblBox->pack_start(*showmaskblMethod, Gtk::PACK_SHRINK, 4); + maskblBox->pack_start(*enablMask, Gtk::PACK_SHRINK, 0); + maskblBox->pack_start(*maskblCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskblBox->pack_start(*blendmaskbl, Gtk::PACK_SHRINK, 0); + maskblBox->pack_start(*radmaskbl, Gtk::PACK_SHRINK, 0); + maskblBox->pack_start(*chromaskbl, Gtk::PACK_SHRINK, 0); + maskblBox->pack_start(*gammaskbl, Gtk::PACK_SHRINK, 0); + maskblBox->pack_start(*slomaskbl, Gtk::PACK_SHRINK, 0); + expmaskbl->add(*maskblBox, false); + panel->pack_start(*expmaskbl); + + ToolParamBlock* const blurrBox = Gtk::manage(new ToolParamBlock()); + blurrBox->pack_start(*blMethod); + blurrBox->pack_start(*radius); + blurrBox->pack_start(*strength); + blurrBox->pack_start(*medMethod); + blurrBox->pack_start(*itera); + blurrBox->pack_start(*guidbl); + blurrBox->pack_start(*epsbl); + blurrBox->pack_start(*sensibn); + blurrBox->pack_start(*blurMethod); + blurrBox->pack_start(*activlum); +// blurrBox->pack_start(*expmaskbl); + expblur->add(*blurrBox, false); + expblur->setLevel(2); + + panel->pack_start(*expblur, false, false); + + + // Denoise Gtk::HBox* const denoiTitleHBox = Gtk::manage(new Gtk::HBox()); Gtk::Label* const denoiLabel = Gtk::manage(new Gtk::Label());