diff --git a/rtdata/languages/default b/rtdata/languages/default index 6bedd3443..ae3a81050 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -670,6 +670,7 @@ HISTORY_MSG_436;Retinex - M - Radius HISTORY_MSG_437;Retinex - M - Method HISTORY_MSG_438;Retinex - M - Equalizer HISTORY_MSG_439;Retinex - Preview +HISTORY_MSG_440;Retinex - Gain transmission HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -1667,6 +1668,7 @@ TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;This curve can be applied alone or with a Gau TP_RETINEX_FREEGAMMA;Free gamma TP_RETINEX_GAIN;Gain TP_RETINEX_GAIN_TOOLTIP;Acts on the restored image.\n\nThis is very different from the others settings. Used for black or white pixels, and to help balance the histogram. +TP_RETINEX_GAINOFFS;Gain and Brightness (offset) TP_RETINEX_GAMMA;Gamma TP_RETINEX_GAMMA_FREE;Free TP_RETINEX_GAMMA_HIGH;High @@ -1705,7 +1707,7 @@ TP_RETINEX_MLABEL_TOOLTIP;Should be near min=0 max=32768\nRestored image with no TP_RETINEX_NEIGHBOR;Radius TP_RETINEX_NEUTRAL;Reset TP_RETINEX_NEUTRAL_TIP;Reset all sliders and curves to their default values. -TP_RETINEX_OFFSET;Brightness +TP_RETINEX_OFFSET;Brightness (offset) TP_RETINEX_SCALES;Gaussian gradient TP_RETINEX_SCALES_TOOLTIP;If slider at 0, all iterations are identical.\nIf > 0 Scale and radius are reduced when iterations increase, and conversely. TP_RETINEX_SETTINGS;Settings @@ -1717,6 +1719,8 @@ TP_RETINEX_TLABEL;TM Min=%1 Max=%2 Mean=%3 Sigma=%4 TP_RETINEX_TLABEL2;TM Tm=%1 TM=%2 TP_RETINEX_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Variance.\nMean and Sigma.\nTm=Min TM=Max of transmission map. TP_RETINEX_TRANSMISSION;Transmission map +TP_RETINEX_GAINTRANSMISSION;Gain transmission +TP_RETINEX_GAINTRANSMISSION_TOOLTIP;Amplfy or reduce transmission-map to achieve luminance.\nAbscissa: transmission -min from 0, mean, and values (max).\nOrdinate : gain 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;Contrast diff --git a/rtengine/curves.cc b/rtengine/curves.cc index d0b4c026f..a0ac2c381 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -1429,6 +1429,39 @@ void RetinextransmissionCurve::Set(const std::vector &curvePoints) } } + +RetinexgaintransmissionCurve::RetinexgaintransmissionCurve() {}; + +void RetinexgaintransmissionCurve::Reset() +{ + lutgaintransmission.reset(); +} + +void RetinexgaintransmissionCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + lutgaintransmission.reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutgaintransmission(501); // raise this value if the quality suffers from this number of samples + + for (int i = 0; i < 501; i++) { + lutgaintransmission[i] = pCurve.getVal(double(i) / 500.); + } +} + +void RetinexgaintransmissionCurve::Set(const std::vector &curvePoints) +{ + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } +} + void ToneCurve::Reset() { lutToneCurve.reset(); diff --git a/rtengine/curves.h b/rtengine/curves.h index e55d7bc2a..330b5c5ce 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -454,6 +454,30 @@ public: } }; +class RetinexgaintransmissionCurve +{ +private: + LUTf lutgaintransmission; // 0xffff range + void Set(const Curve &pCurve); + +public: + virtual ~RetinexgaintransmissionCurve() {}; + RetinexgaintransmissionCurve(); + + void Reset(); + void Set(const Curve *pCurve); + void Set(const std::vector &curvePoints); + float operator[](float index) const + { + return lutgaintransmission[index]; + } + + operator bool (void) const + { + return lutgaintransmission; + } +}; + class ToneCurve diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 80fc53f23..905c8c50e 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, 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 retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, 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, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, 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, 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 void MSR(LabImage* lab, LUTf & mapcurve, bool &mapcontlutili, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, 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 ee75e831a..d24427be9 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -242,16 +242,16 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } - if ((todo & (M_RETINEX|M_INIT)) && params.retinex.enabled) { + if ((todo & (M_RETINEX | M_INIT)) && params.retinex.enabled) { bool dehacontlutili = false; bool mapcontlutili = false; bool useHsl = false; LUTf cdcurve (65536, 0); LUTf mapcurve (65536, 0); - imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehacontlutili, mapcontlutili, useHsl, lhist16RETI, histLRETI); + imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, dehacontlutili, mapcontlutili, useHsl, lhist16RETI, histLRETI); float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax; - 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 + imgsrc->retinex( params.icm, params.retinex, params.toneCurve, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, 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); @@ -782,6 +782,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } } + // Update the monitor color transform if necessary if (todo & M_MONITOR) { ipf.updateColorProfiles(params.icm, monitorProfile, monitorIntent); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 4d442482e..6a6c203d2 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -136,6 +136,7 @@ protected: WavOpacityCurveW waOpacityCurveW; WavOpacityCurveWL waOpacityCurveWL; RetinextransmissionCurve dehatransmissionCurve; + RetinexgaintransmissionCurve dehagaintransmissionCurve; ColorAppearance customColCurve1; ColorAppearance customColCurve2; diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc index 090841a9e..d3d276c43 100644 --- a/rtengine/ipretinex.cc +++ b/rtengine/ipretinex.cc @@ -45,7 +45,6 @@ #include "rawimagesource.h" #include "improcfun.h" #include "opthelper.h" -#define BENCHMARK #include "StopWatch.h" #define MAX_RETINEX_SCALES 8 @@ -207,9 +206,8 @@ 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, 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 RawImageSource::MSR(float** luminance, float** originalLuminance, float **exLuminance, LUTf & mapcurve, bool &mapcontlutili, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) { - BENCHFUN if (deh.enabled) {//enabled float mean, stddv, maxtr, mintr; @@ -733,7 +731,8 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e delta = 1.0f; } - float cdfactor = gain2 * 32768.f / delta; + // float cdfactor = gain2 * 32768.f / delta; + float cdfactor = 32768.f / delta; maxCD = -9999999.f; minCD = 9999999.f; // coeff for auto "transmission" with 2 sigma #95% datas @@ -742,22 +741,72 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e float bza = 16300.f / (2.f * stddv); float bzb = 16300.f - bza * (mean); +//prepare work for curve gain +#ifdef _OPENMP + #pragma omp parallel for +#endif + for (int i = 0; i < H_L; i++) { + for (int j = 0; j < W_L; j++) { + luminance[i][j] = luminance[i][j] - mini; + } + } + + mean = 0.f; + stddv = 0.f; + // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + + mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr); + float asig, bsig, amax, bmax, amin, bmin; + + if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve + asig = 0.166666f / stddv; + bsig = 0.5f - asig * mean; + amax = 0.333333f / (maxtr - mean - stddv); + bmax = 1.f - amax * maxtr; + amin = 0.333333f / (mean - stddv - mintr); + 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 #endif { + float absciss; 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; + float gan; + + if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { + + 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; + } + + + // float cd = cdfactor * ( luminance[i][j] - mini ) + offse; + gan = 2.f * (dehagaintransmissionCurve[absciss]); //new gain function transmission + } else { + gan = 0.5f; + } + + float cd = gan * cdfactor * ( luminance[i][j] ) + offse; if(cd > cdmax) { cdmax = cd; diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 558f509c2..cd6fc2cb2 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -466,6 +466,7 @@ enum ProcEvent { EvmapMethod = 436, EvRetinexmapcurve = 437, EvviewMethod = 438, + EvRetinexgaintransmission = 439, NUMOFEVENTS }; } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index f79f51c91..988bd20dc 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -136,6 +136,23 @@ void RetinexParams::getDefaulttransmissionCurve(std::vector &curve) curve.at(i) = v[i - 1]; } } +void RetinexParams::getDefaultgaintransmissionCurve(std::vector &curve) +{ + double v[16] = { 0.00, 0.1, 0.35, 0.00, + 0.25, 0.25, 0.35, 0.35, + 0.70, 0.25, 0.35, 0.35, + 1.00, 0.1, 0.00, 0.00 + }; + + + curve.resize(17); + curve.at(0 ) = double(FCT_MinMaxCPoints); + + for (size_t i = 1; i < curve.size(); ++i) { + curve.at(i) = v[i - 1]; + } +} + void RetinexParams::setDefaults() { @@ -175,13 +192,16 @@ void RetinexParams::setDefaults() lhcurve.push_back(DCT_Linear); mapcurve.clear(); mapcurve.push_back(DCT_Linear); + getDefaultgaintransmissionCurve(gaintransmissionCurve); getDefaulttransmissionCurve(transmissionCurve); } -void RetinexParams::getCurves(RetinextransmissionCurve &transmissionCurveLUT) const +void RetinexParams::getCurves(RetinextransmissionCurve &transmissionCurveLUT, RetinexgaintransmissionCurve &gaintransmissionCurveLUT) const { transmissionCurveLUT.Set(this->transmissionCurve); + gaintransmissionCurveLUT.Set(this->gaintransmissionCurve); + } @@ -1585,6 +1605,11 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_double_list("Retinex", "TransmissionCurve", transmissionCurve); } + if (!pedited || pedited->retinex.gaintransmissionCurve) { + Glib::ArrayHandle gaintransmissionCurve = retinex.gaintransmissionCurve; + keyFile.set_double_list("Retinex", "GainTransmissionCurve", gaintransmissionCurve); + } + // save channel mixer if (!pedited || pedited->chmixer.red[0] || pedited->chmixer.red[1] || pedited->chmixer.red[2]) { Glib::ArrayHandle rmix (chmixer.red, 3, Glib::OWNERSHIP_NONE); @@ -4129,6 +4154,16 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->retinex.transmissionCurve = true; } } + + + if (keyFile.has_key ("Retinex", "GainTransmissionCurve")) { + retinex.gaintransmissionCurve = keyFile.get_double_list ("Retinex", "GainTransmissionCurve"); + + if (pedited) { + pedited->retinex.gaintransmissionCurve = true; + } + } + } @@ -7514,6 +7549,7 @@ bool ProcParams::operator== (const ProcParams& other) && retinex.cdHcurve == other.retinex.cdHcurve && retinex.lhcurve == other.retinex.lhcurve && retinex.transmissionCurve == other.retinex.transmissionCurve + && retinex.gaintransmissionCurve == other.retinex.gaintransmissionCurve && retinex.str == other.retinex.str && retinex.scal == other.retinex.scal && retinex.iter == other.retinex.iter diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 47b8f1cf1..0b45e7d7a 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -41,6 +41,7 @@ class WavOpacityCurveBY; class WavOpacityCurveW; class WavOpacityCurveWL; class RetinextransmissionCurve; +class RetinexgaintransmissionCurve; enum RenderingIntent { RI_PERCEPTUAL = INTENT_PERCEPTUAL, @@ -282,6 +283,7 @@ public: std::vector cdHcurve; std::vector lhcurve; std::vector transmissionCurve; + std::vector gaintransmissionCurve; std::vector mapcurve; int str; int scal; @@ -312,7 +314,9 @@ public: bool medianmap; RetinexParams (); void setDefaults(); - void getCurves(RetinextransmissionCurve &transmissionCurveLUT) const; + void getCurves(RetinextransmissionCurve &transmissionCurveLUT, RetinexgaintransmissionCurve &gaintransmissionCurveLUT) const; + + static void getDefaultgaintransmissionCurve(std::vector &curve); static void getDefaulttransmissionCurve(std::vector &curve); }; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index d1d4da54f..2251c15dd 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1422,6 +1422,7 @@ SSEFUNCTION int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thres } #else + // 25 fabs function calls and 25 float additions without SSE for (int mm = rr - 2; mm <= rr + 2; mm++) { for (int nn = cc - 2; nn <= cc + 2; nn++) { @@ -2216,7 +2217,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar } -void RawImageSource::retinexPrepareCurves(RetinexParams retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) +void RawImageSource::retinexPrepareCurves(RetinexParams retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) { useHsl = (retinexParams.retinexcolorspace == "HSLLOG" || retinexParams.retinexcolorspace == "HSLLIN"); @@ -2228,11 +2229,10 @@ void RawImageSource::retinexPrepareCurves(RetinexParams retinexParams, LUTf &cdc CurveFactory::mapcurve (mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI); - retinexParams.getCurves(retinextransmissionCurve); + retinexParams.getCurves(retinextransmissionCurve, retinexgaintransmissionCurve); } -//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) +void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, 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; @@ -2384,7 +2384,7 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC } } - MSR(LBuffer, conversionBuffer[2], conversionBuffer[3], mapcurve, mapcontlutili, WNew, HNew, deh, dehatransmissionCurve, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); + MSR(LBuffer, conversionBuffer[2], conversionBuffer[3], mapcurve, mapcontlutili, WNew, HNew, deh, dehatransmissionCurve, dehagaintransmissionCurve, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); if(useHsl) { if(chutili) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index bef4ad4e2..0f4ca2402 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -118,8 +118,8 @@ public: int load (Glib::ustring fname, bool batch = false); void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse); void demosaic (const RAWParams &raw); - 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 retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, 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, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, 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 (); @@ -196,7 +196,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, 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(float** luminance, float **originalLuminance, float **exLuminance, LUTf & mapcurve, bool &mapcontlutili, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); void HLRecovery_inpaint (float** red, float** green, float** blue); static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval); static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]); diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 6a2925be9..10f911529 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -465,6 +465,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = { RETINEX, // EvLradius RETINEX, // EvmapMethod DEMOSAIC, // EvRetinexmapcurve - DEMOSAIC // EvviewMethod + DEMOSAIC, // EvviewMethod + RETINEX // EvRetinexgaintransmission + }; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 9ae940980..9916c9f38 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -129,15 +129,16 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p LUTf mapcurve (65536, 0); LUTu dummy; RetinextransmissionCurve dehatransmissionCurve; + RetinexgaintransmissionCurve dehagaintransmissionCurve; 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, mapcurve, dehatransmissionCurve, dehacontlutili, mapcontlutili, useHsl, dummy, dummy ); + imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, dehacontlutili, mapcontlutili, useHsl, dummy, dummy ); float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax; - imgsrc->retinex( params.icm, params.retinex, params.toneCurve, cdcurve, mapcurve, dehatransmissionCurve, conversionBuffer, dehacontlutili, mapcontlutili, useHsl, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, dummy); + imgsrc->retinex( params.icm, params.retinex, params.toneCurve, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, 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 062c61ba2..1183b8260 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -76,6 +76,7 @@ void ParamsEdited::set (bool v) // retinex.grbl = v; retinex.medianmap = v; retinex.transmissionCurve = v; + retinex.gaintransmissionCurve = v; retinex.highlights = v; retinex.htonalwidth = v; retinex.shadows = v; @@ -544,6 +545,7 @@ void ParamsEdited::initFrom (const std::vector 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.gaintransmissionCurve = retinex.gaintransmissionCurve && p.retinex.gaintransmissionCurve == other.retinex.gaintransmissionCurve; 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; @@ -1088,6 +1090,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.retinex.transmissionCurve = mods.retinex.transmissionCurve; } + if (retinex.gaintransmissionCurve) { + toEdit.retinex.gaintransmissionCurve = mods.retinex.gaintransmissionCurve; + } + if (retinex.retinexMethod) { toEdit.retinex.retinexMethod = mods.retinex.retinexMethod; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 261da1753..8e21ef5ad 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -81,6 +81,7 @@ public: // bool grbl; bool method; bool transmissionCurve; + bool gaintransmissionCurve; bool cdcurve; bool mapcurve; bool cdHcurve; diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index 561a28edf..bad21cfe7 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -161,7 +161,7 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), 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)); + offs = Gtk::manage (new Adjuster (M("TP_RETINEX_OFFSET"), -1000, 5000, 1, 0)); // vart = Gtk::manage (new Adjuster (M("TP_RETINEX_VARIANCE"), 50, 500, 1, 125)); limd = Gtk::manage (new Adjuster (M("TP_RETINEX_THRESHOLD"), 2, 100, 1, 8)); baselog = Gtk::manage (new Adjuster (M("TP_RETINEX_BASELOG"), 1.1, 100., 0.001, 2.718)); @@ -175,6 +175,21 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), limd->set_tooltip_markup (M("TP_RETINEX_THRESHOLD_TOOLTIP")); baselog->set_tooltip_markup (M("TP_RETINEX_BASELOG_TOOLTIP")); + // Gain Transmission map curve + gaintransmissionCurve = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_GAINTRANSMISSION")); + gaintransmissionCurve->setCurveListener (this); + +// std::vector defaultCurve; + rtengine::RetinexParams::getDefaultgaintransmissionCurve(defaultCurve); + gaintransmissionShape = static_cast(gaintransmissionCurve->addCurve(CT_Flat, "", NULL, false)); + gaintransmissionShape->setIdentityValue(0.); + gaintransmissionShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + gaintransmissionShape->setBottomBarBgGradient(milestones); + gaintransmissionCurve->set_tooltip_markup (M("TP_RETINEX_GAINTRANSMISSION_TOOLTIP")); + + gaintransmissionCurve->curveListComplete(); + + Gtk::Frame *p1Frame; p1Frame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_LABEL_MASK")) ); p1Frame->set_border_width(0); @@ -285,19 +300,34 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), settingsVBox->pack_start (*grads); grads->show (); - settingsVBox->pack_start (*gain); - gain->show (); - - settingsVBox->pack_start (*offs); - offs->show (); - -// settingsVBox->pack_start (*vart); -// vart->show (); - settingsVBox->pack_start (*limd); limd->show (); - // settingsVBox->pack_start (*Gtk::manage (new Gtk::HSeparator())); + settingsVBox->pack_start( *transmissionCurveEditorG, Gtk::PACK_SHRINK, 2); + transmissionCurveEditorG->show(); + + settingsVBox->pack_start (*medianmap); + medianmap->show (); + + // settingsVBox->pack_start (*gain); + // gain->show (); + + +// settingsVBox->pack_start (*vart); +// vart->show (); + Gtk::VBox *gainBox = Gtk::manage (new Gtk::VBox()); + + Gtk::HSeparator *separator = Gtk::manage (new Gtk::HSeparator()); + settingsVBox->pack_start(*separator, Gtk::PACK_SHRINK, 2); + gainFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_GAINOFFS"))); + + gainBox->pack_start( *gaintransmissionCurve, Gtk::PACK_SHRINK, 2); + gaintransmissionCurve->show(); + + gainBox->pack_start (*offs); + offs->show (); + gainFrame->add(*gainBox); + settingsVBox->pack_start (*gainFrame); viewbox->pack_start(*viewMethod); // settingsVBox->pack_start(*viewbox); @@ -334,11 +364,7 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), // grbl->show (); // settingsVBox->pack_start (*Gtk::manage (new Gtk::HSeparator())); - settingsVBox->pack_start( *transmissionCurveEditorG, Gtk::PACK_SHRINK, 2); - transmissionCurveEditorG->show(); - settingsVBox->pack_start (*medianmap); - medianmap->show (); expsettings->add(*settingsVBox); neutrHBox = Gtk::manage (new Gtk::HBox ()); @@ -495,6 +521,7 @@ Retinex::~Retinex() delete curveEditorGD; delete curveEditorGDH; delete transmissionCurveEditorG; + delete gaintransmissionCurve; delete curveEditorGH; delete curveEditormap; @@ -526,6 +553,7 @@ void Retinex::neutral_pressed () retinexcolorspace->set_active(0); gammaretinex->set_active(0); transmissionShape->reset(); + gaintransmissionShape->reset(); cdshape->reset(); cdshapeH->reset(); lhshape->reset(); @@ -690,6 +718,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) cdshape->setUnChanged (!pedited->retinex.cdcurve); cdshapeH->setUnChanged (!pedited->retinex.cdHcurve); transmissionShape->setUnChanged (!pedited->retinex.transmissionCurve); + gaintransmissionShape->setUnChanged (!pedited->retinex.gaintransmissionCurve); lhshape->setUnChanged (!pedited->retinex.lhcurve); mapshape->setUnChanged (!pedited->retinex.mapcurve); @@ -810,6 +839,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) mapMethodConn.block(false); viewMethodConn.block(false); transmissionShape->setCurve (pp->retinex.transmissionCurve); + gaintransmissionShape->setCurve (pp->retinex.gaintransmissionCurve); enableListener (); @@ -840,6 +870,7 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) pp->retinex.cdHcurve = cdshapeH->getCurve (); pp->retinex.mapcurve = mapshape->getCurve (); pp->retinex.transmissionCurve = transmissionShape->getCurve (); + pp->retinex.gaintransmissionCurve = gaintransmissionShape->getCurve (); pp->retinex.enabled = getEnabled(); pp->retinex.medianmap = medianmap->get_active(); @@ -875,6 +906,7 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) pedited->retinex.cdcurve = !cdshape->isUnChanged (); pedited->retinex.cdHcurve = !cdshapeH->isUnChanged (); pedited->retinex.transmissionCurve = !transmissionShape->isUnChanged (); + pedited->retinex.gaintransmissionCurve = !gaintransmissionShape->isUnChanged (); pedited->retinex.mapcurve = !mapshape->isUnChanged (); pedited->retinex.enabled = !get_inconsistent(); pedited->retinex.medianmap = !medianmap->get_inconsistent(); @@ -1275,6 +1307,7 @@ void Retinex::autoOpenCurve () cdshape->openIfNonlinear(); cdshapeH->openIfNonlinear(); transmissionShape->openIfNonlinear(); + gaintransmissionShape->openIfNonlinear(); lhshape->openIfNonlinear(); mapshape->openIfNonlinear(); @@ -1290,6 +1323,8 @@ void Retinex::curveChanged (CurveEditor* ce) listener->panelChanged (EvLCDHCurve, M("HISTORY_CUSTOMCURVE")); } else if (ce == transmissionShape) { listener->panelChanged (EvRetinextransmission, M("HISTORY_CUSTOMCURVE")); + } else if (ce == gaintransmissionShape) { + listener->panelChanged (EvRetinexgaintransmission, M("HISTORY_CUSTOMCURVE")); } else if (ce == lhshape) { listener->panelChanged (EvRetinexlhcurve, M("HISTORY_CUSTOMCURVE")); } else if (ce == mapshape) { @@ -1415,6 +1450,7 @@ void Retinex::setBatchMode (bool batchMode) curveEditorGD->setBatchMode (batchMode); curveEditorGDH->setBatchMode (batchMode); transmissionCurveEditorG->setBatchMode (batchMode); + gaintransmissionCurve->setBatchMode (batchMode); curveEditorGH->setBatchMode (batchMode); curveEditormap->setBatchMode (batchMode); diff --git a/rtgui/retinex.h b/rtgui/retinex.h index d24254757..b8034ccb9 100644 --- a/rtgui/retinex.h +++ b/rtgui/retinex.h @@ -76,15 +76,18 @@ protected: Gtk::Label* mMLabels; Gtk::Label* transLabels; Gtk::Label* transLabels2; + Gtk::Frame *gainFrame; DiagonalCurveEditor* cdshape; DiagonalCurveEditor* cdshapeH; DiagonalCurveEditor* mapshape; CurveEditorGroup* transmissionCurveEditorG; + CurveEditorGroup* gaintransmissionCurve; sigc::connection retinexMethodConn, neutralconn, mapMethodConn, viewMethodConn; sigc::connection retinexColorSpaceConn; sigc::connection gammaretinexConn; FlatCurveEditor* transmissionShape; + FlatCurveEditor* gaintransmissionShape; FlatCurveEditor* lhshape; bool lastmedianmap; sigc::connection medianmapConn;