From 44490e81ae9bb9cde02cfcc9d61de2d4d9db39ed Mon Sep 17 00:00:00 2001 From: Desmis Date: Thu, 12 Nov 2015 08:58:07 +0100 Subject: [PATCH] Add mask method --- rtdata/languages/default | 17 +++ rtengine/curves.cc | 39 ++++++ rtengine/curves.h | 1 + rtengine/imagesource.h | 6 +- rtengine/improccoordinator.cc | 6 +- rtengine/ipretinex.cc | 95 ++++++++++++-- rtengine/procevents.h | 7 ++ rtengine/procparams.cc | 104 ++++++++++++++++ rtengine/procparams.h | 8 ++ rtengine/rawimagesource.cc | 7 +- rtengine/rawimagesource.h | 6 +- rtengine/refreshmap.cc | 15 ++- rtengine/shmap.cc | 162 ++++++++++++++++++++++++ rtengine/shmap.h | 2 + rtengine/simpleprocess.cc | 6 +- rtgui/paramsedited.cc | 46 +++++++ rtgui/paramsedited.h | 8 ++ rtgui/retinex.cc | 228 ++++++++++++++++++++++++++++++++++ rtgui/retinex.h | 15 ++- 19 files changed, 750 insertions(+), 28 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index e7836298a..97b327ef6 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -659,6 +659,13 @@ HISTORY_MSG_426;Retinex - Hue equalizer HISTORY_MSG_427;Retinex - Iterations HISTORY_MSG_428;Retinex - T. Gradient HISTORY_MSG_429;Retinex - S. Gradient +HISTORY_MSG_430;Retinex - Mask highlights +HISTORY_MSG_431;Retinex - Mask TW highlights +HISTORY_MSG_432;Retinex - Mask shadows +HISTORY_MSG_433;Retinex - Mask TW shadows +HISTORY_MSG_434;Retinex - Mask radius +HISTORY_MSG_435;Retinex - Mask method +HISTORY_MSG_436;Retinex - Mask curve HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOTS;Snapshots @@ -1637,6 +1644,9 @@ TP_RESIZE_W;Width: TP_RETINEX_CONTEDIT_HSL;Histogram equalizer HSL TP_RETINEX_CONTEDIT_LAB;Histogram equalizer L*a*b* TP_RETINEX_CONTEDIT_LH;Hue equalizer +TP_RETINEX_CONTEDIT_MAP;Mask equalizer +TP_RETINEX_CURVEEDITOR_MAP;L=f(L) +TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;This Curve can be applied alone or with gaussian mask or wavelet mask\nBe aware to artifacts TP_RETINEX_CURVEEDITOR_CD;L=f(L) TP_RETINEX_CURVEEDITOR_CD_TOOLTIP;Luminance according to luminance L=f(L)\nCorrect raw data to reduce halos and artifacts. TP_RETINEX_CURVEEDITOR_LH;Strength=f(H) @@ -1666,6 +1676,13 @@ TP_RETINEX_GRADS_TOOLTIP;If slider at 0, all iterations are identical\nIf > 0 St TP_RETINEX_LABEL;Retinex TP_RETINEX_LABSPACE;L*a*b* TP_RETINEX_LOW;Low +TP_RETINEX_MAP;Mask method +TP_RETINEX_MAP_METHOD_TOOLTIP;Use the mask generate by Gaussian function above to reduce halos and artifacts\nCurve only: apply a diagonal contrast curve on mask, be aware to artifacts\nGaussian mask : generate and use a gaussian blur of the original mask (quick)\nSharp mask : generate and use a wavelet on the original mask (slow or very very slow) +TP_RETINEX_MAP_NONE;none +TP_RETINEX_MAP_CURV;Curve only +TP_RETINEX_MAP_GAUS;Gaussian mask +TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) +TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) TP_RETINEX_MEDIAN;Transmission median filter TP_RETINEX_METHOD;Method TP_RETINEX_METHOD_TOOLTIP;Low = Reinforce low light,\nUniform = Equalize action,\nHigh = Reinforce high light,\nHighlights = Remove magenta in highlights. diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 4ad1d06bd..d0b4c026f 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -504,6 +504,45 @@ void CurveFactory::curveCL ( bool & clcutili, const std::vector& clcurve } } +void CurveFactory::mapcurve ( bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, LUTu & histogram, LUTu & outBeforeCurveHistogram) +{ + bool needed = false; + DiagonalCurve* dCurve = NULL; + outBeforeCurveHistogram.clear(); + bool histNeeded = false; + + if (!mapcurvePoints.empty() && mapcurvePoints[0] != 0) { + dCurve = new DiagonalCurve (mapcurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCurveHistogram) { + histNeeded = true; + } + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + mapcontlutili = true; + } + } + + if (histNeeded) { + for (int i = 0; i < 32768; i++) { + double hval = CLIPD((double)i / 32767.0); + int hi = (int)(255.0 * hval); + outBeforeCurveHistogram[hi] += histogram[i] ; + } + } + + fillCurveArray(dCurve, mapcurve, skip, needed); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } +} + + + + void CurveFactory::curveDehaContL ( bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, LUTu & histogram, LUTu & outBeforeCurveHistogram) { bool needed = false; diff --git a/rtengine/curves.h b/rtengine/curves.h index f0643c7a9..e55d7bc2a 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -283,6 +283,7 @@ public: static void curveWavContL ( bool & wavcontlutili, const std::vector& wavclcurvePoints, LUTf & wavclCurve,/* LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip); static void curveDehaContL ( bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, LUTu & histogram, LUTu & outBeforeCurveHistogram); + static void mapcurve ( bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, LUTu & histogram, LUTu & outBeforeCurveHistogram); static void curveToningCL ( bool & clctoningutili, const std::vector& clcurvePoints, LUTf & clToningCurve, int skip); static void curveToningLL ( bool & llctoningutili, const std::vector& llcurvePoints, LUTf & llToningCurve, int skip); diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index d9f088813..eaf9997fa 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -69,14 +69,14 @@ public: virtual int load (Glib::ustring fname, bool batch = false) = 0; virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse) {}; virtual void demosaic (const RAWParams &raw) {}; - virtual void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, const RetinextransmissionCurve & dehatransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; - virtual void retinexPrepareCurves (RetinexParams retinexParams, LUTf &cdcurve, RetinextransmissionCurve &retinextransmissionCurve, bool &retinexcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; + virtual void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, const RetinextransmissionCurve & dehatransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; + virtual void retinexPrepareCurves (RetinexParams retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; virtual void retinexPrepareBuffers (ColorManagementParams cmp, RetinexParams retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) {}; virtual void flushRawData () {}; virtual void flushRGB () {}; virtual void HLRecovery_Global (ToneCurveParams hrp) {}; virtual void HLRecovery_inpaint (float** red, float** green, float** blue) {}; - virtual void MSR(LabImage* lab, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) {}; + virtual void MSR(LabImage* lab, LUTf & mapcurve, bool &mapcontlutili, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) {}; virtual bool IsrgbSourceModified() = 0; // tracks whether cached rgb output of demosaic has been modified diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 8389ec34e..479ec1282 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -244,12 +244,14 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) if ((todo & (M_RETINEX|M_INIT)) && params.retinex.enabled) { bool dehacontlutili = false; + bool mapcontlutili = false; bool useHsl = false; LUTf cdcurve (65536, 0); + LUTf mapcurve (65536, 0); - imgsrc->retinexPrepareCurves(params.retinex, cdcurve, dehatransmissionCurve, dehacontlutili, useHsl, lhist16RETI, histLRETI); + imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehacontlutili, mapcontlutili, useHsl, lhist16RETI, histLRETI); float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax; - imgsrc->retinex( params.icm, params.retinex, params.toneCurve, cdcurve, dehatransmissionCurve, conversionBuffer, dehacontlutili, useHsl, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, histLRETI);//enabled Retinex + imgsrc->retinex( params.icm, params.retinex, params.toneCurve, mapcurve, dehatransmissionCurve, conversionBuffer, dehacontlutili, mapcontlutili, useHsl, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, histLRETI);//enabled Retinex if(dehaListener) { dehaListener->minmaxChanged(maxCD, minCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc index 0f67c1a84..d444380ce 100644 --- a/rtengine/ipretinex.cc +++ b/rtengine/ipretinex.cc @@ -32,6 +32,7 @@ * College of Physics and Information Engineering, Fuzhou University, Fuzhou, China * inspired from 2003 Fabien Pelisson + * some ideas taken (use of mask) Russell Cottrell - The Retinex .8bf Plugin */ @@ -205,7 +206,7 @@ void mean_stddv( float **dst, float &mean, float &stddv, int W_L, int H_L, const stddv = (float)sqrt(stddv); } -void RawImageSource::MSR(float** luminance, float** originalLuminance, float **exLuminance, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) +void RawImageSource::MSR(float** luminance, float** originalLuminance, float **exLuminance, LUTf & mapcurve, bool &mapcontlutili, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) { if (deh.enabled) {//enabled float mean, stddv, maxtr, mintr; @@ -234,7 +235,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e bool higplus = false ; float elogt; float hl = deh.baselog; - + SHMap* shmap; if(hl >= 2.71828f) { elogt = 2.71828f + SQR(SQR(hl - 2.71828f)); } else { @@ -382,13 +383,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e } } strengthx=ks*strength; - /* - float aahi = 49.f / 99.f; ////reduce sensibility 50% - float bbhi = 1.f - aahi; - float high; - high = bbhi + aahi * (float) deh.highl; - */ - printf("high=%f moderetinex=%d\n",high,moderetinex); + retinex_scales( RetinexScales, scal, moderetinex, nei/grad, high ); int H_L = height; @@ -401,6 +396,17 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e src[i] = &srcBuffer[i * W_L]; } + int h_th, s_th; + + int shHighlights = deh.highlights; + int shShadows = deh.shadows; + int mapmet=0; + if(deh.mapMethod=="map") mapmet=2; + if(deh.mapMethod=="mapT") mapmet=3; + if(deh.mapMethod=="curv") mapmet=1; + if(deh.mapMethod=="gaus") mapmet=4; + + #ifdef _OPENMP #pragma omp parallel for #endif @@ -425,6 +431,10 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e pond /= log(elogt); } + if(mapmet > 1) shmap = new SHMap (W_L, H_L, true); + + + float *buffer = new float[W_L * H_L];; #ifdef _OPENMP #pragma omp parallel @@ -434,9 +444,26 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e if(scale == scal - 1) { gaussianBlur (src, out, W_L, H_L, RetinexScales[scale], buffer); } else { - printf("reti=%f\n",RetinexScales[scale]);// reuse result of last iteration + // reuse result of last iteration gaussianBlur (out, out, W_L, H_L, sqrtf(SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), buffer); } + //printf("scal=%d RetinexScales=%f\n",scale, RetinexScales[scale]); + printf(".."); + + + double shradius = deh.radius; + if(mapmet==4) shradius /= 10.; + + // if(shHighlights > 0 || shShadows > 0) { + if(mapmet==3) if(it==1) shmap->updateL (out, shradius, true, 1);//wav Total + if(mapmet==2 && scale >2) if(it==1) shmap->updateL (out, shradius, true, 1);//wav partial + if(mapmet==4) if(it==1) shmap->updateL (out, shradius, false, 1);//gauss + // } + if (shmap) { + h_th = shmap->max_f - deh.htonalwidth * (shmap->max_f - shmap->avg) / 100; + s_th = deh.stonalwidth * (shmap->avg - shmap->min_f) / 100; + } + #ifdef __SSE2__ vfloat pondv = F2V(pond); @@ -444,6 +471,47 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e vfloat limMaxv = F2V(limdx); #endif + + if(mapmet > 0) { +#ifdef _OPENMP + #pragma omp for +#endif + for (int i = 0; i < H_L; i++) { + if(mapcontlutili) { + int j = 0; + for (; j < W_L; j++) { + if(it==1) out[i][j] = mapcurve[2.f * out[i][j]] / 2.f; + } + } + } + + } + + // if(shHighlights > 0 || shShadows > 0) { + if((mapmet == 2 && scale >2) || mapmet==3 || mapmet==4) { + + +#ifdef _OPENMP + #pragma omp for +#endif + for (int i = 0; i < H_L; i++) { + int j = 0; + for (; j < W_L; j++) { + double mapval = 1.0 + shmap->map[i][j]; + double factor = 1.0; + + if (mapval > h_th) { + factor = (h_th + (100.0 - shHighlights) * (mapval - h_th) / 100.0) / mapval; + } else if (mapval < s_th) { + factor = (s_th - (100.0 - shShadows) * (s_th - mapval) / 100.0) / mapval; + } + out[i][j] *= factor; + + } + } + } + // } + #ifdef _OPENMP #pragma omp for #endif @@ -477,6 +545,13 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e } } } + if(mapmet > 1) { + if(shmap) { + delete shmap; + } + } + shmap = NULL; + delete [] buffer; delete [] outBuffer; delete [] srcBuffer; diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 6f1d7144a..f23d68f2e 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -457,6 +457,13 @@ enum ProcEvent { EvLiter = 426, EvLgrad = 427, EvLgrads = 428, + EvLhighlights = 429, + EvLh_tonalwidth = 430, + EvLshadows = 431, + EvLs_tonalwidth = 432, + EvLradius = 433, + EvmapMethod = 434, + EvRetinexmapcurve = 435, NUMOFEVENTS }; } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 6c737f8a2..075067585 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -153,9 +153,16 @@ void RetinexParams::setDefaults() vart = 200; limd = 8; highl = 4; + highlights = 0; + htonalwidth = 80; + shadows = 0; + stonalwidth = 80; + radius = 40; + baselog = 2.71828; // grbl = 50; retinexMethod = "high"; + mapMethod = "none"; retinexcolorspace = "Lab"; gammaretinex = "none"; medianmap = false; @@ -165,6 +172,8 @@ void RetinexParams::setDefaults() cdHcurve.push_back(DCT_Linear); lhcurve.clear(); lhcurve.push_back(DCT_Linear); + mapcurve.clear(); + mapcurve.push_back(DCT_Linear); getDefaulttransmissionCurve(transmissionCurve); } @@ -1513,6 +1522,10 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_string ("Retinex", "RetinexMethod", retinex.retinexMethod); } + if (!pedited || pedited->retinex.mapMethod) { + keyFile.set_string ("Retinex", "mapMethod", retinex.mapMethod); + } + if (!pedited || pedited->retinex.retinexcolorspace) { keyFile.set_string ("Retinex", "Retinexcolorspace", retinex.retinexcolorspace); } @@ -1526,6 +1539,11 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_double_list("Retinex", "CDCurve", cdcurve); } + if (!pedited || pedited->retinex.mapcurve) { + Glib::ArrayHandle mapcurve = retinex.mapcurve; + keyFile.set_double_list("Retinex", "MAPCurve", mapcurve); + } + if (!pedited || pedited->retinex.cdHcurve) { Glib::ArrayHandle cdHcurve = retinex.cdHcurve; keyFile.set_double_list("Retinex", "CDHCurve", cdHcurve); @@ -1536,6 +1554,26 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_double_list("Retinex", "LHCurve", lhcurve); } + if (!pedited || pedited->retinex.highlights) { + keyFile.set_integer ("Retinex", "Highlights", retinex.highlights); + } + + if (!pedited || pedited->retinex.htonalwidth) { + keyFile.set_integer ("Retinex", "HighlightTonalWidth", retinex.htonalwidth); + } + + if (!pedited || pedited->retinex.shadows) { + keyFile.set_integer ("Retinex", "Shadows", retinex.shadows); + } + + if (!pedited || pedited->retinex.stonalwidth) { + keyFile.set_integer ("Retinex", "ShadowTonalWidth", retinex.stonalwidth); + } + + if (!pedited || pedited->retinex.radius) { + keyFile.set_integer ("Retinex", "Radius", retinex.radius); + } + if (!pedited || pedited->retinex.transmissionCurve) { Glib::ArrayHandle transmissionCurve = retinex.transmissionCurve; keyFile.set_double_list("Retinex", "TransmissionCurve", transmissionCurve); @@ -3818,6 +3856,14 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + if (keyFile.has_key ("Retinex", "mapMethod")) { + retinex.mapMethod = keyFile.get_string ("Retinex", "mapMethod"); + + if (pedited) { + pedited->retinex.mapMethod = true; + } + } + if (keyFile.has_key ("Retinex", "Retinexcolorspace")) { retinex.retinexcolorspace = keyFile.get_string ("Retinex", "Retinexcolorspace"); @@ -3970,6 +4016,14 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + if (keyFile.has_key ("Retinex", "MAPCurve")) { + retinex.mapcurve = keyFile.get_double_list ("Retinex", "MAPCurve"); + + if (pedited) { + pedited->retinex.mapcurve = true; + } + } + if (keyFile.has_key ("Retinex", "CDHCurve")) { retinex.cdHcurve = keyFile.get_double_list ("Retinex", "CDHCurve"); @@ -3986,6 +4040,48 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + if (keyFile.has_key ("Retinex", "Highlights")) { + retinex.highlights = keyFile.get_integer ("Retinex", "Highlights"); + + if (pedited) { + pedited->retinex.highlights = true; + } + } + + if (keyFile.has_key ("Retinex", "HighlightTonalWidth")) { + retinex.htonalwidth = keyFile.get_integer ("Retinex", "HighlightTonalWidth"); + + if (pedited) { + pedited->retinex.htonalwidth = true; + } + } + + if (keyFile.has_key ("Retinex", "Shadows")) { + retinex.shadows = keyFile.get_integer ("Retinex", "Shadows"); + + if (pedited) { + pedited->retinex.shadows = true; + } + } + + if (keyFile.has_key ("Retinex", "ShadowTonalWidth")) { + retinex.stonalwidth = keyFile.get_integer ("Retinex", "ShadowTonalWidth"); + + if (pedited) { + pedited->retinex.stonalwidth = true; + } + } + + + if (keyFile.has_key ("Retinex", "Radius")) { + sh.radius = keyFile.get_integer ("Retinex", "Radius"); + + if (pedited) { + pedited->retinex.radius = true; + } + } + + if (keyFile.has_key ("Retinex", "TransmissionCurve")) { retinex.transmissionCurve = keyFile.get_double_list ("Retinex", "TransmissionCurve"); @@ -7356,6 +7452,7 @@ bool ProcParams::operator== (const ProcParams& other) && toneCurve.hrenabled == other.toneCurve.hrenabled && toneCurve.method == other.toneCurve.method && retinex.cdcurve == other.retinex.cdcurve + && retinex.mapcurve == other.retinex.mapcurve && retinex.cdHcurve == other.retinex.cdHcurve && retinex.lhcurve == other.retinex.lhcurve && retinex.transmissionCurve == other.retinex.transmissionCurve @@ -7370,10 +7467,17 @@ bool ProcParams::operator== (const ProcParams& other) && retinex.gain == other.retinex.gain && retinex.limd == other.retinex.limd && retinex.highl == other.retinex.highl + && retinex.highlights == other.retinex.highlights + && retinex.htonalwidth == other.retinex.htonalwidth + && retinex.shadows == other.retinex.shadows + && retinex.stonalwidth == other.retinex.stonalwidth + && retinex.radius == other.retinex.radius + && retinex.baselog == other.retinex.baselog // && retinex.grbl == other.retinex.grbl && retinex.offs == other.retinex.offs && retinex.retinexMethod == other.retinex.retinexMethod + && retinex.mapMethod == other.retinex.mapMethod && retinex.retinexcolorspace == other.retinex.retinexcolorspace && retinex.gammaretinex == other.retinex.gammaretinex && retinex.vart == other.retinex.vart diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 2b8b7ada6..e2d2539ea 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -273,6 +273,7 @@ public: std::vector cdHcurve; std::vector lhcurve; std::vector transmissionCurve; + std::vector mapcurve; int str; int scal; int iter; @@ -283,9 +284,16 @@ public: int neigh; int gain; int offs; + int highlights; + int htonalwidth; + int shadows; + int stonalwidth; + int radius; + Glib::ustring retinexMethod; Glib::ustring retinexcolorspace; Glib::ustring gammaretinex; + Glib::ustring mapMethod; int vart; int limd; int highl; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 32d91be64..8a4fc3559 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2107,7 +2107,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar } -void RawImageSource::retinexPrepareCurves(RetinexParams retinexParams, LUTf &cdcurve, RetinextransmissionCurve &retinextransmissionCurve, bool &retinexcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) +void RawImageSource::retinexPrepareCurves(RetinexParams retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) { useHsl = (retinexParams.retinexcolorspace == "HSLLOG" || retinexParams.retinexcolorspace == "HSLLIN"); @@ -2116,12 +2116,13 @@ void RawImageSource::retinexPrepareCurves(RetinexParams retinexParams, LUTf &cdc } else { CurveFactory::curveDehaContL (retinexcontlutili, retinexParams.cdcurve, cdcurve, 1, lhist16RETI, histLRETI); } + CurveFactory::mapcurve (mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI); retinexParams.getCurves(retinextransmissionCurve); } //void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, const RetinextransmissionCurve & dehatransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) -void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, const RetinextransmissionCurve & dehatransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) +void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, const RetinextransmissionCurve & dehatransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) { MyTime t4, t5; @@ -2273,7 +2274,7 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC } } - MSR(LBuffer, conversionBuffer[2], conversionBuffer[3], WNew, HNew, deh, dehatransmissionCurve, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); + MSR(LBuffer, conversionBuffer[2], conversionBuffer[3], cdcurve, mapcontlutili, WNew, HNew, deh, dehatransmissionCurve, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); if(useHsl) { if(chutili) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index ee89dd079..f9e7e6cf1 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -152,8 +152,8 @@ public: void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse); void demosaic (const RAWParams &raw); // void retinex (RAWParams raw, ColorManagementParams cmp, RetinexParams lcur, LUTf & cdcurve, bool dehacontlutili); - void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, const RetinextransmissionCurve & dehatransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); - void retinexPrepareCurves (RetinexParams retinexParams, LUTf &cdcurve, RetinextransmissionCurve &retinextransmissionCurve, bool &retinexcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI); + void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, const RetinextransmissionCurve & dehatransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); + void retinexPrepareCurves (RetinexParams retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI); void retinexPrepareBuffers (ColorManagementParams cmp, RetinexParams retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI); void flushRawData (); void flushRGB (); @@ -230,7 +230,7 @@ public: void boxblur2(float** src, float** dst, float** temp, int H, int W, int box ); void boxblur_resamp(float **src, float **dst, float** temp, int H, int W, int box, int samp ); - void MSR(float** luminance, float **originalLuminance, float **exLuminance, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); + void MSR(float** luminance, float **originalLuminance, float **exLuminance, LUTf & mapcurve, bool &mapcontlutili, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); // void MSR(LabImage* lab, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve); //void boxblur_resamp(float **red, float **green, float **blue, int H, int W, float thresh[3], float max[3], diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 30373a35e..83cacfa1a 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -453,10 +453,17 @@ int refreshmap[rtengine::NUMOFEVENTS] = { RETINEX, // EvLhighl DEMOSAIC, // EvLbaselog // DEMOSAIC, // EvLgrbl - DEMOSAIC, // EvRetinexlhcurve - RETINEX, // EvLiter - RETINEX, // EvLgrad - RETINEX // EvLgrads + DEMOSAIC, // EvRetinexlhcurve + RETINEX, // EvLiter + RETINEX, // EvLgrad + RETINEX, // EvLgrads + RETINEX, //EvLhighlights + RETINEX, //EvLh_tonalwidth + RETINEX, //EvLshadows + RETINEX, //EvLs_tonalwidth + RETINEX, //EvLradius + RETINEX, //EvmapMethod + RETINEX //EvRetinexmapcurve }; diff --git a/rtengine/shmap.cc b/rtengine/shmap.cc index 34fadd5e7..f1539171d 100644 --- a/rtengine/shmap.cc +++ b/rtengine/shmap.cc @@ -64,6 +64,20 @@ void SHMap::fillLuminance( Imagefloat * img, float **luminance, double lumi[3] ) } +void SHMap::fillLuminanceL( float ** L, float **luminance) // fill with luminance +{ + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + luminance[i][j] = std::max(L[i][j], 0.f) ;//we can put here some enhancements Gamma, compression data,... + } + +} + void SHMap::update (Imagefloat* img, double radius, double lumi[3], bool hq, int skip) { @@ -210,6 +224,154 @@ void SHMap::update (Imagefloat* img, double radius, double lumi[3], bool hq, int } +void SHMap::updateL (float** L, double radius, bool hq, int skip) +{ + + if (!hq) { + fillLuminanceL( L, map); +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur (map, map, W, H, radius); + } + } + + else + + { + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //experimental dirpyr shmap + + float thresh = (100.f * radius); //1000; + + // set up range function + // calculate size of Lookup table. That's possible because from a value k for all i>=k rangefn[i] will be exp(-10) + // So we use this fact and the automatic clip of lut to reduce the size of lut and the number of calculations to fill the lut + // In past this lut had only integer precision with rangefn[i] = 0 for all i>=k + // We set the last element to a small epsilon 1e-15 instead of zero to avoid divisions by zero + const int lutSize = thresh * sqrtf(10.f) + 1; + thresh *= thresh; + LUTf rangefn(lutSize); + + for (int i = 0; i < lutSize - 1; i++) { + rangefn[i] = xexpf(-min(10.f, (static_cast(i) * i) / thresh )); //*intfactor; + } + + rangefn[lutSize - 1] = 1e-15f; + + // We need one temporary buffer + float ** buffer = allocArray (W, H); + + // the final result has to be in map + // for an even number of levels that means: map => buffer, buffer => map + // for an odd number of levels that means: buffer => map, map => buffer, buffer => map + // so let's calculate the number of levels first + // There are at least two levels + int numLevels = 2; + int scale = 2; + + while (skip * scale < 16) { + scale *= 2; + numLevels++; + } + //printf("numlev=%d\n",numLevels); + float ** dirpyrlo[2]; + + if(numLevels & 1) { // odd number of levels, start with buffer + dirpyrlo[0] = buffer; + dirpyrlo[1] = map; + } else { // even number of levels, start with map + dirpyrlo[0] = map; + dirpyrlo[1] = buffer; + } + + fillLuminanceL( L, dirpyrlo[0]); + + scale = 1; + int level = 0; + int indx = 0; + dirpyr_shmap(dirpyrlo[indx], dirpyrlo[1 - indx], W, H, rangefn, level, scale ); + scale *= 2; + level ++; + indx = 1 - indx; + + while (skip * scale < 16) { + dirpyr_shmap(dirpyrlo[indx], dirpyrlo[1 - indx], W, H, rangefn, level, scale ); + scale *= 2; + level ++; + indx = 1 - indx; + } + + dirpyr_shmap(dirpyrlo[indx], dirpyrlo[1 - indx], W, H, rangefn, level, scale ); + + freeArray(buffer, H); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + /* + // anti-alias filtering the result + #ifdef _OPENMP + #pragma omp for + #endif + for (int i=0; i0 && j>0 && i _max_f) { + _max_f = _val; + } + + _avg += _val; + } + +#ifdef _OPENMP + #pragma omp critical +#endif + { + if(_min_f < min_f ) { + min_f = _min_f; + } + + if(_max_f > max_f ) { + max_f = _max_f; + } + } + } + _avg /= ((H) * (W)); + avg = _avg; + +} + + void SHMap::forceStat (float max_, float min_, float avg_) { diff --git a/rtengine/shmap.h b/rtengine/shmap.h index 3d5609f48..97a394927 100644 --- a/rtengine/shmap.h +++ b/rtengine/shmap.h @@ -36,6 +36,7 @@ public: ~SHMap (); void update (Imagefloat* img, double radius, double lumi[3], bool hq, int skip); + void updateL (float** L, double radius, bool hq, int skip); void forceStat (float max_, float min_, float avg_); private: @@ -43,6 +44,7 @@ private: bool multiThread; void fillLuminance( Imagefloat * img, float **luminance, double lumi[3] ); + void fillLuminanceL( float ** L, float **luminance ); void dirpyr_shmap(float ** data_fine, float ** data_coarse, int width, int height, LUTf & rangefn, int level, int scale); }; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 91b7df178..1836c5446 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -118,16 +118,18 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p if(params.retinex.enabled) { //enabled Retinex LUTf cdcurve (65536, 0); + LUTf mapcurve (65536, 0); LUTu dummy; RetinextransmissionCurve dehatransmissionCurve; bool dehacontlutili = false; + bool mapcontlutili = false; bool useHsl = false; // multi_array2D conversionBuffer(1, 1); multi_array2D conversionBuffer(1, 1); imgsrc->retinexPrepareBuffers(params.icm, params.retinex, conversionBuffer, dummy); - imgsrc->retinexPrepareCurves(params.retinex, cdcurve, dehatransmissionCurve, dehacontlutili, useHsl, dummy, dummy ); + imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehacontlutili, mapcontlutili, useHsl, dummy, dummy ); float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax; - imgsrc->retinex( params.icm, params.retinex, params.toneCurve, cdcurve, dehatransmissionCurve, conversionBuffer, dehacontlutili, useHsl, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, dummy); + imgsrc->retinex( params.icm, params.retinex, params.toneCurve, mapcurve, dehatransmissionCurve, conversionBuffer, dehacontlutili, mapcontlutili, useHsl, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, dummy); } if (pl) { diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 2efed572e..5178f3b8a 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -50,9 +50,11 @@ void ParamsEdited::set (bool v) toneCurve.hrenabled = v; toneCurve.method = v; retinex.cdcurve = v; + retinex.mapcurve = v; retinex.cdHcurve = v; retinex.lhcurve = v; retinex.retinexMethod = v; + retinex.mapMethod = v; retinex.retinexcolorspace = v; retinex.gammaretinex = v; retinex.enabled = v; @@ -73,6 +75,12 @@ void ParamsEdited::set (bool v) // retinex.grbl = v; retinex.medianmap = v; retinex.transmissionCurve = v; + retinex.highlights = v; + retinex.htonalwidth = v; + retinex.shadows = v; + retinex.stonalwidth = v; + retinex.radius = v; + retinex.retinex = v; labCurve.lcurve = v; labCurve.acurve = v; @@ -530,10 +538,12 @@ void ParamsEdited::initFrom (const std::vector toneCurve.hrenabled = toneCurve.hrenabled && p.toneCurve.hrenabled == other.toneCurve.hrenabled; toneCurve.method = toneCurve.method && p.toneCurve.method == other.toneCurve.method; retinex.cdcurve = retinex.cdcurve && p.retinex.cdcurve == other.retinex.cdcurve; + retinex.mapcurve = retinex.mapcurve && p.retinex.mapcurve == other.retinex.mapcurve; retinex.cdHcurve = retinex.cdHcurve && p.retinex.cdHcurve == other.retinex.cdHcurve; retinex.lhcurve = retinex.lhcurve && p.retinex.lhcurve == other.retinex.lhcurve; retinex.transmissionCurve = retinex.transmissionCurve && p.retinex.transmissionCurve == other.retinex.transmissionCurve; retinex.retinexMethod = retinex.retinexMethod && p.retinex.retinexMethod == other.retinex.retinexMethod; + retinex.mapMethod = retinex.mapMethod && p.retinex.mapMethod == other.retinex.mapMethod; retinex.retinexcolorspace = retinex.retinexcolorspace && p.retinex.retinexcolorspace == other.retinex.retinexcolorspace; retinex.gammaretinex = retinex.gammaretinex && p.retinex.gammaretinex == other.retinex.gammaretinex; retinex.str = retinex.str && p.retinex.str == other.retinex.str; @@ -552,6 +562,12 @@ void ParamsEdited::initFrom (const std::vector retinex.baselog = retinex.baselog && p.retinex.baselog == other.retinex.baselog; // retinex.grbl = retinex.grbl && p.retinex.grbl == other.retinex.grbl; retinex.medianmap = retinex.medianmap && p.retinex.medianmap == other.retinex.medianmap; + retinex.highlights = retinex.highlights && p.retinex.highlights == other.retinex.highlights; + retinex.htonalwidth = retinex.htonalwidth && p.retinex.htonalwidth == other.retinex.htonalwidth; + retinex.shadows = retinex.shadows && p.retinex.shadows == other.retinex.shadows; + retinex.stonalwidth = retinex.stonalwidth && p.retinex.stonalwidth == other.retinex.stonalwidth; + retinex.radius = retinex.radius && p.retinex.radius == other.retinex.radius; + retinex.enabled = retinex.enabled && p.retinex.enabled == other.retinex.enabled; labCurve.lcurve = labCurve.lcurve && p.labCurve.lcurve == other.labCurve.lcurve; labCurve.acurve = labCurve.acurve && p.labCurve.acurve == other.labCurve.acurve; @@ -1052,6 +1068,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.retinex.cdcurve = mods.retinex.cdcurve; } + if (retinex.mapcurve) { + toEdit.retinex.mapcurve = mods.retinex.mapcurve; + } + if (retinex.cdHcurve) { toEdit.retinex.cdHcurve = mods.retinex.cdHcurve; } @@ -1068,6 +1088,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.retinex.retinexMethod = mods.retinex.retinexMethod; } + if (retinex.mapMethod) { + toEdit.retinex.mapMethod = mods.retinex.mapMethod; + } + if (retinex.retinexcolorspace) { toEdit.retinex.retinexcolorspace = mods.retinex.retinexcolorspace; } @@ -1144,6 +1168,28 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.retinex.vart = dontforceSet && options.baBehav[ADDSET_RETI_VART] ? toEdit.retinex.vart + mods.retinex.vart : mods.retinex.vart; } + if (retinex.highlights) { + toEdit.retinex.highlights = mods.retinex.highlights; + } + + if (retinex.htonalwidth) { + toEdit.retinex.htonalwidth = mods.retinex.htonalwidth; + } + + if (retinex.shadows) { + toEdit.retinex.shadows = mods.retinex.shadows; + + } + + if (retinex.stonalwidth) { + toEdit.retinex.stonalwidth = mods.retinex.stonalwidth; + } + + if (retinex.radius) { + toEdit.retinex.radius = mods.retinex.radius; + } + + if (labCurve.lcurve) { toEdit.labCurve.lcurve = mods.labCurve.lcurve; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index f174c8d52..ba53ee5ea 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -70,6 +70,7 @@ public: bool gain; bool offs; bool retinexMethod; + bool mapMethod; bool retinexcolorspace; bool gammaretinex; bool vart; @@ -80,11 +81,18 @@ public: bool method; bool transmissionCurve; bool cdcurve; + bool mapcurve; bool cdHcurve; bool lhcurve; bool retinex; bool medianmap; bool isUnchanged() const; + bool highlights; + bool htonalwidth; + bool shadows; + bool stonalwidth; + bool radius; + }; diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index 099ee7310..2ede52af6 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -83,6 +83,17 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), curveEditorGDH->curveListComplete(); + curveEditormap = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_CONTEDIT_MAP")); + curveEditormap->setCurveListener (this); + mapshape = static_cast(curveEditormap->addCurve(CT_Diagonal, M("TP_RETINEX_CURVEEDITOR_MAP"))); + mapshape->setTooltip(M("TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP")); + std::vector milestones222; + milestones222.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones222.push_back( GradientMilestone(1., 1., 1., 1.) ); + mapshape->setBottomBarBgGradient(milestones222); + mapshape->setLeftBarBgGradient(milestones222); + + curveEditormap->curveListComplete(); // Transmission map curve transmissionCurveEditorG = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_TRANSMISSION")); @@ -163,6 +174,28 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), limd->set_tooltip_markup (M("TP_RETINEX_THRESHOLD_TOOLTIP")); baselog->set_tooltip_markup (M("TP_RETINEX_BASELOG_TOOLTIP")); + + mapbox = Gtk::manage (new Gtk::HBox ()); + labmap = Gtk::manage (new Gtk::Label (M("TP_RETINEX_MAP") + ":")); + mapbox->pack_start (*labmap, Gtk::PACK_SHRINK, 1); + + mapMethod = Gtk::manage (new MyComboBoxText ()); + mapMethod->append_text (M("TP_RETINEX_MAP_NONE")); + mapMethod->append_text (M("TP_RETINEX_MAP_CURV")); + mapMethod->append_text (M("TP_RETINEX_MAP_GAUS")); + mapMethod->append_text (M("TP_RETINEX_MAP_MAPP")); + mapMethod->append_text (M("TP_RETINEX_MAP_MAPT")); + mapMethod->set_active(0); + mapMethodConn = mapMethod->signal_changed().connect ( sigc::mem_fun(*this, &Retinex::mapMethodChanged) ); + mapMethod->set_tooltip_markup (M("TP_RETINEX_MAP_METHOD_TOOLTIP")); + + highlights = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), 0, 100, 1, 0)); + h_tonalwidth = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_HLTONALW"), 10, 100, 1, 80)); + shadows = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_SHADOWS"), 0, 100, 1, 0)); + s_tonalwidth = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_SHTONALW"), 10, 100, 1, 80)); + radius = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_RADIUS"), 5, 100, 1, 40)); + + curveEditorGH = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_CONTEDIT_LH")); curveEditorGH->setCurveListener (this); @@ -241,6 +274,24 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), settingsVBox->pack_start (*limd); limd->show (); + settingsVBox->pack_start (*Gtk::manage (new Gtk::HSeparator())); + + mapbox->pack_start(*mapMethod); + settingsVBox->pack_start(*mapbox); + + settingsVBox->pack_start (*curveEditormap, Gtk::PACK_SHRINK, 4); + curveEditormap->show(); + + settingsVBox->pack_start (*highlights); + highlights->show(); + settingsVBox->pack_start (*h_tonalwidth); + h_tonalwidth->show(); + settingsVBox->pack_start (*shadows); + shadows->show(); + settingsVBox->pack_start (*s_tonalwidth); + s_tonalwidth->show(); + settingsVBox->pack_start (*radius); + radius->show(); // settingsVBox->pack_start (*highl); // highl->show (); @@ -249,6 +300,7 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), // settingsVBox->pack_start (*grbl); // grbl->show (); + settingsVBox->pack_start (*Gtk::manage (new Gtk::HSeparator())); settingsVBox->pack_start( *transmissionCurveEditorG, Gtk::PACK_SHRINK, 2); transmissionCurveEditorG->show(); @@ -354,6 +406,32 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), baselog->delay = 200; } + + radius->setAdjusterListener (this); + if (radius->delay < 200) { + radius->delay = 200; + } + + highlights->setAdjusterListener (this); + if (highlights->delay < 200) { + highlights->delay = 200; + } + + h_tonalwidth->setAdjusterListener (this); + if (h_tonalwidth->delay < 200) { + h_tonalwidth->delay = 200; + } + + shadows->setAdjusterListener (this); + if (shadows->delay < 200) { + shadows->delay = 200; + } + + s_tonalwidth->setAdjusterListener (this); + if (s_tonalwidth->delay < 200) { + s_tonalwidth->delay = 200; + } + /* grbl->setAdjusterListener (this); if (grbl->delay < 200) { @@ -378,6 +456,7 @@ Retinex::~Retinex() delete curveEditorGDH; delete transmissionCurveEditorG; delete curveEditorGH; + delete curveEditormap; } void Retinex::neutral_pressed () @@ -396,10 +475,20 @@ void Retinex::neutral_pressed () baselog->resetValue(false); gam->resetValue(false); slope->resetValue(false); + highlights->resetValue(false); + h_tonalwidth->resetValue(false); + shadows->resetValue(false); + s_tonalwidth->resetValue(false); + radius->resetValue(false); + mapMethod->set_active(0); + retinexMethod->set_active(2); + retinexcolorspace->set_active(0); + gammaretinex->set_active(0); transmissionShape->reset(); cdshape->reset(); cdshapeH->reset(); lhshape->reset(); + mapshape->reset(); } void Retinex::foldAllButMe (GdkEventButton* event, MyExpander *expander) @@ -509,6 +598,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) retinexMethodConn.block(true); retinexColorSpaceConn.block(true); gammaretinexConn.block(true); + mapMethodConn.block(true); if (pedited) { @@ -528,12 +618,21 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) // grbl->setEditedState (pedited->retinex.grbl ? Edited : UnEdited); set_inconsistent (multiImage && !pedited->retinex.enabled); medianmap->set_inconsistent (!pedited->retinex.medianmap); + radius->setEditedState (pedited->retinex.radius ? Edited : UnEdited); + highlights->setEditedState (pedited->retinex.highlights ? Edited : UnEdited); + h_tonalwidth->setEditedState (pedited->retinex.htonalwidth ? Edited : UnEdited); + shadows->setEditedState (pedited->retinex.shadows ? Edited : UnEdited); + s_tonalwidth->setEditedState (pedited->retinex.stonalwidth ? Edited : UnEdited); if (!pedited->retinex.retinexMethod) { retinexMethod->set_active_text(M("GENERAL_UNCHANGED")); } + if (!pedited->retinex.mapMethod) { + mapMethod->set_active_text(M("GENERAL_UNCHANGED")); + } + if (!pedited->retinex.retinexcolorspace) { retinexcolorspace->set_active_text(M("GENERAL_UNCHANGED")); } @@ -546,6 +645,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) cdshapeH->setUnChanged (!pedited->retinex.cdHcurve); transmissionShape->setUnChanged (!pedited->retinex.transmissionCurve); lhshape->setUnChanged (!pedited->retinex.lhcurve); + mapshape->setUnChanged (!pedited->retinex.mapcurve); } @@ -563,6 +663,13 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) slope->setValue (pp->retinex.slope); highl->setValue (pp->retinex.highl); baselog->setValue (pp->retinex.baselog); + + radius->setValue (pp->retinex.radius); + highlights->setValue (pp->retinex.highlights); + h_tonalwidth->setValue (pp->retinex.htonalwidth); + shadows->setValue (pp->retinex.shadows); + s_tonalwidth->setValue (pp->retinex.stonalwidth); + // grbl->setValue (pp->retinex.grbl); if(pp->retinex.iter == 1) { grad->set_sensitive(false); @@ -593,6 +700,19 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) // retinexMethod->set_active (4); } + if (pp->retinex.mapMethod == "none") { + mapMethod->set_active (0); + } else if (pp->retinex.mapMethod == "curv") { + mapMethod->set_active (1); + } else if (pp->retinex.mapMethod == "gaus") { + mapMethod->set_active (2); + } else if (pp->retinex.mapMethod == "map") { + mapMethod->set_active (3); + } else if (pp->retinex.mapMethod == "mapT") { + mapMethod->set_active (4); + } + + if (pp->retinex.retinexcolorspace == "Lab") { retinexcolorspace->set_active (0); } else if (pp->retinex.retinexcolorspace == "HSLLOG") { @@ -616,6 +736,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) retinexMethodChanged (); retinexColorSpaceChanged(); gammaretinexChanged(); + mapMethodChanged (); medianmapConn.block(true); medianmapChanged (); @@ -624,10 +745,12 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) cdshape->setCurve (pp->retinex.cdcurve); cdshapeH->setCurve (pp->retinex.cdHcurve); lhshape->setCurve (pp->retinex.lhcurve); + mapshape->setCurve (pp->retinex.mapcurve); retinexMethodConn.block(false); retinexColorSpaceConn.block(false); gammaretinexConn.block(false); + mapMethodConn.block(false); transmissionShape->setCurve (pp->retinex.transmissionCurve); @@ -657,14 +780,22 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) pp->retinex.cdcurve = cdshape->getCurve (); pp->retinex.lhcurve = lhshape->getCurve (); pp->retinex.cdHcurve = cdshapeH->getCurve (); + pp->retinex.mapcurve = mapshape->getCurve (); pp->retinex.transmissionCurve = transmissionShape->getCurve (); pp->retinex.enabled = getEnabled(); pp->retinex.medianmap = medianmap->get_active(); + pp->retinex.radius = (int)radius->getValue (); + pp->retinex.highlights = (int)highlights->getValue (); + pp->retinex.htonalwidth = (int)h_tonalwidth->getValue (); + pp->retinex.shadows = (int)shadows->getValue (); + pp->retinex.stonalwidth = (int)s_tonalwidth->getValue (); + if (pedited) { pedited->retinex.retinexMethod = retinexMethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->retinex.retinexcolorspace = retinexcolorspace->get_active_text() != M("GENERAL_UNCHANGED"); pedited->retinex.gammaretinex = gammaretinex->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->retinex.mapMethod = mapMethod->get_active_text() != M("GENERAL_UNCHANGED"); //%%%%%%%%%%%%%%%%%%%%%% pedited->retinex.str = str->getEditedState (); @@ -685,10 +816,17 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) pedited->retinex.cdcurve = !cdshape->isUnChanged (); pedited->retinex.cdHcurve = !cdshapeH->isUnChanged (); pedited->retinex.transmissionCurve = !transmissionShape->isUnChanged (); + pedited->retinex.mapcurve = !mapshape->isUnChanged (); pedited->retinex.enabled = !get_inconsistent(); pedited->retinex.medianmap = !medianmap->get_inconsistent(); pedited->retinex.lhcurve = !lhshape->isUnChanged (); + pedited->retinex.radius = radius->getEditedState (); + pedited->retinex.highlights = highlights->getEditedState (); + pedited->retinex.htonalwidth = h_tonalwidth->getEditedState (); + pedited->retinex.shadows = shadows->getEditedState (); + pedited->retinex.stonalwidth = s_tonalwidth->getEditedState (); + } if (retinexMethod->get_active_row_number() == 0) { @@ -703,6 +841,18 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) // pp->retinex.retinexMethod = "highliplus"; } + if (mapMethod->get_active_row_number() == 0) { + pp->retinex.mapMethod = "none"; + } else if (mapMethod->get_active_row_number() == 1) { + pp->retinex.mapMethod = "curv"; + } else if (mapMethod->get_active_row_number() == 2) { + pp->retinex.mapMethod = "gaus"; + } else if (mapMethod->get_active_row_number() == 3) { + pp->retinex.mapMethod = "map"; + } else if (mapMethod->get_active_row_number() == 4) { + pp->retinex.mapMethod = "mapT"; + } + if (retinexcolorspace->get_active_row_number() == 0) { pp->retinex.retinexcolorspace = "Lab"; } else if (retinexcolorspace->get_active_row_number() == 1) { @@ -739,6 +889,40 @@ void Retinex::retinexMethodChanged() } } + + +void Retinex::mapMethodChanged() +{ + + if(mapMethod->get_active_row_number() >= 1) { + curveEditormap->show(); + highlights->show(); + h_tonalwidth->show(); + shadows->show(); + s_tonalwidth->show(); + radius->show(); + /* } else if(mapMethod->get_active_row_number() == 1) { + curveEditormap->show(); + highlights->hide(); + h_tonalwidth->hide(); + shadows->hide(); + s_tonalwidth->hide(); + radius->hide();*/ + } else { + curveEditormap->hide(); + highlights->hide(); + h_tonalwidth->hide(); + shadows->hide(); + s_tonalwidth->hide(); + radius->hide(); + + } + + if (listener) { + listener->panelChanged (EvmapMethod, mapMethod->get_active_text ()); + } +} + void Retinex::ColorSpaceUpdateUI () { if (!batchMode) { @@ -838,6 +1022,12 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi gam->setDefault (defParams->retinex.gam); slope->setDefault (defParams->retinex.slope); + radius->setDefault (defParams->retinex.radius); + highlights->setDefault (defParams->retinex.highlights); + h_tonalwidth->setDefault (defParams->retinex.htonalwidth); + shadows->setDefault (defParams->retinex.shadows); + s_tonalwidth->setDefault (defParams->retinex.stonalwidth); + if (pedited) { neigh->setDefaultEditedState (pedited->retinex.neigh ? Edited : UnEdited); gain->setDefaultEditedState (pedited->retinex.gain ? Edited : UnEdited); @@ -855,6 +1045,12 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi gam->setDefaultEditedState (pedited->retinex.gam ? Edited : UnEdited); slope->setDefaultEditedState (pedited->retinex.slope ? Edited : UnEdited); + radius->setDefaultEditedState (pedited->retinex.radius ? Edited : UnEdited); + highlights->setDefaultEditedState (pedited->retinex.highlights ? Edited : UnEdited); + h_tonalwidth->setDefaultEditedState (pedited->retinex.htonalwidth ? Edited : UnEdited); + shadows->setDefaultEditedState (pedited->retinex.shadows ? Edited : UnEdited); + s_tonalwidth->setDefaultEditedState (pedited->retinex.stonalwidth ? Edited : UnEdited); + } else { neigh->setDefaultEditedState (Irrelevant); gain->setDefaultEditedState (Irrelevant); @@ -871,6 +1067,13 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi grads->setDefaultEditedState (Irrelevant); gam->setDefaultEditedState (Irrelevant); slope->setDefaultEditedState (Irrelevant); + + radius->setDefaultEditedState (Irrelevant); + highlights->setDefaultEditedState (Irrelevant); + h_tonalwidth->setDefaultEditedState (Irrelevant); + shadows->setDefaultEditedState (Irrelevant); + s_tonalwidth->setDefaultEditedState (Irrelevant); + } } @@ -935,8 +1138,20 @@ void Retinex::adjusterChanged (Adjuster* a, double newval) listener->panelChanged (EvLgam, gam->getTextValue()); } else if (a == slope) { listener->panelChanged (EvLslope, slope->getTextValue()); + } else if (a == highlights) { + listener->panelChanged (EvLhighlights, highlights->getTextValue()); + } else if (a == h_tonalwidth) { + listener->panelChanged (EvLh_tonalwidth, h_tonalwidth->getTextValue()); + } else if (a == shadows) { + listener->panelChanged (EvLshadows, shadows->getTextValue()); + } else if (a == s_tonalwidth) { + listener->panelChanged (EvLs_tonalwidth, s_tonalwidth->getTextValue()); + } else if (a == radius) { + listener->panelChanged (EvLradius, radius->getTextValue()); + } + } @@ -947,6 +1162,7 @@ void Retinex::autoOpenCurve () cdshapeH->openIfNonlinear(); transmissionShape->openIfNonlinear(); lhshape->openIfNonlinear(); + mapshape->openIfNonlinear(); } @@ -962,6 +1178,8 @@ void Retinex::curveChanged (CurveEditor* ce) listener->panelChanged (EvRetinextransmission, M("HISTORY_CUSTOMCURVE")); } else if (ce == lhshape) { listener->panelChanged (EvRetinexlhcurve, M("HISTORY_CUSTOMCURVE")); + } else if (ce == mapshape) { + listener->panelChanged (EvRetinexmapcurve, M("HISTORY_CUSTOMCURVE")); } } } @@ -998,6 +1216,8 @@ void Retinex::trimValues (rtengine::procparams::ProcParams* pp) // grbl->trimValue(pp->retinex.grbl); gam->trimValue(pp->retinex.gam); slope->trimValue(pp->retinex.slope); + highlights->trimValue(pp->retinex.highlights); + shadows->trimValue(pp->retinex.shadows); } void Retinex::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histLRETI) @@ -1070,11 +1290,19 @@ void Retinex::setBatchMode (bool batchMode) limd->showEditedCB (); highl->showEditedCB (); baselog->showEditedCB (); + + radius->showEditedCB (); + highlights->showEditedCB (); + h_tonalwidth->showEditedCB (); + shadows->showEditedCB (); + s_tonalwidth->showEditedCB (); + // grbl->showEditedCB (); curveEditorGD->setBatchMode (batchMode); curveEditorGDH->setBatchMode (batchMode); transmissionCurveEditorG->setBatchMode (batchMode); curveEditorGH->setBatchMode (batchMode); + curveEditormap->setBatchMode (batchMode); } diff --git a/rtgui/retinex.h b/rtgui/retinex.h index e014bed5d..ac55fea99 100644 --- a/rtgui/retinex.h +++ b/rtgui/retinex.h @@ -22,6 +22,7 @@ protected: CurveEditorGroup* curveEditorGD; CurveEditorGroup* curveEditorGDH; CurveEditorGroup* curveEditorGH; + CurveEditorGroup* curveEditormap; Adjuster* str; Adjuster* scal; Adjuster* grad; @@ -37,10 +38,19 @@ protected: Adjuster* grbl; Adjuster* gam; Adjuster* slope; + Adjuster* highlights; + Adjuster* h_tonalwidth; + Adjuster* shadows; + Adjuster* s_tonalwidth; + Adjuster* radius; + MyExpander* expsettings; Gtk::Label* labmdh; Gtk::HBox* dhbox; + Gtk::HBox* mapbox; + Gtk::Label* labmap; + Gtk::Label* labgam; Gtk::HBox* gambox; Gtk::Button* neutral; @@ -49,6 +59,7 @@ protected: MyComboBoxText* retinexMethod; MyComboBoxText* retinexcolorspace; MyComboBoxText* gammaretinex; + MyComboBoxText* mapMethod; Gtk::CheckButton* medianmap; double nextmin; double nextmax; @@ -65,8 +76,9 @@ protected: DiagonalCurveEditor* cdshape; DiagonalCurveEditor* cdshapeH; + DiagonalCurveEditor* mapshape; CurveEditorGroup* transmissionCurveEditorG; - sigc::connection retinexMethodConn, neutralconn; + sigc::connection retinexMethodConn, neutralconn, mapMethodConn; sigc::connection retinexColorSpaceConn; sigc::connection gammaretinexConn; FlatCurveEditor* transmissionShape; @@ -95,6 +107,7 @@ public: void enabledChanged (); void curveChanged (CurveEditor* ce); void retinexMethodChanged(); + void mapMethodChanged(); void retinexColorSpaceChanged(); void gammaretinexChanged(); void ColorSpaceUpdateUI();