diff --git a/rtdata/languages/default b/rtdata/languages/default index a6227a841..c361da52f 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -638,11 +638,11 @@ HISTORY_MSG_404;W - ES - Base amplification HISTORY_MSG_405;W - Denoise - Level 4 HISTORY_MSG_406;W - ES - Neighboring pixels HISTORY_MSG_407;Retinex - Method -HISTORY_MSG_408;Retinex - Neighboring -HISTORY_MSG_409;Retinex - Gain -HISTORY_MSG_410;Retinex - Offset +HISTORY_MSG_408;Retinex - Radius +HISTORY_MSG_409;Retinex - Contrast +HISTORY_MSG_410;Retinex - Brightness HISTORY_MSG_411;Retinex - Strength -HISTORY_MSG_412;Retinex - Scales +HISTORY_MSG_412;Retinex - G. Gradient HISTORY_MSG_413;Retinex - Variance HISTORY_MSG_414;Retinex - Histogram - Lab HISTORY_MSG_415;Retinex - Transmission @@ -658,6 +658,17 @@ HISTORY_MSG_424;Retinex - HL threshold HISTORY_MSG_425;Retinex - Log base HISTORY_MSG_426;Retinex - Hue equalizer HISTORY_MSG_427;Output rendering intent +HISTORY_MSG_428;Retinex - Iterations +HISTORY_MSG_429;Retinex - T. Gradient +HISTORY_MSG_430;Retinex - S. Gradient +HISTORY_MSG_431;Retinex - Mask highlights +HISTORY_MSG_432;Retinex - Mask TW highlights +HISTORY_MSG_433;Retinex - Mask shadows +HISTORY_MSG_434;Retinex - Mask TW shadows +HISTORY_MSG_435;Retinex - Mask radius +HISTORY_MSG_436;Retinex - Mask method +HISTORY_MSG_437;Retinex - Mask curve +HISTORY_MSG_438;Retinex - Preview HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -1644,6 +1655,9 @@ TP_RESIZE_WIDTH;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) @@ -1664,19 +1678,34 @@ TP_RETINEX_HIGHLIGHT;Highlight threshold TP_RETINEX_HIGHLIGHT_TOOLTIP;Increase action of High algorithm.\nMay require you to re-adjust "Neighboring pixels" and to increase the "White-point correction" in the Raw tab -> Raw White Points tool. TP_RETINEX_HSLSPACE_LIN;HSL-Linear TP_RETINEX_HSLSPACE_LOG;HSL-Logarithmic +TP_RETINEX_ITER;Iterations (Tone-mapping) +TP_RETINEX_ITER_TOOLTIP;Simulate a tone-mapping operator\nHigh values increase the processing time +TP_RETINEX_GRAD;Transmission gradient +TP_RETINEX_GRAD_TOOLTIP;If slider at 0, all iterations are identical\nIf > 0 Variance and Threshold are reduce when iteration increases and conversely +TP_RETINEX_GRADS;Strength gradient +TP_RETINEX_GRADS_TOOLTIP;If slider at 0, all iterations are identical\nIf > 0 Strength is reduce when iteration increases and conversely 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. TP_RETINEX_MLABEL;Restored haze-free Min=%1 Max=%2 TP_RETINEX_MLABEL_TOOLTIP;Should be near min=0 max=32768\nRestored image with no mixture. -TP_RETINEX_NEIGHBOR;Neighboring pixels +TP_RETINEX_NEIGHBOR;Radius TP_RETINEX_NEUTRAL;Reset TP_RETINEX_NEUTRAL_TIP;Reset all sliders and curves to their default values. -TP_RETINEX_OFFSET;Offset +TP_RETINEX_OFFSET;Brightness TP_RETINEX_SETTINGS;Settings +TP_RETINEX_SCALES;Gaussian gradient +TP_RETINEX_SCALES_TOOLTIP;If slider at 0, all iterations are identical\nIf > 0 Scale and Neighboring pixels are reduce when iteration increases and conversely TP_RETINEX_SLOPE;Free gamma slope TP_RETINEX_STRENGTH;Strength TP_RETINEX_THRESHOLD;Threshold @@ -1687,8 +1716,15 @@ TP_RETINEX_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Vari TP_RETINEX_TRANSMISSION;Transmission map TP_RETINEX_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscissa: transmission from negative values (min), mean, and positives values (max).\nOrdinate: amplification or reduction. TP_RETINEX_UNIFORM;Uniform -TP_RETINEX_VARIANCE;Variance +TP_RETINEX_VARIANCE;Contrast TP_RETINEX_VARIANCE_TOOLTIP;Low variance increase local contrast and saturation, but can lead to artifacts. +TP_RETINEX_VIEW;Process (Preview) +TP_RETINEX_VIEW_NONE;Standard +TP_RETINEX_VIEW_MASK;Mask +TP_RETINEX_VIEW_UNSHARP;Unsharp mask +TP_RETINEX_VIEW_TRAN;Transmission (auto) +TP_RETINEX_VIEW_TRAN2;Transmission (fixed) +TP_RETINEX_VIEW_METHOD_TOOLTIP;Standard - normal display\nMask - display mask\nUnsharp mask - display image with high radius unsharp mask\nTransmission (auto - fixed) - displays the file transmission-map , before any action on contrast and brightness\nAttention, this does not correspond to reality, but a shift (or auto) to make it visible TP_RGBCURVES_BLUE;B TP_RGBCURVES_CHANNEL;Channel TP_RGBCURVES_GREEN;G 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..80fc53f23 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, LUTf & mapcurve, 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 96a55989e..d12027c6d 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, cdcurve, 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); @@ -780,6 +782,10 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } } + // Update the monitor color transform if necessary + if (todo & M_MONITOR) { + ipf.updateColorProfiles(params.icm, monitorProfile, monitorIntent); + } // Update the monitor color transform if necessary if (todo & M_MONITOR) { diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc index 54d5d3515..b24cc9bb3 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; @@ -217,10 +218,13 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e float gain2 = (float) deh.gain / 100.f; //def =1 not use gain2 = useHslLin ? gain2 * 0.5f : gain2; float offse = (float) deh.offs; //def = 0 not use - int scal = deh.scal; //def=3 - scal = 3;//disabled scal + int iter = deh.iter; + int gradient = deh.scal; + int scal = 3;//disabled scal int nei = (int) 2.8f * deh.neigh; //def = 220 float vart = (float)deh.vart / 100.f;//variance + float gradvart = (float)deh.grad; + float gradstr = (float)deh.grads; float strength = (float) deh.str / 100.f; // Blend with original L channel data float limD = (float) deh.limd; limD = pow(limD, 1.7f);//about 2500 enough @@ -231,12 +235,18 @@ 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 { elogt = hl; } + int H_L = height; + int W_L = width; + + float *tran[H_L] ALIGNED16; + float *tranBuffer; + int viewmet=0; elogt = 2.71828f;//disabled baselog FlatCurve* shcurve = NULL;//curve L=f(H) @@ -271,281 +281,501 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e if (deh.retinexMethod == "highli" || deh.retinexMethod == "highliplus") { moderetinex = 3; } + for(int it=1; it= 0; scale-- ) { - if(scale == scal - 1) { - gaussianBlur (src, out, W_L, H_L, RetinexScales[scale], buffer); - } else { // reuse result of last iteration - gaussianBlur (out, out, W_L, H_L, sqrtf(SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), buffer); + + for (int i = 0; i < H_L; i++) + for (int j = 0; j < W_L; j++) { + src[i][j] = luminance[i][j] + eps; + luminance[i][j] = 0.f; } -#ifdef __SSE2__ - vfloat pondv = F2V(pond); - vfloat limMinv = F2V(ilimD); - vfloat limMaxv = F2V(limD); + float *out[H_L] ALIGNED16; + float *outBuffer = new float[H_L * W_L]; -#endif -#ifdef _OPENMP - #pragma omp for -#endif + for (int i = 0; i < H_L; i++) { + out[i] = &outBuffer[i * W_L]; + } + + if(viewmet==3 || viewmet==2) { + tranBuffer = new float[H_L * W_L]; for (int i = 0; i < H_L; i++) { - int j = 0; - -#ifdef __SSE2__ - - if(useHslLin) { - for (; j < W_L - 3; j += 4) { - _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * (LIMV(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv) )); - } - } else { - for (; j < W_L - 3; j += 4) { - _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(LIMV(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv) )); - } - } - -#endif - - if(useHslLin) { - for (; j < W_L; j++) { - luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimD, limD)); - } - } else { - for (; j < W_L; j++) { - luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimD, limD)); // /logt ? - } - } + tran[i] = &tranBuffer[i * W_L]; } } - } - delete [] buffer; - delete [] outBuffer; - delete [] srcBuffer; + const float logBetaGain = xlogf(16384.f); + float pond = logBetaGain / (float) scal; - mean = 0.f; - stddv = 0.f; - // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + if(!useHslLin) { + pond /= log(elogt); + } - mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr); -// printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr); + if(mapmet > 1) shmap = new SHMap (W_L, H_L, true); - // mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr); - if (dehatransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve - float asig = 0.166666f / stddv; - float bsig = 0.5f - asig * mean; - float amax = 0.333333f / (maxtr - mean - stddv); - float bmax = 1.f - amax * maxtr; - float amin = 0.333333f / (mean - stddv - mintr); - float bmin = -amin * mintr; - asig *= 500.f; - bsig *= 500.f; - amax *= 500.f; - bmax *= 500.f; - amin *= 500.f; - bmin *= 500.f; + + float *buffer = new float[W_L * H_L];; #ifdef _OPENMP #pragma omp parallel #endif { - float absciss; -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) + for ( int scale = scal - 1; scale >= 0; scale-- ) { + if(scale == scal - 1) { + gaussianBlur (src, out, W_L, H_L, RetinexScales[scale], buffer); + } else { + // 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(".."); + + + if(mapmet==4) shradius /= 1.; + else shradius = 40.; + + // 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); + vfloat limMinv = F2V(ilimdx); + vfloat limMaxv = F2V(limdx); + #endif - for (int i = 0; i < H_L; i++ ) - for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission - if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) { - absciss = asig * luminance[i][j] + bsig; - } else if (luminance[i][j] >= mean) { - absciss = amax * luminance[i][j] + bmax; - } else { /*if(luminance[i][j] <= mean - stddv)*/ - absciss = amin * luminance[i][j] + bmin; + 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; + } + } } - luminance[i][j] *= (-1.f + 4.f * dehatransmissionCurve[absciss]); //new transmission } - } - // median filter on transmission ==> reduce artifacts - if (deh.medianmap) { - int wid = W_L; - int hei = H_L; - float *tmL[hei] ALIGNED16; - float *tmLBuffer = new float[wid * hei]; - int borderL = 1; + // if(shHighlights > 0 || shShadows > 0) { + if(((mapmet == 2 && scale >2) || mapmet==3 || mapmet==4) && it==1) { - for (int i = 0; i < hei; i++) { - tmL[i] = &tmLBuffer[i * wid]; - } #ifdef _OPENMP - #pragma omp parallel for + #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; - for (int i = borderL; i < hei - borderL; i++) { - float pp[9], temp; + 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; - for (int j = borderL; j < wid - borderL; j++) { - med3(luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1], tmL[i][j]); //3x3 + } + } } - } + // } #ifdef _OPENMP - #pragma omp parallel for + #pragma omp for #endif - for (int i = borderL; i < hei - borderL; i++ ) { - for (int j = borderL; j < wid - borderL; j++) { - luminance[i][j] = tmL[i][j]; + for (int i = 0; i < H_L; i++) { + int j = 0; + +#ifdef __SSE2__ + + if(useHslLin) { + for (; j < W_L - 3; j += 4) { + _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * (LIMV(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv) )); + } + } else { + for (; j < W_L - 3; j += 4) { + _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(LIMV(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv) )); + } + } + +#endif + + if(useHslLin) { + for (; j < W_L; j++) { + luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimdx, limdx)); + } + } else { + for (; j < W_L; j++) { + luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimdx, limdx)); // /logt ? + } + } } } - - delete [] tmLBuffer; - } + printf(".\n"); + if(mapmet > 1) { + if(shmap) { + delete shmap; + } + } + shmap = NULL; + delete [] buffer; +// delete [] outBuffer; + delete [] srcBuffer; + + mean = 0.f; + stddv = 0.f; // I call mean_stddv2 instead of mean_stddv ==> logBetaGain - // mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr); + mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr); +// printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr); - } - - float epsil = 0.1f; - - mini = mean - vart * stddv; - - if (mini < mintr) { - mini = mintr + epsil; - } - - maxi = mean + vart * stddv; - - if (maxi > maxtr) { - maxi = maxtr - epsil; - } - - delta = maxi - mini; - // printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr); - - if ( !delta ) { - delta = 1.0f; - } - - float cdfactor = gain2 * 32768.f / delta; - maxCD = -9999999.f; - minCD = 9999999.f; - - - + // mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr); + if (dehatransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve + float asig = 0.166666f / stddv; + float bsig = 0.5f - asig * mean; + float amax = 0.333333f / (maxtr - mean - stddv); + float bmax = 1.f - amax * maxtr; + float amin = 0.333333f / (mean - stddv - mintr); + float bmin = -amin * mintr; + asig *= 500.f; + bsig *= 500.f; + amax *= 500.f; + bmax *= 500.f; + amin *= 500.f; + bmin *= 500.f; #ifdef _OPENMP - #pragma omp parallel + #pragma omp parallel #endif - { - float cdmax = -999999.f, cdmin = 999999.f; - + { + float absciss; #ifdef _OPENMP - #pragma omp for + #pragma omp for schedule(dynamic,16) #endif - for ( int i = 0; i < H_L; i ++ ) - for (int j = 0; j < W_L; j++) { - // float cd = cdfactor * ( luminance[i][j] * logBetaGain - mini ) + offse; - float cd = cdfactor * ( luminance[i][j] - mini ) + offse; - - if(cd > cdmax) { - cdmax = cd; - } - - if(cd < cdmin) { - cdmin = cd; - } - - float str = strength; - - if(lhutili) { // S=f(H) - { - float HH = exLuminance[i][j]; - float valparam; - - if(useHsl || useHslLin) { - valparam = float((shcurve->getVal(HH) - 0.5f)); - } else { - valparam = float((shcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f)); + for (int i = 0; i < H_L; i++ ) + for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission + if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) { + absciss = asig * luminance[i][j] + bsig; + } else if (luminance[i][j] >= mean) { + absciss = amax * luminance[i][j] + bmax; + } else { /*if(luminance[i][j] <= mean - stddv)*/ + absciss = amin * luminance[i][j] + bmin; } - str *= (1.f + 2.f * valparam); + luminance[i][j] *= (-1.f + 4.f * dehatransmissionCurve[absciss]); //new transmission + if(viewmet==3 || viewmet==2) tran[i][j]=luminance[i][j]; + } + } + + // median filter on transmission ==> reduce artifacts + if (deh.medianmap && it==1) {//only one time + int wid = W_L; + int hei = H_L; + float *tmL[hei] ALIGNED16; + float *tmLBuffer = new float[wid * hei]; + int borderL = 1; + + for (int i = 0; i < hei; i++) { + tmL[i] = &tmLBuffer[i * wid]; + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = borderL; i < hei - borderL; i++) { + float pp[9], temp; + + for (int j = borderL; j < wid - borderL; j++) { + med3(luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1], tmL[i][j]); //3x3 } } - // if(exLuminance[i][j] > 65535.f*hig && higplus) str *= hig; - luminance[i][j] = clipretinex( cd, 0.f, 32768.f ) * str + (1.f - str) * originalLuminance[i][j]; +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = borderL; i < hei - borderL; i++ ) { + for (int j = borderL; j < wid - borderL; j++) { + luminance[i][j] = tmL[i][j]; + } + } + + delete [] tmLBuffer; + } -#ifdef _OPENMP - #pragma omp critical -#endif - { - maxCD = maxCD > cdmax ? maxCD : cdmax; - minCD = minCD < cdmin ? minCD : cdmin; + // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + // mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr); + mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr); + } - } - // printf("cdmin=%f cdmax=%f\n",minCD, maxCD); - Tmean = mean; - Tsigma = stddv; - Tmin = mintr; - Tmax = maxtr; + float epsil = 0.1f; - if (shcurve) { - delete shcurve; + mini = mean - varx * stddv; + + if (mini < mintr) { + mini = mintr + epsil; + } + + maxi = mean + varx * stddv; + + if (maxi > maxtr) { + maxi = maxtr - epsil; + } + + delta = maxi - mini; + // printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr); + + if ( !delta ) { + delta = 1.0f; + } + + float cdfactor = gain2 * 32768.f / delta; + maxCD = -9999999.f; + minCD = 9999999.f; + // coeff for auto "transmission" with 2 sigma #95% datas + float aza=16300.f/(2.f*stddv); + float azb=-aza*(mean-2.f*stddv); + float bza=16300.f/(2.f*stddv); + float bzb=16300.f-bza*(mean); + + + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + float cdmax = -999999.f, cdmin = 999999.f; + +#ifdef _OPENMP + #pragma omp for +#endif + + for ( int i = 0; i < H_L; i ++ ) + for (int j = 0; j < W_L; j++) { + // float cd = cdfactor * ( luminance[i][j] * logBetaGain - mini ) + offse; + float cd = cdfactor * ( luminance[i][j] - mini ) + offse; + + if(cd > cdmax) { + cdmax = cd; + } + + if(cd < cdmin) { + cdmin = cd; + } + + float str = strengthx; + + if(lhutili && it==1) { // S=f(H) + { + float HH = exLuminance[i][j]; + float valparam; + + if(useHsl || useHslLin) { + valparam = float((shcurve->getVal(HH) - 0.5f)); + } else { + valparam = float((shcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f)); + } + + str *= (1.f + 2.f * valparam); + } + } + + if(exLuminance[i][j] > 65535.f*hig && higplus) str *= hig; + if(viewmet==0) luminance[i][j]=clipretinex( cd, 0.f, 32768.f ) * str + (1.f - str) * originalLuminance[i][j]; + if(viewmet==1) luminance[i][j] = out[i][j]; + if(viewmet==4) luminance[i][j] = (1.f + str) * originalLuminance[i][j] - str* out[i][j];//unsharp + if(viewmet==2) { + if(tran[i][j]<= mean) luminance[i][j] = azb + aza*tran[i][j];//auto values + else luminance[i][j] = bzb + bza*tran[i][j]; + } + if(viewmet==3) luminance[i][j] = 1000.f + tran[i][j]*700.f;//arbitrary values to help display log values which are between -20 to + 30 - usage values -4 + 5 + + } + +#ifdef _OPENMP + #pragma omp critical +#endif + { + maxCD = maxCD > cdmax ? maxCD : cdmax; + minCD = minCD < cdmin ? minCD : cdmin; + } + + } + delete [] outBuffer; + outBuffer = NULL; + // printf("cdmin=%f cdmax=%f\n",minCD, maxCD); + Tmean = mean; + Tsigma = stddv; + Tmin = mintr; + Tmax = maxtr; + + + if (shcurve && it==1) { + delete shcurve; + } + } + if(viewmet==3 || viewmet==2) { + delete [] tranBuffer; + tranBuffer = NULL; } } diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 21ecf5a83..be95686be 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -456,6 +456,17 @@ enum ProcEvent { EvRetinexlhcurve = 425, EvOIntent = 426, EvMonitorTransform = 427, + EvLiter = 428, + EvLgrad = 429, + EvLgrads = 430, + EvLhighlights = 431, + EvLh_tonalwidth = 432, + EvLshadows = 433, + EvLs_tonalwidth = 434, + EvLradius = 435, + EvmapMethod = 436, + EvRetinexmapcurve = 437, + EvviewMethod = 438, NUMOFEVENTS }; } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 613334469..90eafe375 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -142,6 +142,9 @@ void RetinexParams::setDefaults() enabled = false; str = 20; scal = 3; + iter = 1; + grad = 1; + grads = 1; gam = 1.30; slope = 3.; neigh = 80; @@ -150,9 +153,17 @@ 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"; + viewMethod = "none"; retinexcolorspace = "Lab"; gammaretinex = "none"; medianmap = false; @@ -162,6 +173,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); } @@ -1445,6 +1458,18 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_integer ("Retinex", "Scal", retinex.scal); } + if (!pedited || pedited->retinex.iter) { + keyFile.set_integer ("Retinex", "Iter", retinex.iter); + } + + if (!pedited || pedited->retinex.grad) { + keyFile.set_integer ("Retinex", "Grad", retinex.grad); + } + + if (!pedited || pedited->retinex.grads) { + keyFile.set_integer ("Retinex", "Grads", retinex.grads); + } + if (!pedited || pedited->retinex.gam) { keyFile.set_double ("Retinex", "Gam", retinex.gam); } @@ -1499,6 +1524,14 @@ 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.viewMethod) { + keyFile.set_string ("Retinex", "viewMethod", retinex.viewMethod); + } + if (!pedited || pedited->retinex.retinexcolorspace) { keyFile.set_string ("Retinex", "Retinexcolorspace", retinex.retinexcolorspace); } @@ -1512,6 +1545,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); @@ -1522,6 +1560,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); @@ -3825,6 +3883,23 @@ 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", "viewMethod")) { + retinex.viewMethod = keyFile.get_string ("Retinex", "viewMethod"); + + if (pedited) { + pedited->retinex.viewMethod = true; + } + } + + if (keyFile.has_key ("Retinex", "Retinexcolorspace")) { retinex.retinexcolorspace = keyFile.get_string ("Retinex", "Retinexcolorspace"); @@ -3873,6 +3948,30 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + if (keyFile.has_key ("Retinex", "Iter")) { + retinex.iter = keyFile.get_integer ("Retinex", "Iter"); + + if (pedited) { + pedited->retinex.iter = true; + } + } + + if (keyFile.has_key ("Retinex", "Grad")) { + retinex.grad = keyFile.get_integer ("Retinex", "Grad"); + + if (pedited) { + pedited->retinex.grad = true; + } + } + + if (keyFile.has_key ("Retinex", "Grads")) { + retinex.grads = keyFile.get_integer ("Retinex", "Grads"); + + if (pedited) { + pedited->retinex.grads = true; + } + } + if (keyFile.has_key ("Retinex", "Gam")) { retinex.gam = keyFile.get_double ("Retinex", "Gam"); @@ -3953,6 +4052,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"); @@ -3969,6 +4076,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,21 +7505,33 @@ 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 && retinex.str == other.retinex.str && retinex.scal == other.retinex.scal + && retinex.iter == other.retinex.iter + && retinex.grad == other.retinex.grad + && retinex.grads == other.retinex.grads && retinex.gam == other.retinex.gam && retinex.slope == other.retinex.slope && retinex.neigh == other.retinex.neigh && 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.viewMethod == other.retinex.viewMethod && 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 1103d274d..47b8f1cf1 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -282,16 +282,28 @@ public: std::vector cdHcurve; std::vector lhcurve; std::vector transmissionCurve; + std::vector mapcurve; int str; int scal; + int iter; + int grad; + int grads; double gam; double slope; 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; + Glib::ustring viewMethod; int vart; int limd; int highl; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 02e851414..aadc011dd 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, LUTf & mapcurve, 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], mapcurve, 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..10057d58a 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, LUTf & mapcurve, 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 f31300a64..607aa1226 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -440,22 +440,32 @@ int refreshmap[rtengine::NUMOFEVENTS] = { RETINEX, // EvLstr RETINEX, // EvLscal RETINEX, // EvLvart - RETINEX, // EvLCDCurve + DEMOSAIC, // EvLCDCurve RETINEX, // EvRetinextransmission DEMOSAIC, // EvRetinexEnabled RETINEX, // EvRetinexmedianmap RETINEX, // EvLlimd DEMOSAIC, // Evretinexcolorspace - RETINEX, // EvLCDHCurve + DEMOSAIC, // EvLCDHCurve DEMOSAIC, // Evretinexgamma DEMOSAIC, // EvLgam DEMOSAIC, // EvLslope RETINEX, // EvLhighl DEMOSAIC, // EvLbaselog -// DEMOSAIC, // EvLgrbl - DEMOSAIC, // EvRetinexlhcurve +// DEMOSAIC, // EvLgrbl + DEMOSAIC, // EvRetinexlhcurve ALLNORAW, // EvOIntent - MONITORTRANSFORM // EvMonitorTransform - + MONITORTRANSFORM, // EvMonitorTransform + RETINEX, // EvLiter + RETINEX, // EvLgrad + RETINEX, // EvLgrads + RETINEX, //EvLhighlights + RETINEX, //EvLh_tonalwidth + RETINEX, //EvLshadows + RETINEX, //EvLs_tonalwidth + RETINEX, //EvLradius + RETINEX, //EvmapMethod + DEMOSAIC, //EvRetinexmapcurve + DEMOSAIC //EvviewMethod }; diff --git a/rtengine/shmap.cc b/rtengine/shmap.cc index 34fadd5e7..2471b17a4 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; + int levrad = 16; + levrad=2;//for retinex - otherwise levrad = 16 + // 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 = (int) 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; + //printf("lut=%d rf5=%f rfm=%f\n thre=%f",lutSize, rangefn[5],rangefn[lutSize-10],thresh ); + + // 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 < levrad) { + 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 < levrad) { + 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_) { @@ -236,7 +398,7 @@ SSEFUNCTION void SHMap::dirpyr_shmap(float ** data_fine, float ** data_coarse, i #endif { #if defined( __SSE2__ ) && defined( __x86_64__ ) - __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; + __m128 dirwtv, valv, normv, dftemp1v, dftemp2v, fg; #endif // __SSE2__ int j; #ifdef _OPENMP @@ -252,6 +414,7 @@ SSEFUNCTION void SHMap::dirpyr_shmap(float ** data_fine, float ** data_coarse, i for(int inbr = max(i - scalewin, i % scale); inbr <= min(i + scalewin, height - 1); inbr += scale) { for (int jnbr = j % scale; jnbr <= j + scalewin; jnbr += scale) { + //printf("dat=%f ",abs(data_fine[inbr][jnbr] - data_fine[i][j])); dirwt = ( rangefn[abs(data_fine[inbr][jnbr] - data_fine[i][j])] ); val += dirwt * data_fine[inbr][jnbr]; norm += dirwt; @@ -342,7 +505,7 @@ SSEFUNCTION void SHMap::dirpyr_shmap(float ** data_fine, float ** data_coarse, i #endif { #if defined( __SSE2__ ) && defined( __x86_64__ ) - __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; + __m128 dirwtv, valv, normv, dftemp1v, dftemp2v, fgg; float domkerv[5][5][4] __attribute__ ((aligned (16))) = {{{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}, {{1, 1, 1, 1}, {2, 2, 2, 2}, {2, 2, 2, 2}, {2, 2, 2, 2}, {1, 1, 1, 1}}, {{1, 1, 1, 1}, {2, 2, 2, 2}, {2, 2, 2, 2}, {2, 2, 2, 2}, {1, 1, 1, 1}}, {{1, 1, 1, 1}, {2, 2, 2, 2}, {2, 2, 2, 2}, {2, 2, 2, 2}, {1, 1, 1, 1}}, {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}}; #endif // __SSE2__ 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 6e1c876cf..9ae940980 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -126,16 +126,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, cdcurve, 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 866142a10..062c61ba2 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -50,14 +50,20 @@ 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.viewMethod = v; retinex.retinexcolorspace = v; retinex.gammaretinex = v; retinex.enabled = v; retinex.str = v; retinex.scal = v; + retinex.iter = v; + retinex.grad = v; + retinex.grads = v; retinex.gam = v; retinex.slope = v; retinex.neigh = v; @@ -70,6 +76,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; @@ -528,14 +540,20 @@ 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.viewMethod = retinex.viewMethod && p.retinex.viewMethod == other.retinex.viewMethod; 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; retinex.scal = retinex.scal && p.retinex.scal == other.retinex.scal; + retinex.iter = retinex.iter && p.retinex.iter == other.retinex.iter; + retinex.grad = retinex.grad && p.retinex.grad == other.retinex.grad; + retinex.grads = retinex.grads && p.retinex.grads == other.retinex.grads; retinex.gam = retinex.gam && p.retinex.gam == other.retinex.gam; retinex.slope = retinex.slope && p.retinex.slope == other.retinex.slope; retinex.neigh = retinex.neigh && p.retinex.neigh == other.retinex.neigh; @@ -547,6 +565,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; @@ -1048,6 +1072,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; } @@ -1064,6 +1092,14 @@ 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.viewMethod) { + toEdit.retinex.viewMethod = mods.retinex.viewMethod; + } + if (retinex.retinexcolorspace) { toEdit.retinex.retinexcolorspace = mods.retinex.retinexcolorspace; } @@ -1084,6 +1120,22 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.retinex.str = dontforceSet && options.baBehav[ADDSET_RETI_STR] ? toEdit.retinex.str + mods.retinex.str : mods.retinex.str; } + if (retinex.scal) { + toEdit.retinex.scal = mods.retinex.scal; + } + + if (retinex.iter) { + toEdit.retinex.iter = mods.retinex.iter; + } + + if (retinex.grad) { + toEdit.retinex.grad = mods.retinex.grad; + } + + if (retinex.grads) { + toEdit.retinex.grads = mods.retinex.grads; + } + // if (retinex.scal) { // toEdit.retinex.scal = dontforceSet && options.baBehav[ADDSET_RETI_SCAL] ? toEdit.retinex.scal + mods.retinex.scal : mods.retinex.scal; // } @@ -1124,6 +1176,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 1993c7aaa..261da1753 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -61,12 +61,17 @@ public: bool enabled; bool str; bool scal; + bool iter; + bool grad; + bool grads; bool gam; bool slope; bool neigh; bool gain; bool offs; bool retinexMethod; + bool mapMethod; + bool viewMethod; bool retinexcolorspace; bool gammaretinex; bool vart; @@ -77,11 +82,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 43cbe4f28..fb69de3e3 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -84,6 +84,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")); @@ -145,7 +156,10 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), transLabels->set_tooltip_markup (M("TP_RETINEX_TLABEL_TOOLTIP")); transLabels2 = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); - scal = Gtk::manage (new Adjuster (M("TP_RETINEX_SCALES"), 1, 8., 1., 3.)); + scal = Gtk::manage (new Adjuster (M("TP_RETINEX_SCALES"), -1, 6., 1., 3.)); + iter = Gtk::manage (new Adjuster (M("TP_RETINEX_ITER"), 1, 5., 1., 1.)); + grad = Gtk::manage (new Adjuster (M("TP_RETINEX_GRAD"), -2., 2., 1., 1.)); + grads = Gtk::manage (new Adjuster (M("TP_RETINEX_GRADS"), -2., 2., 1., 1.)); gain = Gtk::manage (new Adjuster (M("TP_RETINEX_GAIN"), 20, 200, 1, 50)); offs = Gtk::manage (new Adjuster (M("TP_RETINEX_OFFSET"), -10000, 10000, 1, 0)); // vart = Gtk::manage (new Adjuster (M("TP_RETINEX_VARIANCE"), 50, 500, 1, 125)); @@ -154,10 +168,48 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), // grbl = Gtk::manage (new Adjuster (M("TP_RETINEX_HIGHLIGHT3"), 1, 100, 1, 50)); gain->set_tooltip_markup (M("TP_RETINEX_GAIN_TOOLTIP")); scal->set_tooltip_markup (M("TP_RETINEX_SCALES_TOOLTIP")); + iter->set_tooltip_markup (M("TP_RETINEX_ITER_TOOLTIP")); + grad->set_tooltip_markup (M("TP_RETINEX_GRAD_TOOLTIP")); + grads->set_tooltip_markup (M("TP_RETINEX_GRADS_TOOLTIP")); // vart->set_tooltip_markup (M("TP_RETINEX_VARIANCE_TOOLTIP")); 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)); + + viewbox = Gtk::manage (new Gtk::HBox ()); + labview = Gtk::manage (new Gtk::Label (M("TP_RETINEX_VIEW") + ":")); + viewbox->pack_start (*labview, Gtk::PACK_SHRINK, 1); + + viewMethod = Gtk::manage (new MyComboBoxText ()); + viewMethod->append_text (M("TP_RETINEX_VIEW_NONE")); + viewMethod->append_text (M("TP_RETINEX_VIEW_MASK")); + viewMethod->append_text (M("TP_RETINEX_VIEW_UNSHARP")); + viewMethod->append_text (M("TP_RETINEX_VIEW_TRAN")); + viewMethod->append_text (M("TP_RETINEX_VIEW_TRAN2")); + viewMethod->set_active(0); + viewMethodConn = viewMethod->signal_changed().connect ( sigc::mem_fun(*this, &Retinex::viewMethodChanged) ); + viewMethod->set_tooltip_markup (M("TP_RETINEX_VIEW_METHOD_TOOLTIP")); + curveEditorGH = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_CONTEDIT_LH")); curveEditorGH->setCurveListener (this); @@ -212,8 +264,17 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), slope->show (); -// settingsVBox->pack_start (*scal); -// scal->show (); + settingsVBox->pack_start (*iter); + iter->show (); + + settingsVBox->pack_start (*scal); + scal->show (); + + settingsVBox->pack_start (*grad); + grad->show (); + + settingsVBox->pack_start (*grads); + grads->show (); settingsVBox->pack_start (*gain); gain->show (); @@ -227,6 +288,30 @@ 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(); + + viewbox->pack_start(*viewMethod); + settingsVBox->pack_start(*viewbox); + + //settingsVBox->pack_start (*viewMethod); + // settingsVBox->pack_start (*highl); // highl->show (); @@ -235,6 +320,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(); @@ -268,6 +354,24 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), scal->delay = 200; } + iter->setAdjusterListener (this); + + if (iter->delay < 200) { + iter->delay = 200; + } + + grad->setAdjusterListener (this); + + if (grad->delay < 200) { + grad->delay = 200; + } + + grads->setAdjusterListener (this); + + if (grads->delay < 200) { + grads->delay = 200; + } + gam->setAdjusterListener (this); if (gam->delay < 500) { @@ -322,6 +426,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) { @@ -346,6 +476,7 @@ Retinex::~Retinex() delete curveEditorGDH; delete transmissionCurveEditorG; delete curveEditorGH; + delete curveEditormap; } void Retinex::neutral_pressed () @@ -355,16 +486,30 @@ void Retinex::neutral_pressed () offs->resetValue(false); str->resetValue(false); scal->resetValue(false); + iter->resetValue(false); + grad->resetValue(false); + grads->resetValue(false); vart->resetValue(false); limd->resetValue(false); highl->resetValue(false); 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); + viewMethod->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) @@ -474,10 +619,15 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) retinexMethodConn.block(true); retinexColorSpaceConn.block(true); gammaretinexConn.block(true); + mapMethodConn.block(true); + viewMethodConn.block(true); if (pedited) { scal->setEditedState (pedited->retinex.scal ? Edited : UnEdited); + iter->setEditedState (pedited->retinex.iter ? Edited : UnEdited); + grad->setEditedState (pedited->retinex.grad ? Edited : UnEdited); + grads->setEditedState (pedited->retinex.grads ? Edited : UnEdited); neigh->setEditedState (pedited->retinex.neigh ? Edited : UnEdited); gam->setEditedState (pedited->retinex.gam ? Edited : UnEdited); slope->setEditedState (pedited->retinex.slope ? Edited : UnEdited); @@ -490,12 +640,25 @@ 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.viewMethod) { + viewMethod->set_active_text(M("GENERAL_UNCHANGED")); + } + if (!pedited->retinex.retinexcolorspace) { retinexcolorspace->set_active_text(M("GENERAL_UNCHANGED")); } @@ -508,6 +671,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); } @@ -516,17 +680,36 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) offs->setValue (pp->retinex.offs); str->setValue (pp->retinex.str); scal->setValue (pp->retinex.scal); + iter->setValue (pp->retinex.iter); + grad->setValue (pp->retinex.grad); + grads->setValue (pp->retinex.grads); vart->setValue (pp->retinex.vart); limd->setValue (pp->retinex.limd); gam->setValue (pp->retinex.gam); 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); + scal->set_sensitive(false); + grads->set_sensitive(false); + } + else { + grad->set_sensitive(true); + scal->set_sensitive(true); + grads->set_sensitive(true); + } setEnabled (pp->retinex.enabled); - medianmapConn.block (true); medianmap->set_active (pp->retinex.medianmap); medianmapConn.block (false); lastmedianmap = pp->retinex.medianmap; @@ -543,6 +726,30 @@ 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.viewMethod == "none") { + viewMethod->set_active (0); + } else if (pp->retinex.viewMethod == "mask") { + viewMethod->set_active (1); + } else if (pp->retinex.viewMethod == "unsharp") { + viewMethod->set_active (2); + } else if (pp->retinex.viewMethod == "tran") { + viewMethod->set_active (3); + } else if (pp->retinex.viewMethod == "tran2") { + viewMethod->set_active (4); + } + if (pp->retinex.retinexcolorspace == "Lab") { retinexcolorspace->set_active (0); } else if (pp->retinex.retinexcolorspace == "HSLLOG") { @@ -566,6 +773,8 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) retinexMethodChanged (); retinexColorSpaceChanged(); gammaretinexChanged(); + mapMethodChanged (); + viewMethodChanged (); medianmapConn.block(true); medianmapChanged (); @@ -574,10 +783,13 @@ 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); + viewMethodConn.block(false); transmissionShape->setCurve (pp->retinex.transmissionCurve); @@ -591,6 +803,9 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) pp->retinex.str = str->getValue (); pp->retinex.scal = (int)scal->getValue (); + pp->retinex.iter = (int) iter->getValue (); + pp->retinex.grad = (int) grad->getValue (); + pp->retinex.grads = (int) grads->getValue (); pp->retinex.gam = gam->getValue (); pp->retinex.slope = slope->getValue (); pp->retinex.neigh = neigh->getValue (); @@ -604,18 +819,30 @@ 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.viewMethod = viewMethod->get_active_text() != M("GENERAL_UNCHANGED"); //%%%%%%%%%%%%%%%%%%%%%% pedited->retinex.str = str->getEditedState (); pedited->retinex.scal = scal->getEditedState (); + pedited->retinex.iter = iter->getEditedState (); + pedited->retinex.grad = grad->getEditedState (); + pedited->retinex.grads = grads->getEditedState (); pedited->retinex.gam = gam->getEditedState (); pedited->retinex.slope = slope->getEditedState (); pedited->retinex.neigh = neigh->getEditedState (); @@ -629,10 +856,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) { @@ -647,6 +881,30 @@ 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 (viewMethod->get_active_row_number() == 0) { + pp->retinex.viewMethod = "none"; + } else if (viewMethod->get_active_row_number() == 1) { + pp->retinex.viewMethod = "mask"; + } else if (viewMethod->get_active_row_number() == 2) { + pp->retinex.viewMethod = "unsharp"; + } else if (viewMethod->get_active_row_number() == 3) { + pp->retinex.viewMethod = "tran"; + } else if (viewMethod->get_active_row_number() == 4) { + pp->retinex.viewMethod = "tran2"; + } + if (retinexcolorspace->get_active_row_number() == 0) { pp->retinex.retinexcolorspace = "Lab"; } else if (retinexcolorspace->get_active_row_number() == 1) { @@ -683,6 +941,83 @@ void Retinex::retinexMethodChanged() } } + + +void Retinex::mapMethodChanged() +{ + + if(mapMethod->get_active_row_number() == 1 || mapMethod->get_active_row_number() == 2) { + curveEditormap->show(); + highlights->show(); + h_tonalwidth->show(); + shadows->show(); + s_tonalwidth->show(); + radius->show(); + } else if(mapMethod->get_active_row_number() == 3 || mapMethod->get_active_row_number() == 4) { + curveEditormap->show(); + highlights->show(); + h_tonalwidth->show(); + shadows->show(); + s_tonalwidth->show(); + 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::viewMethodChanged() +{ + if(viewMethod->get_active_row_number() == 1 || viewMethod->get_active_row_number() == 2) { + vart->hide(); + gain->hide(); + offs->hide(); + limd->hide(); + transmissionCurveEditorG->hide(); + medianmap->hide(); + iter->hide(); + scal->hide(); + grad->hide(); + grads->hide(); + curveEditorGH->hide(); + } + else if(viewMethod->get_active_row_number() == 3 || viewMethod->get_active_row_number() == 4) { + gain->hide(); + offs->hide(); + vart->hide(); + curveEditorGH->hide(); + } + else { + vart->show(); + neigh->show(); + gain->show(); + offs->show(); + limd->show(); + transmissionCurveEditorG->show(); + medianmap->show(); + iter->show(); + scal->show(); + grad->show(); + grads->show(); + curveEditorGH->show(); + } + + if (listener) { + listener->panelChanged (EvviewMethod, viewMethod->get_active_text ()); + } +} + + + void Retinex::ColorSpaceUpdateUI () { if (!batchMode) { @@ -771,6 +1106,9 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi offs->setDefault (defParams->retinex.offs); str->setDefault (defParams->retinex.str); scal->setDefault (defParams->retinex.scal); + iter->setDefault (defParams->retinex.iter); + grad->setDefault (defParams->retinex.grad); + grads->setDefault (defParams->retinex.grads); vart->setDefault (defParams->retinex.vart); limd->setDefault (defParams->retinex.limd); highl->setDefault (defParams->retinex.highl); @@ -779,12 +1117,21 @@ 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); offs->setDefaultEditedState (pedited->retinex.offs ? Edited : UnEdited); str->setDefaultEditedState (pedited->retinex.str ? Edited : UnEdited); scal->setDefaultEditedState (pedited->retinex.scal ? Edited : UnEdited); + iter->setDefaultEditedState (pedited->retinex.iter ? Edited : UnEdited); + grad->setDefaultEditedState (pedited->retinex.grad ? Edited : UnEdited); + grads->setDefaultEditedState (pedited->retinex.grads ? Edited : UnEdited); vart->setDefaultEditedState (pedited->retinex.vart ? Edited : UnEdited); limd->setDefaultEditedState (pedited->retinex.limd ? Edited : UnEdited); highl->setDefaultEditedState (pedited->retinex.highl ? Edited : UnEdited); @@ -793,6 +1140,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); @@ -804,8 +1157,18 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi // grbl->setDefaultEditedState (Irrelevant); str->setDefaultEditedState (Irrelevant); scal->setDefaultEditedState (Irrelevant); + iter->setDefaultEditedState (Irrelevant); + grad->setDefaultEditedState (Irrelevant); + 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); + } } @@ -828,6 +1191,17 @@ void Retinex::adjusterChanged (Adjuster* a, double newval) if (!listener || !getEnabled()) { return; } + if(iter->getTextValue() > "1") { + scal->set_sensitive(true); + grad->set_sensitive(true); + grads->set_sensitive(true); + } + else { + scal->set_sensitive(false); + grad->set_sensitive(false); + grads->set_sensitive(false); + } + if (a == neigh) { listener->panelChanged (EvLneigh, neigh->getTextValue()); @@ -835,6 +1209,12 @@ void Retinex::adjusterChanged (Adjuster* a, double newval) listener->panelChanged (EvLstr, str->getTextValue()); } else if (a == scal) { listener->panelChanged (EvLscal, scal->getTextValue()); + } else if (a == iter) { + listener->panelChanged (EvLiter, iter->getTextValue()); + } else if (a == grad) { + listener->panelChanged (EvLgrad, grad->getTextValue()); + } else if (a == grads) { + listener->panelChanged (EvLgrads, grads->getTextValue()); } else if (a == gain) { listener->panelChanged (EvLgain, gain->getTextValue()); } else if (a == offs) { @@ -853,8 +1233,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()); + } + } @@ -865,6 +1257,7 @@ void Retinex::autoOpenCurve () cdshapeH->openIfNonlinear(); transmissionShape->openIfNonlinear(); lhshape->openIfNonlinear(); + mapshape->openIfNonlinear(); } @@ -880,6 +1273,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")); } } } @@ -903,6 +1298,9 @@ void Retinex::trimValues (rtengine::procparams::ProcParams* pp) { str->trimValue(pp->retinex.str); scal->trimValue(pp->retinex.scal); + iter->trimValue(pp->retinex.iter); + grad->trimValue(pp->retinex.grad); + grads->trimValue(pp->retinex.grads); neigh->trimValue(pp->retinex.neigh); gain->trimValue(pp->retinex.gain); offs->trimValue(pp->retinex.offs); @@ -913,6 +1311,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) @@ -976,17 +1376,28 @@ void Retinex::setBatchMode (bool batchMode) offs->showEditedCB (); str->showEditedCB (); scal->showEditedCB (); + iter->showEditedCB (); + grad->showEditedCB (); + grads->showEditedCB (); gam->showEditedCB (); slope->showEditedCB (); vart->showEditedCB (); 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 59001ce18..d24254757 100644 --- a/rtgui/retinex.h +++ b/rtgui/retinex.h @@ -22,8 +22,12 @@ protected: CurveEditorGroup* curveEditorGD; CurveEditorGroup* curveEditorGDH; CurveEditorGroup* curveEditorGH; + CurveEditorGroup* curveEditormap; Adjuster* str; Adjuster* scal; + Adjuster* grad; + Adjuster* grads; + Adjuster* iter; Adjuster* neigh; Adjuster* gain; Adjuster* offs; @@ -34,10 +38,21 @@ 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::HBox* viewbox; + Gtk::Label* labview; + Gtk::Label* labgam; Gtk::HBox* gambox; Gtk::Button* neutral; @@ -46,6 +61,8 @@ protected: MyComboBoxText* retinexMethod; MyComboBoxText* retinexcolorspace; MyComboBoxText* gammaretinex; + MyComboBoxText* mapMethod; + MyComboBoxText* viewMethod; Gtk::CheckButton* medianmap; double nextmin; double nextmax; @@ -62,8 +79,9 @@ protected: DiagonalCurveEditor* cdshape; DiagonalCurveEditor* cdshapeH; + DiagonalCurveEditor* mapshape; CurveEditorGroup* transmissionCurveEditorG; - sigc::connection retinexMethodConn, neutralconn; + sigc::connection retinexMethodConn, neutralconn, mapMethodConn, viewMethodConn; sigc::connection retinexColorSpaceConn; sigc::connection gammaretinexConn; FlatCurveEditor* transmissionShape; @@ -92,6 +110,8 @@ public: void enabledChanged (); void curveChanged (CurveEditor* ce); void retinexMethodChanged(); + void mapMethodChanged(); + void viewMethodChanged(); void retinexColorSpaceChanged(); void gammaretinexChanged(); void ColorSpaceUpdateUI();