diff --git a/rtdata/languages/default b/rtdata/languages/default index ee6952559..aeb5664e8 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -641,7 +641,7 @@ HISTORY_MSG_408;Retinex - Neighboring HISTORY_MSG_409;Retinex - Gain HISTORY_MSG_410;Retinex - Offset 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 @@ -656,6 +656,8 @@ HISTORY_MSG_423;Retinex - Gamma slope HISTORY_MSG_424;Retinex - HL threshold HISTORY_MSG_425;Retinex - Log base HISTORY_MSG_426;Retinex - Hue equalizer +HISTORY_MSG_427;Retinex - Iterations +HISTORY_MSG_428;Retinex - T. Gradient HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOTS;Snapshots @@ -1654,6 +1656,10 @@ TP_RETINEX_HIGHLIG;Highlight TP_RETINEX_HIGH;High 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_LABEL;Retinex TP_RETINEX_LABSPACE;L*a*b* TP_RETINEX_LOW;Low @@ -1667,6 +1673,8 @@ TP_RETINEX_NEUTRAL;Reset TP_RETINEX_NEUTRAL_TIP;Reset all sliders and curves to their default values. TP_RETINEX_OFFSET;Offset 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 diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc index 54d5d3515..1f6602b62 100644 --- a/rtengine/ipretinex.cc +++ b/rtengine/ipretinex.cc @@ -217,10 +217,12 @@ 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 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 @@ -271,283 +273,342 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e if (deh.retinexMethod == "highli" || deh.retinexMethod == "highliplus") { moderetinex = 3; } - - float aahi = 49.f / 99.f; ////reduce sensibility 50% - float bbhi = 1.f - aahi; - float high; - high = bbhi + aahi * (float) deh.highl; - retinex_scales( RetinexScales, scal, moderetinex, nei, high ); - - int H_L = height; - int W_L = width; - - float *src[H_L] ALIGNED16; - float *srcBuffer = new float[H_L * W_L]; - - for (int i = 0; i < H_L; i++) { - src[i] = &srcBuffer[i * W_L]; - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - 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; + 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); + else if(gradient==1) { + grad=0.25f*it+0.75f; + sc=-0.5f*it+4.5f; + } + else if(gradient==2) { + grad=0.5f*it+0.5f; + sc=-it+6.f; + } + else if(gradient==3) { + grad=0.666f*it+0.333f; + sc=-it+6.f; + } + else if(gradient==4) { + grad=0.8f*it+0.2f; + sc=-it+6.f; + } + else if(gradient==5) { + grad=0.9f*it+0.1f; + sc=-it+6.f; + } + else if(gradient==-1) { + grad=-0.125f*it+1.125f; + sc=3.f; + } + float varx; + float limdx, ilimdx; + if(gradvart!=0) { + if(gradvart==1) { + varx=vart*(-0.125f*it+1.125f); + limdx=limD*(-0.125f*it+1.125f); + ilimdx=1.f/limdx; } - -#ifdef __SSE2__ - vfloat pondv = F2V(pond); - vfloat limMinv = F2V(ilimD); - vfloat limMaxv = F2V(limD); - -#endif -#ifdef _OPENMP - #pragma omp for -#endif - - 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 ? - } - } + else if(gradvart==2) { + varx=vart*(-0.2f*it+1.2f); + limdx=limD*(-0.2f*it+1.2f); + ilimdx=1.f/limdx; + } + else if(gradvart==-1) { + varx=vart*(0.125f*it+0.875f); + limdx=limD*(0.125f*it+0.875f); + ilimdx=1.f/limdx; + } + else if(gradvart==-2) { + varx=vart*(0.4f*it+0.6f); + limdx=limD*(0.4f*it+0.6f); + ilimdx=1.f/limdx; } } - } - delete [] buffer; - delete [] outBuffer; - delete [] srcBuffer; + else { + varx=vart; + limdx=limD; + ilimdx=ilimD; + } + scal=round(sc); + float aahi = 49.f / 99.f; ////reduce sensibility 50% + float bbhi = 1.f - aahi; + float high; + high = bbhi + aahi * (float) deh.highl; + retinex_scales( RetinexScales, scal, moderetinex, nei/grad, high ); - mean = 0.f; - stddv = 0.f; - // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + int H_L = height; + int W_L = width; - 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 *src[H_L] ALIGNED16; + float *srcBuffer = new float[H_L * W_L]; - // 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; + for (int i = 0; i < H_L; i++) { + src[i] = &srcBuffer[i * W_L]; + } - asig *= 500.f; - bsig *= 500.f; - amax *= 500.f; - bmax *= 500.f; - amin *= 500.f; - bmin *= 500.f; +#ifdef _OPENMP + #pragma omp parallel for +#endif + + 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; + } + + float *out[H_L] ALIGNED16; + float *outBuffer = new float[H_L * W_L]; + + for (int i = 0; i < H_L; i++) { + out[i] = &outBuffer[i * W_L]; + } + + const float logBetaGain = xlogf(16384.f); + float pond = logBetaGain / (float) scal; + + if(!useHslLin) { + pond /= log(elogt); + } + + float *buffer = new float[W_L * H_L];; #ifdef _OPENMP #pragma omp parallel #endif { - float absciss; + 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); + } + +#ifdef __SSE2__ + vfloat pondv = F2V(pond); + vfloat limMinv = F2V(ilimdx); + vfloat limMaxv = F2V(limdx); + +#endif #ifdef _OPENMP - #pragma omp for schedule(dynamic,16) + #pragma omp for #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; + 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) )); + } } - 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; - - 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(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 ? + } + } } } - -#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; - } + 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 + } + } + + // 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; + + + + +#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 = 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)); + } + + str *= (1.f + 2.f * valparam); + } + } + + // 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 critical +#endif + { + maxCD = maxCD > cdmax ? maxCD : cdmax; + minCD = minCD < cdmin ? minCD : cdmin; + } + + } + // printf("cdmin=%f cdmax=%f\n",minCD, maxCD); + Tmean = mean; + Tsigma = stddv; + Tmin = mintr; + Tmax = maxtr; + + if (shcurve) { + delete shcurve; + } + } } } diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 4dbbad07c..ae348316f 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -454,6 +454,8 @@ enum ProcEvent { EvLbaselog = 424, // EvLgrbl = 425, EvRetinexlhcurve = 425, + EvLiter = 426, + EvLgrad = 427, NUMOFEVENTS }; } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index becd8932e..ed57f50d3 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -142,6 +142,8 @@ void RetinexParams::setDefaults() enabled = false; str = 20; scal = 3; + iter = 1; + grad = 1; gam = 1.30; slope = 3.; neigh = 80; @@ -1444,6 +1446,14 @@ 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.iter); + } + if (!pedited || pedited->retinex.gam) { keyFile.set_double ("Retinex", "Gam", retinex.gam); } @@ -3851,6 +3861,22 @@ 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", "Gam")) { retinex.gam = keyFile.get_double ("Retinex", "Gam"); @@ -7322,6 +7348,8 @@ bool ProcParams::operator== (const ProcParams& other) && 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.gam == other.retinex.gam && retinex.slope == other.retinex.slope && retinex.neigh == other.retinex.neigh diff --git a/rtengine/procparams.h b/rtengine/procparams.h index d46fd4181..1226d1584 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -275,6 +275,8 @@ public: std::vector transmissionCurve; int str; int scal; + int iter; + int grad; double gam; double slope; int neigh; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 3505da24f..88338f06c 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -453,6 +453,9 @@ int refreshmap[rtengine::NUMOFEVENTS] = { RETINEX, // EvLhighl DEMOSAIC, // EvLbaselog // DEMOSAIC, // EvLgrbl - DEMOSAIC // EvRetinexlhcurve + DEMOSAIC, // EvRetinexlhcurve + RETINEX, // EvLiter + RETINEX // EvLgrad + }; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index ac2fe6523..600a68af4 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -58,6 +58,8 @@ void ParamsEdited::set (bool v) retinex.enabled = v; retinex.str = v; retinex.scal = v; + retinex.iter = v; + retinex.grad = v; retinex.gam = v; retinex.slope = v; retinex.neigh = v; @@ -535,6 +537,8 @@ void ParamsEdited::initFrom (const std::vector 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.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; @@ -1082,6 +1086,18 @@ 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.scal) { // toEdit.retinex.scal = dontforceSet && options.baBehav[ADDSET_RETI_SCAL] ? toEdit.retinex.scal + mods.retinex.scal : mods.retinex.scal; // } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 3fa753013..ed1f07aec 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -61,6 +61,8 @@ public: bool enabled; bool str; bool scal; + bool iter; + bool grad; bool gam; bool slope; bool neigh; diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index b964ecbb5..0578c3e57 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -144,7 +144,9 @@ 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, 5., 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.)); 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)); @@ -153,6 +155,8 @@ 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")); // 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")); @@ -211,8 +215,14 @@ 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 (*gain); gain->show (); @@ -267,6 +277,18 @@ 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; + } + gam->setAdjusterListener (this); if (gam->delay < 500) { @@ -354,6 +376,8 @@ void Retinex::neutral_pressed () offs->resetValue(false); str->resetValue(false); scal->resetValue(false); + iter->resetValue(false); + grad->resetValue(false); vart->resetValue(false); limd->resetValue(false); highl->resetValue(false); @@ -477,6 +501,8 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) if (pedited) { scal->setEditedState (pedited->retinex.scal ? Edited : UnEdited); + iter->setEditedState (pedited->retinex.iter ? Edited : UnEdited); + grad->setEditedState (pedited->retinex.grad ? Edited : UnEdited); neigh->setEditedState (pedited->retinex.neigh ? Edited : UnEdited); gam->setEditedState (pedited->retinex.gam ? Edited : UnEdited); slope->setEditedState (pedited->retinex.slope ? Edited : UnEdited); @@ -515,6 +541,8 @@ 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); vart->setValue (pp->retinex.vart); limd->setValue (pp->retinex.limd); gam->setValue (pp->retinex.gam); @@ -522,10 +550,17 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) highl->setValue (pp->retinex.highl); baselog->setValue (pp->retinex.baselog); // grbl->setValue (pp->retinex.grbl); + if(pp->retinex.iter == 1) { + grad->set_sensitive(false); + scal->set_sensitive(false); + } + else { + grad->set_sensitive(true); + scal->set_sensitive(true); + } setEnabled (pp->retinex.enabled); - medianmapConn.block (true); medianmap->set_active (pp->retinex.medianmap); medianmapConn.block (false); lastmedianmap = pp->retinex.medianmap; @@ -590,6 +625,8 @@ 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.gam = gam->getValue (); pp->retinex.slope = slope->getValue (); pp->retinex.neigh = neigh->getValue (); @@ -615,6 +652,8 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) //%%%%%%%%%%%%%%%%%%%%%% pedited->retinex.str = str->getEditedState (); pedited->retinex.scal = scal->getEditedState (); + pedited->retinex.iter = iter->getEditedState (); + pedited->retinex.grad = grad->getEditedState (); pedited->retinex.gam = gam->getEditedState (); pedited->retinex.slope = slope->getEditedState (); pedited->retinex.neigh = neigh->getEditedState (); @@ -770,6 +809,8 @@ 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); vart->setDefault (defParams->retinex.vart); limd->setDefault (defParams->retinex.limd); highl->setDefault (defParams->retinex.highl); @@ -784,6 +825,8 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi 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); vart->setDefaultEditedState (pedited->retinex.vart ? Edited : UnEdited); limd->setDefaultEditedState (pedited->retinex.limd ? Edited : UnEdited); highl->setDefaultEditedState (pedited->retinex.highl ? Edited : UnEdited); @@ -803,6 +846,8 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi // grbl->setDefaultEditedState (Irrelevant); str->setDefaultEditedState (Irrelevant); scal->setDefaultEditedState (Irrelevant); + iter->setDefaultEditedState (Irrelevant); + grad->setDefaultEditedState (Irrelevant); gam->setDefaultEditedState (Irrelevant); slope->setDefaultEditedState (Irrelevant); } @@ -827,6 +872,15 @@ void Retinex::adjusterChanged (Adjuster* a, double newval) if (!listener || !getEnabled()) { return; } + if(iter->getTextValue() > "1") { + scal->set_sensitive(true); + grad->set_sensitive(true); + } + else { + scal->set_sensitive(false); + grad->set_sensitive(false); + } + if (a == neigh) { listener->panelChanged (EvLneigh, neigh->getTextValue()); @@ -834,6 +888,10 @@ 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 == gain) { listener->panelChanged (EvLgain, gain->getTextValue()); } else if (a == offs) { @@ -902,6 +960,8 @@ 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); neigh->trimValue(pp->retinex.neigh); gain->trimValue(pp->retinex.gain); offs->trimValue(pp->retinex.offs); @@ -975,6 +1035,8 @@ void Retinex::setBatchMode (bool batchMode) offs->showEditedCB (); str->showEditedCB (); scal->showEditedCB (); + iter->showEditedCB (); + grad->showEditedCB (); gam->showEditedCB (); slope->showEditedCB (); vart->showEditedCB (); diff --git a/rtgui/retinex.h b/rtgui/retinex.h index 59001ce18..499b0ef0f 100644 --- a/rtgui/retinex.h +++ b/rtgui/retinex.h @@ -24,6 +24,8 @@ protected: CurveEditorGroup* curveEditorGH; Adjuster* str; Adjuster* scal; + Adjuster* grad; + Adjuster* iter; Adjuster* neigh; Adjuster* gain; Adjuster* offs;