diff --git a/rtdata/languages/default b/rtdata/languages/default
index c8d145390..f4b042ec7 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -670,6 +670,8 @@ HISTORY_MSG_437;Retinex - M - Method
HISTORY_MSG_438;Retinex - M - Equalizer
HISTORY_MSG_439;Retinex - Preview
HISTORY_MSG_440;CbDL - Method
+HISTORY_MSG_441;Retinex - Gain transmission
+HISTORY_MSG_442;Retinex - Scale
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -1668,9 +1670,11 @@ TP_RETINEX_CURVEEDITOR_LH;Strength=f(H)
TP_RETINEX_CURVEEDITOR_LH_TOOLTIP;Strength according to hue Strength=f(H)\nThis curve also acts on chroma when using the "Highlight" retinex method.
TP_RETINEX_CURVEEDITOR_MAP;L=f(L)
TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;This curve can be applied alone or with a Gaussian mask or wavelet mask.\nBeware of artifacts!
+TP_RETINEX_EQUAL;Equalizer
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 Offset (brightness)
TP_RETINEX_GAMMA;Gamma
TP_RETINEX_GAMMA_FREE;Free
TP_RETINEX_GAMMA_HIGH;High
@@ -1688,6 +1692,7 @@ TP_RETINEX_HIGHLIGHT;Highlight threshold
TP_RETINEX_HIGHLIGHT_TOOLTIP;Increase action of High algorithm.\nMay require you to re-adjust "Neighboring pixels" and to increase the "White-point correction" in the Raw tab -> Raw White Points tool.
TP_RETINEX_HSLSPACE_LIN;HSL-Linear
TP_RETINEX_HSLSPACE_LOG;HSL-Logarithmic
+TP_RETINEX_ITERF;Tone mapping
TP_RETINEX_ITER;Iterations (Tone-mapping)
TP_RETINEX_ITER_TOOLTIP;Simulate a tone-mapping operator.\nHigh values increase the processing time.
TP_RETINEX_LABEL;Retinex
@@ -1708,18 +1713,22 @@ 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;Offset (brightness)
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
TP_RETINEX_SLOPE;Free gamma slope
+TP_RETINEX_SKAL;Scale
TP_RETINEX_STRENGTH;Strength
TP_RETINEX_THRESHOLD;Threshold
TP_RETINEX_THRESHOLD_TOOLTIP;Limits in/out.\nIn = image source,\nOut = image gauss.
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_TRANF;Transmission
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 6792df50d..158086cfd 100644
--- a/rtengine/curves.cc
+++ b/rtengine/curves.cc
@@ -1430,6 +1430,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 b0e9d691f..0adc735be 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 2f14c1ded..7434776d5 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -55,7 +55,7 @@ ImProcCoordinator::ImProcCoordinator ()
lhist16(65536), lhist16Cropped(65536),
lhist16CAM(65536), lhist16CroppedCAM(65536),
lhist16CCAM(65536),
- lhist16RETI(65536),
+ lhist16RETI(),
histCropped(65536),
lhist16Clad(65536), lhist16CLlad(65536),
lhist16LClad(65536), lhist16LLClad(65536),
@@ -236,6 +236,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
if (params.retinex.enabled) {
+ lhist16RETI(32768);
lhist16RETI.clear();
imgsrc->retinexPrepareBuffers(params.icm, params.retinex, conversionBuffer, lhist16RETI);
@@ -249,9 +250,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
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);
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 1cd1d56e1..6773e7a12 100644
--- a/rtengine/ipretinex.cc
+++ b/rtengine/ipretinex.cc
@@ -45,10 +45,8 @@
#include "rawimagesource.h"
#include "improcfun.h"
#include "opthelper.h"
-//#define BENCHMARK
#include "StopWatch.h"
-#define MAX_RETINEX_SCALES 8
#define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val )
#define med3(a0,a1,a2,a3,a4,a5,a6,a7,a8,median) { \
@@ -61,13 +59,9 @@ PIX_SORT(pp[3],pp[6]); PIX_SORT(pp[1],pp[4]); PIX_SORT(pp[2],pp[5]); \
PIX_SORT(pp[4],pp[7]); PIX_SORT(pp[4],pp[2]); PIX_SORT(pp[6],pp[4]); \
PIX_SORT(pp[4],pp[2]); median=pp[4];} //pp4 = median
-namespace rtengine
+
+namespace
{
-
-extern const Settings* settings;
-
-static float RetinexScales[MAX_RETINEX_SCALES];
-
void retinex_scales( float* scales, int nscales, int mode, int s, float high)
{
if ( nscales == 1 ) {
@@ -103,6 +97,7 @@ void retinex_scales( float* scales, int nscales, int mode, int s, float high)
}
}
}
+
void mean_stddv2( float **dst, float &mean, float &stddv, int W_L, int H_L, float &maxtr, float &mintr)
{
// summation using double precision to avoid too large summation error for large pictures
@@ -124,14 +119,8 @@ void mean_stddv2( float **dst, float &mean, float &stddv, int W_L, int H_L, floa
sum += dst[i][j];
vsquared += (dst[i][j] * dst[i][j]);
- if ( dst[i][j] > lmax) {
- lmax = dst[i][j] ;
- }
-
- if ( dst[i][j] < lmin) {
- lmin = dst[i][j] ;
- }
-
+ lmax = dst[i][j] > lmax ? dst[i][j] : lmax;
+ lmin = dst[i][j] < lmin ? dst[i][j] : lmin;
}
#ifdef _OPENMP
@@ -149,82 +138,30 @@ void mean_stddv2( float **dst, float &mean, float &stddv, int W_L, int H_L, floa
stddv = (float)sqrt(stddv);
}
-
-
-
-
-
-void mean_stddv( float **dst, float &mean, float &stddv, int W_L, int H_L, const float factor, float &maxtr, float &mintr)
-
-{
- // summation using double precision to avoid too large summation error for large pictures
- double vsquared = 0.f;
- double sum = 0.f;
- maxtr = 0.f;
- mintr = 0.f;
-#ifdef _OPENMP
- #pragma omp parallel
-#endif
- {
- float lmax = 0.f, lmin = 0.f;
-
-#ifdef _OPENMP
- #pragma omp for reduction(+:sum,vsquared) // this can lead to differences, but parallel summation is more accurate
-#endif
-
- for (int i = 0; i < H_L; i++ )
- for (int j = 0; j < W_L; j++) {
- sum += dst[i][j];
- vsquared += (dst[i][j] * dst[i][j]);
-
- if ( dst[i][j] > lmax) {
- lmax = dst[i][j] ;
- }
-
- if ( dst[i][j] < lmin) {
- lmin = dst[i][j] ;
- }
-
- }
-
-#ifdef _OPENMP
- #pragma omp critical
-#endif
- {
- maxtr = maxtr > lmax ? maxtr : lmax;
- mintr = mintr < lmin ? mintr : lmin;
- }
-
- }
-
- sum *= factor;
- maxtr *= factor;
- mintr *= factor;
- vsquared *= (factor * factor);
- mean = sum / (float) (W_L * H_L);
- vsquared /= (float) W_L * H_L;
- stddv = ( vsquared - (mean * mean) );
- 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)
+
+namespace rtengine
+{
+
+extern const Settings* settings;
+
+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;
- //float mini, delta, maxi;
float delta;
- float eps = 2.f;
+ constexpr float eps = 2.f;
bool useHsl = deh.retinexcolorspace == "HSLLOG";
bool useHslLin = deh.retinexcolorspace == "HSLLIN";
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 iter = deh.iter;
- int gradient = deh.scal;
+ int gradient = deh.scal;
int scal = 3;//disabled scal
- int nei = (int) 2.8f * deh.neigh; //def = 220
+ int nei = (int) (2.8f * deh.neigh); //def = 220
float vart = (float)deh.vart / 100.f;//variance
float gradvart = (float)deh.grad;
float gradstr = (float)deh.grads;
@@ -233,11 +170,10 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
limD = pow(limD, 1.7f);//about 2500 enough
limD *= useHslLin ? 10.f : 1.f;
float ilimD = 1.f / limD;
- int moderetinex = 2; // default to 2 ( deh.retinexMethod == "high" )
float hig = ((float) deh.highl) / 100.f;
- bool higplus = false ;
float elogt;
float hl = deh.baselog;
+ scal = deh.skal;
if(hl >= 2.71828f) {
elogt = 2.71828f + SQR(SQR(hl - 2.71828f));
@@ -249,52 +185,45 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
int W_L = width;
float *tran[H_L] ALIGNED16;
- float *tranBuffer;
- int viewmet = 0;
+ float *tranBuffer = nullptr;
elogt = 2.71828f;//disabled baselog
- FlatCurve* shcurve = NULL;//curve L=f(H)
bool lhutili = false;
- if (deh.enabled) {
- shcurve = new FlatCurve(deh.lhcurve);
+ FlatCurve* shcurve = new FlatCurve(deh.lhcurve); //curve L=f(H)
- if (!shcurve || shcurve->isIdentity()) {
- if (shcurve) {
- delete shcurve;
- shcurve = NULL;
- }
- } else {
- lhutili = true;
+ if (!shcurve || shcurve->isIdentity()) {
+ if (shcurve) {
+ delete shcurve;
+ shcurve = nullptr;
}
+ } else {
+ lhutili = true;
}
+ bool higplus = false ;
+ int moderetinex = 2; // default to 2 ( deh.retinexMethod == "high" )
+
if(deh.retinexMethod == "highliplus") {
higplus = true;
- }
-
- if (deh.retinexMethod == "uni") {
+ moderetinex = 3;
+ } else if (deh.retinexMethod == "uni") {
moderetinex = 0;
- }
-
- if (deh.retinexMethod == "low") {
+ } else if (deh.retinexMethod == "low") {
moderetinex = 1;
- }
-
- if (deh.retinexMethod == "highli" || deh.retinexMethod == "highliplus") {
+ } else { /*if (deh.retinexMethod == "highli") */
moderetinex = 3;
}
- for(int it = 1; it < iter + 1; it++) { //iter nb max of iterations
- float aahi = 49.f / 99.f; ////reduce sensibility 50%
- float bbhi = 1.f - aahi;
- float high;
- high = bbhi + aahi * (float) deh.highl;
+ constexpr float aahi = 49.f / 99.f; ////reduce sensibility 50%
+ constexpr float bbhi = 1.f - aahi;
+
+ for(int it = 1; it < iter + 1; it++) { //iter nb max of iterations
+ float high = bbhi + aahi * (float) deh.highl;
- float grads;
float grad = 1.f;
- float sc = 3.f;
+ float sc = scal;
if(gradient == 0) {
grad = 1.f;
@@ -338,6 +267,23 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
sc = 3.f;
}
+ if(iter == 1) {
+ sc = scal;
+ } else {
+ //adjust sc in function of choice of scale by user if iterations
+ if(scal < 3) {
+ sc -= 1;
+
+ if(sc < 1.f) {//avoid 0
+ sc = 1.f;
+ }
+ }
+
+ if(scal > 4) {
+ sc += 1;
+ }
+ }
+
float varx;
float limdx, ilimdx;
@@ -366,7 +312,6 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
scal = round(sc);
- float strengthx;
float ks = 1.f;
if(gradstr != 0) {
@@ -397,7 +342,10 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
}
- strengthx = ks * strength;
+ float strengthx = ks * strength;
+
+ constexpr auto maxRetinexScales = 8;
+ float RetinexScales[maxRetinexScales];
retinex_scales( RetinexScales, scal, moderetinex, nei / grad, high );
@@ -412,39 +360,28 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
int shHighlights = deh.highlights;
int shShadows = deh.shadows;
+
int mapmet = 0;
if(deh.mapMethod == "map") {
mapmet = 2;
- }
-
- if(deh.mapMethod == "mapT") {
+ } else if(deh.mapMethod == "mapT") {
mapmet = 3;
- }
-
- /*if(deh.mapMethod == "curv") {
- mapmet = 1;
- }*/
-
- if(deh.mapMethod == "gaus") {
+ } else if(deh.mapMethod == "gaus") {
mapmet = 4;
}
const double shradius = mapmet == 4 ? (double) deh.radius : 40.;
+ int viewmet = 0;
+
if(deh.viewMethod == "mask") {
viewmet = 1;
- }
-
- if(deh.viewMethod == "tran") {
+ } else if(deh.viewMethod == "tran") {
viewmet = 2;
- }
-
- if(deh.viewMethod == "tran2") {
+ } else if(deh.viewMethod == "tran2") {
viewmet = 3;
- }
-
- if(deh.viewMethod == "unsharp") {
+ } else if(deh.viewMethod == "unsharp") {
viewmet = 4;
}
@@ -538,6 +475,12 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
#endif
if(mapmet > 0 && mapcontlutili && it == 1) {
+ // TODO: When rgbcurvespeedup branch is merged into master we can simplify the code by
+ // 1) in rawimagesource.retinexPrepareCurves() insert
+ // mapcurve *= 0.5f;
+ // after
+ // CurveFactory::mapcurve (mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI);
+ // 2) remove the division by 2.f from the code 7 lines below this line
#ifdef _OPENMP
#pragma omp parallel for
#endif
@@ -551,21 +494,21 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
if(((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) {
-
-
+ float hWeight = (100.f - shHighlights) / 100.f;
+ float sWeight = (100.f - shShadows) / 100.f;
#ifdef _OPENMP
- #pragma omp parallel for
+ #pragma omp parallel for schedule(dynamic,16)
#endif
for (int i = 0; i < H_L; i++) {
for (int j = 0; j < W_L; j++) {
- double mapval = 1.0 + shmap->map[i][j];
- double factor = 1.0;
+ float mapval = 1.f + shmap->map[i][j];
+ float factor = 1.f;
if (mapval > h_th) {
- factor = (h_th + (100.0 - shHighlights) * (mapval - h_th) / 100.0) / mapval;
+ factor = (h_th + hWeight * (mapval - h_th)) / mapval;
} else if (mapval < s_th) {
- factor = (s_th - (100.0 - shShadows) * (s_th - mapval) / 100.0) / mapval;
+ factor = (s_th - sWeight * (s_th - mapval)) / mapval;
}
out[i][j] *= factor;
@@ -613,10 +556,9 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
}
- shmap = NULL;
+ shmap = nullptr;
delete [] buffer;
- //delete [] outBuffer;
delete [] srcBuffer;
mean = 0.f;
@@ -641,6 +583,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
bmax *= 500.f;
amin *= 500.f;
bmin *= 500.f;
+
#ifdef _OPENMP
#pragma omp parallel
#endif
@@ -660,6 +603,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
absciss = amin * luminance[i][j] + bmin;
}
+ //TODO : move multiplication by 4.f and subtraction of 1.f inside the curve
luminance[i][j] *= (-1.f + 4.f * dehatransmissionCurve[absciss]); //new transmission
if(viewmet == 3 || viewmet == 2) {
@@ -733,7 +677,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,34 +687,80 @@ 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 cdmax = -999999.f, cdmin = 999999.f;
-
#ifdef _OPENMP
- #pragma omp for
+ #pragma omp for schedule(dynamic,16) nowait
#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(cd > cdmax) {
- cdmax = cd;
+ if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) {
+ float absciss;
+
+ 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;
+ // TODO : move multiplication by 2.f inside the curve
+ gan = 2.f * (dehagaintransmissionCurve[absciss]); //new gain function transmission
+ } else {
+ gan = 0.5f;
}
- if(cd < cdmin) {
- cdmin = cd;
- }
+ float cd = gan * cdfactor * ( luminance[i][j] ) + offse;
+
+ cdmax = cd > cdmax ? cd : cdmax;
+ cdmin = cd < cdmin ? cd : cdmin;
float str = strengthx;
- if(lhutili && it == 1) { // S=f(H)
+ if(lhutili && it == 1) { // S=f(H)
{
float HH = exLuminance[i][j];
float valparam;
@@ -784,31 +775,23 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
}
- if(exLuminance[i][j] > 65535.f * hig && higplus) {
+ if(higplus && exLuminance[i][j] > 65535.f * hig) {
str *= hig;
}
if(viewmet == 0) {
- luminance[i][j] = clipretinex( cd, 0.f, 32768.f ) * str + (1.f - str) * originalLuminance[i][j];
- }
-
- if(viewmet == 1) {
+ luminance[i][j] = intp(str, clipretinex( cd, 0.f, 32768.f ), originalLuminance[i][j]);
+ } else if(viewmet == 1) {
luminance[i][j] = out[i][j];
- }
-
- if(viewmet == 4) {
- luminance[i][j] = (1.f + str) * originalLuminance[i][j] - str * out[i][j]; //unsharp
- }
-
- if(viewmet == 2) {
+ } else if(viewmet == 4) {
+ luminance[i][j] = originalLuminance[i][j] + str * (originalLuminance[i][j] - out[i][j]);//unsharp
+ } else if(viewmet == 2) {
if(tran[i][j] <= mean) {
luminance[i][j] = azb + aza * tran[i][j]; //auto values
} else {
luminance[i][j] = bzb + bza * tran[i][j];
}
- }
-
- if(viewmet == 3) {
+ } else { /*if(viewmet == 3) */
luminance[i][j] = 1000.f + tran[i][j] * 700.f; //arbitrary values to help display log values which are between -20 to + 30 - usage values -4 + 5
}
@@ -823,23 +806,23 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
}
+
delete [] outBuffer;
- outBuffer = NULL;
+ outBuffer = nullptr;
//printf("cdmin=%f cdmax=%f\n",minCD, maxCD);
Tmean = mean;
Tsigma = stddv;
Tmin = mintr;
Tmax = maxtr;
-
- if (shcurve && it == 1) {
+ if (shcurve) {
delete shcurve;
+ shcurve = nullptr;
}
}
- if(viewmet == 3 || viewmet == 2) {
+ if(tranBuffer) {
delete [] tranBuffer;
- tranBuffer = NULL;
}
}
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index 3d4f90af1..62d2a4ac1 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -467,6 +467,8 @@ enum ProcEvent {
EvRetinexmapcurve = 437,
EvviewMethod = 438,
EvcbdlMethod = 439,
+ EvRetinexgaintransmission = 440,
+ EvLskal = 441,
NUMOFEVENTS
};
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index d3b12adcd..67b02a650 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -121,7 +121,7 @@ RetinexParams::RetinexParams ()
void RetinexParams::getDefaulttransmissionCurve(std::vector &curve)
{
- double v[12] = { 0.00, 0.34, 0.35, 0.35,
+ double v[12] = { 0.00, 0.50, 0.35, 0.35,
0.60, 0.75, 0.35, 0.35,
1.00, 0.50, 0.35, 0.35,
};
@@ -134,6 +134,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()
{
@@ -158,7 +175,7 @@ void RetinexParams::setDefaults()
radius = 40;
baselog = 2.71828;
-// grbl = 50;
+ skal = 3;
retinexMethod = "high";
mapMethod = "none";
viewMethod = "none";
@@ -173,13 +190,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);
+
}
@@ -1521,9 +1541,9 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
keyFile.set_double ("Retinex", "baselog", retinex.baselog);
}
-// if (!pedited || pedited->retinex.grbl) {
-// keyFile.set_integer ("Retinex", "grbl", retinex.grbl);
-// }
+ if (!pedited || pedited->retinex.skal) {
+ keyFile.set_integer ("Retinex", "skal", retinex.skal);
+ }
if (!pedited || pedited->retinex.retinexMethod) {
keyFile.set_string ("Retinex", "RetinexMethod", retinex.retinexMethod);
@@ -1590,6 +1610,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);
@@ -4057,14 +4082,14 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited)
}
}
- /* if (keyFile.has_key ("Retinex", "grbl")) {
- retinex.grbl = keyFile.get_integer ("Retinex", "grbl");
+ if (keyFile.has_key ("Retinex", "skal")) {
+ retinex.skal = keyFile.get_integer ("Retinex", "skal");
+
+ if (pedited) {
+ pedited->retinex.skal = true;
+ }
+ }
- if (pedited) {
- pedited->retinex.grbl = true;
- }
- }
- */
if (keyFile.has_key ("Retinex", "CDCurve")) {
retinex.cdcurve = keyFile.get_double_list ("Retinex", "CDCurve");
@@ -4146,6 +4171,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;
+ }
+ }
+
}
@@ -7551,6 +7586,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
@@ -7569,7 +7605,7 @@ bool ProcParams::operator== (const ProcParams& other)
&& retinex.radius == other.retinex.radius
&& retinex.baselog == other.retinex.baselog
-// && retinex.grbl == other.retinex.grbl
+ && retinex.skal == other.retinex.skal
&& retinex.offs == other.retinex.offs
&& retinex.retinexMethod == other.retinex.retinexMethod
&& retinex.mapMethod == other.retinex.mapMethod
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 7946ce4d9..7f30f0cc9 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;
@@ -308,11 +310,13 @@ public:
int limd;
int highl;
double baselog;
-// int grbl;
+ int skal;
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 1a4e0dbb5..2780c033f 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1764,7 +1764,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
LCPProfile *pLCPProf = lcpStore->getProfile(lensProf.lcpFile);
if (pLCPProf) { // don't check focal length to allow distortion correction for lenses without chip, also pass dummy focal length 1 in case of 0
- LCPMapper map(pLCPProf, max(idata->getFocalLen(),1.0), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1);
+ LCPMapper map(pLCPProf, max(idata->getFocalLen(), 1.0), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1);
#ifdef _OPENMP
#pragma omp parallel for
@@ -1970,7 +1970,6 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
LUTf *retinexgamtab;//gamma before and after Retinex to restore tones
LUTf lutTonereti;
- lutTonereti(65536);
if(retinexParams.gammaretinex == "low") {
retinexgamtab = &(Color::gammatab_115_2);
@@ -1986,24 +1985,33 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
double gamm2 = retinexParams.gam;
if(gamm2 < 1.) {
- pwr = 1. / pwr;
- gamm = 1. / gamm;
+ std::swap(pwr, gamm);
}
int mode = 0, imax = 0;
Color::calcGamma(pwr, ts, mode, imax, g_a0, g_a1, g_a2, g_a3, g_a4, g_a5); // call to calcGamma with selected gamma and slope
// printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4);
+ double start;
+ double add;
+
+ if(gamm2 < 1.) {
+ start = g_a2;
+ add = g_a4;
+ } else {
+ start = g_a3;
+ add = g_a4;
+ }
+
+ double mul = 1. + g_a4;
+
+ lutTonereti(65536);
+
for (int i = 0; i < 65536; i++) {
double val = (i) / 65535.;
- double start = g_a3;
- double add = g_a4;
- double mul = 1. + g_a4;
double x;
if(gamm2 < 1.) {
- start = g_a2;
- add = g_a4;
x = Color::igammareti (val, gamm, start, ts, mul , add);
} else {
x = Color::gammareti (val, gamm, start, ts, mul , add);
@@ -2055,6 +2063,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
}
*/
if(retinexParams.gammaretinex != "none" && retinexParams.str != 0) {//gamma
+
#ifdef _OPENMP
#pragma omp parallel for
#endif
@@ -2083,7 +2092,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
if(lhist16RETI)
{
- lhist16RETIThr(32769, 0);
+ lhist16RETIThr(lhist16RETI.getSize());
lhist16RETIThr.clear();
}
@@ -2101,7 +2110,6 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
for (; j < W - border - 3; j += 4) {
vfloat H, S, L;
- int pos;
Color::rgb2hsl(LVFU(red[i][j]), LVFU(green[i][j]), LVFU(blue[i][j]), H, S, L);
STVFU(conversionBuffer[0][i - border][j - border], H);
STVFU(conversionBuffer[1][i - border][j - border], S);
@@ -2111,7 +2119,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
if(lhist16RETI) {
for(int p = 0; p < 4; p++) {
- pos = (int) clipretinex( conversionBuffer[2][i - border][j - border + p], 0.f, 32768.f);//histogram in curve HSL
+ int pos = ( conversionBuffer[2][i - border][j - border + p]);//histogram in curve HSL
lhist16RETIThr[pos]++;
}
}
@@ -2121,14 +2129,13 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
for (; j < W - border; j++) {
float H, S, L;
- int pos;
//rgb=>lab
Color::rgb2hslfloat(red[i][j], green[i][j], blue[i][j], conversionBuffer[0][i - border][j - border], conversionBuffer[1][i - border][j - border], L);
L *= 32768.f;
conversionBuffer[2][i - border][j - border] = L;
if(lhist16RETI) {
- pos = (int) clipretinex(L, 0, 32768);
+ int pos = L;
lhist16RETIThr[pos]++;
}
}
@@ -2139,10 +2146,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
{
if(lhist16RETI)
{
- // Add per Thread LUT to global LUT
- for(int i = 0; i < 32769; i++) {
- lhist16RETI[i] += lhist16RETIThr[i];
- }
+ lhist16RETI += lhist16RETIThr; // Add per Thread LUT to global LUT
}
}
#endif
@@ -2150,10 +2154,10 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
}
} else {
TMatrix wprof = iccStore->workingSpaceMatrix (cmp.working);
- double wp[3][3] = {
- {wprof[0][0], wprof[0][1], wprof[0][2]},
- {wprof[1][0], wprof[1][1], wprof[1][2]},
- {wprof[2][0], wprof[2][1], wprof[2][2]}
+ float wp[3][3] = {
+ {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])},
+ {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])},
+ {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])}
};
// Conversion rgb -> lab is hard to vectorize because it uses a lut (that's not the main problem)
@@ -2166,25 +2170,19 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
LUTu lhist16RETIThr;
if(lhist16RETI) {
- lhist16RETIThr(32769, 0);
+ lhist16RETIThr(lhist16RETI.getSize());
lhist16RETIThr.clear();
}
#ifdef _OPENMP
- #pragma omp for
+ #pragma omp for schedule(dynamic,16)
#endif
for (int i = border; i < H - border; i++ )
for (int j = border; j < W - border; j++) {
float X, Y, Z, L, aa, bb;
- int pos;
- float R_, G_, B_;
- R_ = red[i][j];
- G_ = green[i][j];
- B_ = blue[i][j];
- float k;
//rgb=>lab
- Color::rgbxyz(R_, G_, B_, X, Y, Z, wp);
+ Color::rgbxyz(red[i][j], green[i][j], blue[i][j], X, Y, Z, wp);
//convert Lab
Color::XYZ2Lab(X, Y, Z, L, aa, bb);
conversionBuffer[0][i - border][j - border] = aa;
@@ -2195,7 +2193,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
// if(R_>40000.f && G_ > 30000.f && B_ > 30000.f) conversionBuffer[3][i - border][j - border] = R_;
// else conversionBuffer[3][i - border][j - border] = 0.f;
if(lhist16RETI) {
- pos = (int) clipretinex(L, 0, 32768);
+ int pos = L;
lhist16RETIThr[pos]++;//histogram in Curve Lab
}
}
@@ -2204,10 +2202,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
#pragma omp critical
{
if(lhist16RETI) {
- // Add per Thread LUT to global LUT
- for(int i = 0; i < 32769; i++) {
- lhist16RETI[i] += lhist16RETIThr[i];
- }
+ lhist16RETI += lhist16RETIThr; // Add per Thread LUT to global LUT
}
}
#endif
@@ -2219,7 +2214,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");
@@ -2231,13 +2226,11 @@ 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;
t4.set();
@@ -2265,23 +2258,29 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
int mode = 0, imax = 0;
if(gamm2 < 1.) {
- pwr = 1. / pwr;
- gamm = 1. / gamm;
+ std::swap(pwr, gamm);
}
Color::calcGamma(pwr, ts, mode, imax, g_a0, g_a1, g_a2, g_a3, g_a4, g_a5); // call to calcGamma with selected gamma and slope
+ double mul = 1. + g_a4;
+ double add;
+ double start;
+
+ if(gamm2 < 1.) {
+ start = g_a3;
+ add = g_a3;
+ } else {
+ add = g_a4;
+ start = g_a2;
+ }
+
// printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4);
for (int i = 0; i < 65536; i++) {
double val = (i) / 65535.;
double x;
- double mul = 1. + g_a4;
- double add = g_a4;
- double start = g_a2;
if(gamm2 < 1.) {
- start = g_a3;
- add = g_a3;
x = Color::gammareti (val, gamm, start, ts, mul , add);
} else {
x = Color::igammareti (val, gamm, start, ts, mul , add);
@@ -2305,11 +2304,10 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
float val;
if(dehacontlutili && histLRETI) {
- hist16RET(32769, 0);
+ hist16RET(32768);
hist16RET.clear();
histLRETI.clear();
- dLcurve(32769, 0);
- dLcurve.clear();
+ dLcurve(32768);
}
FlatCurve* chcurve = NULL;//curve c=f(H)
@@ -2337,8 +2335,8 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
// one LUT per thread
LUTu hist16RETThr;
- if(dehacontlutili && histLRETI) {
- hist16RETThr(32769, 0);
+ if(hist16RET) {
+ hist16RETThr(hist16RET.getSize());
hist16RETThr.clear();
}
@@ -2352,7 +2350,7 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
LBuffer[i][j] = cdcurve[2.f * temp[i][j]] / 2.f;
if(histLRETI) {
- int pos = (int) clipretinex(LBuffer[i][j], 0.f, 32768.f);
+ int pos = LBuffer[i][j];
hist16RETThr[pos]++; //histogram in Curve
}
}
@@ -2365,29 +2363,29 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
#pragma omp critical
#endif
{
- if(dehacontlutili && histLRETI) {
- // Add per Thread LUT to global LUT
- for(int i = 0; i < 32769; i++) {
- hist16RET[i] += hist16RETThr[i];
- }
+ if(hist16RET) {
+ hist16RET += hist16RETThr; // Add per Thread LUT to global LUT
}
}
}
- if(dehacontlutili && histLRETI) {//update histogram
+ if(hist16RET) {//update histogram
+ // TODO : When rgbcurvesspeedup branch is merged into master, replace this by the following 1-liner
+ // hist16RET.compressTo(histLRETI);
+ // also remove declaration and init of dLcurve some lines above then and finally remove this comment :)
for (int i = 0; i < 32768; i++) {
val = (double)i / 32767.0;
- dLcurve[i] = CLIPD(val);
+ dLcurve[i] = val;
}
for (int i = 0; i < 32768; i++) {
float hval = dLcurve[i];
- int hi = (int)(255.0f * CLIPD(hval));
+ int hi = (int)(255.0f * hval);
histLRETI[hi] += hist16RET[i];
}
}
- 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) {
@@ -2401,7 +2399,6 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
for (; j < W - border; j++) {
float valp;
- float chr;
// if(chutili) { // c=f(H)
{
valp = float((chcurve->getVal(conversionBuffer[3][i - border][j - border]) - 0.5f));
@@ -2450,46 +2447,113 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
// gamut control only in Lab mode
const bool highlight = Tc.hrenabled;
#ifdef _OPENMP
- #pragma omp parallel for
+ #pragma omp parallel
+#endif
+ {
+#ifdef __SSE2__
+ // we need some line buffers to precalculate some expensive stuff using SSE
+ float atan2Buffer[W] ALIGNED16;
+ float sqrtBuffer[W] ALIGNED16;
+ float sincosxBuffer[W] ALIGNED16;
+ float sincosyBuffer[W] ALIGNED16;
+ const vfloat c327d68v = F2V(327.68);
+ const vfloat onev = F2V(1.f);
+#endif // __SSE2__
+#ifdef _OPENMP
+ #pragma omp for
#endif
- for (int i = border; i < H - border; i++ ) {
- for (int j = border; j < W - border; j++) {
+ for (int i = border; i < H - border; i++ ) {
+#ifdef __SSE2__
+ // vectorized precalculation
+ {
+ int j = border;
- float Lprov1 = (LBuffer[i - border][j - border]) / 327.68f;
- float Chprov1 = sqrt(SQR(conversionBuffer[0][i - border][j - border]) + SQR(conversionBuffer[1][i - border][j - border])) / 327.68f;
- float HH = xatan2f(conversionBuffer[1][i - border][j - border], conversionBuffer[0][i - border][j - border]);
- float2 sincosval;
- float valp;
- float chr;
-
- if(chutili) { // c=f(H)
+ for (; j < W - border - 3; j += 4)
{
- valp = float((chcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f));
- Chprov1 *= (1.f + 2.f * valp);
+ vfloat av = LVFU(conversionBuffer[0][i - border][j - border]);
+ vfloat bv = LVFU(conversionBuffer[1][i - border][j - border]);
+ vfloat chprovv = vsqrtf(SQRV(av) + SQRV(bv));
+ STVF(sqrtBuffer[j - border], chprovv / c327d68v);
+ vfloat HHv = xatan2f(bv, av);
+ STVF(atan2Buffer[j - border], HHv);
+ av /= chprovv;
+ bv /= chprovv;
+ vmask selMask = vmaskf_eq(chprovv, ZEROV);
+ STVF(sincosyBuffer[j - border], vself(selMask, onev, av));
+ STVF(sincosxBuffer[j - border], vselfnotzero(selMask, bv));
+ }
+
+ for (; j < W - border; j++)
+ {
+ float aa = conversionBuffer[0][i - border][j - border];
+ float bb = conversionBuffer[1][i - border][j - border];
+ float Chprov1 = sqrt(SQR(aa) + SQR(bb)) / 327.68f;
+ sqrtBuffer[j - border] = Chprov1;
+ float HH = xatan2f(bb, aa);
+ atan2Buffer[j - border] = HH;
+
+ if(Chprov1 == 0.0f) {
+ sincosyBuffer[j - border] = 1.f;
+ sincosxBuffer[j - border] = 0.0f;
+ } else {
+ sincosyBuffer[j - border] = aa / (Chprov1 * 327.68f);
+ sincosxBuffer[j - border] = bb / (Chprov1 * 327.68f);
+ }
}
}
+#endif // __SSE2__
+
+ for (int j = border; j < W - border; j++) {
+ float Lprov1 = (LBuffer[i - border][j - border]) / 327.68f;
+#ifdef __SSE2__
+ float Chprov1 = sqrtBuffer[j - border];
+ float HH = atan2Buffer[j - border];
+ float2 sincosval;
+ sincosval.x = sincosxBuffer[j - border];
+ sincosval.y = sincosyBuffer[j - border];
- sincosval = xsincosf(HH);
- float R, G, B;
-#ifdef _DEBUG
- bool neg = false;
- bool more_rgb = false;
- //gamut control : Lab values are in gamut
- Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb);
#else
- //gamut control : Lab values are in gamut
- Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f);
+ float aa = conversionBuffer[0][i - border][j - border];
+ float bb = conversionBuffer[1][i - border][j - border];
+ float Chprov1 = sqrt(SQR(aa) + SQR(bb)) / 327.68f;
+ float HH = xatan2f(bb, aa);
+ float2 sincosval;// = xsincosf(HH);
+
+ if(Chprov1 == 0.0f) {
+ sincosval.y = 1.f;
+ sincosval.x = 0.0f;
+ } else {
+ sincosval.y = aa / (Chprov1 * 327.68f);
+ sincosval.x = bb / (Chprov1 * 327.68f);
+ }
+
+#endif
+
+ if(chutili) { // c=f(H)
+ float valp = float((chcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f));
+ Chprov1 *= (1.f + 2.f * valp);
+ }
+
+ float R, G, B;
+#ifdef _DEBUG
+ bool neg = false;
+ bool more_rgb = false;
+ //gamut control : Lab values are in gamut
+ Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb);
+#else
+ //gamut control : Lab values are in gamut
+ Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f);
#endif
- conversionBuffer[0][i - border][j - border] = 327.68f * Chprov1 * sincosval.y;
- conversionBuffer[1][i - border][j - border] = 327.68f * Chprov1 * sincosval.x;
- LBuffer[i - border][j - border] = Lprov1 * 327.68f;
+ conversionBuffer[0][i - border][j - border] = 327.68f * Chprov1 * sincosval.y;
+ conversionBuffer[1][i - border][j - border] = 327.68f * Chprov1 * sincosval.x;
+ LBuffer[i - border][j - border] = Lprov1 * 327.68f;
+ }
}
}
-
//end gamut control
#ifdef __SSE2__
vfloat wipv[3][3];
@@ -4300,12 +4364,12 @@ void RawImageSource::hlRecovery (std::string method, float* red, float* green, f
void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr)
{
-BENCHFUN
+ BENCHFUN
histcompr = 3;
histogram(65536 >> histcompr);
histogram.clear();
- const float refwb[3] = {static_cast(refwb_red),static_cast(refwb_green),static_cast(refwb_blue)};
+ const float refwb[3] = {static_cast(refwb_red), static_cast(refwb_green), static_cast(refwb_blue)};
#ifdef _OPENMP
#pragma omp parallel
@@ -4323,11 +4387,11 @@ BENCHFUN
if (ri->getSensorType() == ST_BAYER) {
for (int j = start; j < end; j++) {
- tmphistogram[(int)(refwb[ri->FC(i,j)] * rawData[i][j]) >> histcompr] += 4;
+ tmphistogram[(int)(refwb[ri->FC(i, j)] * rawData[i][j]) >> histcompr] += 4;
}
} else if (ri->getSensorType() == ST_FUJI_XTRANS) {
for (int j = start; j < end; j++) {
- tmphistogram[(int)(refwb[ri->XTRANSFC(i,j)] * rawData[i][j]) >> histcompr] += 4;
+ tmphistogram[(int)(refwb[ri->XTRANSFC(i, j)] * rawData[i][j]) >> histcompr] += 4;
}
} else if (ri->get_colors() == 1) {
for (int j = start; j < end; j++) {
@@ -4354,7 +4418,7 @@ BENCHFUN
// Histogram MUST be 256 in size; gamma is applied, blackpoint and gain also
void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw)
{
-BENCHFUN
+ BENCHFUN
histRedRaw.clear();
histGreenRaw.clear();
histBlueRaw.clear();
@@ -4364,17 +4428,19 @@ BENCHFUN
65535.0f / ri->get_white(3)
};
- const bool fourColours = ri->getSensorType() == ST_BAYER && ((mult[1] != mult[3] || cblacksom[1] != cblacksom[3]) || FC(0,0) == 3 || FC(0,1) == 3 || FC(1,0) == 3 || FC(1,1) == 3);
+ const bool fourColours = ri->getSensorType() == ST_BAYER && ((mult[1] != mult[3] || cblacksom[1] != cblacksom[3]) || FC(0, 0) == 3 || FC(0, 1) == 3 || FC(1, 0) == 3 || FC(1, 1) == 3);
LUTu hist[4];
hist[0](65536);
hist[0].clear();
+
if (ri->get_colors() > 1) {
hist[1](65536);
hist[1].clear();
hist[2](65536);
hist[2].clear();
}
+
if (fourColours) {
hist[3](65536);
hist[3].clear();
@@ -4393,16 +4459,19 @@ BENCHFUN
LUTu tmphist[4];
tmphist[0](65536);
tmphist[0].clear();
+
if (ri->get_colors() > 1) {
tmphist[1](65536);
tmphist[1].clear();
tmphist[2](65536);
tmphist[2].clear();
+
if (fourColours) {
tmphist[3](65536);
tmphist[3].clear();
}
}
+
#ifdef _OPENMP
#pragma omp for nowait
#endif
@@ -4449,9 +4518,11 @@ BENCHFUN
#endif
{
hist[0] += tmphist[0];
+
if (ri->get_colors() > 1) {
hist[1] += tmphist[1];
hist[2] += tmphist[2];
+
if (fourColours) {
hist[3] += tmphist[3];
}
@@ -4463,13 +4534,16 @@ BENCHFUN
int idx;
idx = CLIP((int)Color::gamma(mult[0] * (i - (cblacksom[0]/*+black_lev[0]*/))));
histRedRaw[idx >> 8] += hist[0][i];
+
if (ri->get_colors() > 1) {
idx = CLIP((int)Color::gamma(mult[1] * (i - (cblacksom[1]/*+black_lev[1]*/))));
histGreenRaw[idx >> 8] += hist[1][i];
+
if (fourColours) {
idx = CLIP((int)Color::gamma(mult[3] * (i - (cblacksom[3]/*+black_lev[3]*/))));
histGreenRaw[idx >> 8] += hist[3][i];
}
+
idx = CLIP((int)Color::gamma(mult[2] * (i - (cblacksom[2]/*+black_lev[2]*/))));
histBlueRaw[idx >> 8] += hist[2][i];
}
@@ -4509,6 +4583,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm)
{
BENCHFUN
constexpr double clipHigh = 64000.0;
+
if (ri->get_colors() == 1) {
rm = gm = bm = 1;
return;
@@ -4588,6 +4663,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm)
#ifdef _OPENMP
#pragma omp for schedule(dynamic,16) nowait
#endif
+
for (int i = 32; i < H - 32; i++) {
for (int j = 32; j < W - 32; j++) {
// each loop read 1 rgb triplet value
diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h
index 0dd6c9098..222735432 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 26e8f53d4..5175836e4 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -466,6 +466,9 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
RETINEX, // EvmapMethod
DEMOSAIC, // EvRetinexmapcurve
DEMOSAIC, // EvviewMethod
- ALLNORAW // EvcbdlMethod
+ ALLNORAW, // EvcbdlMethod
+ RETINEX, // EvRetinexgaintransmission
+ RETINEX //EvLskal
+
};
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index b05d517f6..1f64a5ff4 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 1ae650a5f..fba2ef059 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -73,9 +73,10 @@ void ParamsEdited::set (bool v)
retinex.limd = v;
retinex.highl = v;
retinex.baselog = v;
-// retinex.grbl = v;
+ retinex.skal = v;
retinex.medianmap = v;
retinex.transmissionCurve = v;
+ retinex.gaintransmissionCurve = v;
retinex.highlights = v;
retinex.htonalwidth = v;
retinex.shadows = v;
@@ -547,6 +548,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;
@@ -566,7 +568,7 @@ void ParamsEdited::initFrom (const std::vector
retinex.limd = retinex.limd && p.retinex.limd == other.retinex.limd;
retinex.highl = retinex.highl && p.retinex.highl == other.retinex.highl;
retinex.baselog = retinex.baselog && p.retinex.baselog == other.retinex.baselog;
-// retinex.grbl = retinex.grbl && p.retinex.grbl == other.retinex.grbl;
+ retinex.skal = retinex.skal && p.retinex.skal == other.retinex.skal;
retinex.medianmap = retinex.medianmap && p.retinex.medianmap == other.retinex.medianmap;
retinex.highlights = retinex.highlights && p.retinex.highlights == other.retinex.highlights;
retinex.htonalwidth = retinex.htonalwidth && p.retinex.htonalwidth == other.retinex.htonalwidth;
@@ -1093,6 +1095,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;
}
@@ -1165,9 +1171,9 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
toEdit.retinex.baselog = mods.retinex.baselog;
}
-// if (retinex.grbl) {
-// toEdit.retinex.grbl = mods.retinex.grbl;
-// }
+ if (retinex.skal) {
+ toEdit.retinex.skal = mods.retinex.skal;
+ }
if (retinex.gain) {
toEdit.retinex.gain = dontforceSet && options.baBehav[ADDSET_RETI_GAIN] ? toEdit.retinex.gain + mods.retinex.gain : mods.retinex.gain;
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index 8543fbfa8..f8d18ae57 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -78,9 +78,10 @@ public:
bool limd;
bool highl;
bool baselog;
-// bool grbl;
+ bool skal;
bool method;
bool transmissionCurve;
+ bool gaintransmissionCurve;
bool cdcurve;
bool mapcurve;
bool cdHcurve;
diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc
index 820ffe1d7..fead40b88 100644
--- a/rtgui/retinex.cc
+++ b/rtgui/retinex.cc
@@ -54,6 +54,9 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"),
dhbox->pack_start(*retinexcolorspace);
retinexVBox->pack_start(*dhbox);
+ Gtk::VBox *equalVBox = Gtk::manage (new Gtk::VBox());
+
+ equalFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_EQUAL")));
// Histogram equalizer Lab curve
curveEditorGD = new CurveEditorGroup (options.lastRetinexDir, M("TP_RETINEX_CONTEDIT_LAB"));
@@ -161,11 +164,11 @@ 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));
-// grbl = Gtk::manage (new Adjuster (M("TP_RETINEX_HIGHLIGHT3"), 1, 100, 1, 50));
+ baselog = Gtk::manage (new Adjuster (M("TP_RETINEX_BASELOG"), 1., 10., 1., 3.));
+ skal = Gtk::manage (new Adjuster (M("TP_RETINEX_SKAL"), 1, 8, 1, 3));
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"));
@@ -175,6 +178,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);
@@ -251,52 +269,81 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"),
settingsVBox->pack_start (*transLabels2);
transLabels2->show ();
- settingsVBox->pack_start (*curveEditorGD, Gtk::PACK_SHRINK, 4);
+ equalVBox->pack_start (*curveEditorGD, Gtk::PACK_SHRINK, 4);
curveEditorGD->show();
- settingsVBox->pack_start (*curveEditorGDH, Gtk::PACK_SHRINK, 4);
+ equalVBox->pack_start (*curveEditorGDH, Gtk::PACK_SHRINK, 4);
curveEditorGDH->show();
- settingsVBox->pack_start (*curveEditorGH, Gtk::PACK_SHRINK, 4);
+ equalVBox->pack_start (*curveEditorGH, Gtk::PACK_SHRINK, 4);
curveEditorGH->show();
gambox->pack_start(*gammaretinex);
- settingsVBox->pack_start(*gambox);
+ equalVBox->pack_start(*gambox);
gammaretinex->show();
- settingsVBox->pack_start (*gam);
+ equalVBox->pack_start (*gam);
gam->show ();
- settingsVBox->pack_start (*slope);
+ equalVBox->pack_start (*slope);
slope->show ();
+ equalFrame->add(*equalVBox);
+ settingsVBox->pack_start (*equalFrame);
- settingsVBox->pack_start (*iter);
+
+ Gtk::VBox *iterVBox = Gtk::manage (new Gtk::VBox());
+
+ iterFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_ITERF")));
+
+ iterVBox->pack_start (*iter);
iter->show ();
- settingsVBox->pack_start (*scal);
+ iterVBox->pack_start (*scal);
scal->show ();
- settingsVBox->pack_start (*grad);
+ iterVBox->pack_start (*grad);
grad->show ();
- settingsVBox->pack_start (*grads);
+ iterVBox->pack_start (*grads);
grads->show ();
- settingsVBox->pack_start (*gain);
- gain->show ();
+ iterFrame->add(*iterVBox);
+ settingsVBox->pack_start (*iterFrame);
- settingsVBox->pack_start (*offs);
- offs->show ();
+ Gtk::VBox *tranVBox = Gtk::manage (new Gtk::VBox());
-// settingsVBox->pack_start (*vart);
-// vart->show ();
+ tranFrame = Gtk::manage (new Gtk::Frame(M("TP_RETINEX_TRANF")));
- settingsVBox->pack_start (*limd);
+ tranVBox->pack_start( *transmissionCurveEditorG, Gtk::PACK_SHRINK, 2);
+ transmissionCurveEditorG->show();
+
+ tranVBox->pack_start (*skal);
+ skal->show ();
+
+ tranVBox->pack_start (*limd);
limd->show ();
- // settingsVBox->pack_start (*Gtk::manage (new Gtk::HSeparator()));
+ tranVBox->pack_start (*medianmap);
+ medianmap->show ();
+
+ tranFrame->add(*tranVBox);
+ settingsVBox->pack_start (*tranFrame);
+
+ 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);
@@ -326,18 +373,12 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"),
// settingsVBox->pack_start (*highl);
// highl->show ();
-// settingsVBox->pack_start (*baselog);
-// baselog->show ();
+// settingsVBox->pack_start (*baselog);
+// baselog->show ();
-// settingsVBox->pack_start (*grbl);
-// 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 ());
@@ -468,12 +509,12 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"),
s_tonalwidth->delay = 200;
}
- /* grbl->setAdjusterListener (this);
+ skal->setAdjusterListener (this);
+
+ if (skal->delay < 200) {
+ skal->delay = 200;
+ }
- if (grbl->delay < 200) {
- grbl->delay = 200;
- }
- */
pack_start (*retinexVBox);
p1Frame->add(*p1VBox);
pack_start (*p1Frame, Gtk::PACK_EXPAND_WIDGET, 4);
@@ -494,6 +535,7 @@ Retinex::~Retinex()
delete curveEditorGD;
delete curveEditorGDH;
delete transmissionCurveEditorG;
+ delete gaintransmissionCurve;
delete curveEditorGH;
delete curveEditormap;
@@ -525,6 +567,7 @@ void Retinex::neutral_pressed ()
retinexcolorspace->set_active(0);
gammaretinex->set_active(0);
transmissionShape->reset();
+ gaintransmissionShape->reset();
cdshape->reset();
cdshapeH->reset();
lhshape->reset();
@@ -656,7 +699,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
limd->setEditedState (pedited->retinex.limd ? Edited : UnEdited);
highl->setEditedState (pedited->retinex.highl ? Edited : UnEdited);
baselog->setEditedState (pedited->retinex.baselog ? Edited : UnEdited);
-// grbl->setEditedState (pedited->retinex.grbl ? Edited : UnEdited);
+ skal->setEditedState (pedited->retinex.skal ? Edited : UnEdited);
set_inconsistent (multiImage && !pedited->retinex.enabled);
medianmap->set_inconsistent (!pedited->retinex.medianmap);
radius->setEditedState (pedited->retinex.radius ? Edited : UnEdited);
@@ -689,6 +732,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);
@@ -715,7 +759,8 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
shadows->setValue (pp->retinex.shadows);
s_tonalwidth->setValue (pp->retinex.stonalwidth);
-// grbl->setValue (pp->retinex.grbl);
+ skal->setValue (pp->retinex.skal);
+
if(pp->retinex.iter == 1) {
grad->set_sensitive(false);
scal->set_sensitive(false);
@@ -809,6 +854,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 ();
@@ -833,12 +879,13 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited)
pp->retinex.limd = (int)limd->getValue ();
pp->retinex.highl = (int)highl->getValue ();
pp->retinex.baselog = baselog->getValue ();
-// pp->retinex.grbl = (int)grbl->getValue ();
+ pp->retinex.skal = (int)skal->getValue ();
pp->retinex.cdcurve = cdshape->getCurve ();
pp->retinex.lhcurve = lhshape->getCurve ();
pp->retinex.cdHcurve = cdshapeH->getCurve ();
pp->retinex.mapcurve = mapshape->getCurve ();
pp->retinex.transmissionCurve = transmissionShape->getCurve ();
+ pp->retinex.gaintransmissionCurve = gaintransmissionShape->getCurve ();
pp->retinex.enabled = getEnabled();
pp->retinex.medianmap = medianmap->get_active();
@@ -870,10 +917,11 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited)
pedited->retinex.limd = limd->getEditedState ();
pedited->retinex.highl = highl->getEditedState ();
pedited->retinex.baselog = baselog->getEditedState ();
-// pedited->retinex.grbl = grbl->getEditedState ();
+ pedited->retinex.skal = skal->getEditedState ();
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();
@@ -1131,7 +1179,7 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi
limd->setDefault (defParams->retinex.limd);
highl->setDefault (defParams->retinex.highl);
baselog->setDefault (defParams->retinex.baselog);
-// grbl->setDefault (defParams->retinex.grbl);
+ skal->setDefault (defParams->retinex.skal);
gam->setDefault (defParams->retinex.gam);
slope->setDefault (defParams->retinex.slope);
@@ -1154,7 +1202,7 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi
limd->setDefaultEditedState (pedited->retinex.limd ? Edited : UnEdited);
highl->setDefaultEditedState (pedited->retinex.highl ? Edited : UnEdited);
baselog->setDefaultEditedState (pedited->retinex.baselog ? Edited : UnEdited);
-// grbl->setDefaultEditedState (pedited->retinex.grbl ? Edited : UnEdited);
+ skal->setDefaultEditedState (pedited->retinex.skal ? Edited : UnEdited);
gam->setDefaultEditedState (pedited->retinex.gam ? Edited : UnEdited);
slope->setDefaultEditedState (pedited->retinex.slope ? Edited : UnEdited);
@@ -1172,7 +1220,7 @@ void Retinex::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi
limd->setDefaultEditedState (Irrelevant);
highl->setDefaultEditedState (Irrelevant);
baselog->setDefaultEditedState (Irrelevant);
-// grbl->setDefaultEditedState (Irrelevant);
+ skal->setDefaultEditedState (Irrelevant);
str->setDefaultEditedState (Irrelevant);
scal->setDefaultEditedState (Irrelevant);
iter->setDefaultEditedState (Irrelevant);
@@ -1245,8 +1293,8 @@ void Retinex::adjusterChanged (Adjuster* a, double newval)
listener->panelChanged (EvLhighl, highl->getTextValue());
} else if (a == baselog) {
listener->panelChanged (EvLbaselog, baselog->getTextValue());
-// } else if (a == grbl) {
-// listener->panelChanged (EvLgrbl, grbl->getTextValue());
+ } else if (a == skal) {
+ listener->panelChanged (EvLskal, skal->getTextValue());
} else if (a == gam) {
listener->panelChanged (EvLgam, gam->getTextValue());
} else if (a == slope) {
@@ -1274,6 +1322,7 @@ void Retinex::autoOpenCurve ()
cdshape->openIfNonlinear();
cdshapeH->openIfNonlinear();
transmissionShape->openIfNonlinear();
+ gaintransmissionShape->openIfNonlinear();
lhshape->openIfNonlinear();
mapshape->openIfNonlinear();
@@ -1289,6 +1338,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) {
@@ -1410,10 +1461,11 @@ void Retinex::setBatchMode (bool batchMode)
shadows->showEditedCB ();
s_tonalwidth->showEditedCB ();
-// grbl->showEditedCB ();
+ skal->showEditedCB ();
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..064756a7b 100644
--- a/rtgui/retinex.h
+++ b/rtgui/retinex.h
@@ -35,7 +35,7 @@ protected:
Adjuster* limd;
Adjuster* highl;
Adjuster* baselog;
- Adjuster* grbl;
+ Adjuster* skal;
Adjuster* gam;
Adjuster* slope;
Adjuster* highlights;
@@ -76,15 +76,21 @@ protected:
Gtk::Label* mMLabels;
Gtk::Label* transLabels;
Gtk::Label* transLabels2;
+ Gtk::Frame *gainFrame;
+ Gtk::Frame *tranFrame;
+ Gtk::Frame *iterFrame;
+ Gtk::Frame *equalFrame;
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;