From 5f988861b0adf134fc1683e4006877a499186ce3 Mon Sep 17 00:00:00 2001 From: Desmis Date: Fri, 19 Feb 2016 16:58:23 +0100 Subject: [PATCH] Init CBDL before Black and White --- rtdata/languages/default | 5 ++ rtengine/color.cc | 30 ++++++++ rtengine/dcrop.cc | 79 +++++++++++++++++++- rtengine/improccoordinator.cc | 87 ++++++++++++++++++++-- rtengine/improcfun.cc | 135 ++++++++++++++++++++++++---------- rtengine/improcfun.h | 3 +- rtengine/procevents.h | 2 + rtengine/procparams.cc | 17 +++++ rtengine/procparams.h | 2 +- rtengine/refreshmap.cc | 15 ++-- rtengine/simpleprocess.cc | 75 ++++++++++++++++++- rtgui/dirpyrequalizer.cc | 50 +++++++++++++ rtgui/dirpyrequalizer.h | 6 +- rtgui/paramsedited.cc | 7 ++ rtgui/paramsedited.h | 2 +- 15 files changed, 451 insertions(+), 64 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 6bedd3443..553fc4a4b 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -670,6 +670,7 @@ HISTORY_MSG_436;Retinex - M - Radius HISTORY_MSG_437;Retinex - M - Method HISTORY_MSG_438;Retinex - M - Equalizer HISTORY_MSG_439;Retinex - Preview +HISTORY_MSG_440;CbDL - method HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -1206,6 +1207,10 @@ TP_BWMIX_VAL;L TP_CACORRECTION_BLUE;Blue TP_CACORRECTION_LABEL;Chromatic Aberration Correction TP_CACORRECTION_RED;Red +TP_CBDL_METHOD;Process located +TP_CBDL_METHOD_TOOLTIP;"After Black and White" located the tool in L*a*b process.\n"Before Black and White" located the tool at the beginning of rgb process.\nObviously this can lead to differences. +TP_CBDL_AFT;After Black and White +TP_CBDL_BEF;Before Black and White TP_CHMIXER_BLUE;Blue channel TP_CHMIXER_GREEN;Green channel TP_CHMIXER_LABEL;Channel Mixer diff --git a/rtengine/color.cc b/rtengine/color.cc index c0dbab4d3..56880833b 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -808,6 +808,15 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u float somm; float som = mixerRed + mixerGreen + mixerBlue; + if(som >= 0.f && som < 1.f) { + som = 1.f; + } + + if(som < 0.f && som > -1.f) { + som = -1.f; + } + + // rM = mixerRed, gM = mixerGreen, bM = mixerBlue ! //presets if (setting == "RGB-Abs" || setting == "ROYGCBPM-Abs") { @@ -869,6 +878,15 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u bbm = mixerBlue; somm = mixerRed + mixerGreen + mixerBlue; + + if(somm >= 0.f && somm < 1.f) { + somm = 1.f; + } + + if(somm < 0.f && somm > -1.f) { + somm = -1.f; + } + mixerRed = mixerRed / somm; mixerGreen = mixerGreen / somm; mixerBlue = mixerBlue / somm; @@ -1084,6 +1102,10 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u mixerGreen = mixerGreen * filgreen; mixerBlue = mixerBlue * filblue; + if(mixerRed + mixerGreen + mixerBlue == 0) { + mixerRed += 1.f; + } + mixerRed = filcor * mixerRed / (mixerRed + mixerGreen + mixerBlue); mixerGreen = filcor * mixerGreen / (mixerRed + mixerGreen + mixerBlue); mixerBlue = filcor * mixerBlue / (mixerRed + mixerGreen + mixerBlue); @@ -1091,6 +1113,14 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u if(filter != "None") { som = mixerRed + mixerGreen + mixerBlue; + if(som >= 0.f && som < 1.f) { + som = 1.f; + } + + if(som < 0.f && som > -1.f) { + som = -1.f; + } + if(setting == "RGB-Abs" || setting == "ROYGCBPM-Abs") { kcorec = kcorec * som; } diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 2220f68c5..6eb60988c 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -712,6 +712,75 @@ void Crop::update (int todo) transCrop = NULL; } + if ((todo && (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled) { + + if( (!params.colorappearance.enabled )) { + TMatrix wprof, wiprof; + wprof = iccStore->workingSpaceMatrix( params.icm.working ); + wiprof = iccStore->workingSpaceInverseMatrix( params.icm.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]} + }; + + 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]} + }; + + int W = baseCrop->getWidth(); + int H = baseCrop->getHeight(); + LabImage * labcbdl; + labcbdl = new LabImage(W, H); +#ifndef _DEBUG + #pragma omp parallel for schedule(dynamic, 10) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float r = baseCrop->r(i, j); + float g = baseCrop->g(i, j); + float b = baseCrop->b(i, j); + float X, Y, Z; + float L, aa, bb; + Color::rgbxyz(r, g, b, X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, aa, bb); + labcbdl->L[i][j] = L; + labcbdl->a[i][j] = aa; + labcbdl->b[i][j] = bb; + } + } + + parent->ipf.dirpyrequalizer (labcbdl, skip, 0); + + +#ifndef _DEBUG + #pragma omp parallel for schedule(dynamic, 10) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float L = labcbdl->L[i][j]; + float a = labcbdl->a[i][j]; + float b = labcbdl->b[i][j]; + float x1, y1, z1; + float R, G, B; + Color::Lab2XYZ(L, a, b, x1, y1, z1); + Color::xyz2rgb(x1, y1, z1, R, G, B, wip); + baseCrop->r(i, j) = R; + baseCrop->g(i, j) = G; + baseCrop->b(i, j) = B; + } + } + + delete labcbdl; + + } + } + // blurmap for shadow & highlights if ((todo & M_BLURMAP) && params.sh.enabled) { double radius = sqrt (double(SKIPS(parent->fw, skip) * SKIPS(parent->fw, skip) + SKIPS(parent->fh, skip) * SKIPS(parent->fh, skip))) / 2.0; @@ -732,6 +801,7 @@ void Crop::update (int todo) } } + // shadows & highlights & tone curve & convert to cielab /*int xref,yref; xref=000;yref=000; @@ -838,12 +908,13 @@ void Crop::update (int todo) // if (skip==1) { WaveletParams WaveParams = params.wavelet; - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - parent->ipf.dirpyrequalizer (labnCrop, skip); - // parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip); + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled))) { + parent->ipf.dirpyrequalizer (labnCrop, skip, 1); + // parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip); + } } - int kall = 0; int minwin = min(labnCrop->W, labnCrop->H); int maxlevelcrop = 10; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index ee75e831a..84b4412ba 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -242,7 +242,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } - if ((todo & (M_RETINEX|M_INIT)) && params.retinex.enabled) { + if ((todo & (M_RETINEX | M_INIT)) && params.retinex.enabled) { bool dehacontlutili = false; bool mapcontlutili = false; bool useHsl = false; @@ -392,6 +392,73 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) progress ("Preparing shadow/highlight map...", 100 * readyphase / numofphases); + if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled) { + if(((!params.colorappearance.enabled))) { + TMatrix wprof, wiprof; + wprof = iccStore->workingSpaceMatrix( params.icm.working ); + wiprof = iccStore->workingSpaceInverseMatrix( params.icm.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]} + }; + + 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]} + }; + + int W = oprevi->getWidth(); + int H = oprevi->getHeight(); + LabImage * labcbdl; + labcbdl = new LabImage(W, H); +#ifndef _DEBUG + #pragma omp parallel for schedule(dynamic, 10) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float r = oprevi->r(i, j); + float g = oprevi->g(i, j); + float b = oprevi->b(i, j); + float X, Y, Z; + float L, aa, bb; + Color::rgbxyz(r, g, b, X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, aa, bb); + labcbdl->L[i][j] = L; + labcbdl->a[i][j] = aa; + labcbdl->b[i][j] = bb; + } + } + + ipf.dirpyrequalizer (labcbdl, scale, 0); + +#ifndef _DEBUG + #pragma omp parallel for schedule(dynamic, 10) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float L = labcbdl->L[i][j]; + float a = labcbdl->a[i][j]; + float b = labcbdl->b[i][j]; + float x1, y1, z1; + float R, G, B; + Color::Lab2XYZ(L, a, b, x1, y1, z1); + Color::xyz2rgb(x1, y1, z1, R, G, B, wip); + oprevi->r(i, j) = R; + oprevi->g(i, j) = G; + oprevi->b(i, j) = B; + } + } + + delete labcbdl; + + } + } + if ((todo & M_BLURMAP) && params.sh.enabled) { double radius = sqrt (double(pW * pW + pH * pH)) / 2.0; double shradius = params.sh.radius; @@ -407,6 +474,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) shmap->update (oprevi, shradius, ipf.lumimul, params.sh.hq, scale); } + + readyphase++; if (todo & M_AUTOEXP) { @@ -439,6 +508,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, scale == 1 ? 1 : 1); CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, scale == 1 ? 1 : 1); + TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); double wp[3][3] = { {wprof[0][0], wprof[0][1], wprof[0][2]}, @@ -656,15 +726,15 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } */ - //if (scale==1) { - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - progress ("Pyramid wavelet...", 100 * readyphase / numofphases); - ipf.dirpyrequalizer (nprevl, scale); - //ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale); - readyphase++; + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) ) { + progress ("Pyramid wavelet...", 100 * readyphase / numofphases); + ipf.dirpyrequalizer (nprevl, scale, 1); + //ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale); + readyphase++; + } } - //} wavcontlutili = false; //CurveFactory::curveWavContL ( wavcontlutili,params.wavelet.lcurve, wavclCurve, LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,int skip); @@ -782,6 +852,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } } + // Update the monitor color transform if necessary if (todo & M_MONITOR) { ipf.updateColorProfiles(params.icm, monitorProfile, monitorIntent); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index b1f47c3a9..87c51dd64 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3421,10 +3421,22 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e fGammaLUTf[i] = CurveFactory::gamma2 (float(i) / 65535.f) * 65535.f; } - if (hasColorToning || blackwhite) { + if (hasColorToning || blackwhite || (params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled)) { tmpImage = new Imagefloat(working->width, working->height); } + int W = working->width; + int H = working->height; + + + + + + + + + + #define TS 112 #ifdef _OPENMP @@ -4217,48 +4229,48 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } } - //Film Simulations - if ( colorLUT ) { - for (int i = istart, ti = 0; i < tH; i++, ti++) { - for (int j = jstart, tj = 0; j < tW; j++, tj++) { - float &sourceR = rtemp[ti * TS + tj]; - float &sourceG = gtemp[ti * TS + tj]; - float &sourceB = btemp[ti * TS + tj]; + /* //Film Simulations + if ( colorLUT ) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float &sourceR = rtemp[ti * TS + tj]; + float &sourceG = gtemp[ti * TS + tj]; + float &sourceB = btemp[ti * TS + tj]; - if (!clutAndWorkingProfilesAreSame) { - //convert from working to clut profile - float x, y, z; - Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, work2xyz ); - Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2clut ); - } + if (!clutAndWorkingProfilesAreSame) { + //convert from working to clut profile + float x, y, z; + Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, work2xyz ); + Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2clut ); + } - //appply gamma sRGB (default RT) - sourceR = CLIP( Color::gamma_srgb( sourceR ) ); - sourceG = CLIP( Color::gamma_srgb( sourceG ) ); - sourceB = CLIP( Color::gamma_srgb( sourceB ) ); + //appply gamma sRGB (default RT) + sourceR = CLIP( Color::gamma_srgb( sourceR ) ); + sourceG = CLIP( Color::gamma_srgb( sourceG ) ); + sourceB = CLIP( Color::gamma_srgb( sourceB ) ); - float r, g, b; - colorLUT->getRGB( sourceR, sourceG, sourceB, r, g, b ); - // apply strength - sourceR = r * filmSimCorrectedStrength + sourceR * filmSimSourceStrength; - sourceG = g * filmSimCorrectedStrength + sourceG * filmSimSourceStrength; - sourceB = b * filmSimCorrectedStrength + sourceB * filmSimSourceStrength; - // apply inverse gamma sRGB - sourceR = Color::igamma_srgb( sourceR ); - sourceG = Color::igamma_srgb( sourceG ); - sourceB = Color::igamma_srgb( sourceB ); + float r, g, b; + colorLUT->getRGB( sourceR, sourceG, sourceB, r, g, b ); + // apply strength + sourceR = r * filmSimCorrectedStrength + sourceR * filmSimSourceStrength; + sourceG = g * filmSimCorrectedStrength + sourceG * filmSimSourceStrength; + sourceB = b * filmSimCorrectedStrength + sourceB * filmSimSourceStrength; + // apply inverse gamma sRGB + sourceR = Color::igamma_srgb( sourceR ); + sourceG = Color::igamma_srgb( sourceG ); + sourceB = Color::igamma_srgb( sourceB ); - if (!clutAndWorkingProfilesAreSame) { - //convert from clut to working profile - float x, y, z; - Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, clut2xyz ); - Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2work ); - } - - } - } - } + if (!clutAndWorkingProfilesAreSame) { + //convert from clut to working profile + float x, y, z; + Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, clut2xyz ); + Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2work ); + } + } + } + } + */ //black and white if(blackwhite) { if (hasToneCurvebw1) { @@ -4405,6 +4417,50 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } } + + //Film Simulations + if ( colorLUT ) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float &sourceR = rtemp[ti * TS + tj]; + float &sourceG = gtemp[ti * TS + tj]; + float &sourceB = btemp[ti * TS + tj]; + + if (!clutAndWorkingProfilesAreSame) { + //convert from working to clut profile + float x, y, z; + Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, work2xyz ); + Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2clut ); + } + + //appply gamma sRGB (default RT) + sourceR = CLIP( Color::gamma_srgb( sourceR ) ); + sourceG = CLIP( Color::gamma_srgb( sourceG ) ); + sourceB = CLIP( Color::gamma_srgb( sourceB ) ); + + float r, g, b; + colorLUT->getRGB( sourceR, sourceG, sourceB, r, g, b ); + // apply strength + sourceR = r * filmSimCorrectedStrength + sourceR * filmSimSourceStrength; + sourceG = g * filmSimCorrectedStrength + sourceG * filmSimSourceStrength; + sourceB = b * filmSimCorrectedStrength + sourceB * filmSimSourceStrength; + // apply inverse gamma sRGB + sourceR = Color::igamma_srgb( sourceR ); + sourceG = Color::igamma_srgb( sourceG ); + sourceB = Color::igamma_srgb( sourceB ); + + if (!clutAndWorkingProfilesAreSame) { + //convert from clut to working profile + float x, y, z; + Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, clut2xyz ); + Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2work ); + } + + } + } + } + + if(!blackwhite) { // ready, fill lab for (int i = istart, ti = 0; i < tH; i++, ti++) { @@ -6481,8 +6537,9 @@ void ImProcFunctions::badpixlab(LabImage* lab, double rad, int thr, int mode, fl } } -void ImProcFunctions::dirpyrequalizer (LabImage* lab, int scale) +void ImProcFunctions::dirpyrequalizer (LabImage* lab, int scale, int mode) { + printf("mode=%d\n", mode); if (params->dirpyrequalizer.enabled && lab->W >= 8 && lab->H >= 8) { float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 44224fa2e..f69f04e19 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -284,7 +284,8 @@ public: void impulse_nrcam (CieImage* ncie, double thresh, float **buffers[3]); void dirpyrdenoise (LabImage* src);//Emil's pyramid denoise - void dirpyrequalizer (LabImage* lab, int scale);//Emil's wavelet + void dirpyrequalizer (LabImage* lab, int scale, int mode);//Emil's wavelet + void EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0); float *CompressDR(float *Source, int skip, struct cont_params &cp, int W_L, int H_L, float Compression, float DetailBoost, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx, float *Compressed); diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 558f509c2..3d4f90af1 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -466,7 +466,9 @@ enum ProcEvent { EvmapMethod = 436, EvRetinexmapcurve = 437, EvviewMethod = 438, + EvcbdlMethod = 439, NUMOFEVENTS + }; } #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index f79f51c91..fcdd9fa0f 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -1219,7 +1219,9 @@ void ProcParams::setDefaults () dirpyrequalizer.enabled = false; dirpyrequalizer.gamutlab = false; + dirpyrequalizer.cbdlMethod = "aft"; + for(int i = 0; i < 6; i ++) { dirpyrequalizer.mult[i] = 1.0; } @@ -3028,6 +3030,10 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_boolean ("Directional Pyramid Equalizer", "Gamutlab", dirpyrequalizer.gamutlab); } + if (!pedited || pedited->dirpyrequalizer.cbdlMethod) { + keyFile.set_string ("Directional Pyramid Equalizer", "cbdlMethod", dirpyrequalizer.cbdlMethod); + } + for(int i = 0; i < 6; i++) { std::stringstream ss; ss << "Mult" << i; @@ -6610,6 +6616,16 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + + if (keyFile.has_key ("Directional Pyramid Equalizer", "cbdlMethod")) { + dirpyrequalizer.cbdlMethod = keyFile.get_string ("Directional Pyramid Equalizer", "cbdlMethod"); + + if (pedited) { + pedited->dirpyrequalizer.cbdlMethod = true; + } + } + + // if (keyFile.has_key ("Directional Pyramid Equalizer", "Algorithm")) { dirpyrequalizer.algo = keyFile.get_string ("Directional Pyramid Equalizer", "Algorithm"); if (pedited) pedited->dirpyrequalizer.algo = true; } if (keyFile.has_key ("Directional Pyramid Equalizer", "Hueskin")) { Glib::ArrayHandle thresh = keyFile.get_integer_list ("Directional Pyramid Equalizer", "Hueskin"); @@ -7880,6 +7896,7 @@ bool ProcParams::operator== (const ProcParams& other) // && dirpyrequalizer.algo == other.dirpyrequalizer.algo && dirpyrequalizer.hueskin == other.dirpyrequalizer.hueskin && dirpyrequalizer.threshold == other.dirpyrequalizer.threshold + && dirpyrequalizer.cbdlMethod == other.dirpyrequalizer.cbdlMethod && dirpyrequalizer.skinprotect == other.dirpyrequalizer.skinprotect && hsvequalizer.hcurve == other.hsvequalizer.hcurve && hsvequalizer.scurve == other.hsvequalizer.scurve diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 47b8f1cf1..b68db845c 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1106,7 +1106,7 @@ public: double skinprotect; Threshold hueskin; //Glib::ustring algo; - + Glib::ustring cbdlMethod; DirPyrEqualizerParams() : hueskin(20, 80, 2000, 1200, false) {}; }; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 6a2925be9..292a54133 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -119,8 +119,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = { ALLNORAW, // EvDPDNLuma, ALLNORAW, // EvDPDNChroma, ALLNORAW, // EvDPDNGamma, - DIRPYREQUALIZER, // EvDirPyrEqualizer, - DIRPYREQUALIZER, // EvDirPyrEqlEnabled, + ALLNORAW, // EvDirPyrEqualizer, + ALLNORAW, // EvDirPyrEqlEnabled, LUMINANCECURVE, // EvLSaturation, LUMINANCECURVE, // EvLaCurve, LUMINANCECURVE, // EvLbCurve, @@ -275,12 +275,12 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvLCLCurve LUMINANCECURVE, // EvLLHCurve LUMINANCECURVE, // EvLHHCurve - DIRPYREQUALIZER, // EvDirPyrEqualizerThreshold + ALLNORAW, // EvDirPyrEqualizerThreshold ALLNORAW, // EvDPDNenhance RGBCURVE, // EvBWMethodalg - DIRPYREQUALIZER, // EvDirPyrEqualizerSkin - DIRPYREQUALIZER, // EvDirPyrEqlgamutlab - DIRPYREQUALIZER, // EvDirPyrEqualizerHueskin + ALLNORAW, // EvDirPyrEqualizerSkin + ALLNORAW, // EvDirPyrEqlgamutlab + ALLNORAW, // EvDirPyrEqualizerHueskin ALLNORAW, // EvDPDNmedian ALLNORAW, // EvDPDNmedmet RGBCURVE, // EvColorToningEnabled @@ -465,6 +465,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { RETINEX, // EvLradius RETINEX, // EvmapMethod DEMOSAIC, // EvRetinexmapcurve - DEMOSAIC // EvviewMethod + DEMOSAIC, // EvviewMethod + ALLNORAW // EvcbdlMethod }; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 9ae940980..06bd755e4 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -739,6 +739,74 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p baseImg = trImg; } + + if (params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled) { + if(((!params.colorappearance.enabled))) { + TMatrix wprof, wiprof; + wprof = iccStore->workingSpaceMatrix( params.icm.working ); + wiprof = iccStore->workingSpaceInverseMatrix( params.icm.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]} + }; + + 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]} + }; + + int W = baseImg->getWidth(); + int H = baseImg->getHeight(); + LabImage * labcbdl; + labcbdl = new LabImage(W, H); +#ifndef _DEBUG + #pragma omp parallel for schedule(dynamic, 10) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float r = baseImg->r(i, j); + float g = baseImg->g(i, j); + float b = baseImg->b(i, j); + float X, Y, Z; + float L, aa, bb; + Color::rgbxyz(r, g, b, X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, aa, bb); + labcbdl->L[i][j] = L; + labcbdl->a[i][j] = aa; + labcbdl->b[i][j] = bb; + } + } + + ipf.dirpyrequalizer (labcbdl, 1, 0); + +#ifndef _DEBUG + #pragma omp parallel for schedule(dynamic, 10) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float L = labcbdl->L[i][j]; + float a = labcbdl->a[i][j]; + float b = labcbdl->b[i][j]; + float x1, y1, z1; + float R, G, B; + Color::Lab2XYZ(L, a, b, x1, y1, z1); + Color::xyz2rgb(x1, y1, z1, R, G, B, wip); + baseImg->r(i, j) = R; + baseImg->g(i, j) = G; + baseImg->b(i, j) = B; + } + } + + delete labcbdl; + + } + } + // update blurmap SHMap* shmap = NULL; @@ -982,9 +1050,12 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL ); + // directional pyramid wavelet - if((params.colorappearance.enabled && !settings->autocielab) || !params.colorappearance.enabled) { - ipf.dirpyrequalizer (labView, 1); //TODO: this is the luminance tonecurve, not the RGB one + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if((params.colorappearance.enabled && !settings->autocielab) || !params.colorappearance.enabled) { + ipf.dirpyrequalizer (labView, 1, 2); //TODO: this is the luminance tonecurve, not the RGB one + } } int kall = 2; diff --git a/rtgui/dirpyrequalizer.cc b/rtgui/dirpyrequalizer.cc index 5d8a7011e..7996a340e 100644 --- a/rtgui/dirpyrequalizer.cc +++ b/rtgui/dirpyrequalizer.cc @@ -51,6 +51,24 @@ DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, "dirpyrequalizer", Color::hsv2rgb01(0.3240, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(1. , r, g, b) ); // hsv: 0.324 rad: 2.5 + Gtk::VBox * cbVBox = Gtk::manage ( new Gtk::VBox()); + cbVBox->set_border_width(4); + cbVBox->set_spacing(2); + + cdbox = Gtk::manage (new Gtk::HBox ()); + labmcd = Gtk::manage (new Gtk::Label (M("TP_CBDL_METHOD") + ":")); + cdbox->pack_start (*labmcd, Gtk::PACK_SHRINK, 1); + + cbdlMethod = Gtk::manage (new MyComboBoxText ()); + cbdlMethod->append_text (M("TP_CBDL_BEF")); + cbdlMethod->append_text (M("TP_CBDL_AFT")); + cbdlMethod->set_active(0); + cbdlMethodConn = cbdlMethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrEqualizer::cbdlMethodChanged) ); + cbdlMethod->set_tooltip_markup (M("TP_CBDL_METHOD_TOOLTIP")); + cdbox->pack_start(*cbdlMethod); + cbVBox->pack_start(*cdbox); + pack_start(*cbVBox); + setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); Gtk::HBox * buttonBox1 = Gtk::manage (new Gtk::HBox(true, 10)); @@ -146,12 +164,17 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); + cbdlMethodConn.block(true); if (pedited) { set_inconsistent (multiImage && !pedited->dirpyrequalizer.enabled); gamutlab->set_inconsistent (!pedited->dirpyrequalizer.gamutlab); + if (!pedited->dirpyrequalizer.cbdlMethod) { + cbdlMethod->set_active_text(M("GENERAL_UNCHANGED")); + } + for(int i = 0; i < 6; i++) { multiplier[i]->setEditedState (pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited); } @@ -187,6 +210,15 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) skinprotect->setValue(pp->dirpyrequalizer.skinprotect); hueskin->setValue(pp->dirpyrequalizer.hueskin); + if (pp->dirpyrequalizer.cbdlMethod == "bef") { + cbdlMethod->set_active (0); + } else if (pp->dirpyrequalizer.cbdlMethod == "aft") { + cbdlMethod->set_active (1); + } + + cbdlMethodChanged (); + cbdlMethodConn.block(false); + enableListener (); } @@ -208,6 +240,7 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) pedited->dirpyrequalizer.enabled = !get_inconsistent(); pedited->dirpyrequalizer.hueskin = hueskin->getEditedState (); + pedited->dirpyrequalizer.cbdlMethod = cbdlMethod->get_active_text() != M("GENERAL_UNCHANGED"); for(int i = 0; i < 6; i++) { pedited->dirpyrequalizer.mult[i] = multiplier[i]->getEditedState(); @@ -218,6 +251,13 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) // pedited->dirpyrequalizer.algo = algo->get_active_text()!=M("GENERAL_UNCHANGED"); } + + if (cbdlMethod->get_active_row_number() == 0) { + pp->dirpyrequalizer.cbdlMethod = "bef"; + } else if (cbdlMethod->get_active_row_number() == 1) { + pp->dirpyrequalizer.cbdlMethod = "aft"; + } + /* if (algo->get_active_row_number()==0) pp->dirpyrequalizer.algo = "FI"; else if (algo->get_active_row_number()==1) @@ -282,6 +322,16 @@ void DirPyrEqualizer::setBatchMode (bool batchMode) // algo->append_text (M("GENERAL_UNCHANGED")); } +void DirPyrEqualizer::cbdlMethodChanged() +{ + + if (listener) { + listener->panelChanged (EvcbdlMethod, cbdlMethod->get_active_text ()); + } +} + + + void DirPyrEqualizer::adjusterChanged (Adjuster* a, double newval) { diff --git a/rtgui/dirpyrequalizer.h b/rtgui/dirpyrequalizer.h index 6c0a4613d..9b806989c 100644 --- a/rtgui/dirpyrequalizer.h +++ b/rtgui/dirpyrequalizer.h @@ -45,6 +45,10 @@ protected: sigc::connection lumaneutralPressedConn; sigc::connection lumacontrastPlusPressedConn; sigc::connection lumacontrastMinusPressedConn; + sigc::connection cbdlMethodConn; + Gtk::Label* labmcd; + Gtk::HBox* cdbox; + MyComboBoxText* cbdlMethod; bool lastgamutlab; @@ -61,7 +65,7 @@ public: void trimValues (rtengine::procparams::ProcParams* pp); void adjusterChanged (ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight); // void algoChanged (); - + void cbdlMethodChanged(); void adjusterChanged (Adjuster* a, double newval); void enabledChanged(); void gamutlabToggled (); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 062c61ba2..30d44f476 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -487,6 +487,8 @@ void ParamsEdited::set (bool v) dirpyrequalizer.enabled = v; dirpyrequalizer.gamutlab = v; + dirpyrequalizer.cbdlMethod = v; + for(int i = 0; i < 6; i++) { dirpyrequalizer.mult[i] = v; @@ -973,6 +975,7 @@ void ParamsEdited::initFrom (const std::vector dirpyrequalizer.enabled = dirpyrequalizer.enabled && p.dirpyrequalizer.enabled == other.dirpyrequalizer.enabled; dirpyrequalizer.gamutlab = dirpyrequalizer.gamutlab && p.dirpyrequalizer.gamutlab == other.dirpyrequalizer.gamutlab; + dirpyrequalizer.cbdlMethod = dirpyrequalizer.cbdlMethod && p.dirpyrequalizer.cbdlMethod == other.dirpyrequalizer.cbdlMethod; for(int i = 0; i < 6; i++) { dirpyrequalizer.mult[i] = dirpyrequalizer.mult[i] && p.dirpyrequalizer.mult[i] == other.dirpyrequalizer.mult[i]; @@ -2700,6 +2703,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; } + if (dirpyrequalizer.cbdlMethod) { + toEdit.dirpyrequalizer.cbdlMethod = mods.dirpyrequalizer.cbdlMethod; + } + for(int i = 0; i < 6; i++) { if(dirpyrequalizer.mult[i]) { toEdit.dirpyrequalizer.mult[i] = dontforceSet && options.baBehav[ADDSET_DIRPYREQ] ? toEdit.dirpyrequalizer.mult[i] + mods.dirpyrequalizer.mult[i] : mods.dirpyrequalizer.mult[i]; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 261da1753..3a0105c55 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -647,7 +647,7 @@ public: bool enabled; bool gamutlab; bool mult[6]; - + bool cbdlMethod; bool threshold; bool skinprotect; bool hueskin;