From 51de80b558c73db9b79fb76f0f9caff337e0326a Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 1 Mar 2016 19:16:34 +0100 Subject: [PATCH] Fixed bug with combination of cbdl and ciecam, cleaned code, made SSE version for lab2rgb --- rtdata/languages/default | 8 ++-- rtengine/dcrop.cc | 47 ++----------------- rtengine/imagedimensions.h | 4 +- rtengine/improccoordinator.cc | 50 ++------------------ rtengine/improcfun.cc | 88 +++++++++++++++++++++++++++++------ rtengine/improcfun.h | 4 +- rtengine/refreshmap.cc | 2 +- rtengine/simpleprocess.cc | 48 ++----------------- 8 files changed, 99 insertions(+), 152 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 553fc4a4b..69cc20327 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1204,11 +1204,11 @@ TP_BWMIX_TCMODE_SATANDVALBLENDING;B&W Saturation and Value Blending TP_BWMIX_TCMODE_STANDARD;B&W Standard TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard TP_BWMIX_VAL;L -TP_CACORRECTION_BLUE;Blue -TP_CACORRECTION_LABEL;Chromatic Aberration Correction -TP_CACORRECTION_RED;Red +TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. +TP_CBDL_AFT;After Black-and-White +TP_CBDL_BEF;Before Black-and-White 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_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 diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index cc993b811..4a0e928de 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -712,52 +712,15 @@ void Crop::update (int todo) transCrop = NULL; } - if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled) { - - TMatrix wprof = iccStore->workingSpaceMatrix( params.icm.working ); - const float wp[3][3] = { - {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, - {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, - {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])} - }; + if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) { const int W = baseCrop->getWidth(); const int H = baseCrop->getHeight(); LabImage labcbdl(W, H); -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif + parent->ipf.rgb2lab(*baseCrop, labcbdl, params.icm.working); + parent->ipf.dirpyrequalizer (&labcbdl, skip); + parent->ipf.lab2rgb(labcbdl, *baseCrop, params.icm.working); - //convert RGB => Lab - for(int i = 0; i < H; i++) { - for(int j = 0; j < W; j++) { - float X, Y, Z; - Color::rgbxyz(baseCrop->r(i, j), baseCrop->g(i, j), baseCrop->b(i, j), X, Y, Z, wp); - Color::XYZ2Lab(X, Y, Z, labcbdl.L[i][j], labcbdl.a[i][j], labcbdl.b[i][j]); - } - } - - parent->ipf.dirpyrequalizer (&labcbdl, skip, 0); - - TMatrix wiprof = iccStore->workingSpaceInverseMatrix( params.icm.working ); - const float wip[3][3] = { - {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, - {static_cast(wiprof[1][0]), static_cast(wiprof[1][1]), static_cast(wiprof[1][2])}, - {static_cast(wiprof[2][0]), static_cast(wiprof[2][1]), static_cast(wiprof[2][2])} - }; - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - //convert Lab => RGB - for(int i = 0; i < H; i++) { - for(int j = 0; j < W; j++) { - float X, Y, Z; - Color::Lab2XYZ(labcbdl.L[i][j], labcbdl.a[i][j], labcbdl.b[i][j], X, Y, Z); - Color::xyz2rgb(X, Y, Z, baseCrop->r(i, j), baseCrop->g(i, j), baseCrop->b(i, j), wip); - } - } } // blurmap for shadow & highlights @@ -889,7 +852,7 @@ void Crop::update (int todo) if(params.dirpyrequalizer.cbdlMethod == "aft") { if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled))) { - parent->ipf.dirpyrequalizer (labnCrop, skip, 1); + parent->ipf.dirpyrequalizer (labnCrop, skip); // parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip); } } diff --git a/rtengine/imagedimensions.h b/rtengine/imagedimensions.h index 0b50d71c1..e3b98f7c5 100644 --- a/rtengine/imagedimensions.h +++ b/rtengine/imagedimensions.h @@ -48,11 +48,11 @@ public: { return height; } - int getWidth () + int getWidth () const { return width; } - int getHeight () + int getHeight () const { return height; } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index bcb2c05ff..2f14c1ded 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -388,55 +388,15 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false); - - if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled) { - TMatrix wprof = iccStore->workingSpaceMatrix( params.icm.working ); - const float wp[3][3] = { - {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, - {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, - {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])} - }; - + if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) { const int W = oprevi->getWidth(); const int H = oprevi->getHeight(); LabImage labcbdl(W, H); -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - //convert RGB => Lab - for(int i = 0; i < H; i++) { - for(int j = 0; j < W; j++) { - float X, Y, Z; - Color::rgbxyz(oprevi->r(i, j), oprevi->g(i, j), oprevi->b(i, j), X, Y, Z, wp); - Color::XYZ2Lab(X, Y, Z, labcbdl.L[i][j], labcbdl.a[i][j], labcbdl.b[i][j]); - } - } - - ipf.dirpyrequalizer (&labcbdl, scale, 0); - - TMatrix wiprof = iccStore->workingSpaceInverseMatrix( params.icm.working ); - const float wip[3][3] = { - {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, - {static_cast(wiprof[1][0]), static_cast(wiprof[1][1]), static_cast(wiprof[1][2])}, - {static_cast(wiprof[2][0]), static_cast(wiprof[2][1]), static_cast(wiprof[2][2])} - }; - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for(int i = 0; i < H; i++) { - for(int j = 0; j < W; j++) { - float X, Y, Z; - Color::Lab2XYZ(labcbdl.L[i][j], labcbdl.a[i][j], labcbdl.b[i][j], X, Y, Z); - Color::xyz2rgb(X, Y, Z, oprevi->r(i, j), oprevi->g(i, j), oprevi->b(i, j), wip); - } - } + ipf.rgb2lab(*oprevi, labcbdl, params.icm.working); + ipf.dirpyrequalizer (&labcbdl, scale); + ipf.lab2rgb(labcbdl, *oprevi, params.icm.working); } - - readyphase++; progress ("Preparing shadow/highlight map...", 100 * readyphase / numofphases); @@ -710,7 +670,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) 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.dirpyrequalizer (nprevl, scale); //ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale); readyphase++; } diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index df8821a4b..79a0bb36c 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -52,17 +52,6 @@ namespace rtengine using namespace procparams; -#undef ABS -#undef CLIPS -#undef CLIPC - -#define ABS(a) ((a)<0?-(a):(a)) -#define CLIPS(a) ((a)>-32768?((a)<32767?(a):32767):-32768) -#define CLIPC(a) ((a)>-32000?((a)<32000?(a):32000):-32000) -#define CLIP2(a) ((a)0.0?((a)<65535.5?(a):65535.5):0.0) - - extern const Settings* settings; LUTf ImProcFunctions::cachef; LUTf ImProcFunctions::gamma2curve; @@ -6537,7 +6526,7 @@ void ImProcFunctions::badpixlab(LabImage* lab, double rad, int thr, int mode, fl } } -void ImProcFunctions::dirpyrequalizer (LabImage* lab, int scale, int mode) +void ImProcFunctions::dirpyrequalizer (LabImage* lab, int scale) { if (params->dirpyrequalizer.enabled && lab->W >= 8 && lab->H >= 8) { float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; @@ -7146,8 +7135,79 @@ double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_si } } +void ImProcFunctions::rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace) +{ + TMatrix wprof = iccStore->workingSpaceMatrix( workingSpace ); + const float wp[3][3] = { + {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, + {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, + {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])} + }; + + const int W = src.getWidth(); + const int H = src.getHeight(); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float X, Y, Z; + Color::rgbxyz(src.r(i, j), src.g(i, j), src.b(i, j), X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, dst.L[i][j], dst.a[i][j], dst.b[i][j]); + } + } +} + +SSEFUNCTION void ImProcFunctions::lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace) +{ + TMatrix wiprof = iccStore->workingSpaceInverseMatrix( workingSpace ); + const float wip[3][3] = { + {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, + {static_cast(wiprof[1][0]), static_cast(wiprof[1][1]), static_cast(wiprof[1][2])}, + {static_cast(wiprof[2][0]), static_cast(wiprof[2][1]), static_cast(wiprof[2][2])} + }; + + const int W = dst.getWidth(); + const int H = dst.getHeight(); +#ifdef __SSE2__ + vfloat wipv[3][3]; + + for(int i = 0; i < 3; i++) { + for(int j = 0; j < 3; j++) { + wipv[i][j] = F2V(wiprof[i][j]); + } + } +#endif + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = 0; i < H; i++) { + int j = 0; +#ifdef __SSE2__ + for(; j < W - 3; j += 4) { + vfloat X, Y, Z; + vfloat R,G,B; + Color::Lab2XYZ(LVFU(src.L[i][j]), LVFU(src.a[i][j]), LVFU(src.b[i][j]), X, Y, Z); + Color::xyz2rgb(X, Y, Z, R, G, B, wipv); + STVFU(dst.r(i, j), R); + STVFU(dst.g(i, j), G); + STVFU(dst.b(i, j), B); + } + +#endif + for(; j < W; j++) { + float X, Y, Z; + Color::Lab2XYZ(src.L[i][j], src.a[i][j], src.b[i][j], X, Y, Z); + Color::xyz2rgb(X, Y, Z, dst.r(i, j), dst.g(i, j), dst.b(i, j), wip); + } + } +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } -#undef PIX_SORT -#undef med3x3 diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index f69f04e19..133c59f6e 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -284,7 +284,7 @@ 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, int mode);//Emil's wavelet + void dirpyrequalizer (LabImage* lab, int scale);//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); @@ -384,6 +384,8 @@ public: static void getAutoExp (LUTu & histogram, int histcompr, double defgain, double clip, double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh); static double getAutoDistor (const Glib::ustring& fname, int thumb_size); double getTransformAutoFill (int oW, int oH, const LCPMapper *pLCPMap = NULL); + void rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace); + void lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace); }; } #endif diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 292a54133..1bcaf3fa3 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -200,7 +200,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvLLCCurve LUMINANCECURVE, // EvLLCredsk ALLNORAW, // EvDPDNLdetail - LUMINANCECURVE, // EvCATEnabled + ALLNORAW, // EvCATEnabled LUMINANCECURVE, // EvCATDegree LUMINANCECURVE, // EvCATMethodsur LUMINANCECURVE, // EvCATAdapscen diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 1d171e09a..c03addb42 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -740,51 +740,13 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p } - if (params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled) { - TMatrix wprof = iccStore->workingSpaceMatrix( params.icm.working ); - const float wp[3][3] = { - {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, - {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, - {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])} - }; - + if (params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) { const int W = baseImg->getWidth(); const int H = baseImg->getHeight(); LabImage labcbdl(W, H); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for(int i = 0; i < H; i++) { - for(int j = 0; j < W; j++) { - float X, Y, Z; - Color::rgbxyz(baseImg->r(i, j), baseImg->g(i, j), baseImg->b(i, j), X, Y, Z, wp); - //convert Lab - Color::XYZ2Lab(X, Y, Z, labcbdl.L[i][j], labcbdl.a[i][j], labcbdl.b[i][j]); - } - } - - ipf.dirpyrequalizer (&labcbdl, 1, 0); - - TMatrix wiprof = iccStore->workingSpaceInverseMatrix( params.icm.working ); - const float wip[3][3] = { - {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, - {static_cast(wiprof[1][0]), static_cast(wiprof[1][1]), static_cast(wiprof[1][2])}, - {static_cast(wiprof[2][0]), static_cast(wiprof[2][1]), static_cast(wiprof[2][2])} - }; - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for(int i = 0; i < H; i++) { - for(int j = 0; j < W; j++) { - float X, Y, Z; - Color::Lab2XYZ(labcbdl.L[i][j], labcbdl.a[i][j], labcbdl.b[i][j], X, Y, Z); - Color::xyz2rgb(X, Y, Z, baseImg->r(i, j), baseImg->g(i, j), baseImg->b(i, j), wip); - } - } + ipf.rgb2lab(*baseImg, labcbdl, params.icm.working); + ipf.dirpyrequalizer (&labcbdl, 1); + ipf.lab2rgb(labcbdl, *baseImg, params.icm.working); } // update blurmap @@ -1034,7 +996,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p // directional pyramid wavelet 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 + ipf.dirpyrequalizer (labView, 1); //TODO: this is the luminance tonecurve, not the RGB one } }