diff --git a/rtdata/dcpprofiles/Nikon D750.dcp b/rtdata/dcpprofiles/Nikon D750.dcp
index ad9cd5679..6dcef8386 100644
Binary files a/rtdata/dcpprofiles/Nikon D750.dcp and b/rtdata/dcpprofiles/Nikon D750.dcp differ
diff --git a/rtdata/languages/default b/rtdata/languages/default
index b404f1e52..5bd472cdc 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -675,6 +675,71 @@ HISTORY_MSG_440;CbDL - Method
HISTORY_MSG_441;Retinex - Gain transmission
HISTORY_MSG_442;Retinex - Scale
HISTORY_MSG_443;Output Black Point Compensation
+HISTORY_MSG_444;Local L*a*b*
+HISTORY_MSG_445;Local - Bottom
+HISTORY_MSG_446;Local - Right
+HISTORY_MSG_447;Local - Center
+HISTORY_MSG_448;Local - Lightness/
+HISTORY_MSG_449;Local - Lightness
+HISTORY_MSG_450;Local - Contrast
+HISTORY_MSG_451;Local - Chrominance
+HISTORY_MSG_452;Local - Transition
+HISTORY_MSG_453;Local - Avoid color shift
+HISTORY_MSG_454;Local - Top
+HISTORY_MSG_455;Local - Left
+HISTORY_MSG_456;Local - Method
+HISTORY_MSG_457;Local - Color Inverse
+HISTORY_MSG_458;Local - Radius
+HISTORY_MSG_459;Local - Blur Inverse
+HISTORY_MSG_460;Local - Noise
+HISTORY_MSG_461;Local - Scope
+HISTORY_MSG_462;Local - Retinex method
+HISTORY_MSG_463;Local - Retinex strength
+HISTORY_MSG_464;Local - Retinex radius
+HISTORY_MSG_465;Local - Retinex contrast
+HISTORY_MSG_466;Local - Retinex Gain curve
+HISTORY_MSG_467;Local - Retinex chroma
+HISTORY_MSG_468;Local - Retinex Inverse
+HISTORY_MSG_469;Local - Hue scope
+HISTORY_MSG_470;Local - Spot
+HISTORY_MSG_471;Local - Blur Luminance only
+HISTORY_MSG_472;Local - Update GUI and Mip -1
+HISTORY_MSG_473;Local - Sh Radius
+HISTORY_MSG_474;Local - Sh Amount
+HISTORY_MSG_475;Local - Sh Damping
+HISTORY_MSG_476;Local - Sh Iterations
+HISTORY_MSG_477;Local - Sh Scope
+HISTORY_MSG_478;Local - Sh Inverse
+HISTORY_MSG_479;Local - Spot size
+HISTORY_MSG_480;Local - Hue theshold
+HISTORY_MSG_481;Local - Hue proximity
+HISTORY_MSG_482;Local - Quality
+HISTORY_MSG_483;Local - Noise lum f
+HISTORY_MSG_484;Local - Noise lum c
+HISTORY_MSG_485;Local - Noise chro f
+HISTORY_MSG_486;Local - Noise chro c
+HISTORY_MSG_487;Local - cbdl threshold
+HISTORY_MSG_488;Local - cbdl mult
+HISTORY_MSG_489;Local - cbdl scope
+HISTORY_MSG_490;Local - Blur scope
+HISTORY_MSG_491;Local - TM strength
+HISTORY_MSG_492;Local - TM gamma
+HISTORY_MSG_493;Local - TM edge stopping
+HISTORY_MSG_494;Local - TM scale
+HISTORY_MSG_495;Local - TM Reweighting
+HISTORY_MSG_496;Local - TM scope
+HISTORY_MSG_497;Local - Update GUI and Mip -2
+HISTORY_MSG_498;Local - Update GUI and Mip -3
+HISTORY_MSG_499;Local - LL Curve
+HISTORY_MSG_500;Local - Color and light
+HISTORY_MSG_501;Local - Blur and noise
+HISTORY_MSG_502;Local - Tone mapping
+HISTORY_MSG_503;Local - Retinex
+HISTORY_MSG_504;Local - Sharpening
+HISTORY_MSG_505;Local - CBDL
+HISTORY_MSG_506;Local - Denoise
+HISTORY_MSG_507;Local - LH Curve
+HISTORY_MSG_508;Local - Enable curve
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -846,6 +911,7 @@ PARTIALPASTE_IPTCINFO;IPTC
PARTIALPASTE_LABCURVE;L*a*b* adjustments
PARTIALPASTE_LENSGROUP;Lens Related Settings
PARTIALPASTE_LENSPROFILE;Lens correction profile
+PARTIALPASTE_LOCALLAB;Local L*a*b*
PARTIALPASTE_METAGROUP;Metadata
PARTIALPASTE_PCVIGNETTE;Vignette filter
PARTIALPASTE_PERSPECTIVE;Perspective
@@ -1003,6 +1069,11 @@ PREFERENCES_MENUGROUPRANK;Group "Rank"
PREFERENCES_MENUOPTIONS;Context Menu Options
PREFERENCES_METADATA;Metadata
PREFERENCES_MIN;Mini (100x115)
+PREFERENCES_MIP;Mip Profiles
+PREFERENCES_MIP_LABEL;Mip profiles:
+PREFERENCES_MIP_OPT;In Profiles - near Cache
+PREFERENCES_MIP_PREV;Next Input file
+PREFERENCES_MIP_TOOLTIP;Next input file allow multiple sessions of the same file, but do not allow path with NON ASCII characters.\nIn Profiles - near Cache, allow NON ASCII characters in path, but allow only one session for the same file.
PREFERENCES_MONINTENT;Default rendering intent
PREFERENCES_MONITOR;Monitor
PREFERENCES_MONPROFILE;Default color profile
@@ -1603,7 +1674,82 @@ TP_LENSPROFILE_LABEL;Lens Correction Profile
TP_LENSPROFILE_USECA;Chromatic aberration correction
TP_LENSPROFILE_USEDIST;Distortion correction
TP_LENSPROFILE_USEVIGN;Vignetting correction
-TP_NEUTRAL;Reset
+TP_LOCALLAB_ACTIV;Blur luminance only
+TP_LOCALLAB_AVOID;Avoid color shift
+TP_LOCALLAB_BLUFR;Blur & Noise
+TP_LOCALLAB_CENTER_X;Center X
+TP_LOCALLAB_CENTER_Y;Center Y
+TP_LOCALLAB_CBDL;Contrast by detail levels
+TP_LOCALLAB_CHROMA;Chrominance
+TP_LOCALLAB_CHRRT;Chroma
+TP_LOCALLAB_CIRCRADIUS;Spot size
+TP_LOCALLAB_COFR;Color & Light
+TP_LOCALLAB_CONTRAST;Contrast
+TP_LOCALLAB_CURV;Enable curves
+TP_LOCALLAB_DENOIS;Denoise
+TP_LOCALLAB_LUM;Curves
+TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP;To be active, you must check button 'Enable curves'
+TP_LOCALLAB_NOISELUMFINE;Luminance fine
+TP_LOCALLAB_NOISELUMCOARSE;Luminance coarse
+TP_LOCALLAB_NOISECHROFINE;Chroma fine
+TP_LOCALLAB_NOISECHROCOARSE;Chroma coarse
+TP_LOCALLAB_GAM;Gamma
+TP_LOCALLAB_ESTOP;Edge stopping
+TP_LOCALLAB_SCALTM;Scale
+TP_LOCALLAB_REWEI;Reweighting iterates
+TP_LOCALLAB_INDSL;Independent (mouse + sliders)
+TP_LOCALLAB_IND;Independent (mouse)
+TP_LOCALLAB_INVERS;Inverse
+TP_LOCALLAB_LABEL;Local L*a*b*
+TP_LOCALLAB_NEUTRAL;Reset
+TP_LOCALLAB_NEUTRAL_TIP;Reset Current Control point
+TP_LOCALLAB_NBSPOT;Control points
+TP_LOCALLAB_NBSPOT_TOOLTIP;Add multiple control points and select
+TP_LOCALLAB_STD;Quality Standard
+TP_LOCALLAB_ENH;Quality Enhanced
+TP_LOCALLAB_ENHDEN;Quality Enhanced + chroma denoise
+TP_LOCALLAB_THRES;Hue threshold
+TP_LOCALLAB_PROXI;Hue proximity radius
+TP_LOCALLAB_ANBSPOT;Help to Move Control point
+TP_LOCALLAB_ANBSPOT_TOOLTIP;Provisory control (I hope somebody can help to manage events!! and suppress this bad function)
+TP_LOCALLAB_LIGHTNESS;Lightness
+TP_LOCALLAB_METHOD_TOOLTIP;Default - standard.\nIf you select Enhanced or enhanced chroma denoise - only for Color Light-Sharpening-Retinex-CBDL in normal mode, algorithm will detect the variations of hue in the select area and improve shape detection.\nHue threshold define since what value is exclude (* 100 radians).\nHue proximity radius define the radius around each point to calculate variations.\nEnhanced and Hue threshold significantly increases processing times.
+TP_LOCALLAB_RADIUS;Radius
+TP_LOCALLAB_RETI;Retinex
+TP_LOCALLAB_TRANSMISSIONGAIN;Transmission gain
+TP_LOCRETI_METHOD;Method
+TP_LOCALLAB_STREN;Strength
+TP_LOCALLAB_TM;Tone Mapping
+TP_LOCALLAB_STR;Strength
+TP_LOCALLAB_NEIGH;Radius
+TP_LOCALLAB_VART;Contrast
+TP_LOCALLAB_SENSI;Scope
+TP_LOCALLAB_SENSI_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm.
+TP_LOCALLAB_SENSIH;Hue Scope
+TP_LOCALLAB_SENSIH_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm.
+TP_LOCALLAB_SHARP;Sharpening
+TP_LOCALLAB_SHARRADIUS;Radius
+TP_LOCALLAB_SHARAMOUNT;Amount
+TP_LOCALLAB_SHARDAMPING;Damping
+TP_LOCALLAB_SHARITER;Iterations
+TP_LOCALLAB_SENSIS;Scope
+TP_LOCALLAB_SENSICB;Scope
+TP_LOCALLAB_SENSIBN;Scope
+TP_LOCALLAB_SENSIS_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm.
+TP_LOCALLAB_SHFR;Shape
+TP_LOCALLAB_STRENGTH;Noise
+TP_LOCALLAB_STYPE;Shape method
+TP_LOCALLAB_STYPE_TOOLTIP;You can choose between:\nSymmetrical - left handle linked to right, top handle linked to bottom.\nIndependent - all handles are independent.
+TP_LOCALLAB_SYMSL;Symmetrical (mouse + sliders)
+TP_LOCALLAB_SYM;Symmetrical (mouse)
+TP_LOCALLAB_TRANSIT;Transition
+TP_LOCALLAB_TRANSIT_TOOLTIP;Adjust smoothness of transition between affected and unaffected areas.
+TP_LOCAL_HEIGHT;Bottom
+TP_LOCAL_HEIGHT_T;Top
+TP_LOCAL_WIDTH;Right
+TP_LOCAL_WIDTH_L;Left
+TP_LOCRETI_METHOD_TOOLTIP;Low = Reinforce low light.\nUniform = Equalize action.\nHigh = Reinforce high light.\n
+TP_NEUTRAL;Neutral
TP_NEUTRAL_TIP;Resets exposure sliders to neutral values.\nApplies to the same controls that Auto Levels applies to, regardless of whether you used Auto Levels or not.
TP_PCVIGNETTE_FEATHER;Feather
TP_PCVIGNETTE_FEATHER_TOOLTIP;Feathering:\n0 = corners only,\n50 = halfway to center,\n100 = to center.
diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index 477ccecae..35e8c7e01 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -12,7 +12,7 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc
loadinitial.cc procparams.cc rawimagesource.cc demosaic_algos.cc shmap.cc simpleprocess.cc refreshmap.cc
fast_demo.cc amaze_demosaic_RT.cc CA_correct_RT.cc cfa_linedn_RT.cc green_equil_RT.cc hilite_recon.cc expo_before_b.cc
stdimagesource.cc myfile.cc iccjpeg.cc improccoordinator.cc pipettebuffer.cc coord.cc
- processingjob.cc rtthumbnail.cc utils.cc labimage.cc slicer.cc cieimage.cc
+ processingjob.cc rtthumbnail.cc utils.cc labimage.cc slicer.cc cieimage.cc iplocallab.cc
iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc ipvibrance.cc
imagedimensions.cc jpeg_ijg/jpeg_memsrc.cc jdatasrc.cc iimage.cc
EdgePreservingDecomposition.cc cplx_wavelet_dec.cc FTblockDN.cc
diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc
index 6bb0c4c3c..30a8e92c6 100644
--- a/rtengine/FTblockDN.cc
+++ b/rtengine/FTblockDN.cc
@@ -1142,7 +1142,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef
if (!memoryAllocationFailed) {
if (nrQuality == QUALITY_STANDARD) {
- if (!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb)) { //enhance mode
+ if (!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, nullptr, 0, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb)) { //enhance mode
memoryAllocationFailed = true;
}
} else { /*if (nrQuality==QUALITY_HIGH)*/
@@ -1151,7 +1151,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef
}
if (!memoryAllocationFailed) {
- if (!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb)) {
+ if (!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, nullptr, 0, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb)) {
memoryAllocationFailed = true;
}
}
@@ -1179,7 +1179,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef
if (!memoryAllocationFailed) {
if (nrQuality == QUALITY_STANDARD) {
- if (!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb)) { //enhance mode
+ if (!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, nullptr, 0, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb)) { //enhance mode
memoryAllocationFailed = true;
}
} else { /*if (nrQuality==QUALITY_HIGH)*/
@@ -1188,7 +1188,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef
}
if (!memoryAllocationFailed) {
- if (!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb)) {
+ if (!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, nullptr, 0, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb)) {
memoryAllocationFailed = true;
}
}
@@ -2408,7 +2408,7 @@ SSEFUNCTION bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposi
float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl);
if (lvl == maxlvl - 1) {
- ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], madab[lvl], true);
+ ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], nullptr, 0, madab[lvl], true);
} else {
//simple wavelet shrinkage
@@ -2482,8 +2482,12 @@ bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L,
int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5);
- if (edge == 1) {
- maxlvl = 4; //for refine denoise edge wavelet
+ if (edge == 1 || edge == 3) {
+ maxlvl = 4; //for refine denoise edge wavelet
+ }
+
+ if (edge == 2) {
+ maxlvl = 7; //for locallab denoise
}
int maxWL = 0, maxHL = 0;
@@ -2536,11 +2540,20 @@ bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L,
bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab,
- float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb)//mod JD
+ float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb)//mod JD
{
int maxlvl = WaveletCoeffs_L.maxlevel();
+
+ if (local == 2) {
+ maxlvl = 7; //for local denoise
+ }
+
+ if (local == 3) {
+ maxlvl = 4; //for shape detection
+ }
+
int maxWL = 0, maxHL = 0;
for (int lvl = 0; lvl < maxlvl; ++lvl) {
@@ -2574,7 +2587,7 @@ bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L
for (int lvl = 0; lvl < maxlvl; ++lvl) {
for (int dir = 1; dir < 4; ++dir) {
- ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl]);
+ ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], nullptr, 0);
}
}
}
@@ -2610,7 +2623,7 @@ SSEFUNCTION void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeff
// printf("OK lev=%d\n",level);
float mad_L = madL[dir - 1] ;
- if (edge == 1 && vari) {
+ if ((edge == 1 || edge == 2 || edge == 3) && vari) {
noisevarlum = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer
for (int i = 0; i < W_L * H_L; ++i) {
@@ -2684,7 +2697,7 @@ SSEFUNCTION void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeff
SSEFUNCTION void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch,
- bool denoiseMethodRgb, float * madL, float * madaab, bool madCalculated)
+ bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab, bool madCalculated)
{
//simple wavelet shrinkage
@@ -2717,8 +2730,17 @@ SSEFUNCTION void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoef
}
}
- if (noisevar_ab > 0.001f) {
- madab = useNoiseCCurve ? madab : madab * noisevar_ab;
+ float noisevarfc;
+
+ if ((local == 2 || local == 3) && variC) {
+ noisevarfc = variC[level];
+ } else {
+ noisevarfc = noisevar_ab;
+ }
+
+ if (noisevarfc > 0.001f) {//noisevar_ab
+ // madab = useNoiseCCurve ? madab : madab * noisevar_ab;
+ madab = useNoiseCCurve ? madab : madab * noisevarfc;
#ifdef __SSE2__
__m128 onev = _mm_set1_ps(1.f);
__m128 mad_abrv = _mm_set1_ps(madab);
@@ -3041,7 +3063,7 @@ void ImProcFunctions::calcautodn_info (float &chaut, float &delta, int Nb, int l
delta *= 0.15f;
} else if (chaut < 650.f) {
delta *= 0.1f;
- } else /*if (chaut >= 650.f)*/ {
+ } else { /*if (chaut >= 650.f)*/
delta *= 0.07f;
}
@@ -3079,7 +3101,7 @@ void ImProcFunctions::calcautodn_info (float &chaut, float &delta, int Nb, int l
delta *= 0.3f;
} else if (chaut < 650.f) {
delta *= 0.2f;
- } else /*if (chaut >= 650.f)*/ {
+ } else { /*if (chaut >= 650.f)*/
delta *= 0.15f;
}
diff --git a/rtengine/color.h b/rtengine/color.h
index 77db1f4f7..363c8f81f 100644
--- a/rtengine/color.h
+++ b/rtengine/color.h
@@ -1352,6 +1352,56 @@ public:
static void skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s);
// static void scaleredcdbl ( float skinprot, float param, float limit, float HH, float deltaHH, float &scale,float &scaleext);
+ static inline void pregamutlab (float lum, float hue, float &chr)//big approximation to limit gamut (Prophoto) before good gamut procedure for locallab chroma, to avoid crash
+ {
+ if (lum >= 95.0f) {
+ if(hue > 1.5f && hue < 2.f ) {
+ chr = 120.f;
+ } else if(hue > 0.7f && hue <= 1.5f) {
+ chr = 60.f;
+ } else {
+ chr = 40.f;
+ }
+ } else if(lum > 75.f) {
+ if(hue > 1.f && hue < 3.14f ) {
+ chr = 130.f;
+ } else if(hue > -0.4f && hue <= 1.f) {
+ chr = 80.f;
+ } else if(hue > -3.15f && hue > -2.f) {
+ chr = 80.f;
+ } else {
+ chr = 60.f;
+ }
+
+ } else if(lum > 35.f) {
+ chr = 100.f;
+ } else if(lum > 20.f) {
+ if(hue < -1.f && hue > -2.f ) {
+ chr = 120.f;
+ } else {
+ chr = 80.f;
+ }
+ } else if(lum > 7.f) {
+ if(hue < -1.f && hue > -1.8f ) {
+ chr = 120.f;
+ } else {
+ chr = 60.f;
+ }
+
+ } else {
+ if(hue < -1.f && hue > -1.6f ) {
+ chr = 80.f;
+ } else {
+ chr = 40.f;
+ }
+
+ }
+
+ // if(lum < 4.f) {
+ // chr = 0.1f;
+ // }
+ }
+
static inline void SkinSatCbdl (float lum, float hue, float chrom, float skinprot, float &scale, bool neg, float b_l, float t_l, float t_r)
{
diff --git a/rtengine/curves.cc b/rtengine/curves.cc
index cf2fd0d04..0d6896940 100644
--- a/rtengine/curves.cc
+++ b/rtengine/curves.cc
@@ -45,13 +45,13 @@ using namespace std;
namespace rtengine
{
-Curve::Curve () : N(0), ppn(0), x(nullptr), y(nullptr), mc(0.0), mfc(0.0), msc(0.0), mhc(0.0), ypp(nullptr), x1(0.0), y1(0.0), x2(0.0), y2(0.0), x3(0.0), y3(0.0), firstPointIncluded(false), increment(0.0), nbr_points(0), hashSize(1000 /* has to be initialized to the maximum value */) {}
+Curve::Curve () : N (0), ppn (0), x (nullptr), y (nullptr), mc (0.0), mfc (0.0), msc (0.0), mhc (0.0), ypp (nullptr), x1 (0.0), y1 (0.0), x2 (0.0), y2 (0.0), x3 (0.0), y3 (0.0), firstPointIncluded (false), increment (0.0), nbr_points (0), hashSize (1000 /* has to be initialized to the maximum value */) {}
void Curve::AddPolygons ()
{
if (firstPointIncluded) {
- poly_x.push_back(x1);
- poly_y.push_back(y1);
+ poly_x.push_back (x1);
+ poly_y.push_back (y1);
}
for (int k = 1; k < (nbr_points - 1); k++) {
@@ -62,20 +62,20 @@ void Curve::AddPolygons ()
double tr2t = tr * 2 * t;
// adding a point to the polyline
- poly_x.push_back( tr2 * x1 + tr2t * x2 + t2 * x3);
- poly_y.push_back( tr2 * y1 + tr2t * y2 + t2 * y3);
+ poly_x.push_back ( tr2 * x1 + tr2t * x2 + t2 * x3);
+ poly_y.push_back ( tr2 * y1 + tr2t * y2 + t2 * y3);
}
// adding the last point of the sub-curve
- poly_x.push_back(x3);
- poly_y.push_back(y3);
+ poly_x.push_back (x3);
+ poly_y.push_back (y3);
}
void Curve::fillDyByDx ()
{
- dyByDx.resize(poly_x.size() - 1);
+ dyByDx.resize (poly_x.size() - 1);
- for(unsigned int i = 0; i < poly_x.size() - 1; i++) {
+ for (unsigned int i = 0; i < poly_x.size() - 1; i++) {
double dx = poly_x[i + 1] - poly_x[i];
double dy = poly_y[i + 1] - poly_y[i];
dyByDx[i] = dy / dx;
@@ -85,18 +85,18 @@ void Curve::fillDyByDx ()
void Curve::fillHash()
{
- hash.resize(hashSize + 2);
+ hash.resize (hashSize + 2);
unsigned int polyIter = 0;
double const increment = 1. / hashSize;
double milestone = 0.;
for (unsigned short i = 0; i < (hashSize + 1);) {
- while(poly_x[polyIter] <= milestone) {
+ while (poly_x[polyIter] <= milestone) {
++polyIter;
}
- hash.at(i).smallerValue = polyIter - 1;
+ hash.at (i).smallerValue = polyIter - 1;
++i;
milestone = i * increment;
}
@@ -105,17 +105,17 @@ void Curve::fillHash()
polyIter = 0;
for (unsigned int i = 0; i < (hashSize + 1);) {
- while(poly_x[polyIter] < (milestone + increment)) {
+ while (poly_x[polyIter] < (milestone + increment)) {
++polyIter;
}
- hash.at(i).higherValue = polyIter;
+ hash.at (i).higherValue = polyIter;
++i;
milestone = i * increment;
}
- hash.at(hashSize + 1).smallerValue = poly_x.size() - 1;
- hash.at(hashSize + 1).higherValue = poly_x.size();
+ hash.at (hashSize + 1).smallerValue = poly_x.size() - 1;
+ hash.at (hashSize + 1).higherValue = poly_x.size();
/*
* Uncoment the code below to dump the polygon points and the hash table in files
@@ -153,7 +153,7 @@ int Curve::getSize () const
* @param x Y value of the control points, or -1 if invalid
* @param y Y value of the control points, or -1 if invalid
*/
-void Curve::getControlPoint(int cpNum, double &x, double &y) const
+void Curve::getControlPoint (int cpNum, double &x, double &y) const
{
if (this->x && cpNum < N) {
x = this->x[cpNum];
@@ -169,7 +169,7 @@ void Curve::getControlPoint(int cpNum, double &x, double &y) const
const double CurveFactory::sRGBGamma = 2.2;
const double CurveFactory::sRGBGammaCurve = 2.4;
-void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed)
+void fillCurveArray (DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed)
{
if (needed) {
@@ -187,7 +187,7 @@ void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool nee
float skipmul = 1.f / (float) skip;
for (int i = 0; i <= 0x10000 - skip; i += skip) {
- for(int j = 1; j < skip; j++) {
+ for (int j = 1; j < skip; j++) {
outCurve[i + j] = ( outCurve[i] * (skip - j) + outCurve[i + skip] * j ) * skipmul;
}
}
@@ -211,14 +211,14 @@ void CurveFactory::curveLightBrightColor (const std::vector& curvePoints
customColCurve3.Reset();
if (!curvePoints3.empty() && curvePoints3[0] > DCT_Linear && curvePoints3[0] < DCT_Unchanged) {
- DiagonalCurve tcurve(curvePoints3, CURVES_MIN_POLY_POINTS / skip);
+ DiagonalCurve tcurve (curvePoints3, CURVES_MIN_POLY_POINTS / skip);
if (outBeforeCCurveHistogramC) {
- histogramC.compressTo(outBeforeCCurveHistogramC, 48000);
+ histogramC.compressTo (outBeforeCCurveHistogramC, 48000);
}
if (!tcurve.isIdentity()) {
- customColCurve3.Set(tcurve);
+ customColCurve3.Set (tcurve);
}
}
@@ -226,14 +226,14 @@ void CurveFactory::curveLightBrightColor (const std::vector& curvePoints
customColCurve2.Reset();
if (!curvePoints2.empty() && curvePoints2[0] > DCT_Linear && curvePoints2[0] < DCT_Unchanged) {
- DiagonalCurve tcurve(curvePoints2, CURVES_MIN_POLY_POINTS / skip);
+ DiagonalCurve tcurve (curvePoints2, CURVES_MIN_POLY_POINTS / skip);
if (outBeforeCCurveHistogram) {
histNeeded = true;
}
if (!tcurve.isIdentity()) {
- customColCurve2.Set(tcurve);
+ customColCurve2.Set (tcurve);
}
}
@@ -242,19 +242,19 @@ void CurveFactory::curveLightBrightColor (const std::vector& curvePoints
customColCurve1.Reset();
if (!curvePoints1.empty() && curvePoints1[0] > DCT_Linear && curvePoints1[0] < DCT_Unchanged) {
- DiagonalCurve tcurve(curvePoints1, CURVES_MIN_POLY_POINTS / skip);
+ DiagonalCurve tcurve (curvePoints1, CURVES_MIN_POLY_POINTS / skip);
if (outBeforeCCurveHistogram) {
histNeeded = true;
}
if (!tcurve.isIdentity()) {
- customColCurve1.Set(tcurve);
+ customColCurve1.Set (tcurve);
}
}
if (histNeeded) {
- histogram.compressTo(outBeforeCCurveHistogram, 32768);
+ histogram.compressTo (outBeforeCCurveHistogram, 32768);
}
}
@@ -271,14 +271,14 @@ void CurveFactory::curveBW ( const std::vector& curvePointsbw, const std
customToneCurvebw2.Reset();
if (!curvePointsbw2.empty() && curvePointsbw2[0] > DCT_Linear && curvePointsbw2[0] < DCT_Unchanged) {
- DiagonalCurve tcurve(curvePointsbw2, CURVES_MIN_POLY_POINTS / skip);
+ DiagonalCurve tcurve (curvePointsbw2, CURVES_MIN_POLY_POINTS / skip);
if (outBeforeCCurveHistogrambw) {
histNeeded = true;
}
if (!tcurve.isIdentity()) {
- customToneCurvebw2.Set(tcurve, gamma_);
+ customToneCurvebw2.Set (tcurve, gamma_);
}
}
@@ -286,21 +286,21 @@ void CurveFactory::curveBW ( const std::vector& curvePointsbw, const std
customToneCurvebw1.Reset();
if (!curvePointsbw.empty() && curvePointsbw[0] > DCT_Linear && curvePointsbw[0] < DCT_Unchanged) {
- DiagonalCurve tcurve(curvePointsbw, CURVES_MIN_POLY_POINTS / skip);
+ DiagonalCurve tcurve (curvePointsbw, CURVES_MIN_POLY_POINTS / skip);
if (outBeforeCCurveHistogrambw ) {
histNeeded = true;
}
if (!tcurve.isIdentity()) {
- customToneCurvebw1.Set(tcurve, gamma_);
+ customToneCurvebw1.Set (tcurve, gamma_);
}
}
// create first curve if needed
if (histNeeded) {
- histogrambw.compressTo(outBeforeCCurveHistogrambw, 32768);
+ histogrambw.compressTo (outBeforeCCurveHistogrambw, 32768);
}
}
@@ -311,14 +311,14 @@ void CurveFactory::curveCL ( bool & clcutili, const std::vector& clcurve
std::unique_ptr dCurve;
if (!clcurvePoints.empty() && clcurvePoints[0] != 0) {
- dCurve = std::unique_ptr(new DiagonalCurve(clcurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (clcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
clcutili = true;
}
}
- fillCurveArray(dCurve.get(), clCurve, skip, clcutili);
+ fillCurveArray (dCurve.get(), clCurve, skip, clcutili);
}
void CurveFactory::mapcurve ( bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram)
@@ -329,7 +329,7 @@ void CurveFactory::mapcurve ( bool & mapcontlutili, const std::vector& m
bool histNeeded = false;
if (!mapcurvePoints.empty() && mapcurvePoints[0] != 0) {
- dCurve = std::unique_ptr(new DiagonalCurve(mapcurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (mapcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (outBeforeCurveHistogram) {
histNeeded = true;
@@ -342,10 +342,10 @@ void CurveFactory::mapcurve ( bool & mapcontlutili, const std::vector& m
}
if (histNeeded) {
- histogram.compressTo(outBeforeCurveHistogram, 32768);
+ histogram.compressTo (outBeforeCurveHistogram, 32768);
}
- fillCurveArray(dCurve.get(), mapcurve, skip, needed);
+ fillCurveArray (dCurve.get(), mapcurve, skip, needed);
}
void CurveFactory::curveDehaContL ( bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram)
@@ -356,7 +356,7 @@ void CurveFactory::curveDehaContL ( bool & dehacontlutili, const std::vector(new DiagonalCurve(dehaclcurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (dehaclcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (outBeforeCurveHistogram) {
histNeeded = true;
@@ -369,10 +369,10 @@ void CurveFactory::curveDehaContL ( bool & dehacontlutili, const std::vector dCurve;
if (!wavclcurvePoints.empty() && wavclcurvePoints[0] != 0) {
- dCurve = std::unique_ptr(new DiagonalCurve(wavclcurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (wavclcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
needed = true;
@@ -390,7 +390,7 @@ void CurveFactory::curveWavContL ( bool & wavcontlutili, const std::vector& curvePoints, LUTf &
std::unique_ptr dCurve;
if (!curvePoints.empty() && curvePoints[0] != 0) {
- dCurve = std::unique_ptr(new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
needed = true;
}
}
- fillCurveArray(dCurve.get(), ToningCurve, skip, needed);
+ fillCurveArray (dCurve.get(), ToningCurve, skip, needed);
}
+void CurveFactory::curveLocal (bool & locallutili, const std::vector& curvePoints, LUTf & LocalLCurve, int skip)
+{
+ bool needed = false;
+ std::unique_ptr dCurve;
+
+ if (!curvePoints.empty() && curvePoints[0] != 0) {
+ dCurve = std::unique_ptr (new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip));
+
+ if (dCurve && !dCurve->isIdentity()) {
+ needed = true;
+ locallutili = true;
+ }
+ }
+
+ fillCurveArray (dCurve.get(), LocalLCurve, skip, needed);
+ //LocalLCurve.dump("wav");
+
+}
+
+
+
+void CurveFactory::localLCurve (double br, double contr, /*const std::vector& curvePoints,*/
+ LUTu & histogram, LUTf & outCurve,
+ int skip, bool & utili)
+{
+
+ // curve without contrast
+ LUTf dcurve (65536, 0);
+
+ // clear array that stores histogram valid before applying the custom curve
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ // check if brightness curve is needed
+ if (br > 0.00001 || br < -0.00001) {
+ utili = true;
+
+ std::vector brightcurvePoints;
+ brightcurvePoints.resize (9);
+ brightcurvePoints.at (0) = double (DCT_NURBS);
+
+ brightcurvePoints.at (1) = 0.; // black point. Value in [0 ; 1] range
+ brightcurvePoints.at (2) = 0.; // black point. Value in [0 ; 1] range
+
+ if (br > 0) {
+ brightcurvePoints.at (3) = 0.1; // toe point
+ brightcurvePoints.at (4) = 0.1 + br / 150.0; //value at toe point
+
+ brightcurvePoints.at (5) = 0.7; // shoulder point
+ brightcurvePoints.at (6) = min (1.0, 0.7 + br / 300.0); //value at shoulder point
+ } else {
+ brightcurvePoints.at (3) = 0.1 - br / 150.0; // toe point
+ brightcurvePoints.at (4) = 0.1; // value at toe point
+
+ brightcurvePoints.at (5) = min (1.0, 0.7 - br / 300.0); // shoulder point
+ brightcurvePoints.at (6) = 0.7; // value at shoulder point
+ }
+
+ brightcurvePoints.at (7) = 1.; // white point
+ brightcurvePoints.at (8) = 1.; // value at white point
+
+ DiagonalCurve* brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS / skip);
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ // Applying brightness curve
+ for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
+
+ // change to [0,1] range
+ float val = (float)i / 32767.0;
+
+ // apply brightness curve
+ val = brightcurve->getVal (val);
+
+ // store result in a temporary array
+ dcurve[i] = CLIPD (val);
+ }
+
+ delete brightcurve;
+ } else {
+ for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
+ // set the identity curve in the temporary array
+ dcurve[i] = (float)i / 32767.0;
+ }
+ }
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ // check if contrast curve is needed
+ if (contr > 0.00001 || contr < -0.00001) {
+ utili = true;
+
+ DiagonalCurve* contrastcurve = NULL;
+
+ // compute mean luminance of the image with the curve applied
+ int sum = 0;
+ float avg = 0;
+
+ //float sqavg = 0;
+ for (int i = 0; i < 32768; i++) {
+ avg += dcurve[i] * histogram[i];
+ //sqavg += dcurve[i]*dcurve[i] * histogram[i];
+ sum += histogram[i];
+ }
+
+ if (sum) {
+ avg /= sum;
+ //sqavg /= sum;
+ //float stddev = sqrt(sqavg-avg*avg);
+ // printf("avg=%f\n",avg);
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ std::vector contrastcurvePoints;
+ contrastcurvePoints.resize (9);
+ contrastcurvePoints.at (0) = double (DCT_NURBS);
+
+ contrastcurvePoints.at (1) = 0.; // black point. Value in [0 ; 1] range
+ contrastcurvePoints.at (2) = 0.; // black point. Value in [0 ; 1] range
+
+ contrastcurvePoints.at (3) = avg - avg * (0.6 - contr / 250.0); // toe point
+ contrastcurvePoints.at (4) = avg - avg * (0.6 + contr / 250.0); // value at toe point
+
+ contrastcurvePoints.at (5) = avg + (1 - avg) * (0.6 - contr / 250.0); // shoulder point
+ contrastcurvePoints.at (6) = avg + (1 - avg) * (0.6 + contr / 250.0); // value at shoulder point
+
+ contrastcurvePoints.at (7) = 1.; // white point
+ contrastcurvePoints.at (8) = 1.; // value at white point
+
+ contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ } else {
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image
+ std::vector contrastcurvePoints;
+ contrastcurvePoints.resize (5);
+ contrastcurvePoints.at (0) = double (DCT_NURBS);
+
+ contrastcurvePoints.at (1) = 0.; // black point. Value in [0 ; 1] range
+ contrastcurvePoints.at (2) = 1.; // black point. Value in [0 ; 1] range
+
+ contrastcurvePoints.at (3) = 1.; // white point
+ contrastcurvePoints.at (4) = 1.; // value at white point
+
+ contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ }
+
+ // apply contrast enhancement
+ for (int i = 0; i < 32768; i++) {
+ dcurve[i] = contrastcurve->getVal (dcurve[i]);
+ }
+
+ delete contrastcurve;
+ }
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ // create a curve if needed
+ /* DiagonalCurve* tcurve = NULL;
+ bool histNeeded = false;
+ if (!curvePoints.empty() && curvePoints[0]!=0) {
+ tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS/skip);
+ }
+ if (tcurve && tcurve->isIdentity()) {
+ delete tcurve;
+ tcurve = NULL;
+ }
+
+ if (tcurve) {
+ utili=true;//if active
+
+ // L values go up to 32767, last stop is for highlight overflow
+ for (int i=0; i<32768; i++) {
+ float val;
+ // apply custom/parametric/NURBS curve, if any
+ val = tcurve->getVal (dcurve[i]);
+
+ outCurve[i] = (32767.0 * val);
+ }
+ }
+ else
+ */
+ {
+ // Skip the slow getval method if no curve is used (or an identity curve)
+ // L values go up to 32767, last stop is for highlight overflow
+ for (int i = 0; i < 32768; i++) {
+ outCurve[i] = 32767.0 * dcurve[i];
+ }
+ }
+
+ for (int i = 32768; i < 65536; i++) {
+ outCurve[i] = (float)i;
+ }
+
+ // if (tcurve)
+ // delete tcurve;
+
+}
+
+
+
+
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void CurveFactory::complexsgnCurve (bool & autili, bool & butili, bool & ccutili, bool & cclutili,
@@ -423,56 +629,56 @@ void CurveFactory::complexsgnCurve (bool & autili, bool & butili, bool & ccutil
// create a curve if needed
if (!acurvePoints.empty() && acurvePoints[0] != 0) {
- dCurve = std::unique_ptr(new DiagonalCurve(acurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (acurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
autili = true;
}
}
- fillCurveArray(dCurve.get(), aoutCurve, skip, autili);
+ fillCurveArray (dCurve.get(), aoutCurve, skip, autili);
dCurve = nullptr;
//-----------------------------------------------------
if (!bcurvePoints.empty() && bcurvePoints[0] != 0) {
- dCurve = std::unique_ptr(new DiagonalCurve(bcurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (bcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
butili = true;
}
}
- fillCurveArray(dCurve.get(), boutCurve, skip, butili);
+ fillCurveArray (dCurve.get(), boutCurve, skip, butili);
dCurve = nullptr;
//-----------------------------------------------
if (!cccurvePoints.empty() && cccurvePoints[0] != 0) {
- dCurve = std::unique_ptr(new DiagonalCurve(cccurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (cccurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
ccutili = true;
}
}
- fillCurveArray(dCurve.get(), satCurve, skip, ccutili);
+ fillCurveArray (dCurve.get(), satCurve, skip, ccutili);
dCurve = nullptr;
//----------------------------
if (!lccurvePoints.empty() && lccurvePoints[0] != 0) {
- dCurve = std::unique_ptr(new DiagonalCurve(lccurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve = std::unique_ptr (new DiagonalCurve (lccurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
cclutili = true;
}
}
- fillCurveArray(dCurve.get(), lhskCurve, skip, cclutili);
+ fillCurveArray (dCurve.get(), lhskCurve, skip, cclutili);
}
@@ -495,7 +701,7 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
// the curve shapes are defined in sRGB gamma, but the output curves will operate on linear floating point data,
// hence we do both forward and inverse gamma conversions here.
const float gamma_ = Color::sRGBGammaCurve;
- const float start = expf(gamma_ * logf( -0.055 / ((1.0 / gamma_ - 1.0) * 1.055 )));
+ const float start = expf (gamma_ * logf ( -0.055 / ((1.0 / gamma_ - 1.0) * 1.055 )));
const float slope = 1.055 * powf (start, 1.0 / gamma_ - 1) - 0.055 / start;
const float mul = 1.055;
const float add = 0.055;
@@ -515,20 +721,20 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
// check if brightness curve is needed
if (br > 0.00001 || br < -0.00001) {
- std::vector brightcurvePoints(9);
+ std::vector brightcurvePoints (9);
brightcurvePoints[0] = DCT_NURBS;
brightcurvePoints[1] = 0.; //black point. Value in [0 ; 1] range
brightcurvePoints[2] = 0.; //black point. Value in [0 ; 1] range
- if(br > 0) {
+ if (br > 0) {
brightcurvePoints[3] = 0.1; //toe point
brightcurvePoints[4] = 0.1 + br / 150.0; //value at toe point
brightcurvePoints[5] = 0.7; //shoulder point
- brightcurvePoints[6] = min(1.0, 0.7 + br / 300.0); //value at shoulder point
+ brightcurvePoints[6] = min (1.0, 0.7 + br / 300.0); //value at shoulder point
} else {
- brightcurvePoints[3] = max(0.0, 0.1 - br / 150.0); //toe point
+ brightcurvePoints[3] = max (0.0, 0.1 - br / 150.0); //toe point
brightcurvePoints[4] = 0.1; //value at toe point
brightcurvePoints[5] = 0.7 - br / 300.0; //shoulder point
@@ -538,47 +744,47 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
brightcurvePoints[7] = 1.; // white point
brightcurvePoints[8] = 1.; // value at white point
- brightcurve = std::unique_ptr(new DiagonalCurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ brightcurve = std::unique_ptr (new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS / skip));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- hlCurve.setClip(LUT_CLIP_BELOW); // used LUT_CLIP_BELOW, because we want to have a baseline of 2^expcomp in this curve. If we don't clip the lut we get wrong values, see Issue 2621 #14 for details
+ hlCurve.setClip (LUT_CLIP_BELOW); // used LUT_CLIP_BELOW, because we want to have a baseline of 2^expcomp in this curve. If we don't clip the lut we get wrong values, see Issue 2621 #14 for details
float exp_scale = a;
float scale = 65536.0;
- float comp = (max(0.0, ecomp) + 1.0) * hlcompr / 100.0;
- float shoulder = ((scale / max(1.0f, exp_scale)) * (hlcomprthresh / 200.0)) + 0.1;
+ float comp = (max (0.0, ecomp) + 1.0) * hlcompr / 100.0;
+ float shoulder = ((scale / max (1.0f, exp_scale)) * (hlcomprthresh / 200.0)) + 0.1;
if (comp <= 0.0f) {
- hlCurve.makeConstant(exp_scale);
+ hlCurve.makeConstant (exp_scale);
} else {
- hlCurve.makeConstant(exp_scale, shoulder + 1);
+ hlCurve.makeConstant (exp_scale, shoulder + 1);
float scalemshoulder = scale - shoulder;
#ifdef __SSE2__
int i = shoulder + 1;
- if(i & 1) { // original formula, slower than optimized formulas below but only used once or none, so I let it as is for reference
+ if (i & 1) { // original formula, slower than optimized formulas below but only used once or none, so I let it as is for reference
// change to [0,1] range
float val = (float)i - shoulder;
float R = val * comp / (scalemshoulder);
- hlCurve[i] = xlog(1.0 + R * exp_scale) / R; // don't use xlogf or 1.f here. Leads to errors caused by too low precision
+ hlCurve[i] = xlog (1.0 + R * exp_scale) / R; // don't use xlogf or 1.f here. Leads to errors caused by too low precision
i++;
}
- vdouble onev = _mm_set1_pd(1.0);
- vdouble Rv = _mm_set_pd((i + 1 - shoulder) * (double)comp / scalemshoulder, (i - shoulder) * (double)comp / scalemshoulder);
- vdouble incrementv = _mm_set1_pd(2.0 * comp / scalemshoulder);
- vdouble exp_scalev = _mm_set1_pd(exp_scale);
+ vdouble onev = _mm_set1_pd (1.0);
+ vdouble Rv = _mm_set_pd ((i + 1 - shoulder) * (double)comp / scalemshoulder, (i - shoulder) * (double)comp / scalemshoulder);
+ vdouble incrementv = _mm_set1_pd (2.0 * comp / scalemshoulder);
+ vdouble exp_scalev = _mm_set1_pd (exp_scale);
for (; i < 0x10000; i += 2) {
// change to [0,1] range
- vdouble resultv = xlog(onev + Rv * exp_scalev) / Rv;
- vfloat resultfv = _mm_cvtpd_ps(resultv);
- _mm_store_ss(&hlCurve[i], resultfv);
- resultfv = PERMUTEPS(resultfv, _MM_SHUFFLE(1, 1, 1, 1));
- _mm_store_ss(&hlCurve[i + 1], resultfv);
+ vdouble resultv = xlog (onev + Rv * exp_scalev) / Rv;
+ vfloat resultfv = _mm_cvtpd_ps (resultv);
+ _mm_store_ss (&hlCurve[i], resultfv);
+ resultfv = PERMUTEPS (resultfv, _MM_SHUFFLE (1, 1, 1, 1));
+ _mm_store_ss (&hlCurve[i + 1], resultfv);
Rv += incrementv;
}
@@ -588,7 +794,7 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
for (int i = shoulder + 1; i < 0x10000; i++) {
// change to [0,1] range
- hlCurve[i] = xlog(1.0 + R * exp_scale) / R; // don't use xlogf or 1.f here. Leads to errors caused by too low precision
+ hlCurve[i] = xlog (1.0 + R * exp_scale) / R; // don't use xlogf or 1.f here. Leads to errors caused by too low precision
R += increment;
}
@@ -598,14 +804,14 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
// curve without contrast
- LUTf dcurve(0x10000);
+ LUTf dcurve (0x10000);
//%%%%%%%%%%%%%%%%%%%%%%%%%%
// change to [0,1] range
- shCurve.setClip(LUT_CLIP_ABOVE); // used LUT_CLIP_ABOVE, because the curve converges to 1.0 at the upper end and we don't want to exceed this value.
+ shCurve.setClip (LUT_CLIP_ABOVE); // used LUT_CLIP_ABOVE, because the curve converges to 1.0 at the upper end and we don't want to exceed this value.
float val = 1.f / 65535.f;
float val2 = simplebasecurve (val, black, 0.015 * shcompr);
- shCurve[0] = CLIPD(val2) / val;
+ shCurve[0] = CLIPD (val2) / val;
// gamma correction
val = Color::gammatab_srgb[0] / 65535.f;
@@ -616,7 +822,7 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
}
// store result in a temporary array
- dcurve[0] = CLIPD(val);
+ dcurve[0] = CLIPD (val);
for (int i = 1; i < 0x10000; i++) {
float val = i / 65535.f;
@@ -629,7 +835,7 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
// apply brightness curve
if (brightcurve) {
- val = CLIPD(brightcurve->getVal (val)); // TODO: getVal(double) is very slow! Optimize with a LUTf
+ val = CLIPD (brightcurve->getVal (val)); // TODO: getVal(double) is very slow! Optimize with a LUTf
}
// store result in a temporary array
@@ -651,14 +857,14 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
for (int i = 0; i <= 0xffff; i++) {
float fi = i * hlCurve[i];
- avg += dcurve[(int)(shCurve[fi] * fi)] * histogram[i];
+ avg += dcurve[ (int) (shCurve[fi] * fi)] * histogram[i];
sum += histogram[i];
}
avg /= sum;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- std::vector contrastcurvePoints(9);
+ std::vector contrastcurvePoints (9);
contrastcurvePoints[0] = DCT_NURBS;
contrastcurvePoints[1] = 0; //black point. Value in [0 ; 1] range
@@ -673,7 +879,7 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
contrastcurvePoints[7] = 1.; // white point
contrastcurvePoints[8] = 1.; // value at white point
- const DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
+ const DiagonalCurve contrastcurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// apply contrast enhancement
@@ -689,10 +895,10 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
customToneCurve2.Reset();
if (!curvePoints2.empty() && curvePoints2[0] > DCT_Linear && curvePoints2[0] < DCT_Unchanged) {
- const DiagonalCurve tcurve(curvePoints2, CURVES_MIN_POLY_POINTS / skip);
+ const DiagonalCurve tcurve (curvePoints2, CURVES_MIN_POLY_POINTS / skip);
if (!tcurve.isIdentity()) {
- customToneCurve2.Set(tcurve, gamma_);
+ customToneCurve2.Set (tcurve, gamma_);
}
if (outBeforeCCurveHistogram ) {
@@ -708,10 +914,10 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
customToneCurve1.Reset();
if (!curvePoints.empty() && curvePoints[0] > DCT_Linear && curvePoints[0] < DCT_Unchanged) {
- const DiagonalCurve tcurve(curvePoints, CURVES_MIN_POLY_POINTS / skip);
+ const DiagonalCurve tcurve (curvePoints, CURVES_MIN_POLY_POINTS / skip);
if (!tcurve.isIdentity()) {
- customToneCurve1.Set(tcurve, gamma_);
+ customToneCurve1.Set (tcurve, gamma_);
}
if (outBeforeCCurveHistogram) {
@@ -722,17 +928,17 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#ifdef __SSE2__
- vfloat gamma_v = F2V(gamma_);
- vfloat startv = F2V(start);
- vfloat slopev = F2V(slope);
- vfloat mulv = F2V(mul);
- vfloat addv = F2V(add);
- vfloat c65535v = F2V(65535.f);
+ vfloat gamma_v = F2V (gamma_);
+ vfloat startv = F2V (start);
+ vfloat slopev = F2V (slope);
+ vfloat mulv = F2V (mul);
+ vfloat addv = F2V (add);
+ vfloat c65535v = F2V (65535.f);
for (int i = 0; i <= 0xffff; i += 4) {
- vfloat valv = LVFU(dcurve[i]);
+ vfloat valv = LVFU (dcurve[i]);
valv = igamma (valv, gamma_v, startv, slopev, mulv, addv);
- STVFU(outCurve[i], c65535v * valv);
+ STVFU (outCurve[i], c65535v * valv);
}
#else
@@ -750,7 +956,7 @@ SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double
float fi = i;
float hval = hlCurve[i] * fi;
hval = dcurve[shCurve[hval] * hval];
- int hi = (int)(255.f * (hval));
+ int hi = (int) (255.f * (hval));
outBeforeCCurveHistogram[hi] += histogram[i] ;
}
}
@@ -767,6 +973,7 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vector brightcurvePoints;
- brightcurvePoints.resize(9);
- brightcurvePoints.at(0) = double(DCT_NURBS);
+ brightcurvePoints.resize (9);
+ brightcurvePoints.at (0) = double (DCT_NURBS);
- brightcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
- brightcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
+ brightcurvePoints.at (1) = 0.; // black point. Value in [0 ; 1] range
+ brightcurvePoints.at (2) = 0.; // black point. Value in [0 ; 1] range
if (br > 0) {
- brightcurvePoints.at(3) = 0.1; // toe point
- brightcurvePoints.at(4) = 0.1 + br / 150.0; //value at toe point
+ brightcurvePoints.at (3) = 0.1; // toe point
+ brightcurvePoints.at (4) = 0.1 + br / 150.0; //value at toe point
- brightcurvePoints.at(5) = 0.7; // shoulder point
- brightcurvePoints.at(6) = min(1.0, 0.7 + br / 300.0); //value at shoulder point
+ brightcurvePoints.at (5) = 0.7; // shoulder point
+ brightcurvePoints.at (6) = min (1.0, 0.7 + br / 300.0); //value at shoulder point
} else {
- brightcurvePoints.at(3) = 0.1 - br / 150.0; // toe point
- brightcurvePoints.at(4) = 0.1; // value at toe point
+ brightcurvePoints.at (3) = 0.1 - br / 150.0; // toe point
+ brightcurvePoints.at (4) = 0.1; // value at toe point
- brightcurvePoints.at(5) = min(1.0, 0.7 - br / 300.0); // shoulder point
- brightcurvePoints.at(6) = 0.7; // value at shoulder point
+ brightcurvePoints.at (5) = min (1.0, 0.7 - br / 300.0); // shoulder point
+ brightcurvePoints.at (6) = 0.7; // value at shoulder point
}
- brightcurvePoints.at(7) = 1.; // white point
- brightcurvePoints.at(8) = 1.; // value at white point
+ brightcurvePoints.at (7) = 1.; // white point
+ brightcurvePoints.at (8) = 1.; // value at white point
- DiagonalCurve brightcurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip);
+ DiagonalCurve brightcurve (brightcurvePoints, CURVES_MIN_POLY_POINTS / skip);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Applying brightness curve
@@ -817,11 +1024,11 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vector contrastcurvePoints;
- if(sum) {
+ if (sum) {
avg /= sum;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- contrastcurvePoints.resize(9);
- contrastcurvePoints.at(0) = double(DCT_NURBS);
+ contrastcurvePoints.resize (9);
+ contrastcurvePoints.at (0) = double (DCT_NURBS);
- contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
+ contrastcurvePoints.at (1) = 0.; // black point. Value in [0 ; 1] range
+ contrastcurvePoints.at (2) = 0.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(3) = avg - avg * (0.6 - contr / 250.0); // toe point
- contrastcurvePoints.at(4) = avg - avg * (0.6 + contr / 250.0); // value at toe point
+ contrastcurvePoints.at (3) = avg - avg * (0.6 - contr / 250.0); // toe point
+ contrastcurvePoints.at (4) = avg - avg * (0.6 + contr / 250.0); // value at toe point
- contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - contr / 250.0); // shoulder point
- contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + contr / 250.0); // value at shoulder point
+ contrastcurvePoints.at (5) = avg + (1 - avg) * (0.6 - contr / 250.0); // shoulder point
+ contrastcurvePoints.at (6) = avg + (1 - avg) * (0.6 + contr / 250.0); // value at shoulder point
- contrastcurvePoints.at(7) = 1.; // white point
- contrastcurvePoints.at(8) = 1.; // value at white point
+ contrastcurvePoints.at (7) = 1.; // white point
+ contrastcurvePoints.at (8) = 1.; // value at white point
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} else {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image
- contrastcurvePoints.resize(5);
- contrastcurvePoints.at(0) = double(DCT_NURBS);
+ contrastcurvePoints.resize (5);
+ contrastcurvePoints.at (0) = double (DCT_NURBS);
- contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(2) = 1.; // black point. Value in [0 ; 1] range
+ contrastcurvePoints.at (1) = 0.; // black point. Value in [0 ; 1] range
+ contrastcurvePoints.at (2) = 1.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(3) = 1.; // white point
- contrastcurvePoints.at(4) = 1.; // value at white point
+ contrastcurvePoints.at (3) = 1.; // white point
+ contrastcurvePoints.at (4) = 1.; // value at white point
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
- DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
+ DiagonalCurve contrastcurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
// apply contrast enhancement
for (int i = 0; i < 32768; i++) {
@@ -894,7 +1101,7 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vector(new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip));
+ tcurve = std::unique_ptr (new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip));
if (outBeforeCCurveHistogram) {
histNeeded = true;
@@ -914,7 +1121,7 @@ void CurveFactory::complexLCurve (double br, double contr, const std::vector& curvePoints, LUTf & outC
std::unique_ptr tcurve;
if (!curvePoints.empty() && curvePoints[0] != 0) {
- tcurve = std::unique_ptr(new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
+ tcurve = std::unique_ptr (new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip));
}
if (tcurve && tcurve->isIdentity()) {
@@ -961,14 +1168,14 @@ void CurveFactory::RGBCurve (const std::vector& curvePoints, LUTf & outC
if (tcurve) {
if (!outCurve) {
- outCurve(65536, 0);
+ outCurve (65536, 0);
}
for (int i = 0; i < 65536; i++) {
// apply custom/parametric/NURBS curve, if any
// RGB curves are defined with sRGB gamma, but operate on linear data
float val = Color::gamma2curve[i] / 65535.f;
- val = tcurve->getVal(val);
+ val = tcurve->getVal (val);
outCurve[i] = Color::igammatab_srgb[val * 65535.f];
}
} else { // let the LUTf empty for identity curves
@@ -977,18 +1184,149 @@ void CurveFactory::RGBCurve (const std::vector& curvePoints, LUTf & outC
}
+LocretigainCurverab::LocretigainCurverab() : sum (0.f) {};
+
+void LocretigainCurverab::Reset()
+{
+ lutLocretigainCurverab.reset();
+ sum = 0.f;
+}
+
+void LocretigainCurverab::Set (const Curve &pCurve)
+{
+ if (pCurve.isIdentity()) {
+ Reset(); // raise this value if the quality suffers from this number of samples
+ return;
+ }
+
+ lutLocretigainCurverab (501); // raise this value if the quality suffers from this number of samples
+ sum = 0.f;
+
+ for (int i = 0; i < 501; i++) {
+ lutLocretigainCurverab[i] = pCurve.getVal (double (i) / 500.);
+
+ if (lutLocretigainCurverab[i] < 0.02f) {
+ lutLocretigainCurverab[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value
+ }
+
+ sum += lutLocretigainCurverab[i];
+ }
+
+ //lutLocCurve.dump("wav");
+}
+
+void LocretigainCurverab::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();
+ }
+}
+
+LocLHCurve::LocLHCurve() : sum (0.f) {};
+
+void LocLHCurve::Reset()
+{
+ lutLocLHCurve.reset();
+ sum = 0.f;
+}
+
+void LocLHCurve::Set (const Curve &pCurve)
+{
+ if (pCurve.isIdentity()) {
+ Reset(); // raise this value if the quality suffers from this number of samples
+ return;
+ }
+
+ lutLocLHCurve (501); // raise this value if the quality suffers from this number of samples
+ sum = 0.f;
+
+ for (int i = 0; i < 501; i++) {
+ lutLocLHCurve[i] = pCurve.getVal (double (i) / 500.);
+
+ if (lutLocLHCurve[i] < 0.02f) {
+ lutLocLHCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value
+ }
+
+ sum += lutLocLHCurve[i];
+ }
+
+ //lutLocCurve.dump("wav");
+}
+
+void LocLHCurve::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();
+ }
+}
+
+
+LocretigainCurve::LocretigainCurve() : sum (0.f) {};
+
+void LocretigainCurve::Reset()
+{
+ lutLocretigainCurve.reset();
+ sum = 0.f;
+}
+
+void LocretigainCurve::Set (const Curve &pCurve)
+{
+ if (pCurve.isIdentity()) {
+ Reset(); // raise this value if the quality suffers from this number of samples
+ return;
+ }
+
+ lutLocretigainCurve (501); // raise this value if the quality suffers from this number of samples
+ sum = 0.f;
+
+ for (int i = 0; i < 501; i++) {
+ lutLocretigainCurve[i] = pCurve.getVal (double (i) / 500.);
+
+ if (lutLocretigainCurve[i] < 0.02f) {
+ lutLocretigainCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value
+ }
+
+ sum += lutLocretigainCurve[i];
+ }
+
+ //lutLocCurve.dump("wav");
+}
+void LocretigainCurve::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 ColorAppearance::Reset()
{
lutColCurve.reset();
}
// Fill a LUT with X/Y, ranged 0xffff
-void ColorAppearance::Set(const Curve &pCurve)
+void ColorAppearance::Set (const Curve &pCurve)
{
- lutColCurve(65536);
+ lutColCurve (65536);
for (int i = 0; i < 65536; i++) {
- lutColCurve[i] = pCurve.getVal(double(i) / 65535.) * 65535.;
+ lutColCurve[i] = pCurve.getVal (double (i) / 65535.) * 65535.;
}
}
@@ -1000,26 +1338,26 @@ void RetinextransmissionCurve::Reset()
luttransmission.reset();
}
-void RetinextransmissionCurve::Set(const Curve &pCurve)
+void RetinextransmissionCurve::Set (const Curve &pCurve)
{
if (pCurve.isIdentity()) {
luttransmission.reset(); // raise this value if the quality suffers from this number of samples
return;
}
- luttransmission(501); // raise this value if the quality suffers from this number of samples
+ luttransmission (501); // raise this value if the quality suffers from this number of samples
for (int i = 0; i < 501; i++) {
- luttransmission[i] = pCurve.getVal(double(i) / 500.);
+ luttransmission[i] = pCurve.getVal (double (i) / 500.);
}
}
-void RetinextransmissionCurve::Set(const std::vector &curvePoints)
+void RetinextransmissionCurve::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);
+ FlatCurve tcurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue (0.);
+ Set (tcurve);
} else {
Reset();
}
@@ -1033,26 +1371,26 @@ void RetinexgaintransmissionCurve::Reset()
lutgaintransmission.reset();
}
-void RetinexgaintransmissionCurve::Set(const Curve &pCurve)
+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
+ 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.);
+ lutgaintransmission[i] = pCurve.getVal (double (i) / 500.);
}
}
-void RetinexgaintransmissionCurve::Set(const std::vector &curvePoints)
+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);
+ FlatCurve tcurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue (0.);
+ Set (tcurve);
} else {
Reset();
}
@@ -1064,34 +1402,34 @@ void ToneCurve::Reset()
}
// Fill a LUT with X/Y, ranged 0xffff
-void ToneCurve::Set(const Curve &pCurve, float gamma)
+void ToneCurve::Set (const Curve &pCurve, float gamma)
{
- lutToneCurve(65536);
+ lutToneCurve (65536);
if (gamma <= 0.0 || gamma == 1.) {
for (int i = 0; i < 65536; i++) {
- lutToneCurve[i] = (float)pCurve.getVal(float(i) / 65535.f) * 65535.f;
+ lutToneCurve[i] = (float)pCurve.getVal (float (i) / 65535.f) * 65535.f;
}
- } else if(gamma == (float)Color::sRGBGammaCurve) {
+ } else if (gamma == (float)Color::sRGBGammaCurve) {
// for sRGB gamma we can use luts, which is much faster
for (int i = 0; i < 65536; i++) {
float val = Color::gammatab_srgb[i] / 65535.f;
- val = pCurve.getVal(val);
+ val = pCurve.getVal (val);
val = Color::igammatab_srgb[val * 65535.f];
lutToneCurve[i] = val;
}
} else {
- const float start = expf(gamma * logf( -0.055 / ((1.0 / gamma - 1.0) * 1.055 )));
+ const float start = expf (gamma * logf ( -0.055 / ((1.0 / gamma - 1.0) * 1.055 )));
const float slope = 1.055 * powf (start, 1.0 / gamma - 1) - 0.055 / start;
const float mul = 1.055;
const float add = 0.055;
// apply gamma, that is 'pCurve' is defined with the given gamma and here we convert it to a curve in linear space
for (int i = 0; i < 65536; i++) {
- float val = float(i) / 65535.f;
+ float val = float (i) / 65535.f;
val = CurveFactory::gamma (val, gamma, start, slope, mul, add);
- val = pCurve.getVal(val);
+ val = pCurve.getVal (val);
val = CurveFactory::igamma (val, gamma, start, slope, mul, add);
lutToneCurve[i] = val * 65535.f;
}
@@ -1103,40 +1441,40 @@ void OpacityCurve::Reset()
lutOpacityCurve.reset();
}
-void OpacityCurve::Set(const Curve *pCurve)
+void OpacityCurve::Set (const Curve *pCurve)
{
if (pCurve->isIdentity()) {
lutOpacityCurve.reset(); // raise this value if the quality suffers from this number of samples
return;
}
- lutOpacityCurve(501); // raise this value if the quality suffers from this number of samples
+ lutOpacityCurve (501); // raise this value if the quality suffers from this number of samples
for (int i = 0; i < 501; i++) {
- lutOpacityCurve[i] = pCurve->getVal(double(i) / 500.);
+ lutOpacityCurve[i] = pCurve->getVal (double (i) / 500.);
}
//lutOpacityCurve.dump("opacity");
}
-void OpacityCurve::Set(const std::vector &curvePoints, bool &opautili)
+void OpacityCurve::Set (const std::vector &curvePoints, bool &opautili)
{
std::unique_ptr tcurve;
if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
- tcurve = std::unique_ptr(new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
- tcurve->setIdentityValue(0.);
+ tcurve = std::unique_ptr (new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
+ tcurve->setIdentityValue (0.);
}
if (tcurve) {
- Set(tcurve.get());
+ Set (tcurve.get());
opautili = true;
tcurve = nullptr;
}
}
-WavCurve::WavCurve() : sum(0.f) {};
+WavCurve::WavCurve() : sum (0.f) {};
void WavCurve::Reset()
{
@@ -1144,20 +1482,20 @@ void WavCurve::Reset()
sum = 0.f;
}
-void WavCurve::Set(const Curve &pCurve)
+void WavCurve::Set (const Curve &pCurve)
{
if (pCurve.isIdentity()) {
Reset(); // raise this value if the quality suffers from this number of samples
return;
}
- lutWavCurve(501); // raise this value if the quality suffers from this number of samples
+ lutWavCurve (501); // raise this value if the quality suffers from this number of samples
sum = 0.f;
for (int i = 0; i < 501; i++) {
- lutWavCurve[i] = pCurve.getVal(double(i) / 500.);
+ lutWavCurve[i] = pCurve.getVal (double (i) / 500.);
- if(lutWavCurve[i] < 0.02f) {
+ if (lutWavCurve[i] < 0.02f) {
lutWavCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value
}
@@ -1166,13 +1504,13 @@ void WavCurve::Set(const Curve &pCurve)
//lutWavCurve.dump("wav");
}
-void WavCurve::Set(const std::vector &curvePoints)
+void WavCurve::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);
+ FlatCurve tcurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue (0.);
+ Set (tcurve);
} else {
Reset();
}
@@ -1186,26 +1524,26 @@ void WavOpacityCurveRG::Reset()
lutOpacityCurveRG.reset();
}
-void WavOpacityCurveRG::Set(const Curve &pCurve)
+void WavOpacityCurveRG::Set (const Curve &pCurve)
{
if (pCurve.isIdentity()) {
Reset(); // raise this value if the quality suffers from this number of samples
return;
}
- lutOpacityCurveRG(501); // raise this value if the quality suffers from this number of samples
+ lutOpacityCurveRG (501); // raise this value if the quality suffers from this number of samples
for (int i = 0; i < 501; i++) {
- lutOpacityCurveRG[i] = pCurve.getVal(double(i) / 500.);
+ lutOpacityCurveRG[i] = pCurve.getVal (double (i) / 500.);
}
}
-void WavOpacityCurveRG::Set(const std::vector &curvePoints)
+void WavOpacityCurveRG::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);
+ FlatCurve tcurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue (0.);
+ Set (tcurve);
} else {
Reset();
}
@@ -1219,26 +1557,26 @@ void WavOpacityCurveBY::Reset()
lutOpacityCurveBY.reset();
}
-void WavOpacityCurveBY::Set(const Curve &pCurve)
+void WavOpacityCurveBY::Set (const Curve &pCurve)
{
if (pCurve.isIdentity()) {
lutOpacityCurveBY.reset(); // raise this value if the quality suffers from this number of samples
return;
}
- lutOpacityCurveBY(501); // raise this value if the quality suffers from this number of samples
+ lutOpacityCurveBY (501); // raise this value if the quality suffers from this number of samples
for (int i = 0; i < 501; i++) {
- lutOpacityCurveBY[i] = pCurve.getVal(double(i) / 500.);
+ lutOpacityCurveBY[i] = pCurve.getVal (double (i) / 500.);
}
}
-void WavOpacityCurveBY::Set(const std::vector &curvePoints)
+void WavOpacityCurveBY::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);
+ FlatCurve tcurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue (0.);
+ Set (tcurve);
} else {
Reset();
}
@@ -1251,26 +1589,26 @@ void WavOpacityCurveW::Reset()
lutOpacityCurveW.reset();
}
-void WavOpacityCurveW::Set(const Curve &pCurve)
+void WavOpacityCurveW::Set (const Curve &pCurve)
{
if (pCurve.isIdentity()) {
lutOpacityCurveW.reset(); // raise this value if the quality suffers from this number of samples
return;
}
- lutOpacityCurveW(501); // raise this value if the quality suffers from this number of samples
+ lutOpacityCurveW (501); // raise this value if the quality suffers from this number of samples
for (int i = 0; i < 501; i++) {
- lutOpacityCurveW[i] = pCurve.getVal(double(i) / 500.);
+ lutOpacityCurveW[i] = pCurve.getVal (double (i) / 500.);
}
}
-void WavOpacityCurveW::Set(const std::vector &curvePoints)
+void WavOpacityCurveW::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);
+ FlatCurve tcurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue (0.);
+ Set (tcurve);
} else {
Reset();
}
@@ -1283,33 +1621,33 @@ void WavOpacityCurveWL::Reset()
lutOpacityCurveWL.reset();
}
-void WavOpacityCurveWL::Set(const Curve &pCurve)
+void WavOpacityCurveWL::Set (const Curve &pCurve)
{
if (pCurve.isIdentity()) {
lutOpacityCurveWL.reset(); // raise this value if the quality suffers from this number of samples
return;
}
- lutOpacityCurveWL(501); // raise this value if the quality suffers from this number of samples
+ lutOpacityCurveWL (501); // raise this value if the quality suffers from this number of samples
for (int i = 0; i < 501; i++) {
- lutOpacityCurveWL[i] = pCurve.getVal(double(i) / 500.);
+ lutOpacityCurveWL[i] = pCurve.getVal (double (i) / 500.);
}
}
-void WavOpacityCurveWL::Set(const std::vector &curvePoints)
+void WavOpacityCurveWL::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);
+ FlatCurve tcurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue (0.);
+ Set (tcurve);
} else {
Reset();
}
}
-NoiseCurve::NoiseCurve() : sum(0.f) {};
+NoiseCurve::NoiseCurve() : sum (0.f) {};
void NoiseCurve::Reset()
{
@@ -1317,20 +1655,20 @@ void NoiseCurve::Reset()
sum = 0.f;
}
-void NoiseCurve::Set(const Curve &pCurve)
+void NoiseCurve::Set (const Curve &pCurve)
{
if (pCurve.isIdentity()) {
Reset(); // raise this value if the quality suffers from this number of samples
return;
}
- lutNoiseCurve(501); // raise this value if the quality suffers from this number of samples
+ lutNoiseCurve (501); // raise this value if the quality suffers from this number of samples
sum = 0.f;
for (int i = 0; i < 501; i++) {
- lutNoiseCurve[i] = pCurve.getVal(double(i) / 500.);
+ lutNoiseCurve[i] = pCurve.getVal (double (i) / 500.);
- if(lutNoiseCurve[i] < 0.01f) {
+ if (lutNoiseCurve[i] < 0.01f) {
lutNoiseCurve[i] = 0.01f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value
}
@@ -1340,13 +1678,13 @@ void NoiseCurve::Set(const Curve &pCurve)
//lutNoisCurve.dump("Nois");
}
-void NoiseCurve::Set(const std::vector &curvePoints)
+void NoiseCurve::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);
+ FlatCurve tcurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue (0.);
+ Set (tcurve);
} else {
Reset();
}
@@ -1360,7 +1698,7 @@ void ColorGradientCurve::Reset()
lut3.reset();
}
-void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin)
+void ColorGradientCurve::SetXYZ (const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin)
{
if (pCurve->isIdentity()) {
lut1.reset();
@@ -1370,9 +1708,9 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3],
}
if (!lut1) {
- lut1(501);
- lut2(501);
- lut3(501);
+ lut1 (501);
+ lut2 (501);
+ lut3 (501);
}
float r, g, b, xx, yy, zz;
@@ -1380,8 +1718,8 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3],
int upperBound = lut1.getUpperBound();
if (pCurve->isIdentity()) {
- Color::hsv2rgb(0.5f, satur, lumin, r, g, b);
- Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb);
+ Color::hsv2rgb (0.5f, satur, lumin, r, g, b);
+ Color::rgbxyz (r, g, b, xx, yy, zz, xyz_rgb);
for (int i = 0; i <= 500; ++i) {
// WARNING: set the identity value according to what is set in the GUI
@@ -1396,7 +1734,7 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3],
int nPoints = pCurve->getSize();
int ptNum = 0;
double nextX, nextY;
- pCurve->getControlPoint(ptNum, nextX, nextY);
+ pCurve->getControlPoint (ptNum, nextX, nextY);
double prevY = nextY;
double dY = 0.;
low = nextX;
@@ -1404,14 +1742,14 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3],
//lr1=low;
for (int i = 0; i <= upperBound; ++i) {
- double x = double(i) / double(upperBound);
+ double x = double (i) / double (upperBound);
if (x > nextX) {
++ptNum;
if (ptNum < nPoints) {
prevY = nextY;
- pCurve->getControlPoint(ptNum, nextX, nextY);
+ pCurve->getControlPoint (ptNum, nextX, nextY);
dY = nextY - prevY;
high = nextX;
lr2 = (0.5f + high) / 2.f; //optimize use of gamut in high light..one can optimize more using directly high ?
@@ -1420,70 +1758,70 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3],
}
if (!ptNum) {
- Color::hsv2rgb(float(prevY), satur, lr1, r, g, b);
- Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb);
+ Color::hsv2rgb (float (prevY), satur, lr1, r, g, b);
+ Color::rgbxyz (r, g, b, xx, yy, zz, xyz_rgb);
lut1[i] = xx;
lut2[i] = yy;
lut3[i] = zz;
} else if (ptNum >= nPoints) {
- Color::hsv2rgb(float(nextY), satur, lr2, r, g, b);
- Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb);
+ Color::hsv2rgb (float (nextY), satur, lr2, r, g, b);
+ Color::rgbxyz (r, g, b, xx, yy, zz, xyz_rgb);
lut1[i] = xx;
lut2[i] = yy;
lut3[i] = zz;
} else {
- double currY = pCurve->getVal(x) - prevY;
+ double currY = pCurve->getVal (x) - prevY;
if (dY > 0.000001 || dY < -0.000001) {
float r1, g1, b1, r2, g2, b2;
- Color::hsv2rgb(float(prevY), satur, lr1, r1, g1, b1);
- Color::hsv2rgb(float(nextY), satur, lr2, r2, g2, b2);
+ Color::hsv2rgb (float (prevY), satur, lr1, r1, g1, b1);
+ Color::hsv2rgb (float (nextY), satur, lr2, r2, g2, b2);
LUTf dum;
float X1, X2, Y1, Y2, Z1, Z2, L1, a_1, b_1, c1, h1;
- Color::rgbxyz(r2, g2, b2, X2, Y2, Z2, xyz_rgb);
- Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb);
+ Color::rgbxyz (r2, g2, b2, X2, Y2, Z2, xyz_rgb);
+ Color::rgbxyz (r1, g1, b1, X1, Y1, Z1, xyz_rgb);
//I use XYZ to mix color 1 and 2 rather than rgb (gamut) and rather than Lab artifacts
X1 = X1 + (X2 - X1) * currY / dY;
- if(X1 < 0.f) {
+ if (X1 < 0.f) {
X1 = 0.f; //negative value not good
}
Y1 = Y1 + (Y2 - Y1) * currY / dY;
- if(Y1 < 0.f) {
+ if (Y1 < 0.f) {
Y1 = 0.f;
}
Z1 = Z1 + (Z2 - Z1) * currY / dY;
- if(Z1 < 0.f) {
+ if (Z1 < 0.f) {
Z1 = 0.f;
}
- Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1);//prepare to gamut control
- Color::Lab2Lch(a_1, b_1, c1, h1);
+ Color::XYZ2Lab (X1, Y1, Z1, L1, a_1, b_1); //prepare to gamut control
+ Color::Lab2Lch (a_1, b_1, c1, h1);
float Lr = L1 / 327.68f;
float RR, GG, BB;
#ifndef NDEBUG
bool neg = false;
bool more_rgb = false;
//gamut control : Lab values are in gamut
- Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb);
+ Color::gamutLchonly (h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb);
#else
- Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f);
+ Color::gamutLchonly (h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f);
#endif
L1 = Lr * 327.68f;
float a, b, X, Y, Z;
// converting back to rgb
- Color::Lch2Lab(c1, h1, a, b);
- Color::Lab2XYZ(L1, a, b, X, Y, Z);
+ Color::Lch2Lab (c1, h1, a, b);
+ Color::Lab2XYZ (L1, a, b, X, Y, Z);
lut1[i] = X;
lut2[i] = Y;
lut3[i] = Z;
} else {
- Color::hsv2rgb(float(nextY), satur, lumin, r, g, b);
- Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb);
+ Color::hsv2rgb (float (nextY), satur, lumin, r, g, b);
+ Color::rgbxyz (r, g, b, xx, yy, zz, xyz_rgb);
lut1[i] = xx;
lut2[i] = yy;
lut3[i] = zz;
@@ -1500,20 +1838,20 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3],
*/
}
-void ColorGradientCurve::SetXYZ(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin)
+void ColorGradientCurve::SetXYZ (const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin)
{
std::unique_ptr tcurve;
if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
- tcurve = std::unique_ptr(new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
+ tcurve = std::unique_ptr (new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
}
if (tcurve) {
- SetXYZ(tcurve.get(), xyz_rgb, rgb_xyz, satur, lumin);
+ SetXYZ (tcurve.get(), xyz_rgb, rgb_xyz, satur, lumin);
}
}
-void ColorGradientCurve::SetRGB(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3])
+void ColorGradientCurve::SetRGB (const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3])
{
if (pCurve->isIdentity()) {
lut1.reset();
@@ -1523,9 +1861,9 @@ void ColorGradientCurve::SetRGB(const Curve *pCurve, const double xyz_rgb[3][3],
}
if (!lut1) {
- lut1(501);
- lut2(501);
- lut3(501);
+ lut1 (501);
+ lut2 (501);
+ lut3 (501);
}
float r, g, b;
@@ -1535,54 +1873,54 @@ void ColorGradientCurve::SetRGB(const Curve *pCurve, const double xyz_rgb[3][3],
int nPoints = pCurve->getSize();
int ptNum = 0;
double nextX, nextY;
- pCurve->getControlPoint(ptNum, nextX, nextY);
+ pCurve->getControlPoint (ptNum, nextX, nextY);
double prevY = nextY;
double dY = 0.;
Color::eInterpolationDirection dir = Color::ID_DOWN;
for (int i = 0; i <= upperBound; ++i) {
- double x = double(i) / double(upperBound);
+ double x = double (i) / double (upperBound);
if (x > nextX) {
++ptNum;
if (ptNum < nPoints) {
prevY = nextY;
- pCurve->getControlPoint(ptNum, nextX, nextY);
+ pCurve->getControlPoint (ptNum, nextX, nextY);
dY = nextY - prevY;
- dir = Color::getHueInterpolationDirection(prevY, nextY, Color::IP_SHORTEST);
+ dir = Color::getHueInterpolationDirection (prevY, nextY, Color::IP_SHORTEST);
}
}
if (!ptNum) {
- Color::hsv2rgb(float(prevY), 1.f, 1.f, r, g, b);
+ Color::hsv2rgb (float (prevY), 1.f, 1.f, r, g, b);
lut1[i] = r;
lut2[i] = g;
lut3[i] = b;
} else if (ptNum >= nPoints) {
- Color::hsv2rgb(float(nextY), 1.f, 1.f, r, g, b);
+ Color::hsv2rgb (float (nextY), 1.f, 1.f, r, g, b);
lut1[i] = r;
lut2[i] = g;
lut3[i] = b;
} else {
- double currY = pCurve->getVal(x) - prevY;
+ double currY = pCurve->getVal (x) - prevY;
if (dY > 0.0000001 || dY < -0.0000001) {
#if 1
float ro, go, bo;
- double h2 = Color::interpolateHueHSV(prevY, nextY, currY / dY, dir);
- Color::hsv2rgb(h2, 1.f, 1.f, ro, go, bo);
+ double h2 = Color::interpolateHueHSV (prevY, nextY, currY / dY, dir);
+ Color::hsv2rgb (h2, 1.f, 1.f, ro, go, bo);
#else
float r1, g1, b1, r2, g2, b2, ro, go, bo;
- Color::hsv2rgb(float(prevY), 1., 1., r1, g1, b1);
- Color::hsv2rgb(float(nextY), 1., 1., r2, g2, b2);
- Color::interpolateRGBColor(currY / dY, r1, g1, b1, r2, g2, b2, Color::CHANNEL_LIGHTNESS | Color::CHANNEL_CHROMATICITY | Color::CHANNEL_HUE, xyz_rgb, rgb_xyz, ro, go, bo);
+ Color::hsv2rgb (float (prevY), 1., 1., r1, g1, b1);
+ Color::hsv2rgb (float (nextY), 1., 1., r2, g2, b2);
+ Color::interpolateRGBColor (currY / dY, r1, g1, b1, r2, g2, b2, Color::CHANNEL_LIGHTNESS | Color::CHANNEL_CHROMATICITY | Color::CHANNEL_HUE, xyz_rgb, rgb_xyz, ro, go, bo);
#endif
lut1[i] = ro;
lut2[i] = go;
lut3[i] = bo;
} else {
- Color::hsv2rgb(float(nextY), 1.f, 1.f, r, g, b);
+ Color::hsv2rgb (float (nextY), 1.f, 1.f, r, g, b);
lut1[i] = r;
lut2[i] = g;
lut3[i] = b;
@@ -1599,20 +1937,20 @@ void ColorGradientCurve::SetRGB(const Curve *pCurve, const double xyz_rgb[3][3],
*/
}
-void ColorGradientCurve::SetRGB(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3])
+void ColorGradientCurve::SetRGB (const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3])
{
std::unique_ptr tcurve;
if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
- tcurve = std::unique_ptr(new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
+ tcurve = std::unique_ptr (new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
}
if (tcurve) {
- SetRGB(tcurve.get(), xyz_rgb, rgb_xyz);
+ SetRGB (tcurve.get(), xyz_rgb, rgb_xyz);
}
}
-void ColorGradientCurve::getVal(float index, float &r, float &g, float &b) const
+void ColorGradientCurve::getVal (float index, float &r, float &g, float &b) const
{
r = lut1[index * 500.f];
g = lut2[index * 500.f];
@@ -1620,15 +1958,15 @@ void ColorGradientCurve::getVal(float index, float &r, float &g, float &b) const
}
// this is a generic cubic spline implementation, to clean up we could probably use something already existing elsewhere
-void PerceptualToneCurve::cubic_spline(const float x[], const float y[], const int len, const float out_x[], float out_y[], const int out_len)
+void PerceptualToneCurve::cubic_spline (const float x[], const float y[], const int len, const float out_x[], float out_y[], const int out_len)
{
int i, j;
- float **A = (float **)malloc(2 * len * sizeof(*A));
- float *As = (float *)calloc(1, 2 * len * 2 * len * sizeof(*As));
- float *b = (float *)calloc(1, 2 * len * sizeof(*b));
- float *c = (float *)calloc(1, 2 * len * sizeof(*c));
- float *d = (float *)calloc(1, 2 * len * sizeof(*d));
+ float **A = (float **)malloc (2 * len * sizeof (*A));
+ float *As = (float *)calloc (1, 2 * len * 2 * len * sizeof (*As));
+ float *b = (float *)calloc (1, 2 * len * sizeof (*b));
+ float *c = (float *)calloc (1, 2 * len * sizeof (*c));
+ float *d = (float *)calloc (1, 2 * len * sizeof (*d));
for (i = 0; i < 2 * len; i++) {
A[i] = &As[2 * len * i];
@@ -1650,18 +1988,18 @@ void PerceptualToneCurve::cubic_spline(const float x[], const float y[], const i
A[i][len - 1] = 6 * (b[i + 1] - b[i]);
}
- for(i = 1; i < len - 2; i++) {
+ for (i = 1; i < len - 2; i++) {
float v = A[i + 1][i] / A[i][i];
- for(j = 1; j <= len - 1; j++) {
+ for (j = 1; j <= len - 1; j++) {
A[i + 1][j] -= v * A[i][j];
}
}
- for(i = len - 2; i > 0; i--) {
+ for (i = len - 2; i > 0; i--) {
float acc = 0;
- for(j = i; j <= len - 2; j++) {
+ for (j = i; j <= len - 2; j++) {
acc += A[i][j] * c[j];
}
@@ -1685,35 +2023,35 @@ void PerceptualToneCurve::cubic_spline(const float x[], const float y[], const i
out_y[i] = y_out;
}
- free(A);
- free(As);
- free(b);
- free(c);
- free(d);
+ free (A);
+ free (As);
+ free (b);
+ free (c);
+ free (d);
}
// generic function for finding minimum of f(x) in the a-b range using the interval halving method
-float PerceptualToneCurve::find_minimum_interval_halving(float (*func)(float x, void *arg), void *arg, float a, float b, float tol, int nmax)
+float PerceptualToneCurve::find_minimum_interval_halving (float (*func) (float x, void *arg), void *arg, float a, float b, float tol, int nmax)
{
float L = b - a;
float x = (a + b) * 0.5;
for (int i = 0; i < nmax; i++) {
- float f_x = func(x, arg);
+ float f_x = func (x, arg);
if ((b - a) * 0.5 < tol) {
return x;
}
float x1 = a + L / 4;
- float f_x1 = func(x1, arg);
+ float f_x1 = func (x1, arg);
if (f_x1 < f_x) {
b = x;
x = x1;
} else {
float x2 = b - L / 4;
- float f_x2 = func(x2, arg);
+ float f_x2 = func (x2, arg);
if (f_x2 < f_x) {
a = x;
@@ -1734,7 +2072,7 @@ struct find_tc_slope_fun_arg {
const ToneCurve * tc;
};
-float PerceptualToneCurve::find_tc_slope_fun(float k, void *arg)
+float PerceptualToneCurve::find_tc_slope_fun (float k, void *arg)
{
struct find_tc_slope_fun_arg *a = (struct find_tc_slope_fun_arg *)arg;
float areasum = 0;
@@ -1742,7 +2080,7 @@ float PerceptualToneCurve::find_tc_slope_fun(float k, void *arg)
for (int i = 0; i < steps; i++) {
float x = 0.1 + ((float)i / (steps - 1)) * 0.5; // testing (sRGB) range [0.1 - 0.6], ie ignore highligths and dark shadows
- float y = CurveFactory::gamma2(a->tc->lutToneCurve[CurveFactory::igamma2(x) * 65535] / 65535.0);
+ float y = CurveFactory::gamma2 (a->tc->lutToneCurve[CurveFactory::igamma2 (x) * 65535] / 65535.0);
float y1 = k * x;
if (y1 > 1) {
@@ -1755,7 +2093,7 @@ float PerceptualToneCurve::find_tc_slope_fun(float k, void *arg)
return areasum;
}
-float PerceptualToneCurve::get_curve_val(float x, float range[2], float lut[], size_t lut_size)
+float PerceptualToneCurve::get_curve_val (float x, float range[2], float lut[], size_t lut_size)
{
float xm = (x - range[0]) / (range[1] - range[0]) * (lut_size - 1);
@@ -1781,7 +2119,7 @@ float PerceptualToneCurve::calculateToneCurveContrastValue() const
// Note: the analysis is made on the gamma encoded curve, as the LUT is linear we make backwards gamma to
struct find_tc_slope_fun_arg arg = { this };
- float k = find_minimum_interval_halving(find_tc_slope_fun, &arg, 0.1, 5.0, 0.01, 20); // normally found in 8 iterations
+ float k = find_minimum_interval_halving (find_tc_slope_fun, &arg, 0.1, 5.0, 0.01, 20); // normally found in 8 iterations
//fprintf(stderr, "average slope: %f\n", k);
float maxslope = 0;
@@ -1790,11 +2128,11 @@ float PerceptualToneCurve::calculateToneCurveContrastValue() const
const float xd = 0.07;
const float tx[] = { 0.30, 0.35, 0.40, 0.45 }; // we only look in the midtone range
- for (int i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) {
+ for (int i = 0; i < sizeof (tx) / sizeof (tx[0]); i++) {
float x0 = tx[i] - xd;
- float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0;
+ float y0 = CurveFactory::gamma2 (lutToneCurve[CurveFactory::igamma2 (x0) * 65535.f] / 65535.f) - k * x0;
float x1 = tx[i] + xd;
- float y1 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x1) * 65535.f] / 65535.f) - k * x1;
+ float y1 = CurveFactory::gamma2 (lutToneCurve[CurveFactory::igamma2 (x1) * 65535.f] / 65535.f) - k * x1;
float slope = 1.0 + (y1 - y0) / (x1 - x0);
if (slope > maxslope) {
@@ -1807,11 +2145,11 @@ float PerceptualToneCurve::calculateToneCurveContrastValue() const
{
const float tx[] = { 0.20, 0.25, 0.50, 0.55 }; // we only look in the midtone range
- for (int i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) {
+ for (int i = 0; i < sizeof (tx) / sizeof (tx[0]); i++) {
float x0 = tx[i] - xd;
- float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0;
+ float y0 = CurveFactory::gamma2 (lutToneCurve[CurveFactory::igamma2 (x0) * 65535.f] / 65535.f) - k * x0;
float x1 = tx[i] + xd;
- float y1 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x1) * 65535.f] / 65535.f) - k * x1;
+ float y1 = CurveFactory::gamma2 (lutToneCurve[CurveFactory::igamma2 (x1) * 65535.f] / 65535.f) - k * x1;
float slope = 1.0 + (y1 - y0) / (x1 - x0);
if (slope > e_maxslope) {
@@ -1826,7 +2164,7 @@ float PerceptualToneCurve::calculateToneCurveContrastValue() const
return maxslope;
}
-void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurveState & state) const
+void PerceptualToneCurve::Apply (float &r, float &g, float &b, PerceptualToneCurveState & state) const
{
float x, y, z;
@@ -1840,11 +2178,11 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
b = newb;
}
- const AdobeToneCurve& adobeTC = static_cast((const ToneCurve&) * this);
+ const AdobeToneCurve& adobeTC = static_cast ((const ToneCurve&) * this);
float ar = r;
float ag = g;
float ab = b;
- adobeTC.Apply(ar, ag, ab);
+ adobeTC.Apply (ar, ag, ab);
if (ar >= 65535.f && ag >= 65535.f && ab >= 65535.f) {
// clip fast path, will also avoid strange colors of clipped highlights
@@ -1867,22 +2205,22 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
float oldLuminance = r * Yr + g * Yg + b * Yb;
float newLuminance = ar * Yr + ag * Yg + ab * Yb;
float Lcoef = newLuminance / oldLuminance;
- r = LIM(r * Lcoef, 0.f, 65535.f);
- g = LIM(g * Lcoef, 0.f, 65535.f);
- b = LIM(b * Lcoef, 0.f, 65535.f);
+ r = LIM (r * Lcoef, 0.f, 65535.f);
+ g = LIM (g * Lcoef, 0.f, 65535.f);
+ b = LIM (b * Lcoef, 0.f, 65535.f);
// move to JCh so we can modulate chroma based on the global contrast-related chroma scaling factor
- Color::Prophotoxyz(r, g, b, x, y, z);
+ Color::Prophotoxyz (r, g, b, x, y, z);
float J, C, h;
- Ciecam02::xyz2jch_ciecam02float( J, C, h,
- aw, fl,
- x * 0.0015259022f, y * 0.0015259022f, z * 0.0015259022f,
- xw, yw, zw,
- c, nc, pow1, nbb, ncb, cz, d);
+ Ciecam02::xyz2jch_ciecam02float ( J, C, h,
+ aw, fl,
+ x * 0.0015259022f, y * 0.0015259022f, z * 0.0015259022f,
+ xw, yw, zw,
+ c, nc, pow1, nbb, ncb, cz, d);
- if (!isfinite(J) || !isfinite(C) || !isfinite(h)) {
+ if (!isfinite (J) || !isfinite (C) || !isfinite (h)) {
// this can happen for dark noise colors or colors outside human gamut. Then we just return the curve's result.
if (!state.isProphoto) {
float newr = state.Prophoto2Working[0][0] * r + state.Prophoto2Working[0][1] * g + state.Prophoto2Working[0][2] * b;
@@ -1914,9 +2252,9 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
float x = (C - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim
if (x < 0.5f) {
- x = 2.f * SQR(x);
+ x = 2.f * SQR (x);
} else {
- x = 1.f - 2.f * SQR(1 - x);
+ x = 1.f - 2.f * SQR (1 - x);
}
saturated_scale_factor = (1.f - x) + saturated_scale_factor * x;
@@ -1942,9 +2280,9 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
float x = (nL - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim
if (x < 0.5f) {
- x = 2.f * SQR(x);
+ x = 2.f * SQR (x);
} else {
- x = 1.f - 2.f * SQR(1 - x);
+ x = 1.f - 2.f * SQR (1 - x);
}
dark_scale_factor = dark_scale_factor * (1.0f - x) + x;
@@ -1968,9 +2306,9 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
float x = (J - lolim) / (hilim - lolim);
if (x < 0.5f) {
- x = 2.f * SQR(x);
+ x = 2.f * SQR (x);
} else {
- x = 1.f - 2.f * SQR(1 - x);
+ x = 1.f - 2.f * SQR (1 - x);
}
dark_scale_factor = dark_scale_factor * (1.f - x) + x;
@@ -1983,12 +2321,12 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
C *= cmul;
- Ciecam02::jch2xyz_ciecam02float( x, y, z,
- J, C, h,
- xw, yw, zw,
- f, c, nc, 1, pow1, nbb, ncb, fl, cz, d, aw );
+ Ciecam02::jch2xyz_ciecam02float ( x, y, z,
+ J, C, h,
+ xw, yw, zw,
+ f, c, nc, 1, pow1, nbb, ncb, fl, cz, d, aw );
- if (!isfinite(x) || !isfinite(y) || !isfinite(z)) {
+ if (!isfinite (x) || !isfinite (y) || !isfinite (z)) {
// can happen for colors on the rim of being outside gamut, that worked without chroma scaling but not with. Then we return only the curve's result.
if (!state.isProphoto) {
float newr = state.Prophoto2Working[0][0] * r + state.Prophoto2Working[0][1] * g + state.Prophoto2Working[0][2] * b;
@@ -2002,13 +2340,13 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
return;
}
- Color::xyz2Prophoto(x, y, z, r, g, b);
+ Color::xyz2Prophoto (x, y, z, r, g, b);
r *= 655.35f;
g *= 655.35f;
b *= 655.35f;
- r = LIM(r, 0.f, 65535.f);
- g = LIM(g, 0.f, 65535.f);
- b = LIM(b, 0.f, 65535.f);
+ r = LIM (r, 0.f, 65535.f);
+ g = LIM (g, 0.f, 65535.f);
+ b = LIM (b, 0.f, 65535.f);
{
// limit saturation increase in rgb space to avoid severe clipping and flattening in extreme highlights
@@ -2017,8 +2355,8 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
// saturation greatly, but desaturates extreme highlights and thus provide a smooth transition to
// the white point. However the desaturation effect is quite strong so we make a weighting
float ah, as, av, h, s, v;
- Color::rgb2hsv(ar, ag, ab, ah, as, av);
- Color::rgb2hsv(r, g, b, h, s, v);
+ Color::rgb2hsv (ar, ag, ab, ah, as, av);
+ Color::rgb2hsv (r, g, b, h, s, v);
float sat_scale = as <= 0.f ? 1.f : s / as; // saturation scale compared to Adobe curve
float keep = 0.2f;
@@ -2033,9 +2371,9 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv
float x = (sat_scale - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim
if (x < 0.5f) {
- x = 2.f * SQR(x);
+ x = 2.f * SQR (x);
} else {
- x = 1.f - 2.f * SQR(1 - x);
+ x = 1.f - 2.f * SQR (1 - x);
}
keep = (1.f - x) + keep * x;
@@ -2079,9 +2417,9 @@ void PerceptualToneCurve::init()
c = 0.69f;
nc = 1.00f;
- Ciecam02::initcam1float(gamut, yb, 1.f, f, la, xw, yw, zw, n, d, nbb, ncb,
- cz, aw, wh, pfl, fl, c);
- pow1 = pow_F( 1.64f - pow_F( 0.29f, n ), 0.73f );
+ Ciecam02::initcam1float (gamut, yb, 1.f, f, la, xw, yw, zw, n, d, nbb, ncb,
+ cz, aw, wh, pfl, fl, c);
+ pow1 = pow_F ( 1.64f - pow_F ( 0.29f, n ), 0.73f );
{
// init contrast-value-to-chroma-scaling conversion curve
@@ -2105,7 +2443,7 @@ void PerceptualToneCurve::init()
2.00, 1.22 // highest contrast
};
- const size_t in_len = sizeof(p) / sizeof(p[0]) / 2;
+ const size_t in_len = sizeof (p) / sizeof (p[0]) / 2;
float in_x[in_len];
float in_y[in_len];
@@ -2114,25 +2452,25 @@ void PerceptualToneCurve::init()
in_y[i] = p[2 * i + 1];
}
- const size_t out_len = sizeof(cf) / sizeof(cf[0]);
+ const size_t out_len = sizeof (cf) / sizeof (cf[0]);
float out_x[out_len];
for (size_t i = 0; i < out_len; i++) {
out_x[i] = in_x[0] + (in_x[in_len - 1] - in_x[0]) * (float)i / (out_len - 1);
}
- cubic_spline(in_x, in_y, in_len, out_x, cf, out_len);
+ cubic_spline (in_x, in_y, in_len, out_x, cf, out_len);
cf_range[0] = in_x[0];
cf_range[1] = in_x[in_len - 1];
}
}
-void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const
+void PerceptualToneCurve::initApplyState (PerceptualToneCurveState & state, Glib::ustring workingSpace) const
{
// Get the curve's contrast value, and convert to a chroma scaling
const float contrast_value = calculateToneCurveContrastValue();
- state.cmul_contrast = get_curve_val(contrast_value, cf_range, cf, sizeof(cf) / sizeof(cf[0]));
+ state.cmul_contrast = get_curve_val (contrast_value, cf_range, cf, sizeof (cf) / sizeof (cf[0]));
//fprintf(stderr, "contrast value: %f => chroma scaling %f\n", contrast_value, state.cmul_contrast);
// Create state for converting to/from prophoto (if necessary)
@@ -2140,8 +2478,8 @@ void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib:
state.isProphoto = true;
} else {
state.isProphoto = false;
- TMatrix Work = iccStore->workingSpaceMatrix(workingSpace);
- memset(state.Working2Prophoto, 0, sizeof(state.Working2Prophoto));
+ TMatrix Work = iccStore->workingSpaceMatrix (workingSpace);
+ memset (state.Working2Prophoto, 0, sizeof (state.Working2Prophoto));
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
@@ -2150,7 +2488,7 @@ void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib:
}
Work = iccStore->workingSpaceInverseMatrix (workingSpace);
- memset(state.Prophoto2Working, 0, sizeof(state.Prophoto2Working));
+ memset (state.Prophoto2Working, 0, sizeof (state.Prophoto2Working));
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
diff --git a/rtengine/curves.h b/rtengine/curves.h
index 348772075..773fecc53 100644
--- a/rtengine/curves.h
+++ b/rtengine/curves.h
@@ -67,13 +67,13 @@ protected:
double k = sqrt ((m1 - 1.0) * (m1 - m2) * 0.5) / (1.0 - m2);
double l = (m1 - m2) / (1.0 - m2) + k;
- double lx = xlog(x);
- return m2 * x + (1.0 - m2) * (2.0 - xexp(k * lx)) * xexp(l * lx);
+ double lx = xlog (x);
+ return m2 * x + (1.0 - m2) * (2.0 - xexp (k * lx)) * xexp (l * lx);
}
// basic concave function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point
static inline double baseu (double x, double m1, double m2)
{
- return 1.0 - basel(1.0 - x, m1, m2);
+ return 1.0 - basel (1.0 - x, m1, m2);
}
// convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery
static inline double cupper (double x, double m, double hr)
@@ -93,12 +93,12 @@ protected:
return x * m;
}
- return 1.0 - hr + hr * baseu((x - x1) / hr, m, 0);
+ return 1.0 - hr + hr * baseu ((x - x1) / hr, m, 0);
}
// concave curve between (0,0) and (1,1) with slope m at (1,1). sr controls the shadow recovery
static inline double clower (double x, double m, double sr)
{
- return 1.0 - cupper(1.0 - x, m, sr);
+ return 1.0 - cupper (1.0 - x, m, sr);
}
// convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery
static inline double cupper2 (double x, double m, double hr)
@@ -114,7 +114,7 @@ protected:
return x * m;
}
- return 1.0 - hr + hr * baseu((x - x1) / hr, m, 0.3 * hr);
+ return 1.0 - hr + hr * baseu ((x - x1) / hr, m, 0.3 * hr);
}
static inline double clower2 (double x, double m, double sr)
{
@@ -125,7 +125,7 @@ protected:
return 1 - (1 - x) * m;
} else {
double y1 = 1 - (1 - x1) * m;
- return y1 + m * (x - x1) - (1 - m) * SQR(SQR(1 - x / x1));
+ return y1 + m * (x - x1) - (1 - m) * SQR (SQR (1 - x / x1));
}
}
// tone curve base. a: slope (from exp.comp.), b: black point normalized by 65535,
@@ -140,7 +140,7 @@ protected:
if (x > m) {
return y + (x - m) * slope; //value on straight line between (m,y) and (1,1)
} else {
- return y * clower2(x / m, slope * m / y, 2.0 - sr);
+ return y * clower2 (x / m, slope * m / y, 2.0 - sr);
}
} else {
double slope = a / (1.0 - b);
@@ -150,7 +150,7 @@ protected:
if (x <= m) {
return b == 0 ? x * slope : clower (x / m, slope * m / y, sr) * y;
} else if (a * D > 1.0) {
- return y + (1.0 - y) * cupper2((x - m) / (D - m), slope * (D - m) / (1.0 - y), hr);
+ return y + (1.0 - y) * cupper2 ((x - m) / (D - m), slope * (D - m) / (1.0 - y), hr);
} else {
return y + (x - m) * slope;
}
@@ -169,7 +169,7 @@ protected:
if (x > m) {
return y + (x - m) * slope; //value on straight line between (m,y) and (1,1)
} else {
- return y * clower2(x / m, slope * m / y, 2.0 - sr);
+ return y * clower2 (x / m, slope * m / y, 2.0 - sr);
}
} else {
double slope = 1.0 / (1.0 - b);
@@ -193,18 +193,18 @@ public:
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// accurately determine value from integer array with float as index
//linearly interpolate from ends of range if arg is out of bounds
- static inline float interp(int *array, float f)
+ static inline float interp (int *array, float f)
{
- int index = CLIPI(floor(f));
- float part = (float)((f) - index) * (float)(array[index + 1] - array[index]);
+ int index = CLIPI (floor (f));
+ float part = (float) ((f) - index) * (float) (array[index + 1] - array[index]);
return (float)array[index] + part;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// accurately determine value from float array with float as index
//linearly interpolate from ends of range if arg is out of bounds
- static inline float flinterp(float *array, float f)
+ static inline float flinterp (float *array, float f)
{
- int index = CLIPI(floor(f));
+ int index = CLIPI (floor (f));
float part = ((f) - (float)index) * (array[index + 1] - array[index]);
return array[index] + part;
}
@@ -215,44 +215,44 @@ public:
// standard srgb gamma and its inverse
static inline double gamma2 (double x)
{
- return x <= 0.00304 ? x * 12.92 : 1.055 * exp(log(x) / sRGBGammaCurve) - 0.055;
+ return x <= 0.00304 ? x * 12.92 : 1.055 * exp (log (x) / sRGBGammaCurve) - 0.055;
}
static inline double igamma2 (double x)
{
- return x <= 0.03928 ? x / 12.92 : exp(log((x + 0.055) / 1.055) * sRGBGammaCurve);
+ return x <= 0.03928 ? x / 12.92 : exp (log ((x + 0.055) / 1.055) * sRGBGammaCurve);
}
static inline float gamma2 (float x)
{
- return x <= 0.00304 ? x * 12.92 : 1.055 * expf(logf(x) / sRGBGammaCurve) - 0.055;
+ return x <= 0.00304 ? x * 12.92 : 1.055 * expf (logf (x) / sRGBGammaCurve) - 0.055;
}
static inline float igamma2 (float x)
{
- return x <= 0.03928 ? x / 12.92 : expf(logf((x + 0.055) / 1.055) * sRGBGammaCurve);
+ return x <= 0.03928 ? x / 12.92 : expf (logf ((x + 0.055) / 1.055) * sRGBGammaCurve);
}
// gamma function with adjustable parameters
static inline double gamma (double x, double gamma, double start, double slope, double mul, double add)
{
- return (x <= start ? x*slope : exp(log(x) / gamma) * mul - add);
+ return (x <= start ? x*slope : exp (log (x) / gamma) * mul - add);
}
static inline double igamma (double x, double gamma, double start, double slope, double mul, double add)
{
- return (x <= start * slope ? x / slope : exp(log((x + add) / mul) * gamma) );
+ return (x <= start * slope ? x / slope : exp (log ((x + add) / mul) * gamma) );
}
static inline float gamma (float x, float gamma, float start, float slope, float mul, float add)
{
- return (x <= start ? x*slope : xexpf(xlogf(x) / gamma) * mul - add);
+ return (x <= start ? x*slope : xexpf (xlogf (x) / gamma) * mul - add);
}
static inline float igamma (float x, float gamma, float start, float slope, float mul, float add)
{
- return (x <= start * slope ? x / slope : xexpf(xlogf((x + add) / mul) * gamma) );
+ return (x <= start * slope ? x / slope : xexpf (xlogf ((x + add) / mul) * gamma) );
}
#ifdef __SSE2__
static inline vfloat igamma (vfloat x, vfloat gamma, vfloat start, vfloat slope, vfloat mul, vfloat add)
{
#if !defined(__clang__)
- return (x <= start * slope ? x / slope : xexpf(xlogf((x + add) / mul) * gamma) );
+ return (x <= start * slope ? x / slope : xexpf (xlogf ((x + add) / mul) * gamma) );
#else
- return vself(vmaskf_le(x, start * slope), x / slope, xexpf(xlogf((x + add) / mul) * gamma));
+ return vself (vmaskf_le (x, start * slope), x / slope, xexpf (xlogf ((x + add) / mul) * gamma));
#endif
}
#endif
@@ -261,19 +261,19 @@ public:
if (comp > 0.0) {
float val = level + (hlrange - 65536.0);
- if(val == 0.0f) { // to avoid division by zero
+ if (val == 0.0f) { // to avoid division by zero
val = 0.000001f;
}
float Y = val * exp_scale / hlrange;
Y *= comp;
- if(Y <= -1.0) { // to avoid log(<=0)
+ if (Y <= -1.0) { // to avoid log(<=0)
Y = -.999999f;
}
float R = hlrange / (val * comp);
- return log(1.0 + Y) * R;
+ return log (1.0 + Y) * R;
} else {
return exp_scale;
}
@@ -296,9 +296,18 @@ public:
static void curveToning ( const std::vector& curvePoints, LUTf & ToningCurve, int skip);
+ static void curveLocal ( bool & locallutili, const std::vector& curvePoints, LUTf & LocalLCurve, int skip);
+
static void complexsgnCurve ( bool & autili, bool & butili, bool & ccutili, bool & clcutili, const std::vector& acurvePoints,
const std::vector& bcurvePoints, const std::vector& cccurvePoints, const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve,
int skip = 1);
+
+ static void localLCurve (double br, double contr,/* const std::vector& curvePoints,*/ LUTu & histogram, LUTf & outCurve, int skip, bool & utili);
+
+ static void updatechroma (
+ const std::vector& cccurvePoints,
+ LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma
+ int skip = 1);
static void complexLCurve (double br, double contr, const std::vector& curvePoints, const LUTu & histogram, LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip, bool & utili);
static void curveLightBrightColor (
@@ -367,7 +376,7 @@ protected:
}
static inline double pfull (double x, double prot, double sh, double hl)
{
- return (1 - sh) * (1 - hl) * p00(x, prot) + sh * hl * p11(x, prot) + (1 - sh) * hl * p01(x, prot) + sh * (1 - hl) * p10(x, prot);
+ return (1 - sh) * (1 - hl) * p00 (x, prot) + sh * hl * p11 (x, prot) + (1 - sh) * hl * p01 (x, prot) + sh * (1 - hl) * p10 (x, prot);
}
void fillHash();
@@ -378,7 +387,7 @@ public:
virtual ~Curve () {};
void AddPolygons ();
int getSize () const; // return the number of control points
- void getControlPoint(int cpNum, double &x, double &y) const;
+ void getControlPoint (int cpNum, double &x, double &y) const;
virtual double getVal (double t) const = 0;
virtual void getVal (const std::vector& t, std::vector& res) const = 0;
@@ -436,16 +445,16 @@ class RetinextransmissionCurve
{
private:
LUTf luttransmission; // 0xffff range
- void Set(const Curve &pCurve);
+ void Set (const Curve &pCurve);
public:
virtual ~RetinextransmissionCurve() {};
RetinextransmissionCurve();
void Reset();
- void Set(const Curve *pCurve);
- void Set(const std::vector &curvePoints);
- float operator[](float index) const
+ void Set (const Curve *pCurve);
+ void Set (const std::vector &curvePoints);
+ float operator[] (float index) const
{
return luttransmission[index];
}
@@ -460,16 +469,16 @@ class RetinexgaintransmissionCurve
{
private:
LUTf lutgaintransmission; // 0xffff range
- void Set(const Curve &pCurve);
+ 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
+ void Set (const Curve *pCurve);
+ void Set (const std::vector &curvePoints);
+ float operator[] (float index) const
{
return lutgaintransmission[index];
}
@@ -490,7 +499,7 @@ public:
virtual ~ToneCurve() {};
void Reset();
- void Set(const Curve &pCurve, float gamma = 0);
+ void Set (const Curve &pCurve, float gamma = 0);
operator bool (void) const
{
return lutToneCurve;
@@ -505,8 +514,8 @@ public:
virtual ~OpacityCurve() {};
void Reset();
- void Set(const Curve *pCurve);
- void Set(const std::vector &curvePoints, bool &opautili);
+ void Set (const Curve *pCurve);
+ void Set (const std::vector &curvePoints, bool &opautili);
// TODO: transfer this method to the Color class...
float blend (float x, float lower, float upper) const
@@ -527,11 +536,97 @@ public:
}
};
+class LocLHCurve
+{
+private:
+ LUTf lutLocLHCurve; // 0xffff range
+ void Set (const Curve &pCurve);
+
+public:
+ float sum;
+
+ virtual ~LocLHCurve() {};
+ LocLHCurve();
+ void Reset();
+ void Set (const std::vector &curvePoints);
+ float getSum() const
+ {
+ return sum;
+ }
+
+ float operator[] (float index) const
+ {
+ return lutLocLHCurve[index];
+ }
+ operator bool (void) const
+ {
+ return lutLocLHCurve;
+ }
+};
+
+
+class LocretigainCurve
+{
+private:
+ LUTf lutLocretigainCurve; // 0xffff range
+ void Set (const Curve &pCurve);
+
+public:
+ float sum;
+
+ virtual ~LocretigainCurve() {};
+ LocretigainCurve();
+ void Reset();
+ void Set (const std::vector &curvePoints);
+ float getSum() const
+ {
+ return sum;
+ }
+
+ float operator[] (float index) const
+ {
+ return lutLocretigainCurve[index];
+ }
+ operator bool (void) const
+ {
+ return lutLocretigainCurve;
+ }
+};
+
+class LocretigainCurverab
+{
+private:
+ LUTf lutLocretigainCurverab; // 0xffff range
+ void Set (const Curve &pCurve);
+
+public:
+ float sum;
+
+ virtual ~LocretigainCurverab() {};
+ LocretigainCurverab();
+ void Reset();
+ void Set (const std::vector &curvePoints);
+ float getSum() const
+ {
+ return sum;
+ }
+
+ float operator[] (float index) const
+ {
+ return lutLocretigainCurverab[index];
+ }
+ operator bool (void) const
+ {
+ return lutLocretigainCurverab;
+ }
+};
+
+
class WavCurve
{
private:
LUTf lutWavCurve; // 0xffff range
- void Set(const Curve &pCurve);
+ void Set (const Curve &pCurve);
public:
float sum;
@@ -539,13 +634,13 @@ public:
virtual ~WavCurve() {};
WavCurve();
void Reset();
- void Set(const std::vector &curvePoints);
+ void Set (const std::vector &curvePoints);
float getSum() const
{
return sum;
}
- float operator[](float index) const
+ float operator[] (float index) const
{
return lutWavCurve[index];
}
@@ -559,15 +654,15 @@ class WavOpacityCurveRG
{
private:
LUTf lutOpacityCurveRG; // 0xffff range
- void Set(const Curve &pCurve);
+ void Set (const Curve &pCurve);
public:
virtual ~WavOpacityCurveRG() {};
WavOpacityCurveRG();
void Reset();
// void Set(const std::vector &curvePoints, bool &opautili);
- void Set(const std::vector &curvePoints);
- float operator[](float index) const
+ void Set (const std::vector &curvePoints);
+ float operator[] (float index) const
{
return lutOpacityCurveRG[index];
}
@@ -581,16 +676,16 @@ class WavOpacityCurveBY
{
private:
LUTf lutOpacityCurveBY; // 0xffff range
- void Set(const Curve &pCurve);
+ void Set (const Curve &pCurve);
public:
virtual ~WavOpacityCurveBY() {};
WavOpacityCurveBY();
void Reset();
- void Set(const Curve *pCurve);
- void Set(const std::vector &curvePoints);
- float operator[](float index) const
+ void Set (const Curve *pCurve);
+ void Set (const std::vector &curvePoints);
+ float operator[] (float index) const
{
return lutOpacityCurveBY[index];
}
@@ -604,16 +699,16 @@ class WavOpacityCurveW
{
private:
LUTf lutOpacityCurveW; // 0xffff range
- void Set(const Curve &pCurve);
+ void Set (const Curve &pCurve);
public:
virtual ~WavOpacityCurveW() {};
WavOpacityCurveW();
void Reset();
- void Set(const Curve *pCurve);
- void Set(const std::vector &curvePoints);
- float operator[](float index) const
+ void Set (const Curve *pCurve);
+ void Set (const std::vector &curvePoints);
+ float operator[] (float index) const
{
return lutOpacityCurveW[index];
}
@@ -628,16 +723,16 @@ class WavOpacityCurveWL
{
private:
LUTf lutOpacityCurveWL; // 0xffff range
- void Set(const Curve &pCurve);
+ void Set (const Curve &pCurve);
public:
virtual ~WavOpacityCurveWL() {};
WavOpacityCurveWL();
void Reset();
- void Set(const Curve *pCurve);
- void Set(const std::vector &curvePoints);
- float operator[](float index) const
+ void Set (const Curve *pCurve);
+ void Set (const std::vector &curvePoints);
+ float operator[] (float index) const
{
return lutOpacityCurveWL[index];
}
@@ -653,19 +748,19 @@ class NoiseCurve
private:
LUTf lutNoiseCurve; // 0xffff range
float sum;
- void Set(const Curve &pCurve);
+ void Set (const Curve &pCurve);
public:
virtual ~NoiseCurve() {};
NoiseCurve();
void Reset();
- void Set(const std::vector &curvePoints);
+ void Set (const std::vector &curvePoints);
float getSum() const
{
return sum;
}
- float operator[](float index) const
+ float operator[] (float index) const
{
return lutNoiseCurve[index];
}
@@ -687,10 +782,10 @@ public:
virtual ~ColorGradientCurve() {};
void Reset();
- void SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin);
- void SetXYZ(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin);
- void SetRGB(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3]);
- void SetRGB(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3]);
+ void SetXYZ (const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin);
+ void SetXYZ (const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin);
+ void SetRGB (const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3]);
+ void SetRGB (const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3]);
/**
* @brief Get the value of Red, Green and Blue corresponding to the requested index
@@ -699,7 +794,7 @@ public:
* @param g corresponding green value [0 ; 65535] (return value)
* @param b corresponding blue value [0 ; 65535] (return value)
*/
- void getVal(float index, float &r, float &g, float &b) const;
+ void getVal (float index, float &r, float &g, float &b) const;
operator bool (void) const
{
return lut1 && lut2 && lut3;
@@ -714,7 +809,7 @@ public:
virtual ~ColorAppearance() {};
void Reset();
- void Set(const Curve &pCurve);
+ void Set (const Curve &pCurve);
operator bool (void) const
{
return lutColCurve;
@@ -724,7 +819,7 @@ public:
class Lightcurve : public ColorAppearance
{
public:
- void Apply(float& Li) const;
+ void Apply (float& Li) const;
};
//lightness curve
@@ -739,7 +834,7 @@ inline void Lightcurve::Apply (float& Li) const
class Brightcurve : public ColorAppearance
{
public:
- void Apply(float& Br) const;
+ void Apply (float& Br) const;
};
//brightness curve
@@ -754,7 +849,7 @@ inline void Brightcurve::Apply (float& Br) const
class Chromacurve : public ColorAppearance
{
public:
- void Apply(float& Cr) const;
+ void Apply (float& Cr) const;
};
//Chroma curve
@@ -768,7 +863,7 @@ inline void Chromacurve::Apply (float& Cr) const
class Saturcurve : public ColorAppearance
{
public:
- void Apply(float& Sa) const;
+ void Apply (float& Sa) const;
};
//Saturation curve
@@ -783,7 +878,7 @@ inline void Saturcurve::Apply (float& Sa) const
class Colorfcurve : public ColorAppearance
{
public:
- void Apply(float& Cf) const;
+ void Apply (float& Cf) const;
};
//Colorfullness curve
@@ -799,56 +894,56 @@ inline void Colorfcurve::Apply (float& Cf) const
class StandardToneCurve : public ToneCurve
{
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
class StandardToneCurvebw : public ToneCurve
{
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
class AdobeToneCurve : public ToneCurve
{
private:
- void RGBTone(float& r, float& g, float& b) const; // helper for tone curve
+ void RGBTone (float& r, float& g, float& b) const; // helper for tone curve
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
class AdobeToneCurvebw : public ToneCurve
{
private:
- void RGBTone(float& r, float& g, float& b) const; // helper for tone curve
+ void RGBTone (float& r, float& g, float& b) const; // helper for tone curve
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
class SatAndValueBlendingToneCurve : public ToneCurve
{
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
class SatAndValueBlendingToneCurvebw : public ToneCurve
{
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
class WeightedStdToneCurve : public ToneCurve
{
private:
- float Triangle(float refX, float refY, float X2) const;
+ float Triangle (float refX, float refY, float X2) const;
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
class LuminanceToneCurve : public ToneCurve
{
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
class PerceptualToneCurveState
@@ -873,23 +968,23 @@ private:
static float f, c, nc, yb, la, xw, yw, zw, gamut;
static float n, d, nbb, ncb, cz, aw, wh, pfl, fl, pow1;
- static void cubic_spline(const float x[], const float y[], const int len, const float out_x[], float out_y[], const int out_len);
- static float find_minimum_interval_halving(float (*func)(float x, void *arg), void *arg, float a, float b, float tol, int nmax);
- static float find_tc_slope_fun(float k, void *arg);
- static float get_curve_val(float x, float range[2], float lut[], size_t lut_size);
+ static void cubic_spline (const float x[], const float y[], const int len, const float out_x[], float out_y[], const int out_len);
+ static float find_minimum_interval_halving (float (*func) (float x, void *arg), void *arg, float a, float b, float tol, int nmax);
+ static float find_tc_slope_fun (float k, void *arg);
+ static float get_curve_val (float x, float range[2], float lut[], size_t lut_size);
float calculateToneCurveContrastValue() const;
public:
static void init();
- void initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const;
- void Apply(float& r, float& g, float& b, PerceptualToneCurveState & state) const;
+ void initApplyState (PerceptualToneCurveState & state, Glib::ustring workingSpace) const;
+ void Apply (float& r, float& g, float& b, PerceptualToneCurveState & state) const;
};
class WeightedStdToneCurvebw : public ToneCurve
{
private:
- float Triangle(float refX, float refY, float X2) const;
+ float Triangle (float refX, float refY, float X2) const;
public:
- void Apply(float& r, float& g, float& b) const;
+ void Apply (float& r, float& g, float& b) const;
};
// Standard tone curve
@@ -989,19 +1084,19 @@ inline void AdobeToneCurvebw::RGBTone (float& r, float& g, float& b) const
}
// Modifying the Luminance channel only
-inline void LuminanceToneCurve::Apply(float &r, float &g, float &b) const
+inline void LuminanceToneCurve::Apply (float &r, float &g, float &b) const
{
assert (lutToneCurve);
float currLuminance = r * 0.2126729f + g * 0.7151521f + b * 0.0721750f;
float newLuminance = lutToneCurve[currLuminance];
float coef = newLuminance / currLuminance;
- r = LIM(r * coef, 0.f, 65535.f);
- g = LIM(g * coef, 0.f, 65535.f);
- b = LIM(b * coef, 0.f, 65535.f);
+ r = LIM (r * coef, 0.f, 65535.f);
+ g = LIM (g * coef, 0.f, 65535.f);
+ b = LIM (b * coef, 0.f, 65535.f);
}
-inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const
+inline float WeightedStdToneCurve::Triangle (float a, float a1, float b) const
{
if (a != b) {
float b1;
@@ -1018,7 +1113,7 @@ inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const
return a1;
}
-inline float WeightedStdToneCurvebw::Triangle(float a, float a1, float b) const
+inline float WeightedStdToneCurvebw::Triangle (float a, float a1, float b) const
{
if (a != b) {
float b1;
@@ -1044,20 +1139,20 @@ inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const
assert (lutToneCurve);
float r1 = lutToneCurve[r];
- float g1 = Triangle(r, r1, g);
- float b1 = Triangle(r, r1, b);
+ float g1 = Triangle (r, r1, g);
+ float b1 = Triangle (r, r1, b);
float g2 = lutToneCurve[g];
- float r2 = Triangle(g, g2, r);
- float b2 = Triangle(g, g2, b);
+ float r2 = Triangle (g, g2, r);
+ float b2 = Triangle (g, g2, b);
float b3 = lutToneCurve[b];
- float r3 = Triangle(b, b3, r);
- float g3 = Triangle(b, b3, g);
+ float r3 = Triangle (b, b3, r);
+ float g3 = Triangle (b, b3, g);
- r = CLIP( r1 * 0.50f + r2 * 0.25f + r3 * 0.25f);
- g = CLIP(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f);
- b = CLIP(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f);
+ r = CLIP ( r1 * 0.50f + r2 * 0.25f + r3 * 0.25f);
+ g = CLIP (g1 * 0.25f + g2 * 0.50f + g3 * 0.25f);
+ b = CLIP (b1 * 0.25f + b2 * 0.25f + b3 * 0.50f);
}
inline void WeightedStdToneCurvebw::Apply (float& r, float& g, float& b) const
@@ -1066,20 +1161,20 @@ inline void WeightedStdToneCurvebw::Apply (float& r, float& g, float& b) const
assert (lutToneCurve);
float r1 = lutToneCurve[r];
- float g1 = Triangle(r, r1, g);
- float b1 = Triangle(r, r1, b);
+ float g1 = Triangle (r, r1, g);
+ float b1 = Triangle (r, r1, b);
float g2 = lutToneCurve[g];
- float r2 = Triangle(g, g2, r);
- float b2 = Triangle(g, g2, b);
+ float r2 = Triangle (g, g2, r);
+ float b2 = Triangle (g, g2, b);
float b3 = lutToneCurve[b];
- float r3 = Triangle(b, b3, r);
- float g3 = Triangle(b, b3, g);
+ float r3 = Triangle (b, b3, r);
+ float g3 = Triangle (b, b3, g);
- r = CLIP( r1 * 0.50f + r2 * 0.25f + r3 * 0.25f);
- g = CLIP(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f);
- b = CLIP(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f);
+ r = CLIP ( r1 * 0.50f + r2 * 0.25f + r3 * 0.25f);
+ g = CLIP (g1 * 0.25f + g2 * 0.50f + g3 * 0.25f);
+ b = CLIP (b1 * 0.25f + b2 * 0.25f + b3 * 0.50f);
}
// Tone curve modifying the value channel only, preserving hue and saturation
@@ -1100,19 +1195,19 @@ inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) c
bool increase = newLum > lum;
- Color::rgb2hsv(r, g, b, h, s, v);
+ Color::rgb2hsv (r, g, b, h, s, v);
if (increase) {
// Linearly targeting Value = 1 and Saturation = 0
float coef = (newLum - lum) / (65535.f - lum);
float dV = (1.f - v) * coef;
s *= 1.f - coef;
- Color::hsv2rgb(h, s, v + dV, r, g, b);
+ Color::hsv2rgb (h, s, v + dV, r, g, b);
} else {
// Linearly targeting Value = 0
float coef = (lum - newLum) / lum ;
float dV = v * coef;
- Color::hsv2rgb(h, s, v - dV, r, g, b);
+ Color::hsv2rgb (h, s, v - dV, r, g, b);
}
}
@@ -1132,19 +1227,19 @@ inline void SatAndValueBlendingToneCurvebw::Apply (float& r, float& g, float& b)
bool increase = newLum > lum;
- Color::rgb2hsv(r, g, b, h, s, v);
+ Color::rgb2hsv (r, g, b, h, s, v);
if (increase) {
// Linearly targeting Value = 1 and Saturation = 0
float coef = (newLum - lum) / (65535.f - lum);
float dV = (1.f - v) * coef;
s *= 1.f - coef;
- Color::hsv2rgb(h, s, v + dV, r, g, b);
+ Color::hsv2rgb (h, s, v + dV, r, g, b);
} else {
// Linearly targeting Value = 0
float coef = (lum - newLum) / lum ;
float dV = v * coef;
- Color::hsv2rgb(h, s, v - dV, r, g, b);
+ Color::hsv2rgb (h, s, v - dV, r, g, b);
}
}
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index a90c78069..6a07d23cd 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -22,6 +22,11 @@
#include "mytime.h"
#include "refreshmap.h"
#include "rt_math.h"
+#include
+#include
+#include
+#include
+//#include
// "ceil" rounding
#define SKIPS(a,b) ((a) / (b) + ((a) % (b) > 0))
@@ -31,15 +36,15 @@ namespace rtengine
extern const Settings* settings;
Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow)
- : PipetteBuffer(editDataProvider), origCrop(nullptr), laboCrop(nullptr), labnCrop(nullptr),
- cropImg(nullptr), cbuf_real(nullptr), cshmap(nullptr), transCrop(nullptr), cieCrop(nullptr), cbuffer(nullptr),
- updating(false), newUpdatePending(false), skip(10), padding(0),
- cropx(0), cropy(0), cropw(-1), croph(-1),
- trafx(0), trafy(0), trafw(-1), trafh(-1),
- rqcropx(0), rqcropy(0), rqcropw(-1), rqcroph(-1),
- borderRequested(32), upperBorder(0), leftBorder(0),
- cropAllocated(false),
- cropImageListener(nullptr), parent(parent), isDetailWindow(isDetailWindow)
+ : PipetteBuffer (editDataProvider), origCrop (nullptr), laboCrop (nullptr), labnCrop (nullptr),
+ cropImg (nullptr), cbuf_real (nullptr), shbuf_real (nullptr), cshmap (nullptr), transCrop (nullptr), cieCrop (nullptr), cbuffer (nullptr), shbuffer (nullptr),
+ updating (false), newUpdatePending (false), skip (10), padding (0),
+ cropx (0), cropy (0), cropw (-1), croph (-1),
+ trafx (0), trafy (0), trafw (-1), trafh (-1),
+ rqcropx (0), rqcropy (0), rqcropw (-1), rqcroph (-1),
+ borderRequested (32), upperBorder (0), leftBorder (0),
+ cropAllocated (false),
+ cropImageListener (nullptr), parent (parent), isDetailWindow (isDetailWindow)
{
parent->crops.push_back (this);
}
@@ -47,7 +52,7 @@ Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool
Crop::~Crop ()
{
- MyMutex::MyLock cropLock(cropMutex);
+ MyMutex::MyLock cropLock (cropMutex);
std::vector::iterator i = std::find (parent->crops.begin(), parent->crops.end(), this);
@@ -55,14 +60,14 @@ Crop::~Crop ()
parent->crops.erase (i);
}
- MyMutex::MyLock processingLock(parent->mProcessing);
+ MyMutex::MyLock processingLock (parent->mProcessing);
freeAll ();
}
void Crop::destroy ()
{
- MyMutex::MyLock lock(cropMutex);
- MyMutex::MyLock processingLock(parent->mProcessing);
+ MyMutex::MyLock lock (cropMutex);
+ MyMutex::MyLock processingLock (parent->mProcessing);
freeAll();
}
@@ -70,7 +75,7 @@ void Crop::setListener (DetailedCropListener* il)
{
// We can make reads in the IF, because the mProcessing lock is only needed for change
if (cropImageListener != il) {
- MyMutex::MyLock lock(cropMutex);
+ MyMutex::MyLock lock (cropMutex);
cropImageListener = il;
}
}
@@ -85,9 +90,9 @@ EditUniqueID Crop::getCurrEditID()
* Delete the edit image buffer if there's no subscriber anymore.
* If allocation has to be done, it is deferred to Crop::update
*/
-void Crop::setEditSubscriber(EditSubscriber* newSubscriber)
+void Crop::setEditSubscriber (EditSubscriber* newSubscriber)
{
- MyMutex::MyLock lock(cropMutex);
+ MyMutex::MyLock lock (cropMutex);
// At this point, editCrop.dataProvider->currSubscriber is the old subscriber
EditSubscriber *oldSubscriber = PipetteBuffer::dataProvider ? PipetteBuffer::dataProvider->getCurrSubscriber() : nullptr;
@@ -113,7 +118,7 @@ void Crop::setEditSubscriber(EditSubscriber* newSubscriber)
void Crop::update (int todo)
{
- MyMutex::MyLock cropLock(cropMutex);
+ MyMutex::MyLock cropLock (cropMutex);
ProcParams& params = parent->params;
// CropGUIListener* cropgl;
@@ -153,16 +158,16 @@ void Crop::update (int todo)
bool needstransform = parent->ipf.needsTransform();
if (todo & (M_INIT | M_LINDENOISE)) {
- MyMutex::MyLock lock(parent->minit); // Also used in improccoord
+ MyMutex::MyLock lock (parent->minit); // Also used in improccoord
- int tr = getCoarseBitMask(params.coarse);
+ int tr = getCoarseBitMask (params.coarse);
if (!needsinitupdate) {
setCropSizes (rqcropx, rqcropy, rqcropw, rqcroph, skip, true);
}
- // printf("x=%d y=%d crow=%d croh=%d skip=%d\n",rqcropx, rqcropy, rqcropw, rqcroph, skip);
- // printf("trafx=%d trafyy=%d trafwsk=%d trafHs=%d \n",trafx, trafy, trafw*skip, trafh*skip);
+ // printf("x=%d y=%d crow=%d croh=%d skip=%d\n",rqcropx, rqcropy, rqcropw, rqcroph, skip);
+ // printf("trafx=%d trafyy=%d trafwsk=%d trafHs=%d \n",trafx, trafy, trafw*skip, trafh*skip);
Imagefloat *calclum = nullptr;//for Luminance denoise curve
NoiseCurve noiseLCurve;
@@ -170,17 +175,17 @@ void Crop::update (int todo)
float autoNR = (float) settings->nrauto;//
float autoNRmax = (float) settings->nrautomax;//
- params.dirpyrDenoise.getCurves(noiseLCurve, noiseCCurve);
+ params.dirpyrDenoise.getCurves (noiseLCurve, noiseCCurve);
int tilesize;
int overlap;
- if(settings->leveldnti == 0) {
+ if (settings->leveldnti == 0) {
tilesize = 1024;
overlap = 128;
}
- if(settings->leveldnti == 1) {
+ if (settings->leveldnti == 1) {
tilesize = 768;
overlap = 96;
}
@@ -201,35 +206,35 @@ void Crop::update (int todo)
int *centerTile_X = new int [numtiles_W];
int *centerTile_Y = new int [numtiles_H];
- for(int cX = 0; cX < numtiles_W; cX++) {
+ for (int cX = 0; cX < numtiles_W; cX++) {
centerTile_X[cX] = tileWskip / 2 + tileWskip * cX;
}
- for(int cY = 0; cY < numtiles_H; cY++) {
+ for (int cY = 0; cY < numtiles_H; cY++) {
centerTile_Y[cY] = tileHskip / 2 + tileHskip * cY;
}
- if(settings->leveldnautsimpl == 1) {
- if(params.dirpyrDenoise.Cmethod == "MAN" || params.dirpyrDenoise.Cmethod == "PON" ) {
+ if (settings->leveldnautsimpl == 1) {
+ if (params.dirpyrDenoise.Cmethod == "MAN" || params.dirpyrDenoise.Cmethod == "PON" ) {
PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip);
parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw );
}
} else {
- if(params.dirpyrDenoise.C2method == "MANU") {
+ if (params.dirpyrDenoise.C2method == "MANU") {
PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip);
parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw );
}
}
- if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PRE") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "PREV")) {
+ if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PRE") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "PREV")) {
PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip);
parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw );
- if((!isDetailWindow) && parent->adnListener && skip == 1 && params.dirpyrDenoise.enabled) {
+ if ((!isDetailWindow) && parent->adnListener && skip == 1 && params.dirpyrDenoise.enabled) {
float lowdenoise = 1.f;
int levaut = settings->leveldnaut;
- if(levaut == 1) { //Standard
+ if (levaut == 1) { //Standard
lowdenoise = 0.7f;
}
@@ -240,16 +245,16 @@ void Crop::update (int todo)
int poscenterX = 0;
int poscenterY = 0;
- for(int cc = 0; cc < numtiles_W; cc++) {
- if(abs(centerTile_X[cc] - CenterPreview_X) < minimuX) {
- minimuX = abs(centerTile_X[cc] - CenterPreview_X);
+ for (int cc = 0; cc < numtiles_W; cc++) {
+ if (abs (centerTile_X[cc] - CenterPreview_X) < minimuX) {
+ minimuX = abs (centerTile_X[cc] - CenterPreview_X);
poscenterX = cc;
}
}
- for(int cc = 0; cc < numtiles_H; cc++) {
- if(abs(centerTile_Y[cc] - CenterPreview_Y) < minimuY) {
- minimuY = abs(centerTile_Y[cc] - CenterPreview_Y);
+ for (int cc = 0; cc < numtiles_H; cc++) {
+ if (abs (centerTile_Y[cc] - CenterPreview_Y) < minimuY) {
+ minimuY = abs (centerTile_Y[cc] - CenterPreview_Y);
poscenterY = cc;
}
}
@@ -257,20 +262,20 @@ void Crop::update (int todo)
// printf("TileCX=%d TileCY=%d prevX=%d prevY=%d \n",centerTile_X[poscenterX],centerTile_Y[poscenterY],CenterPreview_X,CenterPreview_Y);
int crW;
- if(settings->leveldnv == 0) {
+ if (settings->leveldnv == 0) {
crW = 100;
}
- if(settings->leveldnv == 1) {
+ if (settings->leveldnv == 1) {
crW = 250;
}
// if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
- if(settings->leveldnv == 2) {
- crW = int(tileWskip / 2);
+ if (settings->leveldnv == 2) {
+ crW = int (tileWskip / 2);
}
- if(settings->leveldnv == 3) {
+ if (settings->leveldnv == 3) {
crW = tileWskip - 10;
}
@@ -292,7 +297,7 @@ void Crop::update (int todo)
adjustr = 1.f / 1.2f;
}
- if(parent->adnListener) {
+ if (parent->adnListener) {
parent->adnListener->noiseTilePrev (centerTile_X[poscenterX], centerTile_Y[poscenterY], CenterPreview_X, CenterPreview_Y, crW, trafw * skip);
}
@@ -309,15 +314,15 @@ void Crop::update (int todo)
int H = origCrop->getHeight();
Imagefloat *provicalc = new Imagefloat ((W + 1) / 2, (H + 1) / 2); //for denoise curves
- for(int ii = 0; ii < H; ii += 2) {
- for(int jj = 0; jj < W; jj += 2) {
- provicalc->r(ii >> 1, jj >> 1) = origCrop->r(ii, jj);
- provicalc->g(ii >> 1, jj >> 1) = origCrop->g(ii, jj);
- provicalc->b(ii >> 1, jj >> 1) = origCrop->b(ii, jj);
+ for (int ii = 0; ii < H; ii += 2) {
+ for (int jj = 0; jj < W; jj += 2) {
+ provicalc->r (ii >> 1, jj >> 1) = origCrop->r (ii, jj);
+ provicalc->g (ii >> 1, jj >> 1) = origCrop->g (ii, jj);
+ provicalc->b (ii >> 1, jj >> 1) = origCrop->b (ii, jj);
}
}
- parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB);//for denoise luminance curve
+ parent->imgsrc->convertColorSpace (provicalc, params.icm, parent->currWB); //for denoise luminance curve
float maxr = 0.f;
float maxb = 0.f;
@@ -331,19 +336,19 @@ void Crop::update (int todo)
maxblueaut = 0.f;
minredaut = 0.f;
minblueaut = 0.f;
- LUTf gamcurve(65536, 0);
+ LUTf gamcurve (65536, 0);
float gam, gamthresh, gamslope;
- parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope);
- parent->ipf.RGB_denoise_info(origCrop, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc, true);
+ parent->ipf.RGB_denoise_infoGamCurve (params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope);
+ parent->ipf.RGB_denoise_info (origCrop, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc, true);
// printf("redy=%f skin=%f pcskin=%f\n",redyel, skinc,nsknc);
// printf("DCROP skip=%d cha=%4.0f Nb=%d red=%4.0f bl=%4.0f redM=%4.0f bluM=%4.0f L=%4.0f sigL=%4.0f Ch=%4.0f Si=%4.0f\n",skip, chaut,Nb, redaut,blueaut, maxredaut, maxblueaut, lumema, sigma_L, chromina, sigma);
float multip = 1.f;
- if(!parent->imgsrc->isRAW()) {
+ if (!parent->imgsrc->isRAW()) {
multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good for gamma=1
}
- float maxmax = max(maxredaut, maxblueaut);
+ float maxmax = max (maxredaut, maxblueaut);
float delta;
int mode = 0;
// float redyel, skinc, nsknc;
@@ -351,18 +356,18 @@ void Crop::update (int todo)
parent->ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc);
- if(maxredaut > maxblueaut) {
+ if (maxredaut > maxblueaut) {
// maxr=(maxredaut-chaut)/((autoNRmax*multip*adjustr)/2.f);
maxr = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
- if(minblueaut <= minredaut && minblueaut < chaut) {
+ if (minblueaut <= minredaut && minblueaut < chaut) {
maxb = (-chaut + minblueaut) / (autoNRmax * multip * adjustr * lowdenoise);
}
} else {
// maxb=(maxblueaut-chaut)/((autoNRmax*multip*adjustr)/2.f);
maxb = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
- if(minredaut <= minblueaut && minredaut < chaut) {
+ if (minredaut <= minblueaut && minredaut < chaut) {
maxr = (-chaut + minredaut) / (autoNRmax * multip * adjustr * lowdenoise);
}
}//maxb mxr - empirical evaluation red / blue
@@ -371,35 +376,35 @@ void Crop::update (int todo)
params.dirpyrDenoise.chroma = chaut / (autoNR * multip * adjustr * lowdenoise);
params.dirpyrDenoise.redchro = maxr;
params.dirpyrDenoise.bluechro = maxb;
- parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro);
+ parent->adnListener->chromaChanged (params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro);
delete provicalc;
}
}
- if(skip == 1 && params.dirpyrDenoise.enabled && !parent->denoiseInfoStore.valid && ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO"))) {
+ if (skip == 1 && params.dirpyrDenoise.enabled && !parent->denoiseInfoStore.valid && ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO"))) {
MyTime t1aue, t2aue;
t1aue.set();
int crW, crH;
- if(settings->leveldnv == 0) {
+ if (settings->leveldnv == 0) {
crW = 100;
crH = 100;
}
- if(settings->leveldnv == 1) {
+ if (settings->leveldnv == 1) {
crW = 250;
crH = 250;
}
// if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
- if(settings->leveldnv == 2) {
- crW = int(tileWskip / 2);
- crH = int(tileHskip / 2);
+ if (settings->leveldnv == 2) {
+ crW = int (tileWskip / 2);
+ crH = int (tileHskip / 2);
}
- if(settings->leveldnv == 3) {
+ if (settings->leveldnv == 3) {
crW = tileWskip - 10;
crH = tileHskip - 10;
}
@@ -407,13 +412,13 @@ void Crop::update (int todo)
float lowdenoise = 1.f;
int levaut = settings->leveldnaut;
- if(levaut == 1) { //Standard
+ if (levaut == 1) { //Standard
lowdenoise = 0.7f;
}
- LUTf gamcurve(65536, 0);
+ LUTf gamcurve (65536, 0);
float gam, gamthresh, gamslope;
- parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope);
+ parent->ipf.RGB_denoise_infoGamCurve (params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope);
int Nb[9];
#ifdef _OPENMP
#pragma omp parallel
@@ -436,26 +441,26 @@ void Crop::update (int todo)
#pragma omp for schedule(dynamic) collapse(2) nowait
#endif
- for(int wcr = 0; wcr <= 2; wcr++) {
- for(int hcr = 0; hcr <= 2; hcr++) {
+ for (int wcr = 0; wcr <= 2; wcr++) {
+ for (int hcr = 0; hcr <= 2; hcr++) {
PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, 1);
parent->imgsrc->getImage (parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw );
// we only need image reduced to 1/4 here
- for(int ii = 0; ii < crH; ii += 2) {
- for(int jj = 0; jj < crW; jj += 2) {
- provicalc->r(ii >> 1, jj >> 1) = origCropPart->r(ii, jj);
- provicalc->g(ii >> 1, jj >> 1) = origCropPart->g(ii, jj);
- provicalc->b(ii >> 1, jj >> 1) = origCropPart->b(ii, jj);
+ for (int ii = 0; ii < crH; ii += 2) {
+ for (int jj = 0; jj < crW; jj += 2) {
+ provicalc->r (ii >> 1, jj >> 1) = origCropPart->r (ii, jj);
+ provicalc->g (ii >> 1, jj >> 1) = origCropPart->g (ii, jj);
+ provicalc->b (ii >> 1, jj >> 1) = origCropPart->b (ii, jj);
}
}
- parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB);//for denoise luminance curve
+ parent->imgsrc->convertColorSpace (provicalc, params.icm, parent->currWB); //for denoise luminance curve
float pondcorrec = 1.0f;
float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f;
int nb = 0;
- parent->ipf.RGB_denoise_info(origCropPart, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc);
+ parent->ipf.RGB_denoise_info (origCropPart, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc);
//printf("DCROP skip=%d cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f\n",skip, chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema);
Nb[hcr * 3 + wcr] = nb;
@@ -494,7 +499,7 @@ void Crop::update (int todo)
float multip = 1.f;
- if(!parent->imgsrc->isRAW()) {
+ if (!parent->imgsrc->isRAW()) {
multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1
}
@@ -521,15 +526,15 @@ void Crop::update (int todo)
int lissage = settings->leveldnliss;
for (int k = 0; k < 9; k++) {
- float maxmax = max(parent->denoiseInfoStore.max_r[k], parent->denoiseInfoStore.max_b[k]);
+ float maxmax = max (parent->denoiseInfoStore.max_r[k], parent->denoiseInfoStore.max_b[k]);
parent->ipf.calcautodn_info (parent->denoiseInfoStore.ch_M[k], delta[k], Nb[k], levaut, maxmax, lumL[k], chromC[k], mode, lissage, ry[k], sk[k], pcsk[k]);
// printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]);
}
for (int k = 0; k < 9; k++) {
- if(parent->denoiseInfoStore.max_r[k] > parent->denoiseInfoStore.max_b[k]) {
+ if (parent->denoiseInfoStore.max_r[k] > parent->denoiseInfoStore.max_b[k]) {
Max_R[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
- Min_B[k] = -(parent->denoiseInfoStore.ch_M[k] - min_b[k]) / (autoNRmax * multip * adjustr * lowdenoise);
+ Min_B[k] = - (parent->denoiseInfoStore.ch_M[k] - min_b[k]) / (autoNRmax * multip * adjustr * lowdenoise);
Max_B[k] = 0.f;
Min_R[k] = 0.f;
} else {
@@ -548,19 +553,19 @@ void Crop::update (int todo)
MinRMoy += Min_R[k];
MinBMoy += Min_B[k];
- if(Max_R[k] > MaxR) {
+ if (Max_R[k] > MaxR) {
MaxR = Max_R[k];
}
- if(Max_B[k] > MaxB) {
+ if (Max_B[k] > MaxB) {
MaxB = Max_B[k];
}
- if(Min_R[k] < MinR) {
+ if (Min_R[k] < MinR) {
MinR = Min_R[k];
}
- if(Min_B[k] < MinB) {
+ if (Min_B[k] < MinB) {
MinB = Min_B[k];
}
}
@@ -571,7 +576,7 @@ void Crop::update (int todo)
MinBMoy /= 9;
MinRMoy /= 9;
- if(MaxR > MaxB) {
+ if (MaxR > MaxB) {
maxr = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; //#std Dev
//maxb=MinB;
maxb = MinBMoy + (MinB - MinBMoy) * 0.66f;
@@ -585,55 +590,56 @@ void Crop::update (int todo)
params.dirpyrDenoise.redchro = maxr;
params.dirpyrDenoise.bluechro = maxb;
parent->denoiseInfoStore.valid = true;
- if(parent->adnListener) {
- parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro);
+
+ if (parent->adnListener) {
+ parent->adnListener->chromaChanged (params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro);
}
if (settings->verbose) {
t2aue.set();
- printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue));
+ printf ("Info denoise auto performed in %d usec:\n", t2aue.etime (t1aue));
}
//end evaluate noise
}
// if(params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto
- if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto
+ if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto
PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip);
parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw );
}
DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise;
- if(params.dirpyrDenoise.Lmethod == "CUR") {
- if(noiseLCurve) {
+ if (params.dirpyrDenoise.Lmethod == "CUR") {
+ if (noiseLCurve) {
denoiseParams.luma = 0.5f; //very small value to init process - select curve or slider
} else {
denoiseParams.luma = 0.0f;
}
- } else if(denoiseParams.Lmethod == "SLI") {
+ } else if (denoiseParams.Lmethod == "SLI") {
noiseLCurve.Reset();
}
- if((noiseLCurve || noiseCCurve ) && skip == 1 && denoiseParams.enabled) { //only allocate memory if enabled and skip
+ if ((noiseLCurve || noiseCCurve ) && skip == 1 && denoiseParams.enabled) { //only allocate memory if enabled and skip
// we only need image reduced to 1/4 here
int W = origCrop->getWidth();
int H = origCrop->getHeight();
calclum = new Imagefloat ((W + 1) / 2, (H + 1) / 2); //for denoise curves
- for(int ii = 0; ii < H; ii += 2) {
- for(int jj = 0; jj < W; jj += 2) {
- calclum->r(ii >> 1, jj >> 1) = origCrop->r(ii, jj);
- calclum->g(ii >> 1, jj >> 1) = origCrop->g(ii, jj);
- calclum->b(ii >> 1, jj >> 1) = origCrop->b(ii, jj);
+ for (int ii = 0; ii < H; ii += 2) {
+ for (int jj = 0; jj < W; jj += 2) {
+ calclum->r (ii >> 1, jj >> 1) = origCrop->r (ii, jj);
+ calclum->g (ii >> 1, jj >> 1) = origCrop->g (ii, jj);
+ calclum->b (ii >> 1, jj >> 1) = origCrop->b (ii, jj);
}
}
- parent->imgsrc->convertColorSpace(calclum, params.icm, parent->currWB);//for denoise luminance curve
+ parent->imgsrc->convertColorSpace (calclum, params.icm, parent->currWB); //for denoise luminance curve
}
- if(skip != 1) if(parent->adnListener) {
- parent->adnListener->noiseChanged(0.f, 0.f);
+ if (skip != 1) if (parent->adnListener) {
+ parent->adnListener->noiseChanged (0.f, 0.f);
}
if (todo & M_LINDENOISE) {
@@ -641,26 +647,26 @@ void Crop::update (int todo)
int kall = 0;
float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi;
- parent->ipf.RGB_denoise(kall, origCrop, origCrop, calclum, parent->denoiseInfoStore.ch_M, parent->denoiseInfoStore.max_r, parent->denoiseInfoStore.max_b, parent->imgsrc->isRAW(), /*Roffset,*/ denoiseParams, parent->imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi);
+ parent->ipf.RGB_denoise (kall, origCrop, origCrop, calclum, parent->denoiseInfoStore.ch_M, parent->denoiseInfoStore.max_r, parent->denoiseInfoStore.max_b, parent->imgsrc->isRAW(), /*Roffset,*/ denoiseParams, parent->imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi);
if (parent->adnListener) {
- parent->adnListener->noiseChanged(nresi, highresi);
+ parent->adnListener->noiseChanged (nresi, highresi);
}
if (settings->leveldnautsimpl == 1) {
if ((denoiseParams.Cmethod == "AUT" || denoiseParams.Cmethod == "PRE") && (parent->adnListener)) { // force display value of sliders
- parent->adnListener->chromaChanged(denoiseParams.chroma, denoiseParams.redchro, denoiseParams.bluechro);
+ parent->adnListener->chromaChanged (denoiseParams.chroma, denoiseParams.redchro, denoiseParams.bluechro);
}
} else {
- if((denoiseParams.C2method == "AUTO" || denoiseParams.C2method == "PREV") && (parent->adnListener)) { // force display value of sliders
- parent->adnListener->chromaChanged(denoiseParams.chroma, denoiseParams.redchro, denoiseParams.bluechro);
+ if ((denoiseParams.C2method == "AUTO" || denoiseParams.C2method == "PREV") && (parent->adnListener)) { // force display value of sliders
+ parent->adnListener->chromaChanged (denoiseParams.chroma, denoiseParams.redchro, denoiseParams.bluechro);
}
}
}
}
- parent->imgsrc->convertColorSpace(origCrop, params.icm, parent->currWB);
+ parent->imgsrc->convertColorSpace (origCrop, params.icm, parent->currWB);
delete [] min_r;
delete [] min_b;
@@ -675,7 +681,7 @@ void Crop::update (int todo)
}
// has to be called after setCropSizes! Tools prior to this point can't handle the Edit mechanism, but that shouldn't be a problem.
- createBuffer(cropw, croph);
+ createBuffer (cropw, croph);
// transform
if (needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled)) {
@@ -684,11 +690,12 @@ void Crop::update (int todo)
}
if (needstransform)
- parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, SKIPS(parent->fw, skip), SKIPS(parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(),
+ parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, SKIPS (parent->fw, skip), SKIPS (parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(),
parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(),
parent->imgsrc->getMetaData()->getFocusDist(), parent->imgsrc->getRotateDegree(), false);
- else
- baseCrop->copyData(transCrop);
+ else {
+ baseCrop->copyData (transCrop);
+ }
if (transCrop) {
baseCrop = transCrop;
@@ -705,29 +712,29 @@ void Crop::update (int todo)
const int W = baseCrop->getWidth();
const int H = baseCrop->getHeight();
- LabImage labcbdl(W, H);
- parent->ipf.rgb2lab(*baseCrop, labcbdl, params.icm.working);
+ LabImage labcbdl (W, H);
+ parent->ipf.rgb2lab (*baseCrop, labcbdl, params.icm.working);
parent->ipf.dirpyrequalizer (&labcbdl, skip);
- parent->ipf.lab2rgb(labcbdl, *baseCrop, params.icm.working);
+ parent->ipf.lab2rgb (labcbdl, *baseCrop, params.icm.working);
}
// blurmap for shadow & highlights
if ((todo & M_BLURMAP) && params.sh.enabled) {
- double radius = sqrt (double(SKIPS(parent->fw, skip) * SKIPS(parent->fw, skip) + SKIPS(parent->fh, skip) * SKIPS(parent->fh, skip))) / 2.0;
+ double radius = sqrt (double (SKIPS (parent->fw, skip) * SKIPS (parent->fw, skip) + SKIPS (parent->fh, skip) * SKIPS (parent->fh, skip))) / 2.0;
double shradius = params.sh.radius;
if (!params.sh.hq) {
shradius *= radius / 1800.0;
}
- if(!cshmap) {
+ if (!cshmap) {
cshmap = new SHMap (cropw, croph, true);
}
cshmap->update (baseCrop, shradius, parent->ipf.lumimul, params.sh.hq, skip);
- if(parent->shmap->min_f < 65535.f) { // don't call forceStat with wrong values
+ if (parent->shmap->min_f < 65535.f) { // don't call forceStat with wrong values
cshmap->forceStat (parent->shmap->max_f, parent->shmap->min_f, parent->shmap->avg);
}
}
@@ -749,7 +756,7 @@ void Crop::update (int todo)
if (todo & M_RGBCURVE) {
double rrm, ggm, bbm;
DCPProfile::ApplyState as;
- DCPProfile *dcpProf = parent->imgsrc->getDCP(params.icm, parent->currWB, as);
+ DCPProfile *dcpProf = parent->imgsrc->getDCP (params.icm, parent->currWB, as);
LUTu histToneCurve;
parent->ipf.rgbProc (baseCrop, laboCrop, this, parent->hltonecurve, parent->shtonecurve, parent->tonecurve, cshmap,
@@ -775,9 +782,11 @@ void Crop::update (int todo)
}*/
// apply luminance operations
- if (todo & (M_LUMINANCE + M_COLOR)) {
+ //bool tutu = true;
+ if (todo & (M_LUMINANCE + M_COLOR)) { //
+ //if (tutu) { //
//I made a little change here. Rather than have luminanceCurve (and others) use in/out lab images, we can do more if we copy right here.
- labnCrop->CopyFrom(laboCrop);
+ labnCrop->CopyFrom (laboCrop);
//parent->ipf.luminanceCurve (labnCrop, labnCrop, parent->lumacurve);
@@ -788,31 +797,441 @@ void Crop::update (int todo)
bool clcutili = parent->clcutili;
bool cclutili = parent->cclutili;
bool wavcontlutili = parent->wavcontlutili;
+ bool locallutili = parent->locallutili;
+ LUTf lllocalcurve2 (65536, 0);
LUTu dummy;
+ bool needslocal = params.locallab.enabled;
+ LocretigainCurve locRETgainCurve;
+ LocLHCurve loclhCurve;
+
+ LocretigainCurverab locRETgainCurverab;
+ locallutili = false;
+ int sca = skip;
+
+ bool tyty = false;
+ int maxspot = settings->nspot + 1;
+
+ if (needslocal ) {
+ // if(tyty ) {
+ //Glib::ustring datalab2 = parent->imgsrc->getFileName() + ".mip";
+ Glib::ustring pop = options.getUserProfilePath() + "/";
+
+ Glib::ustring datalab;
+
+ if (options.mip == MI_opt) {
+ datalab = pop + Glib::path_get_basename (parent->imgsrc->getFileName () + ".mip");
+ }
+
+ if (options.mip == MI_prev) {
+ datalab = parent->imgsrc->getFileName() + ".mip";
+ }
+
+
+ ifstream fich (datalab, ios::in);
+
+ if (fich && parent->versionmip != 0) {//to avoid crash in some cases
+ int **dataspotd;
+
+ int realspot = params.locallab.nbspot;
+ bool tata = true;
+ bool locutili = parent->locutili;
+
+
+ for (int sp = 1; sp < maxspot; sp++) {
+ if (sp != realspot) {
+
+ params.locallab.circrad = parent->circrads[sp] ;
+ params.locallab.locX = parent->locx[sp] ;
+ params.locallab.locY = parent->locy[sp];
+ params.locallab.locYT = parent->locyt[sp];
+ params.locallab.locXL = parent->locxl[sp];
+ params.locallab.centerX = parent->centerx[sp];
+ params.locallab.centerY = parent->centery[sp];
+ params.locallab.lightness = parent->lights[sp];
+ params.locallab.contrast = parent->contrs[sp];
+ params.locallab.chroma = parent->chroms[sp];
+ params.locallab.sensi = parent->sensis[sp];
+ params.locallab.transit = parent->transits[sp];
+
+ if (parent->inverss[sp] == 0) {
+ params.locallab.invers = false;
+ } else {
+ params.locallab.invers = true;
+ }
+
+ if (parent->smeths[sp] == 0) {
+ params.locallab.Smethod = "IND" ;
+ } else if (parent->smeths[sp] == 1) {
+ params.locallab.Smethod = "SYM" ;
+ } else if (parent->smeths[sp] == 2) {
+ params.locallab.Smethod = "INDSL";
+ } else if (parent->smeths[sp] == 3) {
+ params.locallab.Smethod = "SYMSL";
+ }
+
+ params.locallab.radius = parent->radiuss[sp];
+ params.locallab.strength = parent->strengths[sp];
+ params.locallab.sensibn = parent->sensibns[sp];
+
+ if ( parent->inversrads[sp] == 0) {
+ params.locallab.inversrad = false;
+ } else {
+ params.locallab.inversrad = true;
+ }
+
+ params.locallab.str = parent->strs[sp];
+ params.locallab.chrrt = parent->chrrts[sp];
+ params.locallab.neigh = parent->neighs[sp];
+ params.locallab.vart = parent->varts[sp];
+ params.locallab.sensih = parent->sensihs[sp];
+
+ if (parent->inversrets[sp] == 0) {
+ params.locallab.inversret = false;
+ } else {
+ params.locallab.inversret = true;
+ }
+
+ if (parent->retinexs[sp] == 0) {
+ params.locallab.retinexMethod = "low" ;
+ } else if (parent->retinexs[sp] == 1) {
+ params.locallab.retinexMethod = "uni" ;
+ } else if (parent->retinexs[sp] == 2) {
+ params.locallab.retinexMethod = "high";
+ }
+
+ params.locallab.sharradius = parent->sharradiuss[sp];
+ params.locallab.sharamount = parent->sharamounts[sp];
+ params.locallab.shardamping = parent->shardampings[sp];
+ params.locallab.shariter = parent->shariters[sp];
+ params.locallab.sensisha = parent->sensishas[sp];
+
+ if (parent->inversshas[sp] == 0) {
+ params.locallab.inverssha = false;
+ } else {
+ params.locallab.inverssha = true;
+ }
+
+ if (parent->qualitys[sp] == 0) {
+ params.locallab.qualityMethod = "std" ;
+ } else if (parent->qualitys[sp] == 1) {
+ params.locallab.qualityMethod = "enh" ;
+ } else if (parent->qualitys[sp] == 2) {
+ params.locallab.qualityMethod = "enhden" ;
+ }
+
+ params.locallab.thres = parent->thress[sp];
+ params.locallab.proxi = parent->proxis[sp];
+
+ params.locallab.noiselumf = parent->noiselumfs[sp];
+ params.locallab.noiselumc = parent->noiselumcs[sp];
+ params.locallab.noisechrof = parent->noisechrofs[sp];
+ params.locallab.noisechroc = parent->noisechrocs[sp];
+ params.locallab.mult[0] = parent->mult0s[sp];
+ params.locallab.mult[1] = parent->mult1s[sp];
+ params.locallab.mult[2] = parent->mult2s[sp];
+ params.locallab.mult[3] = parent->mult3s[sp];
+ params.locallab.mult[4] = parent->mult4s[sp];
+ params.locallab.threshold = parent->thresholds[sp];
+ params.locallab.sensicb = parent->sensicbs[sp];
+
+ if (parent->activlums[sp] == 0) {
+ params.locallab.activlum = false;
+ } else {
+ params.locallab.activlum = true;
+ }
+
+ params.locallab.stren = parent->strens[sp];
+ params.locallab.gamma = parent->gammas[sp];
+ params.locallab.estop = parent->estops[sp];
+ params.locallab.scaltm = parent->scaltms[sp];
+ params.locallab.rewei = parent->reweis[sp];
+ params.locallab.sensitm = parent->sensitms[sp];
+ params.locallab.retrab = parent->retrabs[sp];
+
+ if (parent->curvactivs[sp] == 0) {
+ params.locallab.curvactiv = false;
+ } else {
+ params.locallab.curvactiv = true;
+ }
+
+ std::vector cretie;
+
+ for (int j = 0; j < parent->sizeretics[sp]; j++) {
+ cretie.push_back ((double) (parent->reticurvs[sp * 500 + j]) / 1000.);
+ }
+
+ params.locallab.localTgaincurve.clear();
+ params.locallab.localTgaincurve = cretie;
+
+ std::vector llc;
+
+ for (int j = 0; j < parent->sizellcs[sp]; j++) {
+ llc.push_back ((double) (parent->llcurvs[sp * 500 + j]) / 1000.);
+ }
+
+ params.locallab.llcurve.clear();
+ params.locallab.llcurve = llc;
+
+ std::vector lhc;
+
+ for (int j = 0; j < parent->sizelhcs[sp]; j++) {
+ lhc.push_back ((double) (parent->lhcurvs[sp * 500 + j]) / 1000.);
+ }
+
+ params.locallab.LHcurve.clear();
+ params.locallab.LHcurve = lhc;
+
+ params.locallab.getCurves (locRETgainCurve, locRETgainCurverab, loclhCurve);
+ locallutili = false;
+ CurveFactory::curveLocal (locallutili, params.locallab.llcurve, lllocalcurve2, sca);
+
+ params.locallab.hueref = (parent->huerefs[sp]) / 100.f;
+ params.locallab.chromaref = parent->chromarefs[sp];
+ params.locallab.lumaref = parent->lumarefs[sp];
+
+ parent->ipf.Lab_Local (1, sp, (float**)shbuffer, labnCrop, labnCrop, trafx / skip, trafy / skip, cropx / skip, cropy / skip, SKIPS (parent->fw, skip), SKIPS (parent->fh, skip), parent->fw, parent->fh, locutili, skip, locRETgainCurve, locallutili, lllocalcurve2, loclhCurve, params.locallab.hueref, params.locallab.chromaref, params.locallab.lumaref);
+ lllocalcurve2.clear();
+
+ if (skip <= 2) {
+ usleep (settings->cropsleep); //wait to avoid crash when crop 100% and move window
+ }
+ }
+ }
+
+
+
+ int sp ;
+ sp = realspot;
+ bool locutili2 = parent->locutili;
+ locallutili = false;
+
+ parent->sps[sp] = sp;
+ parent->circrads[sp] = params.locallab.circrad = parent->circrads[0];
+ parent->locx[sp] = params.locallab.locX = parent->locx[0];
+ parent->locy[sp] = params.locallab.locY = parent->locy[0];
+ parent->locyt[sp] = params.locallab.locYT = parent->locyt[0];
+ parent->locxl[sp] = params.locallab.locXL = parent->locxl[0];
+ parent->centerx[sp] = params.locallab.centerX = parent->centerx[0];
+ parent->centery[sp] = params.locallab.centerY = parent->centery[0];
+ parent->lights[sp] = params.locallab.lightness = parent->lights[0];
+ parent->contrs[sp] = params.locallab.contrast = parent->contrs[0];
+ parent->chroms[sp] = params.locallab.chroma = parent->chroms[0];
+ parent->sensis[sp] = params.locallab.sensi = parent->sensis[0];
+ parent->transits[sp] = params.locallab.transit = parent->transits[0];
+
+ if (parent->inverss[0] == 0) {
+ params.locallab.invers = false;
+ parent->inverss[sp] = 0;
+
+ } else {
+ params.locallab.invers = true;
+ parent->inverss[sp] = 1;
+
+ }
+
+ if (parent->smeths[0] == 0) {
+ params.locallab.Smethod = "IND" ;
+ parent->smeths[sp] = 0;
+
+ } else if (parent->smeths[0] == 1) {
+ params.locallab.Smethod = "SYM" ;
+ parent->smeths[sp] = 1;
+
+ } else if (parent->smeths[0] == 2) {
+ params.locallab.Smethod = "INDSL";
+ parent->smeths[2] = 0;
+
+
+ } else if (parent->smeths[0] == 3) {
+ params.locallab.Smethod = "SYMSL";
+ parent->smeths[sp] = 3;
+
+ }
+
+ params.locallab.radius = parent->radiuss[0];
+ params.locallab.strength = parent->strengths[0];
+ params.locallab.sensibn = parent->sensibns[0];
+
+ parent->radiuss[sp] = params.locallab.radius;
+ parent->strengths[sp] = params.locallab.strength;
+ parent->sensibns[sp] = params.locallab.sensibn;
+
+ if ( parent->inversrads[0] == 0) {
+ params.locallab.inversrad = false;
+ parent->inversrads[sp] = 0;
+ } else {
+ params.locallab.inversrad = true;
+ parent->inversrads[sp] = 1;
+ }
+
+ parent->strs[sp] = params.locallab.str = parent->strs[0];
+ parent->chrrts[sp] = params.locallab.chrrt = parent->chrrts[0];
+ parent->neighs[sp] = params.locallab.neigh = parent->neighs[0];
+ parent->varts[sp] = params.locallab.vart = parent->varts[0];
+ parent->sensihs[sp] = params.locallab.sensih = parent->sensihs[0];
+
+ if (parent->inversrets[0] == 0) {
+ params.locallab.inversret = false;
+ parent->inversrets[sp] = 0;
+ } else {
+ params.locallab.inversret = true;
+ parent->inversrets[sp] = 1;
+
+ }
+
+ if (parent->retinexs[sp] == 0) {
+ params.locallab.retinexMethod = "low" ;
+ parent->retinexs[sp] = 0;
+ } else if (parent->retinexs[sp] == 1) {
+ params.locallab.retinexMethod = "uni" ;
+ parent->retinexs[sp] = 1;
+
+ } else if (parent->retinexs[sp] == 2) {
+ params.locallab.retinexMethod = "high";
+ parent->retinexs[sp] = 2;
+
+ }
+
+ parent->sharradiuss[sp] = params.locallab.sharradius = parent->sharradiuss[0];
+
+ parent->sharamounts[sp] = params.locallab.sharamount = parent->sharamounts[0];
+ parent->shardampings[sp] = params.locallab.shardamping = parent->shardampings[0];
+ parent->shariters[sp] = params.locallab.shariter = parent->shariters[0];
+ parent->sensishas[sp] = params.locallab.sensisha = parent->sensishas[0];
+
+ if (parent->inversshas[0] == 0) {
+ params.locallab.inverssha = false;
+ parent->inversshas[sp] = 0;
+ } else {
+ params.locallab.inverssha = true;
+ parent->inversshas[sp] = 1;
+
+ }
+
+ if (parent->qualitys[sp] == 0) {
+ params.locallab.qualityMethod = "std" ;
+ parent->qualitys[sp] = 0;
+ } else if (parent->qualitys[sp] == 1) {
+ params.locallab.qualityMethod = "enh" ;
+ parent->qualitys[sp] = 1;
+ } else if (parent->qualitys[sp] == 2) {
+ params.locallab.qualityMethod = "enhden" ;
+ parent->qualitys[sp] = 2;
+ }
+
+ parent->thress[sp] = params.locallab.thres = parent->thress[0];
+ parent->proxis[sp] = params.locallab.proxi = parent->proxis[0];
+
+ parent->noiselumfs[sp] = params.locallab.noiselumf = parent->noiselumfs[0];
+ parent->noiselumcs[sp] = params.locallab.noiselumc = parent->noiselumcs[0];
+ parent->noisechrofs[sp] = params.locallab.noisechrof = parent->noisechrofs[0];
+ parent->noisechrocs[sp] = params.locallab.noisechroc = parent->noisechrocs[0];
+ parent->mult0s[sp] = params.locallab.mult[0] = parent->mult0s[0];
+ parent->mult1s[sp] = params.locallab.mult[1] = parent->mult1s[0];
+ parent->mult2s[sp] = params.locallab.mult[2] = parent->mult2s[0];
+ parent->mult3s[sp] = params.locallab.mult[3] = parent->mult3s[0];
+ parent->mult4s[sp] = params.locallab.mult[4] = parent->mult4s[0];
+ parent->thresholds[sp] = params.locallab.threshold = parent->thresholds[0];
+ parent->sensicbs[sp] = params.locallab.sensicb = parent->sensicbs[0];
+
+ if (parent->activlums[0] == 0) {
+ params.locallab.activlum = false;
+ parent->activlums[sp] = 0;
+ } else {
+ params.locallab.activlum = true;
+ parent->activlums[sp] = 1;
+
+ }
+
+ parent->strens[sp] = params.locallab.stren = parent->strens[0];
+ parent->gammas[sp] = params.locallab.gamma = parent->gammas[0];
+ parent->estops[sp] = params.locallab.estop = parent->estops[0];
+ parent->scaltms[sp] = params.locallab.scaltm = parent->scaltms[0];
+ parent->reweis[sp] = params.locallab.rewei = parent->reweis[0];
+ parent->sensitms[sp] = params.locallab.sensitm = parent->sensitms[0];
+ parent->retrabs[sp] = params.locallab.retrab = parent->retrabs[0];
+
+ if (parent->curvactivs[0] == 0) {
+ params.locallab.curvactiv = false;
+ parent->curvactivs[sp] = 0;
+
+ } else {
+ params.locallab.curvactiv = true;
+ parent->curvactivs[sp] = 1;
+
+ }
+
+ std::vector ccret;
+
+ for (int j = 0; j < parent->sizeretics[sp]; j++) {
+ ccret.push_back ((double) (parent->reticurvs[0 * 500 + j]) / 1000.);
+ parent->reticurvs[sp * 500 + j] = parent->reticurvs[0 * 500 + j];
+ }
+
+ params.locallab.localTgaincurve.clear();
+ params.locallab.localTgaincurve = ccret;
+
+ std::vector llcL;
+
+ for (int j = 0; j < parent->sizellcs[sp]; j++) {
+ llcL.push_back ((double) (parent->llcurvs[0 * 500 + j]) / 1000.);
+ parent->llcurvs[sp * 500 + j] = parent->llcurvs[0 * 500 + j] ;
+ }
+
+ params.locallab.llcurve.clear();
+ params.locallab.llcurve = llcL;
+
+ std::vector lhcL;
+
+ for (int j = 0; j < parent->sizelhcs[sp]; j++) {
+ lhcL.push_back ((double) (parent->lhcurvs[0 * 500 + j]) / 1000.);
+ parent->lhcurvs[sp * 500 + j] = parent->lhcurvs[0 * 500 + j] ;
+ }
+
+ params.locallab.LHcurve.clear();
+ params.locallab.LHcurve = lhcL;
+
+ params.locallab.getCurves (locRETgainCurve, locRETgainCurverab, loclhCurve);
+ locallutili = false;
+
+ CurveFactory::curveLocal (locallutili, params.locallab.llcurve, lllocalcurve2, sca); // skip == 1 ? 1 : 16);
+
+
+ params.locallab.hueref = (parent->huerefs[sp]) / 100.f;
+ params.locallab.chromaref = parent->chromarefs[sp];
+ params.locallab.lumaref = parent->lumarefs[sp];
+
+ parent->ipf.Lab_Local (1, sp, (float**)shbuffer, labnCrop, labnCrop, trafx / skip, trafy / skip, cropx / skip, cropy / skip, SKIPS (parent->fw, skip), SKIPS (parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(), locutili2, skip, locRETgainCurve, locallutili, lllocalcurve2, loclhCurve, params.locallab.hueref, params.locallab.chromaref, params.locallab.lumaref);
+ lllocalcurve2.clear();
+
+
+ }
+ }
+
int moderetinex;
// parent->ipf.MSR(labnCrop, labnCrop->W, labnCrop->H, 1);
parent->ipf.chromiLuminanceCurve (this, 1, labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve, parent->lhskcurve, parent->clcurve, parent->lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy);
parent->ipf.vibrance (labnCrop);
- if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
- parent->ipf.EPDToneMap(labnCrop, 5, 1);
+ if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
+ parent->ipf.EPDToneMap (labnCrop, 5, 1);
}
//parent->ipf.EPDToneMap(labnCrop, 5, 1); //Go with much fewer than normal iterates for fast redisplay.
// for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled
if (skip == 1) {
- if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
+ if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
parent->ipf.impulsedenoise (labnCrop);
}
- if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled) ) {
+ if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled) ) {
parent->ipf.defringe (labnCrop);
}
parent->ipf.MLsharpen (labnCrop);
- if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
+ if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
parent->ipf.MLmicrocontrast (labnCrop);
parent->ipf.sharpening (labnCrop, (float**)cbuffer, params.sharpening);
}
@@ -821,46 +1240,46 @@ void Crop::update (int todo)
// if (skip==1) {
WaveletParams WaveParams = params.wavelet;
- if(params.dirpyrequalizer.cbdlMethod == "aft") {
- if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled))) {
+ if (params.dirpyrequalizer.cbdlMethod == "aft") {
+ if (((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled))) {
parent->ipf.dirpyrequalizer (labnCrop, skip);
// parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip);
}
}
int kall = 0;
- int minwin = min(labnCrop->W, labnCrop->H);
+ int minwin = min (labnCrop->W, labnCrop->H);
int maxlevelcrop = 10;
// if(cp.mul[9]!=0)maxlevelcrop=10;
// adap maximum level wavelet to size of crop
- if(minwin * skip < 1024) {
+ if (minwin * skip < 1024) {
maxlevelcrop = 9; //sampling wavelet 512
}
- if(minwin * skip < 512) {
+ if (minwin * skip < 512) {
maxlevelcrop = 8; //sampling wavelet 256
}
- if(minwin * skip < 256) {
+ if (minwin * skip < 256) {
maxlevelcrop = 7; //sampling 128
}
- if(minwin * skip < 128) {
+ if (minwin * skip < 128) {
maxlevelcrop = 6;
}
- if(minwin < 64) {
+ if (minwin < 64) {
maxlevelcrop = 5;
}
int realtile;
- if(params.wavelet.Tilesmethod == "big") {
+ if (params.wavelet.Tilesmethod == "big") {
realtile = 22;
}
- if(params.wavelet.Tilesmethod == "lit") {
+ if (params.wavelet.Tilesmethod == "lit") {
realtile = 12;
}
@@ -872,69 +1291,70 @@ void Crop::update (int todo)
parent->ipf.Tile_calc (tilesize, overlap, kall, labnCrop->W, labnCrop->H, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip);
//now we have tile dimensions, overlaps
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- int minsizetile = min(tilewidth, tileheight);
+ int minsizetile = min (tilewidth, tileheight);
int maxlev2 = 10;
- if(minsizetile < 1024 && maxlevelcrop == 10) {
+ if (minsizetile < 1024 && maxlevelcrop == 10) {
maxlev2 = 9;
}
- if(minsizetile < 512) {
+ if (minsizetile < 512) {
maxlev2 = 8;
}
- if(minsizetile < 256) {
+ if (minsizetile < 256) {
maxlev2 = 7;
}
- if(minsizetile < 128) {
+ if (minsizetile < 128) {
maxlev2 = 6;
}
- int maxL = min(maxlev2, maxlevelcrop);
+ int maxL = min (maxlev2, maxlevelcrop);
- if(parent->awavListener) {
- parent->awavListener->wavChanged(float(maxL));
+ if (parent->awavListener) {
+ parent->awavListener->wavChanged (float (maxL));
}
- if((params.wavelet.enabled)) {
+ if ((params.wavelet.enabled)) {
WavCurve wavCLVCurve;
WavOpacityCurveRG waOpacityCurveRG;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
WavOpacityCurveWL waOpacityCurveWL;
+
LUTf wavclCurve;
LUTu dummy;
- params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves (wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
- parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, wavcontlutili, skip);
+ parent->ipf.ip_wavelet (labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, wavcontlutili, skip);
}
// }
// }
- if(params.colorappearance.enabled) {
+ if (params.colorappearance.enabled) {
float fnum = parent->imgsrc->getMetaData()->getFNumber (); // F number
float fiso = parent->imgsrc->getMetaData()->getISOSpeed () ; // ISO
float fspeed = parent->imgsrc->getMetaData()->getShutterSpeed () ; // Speed
double fcomp = parent->imgsrc->getMetaData()->getExpComp (); // Compensation +/-
double adap; // Scene's luminosity adaptation factor
- if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
+ if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
adap = 2000.;
} else {
- double E_V = fcomp + log2 (double((fnum * fnum) / fspeed / (fiso / 100.f)));
+ double E_V = fcomp + log2 (double ((fnum * fnum) / fspeed / (fiso / 100.f)));
E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
- E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV
- adap = pow(2., E_V - 3.); // cd / m2
+ E_V += log2 (params.raw.expos); // exposure raw white point ; log2 ==> linear to EV
+ adap = pow (2., E_V - 3.); // cd / m2
// end calculation adaptation scene luminosity
}
int begh = 0, endh = labnCrop->H;
bool execsharp = false;
- if(skip == 1) {
+ if (skip == 1) {
execsharp = true;
}
@@ -942,9 +1362,9 @@ void Crop::update (int todo)
cieCrop = new CieImage (cropw, croph);
}
- if(settings->ciecamfloat) {
+ if (settings->ciecamfloat) {
float d; // not used after this block
- parent->ipf.ciecam_02float (cieCrop, float(adap), begh, endh, 1, 2, labnCrop, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3,
+ parent->ipf.ciecam_02float (cieCrop, float (adap), begh, endh, 1, 2, labnCrop, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3,
dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, 1, execsharp, d, skip, 1);
} else {
double dd; // not used after this block
@@ -1024,11 +1444,17 @@ void Crop::freeAll ()
laboCrop = nullptr;
}
+
if (labnCrop ) {
delete labnCrop;
labnCrop = nullptr;
}
+ /* if (lablocCrop ) {
+ delete lablocCrop;
+ lablocCrop = NULL;
+ }
+ */
if (cropImg ) {
delete cropImg;
cropImg = nullptr;
@@ -1049,6 +1475,11 @@ void Crop::freeAll ()
cbuffer = nullptr;
}
+ if (shbuffer ) {
+ delete [] shbuffer;
+ shbuffer = nullptr;
+ }
+
if (cshmap ) {
delete cshmap;
cshmap = nullptr;
@@ -1083,12 +1514,12 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
rqcroph = rch;
// store and set requested crop size
- int rqx1 = LIM(rqcropx, 0, parent->fullw - 1);
- int rqy1 = LIM(rqcropy, 0, parent->fullh - 1);
+ int rqx1 = LIM (rqcropx, 0, parent->fullw - 1);
+ int rqy1 = LIM (rqcropy, 0, parent->fullh - 1);
int rqx2 = rqx1 + rqcropw - 1;
int rqy2 = rqy1 + rqcroph - 1;
- rqx2 = LIM(rqx2, 0, parent->fullw - 1);
- rqy2 = LIM(rqy2, 0, parent->fullh - 1);
+ rqx2 = LIM (rqx2, 0, parent->fullw - 1);
+ rqy2 = LIM (rqy2, 0, parent->fullh - 1);
this->skip = skip;
@@ -1098,10 +1529,10 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
int bx2 = rqx2 + skip * borderRequested;
int by2 = rqy2 + skip * borderRequested;
// clip it to fit into image area
- bx1 = LIM(bx1, 0, parent->fullw - 1);
- by1 = LIM(by1, 0, parent->fullh - 1);
- bx2 = LIM(bx2, 0, parent->fullw - 1);
- by2 = LIM(by2, 0, parent->fullh - 1);
+ bx1 = LIM (bx1, 0, parent->fullw - 1);
+ by1 = LIM (by1, 0, parent->fullh - 1);
+ bx2 = LIM (bx2, 0, parent->fullw - 1);
+ by2 = LIM (by2, 0, parent->fullh - 1);
int bw = bx2 - bx1 + 1;
int bh = by2 - by1 + 1;
@@ -1114,17 +1545,18 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
int orW, orH;
parent->imgsrc->getSize (cp, orW, orH);
- int cw = SKIPS(bw, skip);
- int ch = SKIPS(bh, skip);
+ int cw = SKIPS (bw, skip);
+ int ch = SKIPS (bh, skip);
- leftBorder = SKIPS(rqx1 - bx1, skip);
- upperBorder = SKIPS(rqy1 - by1, skip);
+ leftBorder = SKIPS (rqx1 - bx1, skip);
+ upperBorder = SKIPS (rqy1 - by1, skip);
if (settings->verbose) {
printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh, cw, ch);
}
EditType editType = ET_PIPETTE;
+
if (const auto editProvider = PipetteBuffer::getDataProvider ()) {
if (const auto editSubscriber = editProvider->getCurrSubscriber ()) {
editType = editSubscriber->getEditingType ();
@@ -1142,11 +1574,11 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
origCrop = new Imagefloat;
}
- origCrop->allocate(trafw, trafh); // Resizing the buffer (optimization)
+ origCrop->allocate (trafw, trafh); // Resizing the buffer (optimization)
// if transCrop doesn't exist yet, it'll be created where necessary
if (transCrop) {
- transCrop->allocate(cropw, croph);
+ transCrop->allocate (cropw, croph);
}
if (laboCrop) {
@@ -1155,17 +1587,25 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
laboCrop = new LabImage (cropw, croph);
+ // if (translabCrop) translabCrop->reallocLab();
+
if (labnCrop) {
delete labnCrop; // labnCrop can't be resized
}
labnCrop = new LabImage (cropw, croph);
+ /* if (lablocCrop) {
+ delete lablocCrop; // labnCrop can't be resized
+ }
+
+ lablocCrop = new LabImage (cropw, croph);
+ */
if (!cropImg) {
cropImg = new Image8;
}
- cropImg->allocate(cropw, croph); // Resizing the buffer (optimization)
+ cropImg->allocate (cropw, croph); // Resizing the buffer (optimization)
//cieCrop is only used in Crop::update, it is destroyed now but will be allocated on first use
if (cieCrop) {
@@ -1177,28 +1617,43 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
delete [] cbuffer;
}
+ if (shbuffer ) {
+ delete [] shbuffer;
+ }
+
if (cbuf_real) {
delete [] cbuf_real;
}
+ if (shbuf_real) {
+ delete [] shbuf_real;
+ }
+
if (cshmap ) {
delete cshmap;
cshmap = nullptr;
}
cbuffer = new float*[croph];
- cbuf_real = new float[(croph + 2)*cropw];
+ cbuf_real = new float[ (croph + 2)*cropw];
for (int i = 0; i < croph; i++) {
cbuffer[i] = cbuf_real + cropw * i + cropw;
}
- if(params.sh.enabled) {
+ shbuffer = new float*[croph];
+ shbuf_real = new float[ (croph + 2)*cropw];
+
+ for (int i = 0; i < croph; i++) {
+ shbuffer[i] = shbuf_real + cropw * i + cropw;
+ }
+
+ if (params.sh.enabled) {
cshmap = new SHMap (cropw, croph, true);
}
if (editType == ET_PIPETTE) {
- PipetteBuffer::resize(cropw, croph);
+ PipetteBuffer::resize (cropw, croph);
} else if (PipetteBuffer::bufferCreated()) {
PipetteBuffer::flush();
}
diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h
index 450c659f0..c2fcc2a63 100644
--- a/rtengine/dcrop.h
+++ b/rtengine/dcrop.h
@@ -47,12 +47,14 @@ protected:
Image8* cropImg; // "one chunk" allocation ; displayed image in monitor color space, showing the output profile as well (soft-proofing enabled, which then correspond to workimg) or not
float * cbuf_real; // "one chunk" allocation
SHMap* cshmap; // per line allocation
+ float * shbuf_real; // "one chunk" allocation
// --- automatically allocated and deleted when necessary, and only renewed on size changes
Imagefloat* transCrop; // "one chunk" allocation, allocated if necessary
CieImage* cieCrop; // allocating 6 images, each in "one chunk" allocation
// -----------------------------------------------------------------
float** cbuffer;
+ float** shbuffer;
bool updating; /// Flag telling if an updater thread is currently processing
bool newUpdatePending; /// Flag telling the updater thread that a new update is pending
@@ -77,6 +79,7 @@ protected:
public:
Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow);
virtual ~Crop ();
+// MyMutex* locMutex;
void mLock ()
{
@@ -86,7 +89,7 @@ public:
{
cropMutex.lock();
}
- void setEditSubscriber(EditSubscriber* newSubscriber);
+ void setEditSubscriber (EditSubscriber* newSubscriber);
bool hasListener ()
{
return cropImageListener;
diff --git a/rtengine/dirpyr_equalizer.cc b/rtengine/dirpyr_equalizer.cc
index a3a6d81b0..dd7211667 100644
--- a/rtengine/dirpyr_equalizer.cc
+++ b/rtengine/dirpyr_equalizer.cc
@@ -42,10 +42,14 @@ namespace rtengine
{
static const int maxlevel = 6;
+static const int maxlevelloc = 5;
+
static const float noise = 2000;
//sequence of scales
static const int scales[6] = {1, 2, 4, 8, 16, 32};
+static const int scalesloc[5] = {1, 2, 4, 8, 16};
+
extern const Settings* settings;
//sequence of scales
@@ -257,6 +261,212 @@ SSEFUNCTION void ImProcFunctions :: dirpyr_equalizer(float ** src, float ** dst,
}
+SSEFUNCTION void ImProcFunctions :: cbdl_local_temp(float ** src, float ** dst, float ** loctemp, int srcwidth, int srcheight, const float * mult, const double dirpyrThreshold, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev)
+{
+ int lastlevel = maxlevelloc;
+
+ if(settings->verbose) {
+ printf("Dirpyr scaleprev=%i\n", scaleprev);
+ }
+
+ float atten123 = (float) settings->level123_cbdl;
+
+ if(atten123 > 50.f) {
+ atten123 = 50.f;
+ }
+
+ if(atten123 < 0.f) {
+ atten123 = 0.f;
+ }
+
+ float atten0 = (float) settings->level0_cbdl;
+
+ if(atten0 > 40.f) {
+ atten123 = 40.f;
+ }
+
+ if(atten0 < 0.f) {
+ atten0 = 0.f;
+ }
+
+ if((t_r - t_l) < 0.55f) {
+ t_l = t_r + 0.55f; //avoid too small range
+ }
+
+ while (lastlevel > 0 && fabs(mult[lastlevel - 1] - 1) < 0.001) {
+
+ lastlevel--;
+ //printf("last level to process %d \n",lastlevel);
+ }
+
+ if (lastlevel == 0) {
+ return;
+ }
+
+ int level;
+ float multi[5] = {1.f, 1.f, 1.f, 1.f, 1.f};
+ float scalefl[5];
+
+ for(int lv = 0; lv < 5; lv++) {
+ scalefl[lv] = ((float) scalesloc[lv]) / (float) scaleprev;
+
+ if(lv >= 1) {
+ if(scalefl[lv] < 1.f) {
+ multi[lv] = (atten123 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; //modulate action if zoom < 100%
+ } else {
+ multi[lv] = (float) mult[lv];
+ }
+ } else {
+ if(scalefl[lv] < 1.f) {
+ multi[lv] = (atten0 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; //modulate action if zoom < 100%
+ } else {
+ multi[lv] = (float) mult[lv];
+ }
+ }
+
+ }
+
+ if(settings->verbose) {
+ printf("CbDL local mult0=%f 1=%f 2=%f 3=%f 4=%f\n", multi[0], multi[1], multi[2], multi[3], multi[4]);
+ }
+
+ multi_array2D dirpyrlo (srcwidth, srcheight);
+
+ level = 0;
+
+ //int thresh = 100 * mult[5];
+ int scale = (int)(scalesloc[level]) / scaleprev;
+
+ if(scale < 1) {
+ scale = 1;
+ }
+
+
+ dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, scale);
+
+ level = 1;
+
+ while(level < lastlevel) {
+
+ scale = (int)(scalesloc[level]) / scaleprev;
+
+ if(scale < 1) {
+ scale = 1;
+ }
+
+ dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, scale);
+
+ level ++;
+ }
+
+ float **tmpHue, **tmpChr;
+ /*
+ if(skinprot != 0.f) {
+ // precalculate hue and chroma, use SSE, if available
+ // by precalculating these values we can greatly reduce the number of calculations in idirpyr_eq_channel()
+ // but we need two additional buffers for this preprocessing
+ tmpHue = new float*[srcheight];
+
+ for (int i = 0; i < srcheight; i++) {
+ tmpHue[i] = new float[srcwidth];
+ }
+
+ #ifdef __SSE2__
+ #pragma omp parallel for
+
+ for(int i = 0; i < srcheight; i++) {
+ int j;
+
+ for(j = 0; j < srcwidth - 3; j += 4) {
+ _mm_storeu_ps(&tmpHue[i][j], xatan2f(LVFU(l_b[i][j]), LVFU(l_a[i][j])));
+ }
+
+ for(; j < srcwidth; j++) {
+ tmpHue[i][j] = xatan2f(l_b[i][j], l_a[i][j]);
+ }
+ }
+
+ #else
+ #pragma omp parallel for
+
+ for(int i = 0; i < srcheight; i++) {
+ for(int j = 0; j < srcwidth; j++) {
+ tmpHue[i][j] = xatan2f(l_b[i][j], l_a[i][j]);
+ }
+ }
+
+ #endif
+ tmpChr = new float*[srcheight];
+
+ for (int i = 0; i < srcheight; i++) {
+ tmpChr[i] = new float[srcwidth];
+ }
+
+ #ifdef __SSE2__
+ #pragma omp parallel
+ {
+ __m128 div = _mm_set1_ps(327.68f);
+ #pragma omp for
+
+ for(int i = 0; i < srcheight; i++) {
+ int j;
+
+ for(j = 0; j < srcwidth - 3; j += 4) {
+ _mm_storeu_ps(&tmpChr[i][j], _mm_sqrt_ps(SQRV(LVFU(l_b[i][j])) + SQRV(LVFU(l_a[i][j]))) / div);
+ }
+
+ for(; j < srcwidth; j++) {
+ tmpChr[i][j] = sqrtf(SQR((l_b[i][j])) + SQR((l_a[i][j]))) / 327.68f;
+ }
+ }
+ }
+ #else
+ #pragma omp parallel for
+
+ for(int i = 0; i < srcheight; i++) {
+ for(int j = 0; j < srcwidth; j++) {
+ tmpChr[i][j] = sqrtf(SQR((l_b[i][j])) + SQR((l_a[i][j]))) / 327.68f;
+ }
+ }
+
+ #endif
+ }
+ */
+ // with the current implementation of idirpyr_eq_channel we can safely use the buffer from last level as buffer, saves some memory
+ float ** buffer = dirpyrlo[lastlevel - 1];
+
+ for(int level = lastlevel - 1; level > 0; level--) {
+ idirpyr_eq_channel_loc(dirpyrlo[level], dirpyrlo[level - 1], loctemp, buffer, srcwidth, srcheight, level, multi, dirpyrThreshold, tmpHue, tmpChr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice );
+ }
+
+ scale = scalesloc[0];
+
+ idirpyr_eq_channel_loc(dirpyrlo[0], dst, loctemp, buffer, srcwidth, srcheight, 0, multi, dirpyrThreshold, tmpHue, tmpChr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice );
+ /*
+ if(skinprot != 0.f) {
+ for (int i = 0; i < srcheight; i++) {
+ delete [] tmpChr[i];
+ }
+
+ delete [] tmpChr;
+
+ for (int i = 0; i < srcheight; i++) {
+ delete [] tmpHue[i];
+ }
+
+ delete [] tmpHue;
+ }
+ */
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ #pragma omp parallel for
+
+ for (int i = 0; i < srcheight; i++)
+ for (int j = 0; j < srcwidth; j++) {
+ dst[i][j] = src[i][j];
+ loctemp[i][j] = CLIP(buffer[i][j]); // TODO: Really a clip necessary?
+ }
+
+}
void ImProcFunctions :: dirpyr_equalizercam (CieImage *ncie, float ** src, float ** dst, int srcwidth, int srcheight, float ** h_p, float ** C_p, const double * mult, const double dirpyrThreshold, const double skinprot, bool execdir, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev)
@@ -624,6 +834,102 @@ SSEFUNCTION void ImProcFunctions::dirpyr_channel(float ** data_fine, float ** da
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+void ImProcFunctions::idirpyr_eq_channel_loc(float ** data_coarse, float ** data_fine, float ** loctemp, float ** buffer, int width, int height, int level, float mult[5], const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r , int choice)
+{
+ const float skinprotneg = -skinprot;
+ const float factorHard = (1.f - skinprotneg / 100.f);
+
+ float offs;
+
+ if(skinprot == 0.f) {
+ offs = 0.f;
+ } else {
+ offs = -1.f;
+ }
+
+ float multbis[5];
+
+ multbis[level] = mult[level]; //multbis to reduce artifacts for high values mult
+
+ if(level == 4 && mult[level] > 1.f) {
+ multbis[level] = 1.f + 0.65f * (mult[level] - 1.f);
+ }
+
+ // if(level == 5 && mult[level] > 1.f) {
+ // multbis[level] = 1.f + 0.45f * (mult[level] - 1.f);
+ // }
+
+ LUTf irangefn (0x20000);
+ {
+ const float noisehi = 1.33f * noise * dirpyrThreshold / expf(level * log(3.0)), noiselo = 0.66f * noise * dirpyrThreshold / expf(level * log(3.0));
+ //printf("level=%i multlev=%f noisehi=%f noiselo=%f skinprot=%f\n",level,mult[level], noisehi, noiselo, skinprot);
+
+ for (int i = 0; i < 0x20000; i++) {
+ if (abs(i - 0x10000) > noisehi || multbis[level] < 1.0) {
+ irangefn[i] = multbis[level] + offs;
+ } else {
+ if (abs(i - 0x10000) < noiselo) {
+ irangefn[i] = 1.f + offs ;
+ } else {
+ irangefn[i] = 1.f + offs + (multbis[level] - 1.f) * (noisehi - abs(i - 0x10000)) / (noisehi - noiselo + 0.01f) ;
+ }
+ }
+ }
+ }
+
+ if(skinprot == 0.f)
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+ for(int i = 0; i < height; i++) {
+ for(int j = 0; j < width; j++) {
+ float hipass = (data_fine[i][j] - data_coarse[i][j]);
+ buffer[i][j] += irangefn[hipass + 0x10000] * hipass;
+ }
+ }
+
+ /*
+ else if(skinprot > 0.f)
+ #ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+ #endif
+ for(int i = 0; i < height; i++) {
+ for(int j = 0; j < width; j++) {
+ float scale = 1.f;
+ float hipass = (data_fine[i][j] - data_coarse[i][j]);
+ // These values are precalculated now
+ float modhue = hue[i][j];
+ float modchro = chrom[i][j];
+ Color::SkinSatCbdl ((data_fine[i][j]) / 327.68f, modhue, modchro, skinprot, scale, true, b_l, t_l, t_r);
+ buffer[i][j] += (1.f + (irangefn[hipass + 0x10000]) * scale) * hipass ;
+ }
+ }
+ else
+ #ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+ #endif
+ for(int i = 0; i < height; i++) {
+ for(int j = 0; j < width; j++) {
+ float scale = 1.f;
+ float hipass = (data_fine[i][j] - data_coarse[i][j]);
+ // These values are precalculated now
+ float modhue = hue[i][j];
+ float modchro = chrom[i][j];
+ Color::SkinSatCbdl ((data_fine[i][j]) / 327.68f, modhue, modchro, skinprotneg, scale, false, b_l, t_l, t_r);
+ float correct = irangefn[hipass + 0x10000];
+
+ if (scale == 1.f) {//image hard
+ buffer[i][j] += (1.f + (correct) * (factorHard)) * hipass ;
+ } else { //image soft with scale < 1 ==> skin
+ buffer[i][j] += (1.f + (correct)) * hipass ;
+ }
+ }
+ }
+ */
+}
+
+
+
void ImProcFunctions::idirpyr_eq_channel(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult[5], const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r , int choice)
{
diff --git a/rtengine/gauss.cc b/rtengine/gauss.cc
index 4b84a125a..22339d27c 100644
--- a/rtengine/gauss.cc
+++ b/rtengine/gauss.cc
@@ -1141,7 +1141,6 @@ template void gaussVerticalmult (T** src, T** dst, const int W, const i
template void gaussianBlurImpl(T** src, T** dst, const int W, const int H, const double sigma, T *buffer = nullptr, eGaussType gausstype = GAUSS_STANDARD, T** buffer2 = nullptr)
{
- static constexpr auto GAUSS_SKIP = 0.25;
static constexpr auto GAUSS_3X3_LIMIT = 0.6;
static constexpr auto GAUSS_DOUBLE = 70.0;
@@ -1189,6 +1188,9 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int
} else {
if (sigma < GAUSS_SKIP) {
// don't perform filtering
+#ifdef _OPENMP
+#pragma omp single
+#endif
if (src != dst) {
memcpy (dst[0], src[0], W * H * sizeof(T));
}
diff --git a/rtengine/gauss.h b/rtengine/gauss.h
index 72f115cc4..a8cd26161 100644
--- a/rtengine/gauss.h
+++ b/rtengine/gauss.h
@@ -20,6 +20,8 @@
#define _GAUSS_H_
enum eGaussType {GAUSS_STANDARD, GAUSS_MULT, GAUSS_DIV};
+static constexpr auto GAUSS_SKIP = 0.25;
+
void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, float *buffer = nullptr, eGaussType gausstype = GAUSS_STANDARD, float** buffer2 = nullptr);
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 46cf031bd..a7c2144fb 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -23,6 +23,9 @@
#include "../rtgui/ppversion.h"
#include "colortemp.h"
#include "improcfun.h"
+#include
+#include
+#include
#include "iccstore.h"
#ifdef _OPENMP
#include
@@ -33,63 +36,136 @@ namespace rtengine
extern const Settings* settings;
ImProcCoordinator::ImProcCoordinator ()
- : orig_prev(nullptr), oprevi(nullptr), oprevl(nullptr), nprevl(nullptr), previmg(nullptr), workimg(nullptr),
- ncie(nullptr), imgsrc(nullptr), shmap(nullptr), lastAwbEqual(0.), ipf(¶ms, true), monitorIntent(RI_RELATIVE),
- softProof(false), gamutCheck(false), scale(10), highDetailPreprocessComputed(false), highDetailRawComputed(false),
- allocated(false), bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(NAN),
-
+ : orig_prev (nullptr), oprevi (nullptr), oprevl (nullptr), nprevl (nullptr), previmg (nullptr), workimg (nullptr),
+ ncie (nullptr), imgsrc (nullptr), shmap (nullptr), lastAwbEqual (0.), ipf (¶ms, true), monitorIntent (RI_RELATIVE),
+ softProof (false), gamutCheck (false), scale (10), highDetailPreprocessComputed (false), highDetailRawComputed (false),
+ allocated (false), bwAutoR (-9000.f), bwAutoG (-9000.f), bwAutoB (-9000.f), CAMMean (NAN), coordX (0), coordY (0), localX (0), localY (0),
+ dataspot (nullptr), retistr (nullptr), retistrsav (nullptr), llstr (nullptr), lhstr (nullptr),
ctColorCurve(),
- hltonecurve(65536),
- shtonecurve(65536),
- tonecurve(65536, 0), //,1);
- lumacurve(32770, 0), // lumacurve[32768] and lumacurve[32769] will be set to 32768 and 32769 later to allow linear interpolation
- chroma_acurve(65536, 0),
- chroma_bcurve(65536, 0),
- satcurve(65536, 0),
- lhskcurve(65536, 0),
- clcurve(65536, 0),
- wavclCurve(65536, 0),
- clToningcurve(65536, 0),
- cl2Toningcurve(65536, 0),
- Noisecurve(65536, 0),
- NoiseCCcurve(65536, 0),
- vhist16(65536), vhist16bw(65536),
- lhist16CAM(65536),
- lhist16CCAM(65536),
+// localcurve(65536, 0),
+ hltonecurve (65536),
+ shtonecurve (65536),
+ tonecurve (65536, 0), //,1);
+ lumacurve (32770, 0), // lumacurve[32768] and lumacurve[32769] will be set to 32768 and 32769 later to allow linear interpolation
+ chroma_acurve (65536, 0),
+ chroma_bcurve (65536, 0),
+ satcurve (65536, 0),
+ lhskcurve (65536, 0),
+ clcurve (65536, 0),
+ wavclCurve (65536, 0),
+ clToningcurve (65536, 0),
+ lllocalcurve (65536, 0),
+
+ cl2Toningcurve (65536, 0),
+ Noisecurve (65536, 0),
+ NoiseCCcurve (65536, 0),
+ vhist16 (65536), vhist16bw (65536),
+ lhist16CAM (65536),
+ lhist16CCAM (65536),
lhist16RETI(),
- lhist16LClad(65536),
- histRed(256), histRedRaw(256),
- histGreen(256), histGreenRaw(256),
- histBlue(256), histBlueRaw(256),
- histLuma(256),
- histToneCurve(256),
- histToneCurveBW(256),
- histLCurve(256),
- histCCurve(256),
- histLLCurve(256),
+ lhist16LClad (65536),
+ histRed (256), histRedRaw (256),
+ histGreen (256), histGreenRaw (256),
+ histBlue (256), histBlueRaw (256),
+ histLuma (256),
+ histToneCurve (256),
+ histToneCurveBW (256),
+ histLCurve (256),
+ histCCurve (256),
+ histLLCurve (256),
- histLCAM(256),
- histCCAM(256),
- histClad(256),
- bcabhist(256),
- histChroma(256),
+ histLCAM (256),
+ histCCAM (256),
+ histClad (256),
+ bcabhist (256),
+ histChroma (256),
- histLRETI(256),
+ histLRETI (256),
CAMBrightCurveJ(), CAMBrightCurveQ(),
+ circrads (500, -10000),
+ locx (500, -10000),
+ locy (500, -10000),
+ centerx (500, -10000),
+ centery (500, -10000),
+ locxl (500, -10000),
+ locyt (500, -10000),
+ lights (500, -100000),
+ contrs (500, -10000),
+ chroms (500, -10000),
+ sensis (500, -10000),
+ transits (500, -10000),
+ inverss (500, -10000),
+ curvactivs (500, -10000),
+ smeths (500, -10000),
+ curens (500, -10000),
+ radiuss (500, -10000),
+ strengths (500, -10000),
+ sensibns (500, -10000),
+ inversrads (500, -10000),
+ strs (500, 10000),
+ chrrts (500, -10000),
+ neighs (500, -10000),
+ varts (500, -10000),
+ sensihs (500, -10000),
+ inversrets (500, -10000),
+ retinexs (500, -10000),
+ sps (500, -10000),
+ sharradiuss (500, -10000),
+ sharamounts (500, -10000),
+ shardampings (500, -10000),
+ shariters (500, -10000),
+ inversshas (500, -10000),
+ sensishas (500, -10000),
+ qualitys (500, -10000),
+ proxis (500, -10000),
+ thress (500, -10000),
+ noiselumfs (500, -10000),
+ noiselumcs (500, -10000),
+ noisechrofs (500, -10000),
+ noisechrocs (500, -10000),
+ mult0s (500, -10000),
+ mult1s (500, -10000),
+ mult2s (500, -10000),
+ mult3s (500, -10000),
+ mult4s (500, -10000),
+ thresholds (500, -10000),
+ sensicbs (500, -10000),
+ activlums (500, -10000),
+ versionmip (0),
+ strens (500, -10000),
+ gammas (500, -10000),
+ estops (500, -10000),
+ scaltms (500, -10000),
+ reweis (500, -10000),
+ sensitms (500, -10000),
+ reticurvs (25000, -10000), //allow 500 values for each control point * 500
+ sizeretics (500, -10000),
+ retrabs (500, -10000),
+ llcurvs (25000, -10000), //allow 500 values for each control point * 500
+ sizellcs (500, -10000),
+ lhcurvs (25000, -10000), //allow 500 values for each control point * 500
+ sizelhcs (500, -10000),
+
+ lumarefs (500, -100000.f),
+ chromarefs (500, -100000.f),
+ huerefs (500, -100000.f),
+
rCurve(),
gCurve(),
bCurve(),
- rcurvehist(256), rcurvehistCropped(256), rbeforehist(256),
- gcurvehist(256), gcurvehistCropped(256), gbeforehist(256),
- bcurvehist(256), bcurvehistCropped(256), bbeforehist(256),
- fw(0), fh(0), tr(0),
- fullw(1), fullh(1),
- pW(-1), pH(-1),
- plistener(nullptr), imageListener(nullptr), aeListener(nullptr), acListener(nullptr), abwListener(nullptr), actListener(nullptr), adnListener(nullptr), awavListener(nullptr), dehaListener(nullptr), hListener(nullptr),
- resultValid(false), lastOutputProfile("BADFOOD"), lastOutputIntent(RI__COUNT), lastOutputBPC(false), thread(nullptr), changeSinceLast(0), updaterRunning(false), destroying(false), utili(false), autili(false), wavcontlutili(false),
- butili(false), ccutili(false), cclutili(false), clcutili(false), opautili(false), conversionBuffer(1, 1), colourToningSatLimit(0.f), colourToningSatLimitOpacity(0.f)
+ rcurvehist (256), rcurvehistCropped (256), rbeforehist (256),
+ gcurvehist (256), gcurvehistCropped (256), gbeforehist (256),
+ bcurvehist (256), bcurvehistCropped (256), bbeforehist (256),
+ fw (0), fh (0), tr (0),
+ fullw (1), fullh (1),
+ pW (-1), pH (-1),
+ plistener (nullptr), imageListener (nullptr), aeListener (nullptr), acListener (nullptr), abwListener (nullptr), aloListener (nullptr), actListener (nullptr), adnListener (nullptr), awavListener (nullptr), dehaListener (nullptr), hListener (nullptr),
+ resultValid (false), lastOutputProfile ("BADFOOD"), lastOutputIntent (RI__COUNT), lastOutputBPC (false), thread (nullptr), changeSinceLast (0), updaterRunning (false), destroying (false), utili (false), autili (false), wavcontlutili (false),
+ butili (false), ccutili (false), cclutili (false), clcutili (false), opautili (false), conversionBuffer (1, 1), colourToningSatLimit (0.f), colourToningSatLimitOpacity (0.f)
+
+
{}
void ImProcCoordinator::assign (ImageSource* imgsrc)
@@ -133,7 +209,7 @@ DetailedCrop* ImProcCoordinator::createCrop (::EditDataProvider *editDataProvid
void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
{
- MyMutex::MyLock processingLock(mProcessing);
+ MyMutex::MyLock processingLock (mProcessing);
int numofphases = 14;
int readyphase = 0;
@@ -164,15 +240,15 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
ColorManagementParams cmp = params.icm;
LCurveParams lcur = params.labCurve;
- if( !highDetailNeeded ) {
+ if ( !highDetailNeeded ) {
// if below 100% magnification, take a fast path
- if(rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::none] && rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono]) {
+ if (rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::none] && rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono]) {
rp.bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast];
}
//bayerrp.all_enhance = false;
- if(rp.xtranssensor.method != RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::none] && rp.xtranssensor.method != RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono]) {
+ if (rp.xtranssensor.method != RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::none] && rp.xtranssensor.method != RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono]) {
rp.xtranssensor.method = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::fast];
}
@@ -185,8 +261,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
// raw auto CA is bypassed if no high detail is needed, so we have to compute it when high detail is needed
if ( (todo & M_PREPROC) || (!highDetailPreprocessComputed && highDetailNeeded)) {
- imgsrc->preprocess( rp, params.lensProf, params.coarse );
- imgsrc->getRAWHistogram( histRedRaw, histGreenRaw, histBlueRaw );
+ imgsrc->preprocess ( rp, params.lensProf, params.coarse );
+ imgsrc->getRAWHistogram ( histRedRaw, histGreenRaw, histBlueRaw );
if (highDetailNeeded) {
highDetailPreprocessComputed = true;
@@ -214,13 +290,13 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
if (settings->verbose) {
if (imgsrc->getSensorType() == ST_BAYER) {
- printf("Demosaic Bayer image using method: %s\n", rp.bayersensor.method.c_str());
+ printf ("Demosaic Bayer image using method: %s\n", rp.bayersensor.method.c_str());
} else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) {
- printf("Demosaic X-Trans image with using method: %s\n", rp.xtranssensor.method.c_str());
+ printf ("Demosaic X-Trans image with using method: %s\n", rp.xtranssensor.method.c_str());
}
}
- imgsrc->demosaic( rp);//enabled demosaic
+ imgsrc->demosaic ( rp); //enabled demosaic
// if a demosaic happened we should also call getimage later, so we need to set the M_INIT flag
todo |= M_INIT;
@@ -231,10 +307,10 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
if (params.retinex.enabled) {
- lhist16RETI(32768);
+ lhist16RETI (32768);
lhist16RETI.clear();
- imgsrc->retinexPrepareBuffers(params.icm, params.retinex, conversionBuffer, lhist16RETI);
+ imgsrc->retinexPrepareBuffers (params.icm, params.retinex, conversionBuffer, lhist16RETI);
}
}
@@ -245,12 +321,12 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
LUTf cdcurve (65536, 0);
LUTf mapcurve (65536, 0);
- imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, 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, dehagaintransmissionCurve, 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);
+ if (dehaListener) {
+ dehaListener->minmaxChanged (maxCD, minCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
}
}
@@ -259,7 +335,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
// It has to be done there, because the next 'if' statement will use the value computed here
if (todo & M_AUTOEXP) {
if (params.toneCurve.autoexp) {// this enabled HLRecovery
- if (ToneCurveParams::HLReconstructionNecessary(histRedRaw, histGreenRaw, histBlueRaw) && !params.toneCurve.hrenabled) {
+ if (ToneCurveParams::HLReconstructionNecessary (histRedRaw, histGreenRaw, histBlueRaw) && !params.toneCurve.hrenabled) {
// switching params.toneCurve.hrenabled to true -> shouting in listener's ears!
params.toneCurve.hrenabled = true;
@@ -270,9 +346,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
if (todo & (M_INIT | M_LINDENOISE)) {
- MyMutex::MyLock initLock(minit); // Also used in crop window
+ MyMutex::MyLock initLock (minit); // Also used in crop window
- imgsrc->HLRecovery_Global( params.toneCurve); // this handles Color HLRecovery
+ imgsrc->HLRecovery_Global ( params.toneCurve); // this handles Color HLRecovery
if (settings->verbose) {
@@ -286,14 +362,14 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
} else if (params.wb.method == "Auto") {
if (lastAwbEqual != params.wb.equal) {
double rm, gm, bm;
- imgsrc->getAutoWBMultipliers(rm, gm, bm);
+ imgsrc->getAutoWBMultipliers (rm, gm, bm);
if (rm != -1.) {
- autoWB.update(rm, gm, bm, params.wb.equal);
+ autoWB.update (rm, gm, bm, params.wb.equal);
lastAwbEqual = params.wb.equal;
} else {
lastAwbEqual = -1.;
- autoWB.useDefaults(params.wb.equal);
+ autoWB.useDefaults (params.wb.equal);
}
//double rr,gg,bb;
@@ -306,7 +382,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
params.wb.temperature = currWB.getTemp ();
params.wb.green = currWB.getGreen ();
- int tr = getCoarseBitMask(params.coarse);
+ int tr = getCoarseBitMask (params.coarse);
imgsrc->getFullSize (fw, fh, tr);
@@ -361,7 +437,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
}
*/
- imgsrc->convertColorSpace(orig_prev, params.icm, currWB);
+ imgsrc->convertColorSpace (orig_prev, params.icm, currWB);
ipf.firstAnalysis (orig_prev, params, vhist16);
}
@@ -372,42 +448,45 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
// Remove transformation if unneeded
bool needstransform = ipf.needsTransform();
- if (!needstransform && !((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) && orig_prev != oprevi) {
+ if (!needstransform && ! ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) && orig_prev != oprevi) {
delete oprevi;
oprevi = orig_prev;
}
if ((needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled)) ) {
- if(!oprevi || oprevi == orig_prev)
+ if (!oprevi || oprevi == orig_prev) {
oprevi = new Imagefloat (pW, pH);
+ }
+
if (needstransform)
ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh, imgsrc->getMetaData()->getFocalLen(),
imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false);
- else
- orig_prev->copyData(oprevi);
+ else {
+ orig_prev->copyData (oprevi);
+ }
}
if ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) {
const int W = oprevi->getWidth();
const int H = oprevi->getHeight();
- LabImage labcbdl(W, H);
- ipf.rgb2lab(*oprevi, labcbdl, params.icm.working);
+ LabImage labcbdl (W, H);
+ ipf.rgb2lab (*oprevi, labcbdl, params.icm.working);
ipf.dirpyrequalizer (&labcbdl, scale);
- ipf.lab2rgb(labcbdl, *oprevi, params.icm.working);
+ ipf.lab2rgb (labcbdl, *oprevi, params.icm.working);
}
readyphase++;
progress ("Preparing shadow/highlight map...", 100 * readyphase / numofphases);
if ((todo & M_BLURMAP) && params.sh.enabled) {
- double radius = sqrt (double(pW * pW + pH * pH)) / 2.0;
+ double radius = sqrt (double (pW * pW + pH * pH)) / 2.0;
double shradius = params.sh.radius;
if (!params.sh.hq) {
shradius *= radius / 1800.0;
}
- if(!shmap) {
+ if (!shmap) {
shmap = new SHMap (pW, pH, true);
}
@@ -451,7 +530,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
opautili = false;
- if(params.colorToning.enabled) {
+ if (params.colorToning.enabled) {
TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working);
double wp[3][3] = {
{wprof[0][0], wprof[0][1], wprof[0][2]},
@@ -464,34 +543,34 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
{wiprof[1][0], wiprof[1][1], wiprof[1][2]},
{wiprof[2][0], wiprof[2][1], wiprof[2][2]}
};
- params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili);
- CurveFactory::curveToning(params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16);
- CurveFactory::curveToning(params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16);
+ params.colorToning.getCurves (ctColorCurve, ctOpacityCurve, wp, wip, opautili);
+ CurveFactory::curveToning (params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16);
+ CurveFactory::curveToning (params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16);
}
- if(params.blackwhite.enabled) {
+ if (params.blackwhite.enabled) {
CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, vhist16bw, histToneCurveBW, beforeToneCurveBW, afterToneCurveBW, 1);
}
- colourToningSatLimit = float(params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f;
- colourToningSatLimitOpacity = 1.f - (float(params.colorToning.saturatedOpacity) / 100.f);
+ colourToningSatLimit = float (params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f;
+ colourToningSatLimitOpacity = 1.f - (float (params.colorToning.saturatedOpacity) / 100.f);
int satTH = 80;
int satPR = 30;
int indi = 0;
- if(params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings
+ if (params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings
float moyS = 0.f;
float eqty = 0.f;
ipf.moyeqt (oprevi, moyS, eqty);//return image : mean saturation and standard dev of saturation
//printf("moy=%f ET=%f\n", moyS,eqty);
float satp = ((moyS + 1.5f * eqty) - 0.3f) / 0.7f; //1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale
- if(satp >= 0.92f) {
+ if (satp >= 0.92f) {
satp = 0.92f; //avoid values too high (out of gamut)
}
- if(satp <= 0.15f) {
+ if (satp <= 0.15f) {
satp = 0.15f; //avoid too low values
}
@@ -504,22 +583,22 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
satPR = (int) 100.f * (moyS - 0.85f * eqty);
}
- if(actListener) {
+ if (actListener) {
//if(params.blackwhite.enabled) {actListener->autoColorTonChanged(0, satTH, satPR);}
- if(params.blackwhite.enabled && params.colorToning.autosat) {
- actListener->autoColorTonChanged(0, satTH, satPR); //hide sliders only if autosat
+ if (params.blackwhite.enabled && params.colorToning.autosat) {
+ actListener->autoColorTonChanged (0, satTH, satPR); //hide sliders only if autosat
indi = 0;
} else {
- if(params.colorToning.autosat) {
+ if (params.colorToning.autosat) {
if (params.colorToning.method == "Lab") {
indi = 1;
- } else if(params.colorToning.method == "RGBCurves") {
+ } else if (params.colorToning.method == "RGBCurves") {
indi = 1;
- } else if(params.colorToning.method == "RGBSliders") {
+ } else if (params.colorToning.method == "RGBSliders") {
indi = 1;
- } else if(params.colorToning.method == "Splico") {
+ } else if (params.colorToning.method == "Splico") {
indi = 2;
- } else if(params.colorToning.method == "Splitlr") {
+ } else if (params.colorToning.method == "Splitlr") {
indi = 2;
}
@@ -536,46 +615,48 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
double bbm = 33.;
DCPProfile::ApplyState as;
- DCPProfile *dcpProf = imgsrc->getDCP(params.icm, currWB, as);
+ DCPProfile *dcpProf = imgsrc->getDCP (params.icm, currWB, as);
ipf.rgbProc (oprevi, oprevl, nullptr, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation,
rCurve, gCurve, bCurve, colourToningSatLimit , colourToningSatLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, beforeToneCurveBW, afterToneCurveBW, rrm, ggm, bbm, bwAutoR, bwAutoG, bwAutoB, params.toneCurve.expcomp, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, dcpProf, as, histToneCurve);
- if(params.blackwhite.enabled && params.blackwhite.autoc && abwListener) {
+ if (params.blackwhite.enabled && params.blackwhite.autoc && abwListener) {
if (settings->verbose) {
- printf("ImProcCoordinator / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", bwAutoR, bwAutoG, bwAutoB);
+ printf ("ImProcCoordinator / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", bwAutoR, bwAutoG, bwAutoB);
}
- abwListener->BWChanged((float) rrm, (float) ggm, (float) bbm);
+ abwListener->BWChanged ((float) rrm, (float) ggm, (float) bbm);
}
- if(params.colorToning.autosat && actListener) {
+ if (params.colorToning.autosat && actListener) {
if (settings->verbose) {
- printf("ImProcCoordinator / Auto CT: indi=%d satH=%d satPR=%d\n", indi, (int)colourToningSatLimit , (int) colourToningSatLimitOpacity);
+ printf ("ImProcCoordinator / Auto CT: indi=%d satH=%d satPR=%d\n", indi, (int)colourToningSatLimit , (int) colourToningSatLimitOpacity);
}
- actListener->autoColorTonChanged(indi, (int) colourToningSatLimit, (int)colourToningSatLimitOpacity);//change sliders autosat
+ actListener->autoColorTonChanged (indi, (int) colourToningSatLimit, (int)colourToningSatLimitOpacity); //change sliders autosat
}
// correct GUI black and white with value
}
+ // ipf.Lab_Tile(oprevl, oprevl, scale);
+
// compute L channel histogram
int x1, y1, x2, y2;
- params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2);
+ params.crop.mapToResized (pW, pH, scale, x1, x2, y1, y2);
}
readyphase++;
+ LUTu lhist16 (32768);
if (todo & (M_LUMACURVE | M_CROP)) {
- LUTu lhist16(32768);
lhist16.clear();
#ifdef _OPENMP
- const int numThreads = min(max(pW * pH / (int)lhist16.getSize(), 1), omp_get_max_threads());
+ const int numThreads = min (max (pW * pH / (int)lhist16.getSize(), 1), omp_get_max_threads());
#pragma omp parallel num_threads(numThreads) if(numThreads>1)
#endif
{
- LUTu lhist16thr(lhist16.getSize());
+ LUTu lhist16thr (lhist16.getSize());
lhist16thr.clear();
#ifdef _OPENMP
#pragma omp for nowait
@@ -583,7 +664,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
for (int x = 0; x < pH; x++)
for (int y = 0; y < pW; y++) {
- int pos = (int)(oprevl->L[x][y]);
+ int pos = (int) (oprevl->L[x][y]);
lhist16thr[pos]++;
}
@@ -597,24 +678,1592 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
if (todo & M_LUMACURVE) {
- CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, scale == 1 ? 1 : 16);
+ CurveFactory::curveCL (clcutili, params.labCurve.clcurve, clcurve, scale == 1 ? 1 : 16);
CurveFactory::complexsgnCurve (autili, butili, ccutili, cclutili, params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve,
params.labCurve.lccurve, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, scale == 1 ? 1 : 16);
}
+ //scale = 1;
if (todo & (M_LUMINANCE + M_COLOR) ) {
- nprevl->CopyFrom(oprevl);
-
+ nprevl->CopyFrom (oprevl);
+ int maxspot = settings->nspot + 1;
progress ("Applying Color Boost...", 100 * readyphase / numofphases);
- // ipf.MSR(nprevl, nprevl->W, nprevl->H, 1);
+
+
+ if (params.locallab.enabled) {
+ /*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ * 2017 Jacques Desmis
+ */
+
+
+ // Glib::ustring datalab = imgsrc->getFileName() + ".mip";
+ // printf("mip file=%s \n", datalab.c_str());
+ Glib::ustring pop = options.getUserProfilePath() + "/";
+ Glib::ustring datal;
+
+ if (options.mip == MI_opt) {
+ datal = pop + Glib::path_get_basename (imgsrc->getFileName () + ".mip");
+ }
+
+ if (options.mip == MI_prev) {
+ datal = imgsrc->getFileName() + ".mip";
+ }
+
+ /*
+ //test to see if wofstream and wifstream works with NON ASCII, but it's bad
+ wofstream test(datal, ios::out);
+ if(test.fail()) printf("ca va pas\n");
+ else ("ca va bien\n");
+ test.close();
+ */
+ ifstream fic0 (datal, ios::in);
+
+ printf ("mip files in=%s\n", datal.c_str());
+ // if(! fic0.fail()) {
+ float **shbuffer;
+ versionmip = 0;
+ int maxdat;
+ int sca = 1;
+ //string delim ==> delimiter to separate integer in a string, 70 is lagely enough for curves : noramlly 3 to 21 must be suffisant
+ std::string delim[69] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
+ "&", "#", "{", "[", "]", "}", "$", "*", "?", ">", "!", ";", "<", "(", ")", "+", "-"
+ };
+
+
+
+ if (fic0) {
+ //find current version mip
+ std::string line;
+ std::string spotline;
+ int cont = 0;
+
+ while (getline (fic0, line)) {
+ spotline = line;
+ std::size_t pos = spotline.find ("=");
+ std::size_t posend = spotline.find ("@"); //in case of for futur use
+
+ if (spotline.substr (0, pos) == "Mipversion") {
+ std::string strversion = spotline.substr (pos + 1, (posend - pos));
+ versionmip = std::stoi (strversion.c_str());
+ }
+
+ if (spotline.substr (0, pos) == "Spot") {
+ // string str2 = spotline.substr (pos + 1, (posend - pos));
+ cont = 0;
+ }
+
+
+ }
+
+ fic0.close();
+ }
+
+ printf ("mipvers=%i\n", versionmip);
+ ifstream fic (datal, ios::in);
+ bool reinit = false;
+
+ //printf("versionmip=%i nbspot=%i\n", versionmip, params.locallab.nbspot) ;
+
+
+ if (fic.fail() || versionmip == 0 || params.locallab.nbspot == 0) { //initialize mip with default values if no file or old file to prevent crash
+
+ ofstream fic (datal, ios::out | ios::trunc); // ouverture en écriture avec effacement du fichier ouvert
+
+ if (params.locallab.nbspot == 0) {
+ params.locallab.nbspot = 1;
+ }
+
+
+ if (fic)
+
+ {
+ for (int sp = 1; sp < maxspot; sp++) { // spots default
+ int t_sp = sp;
+ int t_mipversion = 10005;//new value for tone mapping
+ int t_circrad = 18;
+ int t_locX = 250;
+ int t_locY = 250;
+ int t_locYT = 250;
+ int t_locXL = 250;
+ int t_centerX = 0;
+ int t_centerY = 0;
+ int t_lightness = 0;
+ int t_contrast = 0;
+ int t_chroma = 0;
+ int t_sensi = 19;
+ int t_transit = 60;
+ int t_invers = 0;
+ int t_Smeth = 0;
+ int t_currentspot = 1;
+ int t_radius = 0;
+ int t_strength = 0;
+ int t_sensibn = 60;
+ int t_inversrad = 0;
+ int t_str = 0;
+ int t_chrrt = 0;
+ int t_neigh = 50;
+ int t_vart = 200;
+ int t_sensih = 19;
+ int t_inversret = 0;
+ int t_retinexMethod = 2;
+ int t_sharradius = 40;
+ int t_sharamount = 75;
+ int t_shardamping = 75;
+ int t_shariter = 30;
+ int t_sensisha = 19;
+ int t_inverssha = 0;
+ int t_qualityMethod = 0;
+ int t_thres = 50;
+ int t_proxi = 2;
+ int t_noiselumf = 0;
+ int t_noiselumc = 0;
+ int t_noisechrof = 0;
+ int t_noisechroc = 0;
+ int t_mult0 = 100;
+ int t_mult1 = 100;
+ int t_mult2 = 100;
+ int t_mult3 = 100;
+ int t_mult4 = 100;
+ int t_threshold = 20;
+ int t_sensicb = 19;
+ int t_activlum = 0;
+ // end versionmip = 10000
+
+ //begin versionmip = 10001 Tone mapping
+ int t_stren = 0;
+ int t_gamma = 100;
+ int t_estop = 140;
+ int t_scaltm = 3;
+ int t_rewei = 0;
+ int t_sensitm = 40;
+
+ //versionmip = 10002 Reticurv
+ int t_retrab = 500;
+
+ std::string t_curvret = "1000A0B120C350D350E700F500G350H350I1000J120K350L350M";//12 points
+ //10003
+ //std::string t_curvll = "0A";
+ std::string t_curvll = "3000A0B0C1000D1000E"; //"3000A0B0C499D501E1000F1000G";// "3000A0B0C1000D1000E";//with that it works !
+
+ //versionmip = 10004 LHcurv
+ std::string t_curvlh = "1000A0B500C350D350E166F500G350H350I333J500K350L350M500N500O350P350Q666R500S350T350U833V500W350X350Y";
+ //10005
+ int t_curvactiv = 0;
+
+ //all variables except locRETgainCurve 'coomon for all)
+ fic << "Mipversion=" << t_mipversion << '@' << endl;
+ fic << "Spot=" << t_sp << '@' << endl;
+ fic << "Circrad=" << t_circrad << '@' << endl;
+ fic << "LocX=" << t_locX << '@' << endl;
+ fic << "LocY=" << t_locY << '@' << endl;
+ fic << "LocYT=" << t_locYT << '@' << endl;
+ fic << "LocXL=" << t_locXL << '@' << endl ;
+ fic << "CenterX=" << t_centerX << '@' << endl;
+ fic << "CenterY=" << t_centerY << '@' << endl;
+ fic << "Lightness=" << t_lightness << '@' << endl;
+ fic << "Contrast=" << t_contrast << '@' << endl;
+ fic << "Chroma=" << t_chroma << '@' << endl;
+ fic << "Sensi=" << t_sensi << '@' << endl;
+ fic << "Transit=" << t_transit << '@' << endl;
+ fic << "Invers=" << t_invers << '@' << endl;
+ fic << "Smethod=" << t_Smeth << '@' << endl;
+ fic << "Currentspot=" << t_currentspot << '@' << endl;
+ fic << "Radius=" << t_radius << '@' << endl;
+ fic << "Strength=" << t_strength << '@' << endl;
+ fic << "Sensibn=" << t_sensibn << '@' << endl;
+ fic << "Inversrad=" << t_inversrad << '@' << endl;
+ fic << "Str=" << t_str << '@' << endl;
+ fic << "Chroma=" << t_chrrt << '@' << endl;
+ fic << "Neigh=" << t_neigh << '@' << endl;
+ fic << "Vart=" << t_vart << '@' << endl;
+ fic << "Sensih=" << t_sensih << '@' << endl;
+ fic << "Inversret=" << t_inversret << '@' << endl;
+ fic << "retinexMethod=" << t_retinexMethod << '@' << endl;
+ fic << "Sharradius=" << t_sharradius << '@' << endl;
+ fic << "Sharamount=" << t_sharamount << '@' << endl;
+ fic << "Shardamping=" << t_shardamping << '@' << endl;
+ fic << "Shariter=" << t_shariter << '@' << endl;
+ fic << "Sensisha=" << t_sensisha << '@' << endl;
+ fic << "Inverssha=" << t_inverssha << '@' << endl;
+ fic << "qualityMethod=" << t_qualityMethod << '@' << endl;
+ fic << "Thres=" << t_thres << '@' << endl;
+ fic << "Proxi=" << t_proxi << '@' << endl;
+ fic << "Noiselumf=" << t_noiselumf << '@' << endl;
+ fic << "Noiselumc=" << t_noiselumc << '@' << endl;
+ fic << "Noisechrof=" << t_noisechrof << '@' << endl;
+ fic << "Noisechroc=" << t_noisechroc << '@' << endl;
+ fic << "Mult0=" << t_mult0 << '@' << endl;
+ fic << "Mult1=" << t_mult1 << '@' << endl;
+ fic << "Mult2=" << t_mult2 << '@' << endl;
+ fic << "Mult3=" << t_mult3 << '@' << endl;
+ fic << "Mult4=" << t_mult4 << '@' << endl;
+ fic << "Threshold=" << t_threshold << '@' << endl;
+ fic << "Sensicb=" << t_sensicb << '@' << endl;
+ fic << "Activblurlum=" << t_activlum << '@' << endl;
+
+ fic << "Stren=" << t_stren << '@' << endl;
+ fic << "Gamma=" << t_gamma << '@' << endl;
+ fic << "Estop=" << t_estop << '@' << endl;
+ fic << "Scaltm=" << t_scaltm << '@' << endl;
+ fic << "Rewei=" << t_rewei << '@' << endl;
+ fic << "Sensitm=" << t_sensitm << '@' << endl;
+
+ fic << "Retrab=" << t_retrab << '@' << endl;
+ fic << "Curvactiv=" << t_curvactiv << '@' << endl;
+
+ fic << "curveReti=" << t_curvret << '@' << endl;
+ fic << "curveLL=" << t_curvll << '@' << endl;
+ fic << "curveLH=" << t_curvlh << '@' << endl;
+
+ fic << endl;
+ }
+
+ fic.close();
+
+ } else
+
+ {
+ cerr << "can't open file !" << endl;
+ }
+
+ }
+
+
+
+ int realspot = params.locallab.nbspot;
+ std::string inser;
+ dataspot = new int*[60];
+
+ for (int i = 0; i < 60; i++) {
+ dataspot[i] = new int[maxspot];
+ }
+
+ retistr = new std::string[maxspot];
+ llstr = new std::string[maxspot];
+ lhstr = new std::string[maxspot];
+
+
+ {
+ sps[0] = 0;
+ dataspot[2][0] = circrads[0] = params.locallab.circrad;
+ dataspot[3][0] = locx[0] = params.locallab.locX;
+ dataspot[4][0] = locy[0] = params.locallab.locY;
+ dataspot[5][0] = locyt[0] = params.locallab.locYT;
+ dataspot[6][0] = locxl[0] = params.locallab.locXL;
+ dataspot[7][0] = centerx[0] = params.locallab.centerX;
+ dataspot[8][0] = centery[0] = params.locallab.centerY;
+ dataspot[9][0] = lights[0] = params.locallab.lightness;
+ dataspot[10][0] = contrs[0] = params.locallab.contrast;
+ dataspot[11][0] = chroms[0] = params.locallab.chroma;
+ dataspot[12][0] = sensis[0] = params.locallab.sensi;
+ dataspot[13][0] = transits[0] = params. locallab.transit;
+
+ if (!params.locallab.invers) {
+ dataspot[14][0] = inverss[0] = 0;
+ } else {
+ dataspot[14][0] = inverss[0] = 1;
+ }
+
+ if (params.locallab.Smethod == "IND") {
+ dataspot[15][0] = smeths[0] = 0;
+ } else if (params.locallab.Smethod == "SYM") {
+ dataspot[15][0] = smeths[0] = 1;
+ } else if (params.locallab.Smethod == "INDSL") {
+ dataspot[15][0] = smeths[0] = 2;
+ } else if (params.locallab.Smethod == "SYMSL") {
+ dataspot[15][0] = smeths[0] = 3;
+ }
+
+ dataspot[16][0] = curens[0] = params.locallab.nbspot;
+ dataspot[17][0] = radiuss[0] = params.locallab.radius;
+ dataspot[18][0] = strengths[0] = params.locallab.strength;
+ dataspot[19][0] = sensibns[0] = params.locallab.sensibn;
+
+
+ if (!params.locallab.inversrad) {
+ dataspot[20][0] = inversrads[0] = 0;
+ } else {
+ dataspot[20][0] = inversrads[0] = 1;
+ }
+
+ dataspot[21][0] = strs[0] = params.locallab.str;
+ dataspot[22][0] = chrrts[0] = params.locallab.chrrt;
+ dataspot[23][0] = neighs[0] = params.locallab.neigh;
+ dataspot[24][0] = varts[0] = params.locallab.vart;
+ dataspot[25][0] = sensihs[0] = params.locallab.sensih;
+
+ if (!params.locallab.inversret) {
+ dataspot[26][0] = inversrets[0] = 0;
+ } else {
+ dataspot[26][0] = inversrets[0] = 1;
+ }
+
+ if (params.locallab.retinexMethod == "low") {
+ dataspot[27][0] = retinexs[0] = 0;
+ } else if (params.locallab.retinexMethod == "uni") {
+ dataspot[27][0] = retinexs[0] = 1;
+ } else if (params.locallab.retinexMethod == "high") {
+ dataspot[27][0] = retinexs[0] = 2;
+ }
+
+ dataspot[28][0] = sharradiuss[0] = params.locallab.sharradius;
+ dataspot[29][0] = sharamounts[0] = params.locallab.sharamount;
+ dataspot[30][0] = shardampings[0] = params.locallab.shardamping;
+ dataspot[31][0] = shariters[0] = params.locallab.shariter;
+ dataspot[32][0] = sensishas[0] = params.locallab.sensisha;
+
+ if (!params.locallab.inverssha) {
+ dataspot[33][0] = inversshas[0] = 0;
+ } else {
+ dataspot[33][0] = inversshas[0] = 1;
+ }
+
+ if (params.locallab.qualityMethod == "std") {
+ dataspot[34][0] = qualitys[0] = 0;
+ } else if (params.locallab.qualityMethod == "enh") {
+ dataspot[34][0] = qualitys[0] = 1;
+ } else if (params.locallab.qualityMethod == "enhden") {
+ dataspot[34][0] = qualitys[0] = 2;
+ }
+
+ dataspot[35][0] = thress[0] = params.locallab.thres;
+ dataspot[36][0] = proxis[0] = params.locallab.proxi;
+ dataspot[37][0] = noiselumfs[0] = params.locallab.noiselumf;
+ dataspot[38][0] = noiselumcs[0] = params.locallab.noiselumc;
+ dataspot[39][0] = noisechrofs[0] = params.locallab.noisechrof;
+ dataspot[40][0] = noisechrocs[0] = params.locallab.noisechroc;
+
+ dataspot[41][0] = mult0s[0] = params.locallab.mult[0];
+ dataspot[42][0] = mult1s[0] = params.locallab.mult[1];
+ dataspot[43][0] = mult2s[0] = params.locallab.mult[2];
+ dataspot[44][0] = mult3s[0] = params.locallab.mult[3];
+ dataspot[45][0] = mult4s[0] = params.locallab.mult[4];
+ dataspot[46][0] = thresholds[0] = params.locallab.threshold;
+ dataspot[47][0] = sensicbs[0] = params.locallab.sensicb;
+
+ if (!params.locallab.activlum) {
+ dataspot[48][0] = activlums[0] = 0;
+ } else {
+ dataspot[48][0] = activlums[0] = 1;
+ }
+
+ dataspot[49][0] = strens[0] = params.locallab.stren;
+ dataspot[50][0] = gammas[0] = params.locallab.gamma;
+ dataspot[51][0] = estops[0] = params.locallab.estop;
+ dataspot[52][0] = scaltms[0] = params.locallab.scaltm;
+ dataspot[53][0] = reweis[0] = params.locallab.rewei;
+ dataspot[54][0] = sensitms[0] = params.locallab.sensitm;
+ dataspot[55][0] = retrabs[0] = params.locallab.retrab;
+
+ if (!params.locallab.curvactiv) {
+ dataspot[56][0] = curvactivs[0] = 0;
+ } else {
+ dataspot[56][0] = curvactivs[0] = 1;
+ }
+
+ //curve Reti local
+ int siz = params.locallab.localTgaincurve.size();
+
+ if (siz > 69) {
+ siz = 69; //to avoid crash
+ }
+
+ int s_cur[siz + 1];
+ int s_datcur[siz + 1];
+
+ for (int j = 0; j < siz; j++) {
+ s_datcur[j] = reticurvs[0 + j] = (int) (1000. * params.locallab.localTgaincurve[j]);
+ }
+
+ std::string cur_str = "";
+
+ for (int j = 0; j < siz; j++) {
+ cur_str = cur_str + std::to_string (s_datcur[j]) + delim[j];
+ }
+
+ inser = retistr[0] = cur_str + "@";
+ //end retistr
+
+ //curve local L Lum
+ int sizl = params.locallab.llcurve.size();
+
+ if (sizl > 69) {
+ sizl = 69;//to avoid crash
+ }
+
+ int s_curl[sizl + 1];
+ int s_datcurl[sizl + 1];
+
+ for (int j = 0; j < sizl; j++) {
+ s_datcurl[j] = llcurvs[0 + j] = (int) (1000. * params.locallab.llcurve[j]);
+ }
+
+ std::string ll_str = "";
+
+ for (int j = 0; j < sizl; j++) {
+ ll_str = ll_str + std::to_string (s_datcurl[j]) + delim[j];
+ }
+
+ llstr[0] = ll_str + "@";
+ //end local L f(L)
+
+ //curve local L f(H)
+ int sizh = params.locallab.LHcurve.size();
+
+ if (sizh > 69) {
+ sizh = 69;//to avoid crash
+ }
+
+ int s_curh[sizh + 1];
+ int s_datcurh[sizh + 1];
+
+ for (int j = 0; j < sizh; j++) {
+ s_datcurh[j] = lhcurvs[0 + j] = (int) (1000. * params.locallab.LHcurve[j]);
+ }
+
+ std::string lh_str = "";
+
+ for (int j = 0; j < sizh; j++) {
+ lh_str = lh_str + std::to_string (s_datcurh[j]) + delim[j];
+ }
+
+ lhstr[0] = lh_str + "@";
+ //end local L = f(H)
+
+
+
+
+ if (params.locallab.anbspot == 0) {
+ //update GUI and MIP after current spot ==> params, shift with the other alolistener
+ if (aloListener && params.locallab.anbspot == 0) {
+ aloListener->localretChanged (dataspot, retistr[0], llstr[0], lhstr[0], 0, 1);
+ }
+ }
+
+ locallutili = false;
+
+ }
+
+
+
+ //end save
+
+
+ int ns;
+ int realsp = params.locallab.nbspot;
+ bool excurvret = true;
+ bool excurvll = true;
+ bool excurvlh = true;
+
+ ifstream fich (datal, ios::in);
+
+ if (fich) {//may be a file with versionmip = 10000
+ // if(versionmip == 10000) add new blank fields for tone-mapping because TM is 10001
+ //we must add new fields at the good place
+ std::string line;
+ std::string spotline;
+ int cont = 0;
+ int maxind = 57;
+
+ if (versionmip == 10000) {
+ maxind = 49;
+ excurvret = false;
+ excurvll = false;
+ excurvlh = false;
+ }
+
+ if (versionmip == 10001) {
+ maxind = 55;
+ excurvret = false;
+ excurvll = false;
+ excurvlh = false;
+
+ }
+
+ if (versionmip == 10004) {
+ maxind = 56;
+ }
+
+ int sizecu;
+ int sizell;
+ int sizelh;
+
+ while (getline (fich, line)) {
+ spotline = line;
+ std::size_t pos = spotline.find ("=");
+ std::size_t posend = spotline.find ("@"); //in case of for futur use
+
+ if (spotline.substr (0, pos) == "Mipversion") {
+ std::string strversion = spotline.substr (pos + 1, (posend - pos));
+ versionmip = std::stoi (strversion.c_str());
+ }
+
+ if (spotline.substr (0, pos) == "Spot") {
+ cont = 0;
+ }
+
+ cont++;
+ std::string str3 = spotline.substr (pos + 1, (posend - pos));
+
+ if (cont == 1) {
+ ns = std::stoi (str3.c_str());
+ }
+
+ if (cont >= 2 && cont < 16) {
+ dataspot[cont][ns] = std::stoi (str3.c_str());
+
+ }
+
+ if (spotline.substr (0, pos) == "Currentspot") {
+ dataspot[16][0] = std::stoi (str3.c_str());
+ }
+
+ if (cont > 16 && cont < maxind) {
+ dataspot[cont][ns] = std::stoi (str3.c_str());
+
+ }
+
+
+ if (excurvret && spotline.substr (0, pos) == "curveReti") {
+ std::string curstr;
+ int longecur;
+ std::string strend = spotline.substr (posend - 1, 1);
+ std::size_t posz = spotline.find (strend);
+ int longe;
+
+ for (int sl = 0; sl < 69; sl++) {
+ if (delim[sl] == strend) {
+ longe = sl + 1;
+ }
+ }
+
+ retistr[ns] = str3;
+ sizecu = longe;
+
+ // printf("lecture str=%s ns=%i si=%i\n", retistr[ns].c_str(), ns, sizecu);
+ }
+
+ if (excurvll && spotline.substr (0, pos) == "curveLL") {
+ std::string curstrl;
+ int longecurl;
+ std::string strendl = spotline.substr (posend - 1, 1);
+ std::size_t poszl = spotline.find (strendl);
+ int longel;
+
+ for (int sl = 0; sl < 69; sl++) {
+ if (delim[sl] == strendl) {
+ longel = sl + 1;
+ }
+ }
+
+ llstr[ns] = str3;
+ sizell = longel;
+ // printf("lecture strLL=%s ns=%i si=%i\n", llstr[ns].c_str(), ns, sizell);
+ }
+
+ if (excurvlh && spotline.substr (0, pos) == "curveLH") {
+ std::string curstrh;
+ int longecurh;
+ std::string strendh = spotline.substr (posend - 1, 1);
+ std::size_t poszh = spotline.find (strendh);
+ int longeh;
+
+ for (int sh = 0; sh < 69; sh++) {
+ if (delim[sh] == strendh) {
+ longeh = sh + 1;
+ }
+ }
+
+ lhstr[ns] = str3;
+ sizelh = longeh;
+ //printf("lecture strLH=%s ns=%i si=%i\n", lhstr[ns].c_str(), ns, sizelh);
+ }
+
+
+ }
+
+ fich.close();
+ }
+
+
+
+ //new fields for TM
+ if (versionmip == 10000) {
+ for (int sp = 1; sp < maxspot; sp++) { // spots default
+ dataspot[49][sp] = 0; //stren
+ dataspot[50][sp] = 100; //gamma
+ dataspot[51][sp] = 140; //estop
+ dataspot[52][sp] = 3; //scaltm
+ dataspot[53][sp] = 0; //rewei
+ dataspot[54][sp] = 40; //sensitm
+
+ }
+ }
+
+ if (versionmip == 10001) {
+
+ for (int sp = 1; sp < maxspot; sp++) { // spots default
+ dataspot[55][sp] = 500; //retrab
+ std::string cur_str = "1000A0B120C350D350E700F500G350H350I1000J120K350L350M";//12 points
+ retistr[sp] = cur_str + "@";
+ }
+ }
+
+ if (versionmip == 10002) {
+
+ for (int sp = 1; sp < maxspot; sp++) { // spots default
+ std::string ll_str = "3000A0B0C1000D1000E"; //"3000A0B0C499D501E1000F1000G"; //"3000A0B0C1000D1000E"; //"3000A0B0C200D200E800F800G1000H1000I";//"0A"
+ llstr[sp] = ll_str + "@";
+ }
+ }
+
+ if (versionmip == 10003) {
+
+ for (int sp = 1; sp < maxspot; sp++) { // spots default
+ std::string lh_str = "1000A0B500C350D350E166F500G350H350I333J500K350L350M500N500O350P350Q666R500S350T350U833V500W350X350Y";
+ lhstr[sp] = lh_str + "@";
+ }
+ }
+
+ if (versionmip == 10004) {
+
+ for (int sp = 1; sp < maxspot; sp++) { // spots default
+ dataspot[56][sp] = 0; //curvactiv
+ }
+ }
+
+ if (ns < (maxspot - 1)) {
+ ofstream fic (datal, ios::out | ios::app); // ouverture en écriture avec effacement du fichier ouvert
+
+
+ for (int sp = ns + 1 ; sp < maxspot; sp++) { // spots default
+ int t_sp = sp;
+ int t_mipversion = 10005;
+ int t_circrad = 18;
+ int t_locX = 250;
+ int t_locY = 250;
+ int t_locYT = 250;
+ int t_locXL = 250;
+ int t_centerX = 0;
+ int t_centerY = 0;
+ int t_lightness = 0;
+ int t_contrast = 0;
+ int t_chroma = 0;
+ int t_sensi = 19;
+ int t_transit = 60;
+ int t_invers = 0;
+ int t_Smeth = 0;
+ int t_currentspot = 1;
+ int t_radius = 0;
+ int t_strength = 0;
+ int t_sensibn = 60;
+ int t_inversrad = 0;
+ int t_str = 0;
+ int t_chrrt = 0;
+ int t_neigh = 50;
+ int t_vart = 200;
+ int t_sensih = 19;
+ int t_inversret = 0;
+ int t_retinexMethod = 2;
+ int t_sharradius = 40;
+ int t_sharamount = 75;
+ int t_shardamping = 75;
+ int t_shariter = 30;
+ int t_sensisha = 19;
+ int t_inverssha = 0;
+ int t_qualityMethod = 0;
+ int t_thres = 50;
+ int t_proxi = 2;
+ int t_noiselumf = 0;
+ int t_noiselumc = 0;
+ int t_noisechrof = 0;
+ int t_noisechroc = 0;
+ int t_mult0 = 100;
+ int t_mult1 = 100;
+ int t_mult2 = 100;
+ int t_mult3 = 100;
+ int t_mult4 = 100;
+ int t_threshold = 20;
+ int t_sensicb = 19;
+ int t_activlum = 0;
+ //10001 TM
+ int t_stren = 0;
+ int t_gamma = 100;
+ int t_estop = 140;
+ int t_scaltm = 3;
+ int t_rewei = 0;
+ int t_sensitm = 40;
+
+ //10002 curve
+ int t_retrab = 500;
+
+ std::string t_curvret = "1000A0B120C350D350E700F500G350H350I1000J120K350L350M";//12 points
+ //10003
+ std::string t_curvll = "3000A0B0C1000D1000E"; //"3000A0B0C499D501E1000F1000G"; //"3000A0B0C1000D1000E";//0 points with marks
+ //10004
+ std::string t_curvlh = "1000A0B500C350D350E166F500G350H350I333J500K350L350M500N500O350P350Q666R500S350T350U833V500W350X350Y";
+ //10005
+ int t_curvactiv = 0;
+
+ fic << "Mipversion=" << t_mipversion << '@' << endl;
+ fic << "Spot=" << t_sp << '@' << endl;
+ fic << "Circrad=" << t_circrad << '@' << endl;
+ fic << "LocX=" << t_locX << '@' << endl;
+ fic << "LocY=" << t_locY << '@' << endl;
+ fic << "LocYT=" << t_locYT << '@' << endl;
+ fic << "LocXL=" << t_locXL << '@' << endl ;
+ fic << "CenterX=" << t_centerX << '@' << endl;
+ fic << "CenterY=" << t_centerY << '@' << endl;
+ fic << "Lightness=" << t_lightness << '@' << endl;
+ fic << "Contrast=" << t_contrast << '@' << endl;
+ fic << "Chroma=" << t_chroma << '@' << endl;
+ fic << "Sensi=" << t_sensi << '@' << endl;
+ fic << "Transit=" << t_transit << '@' << endl;
+ fic << "Invers=" << t_invers << '@' << endl;
+ fic << "Smethod=" << t_Smeth << '@' << endl;
+ fic << "Currentspot=" << t_currentspot << '@' << endl;
+ fic << "Radius=" << t_radius << '@' << endl;
+ fic << "Strength=" << t_strength << '@' << endl;
+ fic << "Sensibn=" << t_sensibn << '@' << endl;
+ fic << "Inversrad=" << t_inversrad << '@' << endl;
+ fic << "Str=" << t_str << '@' << endl;
+ fic << "Chroma=" << t_chrrt << '@' << endl;
+ fic << "Neigh=" << t_neigh << '@' << endl;
+ fic << "Vart=" << t_vart << '@' << endl;
+ fic << "Sensih=" << t_sensih << '@' << endl;
+ fic << "Inversret=" << t_inversret << '@' << endl;
+ fic << "retinexMethod=" << t_retinexMethod << '@' << endl;
+ fic << "Sharradius=" << t_sharradius << '@' << endl;
+ fic << "Sharamount=" << t_sharamount << '@' << endl;
+ fic << "Shardamping=" << t_shardamping << '@' << endl;
+ fic << "Shariter=" << t_shariter << '@' << endl;
+ fic << "Sensisha=" << t_sensisha << '@' << endl;
+ fic << "Inverssha=" << t_inverssha << '@' << endl;
+ fic << "qualityMethod=" << t_qualityMethod << '@' << endl;
+ fic << "Thres=" << t_thres << '@' << endl;
+ fic << "Proxi=" << t_proxi << '@' << endl;
+ fic << "Noiselumf=" << t_noiselumf << '@' << endl;
+ fic << "Noiselumc=" << t_noiselumc << '@' << endl;
+ fic << "Noisechrof=" << t_noisechrof << '@' << endl;
+ fic << "Noisechroc=" << t_noisechroc << '@' << endl;
+ fic << "Mult0=" << t_mult0 << '@' << endl;
+ fic << "Mult1=" << t_mult1 << '@' << endl;
+ fic << "Mult2=" << t_mult2 << '@' << endl;
+ fic << "Mult3=" << t_mult3 << '@' << endl;
+ fic << "Mult4=" << t_mult4 << '@' << endl;
+ fic << "Threshold=" << t_threshold << '@' << endl;
+ fic << "Sensicb=" << t_sensicb << '@' << endl;
+ fic << "Activblurlum=" << t_activlum << '@' << endl;
+
+ fic << "Stren=" << t_stren << '@' << endl;
+ fic << "Gamma=" << t_gamma << '@' << endl;
+ fic << "Estop=" << t_estop << '@' << endl;
+ fic << "Scaltm=" << t_scaltm << '@' << endl;
+ fic << "Rewei=" << t_rewei << '@' << endl;
+ fic << "Sensitm=" << t_sensitm << '@' << endl;
+ fic << "Retrab=" << t_retrab << '@' << endl;
+ fic << "Curvactiv=" << t_curvactiv << '@' << endl;
+
+ fic << "curveReti=" << t_curvret << '@' << endl;
+ fic << "curveLL=" << t_curvll << '@' << endl;
+ fic << "curveLH=" << t_curvlh << '@' << endl;
+
+ fic << endl;
+ }
+
+ fic.close();
+
+
+ ifstream fich2 (datal, ios::in);
+
+ if (fich2) {
+
+ std::string line2;
+ std::string spotline2;
+ int cont2 = 0;
+ int ns2;
+ int maxin = 57;
+ int sizecu2;
+ int sizell2;
+ int sizelh2;
+
+ while (getline (fich2, line2)) {
+ spotline2 = line2;
+ std::size_t pos2 = spotline2.find ("=");
+ std::size_t posend2 = spotline2.find ("@"); //in case of for futur use
+
+ if (spotline2.substr (0, pos2) == "Mipversion") {
+ std::string strversion = spotline2.substr (pos2 + 1, (posend2 - pos2));
+ versionmip = std::stoi (strversion.c_str());
+ }
+
+ if (spotline2.substr (0, pos2) == "Spot") {
+ cont2 = 0;
+ }
+
+ cont2++;
+ std::string str32 = spotline2.substr (pos2 + 1, (posend2 - pos2));
+
+ if (cont2 == 1) {
+ ns2 = std::stoi (str32.c_str());
+ }
+
+ if (cont2 >= 2 && cont2 < 16) {
+ dataspot[cont2][ns2] = std::stoi (str32.c_str());
+
+ }
+
+ if (spotline2.substr (0, pos2) == "Currentspot") {
+ dataspot[16][0] = std::stoi (str32.c_str());
+ }
+
+ if (cont2 > 16 && cont2 < maxin) {
+ dataspot[cont2][ns2] = std::stoi (str32.c_str());
+
+ }
+
+ if (spotline2.substr (0, pos2) == "curveReti") {
+ std::string curstr2;
+ int longecur2;
+ std::string strend2 = spotline2.substr (posend2 - 1, 1);
+ std::size_t posz2 = spotline2.find (strend2);
+ int longe2;
+
+ for (int sl = 0; sl < 69; sl++) {
+ if (delim[sl] == strend2) {
+ longe2 = sl + 1;
+ }
+ }
+
+ retistr[ns] = str32;
+ sizecu2 = longe2;
+
+ }
+
+ if (spotline2.substr (0, pos2) == "curveLL") {
+ std::string curstr2l;
+ int longecur2l;
+ std::string strend2l = spotline2.substr (posend2 - 1, 1);
+ std::size_t posz2l = spotline2.find (strend2l);
+ int longe2l;
+
+ for (int sl = 0; sl < 69; sl++) {
+ if (delim[sl] == strend2l) {
+ longe2l = sl + 1;
+ }
+ }
+
+ llstr[ns] = str32;
+ sizell2 = longe2l;
+
+ }
+
+ if (spotline2.substr (0, pos2) == "curveLH") {
+ std::string curstr2h;
+ int longecur2h;
+ std::string strend2h = spotline2.substr (posend2 - 1, 1);
+ std::size_t posz2h = spotline2.find (strend2h);
+ int longe2h;
+
+ for (int sh = 0; sh < 69; sh++) {
+ if (delim[sh] == strend2h) {
+ longe2h = sh + 1;
+ }
+ }
+
+ lhstr[ns] = str32;
+ sizelh2 = longe2h;
+
+ }
+
+ }
+
+ fich2.close() ;
+
+ }
+
+
+ }
+
+
+
+ for (int sp = 1; sp < maxspot; sp++) { //spots default
+ params.locallab.hueref = INFINITY;
+ params.locallab.chromaref = INFINITY;
+ bool locutili = locutili;
+ params.locallab.lumaref = INFINITY;
+ params.locallab.circrad = circrads[sp] = dataspot[2][sp];
+ params.locallab.locX = locx[sp] = dataspot[3][sp];
+ params.locallab.locY = locy[sp] = dataspot[4][sp];
+ params.locallab.locYT = locyt[sp] = dataspot[5][sp];
+ params.locallab.locXL = locxl[sp] = dataspot[6][sp];
+ params.locallab.centerX = centerx[sp] = dataspot[7][sp];
+ params.locallab.centerY = centery[sp] = dataspot[8][sp];
+ params.locallab.lightness = lights[sp] = dataspot[9][sp];
+ params.locallab.contrast = contrs[sp] = dataspot[10][sp];
+ params.locallab.chroma = chroms[sp] = dataspot[11][sp];
+ params.locallab.sensi = sensis[sp] = dataspot[12][sp];
+ params.locallab.transit = transits[sp] = dataspot[13][sp];
+ sps[sp] = sp;
+
+ if (dataspot[14][sp] == 0) {
+ inverss[sp] = 0;
+ params.locallab.invers = false;
+ } else {
+ inverss[sp] = 1;
+ params.locallab.invers = true;
+ }
+
+ if (dataspot[15][sp] == 0) {
+ smeths[sp] = 0;
+ params.locallab.Smethod = "IND" ;
+ } else if (dataspot[15][sp] == 1) {
+ smeths[sp] = 1;
+ params.locallab.Smethod = "SYM" ;
+ } else if (dataspot[15][sp] == 2) {
+ smeths[sp] = 2;
+ params.locallab.Smethod = "INDSL";
+ } else if (dataspot[15][sp] == 3) {
+ smeths[sp] = 3;
+ params.locallab.Smethod = "SYMSL";
+ }
+
+ radiuss[sp] = dataspot[17][sp];
+ strengths[sp] = dataspot[18][sp];
+ params.locallab.radius = dataspot[17][sp];
+ params.locallab.strength = dataspot[18][sp];
+ params.locallab.sensibn = dataspot[19][sp];
+
+ if (dataspot[20][sp] == 0) {
+ inversrads[sp] = 0;
+ params.locallab.inversrad = false;
+ } else {
+ inversrads[sp] = 1;
+ params.locallab.inversrad = true;
+ }
+
+
+ params.locallab.str = strs[sp] = dataspot[21][sp];
+ params.locallab.chrrt = chrrts[sp] = dataspot[22][sp];
+ params.locallab.neigh = neighs[sp] = dataspot[23][sp];
+ params.locallab.vart = varts[sp] = dataspot[24][sp];
+ params.locallab.sensih = sensihs[sp] = dataspot[25][sp];
+
+ if (dataspot[26][sp] == 0) {
+ inversrets[sp] = 0;
+ params.locallab.inversret = false;
+ } else {
+ inversrets[sp] = 1;
+ params.locallab.inversret = true;
+ }
+
+ if (dataspot[27][sp] == 0) {
+ retinexs[sp] = 0;
+ params.locallab.retinexMethod = "low" ;
+ } else if (dataspot[27][sp] == 1) {
+ retinexs[sp] = 1;
+ params.locallab.retinexMethod = "uni" ;
+ } else if (dataspot[27][sp] == 2) {
+ retinexs[sp] = 2;
+ params.locallab.retinexMethod = "high";
+ }
+
+ sharradiuss[sp] = dataspot[28][sp];
+ params.locallab.sharradius = dataspot[28][sp];
+
+ params.locallab.sharamount = sharamounts[sp] = dataspot[29][sp];
+ params.locallab.shardamping = shardampings[sp] = dataspot[30][sp];
+ params.locallab.shariter = shariters[sp] = dataspot[31][sp];
+ params.locallab.sensisha = sensishas[sp] = dataspot[32][sp];
+
+ if (dataspot[33][sp] == 0) {
+ inversshas[sp] = 0;
+ params.locallab.inverssha = false;
+ } else {
+ inversshas[sp] = 1;
+ params.locallab.inverssha = true;
+ }
+
+ if (dataspot[34][sp] == 0) {
+ qualitys[sp] = 0;
+ params.locallab.qualityMethod = "std" ;
+ } else if (dataspot[34][sp] == 1) {
+ qualitys[sp] = 1;
+ params.locallab.qualityMethod = "enh" ;
+ } else if (dataspot[34][sp] == 2) {
+ qualitys[sp] = 2;
+ params.locallab.qualityMethod = "enhden" ;
+ }
+
+ params.locallab.thres = thress[sp] = dataspot[35][sp];
+ params.locallab.proxi = proxis[sp] = dataspot[36][sp];
+ params.locallab.noiselumf = noiselumfs[sp] = dataspot[37][sp];
+ params.locallab.noiselumc = noiselumcs[sp] = dataspot[38][sp];
+ params.locallab.noisechrof = noisechrofs[sp] = dataspot[39][sp];
+ params.locallab.noisechroc = noisechrocs[sp] = dataspot[40][sp];
+ params.locallab.mult[0] = mult0s[sp] = dataspot[41][sp];
+ params.locallab.mult[1] = mult1s[sp] = dataspot[42][sp];
+ params.locallab.mult[2] = mult2s[sp] = dataspot[43][sp];
+ params.locallab.mult[3] = mult3s[sp] = dataspot[44][sp];
+ params.locallab.mult[4] = mult4s[sp] = dataspot[45][sp];
+ params.locallab.threshold = thresholds[sp] = dataspot[46][sp];
+ params.locallab.sensicb = sensicbs[sp] = dataspot[47][sp];
+
+ if (dataspot[48][sp] == 0) {
+ activlums[sp] = 0;
+ params.locallab.activlum = false;
+ } else {
+ activlums[sp] = 1;
+ params.locallab.activlum = true;
+ }
+
+ params.locallab.stren = strens[sp] = dataspot[49][sp];
+ params.locallab.gamma = gammas[sp] = dataspot[50][sp];
+ params.locallab.estop = estops[sp] = dataspot[51][sp];
+ params.locallab.scaltm = scaltms[sp] = dataspot[52][sp];
+ params.locallab.rewei = reweis[sp] = dataspot[53][sp];
+ params.locallab.sensitm = sensitms[sp] = dataspot[54][sp];
+ params.locallab.retrab = retrabs[sp] = dataspot[55][sp];
+
+ if (dataspot[56][sp] == 0) {
+ curvactivs[sp] = 0;
+ params.locallab.curvactiv = false;
+ } else {
+ curvactivs[sp] = 1;
+ params.locallab.curvactiv = true;
+ }
+
+ int *s_datc;
+ s_datc = new int[70];
+ int siz;
+
+ ipf.strcurv_data (retistr[sp], s_datc, siz);
+
+ sizeretics[sp] = siz;
+
+ std::vector cretiend;
+
+ for (int j = 0; j < siz; j++) {
+ reticurvs[sp * 500 + j] = s_datc[j];
+ cretiend.push_back ((double) (s_datc[j]) / 1000.);
+ }
+
+ delete [] s_datc;
+
+ int *s_datcl;
+ s_datcl = new int[70];
+ int sizl;
+
+ ipf.strcurv_data (llstr[sp], s_datcl, sizl);
+
+ sizellcs[sp] = sizl;
+
+ std::vector cllend;
+
+ for (int j = 0; j < sizl; j++) {
+ llcurvs[sp * 500 + j] = s_datcl[j];
+ cllend.push_back ((double) (s_datcl[j]) / 1000.);
+ }
+
+ delete [] s_datcl;
+
+ int *s_datch;
+ s_datch = new int[70];
+ int sizh;
+
+ ipf.strcurv_data (lhstr[sp], s_datch, sizh);
+
+ sizelhcs[sp] = sizh;
+
+ std::vector clhend;
+
+ for (int j = 0; j < sizh; j++) {
+ lhcurvs[sp * 500 + j] = s_datch[j];
+ clhend.push_back ((double) (s_datch[j]) / 1000.);
+ }
+
+ delete [] s_datch;
+
+ params.locallab.localTgaincurve.clear();
+ params.locallab.localTgaincurve = cretiend;
+
+ int lenc = params.locallab.localTgaincurve.size();
+
+ params.locallab.llcurve.clear();
+ params.locallab.llcurve = cllend;
+
+ params.locallab.LHcurve.clear();
+ params.locallab.LHcurve = clhend;
+
+
+ locallutili = false;
+ params.locallab.getCurves (locRETgainCurve, locRETgainCurverab, loclhCurve);
+ CurveFactory::curveLocal (locallutili, params.locallab.llcurve, lllocalcurve, sca); //scale == 1 ? 1 : 16);
+
+ ipf.Lab_Local (3, sp, (float**)shbuffer, nprevl, nprevl, 0, 0, 0, 0, pW, pH, fw, fh, locutili, scale, locRETgainCurve, locallutili, lllocalcurve, loclhCurve, params.locallab.hueref, params.locallab.chromaref, params.locallab.lumaref);
+ dataspot[57][sp] = huerefs[sp] = 100.f * params.locallab.hueref;
+ dataspot[58][sp] = chromarefs[sp] = params.locallab.chromaref;
+ dataspot[59][sp] = lumarefs[sp] = params.locallab.lumaref;
+ nextParams.locallab.hueref = params.locallab.hueref;
+ nextParams.locallab.chromaref = params.locallab.chromaref;
+ nextParams.locallab.lumaref = params.locallab.lumaref;
+ lllocalcurve.clear();
+
+ }
+
+
+
+ int sp ;
+ sp = realspot;
+
+
+ int maxreal = 1;//do nothing..in case of
+
+ if (aloListener && realspot != dataspot[16][0]) {
+ //update GUI and MIP
+ aloListener->localChanged (dataspot, retistr[sp], llstr[sp], lhstr[sp], sp, maxreal);
+ }
+
+
+ int sis = 1;
+ params.locallab.hueref = INFINITY;
+ params.locallab.chromaref = INFINITY;
+ params.locallab.lumaref = INFINITY;
+ locallutili = false;
+
+ sps[sp] = sp;
+ dataspot[2][sp] = circrads[sp] = params.locallab.circrad = dataspot[2][0];
+ dataspot[3][sp] = locx[sp] = params.locallab.locX = dataspot[3][0];
+ dataspot[4][sp] = locy[sp] = params.locallab.locY = dataspot[4][0];
+ dataspot[5][sp] = locyt[sp] = params.locallab.locYT = dataspot[5][0];
+ dataspot[6][sp] = locxl[sp] = params.locallab.locXL = dataspot[6][0];
+ dataspot[7][sp] = centerx[sp] = params.locallab.centerX = dataspot[7][0];
+ dataspot[8][sp] = centery[sp] = params.locallab.centerY = dataspot[8][0];
+ dataspot[9][sp] = lights[sp] = params.locallab.lightness = dataspot[9][0];
+ dataspot[10][sp] = contrs[sp] = params.locallab.contrast = dataspot[10][0];
+ dataspot[11][sp] = chroms[sp] = params.locallab.chroma = dataspot[11][0];
+ dataspot[12][sp] = sensis[sp] = params.locallab.sensi = dataspot[12][0];
+ dataspot[13][sp] = transits[sp] = params.locallab.transit = dataspot[13][0];
+
+ if (dataspot[14][0] == 0) {
+ params.locallab.invers = false;
+ dataspot[14][sp] = 0;
+ inverss[sp] = 0;
+ } else {
+ params.locallab.invers = true;
+ dataspot[14][sp] = 1;
+ inverss[sp] = 1;
+ }
+
+ if (dataspot[15][0] == 0) {
+ params.locallab.Smethod = "IND" ;
+ smeths[sp] = 0;
+ dataspot[15][sp] = 0;
+ } else if (dataspot[15][0] == 1) {
+ params.locallab.Smethod = "SYM" ;
+ smeths[sp] = 1;
+ dataspot[15][sp] = 1;
+
+ } else if (dataspot[15][0] == 2) {
+ params.locallab.Smethod = "INDSL" ;
+ smeths[sp] = 2;
+ dataspot[15][sp] = 2;
+ } else if (dataspot[15][0] == 3) {
+ params.locallab.Smethod = "SYMSL" ;
+ smeths[sp] = 3;
+ dataspot[15][sp] = 3;
+ }
+
+ params.locallab.radius = dataspot[17][0];
+ params.locallab.strength = dataspot[18][0];
+ params.locallab.sensibn = dataspot[19][0];
+
+ dataspot[17][sp] = radiuss[sp] = params.locallab.radius;
+ dataspot[18][sp] = strengths[sp] = params.locallab.strength;
+ dataspot[19][sp] = sensibns[sp] = params.locallab.sensibn;
+
+ if (dataspot[20][0] == 0) {
+ params.locallab.inversrad = false;
+ dataspot[20][sp] = 0;
+ inversrads[sp] = 0;
+ } else {
+ params.locallab.inversrad = true;
+ dataspot[20][sp] = 1;
+ inversrads[sp] = 1;
+ }
+
+ dataspot[21][sp] = strs[sp] = params.locallab.str = dataspot[21][0];
+ dataspot[22][sp] = chrrts[sp] = params.locallab.chrrt = dataspot[22][0];
+ dataspot[23][sp] = neighs[sp] = params.locallab.neigh = dataspot[23][0];
+ dataspot[24][sp] = varts[sp] = params.locallab.vart = dataspot[24][0];
+ dataspot[25][sp] = sensihs[sp] = params.locallab.sensih = dataspot[25][0];
+
+ if (dataspot[26][0] == 0) {
+ params.locallab.inversret = false;
+ inversrets[sp] = 0;
+ dataspot[26][sp] = 0;
+ } else {
+ params.locallab.inversret = true;
+ inversrets[sp] = 1;
+ dataspot[26][sp] = 1;
+ }
+
+ if (dataspot[27][0] == 0) {
+ params.locallab.retinexMethod = "low" ;
+ retinexs[sp] = 0;
+ dataspot[27][sp] = 0;
+ } else if (dataspot[27][0] == 1) {
+ params.locallab.retinexMethod = "uni" ;
+ retinexs[sp] = 1;
+ dataspot[27][sp] = 1;
+ } else if (dataspot[27][0] == 2) {
+ params.locallab.Smethod = "high" ;
+ retinexs[sp] = 2;
+ dataspot[27][sp] = 2;
+ }
+
+ dataspot[28][sp] = sharradiuss[sp] = params.locallab.sharradius = dataspot[28][0];
+
+ dataspot[29][sp] = sharamounts[sp] = params.locallab.sharamount = dataspot[29][0];
+ dataspot[30][sp] = shardampings[sp] = params.locallab.shardamping = dataspot[30][0];
+ dataspot[31][sp] = shariters[sp] = params.locallab.shariter = dataspot[31][0];
+ dataspot[32][sp] = sensishas[sp] = params.locallab.sensisha = dataspot[32][0];
+
+ if (dataspot[33][0] == 0) {
+ params.locallab.inverssha = 0;
+ inversshas[sp] = 0;
+ dataspot[33][sp] = 0;
+ } else {
+ params.locallab.inverssha = 1;
+ inversshas[sp] = 1;
+ dataspot[33][sp] = 1;
+ }
+
+ if (dataspot[34][0] == 0) {
+ params.locallab.qualityMethod = "std" ;
+ qualitys[sp] = 0;
+ dataspot[34][sp] = 0;
+ } else if (dataspot[34][0] == 1) {
+ params.locallab.qualityMethod = "enh" ;
+ qualitys[sp] = 1;
+ dataspot[34][sp] = 1;
+ } else if (dataspot[34][0] == 2) {
+ params.locallab.qualityMethod = "enhden" ;
+ qualitys[sp] = 2;
+ dataspot[34][sp] = 2;
+ }
+
+ dataspot[35][sp] = thress[sp] = params.locallab.thres = dataspot[35][0];
+ dataspot[36][sp] = proxis[sp] = params.locallab.proxi = dataspot[36][0];
+ dataspot[37][sp] = noiselumfs[sp] = params.locallab.noiselumf = dataspot[37][0];
+ dataspot[38][sp] = noiselumcs[sp] = params.locallab.noiselumc = dataspot[38][0];
+ dataspot[39][sp] = noisechrofs[sp] = params.locallab.noisechrof = dataspot[39][0];
+ dataspot[40][sp] = noisechrocs[sp] = params.locallab.noisechroc = dataspot[40][0];
+ dataspot[41][sp] = mult0s[sp] = params.locallab.mult[0] = dataspot[41][0];
+ dataspot[42][sp] = mult1s[sp] = params.locallab.mult[1] = dataspot[42][0];
+ dataspot[43][sp] = mult2s[sp] = params.locallab.mult[2] = dataspot[43][0];
+ dataspot[44][sp] = mult3s[sp] = params.locallab.mult[3] = dataspot[44][0];
+ dataspot[45][sp] = mult4s[sp] = params.locallab.mult[4] = dataspot[45][0];
+ dataspot[46][sp] = thresholds[sp] = params.locallab.threshold = dataspot[46][0];
+ dataspot[47][sp] = sensicbs[sp] = params.locallab.sensicb = dataspot[47][0];
+
+ if (dataspot[48][0] == 0) {
+ params.locallab.activlum = 0;
+ activlums[sp] = 0;
+ dataspot[48][sp] = 0;
+ } else {
+ params.locallab.activlum = 1;
+ activlums[sp] = 1;
+ dataspot[48][sp] = 1;
+ }
+
+ dataspot[49][sp] = strens[sp] = params.locallab.stren = dataspot[49][0];
+ dataspot[50][sp] = gammas[sp] = params.locallab.gamma = dataspot[50][0];
+ dataspot[51][sp] = estops[sp] = params.locallab.estop = dataspot[51][0];
+ dataspot[52][sp] = scaltms[sp] = params.locallab.scaltm = dataspot[52][0];
+ dataspot[53][sp] = reweis[sp] = params.locallab.rewei = dataspot[53][0];
+ dataspot[54][sp] = sensitms[sp] = params.locallab.sensitm = dataspot[54][0];
+ dataspot[55][sp] = retrabs[sp] = params.locallab.retrab = dataspot[55][0];
+
+ if (dataspot[56][0] == 0) {
+ params.locallab.curvactiv = false;
+ dataspot[56][sp] = 0;
+ curvactivs[sp] = 0;
+ } else {
+ params.locallab.curvactiv = true;
+ dataspot[56][sp] = 1;
+ curvactivs[sp] = 1;
+ }
+
+ int *s_datc;
+ s_datc = new int[70];
+ int siz;
+
+ ipf.strcurv_data (retistr[0], s_datc, siz);
+ sizeretics[sp] = siz;
+ std::vector cretiend;
+
+ retistr[sp] = retistr[0];
+
+ for (int j = 0; j < siz; j++) {
+ reticurvs[sp * 500 + j] = s_datc[j];
+ cretiend.push_back ((double) (s_datc[j]) / 1000.);
+
+ }
+
+ params.locallab.localTgaincurve.clear();
+ params.locallab.localTgaincurve = cretiend;
+
+ int lenc = params.locallab.localTgaincurve.size();
+
+
+ delete [] s_datc;
+
+ int *s_datcl;
+ s_datcl = new int[70];
+ int sizl;
+
+ ipf.strcurv_data (llstr[0], s_datcl, sizl);
+ sizellcs[sp] = sizl;
+ std::vector cllend;
+
+ llstr[sp] = llstr[0];
+
+ for (int j = 0; j < sizl; j++) {
+ llcurvs[sp * 500 + j] = s_datcl[j];
+ cllend.push_back ((double) (s_datcl[j]) / 1000.);
+
+ }
+
+ params.locallab.llcurve.clear();
+ params.locallab.llcurve = cllend;
+
+ delete [] s_datcl;
+
+ int *s_datch;
+ s_datch = new int[70];
+ int sizh;
+
+ ipf.strcurv_data (lhstr[0], s_datch, sizh);
+ sizelhcs[sp] = sizh;
+ std::vector clhend;
+
+ lhstr[sp] = lhstr[0];
+
+ for (int j = 0; j < sizh; j++) {
+ lhcurvs[sp * 500 + j] = s_datch[j];
+ clhend.push_back ((double) (s_datch[j]) / 1000.);
+
+ }
+
+ params.locallab.LHcurve.clear();
+ params.locallab.LHcurve = clhend;
+
+ delete [] s_datch;
+
+ params.locallab.getCurves (locRETgainCurve, locRETgainCurverab, loclhCurve);
+ locallutili = false;
+ CurveFactory::curveLocal (locallutili, params.locallab.llcurve, lllocalcurve, sca); //scale == 1 ? 1 : 16);
+
+ ipf.Lab_Local (3, sp, (float**)shbuffer, nprevl, nprevl, 0, 0, 0, 0, pW, pH, fw, fh, locutili, scale, locRETgainCurve, locallutili, lllocalcurve, loclhCurve, params.locallab.hueref, params.locallab.chromaref, params.locallab.lumaref);
+ dataspot[57][sp] = huerefs[sp] = 100.f * params.locallab.hueref;
+ dataspot[58][sp] = chromarefs[sp] = params.locallab.chromaref;
+ dataspot[59][sp] = lumarefs[sp] = params.locallab.lumaref;
+ lllocalcurve.clear();
+ nextParams.locallab.hueref = params.locallab.hueref;
+ nextParams.locallab.chromaref = params.locallab.chromaref;
+ nextParams.locallab.lumaref = params.locallab.lumaref;
+
+
+ ofstream fou (datal, ios::out | ios::trunc);
+
+ if (fou)
+
+ {
+
+ for (int spe = 1; spe < maxspot; spe++) {
+ int t_sp = spe;
+ int t_mipversion = 10005;
+ int t_circrad = dataspot[2][spe];
+ int t_locX = dataspot[3][spe];
+ int t_locY = dataspot[4][spe];
+ int t_locYT = dataspot[5][spe];
+ int t_locXL = dataspot[6][spe];
+ int t_centerX = dataspot[7][spe];
+ int t_centerY = dataspot[8][spe];
+ int t_lightness = dataspot[9][spe];
+ int t_contrast = dataspot[10][spe];
+ int t_chroma = dataspot[11][spe];
+ int t_sensi = dataspot[12][spe];
+ int t_transit = dataspot[13][spe];
+ int t_invers = dataspot[14][spe];
+ int t_Smeth = dataspot[15][spe];
+ int t_currentspot = realspot;
+ int t_radius = dataspot[17][spe];
+ int t_strength = dataspot[18][spe];
+ int t_sensibn = dataspot[19][spe];
+ int t_inversrad = dataspot[20][spe];
+ int t_str = dataspot[21][spe];
+ int t_chrrt = dataspot[22][spe];
+ int t_neigh = dataspot[23][spe];
+ int t_vart = dataspot[24][spe];
+ int t_sensih = dataspot[25][spe];
+ int t_inversret = dataspot[26][spe];
+ int t_retinexMethod = dataspot[27][spe];
+ int t_sharradius = dataspot[28][spe];
+ int t_sharamount = dataspot[29][spe];
+ int t_shardamping = dataspot[30][spe];
+ int t_shariter = dataspot[31][spe];
+ int t_sensisha = dataspot[32][spe];
+ int t_inverssha = dataspot[33][spe];
+ int t_qualityMethod = dataspot[34][spe];
+ int t_thres = dataspot[35][spe];
+ int t_proxi = dataspot[36][spe];
+ int t_noiselumf = dataspot[37][spe];
+ int t_noiselumc = dataspot[38][spe];
+ int t_noisechrof = dataspot[39][spe];
+ int t_noisechroc = dataspot[40][spe];
+ int t_mult0 = dataspot[41][spe];
+ int t_mult1 = dataspot[42][spe];
+ int t_mult2 = dataspot[43][spe];
+ int t_mult3 = dataspot[44][spe];
+ int t_mult4 = dataspot[45][spe];
+ int t_threshold = dataspot[46][spe];
+ int t_sensicb = dataspot[47][spe];
+ int t_activlum = dataspot[48][spe];
+
+ int t_stren = dataspot[49][spe];
+ int t_gamma = dataspot[50][spe];
+ int t_estop = dataspot[51][spe];
+ int t_scaltm = dataspot[52][spe];
+ int t_rewei = dataspot[53][spe];
+ int t_sensitm = dataspot[54][spe];
+ int t_retrab = dataspot[55][spe];
+ int t_curvactiv = dataspot[56][spe];
+
+ int t_hueref = dataspot[57][spe];
+ int t_chromaref = dataspot[58][spe];
+ int t_lumaref = dataspot[59][spe];
+
+ std::string t_curvret = retistr[spe];
+ std::string t_curvll = llstr[spe];
+ std::string t_curvlh = lhstr[spe];
+
+ fou << "Mipversion=" << t_mipversion << '@' << endl;
+ fou << "Spot=" << t_sp << '@' << endl;
+ fou << "Circrad=" << t_circrad << '@' << endl;
+ fou << "LocX=" << t_locX << '@' << endl;
+ fou << "LocY=" << t_locY << '@' << endl;
+ fou << "LocYT=" << t_locYT << '@' << endl;
+ fou << "LocXL=" << t_locXL << '@' << endl ;
+ fou << "CenterX=" << t_centerX << '@' << endl;
+ fou << "CenterY=" << t_centerY << '@' << endl;
+ fou << "Lightness=" << t_lightness << '@' << endl;
+ fou << "Contrast=" << t_contrast << '@' << endl;
+ fou << "Chroma=" << t_chroma << '@' << endl;
+ fou << "Sensi=" << t_sensi << '@' << endl;
+ fou << "Transit=" << t_transit << '@' << endl;
+ fou << "Invers=" << t_invers << '@' << endl;
+ fou << "Smethod=" << t_Smeth << '@' << endl;
+ fou << "Currentspot=" << t_currentspot << '@' << endl;
+ fou << "Radius=" << t_radius << '@' << endl;
+ fou << "Strength=" << t_strength << '@' << endl;
+ fou << "Sesibn=" << t_sensibn << '@' << endl;
+ fou << "Inversrad=" << t_inversrad << '@' << endl;
+ fou << "Str=" << t_str << '@' << endl;
+ fou << "Chroma=" << t_chrrt << '@' << endl;
+ fou << "Neigh=" << t_neigh << '@' << endl;
+ fou << "Vart=" << t_vart << '@' << endl;
+ fou << "Sensih=" << t_sensih << '@' << endl;
+ fou << "Inversret=" << t_inversret << '@' << endl;
+ fou << "retinexMethod=" << t_retinexMethod << '@' << endl;
+ fou << "Sharradius=" << t_sharradius << '@' << endl;
+ fou << "Sharamount=" << t_sharamount << '@' << endl;
+ fou << "Shardamping=" << t_shardamping << '@' << endl;
+ fou << "Shariter=" << t_shariter << '@' << endl;
+ fou << "Sensisha=" << t_sensisha << '@' << endl;
+ fou << "Inverssha=" << t_inverssha << '@' << endl;
+ fou << "qualityMethod=" << t_qualityMethod << '@' << endl;
+ fou << "Thres=" << t_thres << '@' << endl;
+ fou << "Proxi=" << t_proxi << '@' << endl;
+ fou << "Noiselumf=" << t_noiselumf << '@' << endl;
+ fou << "Noiselumc=" << t_noiselumc << '@' << endl;
+ fou << "Noisechrof=" << t_noisechrof << '@' << endl;
+ fou << "Noisechroc=" << t_noisechroc << '@' << endl;
+ fou << "Mult0=" << t_mult0 << '@' << endl;
+ fou << "Mult1=" << t_mult1 << '@' << endl;
+ fou << "Mult2=" << t_mult2 << '@' << endl;
+ fou << "Mult3=" << t_mult3 << '@' << endl;
+ fou << "Mult4=" << t_mult4 << '@' << endl;
+ fou << "Threshold=" << t_threshold << '@' << endl;
+ fou << "Sensicb=" << t_sensicb << '@' << endl;
+ fou << "Activblurlum=" << t_activlum << '@' << endl;
+
+ fou << "Stren=" << t_stren << '@' << endl;
+ fou << "Gamma=" << t_gamma << '@' << endl;
+ fou << "Estop=" << t_estop << '@' << endl;
+ fou << "Scaltm=" << t_scaltm << '@' << endl;
+ fou << "Rewei=" << t_rewei << '@' << endl;
+ fou << "Sensitm=" << t_sensitm << '@' << endl;
+
+ fou << "Retrab=" << t_retrab << '@' << endl;
+ fou << "Curvactiv=" << t_curvactiv << '@' << endl;
+
+ fou << "hueref=" << t_hueref << '@' << endl;
+ fou << "chromaref=" << t_chromaref << '@' << endl;
+ fou << "lumaref=" << t_lumaref << '@' << endl;
+ fou << "curveReti=" << t_curvret << endl;
+ fou << "curveLL=" << t_curvll << endl;
+ fou << "curveLH=" << t_curvlh << endl;
+
+ fou << endl;
+ }
+
+ fou.close();
+ }
+
+
+
+ for (int i = 0; i < 60; i++) {
+ delete [] dataspot[i];
+ }
+
+ delete [] dataspot;
+
+ delete [] retistr;
+ delete [] llstr;
+ delete [] lhstr;
+
+
+ // }
+ }
+
+
histCCurve.clear();
histLCurve.clear();
ipf.chromiLuminanceCurve (nullptr, pW, nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, histCCurve, histLCurve);
- ipf.vibrance(nprevl);
+ ipf.vibrance (nprevl);
- if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
- ipf.EPDToneMap(nprevl, 5, 1);
+ if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
+ ipf.EPDToneMap (nprevl, 5, 1);
}
// for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled
@@ -660,8 +2309,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
}
*/
- if(params.dirpyrequalizer.cbdlMethod == "aft") {
- if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) ) {
+ if (params.dirpyrequalizer.cbdlMethod == "aft") {
+ if (((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) ) {
progress ("Pyramid wavelet...", 100 * readyphase / numofphases);
ipf.dirpyrequalizer (nprevl, scale);
//ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale);
@@ -672,35 +2321,35 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
wavcontlutili = false;
//CurveFactory::curveWavContL ( wavcontlutili,params.wavelet.lcurve, wavclCurve, LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,int skip);
- CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve, scale == 1 ? 1 : 16);
+ CurveFactory::curveWavContL (wavcontlutili, params.wavelet.wavclCurve, wavclCurve, scale == 1 ? 1 : 16);
- if((params.wavelet.enabled)) {
+ if ((params.wavelet.enabled)) {
WaveletParams WaveParams = params.wavelet;
// WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY);
- WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ WaveParams.getCurves (wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
int kall = 0;
progress ("Wavelet...", 100 * readyphase / numofphases);
// ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, scale);
- ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, scale);
+ ipf.ip_wavelet (nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, scale);
}
- if(params.colorappearance.enabled) {
+ if (params.colorappearance.enabled) {
//L histo and Chroma histo for ciecam
// histogram well be for Lab (Lch) values, because very difficult to do with J,Q, M, s, C
int x1, y1, x2, y2;
- params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2);
+ params.crop.mapToResized (pW, pH, scale, x1, x2, y1, y2);
lhist16CAM.clear();
lhist16CCAM.clear();
- if(!params.colorappearance.datacie) {
+ if (!params.colorappearance.datacie) {
for (int x = 0; x < pH; x++)
for (int y = 0; y < pW; y++) {
- int pos = CLIP((int)(nprevl->L[x][y]));
- int posc = CLIP((int)sqrt(nprevl->a[x][y] * nprevl->a[x][y] + nprevl->b[x][y] * nprevl->b[x][y]));
+ int pos = CLIP ((int) (nprevl->L[x][y]));
+ int posc = CLIP ((int)sqrt (nprevl->a[x][y] * nprevl->a[x][y] + nprevl->b[x][y] * nprevl->b[x][y]));
lhist16CAM[pos]++;
lhist16CCAM[posc]++;
}
@@ -715,13 +2364,13 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
double fcomp = imgsrc->getMetaData()->getExpComp (); // Compensation +/-
double adap;
- if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
+ if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
adap = 2000.;
} else {
- double E_V = fcomp + log2 (double((fnum * fnum) / fspeed / (fiso / 100.f)));
+ double E_V = fcomp + log2 (double ((fnum * fnum) / fspeed / (fiso / 100.f)));
E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
- E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV
- adap = powf(2.f, E_V - 3.f); // cd / m2
+ E_V += log2 (params.raw.expos); // exposure raw white point ; log2 ==> linear to EV
+ adap = powf (2.f, E_V - 3.f); // cd / m2
// end calculation adaptation scene luminosity
}
@@ -730,16 +2379,16 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
float d;
bool execsharp = false;
- if(!ncie) {
+ if (!ncie) {
ncie = new CieImage (pW, pH);
}
if (!CAMBrightCurveJ && (params.colorappearance.algo == "JC" || params.colorappearance.algo == "JS" || params.colorappearance.algo == "ALL")) {
- CAMBrightCurveJ(32768, 0);
+ CAMBrightCurveJ (32768, 0);
}
if (!CAMBrightCurveQ && (params.colorappearance.algo == "QM" || params.colorappearance.algo == "ALL")) {
- CAMBrightCurveQ(32768, 0);
+ CAMBrightCurveQ (32768, 0);
}
// Issue 2785, only float version of ciecam02 for navigator and pan background
@@ -747,14 +2396,14 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
CAMBrightCurveJ.dirty = true;
CAMBrightCurveQ.dirty = true;
- ipf.ciecam_02float (ncie, float(adap), begh, endh, pW, 2, nprevl, ¶ms, customColCurve1, customColCurve2, customColCurve3, histLCAM, histCCAM, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, execsharp, d, scale, 1);
+ ipf.ciecam_02float (ncie, float (adap), begh, endh, pW, 2, nprevl, ¶ms, customColCurve1, customColCurve2, customColCurve3, histLCAM, histCCAM, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, execsharp, d, scale, 1);
- if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) {
- acListener->autoCamChanged(100.*(double)d);
+ if (params.colorappearance.autodegree && acListener && params.colorappearance.enabled) {
+ acListener->autoCamChanged (100.* (double)d);
}
- if(params.colorappearance.autoadapscen && acListener && params.colorappearance.enabled) {
- acListener->adapCamChanged(adap); //real value of adapt scene luminosity
+ if (params.colorappearance.autoadapscen && acListener && params.colorappearance.enabled) {
+ acListener->adapCamChanged (adap); //real value of adapt scene luminosity
}
readyphase++;
@@ -776,15 +2425,15 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
}
- // Update the monitor color transform if necessary
- if ((todo & M_MONITOR) || (lastOutputProfile!=params.icm.output) || lastOutputIntent!=params.icm.outputIntent || lastOutputBPC!=params.icm.outputBPC) {
+// Update the monitor color transform if necessary
+ if ((todo & M_MONITOR) || (lastOutputProfile != params.icm.output) || lastOutputIntent != params.icm.outputIntent || lastOutputBPC != params.icm.outputBPC) {
lastOutputProfile = params.icm.output;
lastOutputIntent = params.icm.outputIntent;
lastOutputBPC = params.icm.outputBPC;
- ipf.updateColorProfiles(monitorProfile, monitorIntent, softProof, gamutCheck);
+ ipf.updateColorProfiles (monitorProfile, monitorIntent, softProof, gamutCheck);
}
- // process crop, if needed
+// process crop, if needed
for (size_t i = 0; i < crops.size(); i++)
if (crops[i]->hasListener () && cropCall != crops[i] ) {
crops[i]->update (todo); // may call ourselves
@@ -793,7 +2442,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
progress ("Conversion to RGB...", 100 * readyphase / numofphases);
if ((todo != CROP && todo != MINUPDATE) || (todo & M_MONITOR)) {
- MyMutex::MyLock prevImgLock(previmg->getMutex());
+ MyMutex::MyLock prevImgLock (previmg->getMutex());
try {
// Computing the preview image, i.e. converting from WCS->Monitor color space (soft-proofing disabled) or WCS->Output profile->Monitor color space (soft-proofing enabled)
@@ -802,7 +2451,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
// Computing the internal image for analysis, i.e. conversion from WCS->Output profile
delete workimg;
workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, params.icm);
- } catch(char * str) {
+ } catch (char * str) {
progress ("Error converting file...", 0);
return;
}
@@ -865,7 +2514,7 @@ void ImProcCoordinator::freeAll ()
delete workimg;
- if(shmap) {
+ if (shmap) {
delete shmap;
}
@@ -889,7 +2538,7 @@ void ImProcCoordinator::setScale (int prevscale)
printf ("setscale before lock\n");
}
- tr = getCoarseBitMask(params.coarse);
+ tr = getCoarseBitMask (params.coarse);
int nW, nH;
imgsrc->getFullSize (fw, fh, tr);
@@ -900,7 +2549,7 @@ void ImProcCoordinator::setScale (int prevscale)
prevscale--;
PreviewProps pp (0, 0, fw, fh, prevscale);
imgsrc->getSize (pp, nW, nH);
- } while(nH < 400 && prevscale > 1 && (nW * nH < 1000000) ); // sctually hardcoded values, perhaps a better choice is possible
+ } while (nH < 400 && prevscale > 1 && (nW * nH < 1000000) ); // sctually hardcoded values, perhaps a better choice is possible
if (settings->verbose) {
printf ("setscale starts (%d, %d)\n", nW, nH);
@@ -917,11 +2566,12 @@ void ImProcCoordinator::setScale (int prevscale)
oprevi = orig_prev;
oprevl = new LabImage (pW, pH);
nprevl = new LabImage (pW, pH);
+ // nprevloc = new LabImage (pW, pH);
//ncie is only used in ImProcCoordinator::updatePreviewImage, it will be allocated on first use and deleted if not used anymore
previmg = new Image8 (pW, pH);
workimg = new Image8 (pW, pH);
- if(params.sh.enabled) {
+ if (params.sh.enabled) {
shmap = new SHMap (pW, pH, true);
}
@@ -953,7 +2603,7 @@ void ImProcCoordinator::updateLRGBHistograms ()
{
int x1, y1, x2, y2;
- params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2);
+ params.crop.mapToResized (pW, pH, scale, x1, x2, y1, y2);
#pragma omp parallel sections
{
@@ -964,7 +2614,7 @@ void ImProcCoordinator::updateLRGBHistograms ()
for (int i = y1; i < y2; i++)
for (int j = x1; j < x2; j++)
{
- histChroma[(int)(sqrtf(SQR(nprevl->a[i][j]) + SQR(nprevl->b[i][j])) / 188.f)]++; //188 = 48000/256
+ histChroma[ (int) (sqrtf (SQR (nprevl->a[i][j]) + SQR (nprevl->b[i][j])) / 188.f)]++; //188 = 48000/256
}
}
#pragma omp section
@@ -974,7 +2624,7 @@ void ImProcCoordinator::updateLRGBHistograms ()
for (int i = y1; i < y2; i++)
for (int j = x1; j < x2; j++)
{
- histLuma[(int)(nprevl->L[i][j] / 128.f)]++;
+ histLuma[ (int) (nprevl->L[i][j] / 128.f)]++;
}
}
#pragma omp section
@@ -1011,21 +2661,21 @@ void ImProcCoordinator::progress (Glib::ustring str, int pr)
}*/
}
-bool ImProcCoordinator::getAutoWB (double& temp, double& green, double equal)
+bool ImProcCoordinator::getAutoWB (double & temp, double & green, double equal)
{
if (imgsrc) {
if (lastAwbEqual != equal) {
// Issue 2500 MyMutex::MyLock lock(minit); // Also used in crop window
double rm, gm, bm;
- imgsrc->getAutoWBMultipliers(rm, gm, bm);
+ imgsrc->getAutoWBMultipliers (rm, gm, bm);
if (rm != -1) {
- autoWB.update(rm, gm, bm, equal);
+ autoWB.update (rm, gm, bm, equal);
lastAwbEqual = equal;
} else {
lastAwbEqual = -1.;
- autoWB.useDefaults(equal);
+ autoWB.useDefaults (equal);
}
}
@@ -1040,7 +2690,7 @@ bool ImProcCoordinator::getAutoWB (double& temp, double& green, double equal)
}
}
-void ImProcCoordinator::getCamWB (double& temp, double& green)
+void ImProcCoordinator::getCamWB (double & temp, double & green)
{
if (imgsrc) {
@@ -1049,13 +2699,13 @@ void ImProcCoordinator::getCamWB (double& temp, double& green)
}
}
-void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double& tgreen)
+void ImProcCoordinator::getSpotWB (int x, int y, int rect, double & temp, double & tgreen)
{
ColorTemp ret;
{
- MyMutex::MyLock lock(mProcessing);
+ MyMutex::MyLock lock (mProcessing);
std::vector points, red, green, blue;
for (int i = y - rect; i <= y + rect; i++)
@@ -1065,7 +2715,7 @@ void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double&
ipf.transCoord (fw, fh, points, red, green, blue);
- int tr = getCoarseBitMask(params.coarse);
+ int tr = getCoarseBitMask (params.coarse);
ret = imgsrc->getSpotWB (red, green, blue, tr, params.wb.equal);
currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method);
@@ -1086,15 +2736,15 @@ void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double&
void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &h)
{
- MyMutex::MyLock lock(mProcessing);
+ MyMutex::MyLock lock (mProcessing);
LCPMapper *pLCPMap = nullptr;
if (params.lensProf.lcpFile.length() && imgsrc->getMetaData()->getFocalLen() > 0) {
- LCPProfile *pLCPProf = lcpStore->getProfile(params.lensProf.lcpFile);
+ LCPProfile *pLCPProf = lcpStore->getProfile (params.lensProf.lcpFile);
- if (pLCPProf) pLCPMap = new LCPMapper(pLCPProf, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(),
- 0, false, params.lensProf.useDist, fullw, fullh, params.coarse, imgsrc->getRotateDegree());
+ if (pLCPProf) pLCPMap = new LCPMapper (pLCPProf, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(),
+ 0, false, params.lensProf.useDist, fullw, fullh, params.coarse, imgsrc->getRotateDegree());
}
double fillscale = ipf.getTransformAutoFill (fullw, fullh, pLCPMap);
@@ -1116,13 +2766,13 @@ void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &
y = (fullh - h) / 2;
}
-void ImProcCoordinator::setMonitorProfile (const Glib::ustring& profile, RenderingIntent intent)
+void ImProcCoordinator::setMonitorProfile (const Glib::ustring & profile, RenderingIntent intent)
{
monitorProfile = profile;
monitorIntent = intent;
}
-void ImProcCoordinator::getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const
+void ImProcCoordinator::getMonitorProfile (Glib::ustring & profile, RenderingIntent & intent) const
{
profile = monitorProfile;
intent = monitorIntent;
@@ -1134,20 +2784,20 @@ void ImProcCoordinator::setSoftProofing (bool softProof, bool gamutCheck)
this->gamutCheck = gamutCheck;
}
-void ImProcCoordinator::getSoftProofing (bool &softProof, bool &gamutCheck)
+void ImProcCoordinator::getSoftProofing (bool & softProof, bool & gamutCheck)
{
softProof = this->softProof;
gamutCheck = this->gamutCheck;
}
-void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb)
+void ImProcCoordinator::saveInputICCReference (const Glib::ustring & fname, bool apply_wb)
{
- MyMutex::MyLock lock(mProcessing);
+ MyMutex::MyLock lock (mProcessing);
int fW, fH;
- int tr = getCoarseBitMask(params.coarse);
+ int tr = getCoarseBitMask (params.coarse);
imgsrc->getFullSize (fW, fH, tr);
PreviewProps pp (0, 0, fW, fH, 1);
@@ -1155,8 +2805,8 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool
ppar.toneCurve.hrenabled = false;
ppar.icm.input = "(none)";
Imagefloat* im = new Imagefloat (fW, fH);
- imgsrc->preprocess( ppar.raw, ppar.lensProf, ppar.coarse );
- imgsrc->demosaic(ppar.raw );
+ imgsrc->preprocess ( ppar.raw, ppar.lensProf, ppar.coarse );
+ imgsrc->demosaic (ppar.raw );
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method);
if (params.wb.method == "Camera") {
@@ -1164,14 +2814,14 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool
} else if (params.wb.method == "Auto") {
if (lastAwbEqual != params.wb.equal) {
double rm, gm, bm;
- imgsrc->getAutoWBMultipliers(rm, gm, bm);
+ imgsrc->getAutoWBMultipliers (rm, gm, bm);
if (rm != -1.) {
- autoWB.update(rm, gm, bm, params.wb.equal);
+ autoWB.update (rm, gm, bm, params.wb.equal);
lastAwbEqual = params.wb.equal;
} else {
lastAwbEqual = -1.;
- autoWB.useDefaults(params.wb.equal);
+ autoWB.useDefaults (params.wb.equal);
}
}
@@ -1203,9 +2853,9 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool
for (int i = cy; i < cy + ch; i++) {
for (int j = cx; j < cx + cw; j++) {
- tmpim->r(i - cy, j - cx) = im->r(i, j);
- tmpim->g(i - cy, j - cx) = im->g(i, j);
- tmpim->b(i - cy, j - cx) = im->b(i, j);
+ tmpim->r (i - cy, j - cx) = im->r (i, j);
+ tmpim->g (i - cy, j - cx) = im->g (i, j);
+ tmpim->b (i - cy, j - cx) = im->b (i, j);
}
}
@@ -1216,11 +2866,11 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool
// image may contain out of range samples, clip them to avoid wrap-arounds
#pragma omp parallel for
- for(int i = 0; i < im->height; i++) {
- for(int j = 0; j < im->width; j++) {
- im->r(i, j) = CLIP(im->r(i, j));
- im->g(i, j) = CLIP(im->g(i, j));
- im->b(i, j) = CLIP(im->b(i, j));
+ for (int i = 0; i < im->height; i++) {
+ for (int j = 0; j < im->width; j++) {
+ im->r (i, j) = CLIP (im->r (i, j));
+ im->g (i, j) = CLIP (im->g (i, j));
+ im->b (i, j) = CLIP (im->b (i, j));
}
}
@@ -1228,7 +2878,7 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool
delete im;
int imw, imh;
- double tmpScale = ipf.resizeScale(¶ms, fW, fH, imw, imh);
+ double tmpScale = ipf.resizeScale (¶ms, fW, fH, imw, imh);
if (tmpScale != 1.0) {
Image16* tempImage = new Image16 (imw, imh);
@@ -1274,13 +2924,13 @@ void ImProcCoordinator::startProcessing ()
//batchThread->yield(); //the running batch should wait other threads to avoid conflict
- thread = Glib::Thread::create(sigc::mem_fun(*this, &ImProcCoordinator::process), 0, true, true, Glib::THREAD_PRIORITY_NORMAL);
+ thread = Glib::Thread::create (sigc::mem_fun (*this, &ImProcCoordinator::process), 0, true, true, Glib::THREAD_PRIORITY_NORMAL);
}
}
}
-void ImProcCoordinator::startProcessing(int changeCode)
+void ImProcCoordinator::startProcessing (int changeCode)
{
paramsUpdateMutex.lock();
changeSinceLast |= changeCode;
@@ -1328,7 +2978,7 @@ ProcParams* ImProcCoordinator::beginUpdateParams ()
void ImProcCoordinator::endUpdateParams (ProcEvent change)
{
- endUpdateParams( refreshmap[(int)change] );
+ endUpdateParams ( refreshmap[ (int)change] );
}
void ImProcCoordinator::endUpdateParams (int changeFlags)
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index 2cc767b39..5303f28e9 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -51,6 +51,8 @@ class ImProcCoordinator : public StagedImageProcessor
{
friend class Crop;
+private:
+
protected:
Imagefloat *orig_prev;
@@ -87,12 +89,14 @@ protected:
// Precomputed values used by DetailedCrop ----------------------------------------------
float bwAutoR, bwAutoG, bwAutoB;
+ int coordX, coordY, localX, localY;
float CAMMean;
LUTf hltonecurve;
LUTf shtonecurve;
LUTf tonecurve;
LUTf lumacurve;
+// LUTf localcurve;
LUTf chroma_acurve;
LUTf chroma_bcurve;
LUTf satcurve;
@@ -102,6 +106,7 @@ protected:
multi_array2D conversionBuffer;
LUTf wavclCurve;
LUTf clToningcurve;
+ LUTf lllocalcurve;
LUTf cl2Toningcurve;
LUTf Noisecurve;
LUTf NoiseCCcurve;
@@ -135,6 +140,9 @@ protected:
WavOpacityCurveWL waOpacityCurveWL;
RetinextransmissionCurve dehatransmissionCurve;
RetinexgaintransmissionCurve dehagaintransmissionCurve;
+ LocretigainCurve locRETgainCurve;
+ LocretigainCurverab locRETgainCurverab;
+ LocLHCurve loclhCurve;
ColorAppearance customColCurve1;
ColorAppearance customColCurve2;
@@ -156,6 +164,8 @@ protected:
AutoExpListener* aeListener;
AutoCamListener* acListener;
AutoBWListener* abwListener;
+ localListener* aloListener;
+
AutoColorTonListener* actListener;
AutoChromaListener* adnListener;
WaveletListener* awavListener;
@@ -193,8 +203,10 @@ protected:
int changeSinceLast;
bool updaterRunning;
ProcParams nextParams;
+ ProcParams nextParams2;
bool destroying;
bool utili;
+ bool locutili;
bool autili;
bool butili;
bool ccutili;
@@ -202,6 +214,82 @@ protected:
bool clcutili;
bool opautili;
bool wavcontlutili;
+ bool locallutili;
+ int **dataspot;
+ std::string *retistr;
+ std::string *llstr;
+ std::string *lhstr;
+
+ LUTi circrads;
+ LUTi centerx;
+ LUTi centery;
+ LUTi locx;
+ LUTi locy;
+ LUTi locxl;
+ LUTi locyt;
+ LUTi lights;
+ LUTi contrs;
+ LUTi chroms;
+ LUTi sensis;
+ LUTi transits;
+ LUTi inverss;
+ LUTi curvactivs;
+ LUTi smeths;
+ LUTi curens;
+ LUTi radiuss;
+ LUTi strengths;
+ LUTi sensibns;
+ LUTi inversrads;
+ LUTi strs;
+ LUTi chrrts;
+ LUTi neighs;
+ LUTi varts;
+ LUTi sensihs;
+ LUTi inversrets;
+ LUTi retinexs;
+ LUTi sps;
+ LUTi sharradiuss;
+ LUTi sharamounts;
+ LUTi shardampings;
+ LUTi inversshas;
+ LUTi shariters;
+ LUTi sensishas;
+ LUTi qualitys;
+ LUTi thress;
+ LUTi proxis;
+ LUTi noiselumfs;
+ LUTi noiselumcs;
+ LUTi noisechrofs;
+ LUTi noisechrocs;
+ LUTi mult0s;
+ LUTi mult1s;
+ LUTi mult2s;
+ LUTi mult3s;
+ LUTi mult4s;
+ LUTi thresholds;
+ LUTi sensicbs;
+ LUTi activlums;
+ LUTi strens;
+ LUTi gammas;
+ LUTi estops;
+ LUTi scaltms;
+ LUTi reweis;
+ LUTi sensitms;
+
+ int versionmip;
+ LUTi sizeretics;
+ LUTi reticurvs;
+ LUTi retrabs;
+ LUTi llcurvs;
+ LUTi sizellcs;
+ LUTi lhcurvs;
+ LUTi sizelhcs;
+
+ LUTf huerefs;
+ LUTf chromarefs;
+ LUTf lumarefs;
+
+
void startProcessing ();
void process ();
float colourToningSatLimit;
@@ -218,12 +306,14 @@ public:
*dst = params;
}
- void startProcessing(int changeCode);
+ void startProcessing (int changeCode);
ProcParams* beginUpdateParams ();
void endUpdateParams (ProcEvent change); // must be called after beginUpdateParams, triggers update
void endUpdateParams (int changeFlags);
void stopProcessing ();
+// void updatePreviewImage (int todo, Crop* cropCall = NULL);
+ std::string *retistrsav;
void setPreviewScale (int scale)
{
@@ -299,7 +389,7 @@ public:
{
aeListener = ael;
}
- void setHistogramListener(HistogramListener *h)
+ void setHistogramListener (HistogramListener *h)
{
hListener = h;
}
@@ -311,6 +401,11 @@ public:
{
abwListener = abw;
}
+ void setlocalListener (localListener* alo)
+ {
+ aloListener = alo;
+ }
+
void setAutoColorTonListener (AutoColorTonListener* bwct)
{
actListener = bwct;
@@ -336,7 +431,7 @@ public:
}
struct DenoiseInfoStore {
- DenoiseInfoStore () : chM(0), max_r{}, max_b{}, ch_M{}, valid(false) {}
+ DenoiseInfoStore () : chM (0), max_r{}, max_b{}, ch_M{}, valid (false) {}
float chM;
float max_r[9];
float max_b[9];
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index 1a3a969ae..852a11f0a 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -78,6 +78,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile,
monitorTransform = nullptr;
cmsHPROFILE monitor = nullptr;
+
if (!monitorProfile.empty()) {
#if !defined(__APPLE__) // No support for monitor profiles on OS X, all data is sRGB
monitor = iccStore->getProfile (monitorProfile);
@@ -96,6 +97,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile,
if (softProof) {
cmsHPROFILE oprof = nullptr;
+
if (!settings->printerProfile.empty()) {
oprof = iccStore->getProfile(settings->printerProfile);
}
@@ -103,19 +105,23 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile,
if (oprof) {
// NOCACHE is for thread safety, NOOPTIMIZE for precision
flags = cmsFLAGS_SOFTPROOFING | cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
+
if (settings->printerBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
}
+
if (gamutCheck) {
flags |= cmsFLAGS_GAMUTCHECK;
}
+
monitorTransform = cmsCreateProofingTransform(
- iprof, TYPE_Lab_FLT,
- monitor, TYPE_RGB_8,
- oprof,
- monitorIntent, settings->printerIntent,
- flags
- );
+ iprof, TYPE_Lab_FLT,
+ monitor, TYPE_RGB_8,
+ oprof,
+ monitorIntent, settings->printerIntent,
+ flags
+ );
+
if (monitorTransform) {
softProofCreated = true;
}
@@ -124,9 +130,11 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile,
if (!softProofCreated) {
flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
+
if (settings->monitorBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
}
+
monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, monitorIntent, flags);
}
@@ -196,6 +204,7 @@ void ImProcFunctions::firstAnalysis (const Imagefloat* const original, const Pro
}
}
+
// Copyright (c) 2012 Jacques Desmis
void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh, int pW, int pwb, LabImage* lab, const ProcParams* params ,
const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2, const ColorAppearance & customColCurve3,
@@ -535,7 +544,7 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
xw2 = xwd;
yw2 = ywd;
zw2 = zwd;
- } else /*if(params->colorappearance.wbmodel == "RawTCAT02")*/ {
+ } else { /*if(params->colorappearance.wbmodel == "RawTCAT02")*/
xw1 = xw; // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences
yw1 = yw;
zw1 = zw;
@@ -1076,9 +1085,10 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
if(pW != 1) { //only with improccoordinator
int posl;
+
if(libr == 1) {
posl = CLIP((int)(Q * brli)); //40.0 to 100.0 approximative factor for Q - 327 for J
- } else /*if(libr == 0)*/ {
+ } else { /*if(libr == 0)*/
posl = CLIP((int)(J * brli)); //327 for J
}
@@ -1089,11 +1099,12 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
if(pW != 1) { //only with improccoordinator
int posc;
+
if(colch == 0) {
posc = CLIP((int)(C * chsacol)); //450.0 approximative factor for s 320 for M
} else if(colch == 1) {
posc = CLIP((int)(s * chsacol));
- } else /*if(colch == 2)*/ {
+ } else { /*if(colch == 2)*/
posc = CLIP((int)(M * chsacol));
}
@@ -1347,9 +1358,10 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
if(pW != 1) { //only with improccoordinator
int posl;
+
if(libr == 1) {
posl = CLIP((int)(ncie->Q_p[i][j] * brli)); //40.0 to 100.0 approximative factor for Q - 327 for J
- } else /*if(libr == 0)*/ {
+ } else { /*if(libr == 0)*/
posl = CLIP((int)(ncie->J_p[i][j] * brli)); //327 for J
}
@@ -1360,12 +1372,13 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
if(pW != 1) { //only with improccoordinator
int posc;
+
if(colch == 0) {
posc = CLIP((int)(ncie->C_p[i][j] * chsacol)); //450.0 approximative factor for s 320 for M
} else if(colch == 1) {
sa_t = 100.f * sqrt(ncie->C_p[i][j] / ncie->Q_p[i][j]); //Q_p always > 0
posc = CLIP((int)(sa_t * chsacol));
- } else /*if(colch == 2)*/ {
+ } else { /*if(colch == 2)*/
posc = CLIP((int)(ncie->M_p[i][j] * chsacol));
}
@@ -1835,7 +1848,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
xw2 = xwd;
yw2 = ywd;
zw2 = zwd;
- } else /*if(params->colorappearance.wbmodel == "RawTCAT02")*/ {
+ } else { /*if(params->colorappearance.wbmodel == "RawTCAT02")*/
xw1 = xw; // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences
yw1 = yw;
zw1 = zw;
@@ -3004,7 +3017,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
static_cast( wprof[2][2] / Color::D50z)
}
};
- float maxFactorToxyz = max(toxyz[1][0],toxyz[1][1],toxyz[1][2]);
+ float maxFactorToxyz = max(toxyz[1][0], toxyz[1][1], toxyz[1][2]);
float equalR = maxFactorToxyz / toxyz[1][0];
float equalG = maxFactorToxyz / toxyz[1][1];
float equalB = maxFactorToxyz / toxyz[1][2];
@@ -3331,6 +3344,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
float out_rgbx[4 * TS] ALIGNED16; // Line buffer for CLUT
LUTu histToneCurveThr;
+
if(toneCurveHistSize > 0) {
histToneCurveThr(toneCurveHistSize);
histToneCurveThr.clear();
@@ -3484,9 +3498,10 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
rtemp[ti * TS + tj] = tonecurve[ rtemp[ti * TS + tj] ];
gtemp[ti * TS + tj] = tonecurve[ gtemp[ti * TS + tj] ];
btemp[ti * TS + tj] = tonecurve[ btemp[ti * TS + tj] ];
+
if(histToneCurveThr) {
int y = CLIP(lumimulf[0] * Color::gamma2curve[rtemp[ti * TS + tj]] + lumimulf[1] * Color::gamma2curve[gtemp[ti * TS + tj]] + lumimulf[2] * Color::gamma2curve[btemp[ti * TS + tj]]);
- histToneCurveThr[y>>histToneCurveCompression]++;
+ histToneCurveThr[y >> histToneCurveCompression]++;
}
}
}
@@ -3731,7 +3746,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
//gamut control : Lab values are in gamut
Color::gamutLchonly(HH, sincosval, Lpro, Chpro, rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], wip, highlight, 0.15f, 0.96f);
#endif
- //end of gamut control
+ //end of gamut control
} else {
float x_, y_, z_;
//calculate RGB with L_2 and old value of a and b
@@ -4134,20 +4149,25 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
// --------------------------------------------------
#ifndef __SSE2__
+
//gamma correction: pseudo TRC curve
if (hasgammabw) {
Color::trcGammaBW (r, g, b, gammabwr, gammabwg, gammabwb);
}
+
#endif
rtemp[ti * TS + tj] = r;
gtemp[ti * TS + tj] = g;
btemp[ti * TS + tj] = b;
}
+
#ifdef __SSE2__
+
if (hasgammabw) {
//gamma correction: pseudo TRC curve
Color::trcGammaBWRow (&rtemp[ti * TS], >emp[ti * TS], &btemp[ti * TS], tW - jstart, gammabwr, gammabwg, gammabwb);
}
+
#endif
}
@@ -4185,6 +4205,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
} else {
L *= (1.f + valparam); //for negative
}
+
L *= 32768.f;
}
@@ -4206,17 +4227,22 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
Color::xyz2r(X, Y, Z, newRed, wip);
rtemp[ti * TS + tj] = gtemp[ti * TS + tj] = btemp[ti * TS + tj] = newRed;
#ifndef __SSE2__
+
if (hasgammabw) {
//gamma correction: pseudo TRC curve
Color::trcGammaBW (rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], gammabwr, gammabwg, gammabwb);
}
+
#endif
}
+
#ifdef __SSE2__
+
if (hasgammabw) {
//gamma correction: pseudo TRC curve
Color::trcGammaBWRow (&rtemp[ti * TS], >emp[ti * TS], &btemp[ti * TS], tW - jstart, gammabwr, gammabwg, gammabwb);
}
+
#endif
}
}
@@ -4413,13 +4439,14 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
if (editWhateverBuffer) {
free (editWhateverBuffer);
}
+
#ifdef _OPENMP
-#pragma omp critical
-{
- if(toneCurveHistSize > 0) {
- histToneCurve += histToneCurveThr;
- }
-}
+ #pragma omp critical
+ {
+ if(toneCurveHistSize > 0) {
+ histToneCurve += histToneCurveThr;
+ }
+ }
#endif // _OPENMP
}
@@ -4483,17 +4510,22 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
tmpImage->r(i, j) = tmpImage->g(i, j) = tmpImage->b(i, j) = CLIP((bwr * tmpImage->r(i, j) + bwg * tmpImage->g(i, j) + bwb * tmpImage->b(i, j)) * kcorec);
#ifndef __SSE2__
+
//gamma correction: pseudo TRC curve
if (hasgammabw) {
Color::trcGammaBW (tmpImage->r(i, j), tmpImage->g(i, j), tmpImage->b(i, j), gammabwr, gammabwg, gammabwb);
}
+
#endif
}
+
#ifdef __SSE2__
+
if (hasgammabw) {
//gamma correction: pseudo TRC curve
Color::trcGammaBWRow (tmpImage->r(i), tmpImage->g(i), tmpImage->b(i), tW, gammabwr, gammabwg, gammabwb);
}
+
#endif
}
}
@@ -6492,6 +6524,109 @@ void ImProcFunctions::EPDToneMapCIE(CieImage *ncie, float a_w, float c_, float w
*/
}
+void ImProcFunctions::EPDToneMaplocal(LabImage *lab, LabImage *tmp1, unsigned int Iterates, int skip)
+{
+
+ float stren = ((float)params->locallab.stren) / 100.f;
+ float edgest = ((float)params->locallab.estop) / 100.f;
+ float sca = ((float)params->locallab.scaltm) / 10.f;
+ float gamm = ((float)params->locallab.gamma) / 100.f;
+ float rew = ((float)params->locallab.rewei);
+ //Pointers to whole data and size of it.
+ float *L = lab->L[0];
+ float *a = lab->a[0];
+ float *b = lab->b[0];
+ unsigned int i, N = lab->W * lab->H;
+ int WW = lab->W ;
+ int HH = lab->H ;
+ EdgePreservingDecomposition epd(lab->W, lab->H);
+
+ //Due to the taking of logarithms, L must be nonnegative. Further, scale to 0 to 1 using nominal range of L, 0 to 15 bit.
+ float minL = FLT_MAX;
+ float maxL = 0.f;
+ #pragma omp parallel
+ {
+ float lminL = FLT_MAX;
+ float lmaxL = 0.f;
+ #pragma omp for
+
+ for(i = 0; i < N; i++) {
+ if(L[i] < lminL) {
+ lminL = L[i];
+ }
+
+ if(L[i] > lmaxL) {
+ lmaxL = L[i];
+ }
+ }
+
+ #pragma omp critical
+
+ if(lminL < minL) {
+ minL = lminL;
+ }
+
+ if(lmaxL > maxL) {
+ maxL = lmaxL;
+ }
+
+ }
+
+ if(minL > 0.0f) {
+ minL = 0.0f; //Disable the shift if there are no negative numbers. I wish there were just no negative numbers to begin with.
+ }
+
+ #pragma omp parallel for
+
+ for(i = 0; i < N; i++)
+ //{L[i] = (L[i] - minL)/32767.0f;
+ {
+ L[i] = (L[i] - minL) / maxL;
+ L[i] *= gamm;
+ }
+
+ //Some interpretations.
+ float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents.
+ float DetailBoost = stren;
+
+ if(stren < 0.0f) {
+ DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing.
+ }
+
+ //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur.
+ if(Iterates == 0) {
+ Iterates = (unsigned int)(edgest * 15.0f);
+ }
+
+ /* Debuggery. Saves L for toying with outside of RT.
+ char nm[64];
+ sprintf(nm, "%ux%ufloat.bin", lab->W, lab->H);
+ FILE *f = fopen(nm, "wb");
+ fwrite(L, N, sizeof(float), f);
+ fclose(f);*/
+
+ epd.CompressDynamicRange(L, sca / float(skip), edgest, Compression, DetailBoost, Iterates, rew, L);
+
+ //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping.
+ float s = (1.0f + 38.7889f) * powf(Compression, 1.5856f) / (1.0f + 38.7889f * powf(Compression, 1.5856f));
+#ifdef _OPENMP
+ #pragma omp parallel for // removed schedule(dynamic,10)
+#endif
+
+ for(int i = 0; i < N; i++) {
+ int x = i / WW;
+ int y = i - x * WW;
+
+ tmp1->L[x][y] = L[i] * maxL * (1.f / gamm) + minL;
+ tmp1->a[x][y] = s * a[i];
+ tmp1->b[x][y] = s * b[i];
+
+ }
+}
+
+
+
+
//Map tones by way of edge preserving decomposition. Is this the right way to include source?
//#include "EdgePreservingDecomposition.cc"
@@ -6602,6 +6737,12 @@ void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip)
}
+
+
+
+
+
+
void ImProcFunctions::getAutoExp (const LUTu &histogram, int histcompr, double defgain, double clip,
double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh)
{
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index e70083b0b..09183b9cc 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -52,7 +52,7 @@ class ImProcFunctions
double scale;
bool multiThread;
- void calcVignettingParams(int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul);
+ void calcVignettingParams (int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul);
void transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap);
void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH);
@@ -95,9 +95,9 @@ class ImProcFunctions
rd = gd = bd = 0.0;
for (int i = xs, ix = 0; i < xs + 4; i++, ix++) {
- rd += src->r(k, i) * w[ix];
- gd += src->g(k, i) * w[ix];
- bd += src->b(k, i) * w[ix];
+ rd += src->r (k, i) * w[ix];
+ gd += src->g (k, i) * w[ix];
+ bd += src->b (k, i) * w[ix];
}
yr[kx] = rd;
@@ -196,7 +196,7 @@ public:
double lumimul[3];
ImProcFunctions (const ProcParams* iparams, bool imultiThread = true)
- : monitorTransform(nullptr), lab2outputTransform(nullptr), output2monitorTransform(nullptr), params(iparams), scale(1), multiThread(imultiThread), lumimul{} {}
+ : monitorTransform (nullptr), lab2outputTransform (nullptr), output2monitorTransform (nullptr), params (iparams), scale (1), multiThread (imultiThread), lumimul{} {}
~ImProcFunctions ();
void setScale (double iscale);
@@ -244,10 +244,12 @@ public:
void Lanczos (const Image16* src, Image16* dst, float scale);
void deconvsharpening (float** luminance, float** buffer, int W, int H, const SharpeningParams &sharpenParam);
+ void deconvsharpeningloc (float** luminance, float** buffer, int W, int H, float** loctemp, int damp, double radi, int ite, int amo);
+
void MLsharpen (LabImage* lab);// Manuel's clarity / sharpening
- void MLmicrocontrast(float** luminance, int W, int H ); //Manuel's microcontrast
- void MLmicrocontrast(LabImage* lab ); //Manuel's microcontrast
- void MLmicrocontrastcam(CieImage* ncie ); //Manuel's microcontrast
+ void MLmicrocontrast (float** luminance, int W, int H ); //Manuel's microcontrast
+ void MLmicrocontrast (LabImage* lab ); //Manuel's microcontrast
+ void MLmicrocontrastcam (CieImage* ncie ); //Manuel's microcontrast
void impulsedenoise (LabImage* lab);//Emil's impulse denoise
void impulsedenoisecam (CieImage* ncie, float **buffers[3]);
@@ -258,13 +260,14 @@ public:
void dirpyrequalizer (LabImage* lab, int scale);//Emil's wavelet
- void EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0);
- float *CompressDR(float *Source, int skip, struct cont_params &cp, int W_L, int H_L, float Compression, float DetailBoost, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx, float *Compressed);
- void ContrastResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params &cp, int W_L, int H_L, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx);
- float *ContrastDR(float *Source, int skip, struct cont_params &cp, int W_L, int H_L, float Compression, float DetailBoost, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx, float *Contrast = nullptr);
+ void EPDToneMapResid (float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0);
+ float *CompressDR (float *Source, int skip, struct cont_params &cp, int W_L, int H_L, float Compression, float DetailBoost, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx, float *Compressed);
+ void ContrastResid (float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params &cp, int W_L, int H_L, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx);
+ float *ContrastDR (float *Source, int skip, struct cont_params &cp, int W_L, int H_L, float Compression, float DetailBoost, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx, float *Contrast = nullptr);
- void EPDToneMap(LabImage *lab, unsigned int Iterates = 0, int skip = 1);
- void EPDToneMapCIE(CieImage *ncie, float a_w, float c_, float w_h, int Wid, int Hei, int begh, int endh, float minQ, float maxQ, unsigned int Iterates = 0, int skip = 1);
+ void EPDToneMap (LabImage *lab, unsigned int Iterates = 0, int skip = 1);
+ void EPDToneMapCIE (CieImage *ncie, float a_w, float c_, float w_h, int Wid, int Hei, int begh, int endh, float minQ, float maxQ, unsigned int Iterates = 0, int skip = 1);
+ void EPDToneMaplocal (LabImage *lab, LabImage *tmp1, unsigned int Iterates, int skip);
// pyramid denoise
procparams::DirPyrDenoiseParams dnparams;
@@ -272,66 +275,93 @@ public:
int pitch, int scale, const int luma, int chroma );
void idirpyr (LabImage* data_coarse, LabImage* data_fine, int level, LUTf &rangefn_L, LUTf & nrwt_l, LUTf & nrwt_ab,
int pitch, int scale, const int luma, const int chroma/*, LUTf & Lcurve, LUTf & abcurve*/ );
+ //locallab
+ void MSRLocal (float** luminance, float** templ, const float* const *originalLuminance, const int width, const int height, const LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax);
+
+ void Lab_Local (int call, int sp, float** shbuffer, LabImage* original, LabImage* transformed, int sx, int sy, int cx, int cy, int oW, int oH, int fw, int fh, bool locutili, int sk, const LocretigainCurve & locRETgainCcurve, bool locallutili, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, double &hueref, double &chromaref, double &lumaref);
+ void addGaNoise (LabImage *lab, LabImage *dst, const float mean, const float variance, const int sk);
+ void BlurNoise_Localold (int call, const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy);
+ void InverseBlurNoise_Local (const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy);
+ void Reti_Local (int call, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params& lp, float **deltE, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int chro);
+ void InverseReti_Local (const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int chro);
+ void Contrast_Local (int call, float moy, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, float pm, struct local_contra &lco, float lumaref, float av, const struct local_params& lp, float **deltE, LabImage* original, LabImage* transformed, int cx, int cy);
+ void cbdl_Local (int call, int sp, float **loctemp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params& lp, float **deltE, LabImage* original, LabImage* transformed, int cx, int cy);
+ void BlurNoise_Local (int call, int sp, LabImage* tmp1, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params& lp, float **deltE, LabImage* original, LabImage* transformed, int cx, int cy);
+ void TM_Local (int call, int sp, LabImage* tmp1, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params& lp, float **deltE, LabImage* original, LabImage* transformed, int cx, int cy);
+ static void strcurv_data (std::string retistr, int *s_datc, int &siz);
+ void InverseContrast_Local (float ave, const struct local_contra& lco, const struct local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy);
+
+ void DeNoise_Local (int call, const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy);
+
+ void ColorLight_Local (int call, LabImage * bufcolorig, LabImage * bufcoltra, int sp, float moy, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, bool locallutili, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, const local_params& lp, float **deltE, LabImage* original, LabImage* transformed, int cx, int cy);
+ void InverseColorLight_Local (const struct local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy);
+
+ void Sharp_Local (int call, int sp, float **loctemp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params& lp, float **deltE, LabImage* original, LabImage* transformed, int cx, int cy);
+ void InverseSharp_Local (int sp, float **loctemp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params& lp, float **deltE, LabImage* original, LabImage* transformed, int cx, int cy);
+
void Tile_calc (int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip);
- void ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, LUTf &wavclCurve, bool wavcontlutili, int skip);
+ void ip_wavelet (LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, LUTf &wavclCurve, bool wavcontlutili, int skip);
- void WaveletcontAllL(LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_L,
- struct cont_params &cp, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, FlatCurve* ChCurve, bool Chutili);
- void WaveletcontAllLfinal(wavelet_decomposition &WaveletCoeffs_L, struct cont_params &cp, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL);
- void WaveletcontAllAB(LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_a, const WavOpacityCurveW & waOpacityCurveW,
- struct cont_params &cp, const bool useChannelA);
- void WaveletAandBAllAB(LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_a, wavelet_decomposition &WaveletCoeffs_b,
- struct cont_params &cp, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* hhcurve, bool hhutili);
+ void WaveletcontAllL (LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_L,
+ struct cont_params &cp, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, FlatCurve* ChCurve, bool Chutili);
+ void WaveletcontAllLfinal (wavelet_decomposition &WaveletCoeffs_L, struct cont_params &cp, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL);
+ void WaveletcontAllAB (LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_a, const WavOpacityCurveW & waOpacityCurveW,
+ struct cont_params &cp, const bool useChannelA);
+ void WaveletAandBAllAB (LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_a, wavelet_decomposition &WaveletCoeffs_b,
+ struct cont_params &cp, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* hhcurve, bool hhutili);
void ContAllL (float **koeLi, float *maxkoeLi, bool lipschitz, int maxlvl, LabImage * lab, float **varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp,
int W_L, int H_L, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili);
void finalContAllL (float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp,
int W_L, int H_L, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL);
void ContAllAB (LabImage * lab, int maxlvl, float **varhue, float **varchrom, float ** WavCoeffs_a, float * WavCoeffs_a0, int level, int dir, const WavOpacityCurveW & waOpacityCurveW, struct cont_params &cp,
int W_ab, int H_ab, const bool useChannelA);
- void Evaluate2(wavelet_decomposition &WaveletCoeffs_L,
- const struct cont_params& cp, int ind, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, float madL[8][3]);
+ void Evaluate2 (wavelet_decomposition &WaveletCoeffs_L,
+ const struct cont_params& cp, int ind, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, float madL[8][3]);
void Eval2 (float ** WavCoeffs_L, int level, const struct cont_params& cp,
int W_L, int H_L, int skip_L, int ind, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, float *madL);
- void Aver(float * HH_Coeffs, int datalen, float &averagePlus, float &averageNeg, float &max, float &min);
- void Sigma(float * HH_Coeffs, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg);
- void calckoe(float ** WavCoeffs_LL, const struct cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr);
+ void Aver (float * HH_Coeffs, int datalen, float &averagePlus, float &averageNeg, float &max, float &min);
+ void Sigma (float * HH_Coeffs, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg);
+ void calckoe (float ** WavCoeffs_LL, const struct cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr);
- void Median_Denoise( float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr);
- void RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve , const NoiseCurve & noiseCCurve , float &chaut, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &nresi, float &highresi);
- void RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope);
- void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false);
+ void Median_Denoise ( float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr);
+ void RGB_denoise (int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve , const NoiseCurve & noiseCCurve , float &chaut, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &nresi, float &highresi);
+ void RGB_denoise_infoGamCurve (const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope);
+ void RGB_denoise_info (Imagefloat * src, Imagefloat * provicalc, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false);
void RGBtile_denoise (float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer ); //for DCT
void RGBoutput_tile_row (float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top );
- bool WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge);
- bool WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
- void WaveletDenoiseAll_info(int levwav, wavelet_decomposition &WaveletCoeffs_a,
- wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float noisevar_abr, float noisevar_abb, LabImage * noi, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, bool autoch, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
- float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb, bool multiThread);
+ bool WaveletDenoiseAllL (wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge);
+ bool WaveletDenoiseAllAB (wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
+ void WaveletDenoiseAll_info (int levwav, wavelet_decomposition &WaveletCoeffs_a,
+ wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float noisevar_abr, float noisevar_abb, LabImage * noi, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, bool autoch, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
+ float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb, bool multiThread);
- bool WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]);
- bool WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab,
- const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
- void ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge);
- void ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
- float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * madaab = nullptr, bool madCalculated = false);
- void ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b, int level,
- int W_ab, int H_ab, int skip_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float noisevar_abr, float noisevar_abb, LabImage * noi, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, bool autoch, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
- float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb, bool multiThread);
- void Noise_residualAB(wavelet_decomposition &WaveletCoeffs_ab, float &chresid, float &chmaxresid, bool denoiseMethodRgb);
+ bool WaveletDenoiseAll_BiShrinkL (wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]);
+ bool WaveletDenoiseAll_BiShrinkAB (wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab,
+ const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
+ void ShrinkAllL (wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge);
+ void ShrinkAllAB (wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
+ float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab = nullptr, bool madCalculated = false);
+
+ void ShrinkAll_info (float ** WavCoeffs_a, float ** WavCoeffs_b, int level,
+ int W_ab, int H_ab, int skip_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float noisevar_abr, float noisevar_abb, LabImage * noi, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, bool autoch, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
+ float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb, bool multiThread);
+ void Noise_residualAB (wavelet_decomposition &WaveletCoeffs_ab, float &chresid, float &chmaxresid, bool denoiseMethodRgb);
void calcautodn_info (float &chaut, float &delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc);
- float MadMax(float * DataList, int &max, int datalen);
- float Mad(float * DataList, const int datalen);
- float MadRgb(float * DataList, const int datalen);
+ float MadMax (float * DataList, int &max, int datalen);
+ float Mad (float * DataList, const int datalen);
+ float MadRgb (float * DataList, const int datalen);
// pyramid wavelet
void dirpyr_equalizer (float ** src, float ** dst, int srcwidth, int srcheight, float ** l_a, float ** l_b, float ** dest_a, float ** dest_b, const double * mult, const double dirpyrThreshold, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale);//Emil's directional pyramid wavelet
+ void cbdl_local_temp (float ** src, float ** dst, float ** loctemp, int srcwidth, int srcheight, const float * mult, const double dirpyrThreshold, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale);
void dirpyr_equalizercam (CieImage* ncie, float ** src, float ** dst, int srcwidth, int srcheight, float ** h_p, float ** C_p, const double * mult, const double dirpyrThreshold, const double skinprot, bool execdir, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale);//Emil's directional pyramid wavelet
void dirpyr_channel (float ** data_fine, float ** data_coarse, int width, int height, int level, int scale);
void idirpyr_eq_channel (float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float multi[5], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice);
+ void idirpyr_eq_channel_loc (float ** data_coarse, float ** data_fine, float ** loctemp, float ** buffer, int width, int height, int level, float multi[5], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice);
void idirpyr_eq_channelcam (float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float multi[5], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, float b_l, float t_l, float t_r);
void defringe (LabImage* lab);
void defringecam (CieImage* ncie);
@@ -340,11 +370,11 @@ public:
void PF_correct_RT (LabImage * src, LabImage * dst, double radius, int thresh);
void PF_correct_RTcam (CieImage * src, CieImage * dst, double radius, int thresh);
- void Badpixelscam(CieImage * src, CieImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad);
- void BadpixelsLab(LabImage * src, LabImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom);
+ void Badpixelscam (CieImage * src, CieImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad);
+ void BadpixelsLab (LabImage * src, LabImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom);
Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm);
- Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool bw, GammaValues *ga=nullptr);
+ Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool bw, GammaValues *ga = nullptr);
// CieImage *ciec;
bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LCPMapper *pLCPMap = nullptr);
@@ -352,8 +382,8 @@ public:
static void getAutoExp (const LUTu & histogram, int histcompr, double defgain, double clip, double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh);
static double getAutoDistor (const Glib::ustring& fname, int thumb_size);
double getTransformAutoFill (int oW, int oH, const LCPMapper *pLCPMap = nullptr);
- void rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace);
- void lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace);
+ void rgb2lab (const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace);
+ void lab2rgb (const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace);
};
}
#endif
diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc
new file mode 100644
index 000000000..049c5fdf4
--- /dev/null
+++ b/rtengine/iplocallab.cc
@@ -0,0 +1,5068 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ * 2016 Jacques Desmis
+ * 2016 Ingo Weyrich
+
+ */
+#include
+#include
+#include
+
+#include "rtengine.h"
+#include "improcfun.h"
+#include "curves.h"
+#include "gauss.h"
+#include "iccstore.h"
+#include "iccmatrices.h"
+#include "color.h"
+#include "rt_math.h"
+#ifdef _DEBUG
+#include "mytime.h"
+#endif
+
+#include "cplx_wavelet_dec.h"
+
+//#define BENCHMARK
+//#include "StopWatch.h"
+
+#define cliploc( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val )
+
+#define CLIPC(a) ((a)>-42000?((a)<42000?(a):42000):-42000) // limit a and b to 130 probably enough ?
+#define CLIPL(x) LIM(x,0.f,40000.f) // limit L to about L=120 probably enough ?
+#define CLIPLOC(x) LIM(x,0.f,32767.f)
+namespace rtengine
+{
+using namespace procparams;
+
+extern const Settings* settings;
+
+struct local_params {
+ float yc, xc;
+ float lx, ly;
+ float lxL, lyT;
+ float dxx, dyy;
+ int cir;
+ float thr;
+ int prox;
+ int chro, cont, sens, sensh, senscb, sensbn, senstm;
+ float ligh;
+ int shamo, shdamp, shiter, senssha;
+ double shrad;
+ double rad;
+ double stren;
+ int trans;
+ bool inv;
+ bool curvact;
+ bool invrad;
+ bool invret;
+ bool invshar;
+ bool actsp;
+ float str;
+ int qualmet;
+ float noiself;
+ float noiselc;
+ float noisecf;
+ float noisecc;
+ float mulloc[5];
+ float threshol;
+ float strengt;
+ float gamm;
+ float esto;
+ float scalt;
+ float rewe;
+ bool colorena;
+ bool blurena;
+ bool tonemapena;
+ bool retiena;
+ bool sharpena;
+ bool cbdlena;
+ bool denoiena;
+
+
+
+};
+
+static void calcLocalParams (int oW, int oH, const LocallabParams& locallab, struct local_params& lp)
+{
+ int w = oW;
+ int h = oH;
+ int circr = locallab.circrad;
+ float streng = ((float)locallab.stren) / 100.f;
+ float gam = ((float)locallab.gamma) / 100.f;
+ float est = ((float)locallab.estop) / 100.f;
+ float scal_tm = ((float)locallab.scaltm) / 10.f;
+ float rewe = ((float)locallab.rewei);
+
+ float thre = locallab.thres / 100.f;
+ double local_x = locallab.locX / 2000.0;
+ double local_y = locallab.locY / 2000.0;
+ double local_xL = locallab.locXL / 2000.0;
+ double local_yT = locallab.locYT / 2000.0;
+ double local_center_x = locallab.centerX / 2000.0 + 0.5;
+ double local_center_y = locallab.centerY / 2000.0 + 0.5;
+// double local_dxx = locallab.proxi / 8000.0;//for proxi = 2==> # 1 pixel
+// double local_dyy = locallab.proxi / 8000.0;
+ float local_dxx = locallab.proxi;
+ double local_dyy = locallab.proxi;
+
+ if (locallab.qualityMethod == "std") {
+ lp.qualmet = 0;
+ } else if (locallab.qualityMethod == "enh") {
+ lp.qualmet = 1;
+ } else if (locallab.qualityMethod == "enhden") {
+ lp.qualmet = 2;
+ }
+
+ float local_noiself = locallab.noiselumf;
+ float local_noiselc = locallab.noiselumc;
+ float local_noisecf = locallab.noisechrof;
+ float local_noisecc = locallab.noisechroc;
+ float multi[5];
+
+ for (int y = 0; y < 5; y++) {
+ multi[y] = ((float) locallab.mult[y]) / 100.f;
+ }
+
+ float thresho = ((float)locallab.threshold ) / 100.f;
+ int local_chroma = locallab.chroma;
+ int local_sensi = locallab.sensi;
+ int local_sensibn = locallab.sensibn;
+ int local_sensitm = locallab.sensitm;
+ int local_sensih = locallab.sensih;
+ int local_sensicb = locallab.sensicb;
+ int local_contrast = locallab.contrast;
+ float local_lightness = (float) locallab.lightness;
+ int local_transit = locallab.transit;
+ double radius = (double) locallab.radius;
+ double sharradius = ((double) locallab.sharradius) / 100. ;
+ int local_sensisha = locallab.sensisha;
+ int local_sharamount = locallab.sharamount;
+ int local_shardamping = locallab.shardamping;
+ int local_shariter = locallab.shariter;
+ bool inverse = locallab.invers;
+ bool curvacti = locallab.curvactiv;
+ bool acti = locallab.activlum;
+
+ bool inverserad = locallab.inversrad;
+ bool inverseret = locallab.inversret;
+ bool inversesha = locallab.inverssha;
+ double strength = (double) locallab.strength;
+ float str = (float)locallab.str;
+ lp.cir = circr;
+ lp.actsp = acti;
+ lp.xc = w * local_center_x;
+ lp.yc = h * local_center_y;
+ lp.lx = w * local_x;
+ lp.ly = h * local_y;
+ lp.lxL = w * local_xL;
+ lp.lyT = h * local_yT;
+ lp.chro = local_chroma;
+ lp.sens = local_sensi;
+ lp.sensh = local_sensih;
+ lp.senscb = local_sensicb;
+ lp.cont = local_contrast;
+ lp.ligh = local_lightness;
+
+ if (lp.ligh >= -2.f && lp.ligh <= 2.f) {
+ lp.ligh /= 5.f;
+ }
+
+ lp.trans = local_transit;
+ lp.rad = radius;
+ lp.stren = strength;
+ lp.sensbn = local_sensibn;
+ lp.inv = inverse;
+ lp.curvact = curvacti;
+ lp.invrad = inverserad;
+ lp.invret = inverseret;
+ lp.invshar = inversesha;
+ lp.str = str;
+ lp.shrad = sharradius;
+ lp.senssha = local_sensisha;
+ lp.shamo = local_sharamount;
+ lp.shdamp = local_shardamping;
+ lp.shiter = local_shariter;
+ lp.dxx = local_dxx;
+ lp.dyy = h * local_dyy;
+ lp.thr = thre;
+ lp.noiself = local_noiself;
+ lp.noiselc = local_noiselc;
+ lp.noisecf = local_noisecf;
+ lp.noisecc = local_noisecc;
+
+
+ lp.strengt = streng;
+ lp.gamm = gam;
+ lp.esto = est;
+ lp.scalt = scal_tm;
+ lp.rewe = rewe;
+ lp.senstm = local_sensitm;
+
+ for (int y = 0; y < 5; y++) {
+ lp.mulloc[y] = multi[y];
+ }
+
+ lp.threshol = thresho;
+ lp.colorena = locallab.expcolor;
+ lp.blurena = locallab.expblur;
+ lp.tonemapena = locallab.exptonemap;
+ lp.retiena = locallab.expreti;
+ lp.sharpena = locallab.expsharp;
+ lp.cbdlena = locallab.expcbdl;
+ lp.denoiena = locallab.expdenoi;
+
+}
+
+inline static float calcLocalFactor (const float lox, const float loy, const float lcx, const float dx, const float lcy, const float dy, const float ach)
+{
+//elipse x2/a2 + y2/b2=1
+//transition elipsoidal
+//x==>lox y==>loy
+// a==> dx b==>dy
+
+ float kelip = dx / dy;
+ float belip = sqrt ((SQR ((lox - lcx) / kelip) + SQR (loy - lcy))); //determine position ellipse ==> a and b
+ float aelip = belip * kelip;
+ float degrad = aelip / dx;
+ float ap = M_PI / (1.f - ach);
+ float bp = M_PI - ap;
+ return 0.5f * (1.f + xcosf (degrad * ap + bp)); //trigo cos transition
+
+}
+
+
+static void calcTransition (const float lox, const float loy, const float ach, const local_params& lp, int &zone, float &localFactor)
+{
+ // returns the zone (0 = outside selection, 1 = transition zone between outside and inside selection, 2 = inside selection)
+ // and a factor to calculate the transition in case zone == 1
+
+ zone = 0;
+
+ if (lox >= lp.xc && lox < (lp.xc + lp.lx) && loy >= lp.yc && loy < lp.yc + lp.ly) {
+ zone = ( (SQR (lox - lp.xc) / SQR (ach * lp.lx) + SQR (loy - lp.yc) / SQR (ach * lp.ly)) < 1.f) ? 2 : 0;
+
+ if (!zone) {
+ zone = (((SQR (lox - lp.xc) / SQR (ach * lp.lx) + SQR (loy - lp.yc) / SQR (ach * lp.ly)) > 1.f) && ((SQR (lox - lp.xc) / SQR (lp.lx) + SQR (loy - lp.yc) / SQR (lp.ly)) < 1.f)) ? 1 : 0;
+
+ if (zone) {
+ localFactor = calcLocalFactor (lox, loy, lp.xc, lp.lx, lp.yc, lp.ly, ach);
+ }
+ }
+ } else if (lox >= lp.xc && lox < lp.xc + lp.lx && loy < lp.yc && loy > lp.yc - lp.lyT) {
+ zone = (SQR (lox - lp.xc) / SQR (ach * lp.lx) + SQR (loy - lp.yc) / SQR (ach * lp.lyT)) < 1.f ? 2 : 0;
+
+ if (!zone) {
+ zone = (((SQR (lox - lp.xc) / SQR (ach * lp.lx) + SQR (loy - lp.yc) / SQR (ach * lp.lyT)) > 1.f) && ((SQR (lox - lp.xc) / SQR (lp.lx) + SQR (loy - lp.yc) / SQR (lp.lyT)) < 1.f)) ? 1 : 0;
+
+ if (zone) {
+ localFactor = calcLocalFactor (lox, loy, lp.xc, lp.lx, lp.yc, lp.lyT, ach);
+ }
+ }
+ } else if (lox < lp.xc && lox > lp.xc - lp.lxL && loy <= lp.yc && loy > lp.yc - lp.lyT) {
+ zone = (SQR (lox - lp.xc) / SQR (ach * lp.lxL) + SQR (loy - lp.yc) / SQR (ach * lp.lyT)) < 1.f ? 2 : 0;
+
+ if (!zone) {
+ zone = (((SQR (lox - lp.xc) / SQR (ach * lp.lxL) + SQR (loy - lp.yc) / SQR (ach * lp.lyT)) > 1.f) && ((SQR (lox - lp.xc) / SQR (lp.lxL) + SQR (loy - lp.yc) / SQR (lp.lyT)) < 1.f)) ? 1 : 0;
+
+ if (zone) {
+ localFactor = calcLocalFactor (lox, loy, lp.xc, lp.lxL, lp.yc, lp.lyT, ach);
+ }
+ }
+ } else if (lox < lp.xc && lox > lp.xc - lp.lxL && loy > lp.yc && loy < lp.yc + lp.ly) {
+ zone = (SQR (lox - lp.xc) / SQR (ach * lp.lxL) + SQR (loy - lp.yc) / SQR (ach * lp.ly)) < 1.f ? 2 : 0;
+
+ if (!zone) {
+ zone = (((SQR (lox - lp.xc) / SQR (ach * lp.lxL) + SQR (loy - lp.yc) / SQR (ach * lp.ly)) > 1.f) && ((SQR (lox - lp.xc) / SQR (lp.lxL) + SQR (loy - lp.yc) / SQR (lp.ly)) < 1.f)) ? 1 : 0;
+
+ if (zone) {
+ localFactor = calcLocalFactor (lox, loy, lp.xc, lp.lxL, lp.yc, lp.ly, ach);
+ }
+ }
+ }
+}
+
+void ImProcFunctions::strcurv_data (std::string retistr, int *s_datc, int &siz)
+{
+ std::string delim[69] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
+ "&", "#", "{", "[", "]", "}", "$", "*", "?", ">", "!", ";", "<", "(", ")", "+", "-"
+ };
+
+ int s_size;
+ std::size_t posend = retistr.find ("@");
+
+ std::string strend = retistr.substr (posend - 1, 1);
+ // printf("stren=%s posz=%i\n", strend.c_str(), posz);
+ int longe;
+
+ for (int sl = 0; sl < 69; sl++) {
+ if (delim[sl] == strend) {
+ longe = sl + 1;
+ }
+ }
+
+ s_size = longe;
+
+ // printf("sp=%i stren=%s reti=%s long=%i\n", sp, strend.c_str(), retistr[sp].c_str(), longe);
+
+ int s_cur[s_size + 1];
+ int s_datcu[s_size + 1];
+
+ std::size_t pose[s_size + 1];
+ std::size_t valstr[s_size + 1];
+ pose[0] = -1;
+
+ for (int z = 1; z < s_size + 1; z++) {
+ pose[z] = retistr.find (delim[z - 1]);
+ }
+
+
+ for (int z = 1; z < s_size + 1; z++) {
+ std::string sval = retistr.substr (pose[z - 1] + 1, (pose[z] - pose[z - 1]));
+ s_datc[z - 1] = s_datcu[z - 1] = std::stoi (sval.c_str());
+
+ }
+
+ /*
+ //here to verify process is good
+ std::string cur_str = "";
+
+ for(int j = 0; j < s_size; j++) {
+ cur_str = cur_str + std::to_string(s_datcu[j]) + delim[j];
+ }
+ printf("calc str=%s\n", cur_str.c_str());
+ */
+ siz = longe;
+
+}
+
+
+
+void ImProcFunctions::addGaNoise (LabImage *lab, LabImage *dst, const float mean, const float variance, const int sk)
+{
+// BENCHFUN
+//Box-Muller method.
+// add luma noise to image
+
+ srand (1);
+
+ const float variaFactor = SQR (variance) / sk;
+ const float randFactor = 1.f / RAND_MAX;
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ float z0, z1;
+ bool generate = false;
+#ifdef _OPENMP
+ #pragma omp for schedule(static) // static scheduling is important to avoid artefacts
+#endif
+
+ for (int y = 0; y < lab->H; y++) {
+ for (int x = 0; x < lab->W; x++) {
+ generate = !generate;
+ float kvar = 1.f;
+
+ if (lab->L[y][x] < 12000.f) {
+ constexpr float ah = -0.5f / 12000.f;
+ constexpr float bh = 1.5f;
+ kvar = ah * lab->L[y][x] + bh; //increase effect for low lights < 12000.f
+ } else if (lab->L[y][x] > 20000.f) {
+ constexpr float ah = -0.5f / 12768.f;
+ constexpr float bh = 1.f - 20000.f * ah;
+ kvar = ah * lab->L[y][x] + bh; //decrease effect for high lights > 20000.f
+ kvar = kvar < 0.5f ? 0.5f : kvar;
+ }
+
+ float varia = SQR (kvar) * variaFactor;
+
+ if (!generate) {
+ dst->L[y][x] = LIM (lab->L[y][x] + mean + varia * z1, 0.f, 32768.f);
+ continue;
+ }
+
+ int u1 = 0;
+ int u2;
+
+ while (u1 == 0) {
+ u1 = rand();
+ u2 = rand();
+ }
+
+ float u1f = u1 * randFactor;
+ float u2f = u2 * randFactor;
+
+ float2 sincosval = xsincosf (2.f * M_PI * u2f);
+ float factor = sqrtf (-2.f * xlogf (u1f));
+ z0 = factor * sincosval.y;
+ z1 = factor * sincosval.x;
+
+ dst->L[y][x] = LIM (lab->L[y][x] + mean + varia * z0, 0.f, 32768.f);
+
+ }
+ }
+ }
+}
+
+void ImProcFunctions::DeNoise_Local (int call, const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy)
+{
+ // local denoise
+ // BENCHFUN
+ const float ach = (float)lp.trans / 100.f;
+
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+
+ for (int y = 0; y < transformed->H; y++) {
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+
+ int zone;
+ float localFactor;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float factorx = localFactor;
+ float difL, difa, difb;
+
+ if (call == 2) { //simpleprocess
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difL = tmp1->L[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ difa = tmp1->a[loy - begy - 1][lox - begx - 1] - original->a[y][x];
+ difb = tmp1->b[loy - begy - 1][lox - begx - 1] - original->b[y][x];
+ }
+ } else if (call == 1) { //dcrop
+ difL = tmp1->L[y][x] - original->L[y][x];
+ difa = tmp1->a[y][x] - original->a[y][x];
+ difb = tmp1->b[y][x] - original->b[y][x];
+
+ }
+
+ difL *= factorx;
+ difa *= factorx;
+ difb *= factorx;
+ transformed->L[y][x] = original->L[y][x] + difL;
+ transformed->a[y][x] = original->a[y][x] + difa;
+ transformed->b[y][x] = original->b[y][x] + difb;
+ break;
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ float difL, difa, difb;
+
+ if (call == 2) { //simpleprocess
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difL = tmp1->L[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ difa = tmp1->a[loy - begy - 1][lox - begx - 1] - original->a[y][x];
+ difb = tmp1->b[loy - begy - 1][lox - begx - 1] - original->b[y][x];
+ }
+ } else if (call == 1) { //dcrop
+ difL = tmp1->L[y][x] - original->L[y][x];
+ difa = tmp1->a[y][x] - original->a[y][x];
+ difb = tmp1->b[y][x] - original->b[y][x];
+
+ }
+
+ transformed->L[y][x] = original->L[y][x] + difL;
+ transformed->a[y][x] = original->a[y][x] + difa;
+ transformed->b[y][x] = original->b[y][x] + difb;
+ }
+ }
+ }
+ }
+
+
+
+}
+
+
+void ImProcFunctions::cbdl_Local (int call, int sp, float **loctemp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params & lp, float **deltE, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+//local CBDL
+ // BENCHFUN
+ const float localtype = lumaref; // always spot area
+ const float ach = (float)lp.trans / 100.f;
+ float reducac;
+
+ //constant and variable to prepare shape detection
+ if (lp.senscb < 30.f) {
+ reducac = 0.2f * (lp.senscb / 100.f);
+ } else {
+ float areduc = 0.6285714f; //0.44f/0.7f;
+ float breduc = 0.5f - areduc;
+ reducac = areduc * (lp.senscb / 100.f) + breduc;
+ }
+
+
+ constexpr float delhu = 0.1f; //between 0.05 and 0.2
+
+ const float apl = (-1.f) / delhu;
+ const float bpl = - apl * hueplus;
+ const float amo = 1.f / delhu;
+ const float bmo = - amo * huemoins;
+
+
+ const float pb = 4.f;
+ const float pa = (1.f - pb) / 40.f;
+
+ const float ahu = 1.f / (2.8f * lp.senscb - 280.f);
+ const float bhu = 1.f - ahu * 2.8f * lp.senscb;
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++) {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+ int zone;
+ float localFactor = 1.f;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ //prepare shape detection
+ float khu = 0.f;
+ float kch = 1.f;
+ bool kzon = false;
+ float fach = 1.f;
+ float deltachro = fabs (rchro - chromaref);
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280
+
+ //kch to modulate action with chroma
+ if (deltachro < 160.f * SQR (lp.senscb / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.senscb / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.senscb < 40.f ) {
+ kch = pow (kch, pa * lp.senscb + pb); //increase under 40
+ }
+
+
+ // algo with detection of hue ==> artifacts for noisy images ==> denoise before
+ if (lp.senscb < 20.f) { //to try...
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu ) {
+ khu = apl * rhue + bpl;
+ } else if (rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins ) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if (deltaE < 2.8f * lp.senscb) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ if (lp.qualmet == 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ //fach = khu ;
+
+ } else {
+ /*
+ float kcr = 8.f;
+ if(lp.senssha > 30.f){
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr)) * rchro;
+
+ }
+ }
+ */
+ }
+
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float factorx = localFactor;
+ float difL;
+
+ if (call == 2) {
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difL = loctemp[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ }
+ } else if (call == 1) {
+ difL = loctemp[y][x] - original->L[y][x];
+
+ }
+
+ //float difL = loctemp[y][x] - original->L[y][x];
+ difL *= factorx;
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+
+ break;
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ // float difL = loctemp[y][x] - original->L[y][x];
+ float difL;
+
+ if (call == 2) {
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ // bufsh[loy - begy - 1][lox - begx - 1]
+ difL = loctemp[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ }
+ } else if (call == 1) {
+ difL = loctemp[y][x] - original->L[y][x];
+ }
+
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void ImProcFunctions::TM_Local (int call, int sp, LabImage * tmp1, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params & lp, float **deltE, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+//local TM
+ // BENCHFUN
+ const float localtype = lumaref; // always spot area
+ const float ach = (float)lp.trans / 100.f;
+ float reducac;
+
+ //constant and variable to prepare shape detection
+ if (lp.senstm < 30.f) {
+ reducac = 0.2f * (lp.senstm / 100.f);
+ } else {
+ float areduc = 0.6285714f; //0.44f/0.7f;
+ float breduc = 0.5f - areduc;
+ reducac = areduc * (lp.senstm / 100.f) + breduc;
+ }
+
+
+ constexpr float delhu = 0.1f; //between 0.05 and 0.2
+
+ const float apl = (-1.f) / delhu;
+ const float bpl = - apl * hueplus;
+ const float amo = 1.f / delhu;
+ const float bmo = - amo * huemoins;
+
+
+ const float pb = 4.f;
+ const float pa = (1.f - pb) / 40.f;
+
+ const float ahu = 1.f / (2.8f * lp.senstm - 280.f);
+ const float bhu = 1.f - ahu * 2.8f * lp.senstm;
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++) {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+ int zone;
+ float localFactor = 1.f;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ //prepare shape detection
+ float khu = 0.f;
+ float kch = 1.f;
+ bool kzon = false;
+ float fach = 1.f;
+ float deltachro = fabs (rchro - chromaref);
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280
+
+ //kch to modulate action with chroma
+ if (deltachro < 160.f * SQR (lp.senstm / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.senstm / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.senstm < 40.f ) {
+ kch = pow (kch, pa * lp.senstm + pb); //increase under 40
+ }
+
+
+ // algo with detection of hue ==> artifacts for noisy images ==> denoise before
+ if (lp.senstm < 20.f) { //to try...
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu ) {
+ khu = apl * rhue + bpl;
+ } else if (rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins ) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if (deltaE < 2.8f * lp.senstm) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ if (lp.qualmet == 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ //fach = khu ;
+
+ } else {
+ }
+
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+
+ if (!lp.actsp) {
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ }
+
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float factorx = localFactor;
+ float difL, difa, difb;
+
+ if (call == 2) {
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difL = tmp1->L[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ difa = tmp1->a[loy - begy - 1][lox - begx - 1] - original->a[y][x];
+ difb = tmp1->b[loy - begy - 1][lox - begx - 1] - original->b[y][x];
+
+ }
+ } else {
+ difL = tmp1->L[y][x] - original->L[y][x];
+ difa = tmp1->a[y][x] - original->a[y][x];
+ difb = tmp1->b[y][x] - original->b[y][x];
+
+
+ }
+
+ difL *= factorx;
+ difa *= factorx;
+ difb *= factorx;
+
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+
+
+ transformed->a[y][x] = original->a[y][x] + difa * kch * fach;//same as Luma
+ transformed->b[y][x] = original->b[y][x] + difb * kch * fach;//same as Luma
+
+ break;
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ float difL, difa, difb;
+
+ if (call == 2) {
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ // bufsh[loy - begy - 1][lox - begx - 1]
+ difL = tmp1->L[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ difa = tmp1->a[loy - begy - 1][lox - begx - 1] - original->a[y][x];
+ difb = tmp1->b[loy - begy - 1][lox - begx - 1] - original->b[y][x];
+
+ }
+ } else {
+ difL = tmp1->L[y][x] - original->L[y][x];
+ difa = tmp1->a[y][x] - original->a[y][x];
+ difb = tmp1->b[y][x] - original->b[y][x];
+
+ }
+
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+
+
+ transformed->a[y][x] = original->a[y][x] + difa * kch * fach;//same as Luma
+ transformed->b[y][x] = original->b[y][x] + difb * kch * fach;//same as Luma
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+
+void ImProcFunctions::BlurNoise_Local (int call, int sp, LabImage * tmp1, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params & lp, float **deltE, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+//local BLUR
+ // BENCHFUN
+ const float localtype = lumaref; // always spot area
+ const float ach = (float)lp.trans / 100.f;
+ float reducac;
+
+ //constant and variable to prepare shape detection
+ if (lp.sensbn < 30.f) {
+ reducac = 0.2f * (lp.sensbn / 100.f);
+ } else {
+ float areduc = 0.6285714f; //0.44f/0.7f;
+ float breduc = 0.5f - areduc;
+ reducac = areduc * (lp.sensbn / 100.f) + breduc;
+ }
+
+
+ constexpr float delhu = 0.1f; //between 0.05 and 0.2
+
+ const float apl = (-1.f) / delhu;
+ const float bpl = - apl * hueplus;
+ const float amo = 1.f / delhu;
+ const float bmo = - amo * huemoins;
+
+
+ const float pb = 4.f;
+ const float pa = (1.f - pb) / 40.f;
+
+ const float ahu = 1.f / (2.8f * lp.sensbn - 280.f);
+ const float bhu = 1.f - ahu * 2.8f * lp.sensbn;
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++) {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+ int zone;
+ float localFactor = 1.f;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ //prepare shape detection
+ float khu = 0.f;
+ float kch = 1.f;
+ bool kzon = false;
+ float fach = 1.f;
+ float deltachro = fabs (rchro - chromaref);
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280
+
+ //kch to modulate action with chroma
+ if (deltachro < 160.f * SQR (lp.sensbn / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.sensbn / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.sensbn < 40.f ) {
+ kch = pow (kch, pa * lp.sensbn + pb); //increase under 40
+ }
+
+
+ // algo with detection of hue ==> artifacts for noisy images ==> denoise before
+ if (lp.sensbn < 20.f) { //to try...
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu ) {
+ khu = apl * rhue + bpl;
+ } else if (rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins ) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if (deltaE < 2.8f * lp.sensbn) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ if (lp.qualmet == 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ //fach = khu ;
+
+ } else {
+ }
+
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+
+ if (!lp.actsp) {
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ }
+
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float factorx = localFactor;
+ float difL, difa, difb;
+
+ if (call == 2) {
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difL = tmp1->L[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ difa = tmp1->a[loy - begy - 1][lox - begx - 1] - original->a[y][x];
+ difb = tmp1->b[loy - begy - 1][lox - begx - 1] - original->b[y][x];
+
+ }
+ } else {
+ difL = tmp1->L[y][x] - original->L[y][x];
+ difa = tmp1->a[y][x] - original->a[y][x];
+ difb = tmp1->b[y][x] - original->b[y][x];
+
+
+ }
+
+ difL *= factorx;
+ difa *= factorx;
+ difb *= factorx;
+
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+
+ if (!lp.actsp) {
+
+ transformed->a[y][x] = original->a[y][x] + difa * kch * fach;//same as Luma
+ transformed->b[y][x] = original->b[y][x] + difb * kch * fach;//same as Luma
+ }
+
+ break;
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ float difL, difa, difb;
+
+ if (call == 2) {
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ // bufsh[loy - begy - 1][lox - begx - 1]
+ difL = tmp1->L[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ difa = tmp1->a[loy - begy - 1][lox - begx - 1] - original->a[y][x];
+ difb = tmp1->b[loy - begy - 1][lox - begx - 1] - original->b[y][x];
+
+ }
+ } else {
+ difL = tmp1->L[y][x] - original->L[y][x];
+ difa = tmp1->a[y][x] - original->a[y][x];
+ difb = tmp1->b[y][x] - original->b[y][x];
+
+ }
+
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+
+ if (!lp.actsp) {
+
+ transformed->a[y][x] = original->a[y][x] + difa * kch * fach;//same as Luma
+ transformed->b[y][x] = original->b[y][x] + difb * kch * fach;//same as Luma
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void ImProcFunctions::InverseReti_Local (const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int chro)
+{
+ // BENCHFUN
+//inverse local retinex
+ float ach = (float)lp.trans / 100.f;
+
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+
+ for (int y = 0; y < transformed->H; y++) {
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+
+ int zone;
+ float localFactor;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => full effect, no transition
+ if (chro == 0) {
+ transformed->L[y][x] = tmp1->L[y][x];
+ }
+
+ if (chro == 1) {
+
+ transformed->a[y][x] = tmp1->a[y][x];
+ transformed->b[y][x] = tmp1->b[y][x];
+ }
+
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float factorx = 1.f - localFactor;
+
+ if (chro == 0) {
+ float difL = tmp1->L[y][x] - original->L[y][x];
+ difL *= factorx;
+ transformed->L[y][x] = original->L[y][x] + difL;
+ }
+
+ if (chro == 1) {
+ float difa = tmp1->a[y][x] - original->a[y][x];
+ float difb = tmp1->b[y][x] - original->b[y][x];
+
+ difa *= factorx;
+ difb *= factorx;
+
+ transformed->a[y][x] = original->a[y][x] + difa;
+ transformed->b[y][x] = original->b[y][x] + difb;
+ }
+
+ break;
+ }
+
+ case 2: { // inside selection => no effect, keep original values
+ if (chro == 0) {
+ transformed->L[y][x] = original->L[y][x];
+ }
+
+ if (chro == 1) {
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+void ImProcFunctions::Reti_Local (int call, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const struct local_params& lp, float **deltE, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int chro)
+{
+
+//local retinex
+ //BENCHFUN
+ {
+ const float ach = (float)lp.trans / 100.f;
+
+ //chroma
+ constexpr float amplchsens = 2.5f;
+ constexpr float achsens = (amplchsens - 1.f) / (100.f - 20.f); //20. default locallab.sensih
+ constexpr float bchsens = 1.f - 20.f * achsens;
+ const float multchro = lp.sensh * achsens + bchsens;
+
+ //luma
+ constexpr float ampllumsens = 2.f;
+ constexpr float alumsens = (ampllumsens - 1.f) / (100.f - 20.f); //20. default locallab.sensih
+ constexpr float blumsens = 1.f - 20.f * alumsens;
+ const float multlum = lp.sensh * alumsens + blumsens;
+
+ //skin
+ constexpr float amplchsensskin = 1.6f;
+ constexpr float achsensskin = (amplchsensskin - 1.f) / (100.f - 20.f); //20. default locallab.sensih
+ constexpr float bchsensskin = 1.f - 20.f * achsensskin;
+ const float multchroskin = lp.sensh * achsensskin + bchsensskin;
+
+ //transition = difficult to avoid artifact with scope on flat area (sky...)
+ float strn = lp.str / 1.f; // we can chnage 1.f by 2 or...to chnage effect
+
+ constexpr float delhu = 0.1f; //between 0.05 and 0.2
+ const float aplus = (1.f - strn) / delhu;
+ const float bplus = 1.f - aplus * hueplus;
+ const float amoins = (strn - 1.f) / delhu;
+ const float bmoins = 1.f - amoins * huemoins;
+
+ const float apl = (-1.f) / delhu;
+ const float bpl = - apl * hueplus;
+ const float amo = 1.f / delhu;
+ const float bmo = - amo * huemoins;
+
+
+ const float pb = 4.f;
+ const float pa = (1.f - pb) / 40.f;
+
+ const float ahu = 1.f / (2.8f * lp.sensh - 280.f);
+ const float bhu = 1.f - ahu * 2.8f * lp.sensh;
+
+ const float alum = 1.f / (lp.sensh - 100.f);
+ const float blum = 1.f - alum * lp.sensh;
+
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++) {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+ float rL = original->L[y][x] / 327.68f;
+ float eps = 0.f;
+
+ if (fabs (original->b[y][x]) < 0.001f) {
+ eps = 0.01f;
+ }
+
+ float kab = original->a[y][x] / (original->b[y][x] + eps);
+
+ float realstr = 1.f;
+ float realstrch = 1.f;
+ //prepare shape detection
+ float deltachro = fabs (rchro - chromaref);
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //between 0 and 280
+ float deltaL = fabs (lumaref - rL); //between 0 and 100
+
+ float kch = 1.f;
+ float khu = 0.f;
+ float fach = 1.f;
+ float falu = 1.f;
+
+ if (deltachro < 160.f * SQR (lp.sensh / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.sensh / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.sensh < 40.f ) {
+ kch = pow (kch, pa * lp.sensh + pb); //increase under 40
+ }
+
+ bool kzon = false;
+
+ //transition = difficult to avoid artifact with scope on flat area (sky...)
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu) {
+ realstr = aplus * rhue + bplus;
+ khu = apl * rhue + bpl;
+
+ } else if (rhue < huemoins + delhu) {
+ realstr = amoins * rhue + bmoins;
+ khu = amo * rhue + bmo;
+
+ } else {
+ realstr = strn;
+ khu = 1.f;
+
+ }
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ realstr = aplus * rhue + bplus;
+ khu = apl * rhue + bpl;
+
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ realstr = amoins * rhue + bmoins;
+ khu = amo * rhue + bmo;
+
+ } else {
+ realstr = strn;
+ khu = 1.f;
+
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ realstr = aplus * rhue + bplus;
+ khu = apl * rhue + bpl;
+
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ realstr = amoins * rhue + bmoins;
+ khu = amo * rhue + bmo;
+
+ } else {
+ realstr = strn;
+ khu = 1.f;
+
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ realstr = aplus * rhue + bplus;
+ khu = apl * rhue + bpl;
+
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ realstr = amoins * rhue + bmoins;
+ khu = amo * rhue + bmo;
+
+ } else {
+ realstr = strn;
+ khu = 1.f;
+
+ }
+
+ kzon = true;
+ }
+
+ //shape detection for hue chroma and luma
+ if (lp.sensh <= 20.f) { //to try...
+
+ if (deltaE < 2.8f * lp.sensh) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ if (lp.qualmet >= 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ if (deltaL < lp.sensh) {
+ falu = 1.f;
+ } else {
+ falu = alum * deltaL + blum;
+ }
+
+ }
+
+
+ // float kdiff = 0.f;
+ // I add these functions...perhaps not good
+ if (kzon) {
+ if (lp.sensh < 60.f) { //arbitrary value
+ if (hueref < -1.1f && hueref > -2.8f) { // detect blue sky
+ if (chromaref > 0.f && chromaref < 35.f * multchro) { // detect blue sky
+ if ( (rhue > -2.79f && rhue < -1.11f) && (rchro < 35.f * multchro)) {
+ realstr *= 0.9f;
+ } else {
+ realstr = 1.f;
+ }
+ }
+ } else {
+ realstr = strn;
+ }
+
+ if (lp.sensh < 50.f) { //&& lp.chro > 0.f
+ if (hueref > -0.1f && hueref < 1.6f) { // detect skin
+ if (chromaref > 0.f && chromaref < 55.f * multchroskin) { // detect skin
+ if ( (rhue > -0.09f && rhue < 1.59f) && (rchro < 55.f * multchroskin)) {
+ realstr *= 0.7f;
+ } else {
+ realstr = 1.f;
+ }
+ }
+ } else {
+ realstr = strn;
+ }
+ }
+ }
+
+ }
+
+ int zone;
+ float localFactor;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (rL > 0.1f) { //to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ if (chro == 0) {
+ transformed->L[y][x] = original->L[y][x];
+ }
+
+ if (chro == 1) {
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ }
+
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float factorx = localFactor;
+
+ if (chro == 0) {
+ float difL;
+
+ if (call <= 3) {
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difL = tmp1->L[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ difL *= factorx * (100.f + realstr * (1.f - factorx)) / 100.f;
+ difL *= kch * fach;
+
+ transformed->L[y][x] = original->L[y][x] + difL;
+ }
+ } else {
+ difL = (tmp1->L[y][x]) - original->L[y][x];
+ difL *= factorx * (100.f + realstr * (1.f - factorx)) / 100.f;
+ difL *= kch * fach;
+ transformed->L[y][x] = original->L[y][x] + difL;
+ }
+ }
+
+ if (chro == 1) {
+ float difa, difb;
+
+ if (call <= 3) {
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difa = tmp1->a[loy - begy - 1][lox - begx - 1] - original->a[y][x];
+ difb = tmp1->b[loy - begy - 1][lox - begx - 1] - original->b[y][x];
+ difa *= factorx * (100.f + realstr * falu * (1.f - factorx)) / 100.f;
+ difb *= factorx * (100.f + realstr * falu * (1.f - factorx)) / 100.f;
+ transformed->a[y][x] = CLIPC (original->a[y][x] + difa);
+ transformed->b[y][x] = CLIPC (original->b[y][x] + difb);
+ }
+
+ } else {
+ difa = tmp1->a[y][x] - original->a[y][x];
+ difb = tmp1->b[y][x] - original->b[y][x];
+ difa *= factorx * (100.f + realstr * falu * (1.f - factorx)) / 100.f;
+ difb *= factorx * (100.f + realstr * falu * (1.f - factorx)) / 100.f;
+ transformed->a[y][x] = CLIPC (original->a[y][x] + difa);
+ transformed->b[y][x] = CLIPC (original->b[y][x] + difb);
+ }
+ }
+
+ break;
+
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ if (chro == 0) {
+ float difL;
+
+ if (call <= 3) {
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difL = tmp1->L[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ difL *= (100.f + realstr) / 100.f;
+ difL *= kch * fach;
+ transformed->L[y][x] = original->L[y][x] + difL;
+ }
+
+ } else {
+ difL = tmp1->L[y][x] - original->L[y][x];
+ difL *= (100.f + realstr) / 100.f;
+ difL *= kch * fach;
+ transformed->L[y][x] = original->L[y][x] + difL;
+ }
+ }
+
+ if (chro == 1) {
+ float difa, difb;
+
+ if (call <= 3) {
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difa = tmp1->a[loy - begy - 1][lox - begx - 1] - original->a[y][x];
+ difb = tmp1->b[loy - begy - 1][lox - begx - 1] - original->b[y][x];
+ difa *= (100.f + realstr * falu) / 100.f;
+ difb *= (100.f + realstr * falu) / 100.f;
+ transformed->a[y][x] = CLIPC (original->a[y][x] + difa);
+ transformed->b[y][x] = CLIPC (original->b[y][x] + difb);
+ }
+ } else {
+ difa = tmp1->a[y][x] - original->a[y][x];
+ difb = tmp1->b[y][x] - original->b[y][x];
+ difa *= (100.f + realstr * falu) / 100.f;
+ difb *= (100.f + realstr * falu) / 100.f;
+ transformed->a[y][x] = CLIPC (original->a[y][x] + difa);
+ transformed->b[y][x] = CLIPC (original->b[y][x] + difb);
+ }
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+}
+
+void ImProcFunctions::InverseBlurNoise_Local (const struct local_params & lp, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy)
+{
+ // BENCHFUN
+//inverse local blur and noise
+ float ach = (float)lp.trans / 100.f;
+
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+
+ for (int y = 0; y < transformed->H; y++) {
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+
+ int zone;
+ float localFactor;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => full effect, no transition
+ transformed->L[y][x] = tmp1->L[y][x];
+
+ if (!lp.actsp) {
+ transformed->a[y][x] = tmp1->a[y][x];
+ transformed->b[y][x] = tmp1->b[y][x];
+ }
+
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float difL = tmp1->L[y][x] - original->L[y][x];
+ float difa = tmp1->a[y][x] - original->a[y][x];
+ float difb = tmp1->b[y][x] - original->b[y][x];
+
+ float factorx = 1.f - localFactor;
+ difL *= factorx;
+ difa *= factorx;
+ difb *= factorx;
+
+ transformed->L[y][x] = original->L[y][x] + difL;
+
+ if (!lp.actsp) {
+
+ transformed->a[y][x] = original->a[y][x] + difa;
+ transformed->b[y][x] = original->b[y][x] + difb;
+ }
+
+ break;
+ }
+
+ case 2: { // inside selection => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+
+ if (!lp.actsp) {
+
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ }
+ }
+ }
+ }
+ }
+}
+
+struct local_contra {
+ float alsup, blsup;
+ float alsup2, blsup2;
+ float alsup3, blsup3;
+ float alinf;
+ float aDY;
+ float aa;
+ float bb;
+ float aaa, bbb;
+ float ccc;
+// float DY;
+ float dx, dy;
+ float ah, bh;
+ float al, bl;
+};
+
+void ImProcFunctions::Contrast_Local (int call, float moy, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, float pm, struct local_contra & lco, float lumaref, float av, const struct local_params & lp, float **deltE, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+ // BENCHFUN
+// contrast - perhaps for 4 areas if need
+// I tried shmap adaptaed to Lab, but no real gain and artifacts
+ const float localtype = lumaref; // always spot area
+ const float ach = (float)lp.trans / 100.f;
+ float reducac;
+
+ //constant and variable to prepare shape detection
+ if (lp.sens < 30.f) {
+ reducac = 0.2f * (lp.sens / 100.f);
+ } else {
+ float areduc = 0.6285714f; //0.44f/0.7f;
+ float breduc = 0.5f - areduc;
+ reducac = areduc * (lp.sens / 100.f) + breduc;
+ }
+
+ const float realcox = lco.dx, realcoy = lco.dy;
+
+ lco.alsup = (-realcox) / (localtype / 2.f);
+ lco.blsup = -lco.alsup * localtype;
+ lco.alsup2 = (realcoy) / (50.f - localtype / 2.f);
+ lco.blsup2 = -lco.alsup2 * localtype;
+ lco.alsup3 = (realcoy) / (localtype / 2.f - 50.f);
+ lco.blsup3 = -lco.alsup3 * 100.f;
+ lco.aDY = realcoy;
+
+
+
+ constexpr float delhu = 0.1f; //between 0.05 and 0.2
+
+ const float apl = (-1.f) / delhu;
+ const float bpl = - apl * hueplus;
+ const float amo = 1.f / delhu;
+ const float bmo = - amo * huemoins;
+
+
+ const float pb = 4.f;
+ const float pa = (1.f - pb) / 40.f;
+
+ const float ahu = 1.f / (2.8f * lp.sens - 280.f);
+ const float bhu = 1.f - ahu * 2.8f * lp.sens;
+
+ lco.alinf = realcox / (localtype / 2.f);
+ const float vi = (localtype / 2.f) / 100.f;
+ const float vinf = (50.f + localtype / 2.f) / 100.f;
+ ImProcFunctions::secondeg_begin (reducac, vi, lco.aa, lco.bb);//parabolic
+ ImProcFunctions::secondeg_end (reducac, vinf, lco.aaa, lco.bbb, lco.ccc);//parabolic
+
+ if (call == 2) {
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+ //Todo optimization in this first part with something equivalent to bufcolorig and bufcoltra in colorlight_local
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++)
+ {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+ int zone;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ float localFactor = 1.f;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ //prepare shape detection
+ float khu = 0.f;
+ float kch = 1.f;
+ bool kzon = false;
+ float fach = 1.f;
+ float deltachro = fabs (rchro - chromaref);
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280
+ float rL = original->L[y][x] / 327.68f;
+
+ //kch to modulate action with chroma
+ if (deltachro < 160.f * SQR (lp.sens / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.sens / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.sens < 40.f ) {
+ kch = pow (kch, pa * lp.sens + pb); //increase under 40
+ }
+
+
+ // algo with detection of hue ==> artifacts for noisy images ==> denoise before
+ if (lp.sens < 20.f) { //to try...
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu ) {
+ khu = apl * rhue + bpl;
+ } else if (rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins ) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if (deltaE < 2.8f * lp.sens) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ if (lp.qualmet >= 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ //fach = khu ;
+
+ } else {
+ /*
+ float kcr = 8.f;
+ if(lp.sensh > 30.f){
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr)) * rchro;
+
+ }
+ }
+ */
+ }
+
+ if (rL > 0.01f) { //to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ break;
+ }
+
+ case 1: { // inside transition zone
+ if (original->L[y][x] < 32768.f) {
+ float factorx = localFactor;
+ float prov100 = original->L[y][x] / 32768.f;
+ float prov = prov100 * 100.f;
+ bool contin = true;
+
+
+ if (contin) {
+
+ if (prov > localtype) {
+ if (prov >= localtype && prov < 50.f + localtype / 2.f) {
+ float core = (lco.alsup2 * prov + lco.blsup2) ;
+ core *= factorx;
+
+ transformed->L[y][x] = 327.68f * (prov + pm * (prov - localtype) * (core) * kch * fach);
+ } else {
+ float core = lco.aDY * (lco.aaa * prov100 * prov100 + lco.bbb * prov100 + lco.ccc);
+
+ core *= factorx;
+ transformed->L[y][x] = 327.68f * (prov + pm * (prov - localtype) * (core) * kch * fach);
+ }
+ } else { //inferior
+ if (2.f * prov > localtype && prov < localtype) {
+ float core = (lco.alsup * prov + lco.blsup) ;
+ core *= factorx;
+ transformed->L[y][x] = 327.68f * (prov - pm * (localtype - prov) * core * kch * fach);
+ } else if (2.f * prov <= localtype) {
+ float core = prov * lco.alinf * (lco.aa * prov100 * prov100 + lco.bb * prov100);
+
+ core *= factorx;
+ transformed->L[y][x] = 327.68f * (prov - pm * (localtype - prov) * core * kch * fach);
+ }
+ }
+ }
+ } else {
+ transformed->L[y][x] = original->L[y][x];
+ }
+
+ break;
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ if (original->L[y][x] < 32768.f) {
+ float prov100 = original->L[y][x] / 32768.f;
+ float prov = prov100 * 100.f;
+
+ bool contin = true;
+
+ if (contin) {
+
+
+
+ if (prov > localtype ) {
+ if (prov >= localtype && prov < 50.f + localtype / 2.f) {
+ float core = (lco.alsup2 * prov + lco.blsup2) ;
+ transformed->L[y][x] = 327.68f * (prov + pm * (prov - localtype) * core * kch * fach);
+ } else {
+ float core = lco.aDY * (lco.aaa * prov100 * prov100 + lco.bbb * prov100 + lco.ccc);
+ transformed->L[y][x] = 327.68f * (prov + pm * (prov - localtype) * core * kch * fach);
+ }
+ } else { //inferior
+ if (2.f * prov > localtype && prov < localtype) {
+ float core = (lco.alsup * prov + lco.blsup) ;
+ transformed->L[y][x] = 327.68f * (prov - pm * (localtype - prov) * core * kch * fach);
+ } else if (2.f * prov <= localtype) {
+ float core = prov * lco.alinf * (lco.aa * prov100 * prov100 + lco.bb * prov100);
+ transformed->L[y][x] = 327.68f * (prov - pm * (localtype - prov) * core * kch * fach);
+ }
+ }
+ }
+ } else {
+ transformed->L[y][x] = original->L[y][x];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++)
+ {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+ int zone;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+ float localFactor = 1.f;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ //prepare shape detection
+ float khu = 0.f;
+ float kch = 1.f;
+ bool kzon = false;
+ float fach = 1.f;
+ float deltachro = fabs (rchro - chromaref);
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280
+ float rL = original->L[y][x] / 327.68f;
+
+ //kch to modulate action with chroma
+ if (deltachro < 160.f * SQR (lp.sens / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.sens / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.sens < 40.f ) {
+ kch = pow (kch, pa * lp.sens + pb); //increase under 40
+ }
+
+
+ // algo with detection of hue ==> artifacts for noisy images ==> denoise before
+ if (lp.sens < 20.f) { //to try...
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu ) {
+ khu = apl * rhue + bpl;
+ } else if (rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins ) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if (deltaE < 2.8f * lp.sens) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ if (lp.qualmet >= 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ //fach = khu ;
+
+ } else {
+ /*
+ float kcr = 8.f;
+ if(lp.sensh > 30.f){
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr)) * rchro;
+
+ }
+ }
+ */
+ }
+
+ if (rL > 0.01f) { //to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ break;
+ }
+
+ case 1: { // inside transition zone
+ if (original->L[y][x] < 32768.f) {
+ float factorx = localFactor;
+ float prov100 = original->L[y][x] / 32768.f;
+ float prov = prov100 * 100.f;
+ bool contin = true;
+
+
+ if (contin) {
+
+ if (prov > localtype) {
+ if (prov >= localtype && prov < 50.f + localtype / 2.f) {
+ float core = (lco.alsup2 * prov + lco.blsup2) ;
+ core *= factorx;
+
+ transformed->L[y][x] = 327.68f * (prov + pm * (prov - localtype) * (core) * kch * fach);
+ } else {
+ float core = lco.aDY * (lco.aaa * prov100 * prov100 + lco.bbb * prov100 + lco.ccc);
+
+ core *= factorx;
+ transformed->L[y][x] = 327.68f * (prov + pm * (prov - localtype) * (core) * kch * fach);
+ }
+ } else { //inferior
+ if (2.f * prov > localtype && prov < localtype) {
+ float core = (lco.alsup * prov + lco.blsup) ;
+ core *= factorx;
+ transformed->L[y][x] = 327.68f * (prov - pm * (localtype - prov) * core * kch * fach);
+ } else if (2.f * prov <= localtype) {
+ float core = prov * lco.alinf * (lco.aa * prov100 * prov100 + lco.bb * prov100);
+
+ core *= factorx;
+ transformed->L[y][x] = 327.68f * (prov - pm * (localtype - prov) * core * kch * fach);
+ }
+ }
+ }
+ } else {
+ transformed->L[y][x] = original->L[y][x];
+ }
+
+ break;
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ if (original->L[y][x] < 32768.f) {
+ float prov100 = original->L[y][x] / 32768.f;
+ float prov = prov100 * 100.f;
+
+ bool contin = true;
+
+ if (contin) {
+
+
+
+ if (prov > localtype ) {
+ if (prov >= localtype && prov < 50.f + localtype / 2.f) {
+ float core = (lco.alsup2 * prov + lco.blsup2) ;
+ transformed->L[y][x] = 327.68f * (prov + pm * (prov - localtype) * core * kch * fach);
+ } else {
+ float core = lco.aDY * (lco.aaa * prov100 * prov100 + lco.bbb * prov100 + lco.ccc);
+ transformed->L[y][x] = 327.68f * (prov + pm * (prov - localtype) * core * kch * fach);
+ }
+ } else { //inferior
+ if (2.f * prov > localtype && prov < localtype) {
+ float core = (lco.alsup * prov + lco.blsup) ;
+ transformed->L[y][x] = 327.68f * (prov - pm * (localtype - prov) * core * kch * fach);
+ } else if (2.f * prov <= localtype) {
+ float core = prov * lco.alinf * (lco.aa * prov100 * prov100 + lco.bb * prov100);
+ transformed->L[y][x] = 327.68f * (prov - pm * (localtype - prov) * core * kch * fach);
+ }
+ }
+ }
+ } else {
+ transformed->L[y][x] = original->L[y][x];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+ }
+}
+
+
+void ImProcFunctions::InverseContrast_Local (float ave, const local_contra & lco, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+ // BENCHFUN
+ float ach = (float)lp.trans / 100.f;
+
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+
+ for (int y = 0; y < transformed->H; y++) {
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+
+ int zone;
+ float localFactor;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => full effect, no transition
+ if (original->L[y][x] < 32768.f) {
+ float prov = original->L[y][x];
+
+ if (original->L[y][x] > ave) {
+ float kh = lco.ah * (original->L[y][x] / 327.68f) + lco.bh;
+ original->L[y][x] = ave + kh * (original->L[y][x] - ave);
+ } else {
+ float kl = lco.al * (original->L[y][x] / 327.68f) + 1.f;
+ original->L[y][x] = ave - kl * (ave - original->L[y][x]);
+ }
+
+ float diflc = original->L[y][x] - prov;
+ transformed->L[y][x] = prov + diflc;
+ } else {
+ transformed->L[y][x] = original->L[y][x];
+ }
+
+ break;
+ }
+
+ case 1: { // inside transition zone
+ if (original->L[y][x] < 32768.f) {
+ float factorx = localFactor;
+ factorx = 1.f - factorx;
+ float prov = original->L[y][x];
+
+ if (original->L[y][x] > ave) {
+ float kh = lco.ah * (original->L[y][x] / 327.68f) + lco.bh;
+ original->L[y][x] = ave + kh * (original->L[y][x] - ave);
+ } else {
+ float kl = lco.al * (original->L[y][x] / 327.68f) + 1.f;
+ original->L[y][x] = ave - kl * (ave - original->L[y][x]);
+ }
+
+ float diflc = original->L[y][x] - prov;
+ diflc *= factorx;
+ transformed->L[y][x] = prov + diflc;
+
+ } else {
+ transformed->L[y][x] = original->L[y][x];
+ }
+
+ break;
+ }
+
+ case 2: { // inside selection => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ }
+ }
+ }
+ }
+}
+
+static void calclight (float lum, float koef, float & lumnew, bool inv)
+//replace L-curve that does not work in local or bad
+{
+
+ float blac = 0.3f;
+
+ if (inv == false) {
+ blac = 0.99f;
+ }
+
+ if (koef > 0.f) {
+ lumnew = lum + 0.2f * (33000.f - lum) * koef / 100.f;
+ }
+
+ if (koef < 0.f) {
+ lumnew = lum + blac * lum * koef / 100.f;//0.999 instead of 0.2
+
+ if (lumnew < 0.f) {
+ float kc = lum / (lum - lumnew);
+ lumnew = lum + kc * 0.2f * lum * koef / 100.f;
+
+ }
+
+ if (inv == false && koef == -100.f) {
+ lumnew = 0.f;
+ }
+
+ }
+
+ lumnew = CLIPLOC (lumnew);
+
+}
+
+void ImProcFunctions::InverseSharp_Local (int sp, float **loctemp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params & lp, float **deltE, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+//local sharp
+ // BENCHFUN
+ const float localtype = lumaref; // always spot area
+ const float ach = (float)lp.trans / 100.f;
+ float reducac;
+
+ //constant and variable to prepare shape detection
+ if (lp.senssha < 30.f) {
+ reducac = 0.2f * (lp.senssha / 100.f);
+ } else {
+ float areduc = 0.6285714f; //0.44f/0.7f;
+ float breduc = 0.5f - areduc;
+ reducac = areduc * (lp.senssha / 100.f) + breduc;
+ }
+
+
+
+ constexpr float delhu = 0.1f; //between 0.05 and 0.2
+
+ const float apl = (-1.f) / delhu;
+ const float bpl = - apl * hueplus;
+ const float amo = 1.f / delhu;
+ const float bmo = - amo * huemoins;
+
+
+ const float pb = 4.f;
+ const float pa = (1.f - pb) / 40.f;
+
+ const float ahu = 1.f / (2.8f * lp.senssha - 280.f);
+ const float bhu = 1.f - ahu * 2.8f * lp.senssha;
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++) {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+ int zone;
+ float localFactor = 1.f;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ //prepare shape detection
+ float khu = 0.f;
+ float kch = 1.f;
+ bool kzon = false;
+ float fach = 1.f;
+ float deltachro = fabs (rchro - chromaref);
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280
+
+ //kch to modulate action with chroma
+ if (deltachro < 160.f * SQR (lp.senssha / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.senssha / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.senssha < 40.f ) {
+ kch = pow (kch, pa * lp.senssha + pb); //increase under 40
+ }
+
+
+ // algo with detection of hue ==> artifacts for noisy images ==> denoise before
+ if (lp.senssha < 20.f) { //to try...
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu ) {
+ khu = apl * rhue + bpl;
+ } else if (rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins ) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if (deltaE < 2.8f * lp.senssha) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ if (lp.qualmet >= 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ //fach = khu ;
+
+ } else {
+ /*
+ float kcr = 8.f;
+ if(lp.senssha > 30.f){
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr)) * rchro;
+
+ }
+ }
+ */
+ }
+
+
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => full effect, no transition
+ float difL = loctemp[y][x] - original->L[y][x];
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float difL = loctemp[y][x] - original->L[y][x];
+
+ float factorx = 1.f - localFactor;
+ difL *= factorx;
+
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+ break;
+ }
+
+ case 2: { // inside selection => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void ImProcFunctions::Sharp_Local (int call, int sp, float **loctemp, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, const local_params & lp, float **deltE, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+ // BENCHFUN
+ const float localtype = lumaref; // always spot area
+ const float ach = (float)lp.trans / 100.f;
+ float reducac;
+
+ //constant and variable to prepare shape detection
+ if (lp.senssha < 30.f) {
+ reducac = 0.2f * (lp.senssha / 100.f);
+ } else {
+ float areduc = 0.6285714f; //0.44f/0.7f;
+ float breduc = 0.5f - areduc;
+ reducac = areduc * (lp.senssha / 100.f) + breduc;
+ }
+
+ //printf("call=%i\n", call);
+
+ constexpr float delhu = 0.1f; //between 0.05 and 0.2
+
+ const float apl = (-1.f) / delhu;
+ const float bpl = - apl * hueplus;
+ const float amo = 1.f / delhu;
+ const float bmo = - amo * huemoins;
+
+
+ const float pb = 4.f;
+ const float pa = (1.f - pb) / 40.f;
+
+ const float ahu = 1.f / (2.8f * lp.senssha - 280.f);
+ const float bhu = 1.f - ahu * 2.8f * lp.senssha;
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++) {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+ int zone;
+ float localFactor = 1.f;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ //prepare shape detection
+ float khu = 0.f;
+ float kch = 1.f;
+ bool kzon = false;
+ float fach = 1.f;
+ float deltachro = fabs (rchro - chromaref);
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280
+
+ //kch to modulate action with chroma
+ if (deltachro < 160.f * SQR (lp.senssha / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.senssha / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.senssha < 40.f ) {
+ kch = pow (kch, pa * lp.senssha + pb); //increase under 40
+ }
+
+
+ // algo with detection of hue ==> artifacts for noisy images ==> denoise before
+ if (lp.senssha < 20.f) { //to try...
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu ) {
+ khu = apl * rhue + bpl;
+ } else if (rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins ) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ khu = apl * rhue + bpl;
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ khu = amo * rhue + bmo;
+ } else {
+ khu = 1.f;
+ }
+
+ kzon = true;
+ }
+
+ if (deltaE < 2.8f * lp.senssha) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ if (lp.qualmet == 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ //fach = khu ;
+
+ } else {
+ /*
+ float kcr = 8.f;
+ if(lp.senssha > 30.f){
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr)) * rchro;
+
+ }
+ }
+ */
+ }
+
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float factorx = localFactor;
+ float difL;
+
+ if (call == 2) {
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ difL = loctemp[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ }
+ } else if (call == 1) {
+ difL = loctemp[y][x] - original->L[y][x];
+
+ }
+
+ //float difL = loctemp[y][x] - original->L[y][x];
+ difL *= factorx;
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+
+ break;
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ // float difL = loctemp[y][x] - original->L[y][x];
+ float difL;
+
+ if (call == 2) {
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ // bufsh[loy - begy - 1][lox - begx - 1]
+ difL = loctemp[loy - begy - 1][lox - begx - 1] - original->L[y][x];
+ }
+ } else if (call == 1) {
+ difL = loctemp[y][x] - original->L[y][x];
+ }
+
+ transformed->L[y][x] = original->L[y][x] + difL * kch * fach;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+void ImProcFunctions::ColorLight_Local (int call, LabImage * bufcolorig, LabImage * bufcoltra, int sp, float moy, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, bool locallutili, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, const local_params & lp, float ** deltE, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+ // BENCHFUN
+// chroma and lightness
+ const float ach = (float)lp.trans / 100.f;
+
+ //chroma
+ constexpr float amplchsens = 2.5f;
+ constexpr float achsens = (amplchsens - 1.f) / (100.f - 20.f); //20. default locallab.sensi
+ constexpr float bchsens = 1.f - 20.f * achsens;
+ const float multchro = lp.sens * achsens + bchsens;
+
+ //luma
+ constexpr float ampllumsens = 2.f;
+ constexpr float alumsens = (ampllumsens - 1.f) / (100.f - 20.f); //20. default locallab.sensi
+ constexpr float blumsens = 1.f - 20.f * alumsens;
+ const float multlum = lp.sens * alumsens + blumsens;
+
+ //skin
+ constexpr float amplchsensskin = 1.6f;
+ constexpr float achsensskin = (amplchsensskin - 1.f) / (100.f - 20.f); //20. default locallab.sensi
+ constexpr float bchsensskin = 1.f - 20.f * achsensskin;
+ const float multchroskin = lp.sens * achsensskin + bchsensskin;
+
+ //transition = difficult to avoid artifact with scope on flat area (sky...)
+ constexpr float delhu = 0.1f; //between 0.05 and 0.2
+ const float aplus = (1.f - lp.chro) / delhu;
+ const float bplus = 1.f - aplus * hueplus;
+ const float amoins = (lp.chro - 1.f) / delhu;
+ const float bmoins = 1.f - amoins * huemoins;
+
+
+ const float apl = (-1.f) / delhu;
+ const float bpl = - apl * hueplus;
+ const float amo = 1.f / delhu;
+ const float bmo = - amo * huemoins;
+
+
+ const float pb = 4.f;
+ const float pa = (1.f - pb) / 40.f;
+
+ const float ahu = 1.f / (2.8f * lp.sens - 280.f);
+ const float bhu = 1.f - ahu * 2.8f * lp.sens;
+
+ const float alum = 1.f / (lp.sens - 100.f);
+ const float blum = 1.f - alum * lp.sens;
+
+ //luma
+ constexpr float lumdelta = 11.f; //11
+ float modlum = lumdelta * multlum;
+// printf("multlum=%f modlum=%f\n", multlum, modlum);
+
+ // constant and varaibles to prepare shape detection
+ if (lumaref + modlum >= 100.f) {
+ modlum = (100.f - lumaref) / 2.f;
+ }
+
+ if (lumaref - modlum <= 0.f) {
+ modlum = (lumaref) / 2.f;
+ }
+
+ float alu = 1.f / (lumaref + modlum - 100.f); //linear
+ float aa, bb, aaa, bbb, ccc;
+ float reducac = settings->reduchigh;//0.85f;
+ float reducac2 = settings->reduclow;//0.2f;
+
+ float vinf = (lumaref + modlum) / 100.f;
+ float vi = (lumaref - modlum) / 100.f;
+ ImProcFunctions::secondeg_begin (reducac, vi, aa, bb);//parabolic
+ ImProcFunctions::secondeg_end (reducac, vinf, aaa, bbb, ccc);//parabolic
+// printf("vi=%f aa=%f bb=%f vinf=%f aaa=%f bbb=%f ccc=%f\n", vi,aa,bb, vinf, aaa, bbb, ccc);
+ float vinf2 = (lumaref + modlum) / 100.f;
+ float vi2 = (lumaref - modlum) / 100.f;
+ float aaaa, bbbb, cccc, aO, bO;
+ ImProcFunctions::secondeg_end (reducac2, vinf2, aaaa, bbbb, cccc);//parabolic
+ ImProcFunctions::secondeg_begin (reducac2, vi2, aO, bO);//parabolic
+
+ if (call <= 3) {
+ // printf("actif\n");
+ /*
+ if(lllocalcurve) {
+ printf("COURBE\n");
+ }
+
+ if(!lllocalcurve) {
+ printf("PAS DE COURBE\n");
+ }
+ */
+ //Todo optimization in this first part with bufcolorig and bufcoltra
+
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+#endif
+
+ float maxl = -100000.f;
+ float maxa = -100000.f;
+ float maxb = -100000.f;
+ float minl = 100000.f;
+ float mina = 100000.f;
+ float minb = 100000.f;
+ float maxrl = -100000.f;
+ float minrl = 100000.f;
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < transformed->H; y++)
+ {
+
+#ifdef __SSE2__
+ int i = 0;
+ //Todo optimization in this first part with bufcolorig and bufcoltra
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (original->a[y][i]);
+ vfloat bv = LVFU (original->b[y][i]);
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ STVF (sqrtBuffer[i], _mm_sqrt_ps (SQRV (bv) + SQRV (av)) / c327d68v);
+
+ }
+
+ for (; i < transformed->W; i++) {
+ atan2Buffer[i] = xatan2f (original->b[y][i], original->a[y][i]);
+ sqrtBuffer[i] = sqrt (SQR (original->b[y][i]) + SQR (original->a[y][i])) / 327.68f;
+ }
+
+#endif
+
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+
+
+#ifdef __SSE2__
+ float rhue = atan2Buffer[x];
+ float rchro = sqrtBuffer[x];
+#else
+
+ float rhue = xatan2f (original->b[y][x], original->a[y][x]);
+
+ float rchro = sqrt (SQR (original->b[y][x]) + SQR (original->a[y][x])) / 327.68f;
+#endif
+
+ float rL = original->L[y][x] / 327.68f;
+ float rLL = original->L[y][x] / 327.68f;
+
+ if (fabs (original->b[y][x]) < 0.01f) {
+ original->b[y][x] = 0.01f;
+ }
+
+ float eps = 0.f;
+
+ if (fabs (original->b[y][x]) < 0.001f) {
+ eps = 0.01f;
+ }
+
+ float kab = (original->a[y][x] / (original->b[y][x] + eps));
+
+ //prepare shape detection
+// printf("z");
+ //end buf for square
+ float realchro = 1.f;
+ float deltachro = fabs (rchro - chromaref);
+
+ float deltahue = fabs (rhue - hueref);
+
+ if (deltahue > M_PI) {
+ deltahue = - (deltahue - 2.f * M_PI);
+ }
+
+ float deltaE = 20.f * deltahue + deltachro; //pseudo deltaE between 0 and 280
+ float deltaL = fabs (lumaref - rL); //between 0 and 100
+
+ float kch = 1.f;
+ float khu = 0.f;
+ float fach = 1.f;
+ float falu = 1.f;
+
+ //kch acts on luma
+ if (deltachro < 160.f * SQR (lp.sens / 100.f)) {
+ kch = 1.f;
+ } else {
+ float ck = 160.f * SQR (lp.sens / 100.f);
+ float ak = 1.f / (ck - 160.f);
+ float bk = -160.f * ak;
+ kch = ak * deltachro + bk;
+ }
+
+ if (lp.sens < 40.f ) {
+ kch = pow (kch, pa * lp.sens + pb); //increase under 40
+ }
+
+ bool kzon = false;
+
+ //transition = difficult to avoid artifact with scope on flat area (sky...)
+ //hue detection
+ if ((hueref + dhue) < M_PI && rhue < hueplus && rhue > huemoins) { //transition are good
+ if (rhue >= hueplus - delhu) {
+ realchro = aplus * rhue + bplus;
+ khu = apl * rhue + bpl;
+
+ } else if (rhue < huemoins + delhu) {
+ realchro = amoins * rhue + bmoins;
+ khu = amo * rhue + bmo;
+
+ } else {
+ realchro = lp.chro;
+ khu = 1.f;
+
+ }
+
+ kzon = true;
+ } else if ((hueref + dhue) >= M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ realchro = aplus * rhue + bplus;
+ khu = apl * rhue + bpl;
+
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ realchro = amoins * rhue + bmoins;
+ khu = amo * rhue + bmo;
+
+ } else {
+ realchro = lp.chro;
+ khu = 1.f;
+
+ }
+
+ kzon = true;
+ }
+
+ if ((hueref - dhue) > -M_PI && rhue < hueplus && rhue > huemoins) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ realchro = aplus * rhue + bplus;
+ khu = apl * rhue + bpl;
+
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ realchro = amoins * rhue + bmoins;
+ khu = amo * rhue + bmo;
+
+ } else {
+ realchro = lp.chro;
+ khu = 1.f;
+
+ }
+
+ kzon = true;
+ } else if ((hueref - dhue) <= -M_PI && (rhue > huemoins || rhue < hueplus )) {
+ if (rhue >= hueplus - delhu && rhue < hueplus) {
+ realchro = aplus * rhue + bplus;
+ khu = apl * rhue + bpl;
+
+ } else if (rhue >= huemoins && rhue < huemoins + delhu) {
+ realchro = amoins * rhue + bmoins;
+ khu = amo * rhue + bmo;
+
+ } else {
+ realchro = lp.chro;
+ khu = 1.f;
+
+ }
+
+ kzon = true;
+ }
+
+
+ //detection of deltaE and deltaL
+ if (lp.sens <= 20.f) { //to try...
+ //fach and kch acts on luma
+ if (deltaE < 2.8f * lp.sens) {
+ fach = khu;
+ } else {
+ fach = khu * (ahu * deltaE + bhu);
+ }
+
+ float kcr = 10.f;
+
+ if (rchro < kcr) {
+ fach *= (1.f / (kcr * kcr)) * rchro * rchro;
+ }
+
+ //fach = 1.f;//to avoid artifacts in some cases
+ //can be probably improved
+ if (lp.qualmet >= 1) {
+ if (deltE[y][x] > lp.thr) {
+ fach = 1.f;
+ }
+ } else {
+ fach = 1.f;
+ }
+
+ //falu acts on chroma
+ if (deltaL < lp.sens) {
+ falu = 1.f;
+ } else {
+ falu = 1.f;// alum * deltaL + blum;
+ }
+
+ }
+
+ if (kzon) {
+ if (lp.sens < 60.f) { //arbitrary value
+ if (hueref < -1.1f && hueref > -2.8f) { // detect blue sky
+ if (chromaref > 0.f && chromaref < 35.f * multchro) { // detect blue sky
+ if ( (rhue > -2.79f && rhue < -1.11f) && (rchro < 35.f * multchro)) {
+ realchro *= 0.9f;
+ } else {
+ realchro = 1.f;
+ }
+ }
+ } else {
+ realchro = lp.chro;
+ }
+
+ if (lp.sens < 50.f && lp.chro > 0.f) {
+ if (hueref > -0.1f && hueref < 1.6f) { // detect skin
+ if (chromaref > 0.f && chromaref < 55.f * multchroskin) { // detect skin
+ if ( (rhue > -0.09f && rhue < 1.59f) && (rchro < 55.f * multchroskin)) {
+ realchro *= 0.9f;
+ } else {
+ realchro = 1.f;
+ }
+ }
+ } else {
+ realchro = lp.chro;
+ }
+ }
+ }
+
+ }
+
+ float kLinf = rLL / (100.f);
+ float kLsup = kLinf;
+
+ float kdiff = 1.f;
+
+ if (kzon) { ///rhue < hueplus && rhue > huemoins
+
+ if ( (rLL > (lumaref - modlum) && rLL < (lumaref + modlum))) {
+ kdiff = 1.f;
+ } else if (rLL > 0.f && rLL <= (lumaref - modlum)) {
+ kdiff = (aa * kLinf * kLinf + bb * kLinf); //parabolic
+
+ if (kdiff < 0.01f) {
+ kdiff = 0.01f;
+ }
+ } else if (rLL <= 100.f && rLL >= (lumaref + modlum)) {
+
+ kdiff = (aaa * kLsup * kLsup + bbb * kLsup + ccc); //parabolic
+
+ if (kdiff < 0.01f) {
+ kdiff = 0.01f;
+ }
+
+ }
+
+ //end luma
+ } else {
+ float ktes = 1.f;
+
+ if ( (rLL > (lumaref - modlum) && rLL < (lumaref + modlum))) {
+ kdiff = ktes;
+ } else if (rLL > 0.f && rLL <= (lumaref - modlum)) {
+
+ kdiff = (ktes * (aO * kLinf * kLinf + bO * kLinf)); //parabolic
+
+ if (kdiff < 0.01f) {
+ kdiff = 0.01f;
+ }
+
+ } else if (rLL <= 100.f && rLL >= (lumaref + modlum)) {
+
+ kdiff = (ktes * (aaaa * kLsup * kLsup + bbbb * kLsup + cccc)); //parabolic
+
+ if (kdiff < 0.01f) {
+ kdiff = 0.01f;
+ }
+
+ }
+
+ }
+
+ int zone;
+ float localFactor;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+ float th_r = 0.01f;
+
+ if (rL > th_r) { //to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ break;
+ }
+
+ case 1: { // inside transition zone
+ // float lumnew = original->L[y][x];
+ float lumnew = bufcolorig->L[loy - begy - 1][lox - begx - 1];
+
+ float lightcont;
+
+ if (lp.curvact) {
+ if (lllocalcurve) {
+ float lumprov = lllocalcurve[lumnew * 1.9f];
+ lumnew = 0.526316f * lumprov;
+ }
+
+ if (loclhCurve) {
+ float l_r;//Luminance Lab in 0..1
+ l_r = lumnew / 32768.f;
+ {
+ float khu = 1.9f; //in reserve in case of!
+
+ float valparam = float ((loclhCurve[500.f * Color::huelab_to_huehsv2 (rhue)] - 0.5f)); //get l_r=f(H)
+ float valparamneg;
+ valparamneg = valparam;
+
+ if (valparam > 0.f) {
+ l_r = (1.f - valparam) * l_r + valparam * (1.f - SQR (((SQR (1.f - min (l_r, 1.0f))))));
+ } else
+ //for negative
+ {
+ l_r *= (1.f + khu * valparamneg);
+ }
+ }
+
+ lumnew = l_r * 32768.f;
+ }
+
+ }
+
+ if (lp.ligh != 0.f) {
+ // calclight (bufcolorig->L[loy - begy - 1][lox - begx - 1], lp.ligh , lumnew, true);//replace L-curve
+ calclight (lumnew, lp.ligh , lumnew, true);//replace L-curve
+ lightcont = lumnew;
+
+ } else {
+ lightcont = lumnew;
+ }
+
+ float factorx = localFactor;
+ float fac = (100.f + factorx * realchro * falu) / 100.f; //chroma factor transition
+ // float diflc = lightcont - bufcolorig->L[loy - begy - 1][lox - begx - 1];
+ float diflc = lightcont - original->L[y][x];
+ kdiff *= fach * kch;
+ diflc *= kdiff ;
+
+ diflc *= factorx; //transition lightess
+ // transformed->L[y][x] = CLIPL(bufcolorig->L[loy - begy - 1][lox - begx - 1] + diflc);
+ transformed->L[y][x] = CLIPL (original->L[y][x] + diflc);
+
+
+ if (fabs (kab) > 1.f) {
+ transformed->a[y][x] = CLIPC (original->a[y][x] * fac) ;
+ transformed->b[y][x] = CLIPC (original->a[y][x] * fac) / kab;
+ } else {
+ transformed->b[y][x] = CLIPC (original->b[y][x] * fac);
+ transformed->a[y][x] = CLIPC (original->b[y][x] * fac) * kab ;
+
+ }
+
+ break;
+ }
+
+ case 2: { // inside selection => full effect, no transition
+ float lumnew = bufcolorig->L[loy - begy - 1][lox - begx - 1];
+ float lightcont;
+
+ if (lp.curvact) {
+ if (lllocalcurve) {
+ float lumprov = lllocalcurve[lumnew * 1.9f];
+ lumnew = 0.526316f * lumprov;
+ }
+
+ if (loclhCurve) {
+ float l_r;//Luminance Lab in 0..1
+ l_r = lumnew / 32768.f;
+ {
+ float khu = 1.9f;
+
+ float valparam = float ((loclhCurve[500.f * Color::huelab_to_huehsv2 (rhue)] - 0.5f)); //get l_r=f(H)
+ float valparamneg;
+ valparamneg = valparam;
+
+ if (valparam > 0.f) {
+ l_r = (1.f - valparam) * l_r + valparam * (1.f - SQR (((SQR (1.f - min (l_r, 1.0f))))));
+ } else
+ //for negative
+ {
+ l_r *= (1.f + khu * valparamneg);
+ }
+ }
+
+ lumnew = l_r * 32768.f;
+ }
+
+ }
+
+
+ if (lp.ligh != 0.f) {
+ // calclight (original->L[y][x], lp.ligh , lumnew);
+ // calclight (bufcolorig->L[loy - begy - 1][lox - begx - 1], lp.ligh , lumnew, true);//replace L-curve
+ calclight (lumnew, lp.ligh , lumnew, true);//replace L-curve
+ lightcont = lumnew;
+
+ } else {
+ lightcont = lumnew;
+ }
+
+ float fac = (100.f + realchro * falu) / 100.f; //chroma factor transition
+ float diflc = lightcont - original->L[y][x];
+ //float diflc = lightcont - bufcolorig->L[loy - begy - 1][lox - begx - 1];
+
+ kdiff *= fach * kch;
+ diflc *= kdiff ;
+ transformed->L[y][x] = CLIPL (original->L[y][x] + diflc);
+
+ if (fabs (kab) > 1.f) {
+ transformed->a[y][x] = CLIPC (original->a[y][x] * fac) ;
+ transformed->b[y][x] = CLIPC (original->a[y][x] * fac) / kab;
+ } else {
+ transformed->b[y][x] = CLIPC (original->b[y][x] * fac);
+ transformed->a[y][x] = CLIPC (original->b[y][x] * fac) * kab;
+
+ }
+
+ }
+
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ }
+
+}
+
+void ImProcFunctions::InverseColorLight_Local (const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy)
+{
+ // BENCHFUN
+ float ach = (float)lp.trans / 100.f;
+ const float facc = (100.f + lp.chro) / 100.f; //chroma factor transition
+
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+
+ for (int y = 0; y < transformed->H; y++) {
+ int loy = cy + y;
+
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+
+ int zone;
+ float localFactor;
+ calcTransition (lox, loy, ach, lp, zone, localFactor);
+
+ switch (zone) {
+ case 0: { // outside selection and outside transition zone => no effect, keep original values
+ float lumnew = original->L[y][x];
+
+ if (lp.ligh != 0.f) {
+ calclight (original->L[y][x], lp.ligh , lumnew, false);
+ }
+
+ // float lightcont = localcurve[original->L[y][x]]; //apply lightness
+ float lightcont = lumnew ; //original->L[y][x] + (lp.ligh /100.f)*original->L[y][x] ; //apply lightness
+
+
+
+ transformed->L[y][x] = lightcont; //localcurve[original->L[y][x]]; //apply lightness
+ transformed->a[y][x] = original->a[y][x] * facc;
+ transformed->b[y][x] = original->b[y][x] * facc;
+ break;
+ }
+
+ case 1: { // inside transition zone
+ float factorx = 1.f - localFactor;
+ float fac = (100.f + factorx * lp.chro) / 100.f; //chroma factor transition
+ float lumnew = original->L[y][x];
+
+ if (lp.ligh != 0.f) {
+ calclight (original->L[y][x], lp.ligh , lumnew, false);
+ }
+
+ // float lightcont = localcurve[original->L[y][x]]; //apply lightness
+ float lightcont = lumnew ; //original->L[y][x] + (lp.ligh /100.f)*original->L[y][x] ; //apply lightness
+
+ //float lightcont = localcurve[original->L[y][x]]; //apply lightness
+ float diflc = lightcont - original->L[y][x];
+ diflc *= factorx;
+ transformed->L[y][x] = original->L[y][x] + diflc;
+ transformed->a[y][x] = original->a[y][x] * fac;
+ transformed->b[y][x] = original->b[y][x] * fac;
+ break;
+ }
+
+ case 2: { // inside selection => no effect, keep original values
+ transformed->L[y][x] = original->L[y][x];
+ transformed->a[y][x] = original->a[y][x];
+ transformed->b[y][x] = original->b[y][x];
+ }
+ }
+ }
+ }
+
+}
+
+void ImProcFunctions::Lab_Local (int call, int sp, float** shbuffer, LabImage * original, LabImage * transformed, int sx, int sy, int cx, int cy, int oW, int oH, int fw, int fh, bool locutili, int sk, const LocretigainCurve & locRETgainCcurve, bool locallutili, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, double & hueref, double & chromaref, double & lumaref)
+{
+ //general call of others functions : important return hueref, chromaref, lumaref
+ if (params->locallab.enabled) {
+ // BENCHFUN
+#ifdef _DEBUG
+ MyTime t1e, t2e;
+ t1e.set();
+// init variables to display Munsell corrections
+ MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo();
+#endif
+
+
+ int GW = transformed->W;
+ int GH = transformed->H;
+ float moy = 0.f;
+ float maxmad = -10000.f;
+ float minmad = 1000000.f;
+
+ struct local_params lp;
+ calcLocalParams (oW, oH, params->locallab, lp);
+
+ const float radius = lp.rad / (sk * 1.4f); //0 to 70 ==> see skip
+ GW = transformed->W;
+ GH = transformed->H;
+ float **deltE;
+
+ if (lp.qualmet >= 1) {
+
+ deltE = new float*[GH];
+
+ for (int i = 0; i < GH; i++) {
+ deltE[i] = new float[GW];
+ }
+
+ for (int ir = 0; ir < GH; ir++)
+ for (int jr = 0; jr < GW; jr++) {
+ deltE[ir][jr] = 0.f;
+ }
+ }
+
+//begin contrast and evalue hue
+// double precision for large summations
+ double ave = 0.;
+ double aveA = 0.;
+ double aveB = 0.;
+ double aveL = 0.;
+ double aveChro = 0.;
+// int precision for the counters
+ int n = 0;
+ int nab = 0;
+// single precision for the result
+ float av, avA, avB, avL;
+
+//evauate mean luminance for contrast : actually one area
+// evaluate also hue
+ int levred;
+ bool noiscfactiv = false;
+
+ if (lp.qualmet == 2) { //suppress artifacts with quality enhanced
+ levred = 4;
+ noiscfactiv = true;
+ } else {
+ levred = 7;
+ noiscfactiv = false;
+ }
+
+
+
+
+ if ((!lp.inv || !lp.invret) && hueref == INFINITY && chromaref == INFINITY && lumaref == INFINITY) {
+ //evaluate hue, chroma, luma in center spot
+ int spotSize = 0.88623f * max (1, lp.cir / sk); //18
+ //O.88623 = sqrt(PI / 4) ==> sqare equal to circle
+
+ // very small region, don't use omp here
+ for (int y = max (cy, (int) (lp.yc - spotSize)); y < min (transformed->H + cy, (int) (lp.yc + spotSize + 1)); y++) {
+ for (int x = max (cx, (int) (lp.xc - spotSize)); x < min (transformed->W + cx, (int) (lp.xc + spotSize + 1)); x++) {
+ aveL += original->L[y - cy][x - cx];
+ aveA += original->a[y - cy][x - cx];
+ aveB += original->b[y - cy][x - cx];
+ aveChro += sqrtf (SQR (original->b[y - cy][x - cx]) + SQR (original->a[y - cy][x - cx]));
+
+ nab++;
+ }
+ }
+
+ } else if (lp.inv || lp.invret) { //exterior
+ ave = 0.f;
+ n = 0;
+ #pragma omp parallel for reduction(+:ave,n)
+
+ for (int y = 0; y < transformed->H; y++) {
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int loy = cy + y;
+
+ if (lox >= lp.xc && lox < lp.xc + lp.lx && loy >= lp.yc && loy < lp.yc + lp.ly) {
+ } else if (lox >= lp.xc && lox < lp.xc + lp.lx && loy < lp.yc && loy > lp.yc - lp.lyT) {
+ } else if (lox < lp.xc && lox > lp.xc - lp.lxL && loy <= lp.yc && loy > lp.yc - lp.lyT) {
+ } else if (lox < lp.xc && lox > lp.xc - lp.lxL && loy > lp.yc && loy < lp.yc + lp.ly) {
+ } else {
+ ave += original->L[y][x];
+ n++;
+ }
+ }
+ }
+
+ if (n == 0) {
+ ave = 15000.f;
+ n = 1;
+ }
+
+ ave = ave / n;
+ av = ave / 327.68f;
+ }
+
+ aveL = aveL / nab;
+ aveA = aveA / nab;
+ aveB = aveB / nab;
+ aveChro = aveChro / nab;
+ aveChro /= 327.68f;
+ avA = aveA / 327.68f;
+ avB = aveB / 327.68f;
+ avL = aveL / 327.68f;
+
+ if (hueref == INFINITY) {
+ hueref = xatan2f (avB, avA); //mean hue
+ }
+
+ if (chromaref == INFINITY) {
+ chromaref = aveChro;
+ }
+
+ if (lumaref == INFINITY) {
+ lumaref = avL;
+ }
+
+ struct local_contra lco;
+
+// we must here detect : general case, skin, sky,...foliages ???
+// delta dhue, luminance and chroma
+ constexpr float ared = (M_PI - 0.05f) / 100.f;
+
+ constexpr float bred = 0.05f;
+
+ float dhue = ared * lp.sens + bred; //delta hue lght chroma
+
+ float dhueret = ared * lp.sensh + bred; //delta hue retinex
+
+ constexpr float maxh = 4.f; //amplification contrast above mean
+
+ constexpr float maxl = 3.f; //reductio contrast under mean
+
+ float multh = (float) fabs (lp.cont) * (maxh - 1.f) / 100.f + 1.f;
+
+ float mult = (float)fabs (lp.cont) * (maxl - 1.f) / 100.f + 1.f;
+
+ lco.dx = 1.f - 1.f / mult;
+
+ lco.dy = 1.f - 1.f / multh;
+
+
+
+ if ((radius >= GAUSS_SKIP || lp.stren > 0.1) && lp.blurena) { // radius < GAUSS_SKIP means no gauss, just copy of original image
+ LabImage *tmp1;
+ LabImage *bufgb;
+ int GW = transformed->W;
+ int GH = transformed->H;
+
+ if (call == 2 && !lp.invrad) { //simpleprocess
+ int bfh = int (lp.ly + lp.lyT) + 1; //bfw bfh real size of square zone
+ int bfw = int (lp.lx + lp.lxL) + 1;
+ bufgb = new LabImage (bfw, bfh);
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++) //fill with 0
+ for (int jr = 0; jr < bfw; jr++) {
+ bufgb->L[ir][jr] = 0.f;
+ bufgb->a[ir][jr] = 0.f;
+ bufgb->b[ir][jr] = 0.f;
+ }
+
+#ifdef _OPENMP
+// #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < transformed->H ; y++) //{
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int loy = cy + y;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ bufgb->L[loy - begy - 1][lox - begx - 1] = original->L[y][x];//fill square buffer with datas
+ bufgb->a[loy - begy - 1][lox - begx - 1] = original->a[y][x];//fill square buffer with datas
+ bufgb->b[loy - begy - 1][lox - begx - 1] = original->b[y][x];//fill square buffer with datas
+ }
+ }
+
+ tmp1 = new LabImage (bfw, bfh);
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ gaussianBlur (bufgb->L, tmp1->L, bfw, bfh, radius);
+ gaussianBlur (bufgb->a, tmp1->a, bfw, bfh, radius);
+ gaussianBlur (bufgb->b, tmp1->b, bfw, bfh, radius);
+
+ }
+
+
+ } else {
+ tmp1 = new LabImage (transformed->W, transformed->H);;
+
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ gaussianBlur (original->L, tmp1->L, GW, GH, radius);
+ gaussianBlur (original->a, tmp1->a, GW, GH, radius);
+ gaussianBlur (original->b, tmp1->b, GW, GH, radius);
+
+ }
+ }
+
+ if (lp.stren > 0.1f) {
+ float mean = 0.f;//0 best result
+ float variance = lp.stren ; //(double) SQR(lp.stren)/sk;
+ addGaNoise (tmp1, tmp1, mean, variance, sk) ;
+ }
+
+ if (!lp.invrad) { //blur and noise (center)
+ // BlurNoise_Local(call, lp, original, transformed, tmp1, cx, cy);
+ float hueplus = hueref + dhue;
+ float huemoins = hueref - dhue;
+
+ if (hueplus > M_PI) {
+ hueplus = hueref + dhue - 2.f * M_PI;
+ }
+
+ if (huemoins < -M_PI) {
+ huemoins = hueref - dhue + 2.f * M_PI;
+ }
+
+ BlurNoise_Local (call, sp, tmp1, hueplus, huemoins, hueref, dhue, chromaref, lumaref, lp, deltE, original, transformed, cx, cy);
+
+ } else {
+
+ InverseBlurNoise_Local (lp, original, transformed, tmp1, cx, cy);
+
+ }
+
+ if (call == 2 && !lp.invrad) {
+ delete bufgb;
+ }
+
+ delete tmp1;
+ }
+
+ // }
+
+//local denoise
+ if (lp.noiself > 0.f || lp.noiselc > 0.f || lp.noisecf > 0.f || lp.noisecc > 0.f && call < 3 || noiscfactiv && lp.denoiena) {
+ if (lp.noisecf > 0.1f || lp.noisecc > 0.1f) {
+ noiscfactiv = false;
+ levred = 7;
+ }
+
+ if (call == 1) {
+ LabImage *tmp1 = new LabImage (transformed->W, transformed->H);
+ int GW = transformed->W;
+ int GH = transformed->H;
+
+
+ for (int ir = 0; ir < GH; ir++)
+ for (int jr = 0; jr < GW; jr++) {
+ tmp1->L[ir][jr] = original->L[ir][jr];
+ tmp1->a[ir][jr] = original->a[ir][jr];
+ tmp1->b[ir][jr] = original->b[ir][jr];
+ }
+
+ int DaubLen = 6;
+ int wavNestedLevels = 1;
+
+ int levwavL = levred;
+ int skip = 1;
+ wavelet_decomposition* Ldecomp = new wavelet_decomposition (tmp1->L[0], tmp1->W, tmp1->H, levwavL, 1, skip, max (1, wavNestedLevels), DaubLen);
+ wavelet_decomposition* adecomp = new wavelet_decomposition (tmp1->a[0], tmp1->W, tmp1->H, levwavL, 1, skip, max (1, wavNestedLevels), DaubLen);
+ wavelet_decomposition* bdecomp = new wavelet_decomposition (tmp1->b[0], tmp1->W, tmp1->H, levwavL, 1, skip, max (1, wavNestedLevels), DaubLen);
+
+ float madL[8][3];
+ float madab[8][3];
+ int edge;
+
+ if (!Ldecomp->memoryAllocationFailed) {
+
+ for (int lvl = 0; lvl < levred; lvl++) {
+ for (int dir = 1; dir < 4; dir++) {
+ int Wlvl_L = Ldecomp->level_W (lvl);
+ int Hlvl_L = Ldecomp->level_H (lvl);
+
+ float ** WavCoeffs_L = Ldecomp->level_coeffs (lvl);
+
+ madL[lvl][dir - 1] = SQR (Mad (WavCoeffs_L[dir], Wlvl_L * Hlvl_L));
+ }
+ }
+
+
+ int ind = 0;
+ float vari[levred];
+
+ if (levred == 7) {
+ edge = 2;
+ vari[0] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[1] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[2] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+
+ vari[3] = 8.f * SQR ((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0));
+ vari[4] = 8.f * SQR ((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0));
+ vari[5] = 8.f * SQR ((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0));
+ vari[6] = 8.f * SQR ((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0));
+ } else if (levred == 4) {
+ edge = 3;
+ vari[0] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[1] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[2] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[3] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiselc / 25.0));
+
+ }
+
+ if (( lp.noiself > 0.1f || lp.noiselc > 0.1f)) {
+ vari[0] = max (0.0001f, vari[0]);
+ vari[1] = max (0.0001f, vari[1]);
+ vari[2] = max (0.0001f, vari[2]);
+ vari[3] = max (0.0001f, vari[3]);
+
+ if (levred == 7) {
+ vari[4] = max (0.0001f, vari[4]);
+ vari[5] = max (0.0001f, vari[5]);
+ vari[6] = max (0.0001f, vari[6]);
+ }
+
+ float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL
+
+ WaveletDenoiseAllL (*Ldecomp, noisevarlum, madL, vari, edge);
+ }
+ }
+
+ float variC[levred];
+
+ if (!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) {
+ if (levred == 7) {
+ edge = 2;
+ variC[0] = SQR (lp.noisecf / 10.0);
+ variC[1] = SQR (lp.noisecf / 10.0);
+ variC[2] = SQR (lp.noisecf / 10.0);
+
+ variC[3] = SQR (lp.noisecf / 10.0);
+ variC[4] = SQR (lp.noisecf / 10.0);
+ variC[5] = SQR (lp.noisecc / 10.0);
+ variC[6] = SQR (lp.noisecc / 10.0);
+ } else if (levred == 4) {
+ edge = 3;
+ variC[0] = SQR (lp.noisecf / 10.0);
+ variC[1] = SQR (lp.noisecf / 10.0);
+ variC[2] = SQR (lp.noisecf / 10.0);
+ variC[3] = SQR (lp.noisecf / 10.0);
+ }
+
+
+ if (( lp.noisecf > 0.1f || lp.noisecc > 0.1f || noiscfactiv)) {
+ float minic = 0.0001f;
+
+ if (noiscfactiv) {
+ minic = 0.01f;//only for artifact shape detection
+ }
+
+ variC[0] = max (minic, variC[0]);
+ variC[1] = max (minic, variC[1]);
+ variC[2] = max (minic, variC[2]);
+ variC[3] = max (minic, variC[3]);
+
+ if (levred == 7) {
+
+ variC[4] = max (0.0001f, variC[4]);
+ variC[5] = max (0.0001f, variC[5]);
+ variC[6] = max (0.0001f, variC[6]);
+ }
+
+ float* noisevarchrom = new float[GH * GW];
+
+ for (int q = 0; q < GH * GW; q++) {
+ noisevarchrom[q] = 1.f;
+ }
+
+ float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0);
+ WaveletDenoiseAllAB (*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, false, false, false);
+ WaveletDenoiseAllAB (*Ldecomp, *bdecomp, noisevarchrom, madL, variC, edge, noisevarab_r, false, false, false);
+ delete[] noisevarchrom;
+
+ }
+ }
+
+ if (!Ldecomp->memoryAllocationFailed) {
+
+ Ldecomp->reconstruct (tmp1->L[0]);
+ }
+
+ if (!adecomp->memoryAllocationFailed) {
+
+ adecomp->reconstruct (tmp1->a[0]);
+ }
+
+ if (!bdecomp->memoryAllocationFailed) {
+
+ bdecomp->reconstruct (tmp1->b[0]);
+ }
+
+ DeNoise_Local (call, lp, original, transformed, tmp1, cx, cy);
+ delete tmp1;
+ delete Ldecomp;
+ delete adecomp;
+ delete bdecomp;
+ }
+
+ if (call == 2) { //simpleprocess
+ LabImage *bufwv;
+ int GW = transformed->W;
+ int GH = transformed->H;
+ int bfh = int (lp.ly + lp.lyT) + 1; //bfw bfh real size of square zone
+ int bfw = int (lp.lx + lp.lxL) + 1;
+ bufwv = new LabImage (bfw, bfh);
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++) //fill with 0
+ for (int jr = 0; jr < bfw; jr++) {
+ bufwv->L[ir][jr] = 0.f;
+ bufwv->a[ir][jr] = 0.f;
+ bufwv->b[ir][jr] = 0.f;
+
+ }
+
+#ifdef _OPENMP
+// #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < transformed->H ; y++) //{
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int loy = cy + y;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ bufwv->L[loy - begy - 1][lox - begx - 1] = original->L[y][x];//fill square buffer with datas
+ bufwv->a[loy - begy - 1][lox - begx - 1] = original->a[y][x];//fill square buffer with datas
+ bufwv->b[loy - begy - 1][lox - begx - 1] = original->b[y][x];//fill square buffer with datas
+ }
+ }
+
+ int DaubLen = 6;
+ int wavNestedLevels = 1;
+
+ int levwavL = levred;
+ int skip = 1;
+ wavelet_decomposition* Ldecomp = new wavelet_decomposition (bufwv->L[0], bufwv->W, bufwv->H, levwavL, 1, skip, max (1, wavNestedLevels), DaubLen);
+ wavelet_decomposition* adecomp = new wavelet_decomposition (bufwv->a[0], bufwv->W, bufwv->H, levwavL, 1, skip, max (1, wavNestedLevels), DaubLen);
+ wavelet_decomposition* bdecomp = new wavelet_decomposition (bufwv->b[0], bufwv->W, bufwv->H, levwavL, 1, skip, max (1, wavNestedLevels), DaubLen);
+
+ float madL[8][3];
+ float madab[8][3];
+ int edge;
+
+ if (!Ldecomp->memoryAllocationFailed) {
+
+ for (int lvl = 0; lvl < levred; lvl++) {
+ for (int dir = 1; dir < 4; dir++) {
+ int Wlvl_L = Ldecomp->level_W (lvl);
+ int Hlvl_L = Ldecomp->level_H (lvl);
+
+ float ** WavCoeffs_L = Ldecomp->level_coeffs (lvl);
+
+ madL[lvl][dir - 1] = SQR (Mad (WavCoeffs_L[dir], Wlvl_L * Hlvl_L));
+ }
+ }
+
+
+ int ind = 0;
+
+ float vari[levred];
+
+ if (levred == 7) {
+ edge = 2;
+ vari[0] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[1] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[2] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+
+ vari[3] = 8.f * SQR ((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0));
+ vari[4] = 8.f * SQR ((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0));
+ vari[5] = 8.f * SQR ((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0));
+ vari[6] = 8.f * SQR ((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0));
+ } else if (levred == 4) {
+ edge = 3;
+ vari[0] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[1] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[2] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0));
+ vari[3] = 8.f * SQR ((lp.noiself / 125.0) * (1.0 + lp.noiselc / 25.0));
+
+ }
+
+ if (( lp.noiself > 0.1f || lp.noiselc > 0.1f)) {
+ vari[0] = max (0.0001f, vari[0]);
+ vari[1] = max (0.0001f, vari[1]);
+ vari[2] = max (0.0001f, vari[2]);
+ vari[3] = max (0.0001f, vari[3]);
+
+ if (levred == 7) {
+
+ vari[4] = max (0.0001f, vari[4]);
+ vari[5] = max (0.0001f, vari[5]);
+ vari[6] = max (0.0001f, vari[6]);
+ }
+
+ float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL
+
+ WaveletDenoiseAllL (*Ldecomp, noisevarlum, madL, vari, edge);
+ }
+ }
+
+ float variC[levred];
+
+ if (!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) {
+
+ if (levred == 7) {
+ edge = 2;
+ variC[0] = SQR (lp.noisecf / 10.0);
+ variC[1] = SQR (lp.noisecf / 10.0);
+ variC[2] = SQR (lp.noisecf / 10.0);
+
+ variC[3] = SQR (lp.noisecf / 10.0);
+ variC[4] = SQR (lp.noisecf / 10.0);
+ variC[5] = SQR (lp.noisecc / 10.0);
+ variC[6] = SQR (lp.noisecc / 10.0);
+ } else if (levred == 4) {
+ edge = 3;
+ variC[0] = SQR (lp.noisecf / 10.0);
+ variC[1] = SQR (lp.noisecf / 10.0);
+ variC[2] = SQR (lp.noisecf / 10.0);
+ variC[3] = SQR (lp.noisecf / 10.0);
+ }
+
+ if (( lp.noisecf > 0.1f || lp.noisecc > 0.1f || noiscfactiv)) {
+ float minic = 0.0001f;
+
+ if (noiscfactiv) {
+ minic = 0.01f;//only for artifact shape detection
+ }
+
+ variC[0] = max (minic, variC[0]);
+ variC[1] = max (minic, variC[1]);
+ variC[2] = max (minic, variC[2]);
+ variC[3] = max (minic, variC[3]);
+
+ if (levred == 7) {
+
+ variC[4] = max (0.0001f, variC[4]);
+ variC[5] = max (0.0001f, variC[5]);
+ variC[6] = max (0.0001f, variC[6]);
+ }
+
+ float* noisevarchrom = new float[bfh * bfw];
+
+ for (int q = 0; q < bfh * bfw; q++) {
+ noisevarchrom[q] = 1.f;
+ }
+
+ float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0);
+ WaveletDenoiseAllAB (*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, false, false, false);
+ WaveletDenoiseAllAB (*Ldecomp, *bdecomp, noisevarchrom, madL, variC, edge, noisevarab_r, false, false, false);
+ delete[] noisevarchrom;
+
+ }
+ }
+
+ if (!Ldecomp->memoryAllocationFailed) {
+
+ Ldecomp->reconstruct (bufwv->L[0]);
+ }
+
+ if (!adecomp->memoryAllocationFailed) {
+
+ adecomp->reconstruct (bufwv->a[0]);
+ }
+
+ if (!bdecomp->memoryAllocationFailed) {
+
+ bdecomp->reconstruct (bufwv->b[0]);
+ }
+
+ DeNoise_Local (call, lp, original, transformed, bufwv, cx, cy);
+ delete bufwv;
+ delete Ldecomp;
+ delete adecomp;
+ delete bdecomp;
+
+
+ }
+
+ }
+
+
+ if (!lp.inv && (lp.chro != 0 || lp.ligh != 0.f || lp.curvact) && lp.colorena) { // || lllocalcurve)) { //interior ellipse renforced lightness and chroma //locallutili
+ float maxhur = -10.f;
+ float minhur = 10.f;
+ float hueplus = hueref + dhue;
+ float huemoins = hueref - dhue;
+
+ if (hueplus > M_PI) {
+ hueplus = hueref + dhue - 2.f * M_PI;
+ }
+
+ if (huemoins < -M_PI) {
+ huemoins = hueref - dhue + 2.f * M_PI;
+ }
+
+ LabImage *bufcolorig;
+ LabImage *bufcoltra;
+
+ if (call <= 3) { //simpleprocess
+ int GW = transformed->W;
+ int GH = transformed->H;
+ int bfh = int (lp.ly + lp.lyT) + 1; //bfw bfh real size of square zone
+ int bfw = int (lp.lx + lp.lxL) + 1;
+ bufcolorig = new LabImage (bfw, bfh);
+ // bufcoltra = new LabImage(bfw, bfh);
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++) //fill with 0
+ for (int jr = 0; jr < bfw; jr++) {
+ bufcolorig->L[ir][jr] = 0.f;
+ bufcolorig->a[ir][jr] = 0.f;
+ bufcolorig->b[ir][jr] = 0.f;
+
+ }
+
+#ifdef _OPENMP
+// #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < transformed->H ; y++) //{
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int loy = cy + y;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ bufcolorig->L[loy - begy - 1][lox - begx - 1] = original->L[y][x];//fill square buffer with datas
+ bufcolorig->a[loy - begy - 1][lox - begx - 1] = original->a[y][x];//fill square buffer with datas
+ bufcolorig->b[loy - begy - 1][lox - begx - 1] = original->b[y][x];//fill square buffer with datas
+ //float lumprov = bufcolorig->L[loy - begy - 1][lox - begx - 1];
+ //float lumnew = lllocalcurve[lumprov];
+
+ //float lumnew = lllocalcurve[bufcolorig->L[loy - begy - 1][lox - begx - 1]];
+ //bufcolorig->L[loy - begy - 1][lox - begx - 1] = lumnew;
+
+ // bufcoltra->L[loy - begy - 1][lox - begx - 1] = transformed->L[y][x];//fill square buffer with datas
+ // bufcoltra->a[loy - begy - 1][lox - begx - 1] = transformed->a[y][x];//fill square buffer with datas
+ // bufcoltra->b[loy - begy - 1][lox - begx - 1] = transformed->b[y][x];//fill square buffer with datas
+ }
+ }
+
+
+ }
+
+ /*
+ if(locallutili) printf("Courbe oui\n");
+ if(!locallutili) printf("Courbe NON\n");
+ if(lllocalcurve) printf("Courbe RE OUI\n");
+ if(!lllocalcurve) printf("CouRE NON\n");
+ */
+
+ ColorLight_Local (call, bufcolorig, bufcoltra, sp, moy, hueplus, huemoins, hueref, dhue, chromaref, lumaref, locallutili, lllocalcurve, loclhCurve, lp, deltE, original, transformed, cx, cy);
+
+ if (call <= 3) {
+
+ delete bufcolorig;
+ // delete bufcoltra;
+ }
+ }
+//inverse
+ else if (lp.inv && (lp.chro != 0 || lp.ligh != 0.f) && lp.colorena) {
+
+ InverseColorLight_Local (lp, original, transformed, cx, cy);
+ }
+
+
+ if (!lp.inv && lp.cont != 0 && lp.colorena) { //contrast interior ellipse
+ const float pm = lp.cont < 0.f ? -1.f : 1.f;
+ float hueplus = hueref + dhue;
+ float huemoins = hueref - dhue;
+
+ if (hueplus > M_PI) {
+ hueplus = hueref + dhue - 2.f * M_PI;
+ }
+
+ if (huemoins < -M_PI) {
+ huemoins = hueref - dhue + 2.f * M_PI;
+ }
+
+ Contrast_Local (call, moy, hueplus, huemoins, hueref, dhue, chromaref, pm, lco, lumaref, av, lp, deltE, original, transformed, cx, cy);
+ } else if (lp.inv && lp.cont != 0 && lp.colorena) {
+
+ float multL = (float)lp.cont * (maxl - 1.f) / 100.f + 1.f;
+ float multH = (float) lp.cont * (maxh - 1.f) / 100.f + 1.f;
+
+ lco.ah = (multH - 1.f) / (av - 100.f); //av ==> lumaref
+ lco.bh = 1.f - 100.f * lco.ah;
+ lco.al = (multL - 1.f) / av;
+ lco.bl = 1.f;
+
+ InverseContrast_Local (ave, lco, lp, original, transformed, cx, cy);
+ }
+
+ // }
+
+// end contrast interior and exterior
+
+//Tone mapping
+
+//&& lp.tonemapena
+ if (lp.strengt != 0.f && lp.tonemapena) {
+ LabImage *tmp1;
+ LabImage *tmp;
+
+ LabImage *bufgb;
+
+ if (call == 2) { //simpleprocess
+ int GW = transformed->W;
+ int GH = transformed->H;
+ int bfh = int (lp.ly + lp.lyT) + 1; //bfw bfh real size of square zone
+ int bfw = int (lp.lx + lp.lxL) + 1;
+ bufgb = new LabImage (bfw, bfh);
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++) //fill with 0
+ for (int jr = 0; jr < bfw; jr++) {
+ bufgb->L[ir][jr] = 0.f;
+ bufgb->a[ir][jr] = 0.f;
+ bufgb->b[ir][jr] = 0.f;
+ }
+
+#ifdef _OPENMP
+// #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < transformed->H ; y++) //{
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int loy = cy + y;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ bufgb->L[loy - begy - 1][lox - begx - 1] = original->L[y][x];//fill square buffer with datas
+ bufgb->a[loy - begy - 1][lox - begx - 1] = original->a[y][x];//fill square buffer with datas
+ bufgb->b[loy - begy - 1][lox - begx - 1] = original->b[y][x];//fill square buffer with datas
+ }
+ }
+
+ tmp1 = new LabImage (bfw, bfh);
+ ImProcFunctions::EPDToneMaplocal (bufgb, tmp1, 5 , 1);
+ } else {
+ tmp = new LabImage (transformed->W, transformed->H);
+ tmp->CopyFrom (original);
+ tmp1 = new LabImage (transformed->W, transformed->H);
+ ImProcFunctions::EPDToneMaplocal (tmp, tmp1, 5 , sk);
+ delete tmp;
+ }
+
+ float hueplus = hueref + dhue;
+ float huemoins = hueref - dhue;
+
+ if (hueplus > M_PI) {
+ hueplus = hueref + dhue - 2.f * M_PI;
+ }
+
+ if (huemoins < -M_PI) {
+ huemoins = hueref - dhue + 2.f * M_PI;
+ }
+
+
+ TM_Local (call, sp, tmp1, hueplus, huemoins, hueref, dhue, chromaref, lumaref, lp, deltE, original, transformed, cx, cy);
+
+ if (call == 2) {
+ delete bufgb;
+ }
+
+ delete tmp1;
+
+
+ }
+
+//begin cbdl
+ if (lp.mulloc[0] != 1.f || lp.mulloc[1] != 1.f || lp.mulloc[2] != 1.f || lp.mulloc[3] != 1.f || lp.mulloc[4] != 1.f && lp.cbdlena) {
+ int GW = original->W;
+ int GH = original->H;
+ float **bufsh;//buffer por square zone
+ float **loctemp;
+ float **hbuffer;
+ int bfh = int (lp.ly + lp.lyT) + 1; //bfw bfh real size of square zone
+ int bfw = int (lp.lx + lp.lxL) + 1;
+ float b_l = -5.f;
+ float t_l = 25.f;
+ float t_r = 120.f;
+ float b_r = 170.f;
+ double skinprot = 0.;
+ int choice = 0;
+
+
+ if (call == 2) { //call from simpleprocess
+ bufsh = new float*[bfh];
+
+ for (int i = 0; i < bfh; i++) {
+ bufsh[i] = new float[bfw];
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++) //fill with 0
+ for (int jr = 0; jr < bfw; jr++) {
+ bufsh[ir][jr] = 0.f;
+ }
+
+
+#ifdef _OPENMP
+// #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < transformed->H ; y++) //{
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int loy = cy + y;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ bufsh[loy - begy - 1][lox - begx - 1] = original->L[y][x];//fill square buffer with datas
+ }
+ }
+
+ loctemp = new float*[bfh];//allocate temp
+
+ for (int i = 0; i < bfh; i++) {
+ loctemp[i] = new float[bfw];
+ }
+
+ hbuffer = new float*[bfh];//allocate buffer for sharp
+
+ for (int i = 0; i < bfh; i++) {
+ hbuffer[i] = new float[bfw];
+ }
+
+ ImProcFunctions::cbdl_local_temp (bufsh, bufsh, loctemp, bfw, bfh, lp.mulloc, lp.threshol, skinprot, false, b_l, t_l, t_r, b_r, choice, sk);
+
+
+ } else { //call from dcrop.cc
+ loctemp = new float*[GH];//allocate temp
+
+ for (int i = 0; i < GH; i++) {
+ loctemp[i] = new float[GW];
+ }
+
+ ImProcFunctions::cbdl_local_temp (original->L, original->L, loctemp, GW, GH, lp.mulloc, lp.threshol, skinprot, false, b_l, t_l, t_r, b_r, choice, sk);
+
+ }
+
+
+ // I initialize these variable in case of !
+ float hueplus = hueref + dhue;
+ float huemoins = hueref - dhue;
+
+ if (hueplus > M_PI) {
+ hueplus = hueref + dhue - 2.f * M_PI;
+ }
+
+ if (huemoins < -M_PI) {
+ huemoins = hueref - dhue + 2.f * M_PI;
+ }
+
+ cbdl_Local (call, sp, loctemp, hueplus, huemoins, hueref, dhue, chromaref, lumaref, lp, deltE, original, transformed, cx, cy);
+
+ if (call == 2) {
+ for (int i = 0; i < bfh; i++) {
+ delete [] loctemp[i];
+ }
+
+ delete [] loctemp;
+
+ for (int i = 0; i < bfh; i++) {
+ delete [] bufsh[i];
+ }
+
+ delete [] bufsh;
+
+ for (int i = 0; i < bfh; i++) {
+ delete [] hbuffer[i];
+ }
+
+ delete [] hbuffer;
+ } else {
+ for (int i = 0; i < GH; i++) {
+ delete [] loctemp[i];
+ }
+
+ delete [] loctemp;
+
+ }
+
+
+
+ }
+
+// }
+
+//end cbdl
+ if (!lp.invshar && lp.shrad > 0.42 && call < 3 && lp.sharpena) { //interior ellipse for sharpening, call = 1 and 2 only with Dcrop and simpleprocess
+
+ int GW = original->W;
+ int GH = original->H;
+ float **bufsh;//buffer por square zone
+ float **loctemp;
+ float **hbuffer;
+ int bfh = int (lp.ly + lp.lyT) + 1; //bfw bfh real size of square zone
+ int bfw = int (lp.lx + lp.lxL) + 1;
+
+ if (call == 2) { //call from simpleprocess
+ bufsh = new float*[bfh];
+
+ for (int i = 0; i < bfh; i++) {
+ bufsh[i] = new float[bfw];
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++) //fill with 0
+ for (int jr = 0; jr < bfw; jr++) {
+ bufsh[ir][jr] = 0.f;
+ }
+
+
+#ifdef _OPENMP
+// #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < transformed->H ; y++) //{
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int loy = cy + y;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ bufsh[loy - begy - 1][lox - begx - 1] = original->L[y][x];//fill square buffer with datas
+ }
+ }
+
+ loctemp = new float*[bfh];//allocate temp
+
+ for (int i = 0; i < bfh; i++) {
+ loctemp[i] = new float[bfw];
+ }
+
+ hbuffer = new float*[bfh];//allocate buffer for sharp
+
+ for (int i = 0; i < bfh; i++) {
+ hbuffer[i] = new float[bfw];
+ }
+
+ //sharpen only square area instaed of all image
+ ImProcFunctions::deconvsharpeningloc (bufsh, hbuffer, bfw, bfh, loctemp, params->locallab.shardamping, (double)params->locallab.sharradius / 100., params->locallab.shariter, params->locallab.sharamount);
+ } else { //call from dcrop.cc
+ loctemp = new float*[GH];//allocate temp
+
+ for (int i = 0; i < GH; i++) {
+ loctemp[i] = new float[GW];
+ }
+
+ ImProcFunctions::deconvsharpeningloc (original->L, shbuffer, GW, GH, loctemp, params->locallab.shardamping, (double)params->locallab.sharradius / 100., params->locallab.shariter, params->locallab.sharamount);
+
+ }
+
+ float hueplus = hueref + dhue;
+ float huemoins = hueref - dhue;
+
+ if (hueplus > M_PI) {
+ hueplus = hueref + dhue - 2.f * M_PI;
+ }
+
+ if (huemoins < -M_PI) {
+ huemoins = hueref - dhue + 2.f * M_PI;
+ }
+
+ //sharpen ellipse and transition
+ Sharp_Local (call, sp, loctemp, hueplus, huemoins, hueref, dhue, chromaref, lumaref, lp, deltE, original, transformed, cx, cy);
+
+ //cleann all
+ if (call == 2 && !lp.invshar) {
+ for (int i = 0; i < bfh; i++) {
+ delete [] loctemp[i];
+ }
+
+ delete [] loctemp;
+
+ for (int i = 0; i < bfh; i++) {
+ delete [] bufsh[i];
+ }
+
+ delete [] bufsh;
+
+ for (int i = 0; i < bfh; i++) {
+ delete [] hbuffer[i];
+ }
+
+ delete [] hbuffer;
+ } else {
+ for (int i = 0; i < GH; i++) {
+ delete [] loctemp[i];
+ }
+
+ delete [] loctemp;
+
+ }
+
+ /* for (int i = 0; i < GH; i++) {
+ delete [] hbuffer[i];
+ }
+
+ delete [] hbuffer;
+ */
+
+ } else if (lp.invshar && lp.shrad > 0.42 && call < 3 && lp.sharpena) {
+ int GW = original->W;
+ int GH = original->H;
+
+ float **loctemp = new float*[GH];
+
+ for (int i = 0; i < GH; i++) {
+ loctemp[i] = new float[GW];
+ }
+
+ ImProcFunctions::deconvsharpeningloc (original->L, shbuffer, GW, GH, loctemp, params->locallab.shardamping, (double)params->locallab.sharradius / 100., params->locallab.shariter, params->locallab.sharamount);
+
+ float hueplus = hueref + dhue;
+ float huemoins = hueref - dhue;
+
+ if (hueplus > M_PI) {
+ hueplus = hueref + dhue - 2.f * M_PI;
+ }
+
+ if (huemoins < -M_PI) {
+ huemoins = hueref - dhue + 2.f * M_PI;
+ }
+
+ InverseSharp_Local (sp, loctemp, hueplus, huemoins, hueref, dhue, chromaref, lumaref, lp, deltE, original, transformed, cx, cy);
+
+ for (int i = 0; i < GH; i++) {
+ delete [] loctemp[i];
+ }
+
+ delete [] loctemp;
+
+ }
+
+ // }
+//&& lp.retiena
+ if (lp.str > 0.f && lp.retiena) {
+ int GW = transformed->W;
+ int GH = transformed->H;
+
+ LabImage *bufreti;
+
+ float **loctemp;
+ float **hbuffer;
+ int bfh = int (lp.ly + lp.lyT) + 1; //bfw bfh real size of square zone
+ int bfw = int (lp.lx + lp.lxL) + 1;
+
+ float hueplus = hueref + dhueret;
+ float huemoins = hueref - dhueret;
+
+ if (hueplus > M_PI) {
+ hueplus = hueref + dhueret - 2.f * M_PI;
+ }
+
+ if (huemoins < -M_PI) {
+ huemoins = hueref - dhueret + 2.f * M_PI;
+ }
+
+ int Hd, Wd;
+ Hd = GH;
+ Wd = GW;
+
+ if (!lp.invret && call <= 3) {
+
+ Hd = bfh;
+ Wd = bfw;
+ bufreti = new LabImage (bfw, bfh);
+
+ /* bufreti = new float*[bfh];
+
+ for (int i = 0; i < bfh; i++) {
+ bufreti[i] = new float[bfw];
+ }
+ */
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++) //fill with 0
+ for (int jr = 0; jr < bfw; jr++) {
+ bufreti->L[ir][jr] = 0.f;
+ bufreti->a[ir][jr] = 0.f;
+ bufreti->b[ir][jr] = 0.f;
+ }
+
+
+
+#ifdef _OPENMP
+// #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < transformed->H ; y++) //{
+ for (int x = 0; x < transformed->W; x++) {
+ int lox = cx + x;
+ int loy = cy + y;
+ int begx = int (lp.xc - lp.lxL);
+ int begy = int (lp.yc - lp.lyT);
+
+ if (lox >= (lp.xc - lp.lxL) && lox < (lp.xc + lp.lx) && loy >= (lp.yc - lp.lyT) && loy < (lp.yc + lp.ly)) {
+ bufreti->L[loy - begy - 1][lox - begx - 1] = original->L[y][x];//fill square buffer with datas
+ bufreti->a[loy - begy - 1][lox - begx - 1] = original->a[y][x];//fill square buffer with datas
+ bufreti->b[loy - begy - 1][lox - begx - 1] = original->b[y][x];//fill square buffer with datas
+ }
+ }
+
+
+
+ }
+
+ float *orig[Hd] ALIGNED16;
+ float *origBuffer = new float[Hd * Wd];
+
+ for (int i = 0; i < Hd; i++) {
+ orig[i] = &origBuffer[i * Wd];
+ }
+
+ float *orig1[Hd] ALIGNED16;
+ float *origBuffer1 = new float[Hd * Wd];
+
+ for (int i = 0; i < Hd; i++) {
+ orig1[i] = &origBuffer1[i * Wd];
+ }
+
+
+ LabImage *tmpl;
+
+ // LabImage *tmpl = new LabImage(Wd, Hd);
+ if (!lp.invret && call <= 3) {
+
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+ orig[ir][jr] = bufreti->L[ir][jr];
+ orig1[ir][jr] = bufreti->L[ir][jr];
+ }
+
+ tmpl = new LabImage (Wd, Hd);
+
+ } else {
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+ orig[ir][jr] = original->L[ir][jr];
+ orig1[ir][jr] = transformed->L[ir][jr];
+ }
+
+ tmpl = new LabImage (transformed->W, transformed->H);
+
+
+ }
+
+ float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax;
+ ImProcFunctions::MSRLocal (orig, tmpl->L, orig1, Wd, Hd, params->locallab, sk, locRETgainCcurve, 0, 4, 0.8f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+ tmpl->L[ir][jr] = orig[ir][jr];
+ }
+
+ if (!lp.invret) {
+
+ Reti_Local (call, hueplus, huemoins, hueref, dhueret, chromaref, lumaref, lp, deltE, original, transformed, tmpl, cx, cy, 0);
+ } else {
+ InverseReti_Local (lp, original, transformed, tmpl, cx, cy, 0);
+ }
+
+ if (params->locallab.chrrt > 0) {
+
+ if (!lp.invret && call <= 3) {
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+
+ orig[ir][jr] = sqrt (SQR (bufreti->a[ir][jr]) + SQR (bufreti->b[ir][jr]));
+ orig1[ir][jr] = sqrt (SQR (bufreti->a[ir][jr]) + SQR (bufreti->b[ir][jr]));
+ }
+
+ } else {
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int ir = 0; ir < GH; ir += 1)
+ for (int jr = 0; jr < GW; jr += 1) {
+ orig[ir][jr] = sqrt (SQR (original->a[ir][jr]) + SQR (original->b[ir][jr]));
+ orig1[ir][jr] = sqrt (SQR (transformed->a[ir][jr]) + SQR (transformed->b[ir][jr]));
+ }
+ }
+
+ ImProcFunctions::MSRLocal (orig, tmpl->L, orig1, Wd, Hd, params->locallab, sk, locRETgainCcurve, 1, 4, 0.8f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
+
+ if (!lp.invret && call <= 3) {
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+ float Chprov = orig1[ir][jr];
+ float2 sincosval;
+ sincosval.y = Chprov == 0.0f ? 1.f : bufreti->a[ir][jr] / Chprov;
+ sincosval.x = Chprov == 0.0f ? 0.f : bufreti->b[ir][jr] / Chprov;
+ tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y;
+ tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x;
+
+ }
+
+
+ } else {
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+ float Chprov = orig1[ir][jr];
+ float2 sincosval;
+ sincosval.y = Chprov == 0.0f ? 1.f : transformed->a[ir][jr] / Chprov;
+ sincosval.x = Chprov == 0.0f ? 0.f : transformed->b[ir][jr] / Chprov;
+ tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y;
+ tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x;
+
+ }
+ }
+
+ if (!lp.invret) {
+
+ Reti_Local (call, hueplus, huemoins, hueref, dhueret, chromaref, lumaref, lp, deltE, original, transformed, tmpl, cx, cy, 1);
+ } else {
+ InverseReti_Local (lp, original, transformed, tmpl, cx, cy, 1);
+ }
+
+ }
+
+ delete tmpl;
+ delete [] origBuffer;
+ delete [] origBuffer1;
+
+ if (!lp.invret && call <= 3) {
+
+ delete bufreti;
+ }
+ }
+
+
+// Gamut and Munsell control - very important do not desactivated to avoid crash
+ if (params->locallab.avoid) {
+ TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working);
+ float wip[3][3] = {
+ {static_cast (wiprof[0][0]), static_cast (wiprof[0][1]), static_cast (wiprof[0][2])},
+ {static_cast (wiprof[1][0]), static_cast (wiprof[1][1]), static_cast (wiprof[1][2])},
+ {static_cast (wiprof[2][0]), static_cast (wiprof[2][1]), static_cast (wiprof[2][2])}
+ };
+ const bool highlight = params->toneCurve.hrenabled;
+ const bool needHH = (lp.chro != 0.f);
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+#ifdef __SSE2__
+ float atan2Buffer[transformed->W] ALIGNED16;
+ float sqrtBuffer[transformed->W] ALIGNED16;
+ float sincosyBuffer[transformed->W] ALIGNED16;
+ float sincosxBuffer[transformed->W] ALIGNED16;
+ vfloat c327d68v = F2V (327.68f);
+ vfloat onev = F2V (1.f);
+#endif
+
+#ifdef _OPENMP
+#ifdef _DEBUG
+ #pragma omp for schedule(dynamic,16) firstprivate(MunsDebugInfo)
+#else
+ #pragma omp for schedule(dynamic,16)
+#endif
+#endif
+
+ for (int y = 0; y < transformed->H; y++) {
+#ifdef __SSE2__
+ int i = 0;
+
+ for (; i < transformed->W - 3; i += 4) {
+ vfloat av = LVFU (transformed->a[y][i]);
+ vfloat bv = LVFU (transformed->b[y][i]);
+
+ if (needHH) { // only do expensive atan2 calculation if needed
+ STVF (atan2Buffer[i], xatan2f (bv, av));
+ }
+
+ vfloat Chprov1v = vsqrtf (SQRV (bv) + SQRV (av));
+ STVF (sqrtBuffer[i], Chprov1v / c327d68v);
+ vfloat sincosyv = av / Chprov1v;
+ vfloat sincosxv = bv / Chprov1v;
+ vmask selmask = vmaskf_eq (Chprov1v, ZEROV);
+ sincosyv = vself (selmask, onev, sincosyv);
+ sincosxv = vselfnotzero (selmask, sincosxv);
+ STVF (sincosyBuffer[i], sincosyv);
+ STVF (sincosxBuffer[i], sincosxv);
+ }
+
+ for (; i < transformed->W; i++) {
+ float aa = transformed->a[y][i];
+ float bb = transformed->b[y][i];
+
+ if (needHH) { // only do expensive atan2 calculation if needed
+ atan2Buffer[i] = xatan2f (bb, aa);
+ }
+
+ float Chprov1 = sqrtf (SQR (bb) + SQR (aa));
+ sqrtBuffer[i] = Chprov1 / 327.68f;
+
+ if (Chprov1 == 0.0f) {
+ sincosyBuffer[i] = 1.f;
+ sincosxBuffer[i] = 0.0f;
+ } else {
+ sincosyBuffer[i] = aa / Chprov1;
+ sincosxBuffer[i] = bb / Chprov1;
+ }
+
+ }
+
+#endif
+
+ for (int x = 0; x < transformed->W; x++) {
+ float Lprov1 = transformed->L[y][x] / 327.68f;
+ float2 sincosval;
+#ifdef __SSE2__
+ float HH = atan2Buffer[x]; // reading HH from line buffer even if line buffer is not filled is faster than branching
+ float Chprov1 = sqrtBuffer[x];
+ sincosval.y = sincosyBuffer[x];
+ sincosval.x = sincosxBuffer[x];
+ float chr;
+
+#else
+ float aa = transformed->a[y][x];
+ float bb = transformed->b[y][x];
+ float HH, chr;
+
+ if (needHH) { // only do expensive atan2 calculation if needed
+ HH = xatan2f (bb, aa);
+ }
+
+ float Chprov1 = sqrtf (SQR (aa) + SQR (bb)) / 327.68f;
+
+ 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
+
+#ifdef _DEBUG
+ bool neg = false;
+ bool more_rgb = false;
+// Color::pregamutlab (Lprov1, HH, chr);
+ Chprov1 = min (Chprov1, chr);
+
+ Color::gamutLchonly (sincosval, Lprov1, Chprov1, wip, highlight, 0.15f, 0.92f, neg, more_rgb);
+#else
+ Color::pregamutlab (Lprov1, HH, chr);
+ Chprov1 = min (Chprov1, chr);
+ Color::gamutLchonly (sincosval, Lprov1, Chprov1, wip, highlight, 0.15f, 0.92f);
+#endif
+
+ transformed->L[y][x] = Lprov1 * 327.68f;
+ transformed->a[y][x] = 327.68f * Chprov1 * sincosval.y;
+ transformed->b[y][x] = 327.68f * Chprov1 * sincosval.x;
+
+ if (needHH) {
+ float Lprov2 = original->L[y][x] / 327.68f;
+ float correctionHue = 0.f; // Munsell's correction
+ float correctlum = 0.f;
+ float memChprov = sqrtf (SQR (original->a[y][x]) + SQR (original->b[y][x])) / 327.68f;
+ float Chprov = sqrtf (SQR (transformed->a[y][x]) + SQR (transformed->b[y][x])) / 327.68f;
+#ifdef _DEBUG
+ Color::AllMunsellLch (true, Lprov1, Lprov2, HH, Chprov, memChprov, correctionHue, correctlum, MunsDebugInfo);
+#else
+ Color::AllMunsellLch (true, Lprov1, Lprov2, HH, Chprov, memChprov, correctionHue, correctlum);
+#endif
+
+ if (fabs (correctionHue) < 0.015f) {
+ HH += correctlum; // correct only if correct Munsell chroma very little.
+ }
+
+ float2 sincosval = xsincosf (HH + correctionHue);
+
+ transformed->a[y][x] = 327.68f * Chprov * sincosval.y; // apply Munsell
+ transformed->b[y][x] = 327.68f * Chprov * sincosval.x;
+ }
+ }
+ }
+ }
+ }
+
+ if (lp.qualmet == 1) {
+
+ for (int i = 0; i < GH; i++) {
+ delete [] deltE[i];
+ }
+
+ delete [] deltE;
+ }
+
+#ifdef _DEBUG
+
+ if (settings->verbose) {
+ t2e.set();
+ printf ("Color::AllMunsellLch (correction performed in %d usec):\n", t2e.etime (t1e));
+ // printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad dep=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass);
+ // printf(" Munsell luminance : MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad dep=%i\n", MunsDebugInfo->maxdhuelum[0], MunsDebugInfo->maxdhuelum[1], MunsDebugInfo->maxdhuelum[2], MunsDebugInfo->maxdhuelum[3], MunsDebugInfo->depassLum);
+ }
+
+ delete MunsDebugInfo;
+#endif
+
+ }
+
+}
+
+}
diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc
index 2dbdbafb1..5ae650c54 100644
--- a/rtengine/ipretinex.cc
+++ b/rtengine/ipretinex.cc
@@ -52,7 +52,7 @@
namespace
{
-void retinex_scales( float* scales, int nscales, int mode, int s, float high)
+void retinex_scales ( float* scales, int nscales, int mode, int s, float high)
{
if ( nscales == 1 ) {
scales[0] = (float)s / 2.f;
@@ -67,19 +67,19 @@ void retinex_scales( float* scales, int nscales, int mode, int s, float high)
scales[nscales - i - 1] = 2.0f + (float)i * size_step;
}
} else if (mode == 1) {
- size_step = (float)log(s - 2.0f) / (float) nscales;
+ size_step = (float)log (s - 2.0f) / (float) nscales;
for (int i = 0; i < nscales; ++i ) {
scales[nscales - i - 1] = 2.0f + (float)pow (10.f, (i * size_step) / log (10.f));
}
} else if (mode == 2) {
- size_step = (float) log(s - 2.0f) / (float) nscales;
+ size_step = (float) log (s - 2.0f) / (float) nscales;
for ( int i = 0; i < nscales; ++i ) {
scales[i] = s - (float)pow (10.f, (i * size_step) / log (10.f));
}
} else if (mode == 3) {
- size_step = (float) log(s - 2.0f) / (float) nscales;
+ size_step = (float) log (s - 2.0f) / (float) nscales;
for ( int i = 0; i < nscales; ++i ) {
scales[i] = high * s - (float)pow (10.f, (i * size_step) / log (10.f));
@@ -88,7 +88,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)
+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
double vsquared = 0.f;
@@ -125,7 +125,7 @@ void mean_stddv2( float **dst, float &mean, float &stddv, int W_L, int H_L, floa
mean = sum / (double) (W_L * H_L);
vsquared /= (double) W_L * H_L;
stddv = ( vsquared - (mean * mean) );
- stddv = (float)sqrt(stddv);
+ stddv = (float)sqrt (stddv);
}
}
@@ -136,7 +136,7 @@ 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)
+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)
{
if (deh.enabled) {//enabled
@@ -156,7 +156,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
float gradstr = (float)deh.grads;
float strength = (float) deh.str / 100.f; // Blend with original L channel data
float limD = (float) deh.limd;
- limD = pow(limD, 1.7f);//about 2500 enough
+ limD = pow (limD, 1.7f); //about 2500 enough
limD *= useHslLin ? 10.f : 1.f;
float ilimD = 1.f / limD;
float hig = ((float) deh.highl) / 100.f;
@@ -164,8 +164,8 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
float hl = deh.baselog;
scal = deh.skal;
- if(hl >= 2.71828f) {
- elogt = 2.71828f + SQR(SQR(hl - 2.71828f));
+ if (hl >= 2.71828f) {
+ elogt = 2.71828f + SQR (SQR (hl - 2.71828f));
} else {
elogt = hl;
}
@@ -179,7 +179,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
elogt = 2.71828f;//disabled baselog
bool lhutili = false;
- FlatCurve* shcurve = new FlatCurve(deh.lhcurve); //curve L=f(H)
+ FlatCurve* shcurve = new FlatCurve (deh.lhcurve); //curve L=f(H)
if (!shcurve || shcurve->isIdentity()) {
if (shcurve) {
@@ -194,7 +194,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
bool higplus = false ;
int moderetinex = 2; // default to 2 ( deh.retinexMethod == "high" )
- if(deh.retinexMethod == "highliplus") {
+ if (deh.retinexMethod == "highliplus") {
higplus = true;
moderetinex = 3;
} else if (deh.retinexMethod == "uni") {
@@ -208,29 +208,29 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
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
+ for (int it = 1; it < iter + 1; it++) { //iter nb max of iterations
float high = bbhi + aahi * (float) deh.highl;
float grad = 1.f;
float sc = scal;
- if(gradient == 0) {
+ if (gradient == 0) {
grad = 1.f;
sc = 3.f;
- } else if(gradient == 1) {
+ } else if (gradient == 1) {
grad = 0.25f * it + 0.75f;
sc = -0.5f * it + 4.5f;
- } else if(gradient == 2) {
+ } else if (gradient == 2) {
grad = 0.5f * it + 0.5f;
sc = -0.75f * it + 5.75f;
- } else if(gradient == 3) {
+ } else if (gradient == 3) {
grad = 0.666f * it + 0.333f;
sc = -0.75f * it + 5.75f;
- } else if(gradient == 4) {
+ } else if (gradient == 4) {
grad = 0.8f * it + 0.2f;
sc = -0.75f * it + 5.75f;
- } else if(gradient == 5) {
- if(moderetinex != 3) {
+ } else if (gradient == 5) {
+ if (moderetinex != 3) {
grad = 2.5f * it - 1.5f;
} else {
float aa = (11.f * high - 1.f) / 4.f;
@@ -239,8 +239,8 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
sc = -0.75f * it + 5.75f;
- } else if(gradient == 6) {
- if(moderetinex != 3) {
+ } else if (gradient == 6) {
+ if (moderetinex != 3) {
grad = 5.f * it - 4.f;
} else {
float aa = (21.f * high - 1.f) / 4.f;
@@ -251,24 +251,24 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
sc = -0.75f * it + 5.75f;
}
- else if(gradient == -1) {
+ else if (gradient == -1) {
grad = -0.125f * it + 1.125f;
sc = 3.f;
}
- if(iter == 1) {
+ if (iter == 1) {
sc = scal;
} else {
//adjust sc in function of choice of scale by user if iterations
- if(scal < 3) {
+ if (scal < 3) {
sc -= 1;
- if(sc < 1.f) {//avoid 0
+ if (sc < 1.f) { //avoid 0
sc = 1.f;
}
}
- if(scal > 4) {
+ if (scal > 4) {
sc += 1;
}
}
@@ -276,20 +276,20 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
float varx;
float limdx, ilimdx;
- if(gradvart != 0) {
- if(gradvart == 1) {
+ if (gradvart != 0) {
+ if (gradvart == 1) {
varx = vart * (-0.125f * it + 1.125f);
limdx = limD * (-0.125f * it + 1.125f);
ilimdx = 1.f / limdx;
- } else if(gradvart == 2) {
+ } else if (gradvart == 2) {
varx = vart * (-0.2f * it + 1.2f);
limdx = limD * (-0.2f * it + 1.2f);
ilimdx = 1.f / limdx;
- } else if(gradvart == -1) {
+ } else if (gradvart == -1) {
varx = vart * (0.125f * it + 0.875f);
limdx = limD * (0.125f * it + 0.875f);
ilimdx = 1.f / limdx;
- } else if(gradvart == -2) {
+ } else if (gradvart == -2) {
varx = vart * (0.4f * it + 0.6f);
limdx = limD * (0.4f * it + 0.6f);
ilimdx = 1.f / limdx;
@@ -300,30 +300,30 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
ilimdx = ilimD;
}
- scal = round(sc);
+ scal = round (sc);
float ks = 1.f;
- if(gradstr != 0) {
- if(gradstr == 1) {
- if(it <= 3) {
+ if (gradstr != 0) {
+ if (gradstr == 1) {
+ if (it <= 3) {
ks = -0.3f * it + 1.6f;
} else {
ks = 0.5f;
}
- } else if(gradstr == 2) {
- if(it <= 3) {
+ } else if (gradstr == 2) {
+ if (it <= 3) {
ks = -0.6f * it + 2.2f;
} else {
ks = 0.3f;
}
- } else if(gradstr == -1) {
- if(it <= 3) {
+ } else if (gradstr == -1) {
+ if (it <= 3) {
ks = 0.2f * it + 0.6f;
} else {
ks = 1.2f;
}
- } else if(gradstr == -2) {
- if(it <= 3) {
+ } else if (gradstr == -2) {
+ if (it <= 3) {
ks = 0.4f * it + 0.2f;
} else {
ks = 1.5f;
@@ -336,7 +336,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
constexpr auto maxRetinexScales = 8;
float RetinexScales[maxRetinexScales];
- retinex_scales( RetinexScales, scal, moderetinex, nei / grad, high );
+ retinex_scales ( RetinexScales, scal, moderetinex, nei / grad, high );
float *src[H_L] ALIGNED16;
float *srcBuffer = new float[H_L * W_L];
@@ -352,11 +352,11 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
int mapmet = 0;
- if(deh.mapMethod == "map") {
+ if (deh.mapMethod == "map") {
mapmet = 2;
- } else if(deh.mapMethod == "mapT") {
+ } else if (deh.mapMethod == "mapT") {
mapmet = 3;
- } else if(deh.mapMethod == "gaus") {
+ } else if (deh.mapMethod == "gaus") {
mapmet = 4;
}
@@ -364,13 +364,13 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
int viewmet = 0;
- if(deh.viewMethod == "mask") {
+ if (deh.viewMethod == "mask") {
viewmet = 1;
- } else if(deh.viewMethod == "tran") {
+ } else if (deh.viewMethod == "tran") {
viewmet = 2;
- } else if(deh.viewMethod == "tran2") {
+ } else if (deh.viewMethod == "tran2") {
viewmet = 3;
- } else if(deh.viewMethod == "unsharp") {
+ } else if (deh.viewMethod == "unsharp") {
viewmet = 4;
}
@@ -391,7 +391,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
out[i] = &outBuffer[i * W_L];
}
- if(viewmet == 3 || viewmet == 2) {
+ if (viewmet == 3 || viewmet == 2) {
tranBuffer = new float[H_L * W_L];
for (int i = 0; i < H_L; i++) {
@@ -399,11 +399,11 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
}
- const float logBetaGain = xlogf(16384.f);
+ const float logBetaGain = xlogf (16384.f);
float pond = logBetaGain / (float) scal;
- if(!useHslLin) {
- pond /= log(elogt);
+ if (!useHslLin) {
+ pond /= log (elogt);
}
auto shmap = ((mapmet == 2 || mapmet == 3 || mapmet == 4) && it == 1) ? new SHMap (W_L, H_L, true) : nullptr;
@@ -415,12 +415,12 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
#pragma omp parallel
#endif
{
- if(scale == scal - 1)
+ if (scale == scal - 1)
{
gaussianBlur (src, out, W_L, H_L, RetinexScales[scale], buffer);
} else { // reuse result of last iteration
// out was modified in last iteration => restore it
- if((((mapmet == 2 && scale > 1) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1)
+ if ((((mapmet == 2 && scale > 1) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1)
{
#ifdef _OPENMP
#pragma omp for
@@ -433,9 +433,9 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
}
- gaussianBlur (out, out, W_L, H_L, sqrtf(SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), buffer);
+ gaussianBlur (out, out, W_L, H_L, sqrtf (SQR (RetinexScales[scale]) - SQR (RetinexScales[scale + 1])), buffer);
}
- if((((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1 && scale > 0)
+ if ((((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1 && scale > 0)
{
// out will be modified => store it for use in next iteration. We even don't need a new buffer because 'buffer' is free after gaussianBlur :)
#ifdef _OPENMP
@@ -450,20 +450,20 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
}
- if(((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) {
+ if (((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) {
shmap->updateL (out, shradius, true, 1);
h_th = shmap->max_f - deh.htonalwidth * (shmap->max_f - shmap->avg) / 100;
s_th = deh.stonalwidth * (shmap->avg - shmap->min_f) / 100;
}
#ifdef __SSE2__
- vfloat pondv = F2V(pond);
- vfloat limMinv = F2V(ilimdx);
- vfloat limMaxv = F2V(limdx);
+ vfloat pondv = F2V (pond);
+ vfloat limMinv = F2V (ilimdx);
+ vfloat limMaxv = F2V (limdx);
#endif
- if(mapmet > 0 && mapcontlutili && it == 1) {
+ 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;
@@ -482,7 +482,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
- if(((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) {
+ 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
@@ -515,32 +515,32 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
#ifdef __SSE2__
- if(useHslLin) {
+ if (useHslLin) {
for (; j < W_L - 3; j += 4) {
- _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * (LIMV(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv) ));
+ _mm_storeu_ps (&luminance[i][j], LVFU (luminance[i][j]) + pondv * (LIMV (LVFU (src[i][j]) / LVFU (out[i][j]), limMinv, limMaxv) ));
}
} else {
for (; j < W_L - 3; j += 4) {
- _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(LIMV(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv) ));
+ _mm_storeu_ps (&luminance[i][j], LVFU (luminance[i][j]) + pondv * xlogf (LIMV (LVFU (src[i][j]) / LVFU (out[i][j]), limMinv, limMaxv) ));
}
}
#endif
- if(useHslLin) {
+ if (useHslLin) {
for (; j < W_L; j++) {
- luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimdx, limdx));
+ luminance[i][j] += pond * (LIM (src[i][j] / out[i][j], ilimdx, limdx));
}
} else {
for (; j < W_L; j++) {
- luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimdx, limdx)); // /logt ?
+ luminance[i][j] += pond * xlogf (LIM (src[i][j] / out[i][j], ilimdx, limdx)); // /logt ?
}
}
}
}
- if(mapmet > 1) {
- if(shmap) {
+ if (mapmet > 1) {
+ if (shmap) {
delete shmap;
}
}
@@ -554,7 +554,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
float stddv = 0.f;
// I call mean_stddv2 instead of mean_stddv ==> logBetaGain
- mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+ mean_stddv2 ( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
//printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr);
//mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr);
@@ -584,7 +584,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
for (int i = 0; i < H_L; i++ )
for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission
- if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
+ 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;
@@ -595,7 +595,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
//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) {
+ if (viewmet == 3 || viewmet == 2) {
tran[i][j] = luminance[i][j];
}
}
@@ -619,7 +619,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
for (int i = borderL; i < hei - borderL; i++) {
for (int j = borderL; j < wid - borderL; j++) {
- tmL[i][j] = median(luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1]); //3x3
+ tmL[i][j] = median (luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1]); //3x3
}
}
@@ -639,7 +639,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
// I call mean_stddv2 instead of mean_stddv ==> logBetaGain
//mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr);
- mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+ mean_stddv2 ( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
}
@@ -689,7 +689,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
stddv = 0.f;
// I call mean_stddv2 instead of mean_stddv ==> logBetaGain
- mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+ mean_stddv2 ( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
float asig = 0.f, bsig = 0.f, amax = 0.f, bmax = 0.f, amin = 0.f, bmin = 0.f;
if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve
@@ -724,7 +724,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) {
float absciss;
- if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
+ 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;
@@ -747,33 +747,33 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
float str = strengthx;
- if(lhutili && it == 1) { // S=f(H)
+ if (lhutili && it == 1) { // S=f(H)
{
float HH = exLuminance[i][j];
float valparam;
- if(useHsl || useHslLin) {
- valparam = float((shcurve->getVal(HH) - 0.5f));
+ if (useHsl || useHslLin) {
+ valparam = float ((shcurve->getVal (HH) - 0.5f));
} else {
- valparam = float((shcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f));
+ valparam = float ((shcurve->getVal (Color::huelab_to_huehsv2 (HH)) - 0.5f));
}
str *= (1.f + 2.f * valparam);
}
}
- if(higplus && exLuminance[i][j] > 65535.f * hig) {
+ if (higplus && exLuminance[i][j] > 65535.f * hig) {
str *= hig;
}
- if(viewmet == 0) {
- luminance[i][j] = intp(str, clipretinex( cd, 0.f, 32768.f ), originalLuminance[i][j]);
- } else if(viewmet == 1) {
+ if (viewmet == 0) {
+ luminance[i][j] = intp (str, clipretinex ( cd, 0.f, 32768.f ), originalLuminance[i][j]);
+ } else if (viewmet == 1) {
luminance[i][j] = out[i][j];
- } else if(viewmet == 4) {
+ } 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) {
+ } 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];
@@ -808,11 +808,444 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
}
- if(tranBuffer) {
+ if (tranBuffer) {
delete [] tranBuffer;
}
}
}
+void ImProcFunctions::MSRLocal (float** luminance, float** templ, const float* const *originalLuminance, const int width, const int height, const LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax)
+{
+ BENCHFUN
+ bool py = true;
+
+ if (py) {//enabled
+ float mean, stddv, maxtr, mintr;
+ float delta;
+ constexpr float eps = 2.f;
+ constexpr bool useHsl = false; //never used
+ constexpr bool useHslLin = false;//never used
+ const float offse = 0.f; //loc.offs;
+ const float chrT = (float) (loc.chrrt) / 100.f;
+ const int scal = scall;//3;//loc.scale;;
+ const float vart = loc.vart / 100.f;//variance
+ const float strength = loc.str / 100.f; // Blend with original L channel data
+ float limD = 10.f;//(float) loc.limd;
+ limD = pow (limD, 1.7f); //about 2500 enough
+ //limD *= useHslLin ? 10.f : 1.f;
+ float ilimD = 1.f / limD;
+ const float elogt = 2.71828f;
+
+ //empirical skip evaluation : very difficult because quasi all parameters interfere
+ //to test on several images
+ int nei = (int) (krad * loc.neigh);
+
+ if (skip >= 4) {
+ nei = (int) (0.1f * nei + 2.f); //not too bad
+ } else if (skip > 1 && skip < 4) {
+ nei = (int) (0.3f * nei + 2.f);
+ }
+
+ int moderetinex;
+
+ if (loc.retinexMethod == "uni") {
+ moderetinex = 0;
+ } else if (loc.retinexMethod == "low") {
+ moderetinex = 1;
+ } else {
+ if (loc.retinexMethod == "high") { // default to 2 ( deh.retinexMethod == "high" )
+ moderetinex = 2;
+ }
+ }
+
+ const float high = 0.f; // Dummy to pass to retinex_scales(...)
+
+ constexpr auto maxRetinexScales = 8;
+ float RetinexScales[maxRetinexScales];
+
+ retinex_scales ( RetinexScales, scal, moderetinex, nei, high );
+
+
+ const int H_L = height;
+ const int W_L = width;
+ float *src[H_L] ALIGNED16;
+ float *srcBuffer = new float[H_L * W_L];
+
+ for (int i = 0; i < H_L; i++) {
+ src[i] = &srcBuffer[i * W_L];
+ }
+
+ float hi = 0.f;
+ float lo = 0.f;
+ const float shHighlights = (100.f - 0.f) / 100.f; //loc.highlights
+ const float shShadows = (100.f - 0.f) / 100.f; //loc.shadows
+ const int mapmet = (hi > 0 || lo > 0) ? 4 : 0;
+ // const double shradius = mapmet == 4 ? loc.radius : 40.;
+ const double shradius = mapmet == 4 ? 40 : 40.;
+ constexpr int it = 1;//in case of !!
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int i = 0; i < H_L; i++)
+ for (int j = 0; j < W_L; j++) {
+ src[i][j] = luminance[i][j] + eps;
+ luminance[i][j] = 0.f;
+ }
+
+ float *out[H_L] ALIGNED16;
+ float *outBuffer = new float[H_L * W_L];
+
+ for (int i = 0; i < H_L; i++) {
+ out[i] = &outBuffer[i * W_L];
+ }
+
+ const float logBetaGain = xlogf (16384.f);
+ float pond = logBetaGain / (float) scal;
+
+ if (!useHslLin) {
+ pond /= log (elogt);
+ }
+
+ auto shmap = mapmet == 4 ? new SHMap (W_L, H_L, true) : nullptr;
+
+ float *buffer = new float[W_L * H_L];
+
+ for ( int scale = scal - 1; scale >= 0; scale-- ) {
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+
+ if (scale == scal - 1)
+ {
+ gaussianBlur (src, out, W_L, H_L, RetinexScales[scale], buffer);
+ } else { // reuse result of last iteration
+ // out was modified in last iteration => restore it
+ if (((mapmet == 4)) && it == 1)
+ {
+
+#ifdef _OPENMP
+ #pragma omp for
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ out[i][j] = buffer[i * W_L + j];
+ }
+ }
+ }
+
+ gaussianBlur (out, out, W_L, H_L, sqrtf (SQR (RetinexScales[scale]) - SQR (RetinexScales[scale + 1])), buffer);
+ }
+ if ((mapmet == 4) && it == 1 && scale > 0)
+ {
+ // out will be modified => store it for use in next iteration. We even don't need a new buffer because 'buffer' is free after gaussianBlur :)
+#ifdef _OPENMP
+ #pragma omp for
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ buffer[i * W_L + j] = out[i][j];
+ }
+ }
+ }
+ }
+
+ float h_th, s_th;
+ float h_thcomp, s_thcomp;
+
+ if ((mapmet == 4) && it == 1) {
+ shmap->updateL (out, shradius, true, 1);
+ h_thcomp = 0.f;//shmap->max_f - loc.htonalwidth * (shmap->max_f - shmap->avg) / 100.f;
+ h_th = h_thcomp - (shHighlights * h_thcomp);
+ s_thcomp = 0.f;//loc.stonalwidth * (shmap->avg - shmap->min_f) / 100.f;
+ s_th = s_thcomp - (shShadows * s_thcomp);
+ }
+
+ if ((mapmet == 4) && it == 1) {
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ float mapval = 1.f + shmap->map[i][j];
+
+ if (mapval > h_thcomp) {
+ out[i][j] *= h_th / mapval + shHighlights;
+ } else if (mapval < s_thcomp) {
+ out[i][j] *= s_th / mapval + shShadows;
+ }
+ }
+ }
+
+ }
+
+#ifdef __SSE2__
+ vfloat pondv = F2V (pond);
+ vfloat limMinv = F2V (ilimD);
+ vfloat limMaxv = F2V (limD);
+
+#endif
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ int j = 0;
+
+#ifdef __SSE2__
+
+ if (useHslLin) { //keep in case of ??
+ for (; j < W_L - 3; j += 4) {
+ _mm_storeu_ps (&luminance[i][j], LVFU (luminance[i][j]) + pondv * (LIMV (LVFU (src[i][j]) / LVFU (out[i][j]), limMinv, limMaxv) ));
+ }
+ } else {//always Lab mode due to Wavelet
+ for (; j < W_L - 3; j += 4) {
+ _mm_storeu_ps (&luminance[i][j], LVFU (luminance[i][j]) + pondv * xlogf (LIMV (LVFU (src[i][j]) / LVFU (out[i][j]), limMinv, limMaxv) ));
+ }
+ }
+
+#endif
+
+ if (useHslLin) {
+ for (; j < W_L; j++) {
+ luminance[i][j] += pond * (LIM (src[i][j] / out[i][j], ilimD, limD));
+ }
+ } else {
+ for (; j < W_L; j++) {
+ luminance[i][j] += pond * xlogf (LIM (src[i][j] / out[i][j], ilimD, limD)); // /logt ?
+ }
+ }
+ }
+ }
+
+ if (shmap) {
+ delete shmap;
+ }
+
+ shmap = nullptr;
+
+ delete [] buffer;
+ delete [] outBuffer;
+ outBuffer = nullptr;
+ delete [] srcBuffer;
+
+ mean = 0.f;
+ stddv = 0.f;
+
+ mean_stddv2 ( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+ //printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr);
+
+ // mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr);
+
+ bool retcurve = false;//wavRETCcurve
+
+ if (retcurve && mean != 0.f && stddv != 0.f) { //if curve
+ float asig = 0.166666f / stddv;
+ float bsig = 0.5f - asig * mean;
+ float amax = 0.333333f / (maxtr - mean - stddv);
+ float bmax = 1.f - amax * maxtr;
+ float amin = 0.333333f / (mean - stddv - mintr);
+ float bmin = -amin * mintr;
+
+ asig *= 500.f;
+ bsig *= 500.f;
+ amax *= 500.f;
+ bmax *= 500.f;
+ amin *= 500.f;
+ bmin *= 500.f;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int i = 0; i < H_L; i++ )
+ for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission
+ 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 {
+ absciss = amin * luminance[i][j] + bmin;
+ }
+
+ // luminance[i][j] *= (-1.f + 4.f * wavRETCcurve[absciss]); //new transmission
+ }
+
+ // median filter on transmission ==> reduce artifacts
+ bool ty = false;
+
+ if (ty) {//not used here to simplify interface
+ int wid = W_L;
+ int hei = H_L;
+ float *tmL[hei] ALIGNED16;
+ float *tmLBuffer = new float[wid * hei];
+ int borderL = 1;
+
+ for (int i = 0; i < hei; i++) {
+ tmL[i] = &tmLBuffer[i * wid];
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int i = borderL; i < hei - borderL; i++) {
+ float pp[9], temp;
+
+ for (int j = borderL; j < wid - borderL; j++) {
+ tmL[i][j] = median (luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1]); //3x3
+ }
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int i = borderL; i < hei - borderL; i++ ) {
+ for (int j = borderL; j < wid - borderL; j++) {
+ luminance[i][j] = tmL[i][j];
+ }
+ }
+
+ delete [] tmLBuffer;
+
+ }
+
+ // I call mean_stddv2 instead of mean_stddv ==> logBetaGain
+ // mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr);
+ mean_stddv2 ( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+
+ }
+
+ float epsil = 0.1f;
+
+ mini = mean - vart * stddv;
+
+ if (mini < mintr) {
+ mini = mintr + epsil;
+ }
+
+ maxi = mean + vart * stddv;
+
+ if (maxi > maxtr) {
+ maxi = maxtr - epsil;
+ }
+
+ delta = maxi - mini;
+ //printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr);
+
+ if ( !delta ) {
+ delta = 1.0f;
+ }
+
+ float cdfactor = 32768.f / delta;
+ maxCD = -9999999.f;
+ minCD = 9999999.f;
+
+ //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;
+ // bool gaincurve = false; //wavRETgainCcurve
+ const bool hasWavRetGainCurve = locRETgainCcurve && mean != 0.f && stddv != 0.f;
+
+ if (hasWavRetGainCurve) { //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;
+ cdfactor *= 2.f;
+ }
+
+
+ const float maxclip = (chrome == 0 ? 32768.f : 50000.f);
+ float str = strength * (chrome == 0 ? 1.f : chrT);
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ // float absciss;
+ float cdmax = -999999.f, cdmin = 999999.f;
+ float gan = 0.5f;
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for ( int i = 0; i < H_L; i ++ )
+ for (int j = 0; j < W_L; j++) {
+ if (hasWavRetGainCurve) {
+ 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 {
+ absciss = amin * luminance[i][j] + bmin;
+ }
+
+ gan = locRETgainCcurve[absciss]; //new gain function transmission
+ }
+
+ float cd = gan * cdfactor * luminance[i][j] + offse;
+
+ cdmax = cd > cdmax ? cd : cdmax;
+ cdmin = cd < cdmin ? cd : cdmin;
+ luminance[i][j] = LIM ( cd, 0.f, maxclip ) * str + (1.f - str) * originalLuminance[i][j];
+ // templ[i][j] = LIM( cd, 0.f, maxclip ) * str + (1.f - str) * originalLuminance[i][j];
+ // luminance[i][j] = LIM( cd, 0.f, maxclip );
+ }
+
+#ifdef _OPENMP
+ #pragma omp critical
+#endif
+ {
+ maxCD = maxCD > cdmax ? maxCD : cdmax;
+ minCD = minCD < cdmin ? minCD : cdmin;
+ }
+
+ }
+
+ Tmean = mean;
+ Tsigma = stddv;
+ Tmin = mintr;
+ Tmax = maxtr;
+
+
+ }
+
+
+
}
+}
\ No newline at end of file
diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc
index c1a2f479e..56905ae70 100644
--- a/rtengine/ipsharpen.cc
+++ b/rtengine/ipsharpen.cc
@@ -23,6 +23,10 @@
#include "rt_math.h"
#include "sleef.c"
#include "opthelper.h"
+
+//#define BENCHMARK
+//#include "StopWatch.h"
+
using namespace std;
namespace rtengine
@@ -114,7 +118,7 @@ void ImProcFunctions::deconvsharpening (float** luminance, float** tmp, int W, i
float damping = sharpenParam.deconvdamping / 5.0;
bool needdamp = sharpenParam.deconvdamping > 0;
double sigma = sharpenParam.deconvradius / scale;
-
+ // printf("sigma=%f \n", sigma);
#ifdef _OPENMP
#pragma omp parallel
#endif
@@ -150,6 +154,76 @@ void ImProcFunctions::deconvsharpening (float** luminance, float** tmp, int W, i
}
+void ImProcFunctions::deconvsharpeningloc (float** luminance, float** tmp, int W, int H, float** loctemp, int damp, double radi, int ite, int amo)
+{
+ // BENCHFUN
+
+ if (amo < 1) {
+ return;
+ }
+
+ float *tmpI[H] ALIGNED16;
+
+ tmpI[0] = new float[W * H];
+
+ for (int i = 1; i < H; i++) {
+ tmpI[i] = tmpI[i - 1] + W;
+ }
+
+ for (int i = 0; i < H; i++) {
+ for(int j = 0; j < W; j++) {
+ tmpI[i][j] = luminance[i][j];
+ }
+ }
+
+ float damping = (float) damp / 5.0;
+ bool needdamp = damp > 0;
+ double sigma = radi / scale;
+
+ if(sigma < 0.26f) {
+ sigma = 0.26f;
+ }
+
+ int itera = ite;
+ // printf("OK 2 damp=%f sigam=%f iter=%i\n", damping, sigma, itera);
+
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ for (int k = 0; k < itera; k++) {
+ if (!needdamp) {
+ // apply gaussian blur and divide luminance by result of gaussian blur
+ gaussianBlur (tmpI, tmp, W, H, sigma, nullptr, GAUSS_DIV, luminance);
+ } else {
+ // apply gaussian blur + damping
+ gaussianBlur (tmpI, tmp, W, H, sigma);
+ dcdamping (tmp, luminance, damping, W, H);
+ }
+
+ gaussianBlur (tmp, tmpI, W, H, sigma, nullptr, GAUSS_MULT);
+ } // end for
+
+ float p2 = (float) amo / 100.0;
+ float p1 = 1.0 - p2;
+
+#ifdef _OPENMP
+ #pragma omp for
+#endif
+
+ for (int i = 0; i < H; i++)
+ for (int j = 0; j < W; j++) {
+ loctemp[i][j] = luminance[i][j] * p1 + max(tmpI[i][j], 0.0f) * p2;
+ }
+ } // end parallel
+
+ delete [] tmpI[0];
+
+}
+
+
+
+
void ImProcFunctions::sharpening (LabImage* lab, float** b2, SharpeningParams &sharpenParam)
{
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index 52517e527..3388b10f0 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -470,8 +470,75 @@ enum ProcEvent {
EvRetinexgaintransmission = 440,
EvLskal = 441,
EvOBPCompens = 442,
+ EvlocallabEnabled = 443,
+ EvlocallablocY = 444,
+ EvlocallablocX = 445,
+ EvlocallabCenter = 446,
+ EvlocallabDegree = 447,
+ Evlocallablightness = 448,
+ Evlocallabcontrast = 449,
+ Evlocallabchroma = 450,
+ Evlocallabtransit = 451,
+ Evlocallabavoid = 452,
+ EvlocallablocYT = 453,
+ EvlocallablocXL = 454,
+ EvlocallabSmet = 455,
+ Evlocallabinvers = 456,
+ Evlocallabradius = 457,
+ Evlocallabinversrad = 458,
+ Evlocallabstrength = 459,
+ Evlocallabsensi = 460,
+ EvlocallabretinexMethod = 461,
+ Evlocallabstr = 462,
+ Evlocallabneigh = 463,
+ Evlocallabvart = 464,
+ EvlocallabCTgainCurve = 465,
+ Evlocallabchrrt = 466,
+ Evlocallabinversret = 467,
+ Evlocallabsensih = 468,
+ Evlocallabnbspot = 469,
+ Evlocallabactivlum = 470,
+ Evlocallabanbspot = 471,
+ Evlocallabsharradius = 472,
+ Evlocallabsharamount = 473,
+ Evlocallabshardamping = 474,
+ Evlocallabshariter = 475,
+ Evlocallabsensis = 476,
+ Evlocallabinverssha = 477,
+ Evlocallabcircrad = 478,
+ Evlocallabthres = 479,
+ Evlocallabproxi = 480,
+ EvlocallabqualityMethod = 481,
+ Evlocallabnoiselumf = 482,
+ Evlocallabnoiselumc = 483,
+ Evlocallabnoisechrof = 484,
+ Evlocallabnoisechroc = 485,
+ EvlocallabThresho = 486,
+ EvlocallabEqualizer = 487,
+ Evlocallabsensicb = 488,
+ Evlocallabsensibn = 489,
+ Evlocallabstren = 490,
+ Evlocallabgamma = 491,
+ Evlocallabestop = 492,
+ Evlocallabscaltm = 493,
+ Evlocallabrewei = 494,
+ Evlocallabsensitm = 495,
+ EvlocallabCTgainCurverab = 496,
+ Evlocallabretrab = 497,
+ Evlocallabllshape = 498,
+ EvLocenacolor = 499,
+ EvLocenablur = 500,
+ EvLocenatonemap = 501,
+ EvLocenareti = 502,
+ EvLocenasharp = 503,
+ EvLocenacbdl = 504,
+ EvLocenadenoi = 505,
+ EvlocallabLHshape = 506,
+ Evlocallabcurvactiv = 507,
+
NUMOFEVENTS
+
};
}
#endif
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 1ac3cbed2..568f2ecc6 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -46,11 +46,11 @@ const char *RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::numMe
const char *RAWParams::ff_BlurTypestring[RAWParams::numFlatFileBlurTypes] = {/*"Parametric",*/ "Area Flatfield", "Vertical Flatfield", "Horizontal Flatfield", "V+H Flatfield"};
std::vector WBParams::wbEntries;
-bool ToneCurveParams::HLReconstructionNecessary(LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw)
+bool ToneCurveParams::HLReconstructionNecessary (LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw)
{
if (options.rtSettings.verbose)
- printf("histRedRaw[ 0]=%07d, histGreenRaw[ 0]=%07d, histBlueRaw[ 0]=%07d\nhistRedRaw[255]=%07d, histGreenRaw[255]=%07d, histBlueRaw[255]=%07d\n",
- histRedRaw[0], histGreenRaw[0], histBlueRaw[0], histRedRaw[255], histGreenRaw[255], histBlueRaw[255]);
+ printf ("histRedRaw[ 0]=%07d, histGreenRaw[ 0]=%07d, histBlueRaw[ 0]=%07d\nhistRedRaw[255]=%07d, histGreenRaw[255]=%07d, histBlueRaw[255]=%07d\n",
+ histRedRaw[0], histGreenRaw[0], histBlueRaw[0], histRedRaw[255], histGreenRaw[255], histBlueRaw[255]);
return histRedRaw[255] > 50 || histGreenRaw[255] > 50 || histBlueRaw[255] > 50 || histRedRaw[0] > 50 || histGreenRaw[0] > 50 || histBlueRaw[0] > 50;
}
@@ -58,40 +58,40 @@ bool ToneCurveParams::HLReconstructionNecessary(LUTu &histRedRaw, LUTu &histGree
void WBParams::init()
{
// Creation of the different methods and its associated temperature value
- wbEntries.push_back(new WBEntry("Camera" , WBT_CAMERA, M("TP_WBALANCE_CAMERA"), 0, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Auto" , WBT_AUTO, M("TP_WBALANCE_AUTO"), 0, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Daylight" , WBT_DAYLIGHT, M("TP_WBALANCE_DAYLIGHT"), 5300, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Cloudy" , WBT_CLOUDY, M("TP_WBALANCE_CLOUDY"), 6200, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Shade" , WBT_SHADE, M("TP_WBALANCE_SHADE"), 7600, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Water 1" , WBT_WATER, M("TP_WBALANCE_WATER1"), 35000, 0.3f, 1.1f));
- wbEntries.push_back(new WBEntry("Water 2" , WBT_WATER, M("TP_WBALANCE_WATER2"), 48000, 0.63f, 1.38f));
- wbEntries.push_back(new WBEntry("Tungsten" , WBT_TUNGSTEN, M("TP_WBALANCE_TUNGSTEN"), 2856, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F1" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO1"), 6430, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F2" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO2"), 4230, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F3" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO3"), 3450, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F4" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO4"), 2940, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F5" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO5"), 6350, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F6" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO6"), 4150, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F7" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO7"), 6500, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F8" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO8"), 5020, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F9" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO9"), 4330, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F10" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO10"), 5300, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F11" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO11"), 4000, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Fluo F12" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO12"), 3000, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("HMI Lamp" , WBT_LAMP, M("TP_WBALANCE_HMI"), 4800, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("GTI Lamp" , WBT_LAMP, M("TP_WBALANCE_GTI"), 5000, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("JudgeIII Lamp" , WBT_LAMP, M("TP_WBALANCE_JUDGEIII"), 5100, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Solux Lamp 3500K" , WBT_LAMP, M("TP_WBALANCE_SOLUX35"), 3480, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Solux Lamp 4100K" , WBT_LAMP, M("TP_WBALANCE_SOLUX41"), 3930, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Solux Lamp 4700K" , WBT_LAMP, M("TP_WBALANCE_SOLUX47"), 4700, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("NG Solux Lamp 4700K" , WBT_LAMP, M("TP_WBALANCE_SOLUX47_NG"), 4480, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("LED LSI Lumelex 2040", WBT_LED, M("TP_WBALANCE_LED_LSI"), 2970, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("LED CRS SP12 WWMR16" , WBT_LED, M("TP_WBALANCE_LED_CRS"), 3050, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Flash 5500K" , WBT_FLASH, M("TP_WBALANCE_FLASH55"), 5500, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Flash 6000K" , WBT_FLASH, M("TP_WBALANCE_FLASH60"), 6000, 1.f, 1.f));
- wbEntries.push_back(new WBEntry("Flash 6500K" , WBT_FLASH, M("TP_WBALANCE_FLASH65"), 6500, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Camera" , WBT_CAMERA, M ("TP_WBALANCE_CAMERA"), 0, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Auto" , WBT_AUTO, M ("TP_WBALANCE_AUTO"), 0, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Daylight" , WBT_DAYLIGHT, M ("TP_WBALANCE_DAYLIGHT"), 5300, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Cloudy" , WBT_CLOUDY, M ("TP_WBALANCE_CLOUDY"), 6200, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Shade" , WBT_SHADE, M ("TP_WBALANCE_SHADE"), 7600, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Water 1" , WBT_WATER, M ("TP_WBALANCE_WATER1"), 35000, 0.3f, 1.1f));
+ wbEntries.push_back (new WBEntry ("Water 2" , WBT_WATER, M ("TP_WBALANCE_WATER2"), 48000, 0.63f, 1.38f));
+ wbEntries.push_back (new WBEntry ("Tungsten" , WBT_TUNGSTEN, M ("TP_WBALANCE_TUNGSTEN"), 2856, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F1" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO1"), 6430, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F2" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO2"), 4230, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F3" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO3"), 3450, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F4" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO4"), 2940, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F5" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO5"), 6350, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F6" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO6"), 4150, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F7" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO7"), 6500, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F8" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO8"), 5020, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F9" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO9"), 4330, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F10" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO10"), 5300, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F11" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO11"), 4000, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Fluo F12" , WBT_FLUORESCENT, M ("TP_WBALANCE_FLUO12"), 3000, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("HMI Lamp" , WBT_LAMP, M ("TP_WBALANCE_HMI"), 4800, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("GTI Lamp" , WBT_LAMP, M ("TP_WBALANCE_GTI"), 5000, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("JudgeIII Lamp" , WBT_LAMP, M ("TP_WBALANCE_JUDGEIII"), 5100, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Solux Lamp 3500K" , WBT_LAMP, M ("TP_WBALANCE_SOLUX35"), 3480, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Solux Lamp 4100K" , WBT_LAMP, M ("TP_WBALANCE_SOLUX41"), 3930, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Solux Lamp 4700K" , WBT_LAMP, M ("TP_WBALANCE_SOLUX47"), 4700, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("NG Solux Lamp 4700K" , WBT_LAMP, M ("TP_WBALANCE_SOLUX47_NG"), 4480, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("LED LSI Lumelex 2040", WBT_LED, M ("TP_WBALANCE_LED_LSI"), 2970, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("LED CRS SP12 WWMR16" , WBT_LED, M ("TP_WBALANCE_LED_CRS"), 3050, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Flash 5500K" , WBT_FLASH, M ("TP_WBALANCE_FLASH55"), 5500, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Flash 6000K" , WBT_FLASH, M ("TP_WBALANCE_FLASH60"), 6000, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Flash 6500K" , WBT_FLASH, M ("TP_WBALANCE_FLASH65"), 6500, 1.f, 1.f));
// Should remain the last one
- wbEntries.push_back(new WBEntry("Custom" , WBT_CUSTOM, M("TP_WBALANCE_CUSTOM"), 0, 1.f, 1.f));
+ wbEntries.push_back (new WBEntry ("Custom" , WBT_CUSTOM, M ("TP_WBALANCE_CUSTOM"), 0, 1.f, 1.f));
}
void WBParams::cleanup()
@@ -102,15 +102,15 @@ void WBParams::cleanup()
}
// Maps crop to resized width (e.g. smaller previews)
-void CropParams::mapToResized(int resizedWidth, int resizedHeight, int scale, int &x1, int &x2, int &y1, int &y2) const
+void CropParams::mapToResized (int resizedWidth, int resizedHeight, int scale, int &x1, int &x2, int &y1, int &y2) const
{
x1 = 0, x2 = resizedWidth, y1 = 0, y2 = resizedHeight;
if (enabled) {
- x1 = min(resizedWidth - 1, max(0, x / scale));
- y1 = min(resizedHeight - 1, max(0, y / scale));
- x2 = min(resizedWidth, max(0, (x + w) / scale));
- y2 = min(resizedHeight, max(0, (y + h) / scale));
+ x1 = min (resizedWidth - 1, max (0, x / scale));
+ y1 = min (resizedHeight - 1, max (0, y / scale));
+ x2 = min (resizedWidth, max (0, (x + w) / scale));
+ y2 = min (resizedHeight, max (0, (y + h) / scale));
}
}
@@ -119,7 +119,7 @@ RetinexParams::RetinexParams ()
setDefaults ();
}
-void RetinexParams::getDefaulttransmissionCurve(std::vector &curve)
+void RetinexParams::getDefaulttransmissionCurve (std::vector &curve)
{
double v[12] = { 0.00, 0.50, 0.35, 0.35,
0.60, 0.75, 0.35, 0.35,
@@ -127,14 +127,14 @@ void RetinexParams::getDefaulttransmissionCurve(std::vector &curve)
};
- curve.resize(13);
- curve.at(0 ) = double(FCT_MinMaxCPoints);
+ curve.resize (13);
+ curve.at (0 ) = double (FCT_MinMaxCPoints);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
-void RetinexParams::getDefaultgaintransmissionCurve(std::vector &curve)
+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,
@@ -143,11 +143,11 @@ void RetinexParams::getDefaultgaintransmissionCurve(std::vector &curve)
};
- curve.resize(17);
- curve.at(0 ) = double(FCT_MinMaxCPoints);
+ curve.resize (17);
+ curve.at (0 ) = double (FCT_MinMaxCPoints);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
@@ -183,88 +183,88 @@ void RetinexParams::setDefaults()
gammaretinex = "none";
medianmap = false;
cdcurve.clear();
- cdcurve.push_back(DCT_Linear);
+ cdcurve.push_back (DCT_Linear);
cdHcurve.clear();
- cdHcurve.push_back(DCT_Linear);
+ cdHcurve.push_back (DCT_Linear);
lhcurve.clear();
- lhcurve.push_back(DCT_Linear);
+ lhcurve.push_back (DCT_Linear);
mapcurve.clear();
- mapcurve.push_back(DCT_Linear);
- getDefaultgaintransmissionCurve(gaintransmissionCurve);
+ mapcurve.push_back (DCT_Linear);
+ getDefaultgaintransmissionCurve (gaintransmissionCurve);
- getDefaulttransmissionCurve(transmissionCurve);
+ getDefaulttransmissionCurve (transmissionCurve);
}
-void RetinexParams::getCurves(RetinextransmissionCurve &transmissionCurveLUT, RetinexgaintransmissionCurve &gaintransmissionCurveLUT) const
+void RetinexParams::getCurves (RetinextransmissionCurve &transmissionCurveLUT, RetinexgaintransmissionCurve &gaintransmissionCurveLUT) const
{
- transmissionCurveLUT.Set(this->transmissionCurve);
- gaintransmissionCurveLUT.Set(this->gaintransmissionCurve);
+ transmissionCurveLUT.Set (this->transmissionCurve);
+ gaintransmissionCurveLUT.Set (this->gaintransmissionCurve);
}
-ColorToningParams::ColorToningParams () : hlColSat(60, 80, false), shadowsColSat(80, 208, false)
+ColorToningParams::ColorToningParams () : hlColSat (60, 80, false), shadowsColSat (80, 208, false)
{
setDefaults();
}
-void ColorToningParams::getDefaultColorCurve(std::vector &curve)
+void ColorToningParams::getDefaultColorCurve (std::vector &curve)
{
double v[8] = { 0.050, 0.62, 0.25, 0.25,
0.585, 0.11, 0.25, 0.25
};
- curve.resize(9);
- curve.at(0) = double(FCT_MinMaxCPoints);
+ curve.resize (9);
+ curve.at (0) = double (FCT_MinMaxCPoints);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
-void ColorToningParams::getDefaultOpacityCurve(std::vector &curve)
+void ColorToningParams::getDefaultOpacityCurve (std::vector &curve)
{
double v[16] = { 0.00, 0.3, 0.35, 0.00,
0.25, 0.8, 0.35, 0.35,
0.70, 0.8, 0.35, 0.35,
1.00, 0.3, 0.00, 0.00
};
- curve.resize(17);
- curve.at(0 ) = double(FCT_MinMaxCPoints);
+ curve.resize (17);
+ curve.at (0 ) = double (FCT_MinMaxCPoints);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
-void ColorToningParams::getDefaultCLCurve(std::vector &curve)
+void ColorToningParams::getDefaultCLCurve (std::vector &curve)
{
double v[6] = { 0.00, 0.00,
0.35, 0.65,
1.00, 1.00
};
- curve.resize(7);
- curve.at(0) = double(DCT_NURBS);
+ curve.resize (7);
+ curve.at (0) = double (DCT_NURBS);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
-void ColorToningParams::getDefaultCL2Curve(std::vector &curve)
+void ColorToningParams::getDefaultCL2Curve (std::vector &curve)
{
double v[6] = { 0.00, 0.00,
0.35, 0.65,
1.00, 1.00
};
- curve.resize(7);
- curve.at(0) = double(DCT_NURBS);
+ curve.resize (7);
+ curve.at (0) = double (DCT_NURBS);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
@@ -274,13 +274,13 @@ void ColorToningParams::setDefaults()
autosat = true;
method = "Lab";
- getDefaultColorCurve(colorCurve);
- getDefaultOpacityCurve(opacityCurve);
- getDefaultCLCurve(clcurve);
- getDefaultCL2Curve(cl2curve);
+ getDefaultColorCurve (colorCurve);
+ getDefaultOpacityCurve (opacityCurve);
+ getDefaultCLCurve (clcurve);
+ getDefaultCL2Curve (cl2curve);
- hlColSat.setValues(60, 80);
- shadowsColSat.setValues(80, 208);
+ hlColSat.setValues (60, 80);
+ shadowsColSat.setValues (80, 208);
balance = 0;
satProtectionThreshold = 30;
saturatedOpacity = 80;
@@ -300,14 +300,14 @@ void ColorToningParams::setDefaults()
bluehigh = 0.0;
}
-void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vector &opacityCurve) const
+void ColorToningParams::mixerToCurve (std::vector &colorCurve, std::vector &opacityCurve) const
{
// check if non null first
if (!redlow && !greenlow && !bluelow && !redmed && !greenmed && !bluemed && !redhigh && !greenhigh && !bluehigh) {
- colorCurve.resize(1);
- colorCurve.at(0) = FCT_Linear;
- opacityCurve.resize(1);
- opacityCurve.at(0) = FCT_Linear;
+ colorCurve.resize (1);
+ colorCurve.at (0) = FCT_Linear;
+ opacityCurve.resize (1);
+ opacityCurve.at (0) = FCT_Linear;
return;
}
@@ -320,11 +320,11 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto
float minTmp, maxTmp;
// Fill the shadow mixer values of the Color TOning tool
- low[0] = float(redlow ) / 100.f; // [-1. ; +1.]
- low[1] = float(greenlow) / 100.f; // [-1. ; +1.]
- low[2] = float(bluelow ) / 100.f; // [-1. ; +1.]
- minTmp = min(low[0], low[1], low[2]);
- maxTmp = max(low[0], low[1], low[2]);
+ low[0] = float (redlow ) / 100.f; // [-1. ; +1.]
+ low[1] = float (greenlow) / 100.f; // [-1. ; +1.]
+ low[2] = float (bluelow ) / 100.f; // [-1. ; +1.]
+ minTmp = min (low[0], low[1], low[2]);
+ maxTmp = max (low[0], low[1], low[2]);
if (maxTmp - minTmp > 0.005f) {
float v[3];
@@ -362,11 +362,11 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto
}
// Fill the mid-tones mixer values of the Color TOning tool
- med[0] = float(redmed ) / 100.f; // [-1. ; +1.]
- med[1] = float(greenmed) / 100.f; // [-1. ; +1.]
- med[2] = float(bluemed ) / 100.f; // [-1. ; +1.]
- minTmp = min(med[0], med[1], med[2]);
- maxTmp = max(med[0], med[1], med[2]);
+ med[0] = float (redmed ) / 100.f; // [-1. ; +1.]
+ med[1] = float (greenmed) / 100.f; // [-1. ; +1.]
+ med[2] = float (bluemed ) / 100.f; // [-1. ; +1.]
+ minTmp = min (med[0], med[1], med[2]);
+ maxTmp = max (med[0], med[1], med[2]);
if (maxTmp - minTmp > 0.005f) {
float v[3];
@@ -404,11 +404,11 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto
}
// Fill the highlight mixer values of the Color TOning tool
- high[0] = float(redhigh ) / 100.f; // [-1. ; +1.]
- high[1] = float(greenhigh) / 100.f; // [-1. ; +1.]
- high[2] = float(bluehigh ) / 100.f; // [-1. ; +1.]
- minTmp = min(high[0], high[1], high[2]);
- maxTmp = max(high[0], high[1], high[2]);
+ high[0] = float (redhigh ) / 100.f; // [-1. ; +1.]
+ high[1] = float (greenhigh) / 100.f; // [-1. ; +1.]
+ high[2] = float (bluehigh ) / 100.f; // [-1. ; +1.]
+ minTmp = min (high[0], high[1], high[2]);
+ maxTmp = max (high[0], high[1], high[2]);
if (maxTmp - minTmp > 0.005f) {
float v[3];
@@ -454,100 +454,100 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto
- colorCurve.resize( medSat != 0.f ? 13 : 9 );
- colorCurve.at(0) = FCT_MinMaxCPoints;
- opacityCurve.resize(13);
- opacityCurve.at(0) = FCT_MinMaxCPoints;
+ colorCurve.resize ( medSat != 0.f ? 13 : 9 );
+ colorCurve.at (0) = FCT_MinMaxCPoints;
+ opacityCurve.resize (13);
+ opacityCurve.at (0) = FCT_MinMaxCPoints;
float h, s, l;
int idx = 1;
if (lowSat == 0.f) {
if (medSat != 0.f) {
- Color::rgb2hsl(med[0], med[1], med[2], h, s, l);
+ Color::rgb2hsl (med[0], med[1], med[2], h, s, l);
} else { // highSat can't be null if the 2 other ones are!
- Color::rgb2hsl(high[0], high[1], high[2], h, s, l);
+ Color::rgb2hsl (high[0], high[1], high[2], h, s, l);
}
} else {
- Color::rgb2hsl(low[0], low[1], low[2], h, s, l);
+ Color::rgb2hsl (low[0], low[1], low[2], h, s, l);
}
- colorCurve.at(idx++) = xPosLow;
- colorCurve.at(idx++) = h;
- colorCurve.at(idx++) = 0.35;
- colorCurve.at(idx++) = 0.35;
+ colorCurve.at (idx++) = xPosLow;
+ colorCurve.at (idx++) = h;
+ colorCurve.at (idx++) = 0.35;
+ colorCurve.at (idx++) = 0.35;
if (medSat != 0.f) {
- Color::rgb2hsl(med[0], med[1], med[2], h, s, l);
- colorCurve.at(idx++) = xPosMed;
- colorCurve.at(idx++) = h;
- colorCurve.at(idx++) = 0.35;
- colorCurve.at(idx++) = 0.35;
+ Color::rgb2hsl (med[0], med[1], med[2], h, s, l);
+ colorCurve.at (idx++) = xPosMed;
+ colorCurve.at (idx++) = h;
+ colorCurve.at (idx++) = 0.35;
+ colorCurve.at (idx++) = 0.35;
}
if (highSat == 0.f) {
if (medSat != 0.f) {
- Color::rgb2hsl(med[0], med[1], med[2], h, s, l);
+ Color::rgb2hsl (med[0], med[1], med[2], h, s, l);
} else { // lowSat can't be null if the 2 other ones are!
- Color::rgb2hsl(low[0], low[1], low[2], h, s, l);
+ Color::rgb2hsl (low[0], low[1], low[2], h, s, l);
}
} else {
- Color::rgb2hsl(high[0], high[1], high[2], h, s, l);
+ Color::rgb2hsl (high[0], high[1], high[2], h, s, l);
}
- colorCurve.at(idx++) = xPosHigh;
- colorCurve.at(idx++) = h;
- colorCurve.at(idx++) = 0.35;
- colorCurve.at(idx) = 0.35;
+ colorCurve.at (idx++) = xPosHigh;
+ colorCurve.at (idx++) = h;
+ colorCurve.at (idx++) = 0.35;
+ colorCurve.at (idx) = 0.35;
- opacityCurve.at(1) = xPosLow;
- opacityCurve.at(2) = double(lowSat);
- opacityCurve.at(3) = 0.35;
- opacityCurve.at(4) = 0.35;
- opacityCurve.at(5) = xPosMed;
- opacityCurve.at(6) = double(medSat);
- opacityCurve.at(7) = 0.35;
- opacityCurve.at(8) = 0.35;
- opacityCurve.at(9) = xPosHigh;
- opacityCurve.at(10) = double(highSat);
- opacityCurve.at(11) = 0.35;
- opacityCurve.at(12) = 0.35;
+ opacityCurve.at (1) = xPosLow;
+ opacityCurve.at (2) = double (lowSat);
+ opacityCurve.at (3) = 0.35;
+ opacityCurve.at (4) = 0.35;
+ opacityCurve.at (5) = xPosMed;
+ opacityCurve.at (6) = double (medSat);
+ opacityCurve.at (7) = 0.35;
+ opacityCurve.at (8) = 0.35;
+ opacityCurve.at (9) = xPosHigh;
+ opacityCurve.at (10) = double (highSat);
+ opacityCurve.at (11) = 0.35;
+ opacityCurve.at (12) = 0.35;
}
-void ColorToningParams::slidersToCurve(std::vector &colorCurve, std::vector &opacityCurve) const
+void ColorToningParams::slidersToCurve (std::vector &colorCurve, std::vector &opacityCurve) const
{
if (hlColSat.value[0] == 0 && shadowsColSat.value[0] == 0) { // if both opacity are null, set both curves to Linear
- colorCurve.resize(1);
- colorCurve.at(0) = FCT_Linear;
- opacityCurve.resize(1);
- opacityCurve.at(0) = FCT_Linear;
+ colorCurve.resize (1);
+ colorCurve.at (0) = FCT_Linear;
+ opacityCurve.resize (1);
+ opacityCurve.at (0) = FCT_Linear;
return;
}
- colorCurve.resize(9);
- colorCurve.at(0) = FCT_MinMaxCPoints;
- colorCurve.at(1) = 0.26 + 0.12 * double(balance) / 100.;
- colorCurve.at(2) = double(shadowsColSat.value[1]) / 360.;
- colorCurve.at(3) = 0.35;
- colorCurve.at(4) = 0.35;
- colorCurve.at(5) = 0.64 + 0.12 * double(balance) / 100.;
- colorCurve.at(6) = double(hlColSat.value[1]) / 360.;
- colorCurve.at(7) = 0.35;
- colorCurve.at(8) = 0.35;
+ colorCurve.resize (9);
+ colorCurve.at (0) = FCT_MinMaxCPoints;
+ colorCurve.at (1) = 0.26 + 0.12 * double (balance) / 100.;
+ colorCurve.at (2) = double (shadowsColSat.value[1]) / 360.;
+ colorCurve.at (3) = 0.35;
+ colorCurve.at (4) = 0.35;
+ colorCurve.at (5) = 0.64 + 0.12 * double (balance) / 100.;
+ colorCurve.at (6) = double (hlColSat.value[1]) / 360.;
+ colorCurve.at (7) = 0.35;
+ colorCurve.at (8) = 0.35;
- opacityCurve.resize(9);
- opacityCurve.at(0) = FCT_MinMaxCPoints;
- opacityCurve.at(1) = colorCurve.at(1);
- opacityCurve.at(2) = double(shadowsColSat.value[0]) / 100.;
- opacityCurve.at(3) = 0.35;
- opacityCurve.at(4) = 0.35;
- opacityCurve.at(5) = colorCurve.at(5);
- opacityCurve.at(6) = double(hlColSat.value[0]) / 100.;
- opacityCurve.at(7) = 0.35;
- opacityCurve.at(8) = 0.35;
+ opacityCurve.resize (9);
+ opacityCurve.at (0) = FCT_MinMaxCPoints;
+ opacityCurve.at (1) = colorCurve.at (1);
+ opacityCurve.at (2) = double (shadowsColSat.value[0]) / 100.;
+ opacityCurve.at (3) = 0.35;
+ opacityCurve.at (4) = 0.35;
+ opacityCurve.at (5) = colorCurve.at (5);
+ opacityCurve.at (6) = double (hlColSat.value[0]) / 100.;
+ opacityCurve.at (7) = 0.35;
+ opacityCurve.at (8) = 0.35;
}
-void ColorToningParams::getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurve &opacityCurveLUT, const double xyz_rgb[3][3], const double rgb_xyz[3][3], bool &opautili) const
+void ColorToningParams::getCurves (ColorGradientCurve &colorCurveLUT, OpacityCurve &opacityCurveLUT, const double xyz_rgb[3][3], const double rgb_xyz[3][3], bool &opautili) const
{
float satur = 0.8f;
float lumin = 0.5f; //middle of luminance for optimization of gamut - no real importance...as we work in XYZ and gamut control
@@ -556,85 +556,84 @@ void ColorToningParams::getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurv
std::vector cCurve, oCurve;
if (method == "RGBSliders" || method == "Splitlr") {
- slidersToCurve(cCurve, oCurve);
+ slidersToCurve (cCurve, oCurve);
} else if (method == "Splitco") {
- mixerToCurve(cCurve, oCurve);
+ mixerToCurve (cCurve, oCurve);
} else {
cCurve = this->colorCurve;
oCurve = this->opacityCurve;
}
- if(method == "Lab") {
- if(twocolor == "Separ") {
+ if (method == "Lab") {
+ if (twocolor == "Separ") {
satur = 0.9f;
}
- if(twocolor == "All" || twocolor == "Two") {
+ if (twocolor == "All" || twocolor == "Two") {
satur = 0.9f;
}
- colorCurveLUT.SetXYZ(cCurve, xyz_rgb, rgb_xyz, satur, lumin);
- opacityCurveLUT.Set(oCurve, opautili);
- } else if(method == "Splitlr" || method == "Splitco") {
- colorCurveLUT.SetXYZ(cCurve, xyz_rgb, rgb_xyz, satur, lumin);
- opacityCurveLUT.Set(oCurve, opautili);
- } else if(method.substr(0, 3) == "RGB") {
- colorCurveLUT.SetRGB(cCurve, xyz_rgb, rgb_xyz);
- opacityCurveLUT.Set(oCurve, opautili);
+ colorCurveLUT.SetXYZ (cCurve, xyz_rgb, rgb_xyz, satur, lumin);
+ opacityCurveLUT.Set (oCurve, opautili);
+ } else if (method == "Splitlr" || method == "Splitco") {
+ colorCurveLUT.SetXYZ (cCurve, xyz_rgb, rgb_xyz, satur, lumin);
+ opacityCurveLUT.Set (oCurve, opautili);
+ } else if (method.substr (0, 3) == "RGB") {
+ colorCurveLUT.SetRGB (cCurve, xyz_rgb, rgb_xyz);
+ opacityCurveLUT.Set (oCurve, opautili);
}
}
//WaveletParams::WaveletParams (): hueskin(-5, 25, 170, 120, false), hueskin2(-260, -250, -130, -140, false), hllev(50, 75, 100, 98, false), bllev(0, 2, 50, 25, false), pastlev(0, 2, 30, 20, false), satlev(30, 45, 130, 100, false), edgcont(0, 20, 100, 75, false){
-WaveletParams::WaveletParams (): hueskin(-5, 25, 170, 120, false), hueskin2(-260, -250, -130, -140, false), hllev(50, 75, 100, 98, false), bllev(0, 2, 50, 25, false),
- pastlev(0, 2, 30, 20, false), satlev(30, 45, 130, 100, false), edgcont(bl, tl, br, tr, false), /* edgcont(0, 10, 75, 40, false),*/level0noise(0, 0, false), level1noise(0, 0, false), level2noise(0, 0, false), level3noise(0, 0, false)
+WaveletParams::WaveletParams (): hueskin (-5, 25, 170, 120, false), hueskin2 (-260, -250, -130, -140, false), hllev (50, 75, 100, 98, false), bllev (0, 2, 50, 25, false),
+ pastlev (0, 2, 30, 20, false), satlev (30, 45, 130, 100, false), edgcont (bl, tl, br, tr, false), /* edgcont(0, 10, 75, 40, false),*/level0noise (0, 0, false), level1noise (0, 0, false), level2noise (0, 0, false), level3noise (0, 0, false)
{
setDefaults ();
}
-void WaveletParams::getDefaultOpacityCurveRG(std::vector &curve)
+void WaveletParams::getDefaultOpacityCurveRG (std::vector &curve)
{
double v[8] = { 0.0, 0.50, 0.35, 0.35,
1.00, 0.50, 0.35, 0.35
};
- curve.resize(9);
- curve.at(0) = double(FCT_MinMaxCPoints);
+ curve.resize (9);
+ curve.at (0) = double (FCT_MinMaxCPoints);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
-void WaveletParams::getDefaultOpacityCurveBY(std::vector &curve)
+void WaveletParams::getDefaultOpacityCurveBY (std::vector &curve)
{
double v[8] = { 0.0, 0.50, 0.35, 0.35,
1.00, 0.50, 0.35, 0.35
};
- curve.resize(9);
- curve.at(0 ) = double(FCT_MinMaxCPoints);
+ curve.resize (9);
+ curve.at (0 ) = double (FCT_MinMaxCPoints);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
-
-void WaveletParams::getDefaultOpacityCurveW(std::vector &curve)
+void WaveletParams::getDefaultOpacityCurveW (std::vector &curve)
{
double v[16] = { 0.00, 0.35, 0.35, 0.00,
0.35, 0.75, 0.35, 0.35,
0.60, 0.75, 0.35, 0.35,
1.00, 0.35, 0.00, 0.00
};
- curve.resize(17);
- curve.at(0) = double(FCT_MinMaxCPoints);
+ curve.resize (17);
+ curve.at (0) = double (FCT_MinMaxCPoints);
for (size_t i = 1; i < curve.size(); ++i) {
- curve.at(i) = v[i - 1];
+ curve.at (i) = v[i - 1];
}
}
-void WaveletParams::getDefaultOpacityCurveWL(std::vector &curve)
+void WaveletParams::getDefaultOpacityCurveWL (std::vector &curve)
{
double v[8] = { 0.0, 0.50, 0.35, 0.35,
1.00, 0.50, 0.35, 0.35
@@ -644,47 +643,47 @@ void WaveletParams::getDefaultOpacityCurveWL(std::vector