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;