diff --git a/rtdata/languages/default b/rtdata/languages/default
index dbd63d988..15aceb51b 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -1287,6 +1287,7 @@ HISTORY_MSG_1039;Local - Grain - gamma
HISTORY_MSG_1040;Local - Spot - soft radius
HISTORY_MSG_1041;Local - Spot - Munsell
HISTORY_MSG_1042;Local - Log encoding - threshold
+HISTORY_MSG_1043;Local - Exp - normalize
HISTORY_MSG_BLSHAPE;Blur by level
HISTORY_MSG_BLURCWAV;Blur chroma
HISTORY_MSG_BLURWAV;Blur luminance
@@ -2525,7 +2526,7 @@ TP_LOCALLAB_BLURLEVELFRA;Blur levels
TP_LOCALLAB_BLURMASK_TOOLTIP;Uses a large-radius blur to create a mask that allows you to vary the contrast of the image and/or darken/lighten parts of it.
TP_LOCALLAB_BLURRESIDFRA;Blur Residual
TP_LOCALLAB_BLURRMASK_TOOLTIP;Allows you to vary the "radius" of the Gaussian blur (0 to 1000)
-TP_LOCALLAB_BLUR_TOOLNAME;Blur/Grain & Denoise - 1
+TP_LOCALLAB_BLUR_TOOLNAME;Blur/Grain & Denoise
TP_LOCALLAB_BLWH;All changes forced in Black-and-White
TP_LOCALLAB_BLWH_TOOLTIP;Force color components "a" and "b" to zero.\nUseful for black and white processing, or film simulation.
TP_LOCALLAB_BUTTON_ADD;Add
@@ -2538,7 +2539,7 @@ TP_LOCALLAB_CBDL;Contrast by Detail Levels
TP_LOCALLAB_CBDLCLARI_TOOLTIP;Enhances local contrast of the midtones.
TP_LOCALLAB_CBDL_ADJ_TOOLTIP;Same as wavelets.\nThe first level (0) acts on 2x2 pixel details.\nThe last level (5) acts on 64x64 pixel details.
TP_LOCALLAB_CBDL_THRES_TOOLTIP;Prevents the sharpening of noise
-TP_LOCALLAB_CBDL_TOOLNAME;Contrast by Detail Levels - 2
+TP_LOCALLAB_CBDL_TOOLNAME;Contrast by Detail Levels
TP_LOCALLAB_CENTER_X;Center X
TP_LOCALLAB_CENTER_Y;Center Y
TP_LOCALLAB_CH;Curves CL - LC
@@ -2569,7 +2570,7 @@ TP_LOCALLAB_COLORDEPREV_TOOLTIP;Preview ΔE button will only work if you have ac
TP_LOCALLAB_COLORDE_TOOLTIP;Show a blue color-preview for ΔE selection if negative and green if positive.\n\nMask and modifications (show modified areas without mask): show actual modifications if positive, show enhanced modifications (luminance only) with blue and yellow if negative.
TP_LOCALLAB_COLORSCOPE;Scope (color tools)
TP_LOCALLAB_COLORSCOPE_TOOLTIP;Common Scope slider for Color and Light, Shadows/Highlights, Vibrance.\nOther tools have their own scope controls.
-TP_LOCALLAB_COLOR_TOOLNAME;Color & Light - 11
+TP_LOCALLAB_COLOR_TOOLNAME;Color & Light
TP_LOCALLAB_COL_NAME;Name
TP_LOCALLAB_COL_VIS;Status
TP_LOCALLAB_COMPFRA;Directional contrast
@@ -2681,7 +2682,7 @@ TP_LOCALLAB_EXPRETITOOLS;Advanced Retinex Tools
TP_LOCALLAB_EXPSHARP_TOOLTIP;RT-Spot minimum 39*39.\nUse low transition values and high ‘Transition decay’ and ‘Scope’ values to simulate smaller RT-spots.
TP_LOCALLAB_EXPTOOL;Exposure Tools
TP_LOCALLAB_EXPTRC;Tone Response Curve - TRC
-TP_LOCALLAB_EXP_TOOLNAME;Dynamic Range & Exposure - 10
+TP_LOCALLAB_EXP_TOOLNAME;Dynamic Range & Exposure
TP_LOCALLAB_FATAMOUNT;Amount
TP_LOCALLAB_FATANCHOR;Anchor
TP_LOCALLAB_FATANCHORA;Offset
@@ -2760,7 +2761,7 @@ TP_LOCALLAB_LAPRAD2_TOOLTIP;Smooth radius uses a guided filter to decrease artif
TP_LOCALLAB_LAPRAD_TOOLTIP;Smooth radius uses a guided filter to decrease artifacts and smooth out the transition
TP_LOCALLAB_LAP_MASK_TOOLTIP;Solve PDE for all Laplacian masks.\nIf enabled Laplacian threshold mask reduce artifacts and smooth result.\nIf disabled linear response.
TP_LOCALLAB_LC_FFTW_TOOLTIP;FFT improves quality and allows the use of large radii, but increases processing time (depends on the area to be processed). Preferable to use only for large radii. The size of the area can be reduced by a few pixels to optimize the FFTW. This can reduce the processing time by a factor of 1.5 to 10.
-TP_LOCALLAB_LC_TOOLNAME;Local Contrast & Wavelets - 7
+TP_LOCALLAB_LC_TOOLNAME;Local Contrast & Wavelets
TP_LOCALLAB_LEVELBLUR;Maximum blur levels
TP_LOCALLAB_LEVELWAV;Ψ Wavelet levels
TP_LOCALLAB_LEVELWAV_TOOLTIP;The Level is automatically adapted to the size of the spot and the preview.\nFrom level 9 size max 512 to level 1 size max = 4
@@ -2817,7 +2818,7 @@ TP_LOCALLAB_LOGSRCGREY_TOOLTIP;Estimated gray point value of the image.
TP_LOCALLAB_LOGSURSOUR_TOOLTIP;Changes tones and colors to take into account the Scene conditions.\n\nAverage: Average light environment (standard). The image will not change.\n\nDim: Dim environment. The image will become slightly bright.
TP_LOCALLAB_LOGTARGGREY_TOOLTIP;You can adjust this value to suit.
TP_LOCALLAB_LOGVIEWING_TOOLTIP;Corresponds to the medium on which the final image will be viewed (monitor, TV, projector, printer,..), as well as its environment.
-TP_LOCALLAB_LOG_TOOLNAME;Log Encoding - 0
+TP_LOCALLAB_LOG_TOOLNAME;Log Encoding
TP_LOCALLAB_LUM;Curves LL - CC
TP_LOCALLAB_LUMADARKEST;Darkest
TP_LOCALLAB_LUMASK;Background color for luminance mask
@@ -2831,7 +2832,7 @@ TP_LOCALLAB_MASK;Contrast
TP_LOCALLAB_MASK2;Contrast curve
TP_LOCALLAB_MASKCOL;Mask Curves
TP_LOCALLAB_MASKCOM;Common Color Mask
-TP_LOCALLAB_MASKCOM_TOOLNAME;Common Color Mask - 13
+TP_LOCALLAB_MASKCOM_TOOLNAME;Common Color Mask
TP_LOCALLAB_MASKCOM_TOOLTIP;A tool in its own right.\nCan be used to adjust the image appearance (chrominance, luminance, contrast) and texture as a function of Scope.
TP_LOCALLAB_MASKCURVE_TOOLTIP;The 3 curves are set to 1 (maximum) by default:\nC=f(C) the chroma varies according to the chrominance. You can decrease the chroma to improve the selection. By setting this curve close to zero (with a low value of C to activate the curve) you can desaturate the background in Inverse mode.\nL=f(L) the luminance varies according to the luminance, so you can decrease the brightness to improve the selection.\nL and C = f(H) luminance and chroma vary with hue, so you can decrease luminance and chroma to improve selection
TP_LOCALLAB_MASKDDECAY;Decay strength
@@ -3011,7 +3012,7 @@ TP_LOCALLAB_RETI_LIMDOFFS_TOOLTIP;Adjusts the internal parameters to optimize th
TP_LOCALLAB_RETI_LOGLIN_TOOLTIP;Logarithm mode introduces more contrast but will also generate more halos.
TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP;The radius and variance sliders allow you adjust haze and target either the foreground or the background.
TP_LOCALLAB_RETI_SCALE_TOOLTIP;If Scale=1, Retinex behaves like local contrast with additional possibilities.\nIncreasing the value of Scale increases the intensity of the recursive action at the expense of processing time.
-TP_LOCALLAB_RET_TOOLNAME;Dehaze & Retinex - 9
+TP_LOCALLAB_RET_TOOLNAME;Dehaze & Retinex
TP_LOCALLAB_REWEI;Reweighting iterates
TP_LOCALLAB_RGB;RGB Tone Curve
TP_LOCALLAB_RGBCURVE_TOOLTIP;In RGB mode you have 4 choices : Standard, Weighted standard, Luminance & Film-like.
@@ -3048,7 +3049,7 @@ TP_LOCALLAB_SHARDAMPING;Damping
TP_LOCALLAB_SHARFRAME;Modifications
TP_LOCALLAB_SHARITER;Iterations
TP_LOCALLAB_SHARP;Sharpening
-TP_LOCALLAB_SHARP_TOOLNAME;Sharpening - 8
+TP_LOCALLAB_SHARP_TOOLNAME;Sharpening
TP_LOCALLAB_SHARRADIUS;Radius
TP_LOCALLAB_SHORTC;Short Curves 'L' Mask
TP_LOCALLAB_SHORTCMASK_TOOLTIP;Short circuit the 2 curves L(L) and L(H).\nAllows you to mix the current image with the original image modified by the mask job.\nUsable with masks 2, 3, 4, 6, 7
@@ -3083,7 +3084,7 @@ TP_LOCALLAB_SHOWT;Mask and modifications
TP_LOCALLAB_SHOWVI;Mask and modifications
TP_LOCALLAB_SHRESFRA;Shadows/Highlights
TP_LOCALLAB_SHTRC_TOOLTIP;Based on 'working profile' (only those provided), modifies the tones of the image by acting on a TRC (Tone Response Curve).\nGamma acts mainly on light tones.\nSlope acts mainly on dark tones.\nIt is recommended that the TRC of both devices (monitor and output profile) be sRGB (default).
-TP_LOCALLAB_SH_TOOLNAME;Shadows/Highlights & Tone Equalizer - 5
+TP_LOCALLAB_SH_TOOLNAME;Shadows/Highlights & Tone Equalizer
TP_LOCALLAB_SIGMAWAV;Attenuation response
TP_LOCALLAB_SIM;Simple
TP_LOCALLAB_SLOMASKCOL;Slope
@@ -3096,7 +3097,7 @@ TP_LOCALLAB_SOFTRADIUSCOL;Soft radius
TP_LOCALLAB_SOFTRADIUSCOL_TOOLTIP;Applies a guided filter to the output image to reduce possible artifacts.
TP_LOCALLAB_SOFTRETI;Reduce ΔE artifacts
TP_LOCALLAB_SOFTRETI_TOOLTIP;Take into account deltaE to improve Transmission map
-TP_LOCALLAB_SOFT_TOOLNAME;Soft Light & Original Retinex - 6
+TP_LOCALLAB_SOFT_TOOLNAME;Soft Light & Original Retinex
TP_LOCALLAB_SOURCE_ABS;Absolute luminance
TP_LOCALLAB_SOURCE_GRAY;Mean luminance (Yb%)
TP_LOCALLAB_SPECCASE;Specific cases
@@ -3139,7 +3140,7 @@ TP_LOCALLAB_TONEMAPGAM_TOOLTIP;The Gamma slider shifts the tone-mapping effect t
TP_LOCALLAB_TONEMAPREWEI_TOOLTIP;In some cases tone mapping may result in a cartoonish appearance, and in some rare cases soft but wide halos may appear.\n Increasing the number of reweighting iterates will help fight some of these problems.
TP_LOCALLAB_TONEMAP_TOOLTIP;Same as the tone mapping tool in the main menu.\nThe main-menu tool must be deactivated if this tool is used.
TP_LOCALLAB_TONEMASCALE_TOOLTIP;This slider allows you to adjust the transition between "local" and "global" contrast.\nThe greater the value, the larger a detail needs to be for it to be boosted
-TP_LOCALLAB_TONE_TOOLNAME;Tone Mapping - 4
+TP_LOCALLAB_TONE_TOOLNAME;Tone Mapping
TP_LOCALLAB_TOOLCOL;Structure mask as tool
TP_LOCALLAB_TOOLCOLFRMASK_TOOLTIP;Allows you to modify the mask, if one exists
TP_LOCALLAB_TOOLMASK;Mask Tools
@@ -3158,7 +3159,7 @@ TP_LOCALLAB_USEMASK;Laplacian
TP_LOCALLAB_VART;Variance (contrast)
TP_LOCALLAB_VIBRANCE;Vibrance & Warm/Cool
TP_LOCALLAB_VIBRA_TOOLTIP;Adjusts vibrance (essentially the same as the global adjustment).\nCarries out the equivalent of a white-balance adjustment using a CIECAM algorithm.
-TP_LOCALLAB_VIB_TOOLNAME;Vibrance & Warm/Cool - 3
+TP_LOCALLAB_VIB_TOOLNAME;Vibrance & Warm/Cool
TP_LOCALLAB_VIS_TOOLTIP;Click to show/hide selected Control Spot.\nCtrl+click to show/hide all Control Spot.
TP_LOCALLAB_WAMASKCOL;Ψ Mask Wavelet level
TP_LOCALLAB_WARM;Warm/Cool & Color artifacts
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index fb0394df5..790a2bf0d 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -822,6 +822,8 @@ void Crop::update(int todo)
const std::unique_ptr reservCrop(new LabImage(*laboCrop, true));
const std::unique_ptr lastorigCrop(new LabImage(*laboCrop, true));
+ std::unique_ptr savenormtmCrop;
+ std::unique_ptr savenormretiCrop;
auto& lllocalcurve2 = parent->lllocalcurve;
auto& cllocalcurve2 = parent->cllocalcurve;
auto& lclocalcurve2 = parent->lclocalcurve;
@@ -987,6 +989,10 @@ void Crop::update(int todo)
lumare = parent->lumarefs[sp];
sobelre = parent->sobelrefs[sp];
const float avge = parent->avgs[sp];
+ float meantme = parent->meantms[sp];
+ float stdtme = parent->stdtms[sp];
+ float meanretie = parent->meanretis[sp];
+ float stdretie = parent->stdretis[sp];
float minCD;
float maxCD;
@@ -1002,7 +1008,7 @@ void Crop::update(int todo)
skip);
// Locallab mask are only shown for selected spot
if (sp == params.locallab.selspot) {
- parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop.get(), lastorigCrop.get(), cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve,
+ parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop.get(), savenormtmCrop.get(), savenormretiCrop.get(), lastorigCrop.get(), cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve,
lllocalcurve2,locallutili,
cllocalcurve2, localclutili,
lclocalcurve2, locallcutili,
@@ -1045,7 +1051,8 @@ void Crop::update(int todo)
LHutili, HHutili, CHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav,
parent->previewDeltaE, parent->locallColorMask, parent->locallColorMaskinv, parent->locallExpMask, parent->locallExpMaskinv, parent->locallSHMask, parent->locallSHMaskinv, parent->locallvibMask, parent->localllcMask, parent->locallsharMask, parent->locallcbMask, parent->locallretiMask, parent->locallsoftMask, parent->localltmMask, parent->locallblMask,
- parent->localllogMask, parent->locall_Mask, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
+ parent->localllogMask, parent->locall_Mask, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
+ meantme, stdtme, meanretie, stdretie);
if(parent->previewDeltaE || parent->locallColorMask == 5 || parent->locallvibMask == 4 || parent->locallExpMask == 5 || parent->locallSHMask == 4 || parent->localllcMask == 4 || parent->localltmMask == 4 || parent->localllogMask == 4 || parent->locallsoftMask == 6 || parent->localllcMask == 4) {
params.blackwhite.enabled = false;
params.colorToning.enabled = false;
@@ -1070,7 +1077,7 @@ void Crop::update(int todo)
params.softlight.enabled = false;
}
} else {
- parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop.get(), lastorigCrop.get(), cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve,
+ parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop.get(), savenormtmCrop.get(), savenormretiCrop.get(), lastorigCrop.get(), cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve,
lllocalcurve2,locallutili,
cllocalcurve2, localclutili,
lclocalcurve2, locallcutili,
@@ -1113,7 +1120,8 @@ void Crop::update(int todo)
loclmasCurve_wav,lmasutili_wav,
LHutili, HHutili, CHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
+ minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
+ meantme, stdtme, meanretie, stdretie);
}
if (sp + 1u < params.locallab.spots.size()) {
// do not copy for last spot as it is not needed anymore
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 49e92c5c9..71468fd8f 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -799,7 +799,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
ipf.getAutoLogloc(sp, imgsrc, sourceg, blackev, whiteev, Autogr, sourceab, fw, fh, xsta, xend, ysta, yend, SCALE);
-
+ //printf("sg=%f sab=%f\n", sourceg[sp], sourceab[sp]);
params->locallab.spots.at(sp).blackEv = blackev[sp];
params->locallab.spots.at(sp).whiteEv = whiteev[sp];
params->locallab.spots.at(sp).sourceGray = sourceg[sp];
@@ -896,10 +896,13 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
*/
const std::unique_ptr reserv(new LabImage(*oprevl, true));
const std::unique_ptr lastorigimp(new LabImage(*oprevl, true));
+ std::unique_ptr savenormdr;
+ std::unique_ptr savenormtm;
+ std::unique_ptr savenormreti;
float **shbuffer = nullptr;
int sca = 1;
double huere, chromare, lumare, huerefblu, chromarefblu, lumarefblu, sobelre;
- float avge;
+ float avge, meantme, stdtme, meanretie, stdretie;
std::vector locallref;
std::vector locallretiminmax;
huerefs.resize(params->locallab.spots.size());
@@ -910,8 +913,20 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
lumarefs.resize(params->locallab.spots.size());
sobelrefs.resize(params->locallab.spots.size());
avgs.resize(params->locallab.spots.size());
+ meantms.resize(params->locallab.spots.size());
+ stdtms.resize(params->locallab.spots.size());
+ meanretis.resize(params->locallab.spots.size());
+ stdretis.resize(params->locallab.spots.size());
for (int sp = 0; sp < (int)params->locallab.spots.size(); sp++) {
+
+ if(params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap) {
+ savenormtm.reset(new LabImage(*oprevl, true));
+ }
+
+ if(params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) {
+ savenormreti.reset(new LabImage(*oprevl, true));
+ }
// Set local curves of current spot to LUT
locRETgainCurve.Set(params->locallab.spots.at(sp).localTgaincurve);
locRETtransCurve.Set(params->locallab.spots.at(sp).localTtranscurve);
@@ -1000,6 +1015,51 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
} else {
ipf.calc_ref(sp, nprevl, nprevl, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge, locwavCurveden, locwavdenutili);
}
+ //
+ meantme = 0.f;
+ stdtme = 0.f;
+ meanretie = 0.f;
+ stdretie = 0.f;
+
+ bool istm = params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap;
+ bool isreti = params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti;
+ //preparation for mean and sigma on current RT-spot
+ float locx = 0.f;
+ float locy = 0.f;
+ float locxl = 0.f;
+ float locyt = 0.f;
+ float centx = 0.f;
+ float centy = 0.f;
+ float ysta = 0.f;
+ float yend = 1.f;
+ float xsta = 0.f;
+ float xend = 1.f;
+ if(istm || isreti) {
+ locx = params->locallab.spots.at(sp).loc.at(0) / 2000.0;
+ locy = params->locallab.spots.at(sp).loc.at(2) / 2000.0;
+ locxl= params->locallab.spots.at(sp).loc.at(1) / 2000.0;
+ locyt = params->locallab.spots.at(sp).loc.at(3) / 2000.0;
+ centx = params->locallab.spots.at(sp).centerX / 2000.0 + 0.5;
+ centy = params->locallab.spots.at(sp).centerY / 2000.0 + 0.5;
+ ysta = std::max(static_cast(centy - locyt), 0.f);
+ yend = std::min(static_cast(centy + locy), 1.f);
+ xsta = std::max(static_cast(centx - locxl), 0.f);
+ xend = std::min(static_cast(centx + locx), 1.f);
+ // printf("xsta=%f xend=%f ysta=%f yend=%f \n", xsta, xend, ysta, yend);
+ }
+ int ww = nprevl->W;
+ int hh = nprevl->H;
+ int xxs = xsta * ww;
+ int xxe = xend * ww;
+ int yys = ysta * hh;
+ int yye = yend * hh;
+
+ if(istm) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
+ ipf.mean_sig (nprevl->L, meantme, stdtme, xxs, xxe, yys, yye);
+ }
+ if(isreti) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
+ ipf.mean_sig (nprevl->L, meanretie, stdretie,xxs, xxe, yys, yye) ;
+ }
double huerblu = huerefblurs[sp] = huerefblu;
double chromarblu = chromarefblurs[sp] = chromarefblu;
@@ -1009,6 +1069,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
double lumar = lumarefs[sp] = lumare ;
double sobeler = sobelrefs[sp] = sobelre;
float avg = avgs[sp] = avge;
+ float meantm = meantms[sp] = meantme;
+ float stdtm = stdtms[sp] = stdtme;
+ float meanreti = meanretis[sp] = meanretie;
+ float stdreti = stdretis[sp] = stdretie;
+
CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lumar,
hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, avg,
sca);
@@ -1034,7 +1099,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
float Tmin;
float Tmax;
int lastsav;
- ipf.Lab_Local(3, sp, (float**)shbuffer, nprevl, nprevl, reserv.get(), lastorigimp.get(), 0, 0, pW, pH, scale, locRETgainCurve, locRETtransCurve,
+ ipf.Lab_Local(3, sp, (float**)shbuffer, nprevl, nprevl, reserv.get(), savenormtm.get(), savenormreti.get(), lastorigimp.get(), 0, 0, pW, pH, scale, locRETgainCurve, locRETtransCurve,
lllocalcurve, locallutili,
cllocalcurve, localclutili,
lclocalcurve, locallcutili,
@@ -1076,7 +1141,30 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
loclmasCurve_wav, lmasutili_wav,
LHutili, HHutili, CHutili, cclocalcurve, localcutili, rgblocalcurve, localrgbutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc,
huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, lastsav, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
+ minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
+ meantm, stdtm, meanreti, stdreti);
+
+
+
+ if(istm) { //calculate mean and sigma on full image for use by normalize_mean_dt
+ float meanf = 0.f;
+ float stdf = 0.f;
+ ipf.mean_sig (savenormtm.get()->L, meanf, stdf, xxs, xxe, yys, yye);
+
+ //using 2 unused variables noiselumc and softradiustm
+ params->locallab.spots.at(sp).noiselumc = (int) meanf;
+ params->locallab.spots.at(sp).softradiustm = stdf ;
+ }
+
+ if(isreti) { //calculate mean and sigma on full image for use by normalize_mean_dt
+ float meanf = 0.f;
+ float stdf = 0.f;
+ ipf.mean_sig (savenormreti.get()->L, meanf, stdf,xxs, xxe, yys, yye );
+ //using 2 unused variables sensihs and sensiv
+ params->locallab.spots.at(sp).sensihs = (int) meanf;
+ params->locallab.spots.at(sp).sensiv = (int) stdf;
+ }
+
if (sp + 1u < params->locallab.spots.size()) {
// do not copy for last spot as it is not needed anymore
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index 5c17f36b8..9735f8be8 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -339,6 +339,10 @@ protected:
std::vector lumarefs;
std::vector sobelrefs;
std::vector avgs;
+ std::vector meantms;
+ std::vector stdtms;
+ std::vector meanretis;
+ std::vector stdretis;
bool lastspotdup;
bool previewDeltaE;
int locallColorMask;
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index 09b247b6e..c11f0810b 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -147,7 +147,7 @@ enum class BlurType {
explicit ImProcFunctions(const procparams::ProcParams* iparams, bool imultiThread = true)
: monitorTransform(nullptr), params(iparams), scale(1), multiThread(imultiThread), lumimul{} {}
~ImProcFunctions();
- bool needsLuminanceOnly()
+ bool needsLuminanceOnly() const
{
return !(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient());
}
@@ -251,7 +251,7 @@ enum class BlurType {
int shortcu, bool delt, const float hueref, const float chromaref, const float lumaref,
float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, bool fftt, float blu_ma, float cont_ma, int indic);
- void avoidcolshi(struct local_params& lp, int sp, LabImage * original, LabImage *transformed, int cy, int cx, int sk);
+ void avoidcolshi(const struct local_params& lp, int sp, LabImage * original, LabImage *transformed, int cy, int cx, int sk);
void deltaEforMask(float **rdE, int bfw, int bfh, LabImage* bufcolorig, const float hueref, const float chromaref, const float lumaref,
float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh);
@@ -264,7 +264,7 @@ enum class BlurType {
void mean_dt(const float * data, size_t size, double& mean_p, double& dt_p);
float *cos_table(size_t size);
- void normalize_mean_dt(float *data, const float *ref, size_t size, float mod, float sigm);
+ void normalize_mean_dt(float *data, const float *ref, size_t size, float mod, float sigm, float mdef, float sdef, float mdef2, float sdef2);
void retinex_pde(const float *datain, float * dataout, int bfw, int bfh, float thresh, float multy, float *dE, int show, int dEenable, int normalize);
void exposure_pde(float *dataor, float *datain, float * dataout, int bfw, int bfh, float thresh, float mod);
void fftw_convol_blur(float *input, float *output, int bfw, int bfh, float radius, int fftkern, int algo);
@@ -293,11 +293,12 @@ enum class BlurType {
bool delt, const float hueref, const float chromaref, const float lumaref,
float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask);
+ void mean_sig (const float* const * const savenormL, float &meanf, float &stdf, int xStart, int xEnd, int yStart, int yEnd) const;
void calc_ref(int sp, LabImage* original, LabImage* transformed, int cx, int cy, int oW, int oH, int sk, double &huerefblur, double &chromarefblur, double &lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, float &avg, const LocwavCurve & locwavCurveden, bool locwavdenutili);
void copy_ref(LabImage* spotbuffer, LabImage* original, LabImage* transformed, int cx, int cy, int sk, const struct local_params & lp, double &huerefspot, double &chromarefspot, double &lumarefspot);
void paste_ref(LabImage* spotbuffer, LabImage* transformed, int cx, int cy, int sk, const struct local_params & lp);
- void Lab_Local(int call, int sp, float** shbuffer, LabImage* original, LabImage* transformed, LabImage* reserved, LabImage* lastorig, int cx, int cy, int oW, int oH, int sk, const LocretigainCurve& locRETgainCcurve, const LocretitransCurve &locRETtransCcurve,
+ void Lab_Local(int call, int sp, float** shbuffer, LabImage* original, LabImage* transformed, LabImage* reserved, LabImage * savenormtm, LabImage * savenormreti, LabImage* lastorig, int cx, int cy, int oW, int oH, int sk, const LocretigainCurve& locRETgainCcurve, const LocretitransCurve &locRETtransCcurve,
const LUTf& lllocalcurve, bool locallutili,
const LUTf& cllocalcurve, bool localclutili,
const LUTf& lclocalcurve, bool locallcutili,
@@ -314,7 +315,7 @@ enum class BlurType {
const LUTf& lmaskloglocalcurve, bool localmasklogutili,
const LUTf& lmasklocal_curve, bool localmask_utili,
- const LocCCmaskCurve& locccmasCurve, bool lcmasutili, const LocLLmaskCurve& locllmasCurve, bool llmasutili, const LocHHmaskCurve& lochhmasCurve, bool lhmasutili, const LocHHmaskCurve& lochhhmasCurve, bool lhhmasutili,
+ const LocCCmaskCurve& locccmasCurve, bool lcmasutili, const LocLLmaskCurve& locllmasCurve, bool llmasutili, const LocHHmaskCurve& lochhmasCurve, bool lhmasutili, const LocHHmaskCurve& llochhhmasCurve, bool lhhmasutili,
const LocCCmaskCurve& locccmasexpCurve, bool lcmasexputili, const LocLLmaskCurve& locllmasexpCurve, bool llmasexputili, const LocHHmaskCurve& lochhmasexpCurve, bool lhmasexputili,
const LocCCmaskCurve& locccmasSHCurve, bool lcmasSHutili, const LocLLmaskCurve& locllmasSHCurve, bool llmasSHutili, const LocHHmaskCurve& lochhmasSHCurve, bool lhmasSHutili,
const LocCCmaskCurve& locccmasvibCurve, bool lcmasvibutili, const LocLLmaskCurve& locllmasvibCurve, bool llmasvibutili, const LocHHmaskCurve& lochhmasvibCurve, bool lhmasvibutili,
@@ -341,7 +342,8 @@ enum class BlurType {
bool LHutili, bool HHutili, bool CHutili, const LUTf& cclocalcurve, bool localcutili, const LUTf& rgblocalcurve, bool localrgbutili, bool localexutili, const LUTf& exlocalcurve, const LUTf& hltonecurveloc, const LUTf& shtonecurveloc, const LUTf& tonecurveloc, const LUTf& lightCurveloc,
double& huerefblur, double &chromarefblur, double& lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, int &lastsav,
bool prevDeltaE, int llColorMask, int llColorMaskinv, int llExpMask, int llExpMaskinv, int llSHMask, int llSHMaskinv, int llvibMask, int lllcMask, int llsharMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask, int llblMask, int lllogMask, int ll_Mask,
- float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax);
+ float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax,
+ float& meantm, float& stdtm, float& meanreti, float& stdreti);
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);
@@ -357,7 +359,7 @@ enum class BlurType {
const LocwavCurve & loccompwavCurve, bool loccompwavutili, bool wavcurvecomp,
const LocwavCurve & loccomprewavCurve, bool loccomprewavutili, bool wavcurvecompre,
const LocwavCurve & locedgwavCurve, bool locedgwavutili,
- float sigm, float offs,int & maxlvl, float fatdet, float fatanch, float chromalev, float chromablu, bool blurlc, bool blurena, bool levelena, bool comprena, bool compreena, float compress, float thres);
+ float sigm, float offs,int & maxlvl, float sigmadc, float deltad, float chromalev, float chromablu, bool blurlc, bool blurena, bool levelena, bool comprena, bool compreena, float compress, float thres);
void wavcont(const struct local_params& lp, float ** tmp, wavelet_decomposition &wdspot, int level_bl, int maxlvl,
const LocwavCurve & loclevwavCurve, bool loclevwavutili,
@@ -368,7 +370,7 @@ enum class BlurType {
void wavcbd(wavelet_decomposition &wdspot, int level_bl, int maxlvl,
const LocwavCurve& locconwavCurve, bool locconwavutili, float sigm, float offs, float chromalev, int sk);
- void transit_shapedetect2(int call, int senstype, const LabImage * bufexporig, const LabImage * bufexpfin, LabImage * originalmask, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk);
+ void transit_shapedetect2(int sp, float meantm, float stdtm, int call, int senstype, const LabImage * bufexporig, const LabImage * bufexpfin, LabImage * originalmask, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk);
void transit_shapedetect_retinex(int call, int senstype, LabImage * bufexporig, LabImage * bufexpfin, LabImage * bufmask, LabImage * buforigmas, float **buflight, float **bufchro, const float hueref, const float chromaref, const float lumaref, struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk);
void transit_shapedetect(int senstype, const LabImage *bufexporig, LabImage * originalmask, float **bufchro, bool HHutili, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk);
diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc
index 7005af21f..ca1319052 100644
--- a/rtengine/iplocallab.cc
+++ b/rtengine/iplocallab.cc
@@ -1830,6 +1830,27 @@ float find_gray(float source_gray, float target_gray)
return 0.f; // not found
}
+void ImProcFunctions::mean_sig (const float* const * const savenormL, float &meanf, float &stdf, int xStart, int xEnd, int yStart, int yEnd) const {
+ const int size = (yEnd - yStart) * (xEnd - xStart);
+ // use double precision for large accumulations
+ double meand = 0.0;
+ double stdd = 0.0;
+#ifdef _OPENMP
+ #pragma omp parallel for reduction(+:meand, stdd) if(multiThread)
+#endif
+ for (int y = yStart; y < yEnd; ++y) {
+ for (int x = xStart; x < xEnd; ++x) {
+ meand += static_cast(savenormL[y][x]);
+ stdd += SQR(static_cast(savenormL[y][x]));
+ }
+ }
+ meand /= size;
+ stdd /= size;
+ stdd -= SQR(meand);
+ stdf = std::sqrt(stdd);
+ meanf = meand;
+}
+
// basic log encoding taken from ACESutil.Lin_to_Log2, from
// https://github.com/ampas/aces-dev
@@ -2031,7 +2052,7 @@ void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg,
const int wsta = xsta * w;
const int wend = xend * w;
-
+
double mean = 0.0;
int nc = 0;
for (int y = hsta; y < hend; ++y) {
@@ -4308,7 +4329,7 @@ void ImProcFunctions::mean_dt(const float* data, size_t size, double& mean_p, do
dt_p = std::sqrt(dt);
}
-void ImProcFunctions::normalize_mean_dt(float * data, const float * ref, size_t size, float mod, float sigm)
+void ImProcFunctions::normalize_mean_dt(float * data, const float * ref, size_t size, float mod, float sigm, float mdef, float sdef, float mdef2, float sdef2)
{
/*
* Copyright 2009-2011 IPOL Image Processing On Line http://www.ipol.im/
@@ -4318,7 +4339,7 @@ void ImProcFunctions::normalize_mean_dt(float * data, const float * ref, size_t
* @brief laplacian, DFT and Poisson routines
*
* @author Nicolas Limare
- * adapted for Rawtherapee - jacques Desmis july 2019
+ * adapted for Rawtherapee - jacques Desmis july 2019 - march 2021
*/
if (NULL == data || NULL == ref) {
@@ -4329,8 +4350,19 @@ void ImProcFunctions::normalize_mean_dt(float * data, const float * ref, size_t
double mean_ref, mean_data, dt_ref, dt_data;
/* compute mean and variance of the two arrays */
- mean_dt(ref, size, mean_ref, dt_ref);
- mean_dt(data, size, mean_data, dt_data);
+ if(mdef!= 0.f && sdef != 0.f) {
+ mean_ref = mdef;
+ dt_ref = sdef;
+ } else {
+ mean_dt(ref, size, mean_ref, dt_ref);
+ }
+ if(mdef2!= 0.f && sdef2 != 0.f) {
+ // printf("OK shortcut\n");
+ mean_data = mdef2;
+ dt_data = sdef2;
+ } else {
+ mean_dt(data, size, mean_data, dt_data);
+ }
/* compute the normalization coefficients */
const double a = dt_ref / dt_data;
@@ -4474,7 +4506,7 @@ void ImProcFunctions::retinex_pde(const float * datain, float * dataout, int bfw
fftwf_free(data_fft);
if (show != 4 && normalize == 1) {
- normalize_mean_dt(data_tmp, datain, bfw * bfh, 1.f, 1.f);
+ normalize_mean_dt(data_tmp, datain, bfw * bfh, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f);
}
if (show == 0 || show == 4) {
@@ -5800,7 +5832,7 @@ void ImProcFunctions::transit_shapedetect(int senstype, const LabImage * bufexpo
data[(y - ystart)* bfw + (x - xstart)] = bufexporig->L[y - ystart][x - xstart];
}
- normalize_mean_dt(data, datain, bfh * bfw, 1.f, 1.f);
+ normalize_mean_dt(data, datain, bfh * bfw, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f);
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
@@ -6769,7 +6801,7 @@ void ImProcFunctions::BlurNoise_Local(LabImage *tmp1, LabImage * originalmask, c
}
}
-void ImProcFunctions::transit_shapedetect2(int call, int senstype, const LabImage * bufexporig, const LabImage * bufexpfin, LabImage * originalmask, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk)
+void ImProcFunctions::transit_shapedetect2(int sp, float meantm, float stdtm, int call, int senstype, const LabImage * bufexporig, const LabImage * bufexpfin, LabImage * originalmask, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk)
{
//initialize coordinates
int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
@@ -6915,8 +6947,21 @@ void ImProcFunctions::transit_shapedetect2(int call, int senstype, const LabImag
datain[(y - ystart) * bfw + (x - xstart)] = original->L[y][x];
data[(y - ystart)* bfw + (x - xstart)] = bufexpfin->L[y - ystart][x - xstart];
}
-
- normalize_mean_dt(data, datain, bfh * bfw, 1.f, 1.f);
+ if(call == 3 || call == 2) {//improccoordinator and simpleprocess
+ normalize_mean_dt(data, datain, bfw * bfh, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f);
+ } else if(call == 1) {//dcrop
+ float ma = meantm;
+ float sa = stdtm;
+ float ma2 = (float) params->locallab.spots.at(sp).noiselumc;
+ float sa2 = (float) params->locallab.spots.at(sp).softradiustm;
+ //printf("ma=%f sa=%f ma2=%f sa2=%f\n", (double) ma, (double) sa, (double) ma2, (double) sa2);
+ //use normalize with mean and stdv
+ normalize_mean_dt(data, datain, bfw * bfh, 1.f, 1.f, ma, sa, ma2, sa2);
+ }
+
+
+
+
#ifdef _OPENMP
#pragma omp parallel for
#endif
@@ -7166,7 +7211,7 @@ void ImProcFunctions::exposure_pde(float * dataor, float * datain, float * datao
}
#endif
- normalize_mean_dt(data, dataor, bfw * bfh, mod, 1.f);
+ normalize_mean_dt(data, dataor, bfw * bfh, mod, 1.f, 0.f, 0.f, 0.f, 0.f);
{
#ifdef _OPENMP
@@ -8982,6 +9027,8 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
}
}
+
+
#ifdef _OPENMP
const int numThreads = omp_get_max_threads();
#else
@@ -10523,7 +10570,7 @@ void clarimerge(struct local_params& lp, float &mL, float &mC, bool &exec, LabIm
}
}
-void ImProcFunctions::avoidcolshi(struct local_params& lp, int sp, LabImage * original, LabImage *transformed, int cy, int cx, int sk)
+void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImage * original, LabImage *transformed, int cy, int cx, int sk)
{
if (params->locallab.spots.at(sp).avoid && lp.islocal) {
const float ach = lp.trans / 100.f;
@@ -10658,8 +10705,8 @@ void ImProcFunctions::avoidcolshi(struct local_params& lp, int sp, LabImage * or
Color::pregamutlab(Lprov1, HH, chr);
Chprov1 = rtengine::min(Chprov1, chr);
- float R, G, B;
if(!muns) {
+ float R, G, B;
Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, mint, maxt);//replace for best results
}
transformed->L[y][x] = Lprov1 * 327.68f;
@@ -11193,7 +11240,7 @@ void ImProcFunctions::NLMeans(float **img, int strength, int detail_thresh, int
}
void ImProcFunctions::Lab_Local(
- int call, int sp, float** shbuffer, LabImage * original, LabImage * transformed, LabImage * reserved, LabImage * lastorig, int cx, int cy, int oW, int oH, int sk,
+ int call, int sp, float** shbuffer, LabImage * original, LabImage * transformed, LabImage * reserved, LabImage * savenormtm, LabImage * savenormreti, LabImage * lastorig, int cx, int cy, int oW, int oH, int sk,
const LocretigainCurve& locRETgainCcurve, const LocretitransCurve& locRETtransCcurve,
const LUTf& lllocalcurve, bool locallutili,
const LUTf& cllocalcurve, bool localclutili,
@@ -11238,7 +11285,8 @@ void ImProcFunctions::Lab_Local(
bool LHutili, bool HHutili, bool CHutili, const LUTf& cclocalcurve, bool localcutili, const LUTf& rgblocalcurve, bool localrgbutili, bool localexutili, const LUTf& exlocalcurve, const LUTf& hltonecurveloc, const LUTf& shtonecurveloc, const LUTf& tonecurveloc, const LUTf& lightCurveloc,
double& huerefblur, double& chromarefblur, double& lumarefblur, double& hueref, double& chromaref, double& lumaref, double& sobelref, int &lastsav,
bool prevDeltaE, int llColorMask, int llColorMaskinv, int llExpMask, int llExpMaskinv, int llSHMask, int llSHMaskinv, int llvibMask, int lllcMask, int llsharMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask, int llblMask, int lllogMask, int ll_Mask,
- float& minCD, float& maxCD, float& mini, float& maxi, float& Tmean, float& Tsigma, float& Tmin, float& Tmax
+ float& minCD, float& maxCD, float& mini, float& maxi, float& Tmean, float& Tsigma, float& Tmin, float& Tmax,
+ float& meantm, float& stdtm, float& meanreti, float& stdreti
)
{
//general call of others functions : important return hueref, chromaref, lumaref
@@ -11501,7 +11549,7 @@ void ImProcFunctions::Lab_Local(
bool invmask = false;
maskrecov(bufexpfin.get(), original, bufmaskoriglog.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
}
- transit_shapedetect2(call, 11, bufexporig.get(), bufexpfin.get(), originalmasklog.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 11, bufexporig.get(), bufexpfin.get(), originalmasklog.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
}
if (lp.recur) {
@@ -12274,6 +12322,988 @@ void ImProcFunctions::Lab_Local(
}
}
+//Tone mapping
+
+ if ((lp.strengt != 0.f || lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4 || lp.prevdE) && lp.tonemapena && !params->epd.enabled) {
+ if (call <= 3) { //simpleprocess dcrop improcc
+ const int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
+ const int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
+ const int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
+ const int xend = rtengine::min(static_cast(lp.xc + lp.lx) - cx, original->W);
+ const int bfh = yend - ystart;
+ const int bfw = xend - xstart;
+
+ if (bfw >= mDEN && bfh >= mDEN) {
+ // printf("OK TM\n");
+ array2D buflight(bfw, bfh);
+ JaggedArray bufchro(bfw, bfh);
+ std::unique_ptr bufgb(new LabImage(bfw, bfh));
+ const std::unique_ptr tmp1(new LabImage(bfw, bfh));
+ const std::unique_ptr bufgbm(new LabImage(bfw, bfh));
+ const std::unique_ptr tmp1m(new LabImage(bfw, bfh));
+ std::unique_ptr bufmaskorigtm;
+ std::unique_ptr bufmaskblurtm;
+ std::unique_ptr originalmasktm;
+
+ // if (lp.showmasktmmet == 0 || lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4) {
+ if (lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4) {
+ bufmaskorigtm.reset(new LabImage(bfw, bfh));
+ bufmaskblurtm.reset(new LabImage(bfw, bfh));
+ originalmasktm.reset(new LabImage(bfw, bfh));
+ }
+
+ // 3 loops to avoid performance penalty on machines with 4-way L1 cache
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+ {
+ #pragma omp for schedule(dynamic,16) nowait
+#endif
+ for (int y = ystart; y < yend; y++) {
+ for (int x = xstart; x < xend; x++) {
+ bufgbm->L[y - ystart][x - xstart] = bufgb->L[y - ystart][x - xstart] = original->L[y][x];
+ }
+ }
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16) nowait
+#endif
+ for (int y = ystart; y < yend; y++) {
+ for (int x = xstart; x < xend; x++) {
+ bufgbm->a[y - ystart][x - xstart] = bufgb->a[y - ystart][x - xstart] = original->a[y][x];
+ }
+ }
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+ for (int y = ystart; y < yend; y++) {
+ for (int x = xstart; x < xend; x++) {
+ bufgbm->b[y - ystart][x - xstart] = bufgb->b[y - ystart][x - xstart] = original->b[y][x];
+ }
+ }
+#ifdef _OPENMP
+ }
+#endif
+
+ int inv = 0;
+ bool showmaske = false;
+ bool enaMask = false;
+ bool deltaE = false;
+ bool modmask = false;
+ bool zero = false;
+ bool modif = false;
+
+ if (lp.showmasktmmet == 3) {
+ showmaske = true;
+ }
+
+ if (lp.enatmMask) {
+ enaMask = true;
+ }
+
+ if (lp.showmasktmmet == 4) {
+ deltaE = true;
+ }
+
+ if (lp.showmasktmmet == 2) {
+ modmask = true;
+ }
+
+ if (lp.showmasktmmet == 1) {
+ modif = true;
+ }
+
+ if (lp.showmasktmmet == 0) {
+ zero = true;
+ }
+
+ float chrom = lp.chromatm;;
+ float rad = lp.radmatm;
+ float gamma = lp.gammatm;
+ float slope = lp.slomatm;
+ float blendm = lp.blendmatm;
+ float lap = params->locallab.spots.at(sp).lapmasktm;
+ bool pde = params->locallab.spots.at(sp).laplac;
+ int lumask = params->locallab.spots.at(sp).lumask;
+
+ if (!params->locallab.spots.at(sp).enatmMaskaft) {
+ LocwavCurve dummy;
+ int sco = params->locallab.spots.at(sp).scopemask;
+ int shortcu = 0; //lp.mergemet;// params->locallab.spots.at(sp).shortc;
+
+ const float mindE = 2.f + MINSCOPE * sco * lp.thr;
+ const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
+ const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
+ const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
+ int shado = 0;
+ float amountcd = 0.f;
+ float anchorcd = 50.f;
+ LocHHmaskCurve lochhhmasCurve;
+ const int highl = 0;
+
+ maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufgbm.get(), bufmaskorigtm.get(), originalmasktm.get(), original, reserved, inv, lp,
+ 0.f, false,
+ locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, lochhhmasCurve, false, multiThread,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, false, 1, 1, 5, 5,
+ shortcu, params->locallab.spots.at(sp).deltae, hueref, chromaref, lumaref,
+ maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
+ );
+
+ if (lp.showmasktmmet == 3) {
+ showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, bufgbm.get(), transformed, bufmaskorigtm.get(), 0);
+
+ return;
+ }
+ }
+
+ if (lp.showmasktmmet == 0 || lp.showmasktmmet == 1 || lp.showmasktmmet == 2 || lp.showmasktmmet == 4 || lp.showmasktmmet == 3 || lp.enatmMask) {
+ constexpr int itera = 0;
+ ImProcFunctions::EPDToneMaplocal(sp, bufgb.get(), tmp1.get(), itera, sk);//iterate to 0 calculate with edgstopping, improve result, call=1 dcrop we can put iterate to 5
+
+ tmp1m->CopyFrom(tmp1.get(), multiThread); //save current result7
+ if(params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap) {
+ if(call == 3) {
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int y = ystart; y < yend; y++) {
+ for (int x = xstart; x < xend; x++) {
+ savenormtm->L[y][x] = tmp1->L[y - ystart][x - xstart];
+ savenormtm->a[y][x] = tmp1->a[y - ystart][x - xstart];
+ savenormtm->b[y][x] = tmp1->b[y - ystart][x - xstart];
+ }
+ }
+ }
+ }
+ bool enatmMasktmap = params->locallab.spots.at(sp).enatmMaskaft;
+
+ if (enatmMasktmap) {
+ //calculate new values for original, originalmasktm, bufmaskorigtm...in function of tmp1
+ LocwavCurve dummy;
+ int sco = params->locallab.spots.at(sp).scopemask;
+ int shortcu = 0;//lp.mergemet; //params->locallab.spots.at(sp).shortc;
+
+ const float mindE = 2.f + MINSCOPE * sco * lp.thr;
+ const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
+ const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
+ const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
+ int shado = 0;
+ float amountcd = 0.f;
+ float anchorcd = 50.f;
+ LocHHmaskCurve lochhhmasCurve;
+ const int highl = 0;
+
+ maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, tmp1.get(), bufmaskorigtm.get(), originalmasktm.get(), original, reserved, inv, lp,
+ 0.f, false,
+ locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, lochhhmasCurve, false, multiThread,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, false, 1, 1, 5, 5,
+ shortcu, params->locallab.spots.at(sp).deltae, hueref, chromaref, lumaref,
+ maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
+ );
+
+ if (lp.showmasktmmet == 3) {//display mask
+ showmask(params->locallab.spots.at(sp).lumask, lp, xstart, ystart, cx, cy, bfw, bfh, tmp1.get(), transformed, bufmaskorigtm.get(), 0);
+ return;
+ }
+
+ }
+
+ tmp1->CopyFrom(tmp1m.get(), multiThread); //restore current result
+
+
+ float minL = tmp1->L[0][0] - bufgb->L[0][0];
+ float maxL = minL;
+ float minC = std::sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - std::sqrt(SQR(bufgb->a[0][0]) + SQR(bufgb->b[0][0]));
+ float maxC = minC;
+
+#ifdef _OPENMP
+ #pragma omp parallel for reduction(max:maxL) reduction(min:minL) reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < bfh; ir++) {
+ for (int jr = 0; jr < bfw; jr++) {
+ buflight[ir][jr] = tmp1->L[ir][jr] - bufgb->L[ir][jr];
+ minL = rtengine::min(minL, buflight[ir][jr]);
+ maxL = rtengine::max(maxL, buflight[ir][jr]);
+ bufchro[ir][jr] = std::sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - std::sqrt(SQR(bufgb->a[ir][jr]) + SQR(bufgb->b[ir][jr]));
+ minC = rtengine::min(minC, bufchro[ir][jr]);
+ maxC = rtengine::max(maxC, bufchro[ir][jr]);
+ }
+ }
+
+ float coef = 0.01f * rtengine::max(std::fabs(minL), std::fabs(maxL));
+ float coefC = 0.01f * rtengine::max(std::fabs(minC), std::fabs(maxC));
+
+ if (coef == 0.f) {
+ coef = 1.f;
+ } else {
+ coef = 1.f / coef;
+ }
+
+ if (coefC == 0.f) {
+ coefC = 1.f;
+ } else {
+ coefC = 1.f / coefC;
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int y = 0; y < bfh; y++) {
+ for (int x = 0; x < bfw; x++) {
+ buflight[y][x] *= coef;
+ bufchro[y][x] *= coefC;
+ }
+ }
+
+ if(lp.enatmMask && lp.recothrt != 1.f) {
+ float hig = lp.higthrt;
+ float low = lp.lowthrt;
+ float recoth = lp.recothrt;
+ float decay = lp.decayt;
+ bool invmask = false;
+ maskrecov(tmp1.get(), original, bufmaskorigtm.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
+ }
+
+ // transit_shapedetect_retinex(call, 4, bufgb.get(),bufmaskorigtm.get(), originalmasktm.get(), buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, meantm, stdtm, call, 8, bufgb.get(), tmp1.get(), originalmasktm.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
+
+ // transit_shapedetect(8, tmp1.get(), originalmasktm.get(), bufchro, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
+ bufgb.reset();
+
+ if (lp.recur) {
+ original->CopyFrom(transformed, multiThread);
+ float avge;
+ calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
+ }
+ }
+ }
+ }
+ }
+
+//end TM
+
+
+ if ((lp.dehaze != 0 || lp.prevdE) && lp.retiena ) {
+ int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
+ int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
+ int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
+ int xend = rtengine::min(static_cast(lp.xc + lp.lx) - cx, original->W);
+ int bfh = yend - ystart;
+ int bfw = xend - xstart;
+
+ if (bfh >= mSP && bfw >= mSP) {
+ const std::unique_ptr bufexporig(new LabImage(bfw, bfh)); //buffer for data in zone limit
+ const std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); //buffer for data in zone limit
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int y = ystart; y < yend; y++) {
+ for (int x = xstart; x < xend; x++) {
+ bufexporig->L[y - ystart][x - xstart] = original->L[y][x];
+ bufexporig->a[y - ystart][x - xstart] = original->a[y][x];
+ bufexporig->b[y - ystart][x - xstart] = original->b[y][x];
+ }
+ }
+
+ bufexpfin->CopyFrom(bufexporig.get(), multiThread);
+ //calc dehaze
+ const std::unique_ptr tmpImage(new Imagefloat(bfw, bfh));
+
+ DehazeParams dehazeParams;
+ dehazeParams.enabled = true;
+ dehazeParams.strength = lp.dehaze;
+ dehazeParams.showDepthMap = false;
+ dehazeParams.saturation = lp.dehazeSaturation;
+ dehazeParams.depth = lp.depth;
+ lab2rgb(*bufexpfin, *tmpImage.get(), params->icm.workingProfile);
+ dehazeloc(tmpImage.get(), dehazeParams);
+ rgb2lab(*tmpImage.get(), *bufexpfin, params->icm.workingProfile);
+
+ transit_shapedetect2(sp, 0.f, 0.f, call, 30, bufexporig.get(), bufexpfin.get(), nullptr, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
+
+ if (lp.recur) {
+ original->CopyFrom(transformed, multiThread);
+ float avge;
+ calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
+ }
+ }
+ }
+
+ lp.invret = false;//always disabled inverse RETI too complex todo !!
+
+ if (lp.str >= 0.2f && lp.retiena && call != 2) {
+ LabImage *bufreti = nullptr;
+ LabImage *bufmask = nullptr;
+ LabImage *buforig = nullptr;
+ LabImage *buforigmas = nullptr;
+ LabImage *bufmaskorigreti = nullptr;
+
+ if (TW >= mSP && TH >= mSP) {
+
+ array2D buflight(TW, TH);
+ JaggedArray bufchro(TW, TH);
+
+ int Hd, Wd;
+ Hd = TH;
+ Wd = TW;
+
+ bufreti = new LabImage(TW, TH);
+ bufmask = new LabImage(TW, TH);
+ bufmaskorigreti = new LabImage(TW, TH);
+
+ if (!lp.enaretiMasktmap && lp.enaretiMask) {
+ buforig = new LabImage(TW, TH);
+ buforigmas = new LabImage(TW, TH);
+ // bufmaskorigreti = new LabImage(GW, GH);
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < TH; ir++) //fill with 0
+ for (int jr = 0; jr < TW; jr++) {
+ bufreti->L[ir][jr] = 0.f;
+ bufreti->a[ir][jr] = 0.f;
+ bufreti->b[ir][jr] = 0.f;
+ buflight[ir][jr] = 0.f;
+ bufchro[ir][jr] = 0.f;
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int y = 0; y < transformed->H ; y++) //{
+ for (int x = 0; x < transformed->W; x++) {
+ bufreti->L[y][x] = original->L[y][x];
+ bufreti->a[y][x] = original->a[y][x];
+ bufreti->b[y][x] = original->b[y][x];
+ bufmask->L[y][x] = original->L[y][x];
+ bufmask->a[y][x] = original->a[y][x];
+ bufmask->b[y][x] = original->b[y][x];
+
+
+
+ if (!lp.enaretiMasktmap && lp.enaretiMask) {
+ buforig->L[y][x] = original->L[y][x];
+ buforig->a[y][x] = original->a[y][x];
+ buforig->b[y][x] = original->b[y][x];
+
+ // bufmaskorigreti->L[y][x] = original->L[y][x];
+ // bufmaskorigreti->a[y][x] = original->a[y][x];
+ // bufmaskorigreti->b[y][x] = original->b[y][x];
+
+
+ }
+
+ }
+ float raddE = params->locallab.spots.at(sp).softradiusret;
+
+ //calc dE and reduction to use in MSR to reduce artifacts
+ const float mindE = 4.f + MINSCOPE * lp.sensh * lp.thr;
+ const float maxdE = 5.f + MAXSCOPE * lp.sensh * (1 + 0.1f * lp.thr);
+ const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
+ const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
+ const float refa = chromaref * cos(hueref);
+ const float refb = chromaref * sin(hueref);
+
+ const std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd));
+ float** reducDE = *(reducDEBuffer.get());
+
+ float ade = 0.01f * raddE;
+ float bde = 100.f - raddE;
+ float sensibefore = ade * lp.sensh + bde;//we can change sensitivity 0.1 90 or 0.3 70 or 0.4 60
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int y = 0; y < transformed->H ; y++)
+ for (int x = 0; x < transformed->W; x++) {
+ float dE = std::sqrt(SQR(refa - bufreti->a[y][x] / 327.68f) + SQR(refb - bufreti->b[y][x] / 327.68f) + SQR(static_cast(lumaref) - bufreti->b[y][x] / 327.68f));
+ const float reducdE = calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sensibefore);
+ reducDE[y][x] = clipDE(reducdE);
+ }
+
+ const std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd));
+ float** orig = *(origBuffer.get());
+
+ const std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd));
+ float** orig1 = *(origBuffer1.get());
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#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];
+ }
+
+ LabImage *tmpl = new LabImage(Wd, Hd);
+
+ bool fftw = lp.ftwreti;
+ //for Retinex Mask are incorporated in MSR
+ int sco = params->locallab.spots.at(sp).scopemask;
+ float lumask = params->locallab.spots.at(sp).lumask;
+
+ const float mindE2 = 2.f + MINSCOPE * sco * lp.thr;
+ const float maxdE2 = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
+ const float mindElim2 = 2.f + MINSCOPE * limscope * lp.thr;
+ const float maxdElim2 = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
+ ImProcFunctions::MSRLocal(call, sp, fftw, 1, reducDE, bufreti, bufmask, buforig, buforigmas, bufmaskorigreti, orig, orig1,
+ Wd, Hd, Wd, Hd, params->locallab, sk, locRETgainCcurve, locRETtransCcurve, 0, 4, 1.f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
+ locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask,
+ lmaskretilocalcurve, localmaskretiutili,
+ transformed, lp.enaretiMasktmap, lp.enaretiMask,
+ params->locallab.spots.at(sp).deltae, hueref, chromaref, lumaref,
+ maxdE2, mindE2, maxdElim2, mindElim2, lp.iterat, limscope, sco, lp.balance, lp.balanceh, lumask);
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#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(params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) {
+ if(call == 3) {
+ savenormreti->L[ir][jr] = tmpl->L[ir][jr];
+ }
+ }
+ }
+ }
+
+ if (lp.equret) { //equilibrate luminance before / after MSR
+ float *datain = new float[Hd * Wd];
+ float *data = new float[Hd * Wd];
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+ datain[ir * Wd + jr] = orig1[ir][jr];
+ data[ir * Wd + jr] = orig[ir][jr];
+ }
+
+ if(params->locallab.spots.at(sp).equilret){
+ if(call == 3) {//improccoordinator
+ normalize_mean_dt(data, datain, Hd * Wd, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f);
+ } else if(call == 1) {//dcrop
+ float ma = meanreti;
+ float sa = stdreti;
+ float ma2 = (float) params->locallab.spots.at(sp).sensihs;
+ float sa2 = (float) params->locallab.spots.at(sp).sensiv;
+ //printf("ma=%f sa=%f ma2=%f sa2=%f\n", (double) ma, (double) sa, (double) ma2, (double) sa2);
+ //use normalize with mean and stdv
+ normalize_mean_dt(data, datain, Hd * Wd, 1.f, 1.f, ma, sa, ma2, sa2);
+
+ }
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+ tmpl->L[ir][jr] = data[ir * Wd + jr];
+ }
+
+ delete [] datain;
+ delete [] data;
+ }
+
+ if(lp.enaretiMask && lp.recothrr != 1.f) {
+ float hig = lp.higthrr;
+ float low = lp.lowthrr;
+ float recoth = lp.recothrr;
+ float decay = lp.decayr;
+ bool invmask = false;
+ maskrecov(tmpl, original, bufmaskorigreti, Hd, Wd, 0, 0, hig, low, recoth, decay, invmask, sk, multiThread);
+ }
+
+ float minL = tmpl->L[0][0] - bufreti->L[0][0];
+ float maxL = minL;
+#ifdef _OPENMP
+ #pragma omp parallel for reduction(min:minL) reduction(max:maxL) schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ buflight[ir][jr] = tmpl->L[ir][jr] - bufreti->L[ir][jr];
+ minL = rtengine::min(minL, buflight[ir][jr]);
+ maxL = rtengine::max(maxL, buflight[ir][jr]);
+ }
+ }
+
+ const float coef = 0.01f * rtengine::max(std::fabs(minL), std::fabs(maxL));
+
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ buflight[ir][jr] /= coef;
+ }
+ }
+
+ transit_shapedetect_retinex(call, 4, bufreti, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
+
+ if (lp.recur) {
+ original->CopyFrom(transformed, multiThread);
+ float avge;
+ calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
+ }
+
+ if (params->locallab.spots.at(sp).chrrt > 0) {
+
+ if (call == 1) {
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+
+ orig[ir][jr] = std::sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr]));
+ orig1[ir][jr] = std::sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr]));
+ }
+
+ }
+
+ float maxChro = orig1[0][0];
+#ifdef _OPENMP
+ #pragma omp parallel for reduction(max:maxChro) schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ maxChro = rtengine::max(maxChro, orig1[ir][jr]);
+ }
+ }
+
+ float divchro = maxChro;
+
+ //first step change saturation without Retinex ==> gain of time and memory
+ float satreal = lp.str * static_cast(params->locallab.spots.at(sp).chrrt) / 100.f;
+
+ if (params->locallab.spots.at(sp).chrrt <= 0.2) {
+ satreal /= 10.f;
+ }
+
+ DiagonalCurve reti_satur({
+ DCT_NURBS,
+ 0, 0,
+ 0.2, 0.2f + satreal / 250.f,
+ 0.6, rtengine::min(1.f, 0.6f + satreal / 250.f),
+ 1, 1
+ });
+
+ if (call == 1) {
+
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir += 1)
+ for (int jr = 0; jr < Wd; jr += 1) {
+ const 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;
+
+ if (params->locallab.spots.at(sp).chrrt <= 100.0) { //first step
+ float buf = LIM01(orig[ir][jr] / divchro);
+ buf = reti_satur.getVal(buf);
+ buf *= divchro;
+ orig[ir][jr] = buf;
+ }
+
+ tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y;
+ tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x;
+ }
+
+ float minC = std::sqrt(SQR(tmpl->a[0][0]) + SQR(tmpl->b[0][0])) - orig1[0][0];
+ float maxC = minC;
+#ifdef _OPENMP
+ #pragma omp parallel for reduction(min:minC) reduction(max:maxC) schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ bufchro[ir][jr] = std::sqrt(SQR(tmpl->a[ir][jr]) + SQR(tmpl->b[ir][jr])) - orig1[ir][jr];
+ minC = rtengine::min(minC, bufchro[ir][jr]);
+ maxC = rtengine::max(maxC, bufchro[ir][jr]);
+ }
+ }
+
+ float coefC = 0.01f * rtengine::max(std::fabs(minC), std::fabs(maxC));
+
+ if (coefC > 0.f) {
+ coefC = 1.f / coefC;
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ bufchro[ir][jr] *= coefC;
+ }
+ }
+ }
+ }
+
+ transit_shapedetect_retinex(call, 5, tmpl, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
+
+ if (lp.recur) {
+ original->CopyFrom(transformed, multiThread);
+ float avge;
+ calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
+ }
+ }
+
+ delete tmpl;
+ delete bufmask;
+ delete bufmaskorigreti;
+
+ if (!lp.enaretiMasktmap && lp.enaretiMask) {
+ if (buforig) {
+ delete buforig;
+ }
+
+ if (buforigmas) {
+ delete buforigmas;
+ }
+ }
+ delete bufreti;
+ }
+ }
+
+
+
+ if (lp.str >= 0.2f && lp.retiena && call == 2) {
+ int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
+ int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
+ int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
+ int xend = rtengine::min(static_cast(lp.xc + lp.lx) - cx, original->W);
+ int bfh = yend - ystart;
+ int bfw = xend - xstart;
+
+ LabImage *bufreti = nullptr;
+ LabImage *bufmask = nullptr;
+ LabImage *buforig = nullptr;
+ LabImage *buforigmas = nullptr;
+ LabImage *bufmaskorigreti = nullptr;
+ int bfhr = bfh;
+ int bfwr = bfw;
+
+ if (bfw >= mSP && bfh > mSP) {
+ if (lp.ftwreti) {
+ optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
+ }
+
+ array2D buflight(bfw, bfh);
+ JaggedArray bufchro(bfw, bfh);
+
+ int Hd, Wd;
+ Hd = TH;
+ Wd = TW;
+
+ if (!lp.invret && call == 2) {
+
+ Hd = bfh;
+ Wd = bfw;
+ bufreti = new LabImage(bfw, bfh);
+ bufmask = new LabImage(bfw, bfh);
+ bufmaskorigreti = new LabImage(bfw, bfh);
+
+ if (!lp.enaretiMasktmap && lp.enaretiMask) {
+ buforig = new LabImage(bfw, bfh);
+ buforigmas = new LabImage(bfw, bfh);
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#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;
+ buflight[ir][jr] = 0.f;
+ bufchro[ir][jr] = 0.f;
+ }
+
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int y = ystart; y < yend; y++) {
+ for (int x = xstart; x < xend; x++) {
+ bufreti->L[y - ystart][x - xstart] = original->L[y][x];
+ bufreti->a[y - ystart][x - xstart] = original->a[y][x];
+ bufreti->b[y - ystart][x - xstart] = original->b[y][x];
+ bufmask->L[y - ystart][x - xstart] = original->L[y][x];
+ bufmask->a[y - ystart][x - xstart] = original->a[y][x];
+ bufmask->b[y - ystart][x - xstart] = original->b[y][x];
+
+ if (!lp.enaretiMasktmap && lp.enaretiMask) {
+ buforig->L[y - ystart][x - xstart] = original->L[y][x];
+ buforig->a[y - ystart][x - xstart] = original->a[y][x];
+ buforig->b[y - ystart][x - xstart] = original->b[y][x];
+ }
+ }
+ }
+ }
+
+ float raddE = params->locallab.spots.at(sp).softradiusret;
+
+ //calc dE and reduction to use in MSR to reduce artifacts
+ const float mindE = 4.f + MINSCOPE * lp.sensh * lp.thr;
+ const float maxdE = 5.f + MAXSCOPE * lp.sensh * (1 + 0.1f * lp.thr);
+ const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
+ const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
+ const float refa = chromaref * cos(hueref);
+ const float refb = chromaref * sin(hueref);
+
+ const std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd));
+ float** reducDE = *(reducDEBuffer.get());
+ float ade = 0.01f * raddE;
+ float bde = 100.f - raddE;
+ float sensibefore = ade * lp.sensh + bde;//we can change sensitivity 0.1 90 or 0.3 70 or 0.4 60
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int y = ystart; y < yend ; y++) {
+ for (int x = xstart; x < xend; x++) {
+ const float dE = std::sqrt(SQR(refa - bufreti->a[y - ystart][x - xstart] / 327.68f) + SQR(refb - bufreti->b[y - ystart][x - xstart] / 327.68f) + SQR(static_cast(lumaref) - bufreti->b[y - ystart][x - xstart] / 327.68f));
+ const float reducdE = calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sensibefore);
+ reducDE[y - ystart][x - xstart] = clipDE(reducdE);
+ }
+ }
+
+ const std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd));
+ float** orig = *(origBuffer.get());
+
+ const std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd));
+ float** orig1 = *(origBuffer1.get());
+
+ LabImage *tmpl = nullptr;
+
+ if (!lp.invret && call == 2) {
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#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);
+ }
+
+ // float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax;
+ bool fftw = lp.ftwreti;
+ //for Retinex Mask are incorporated in MSR
+ int sco = params->locallab.spots.at(sp).scopemask;
+ float lumask = params->locallab.spots.at(sp).lumask;
+
+ const float mindE2 = 2.f + MINSCOPE * sco * lp.thr;
+ const float maxdE2 = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
+ const float mindElim2 = 2.f + MINSCOPE * limscope * lp.thr;
+ const float maxdElim2 = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
+
+ ImProcFunctions::MSRLocal(call, sp, fftw, 1, reducDE, bufreti, bufmask, buforig, buforigmas, bufmaskorigreti, orig, orig1,
+ Wd, Hd, bfwr, bfhr, params->locallab, sk, locRETgainCcurve, locRETtransCcurve, 0, 4, 1.f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
+ locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask,
+ lmaskretilocalcurve, localmaskretiutili,
+ transformed, lp.enaretiMasktmap, lp.enaretiMask,
+ params->locallab.spots.at(sp).deltae, hueref, chromaref, lumaref,
+ maxdE2, mindE2, maxdElim2, mindElim2, lp.iterat, limscope, sco, lp.balance, lp.balanceh, lumask);
+
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#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.equret) { //equilibrate luminance before / after MSR
+ const std::unique_ptr datain(new float[Hd * Wd]);
+ const std::unique_ptr data(new float[Hd * Wd]);
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir += 1) {
+ for (int jr = 0; jr < Wd; jr += 1) {
+ datain[ir * Wd + jr] = orig1[ir][jr];
+ data[ir * Wd + jr] = orig[ir][jr];
+ }
+ }
+
+ normalize_mean_dt(data.get(), datain.get(), Hd * Wd, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f);
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir += 1) {
+ for (int jr = 0; jr < Wd; jr += 1) {
+ tmpl->L[ir][jr] = data[ir * Wd + jr];
+ }
+ }
+ }
+ if(lp.enaretiMask && lp.recothrr != 1.f) {
+ float hig = lp.higthrr;
+ float low = lp.lowthrr;
+ float recoth = lp.recothrr;
+ float decay = lp.decayr;
+ bool invmask = false;
+ maskrecov(tmpl, original, bufmaskorigreti, Hd, Wd, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
+ }
+
+ if (!lp.invret) {
+ float minL = tmpl->L[0][0] - bufreti->L[0][0];
+ float maxL = minL;
+#ifdef _OPENMP
+ #pragma omp parallel for reduction(min:minL) reduction(max:maxL) schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ buflight[ir][jr] = tmpl->L[ir][jr] - bufreti->L[ir][jr];
+ minL = rtengine::min(minL, buflight[ir][jr]);
+ maxL = rtengine::max(maxL, buflight[ir][jr]);
+ }
+ }
+
+ float coef = 0.01f * rtengine::max(std::fabs(minL), std::fabs(maxL));
+
+ if (coef > 0.f) {
+ coef = 1.f / coef;
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ buflight[ir][jr] *= coef;
+ }
+ }
+ }
+
+ transit_shapedetect_retinex(call, 4, bufreti, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
+
+ if (lp.recur) {
+ original->CopyFrom(transformed, multiThread);
+ float avge;
+ calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
+ }
+ }
+
+ if (params->locallab.spots.at(sp).chrrt > 0) {
+ if (!lp.invret && call == 2) {
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir += 1) {
+ for (int jr = 0; jr < Wd; jr += 1) {
+ orig[ir][jr] = std::sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr]));
+ orig1[ir][jr] = std::sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr]));
+ }
+ }
+ }
+
+ float maxChro = orig1[0][0];
+#ifdef _OPENMP
+ #pragma omp parallel for reduction(max:maxChro) schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ maxChro = rtengine::max(maxChro, orig1[ir][jr]);
+ }
+ }
+
+ //first step change saturation without Retinex ==> gain of time and memory
+ float satreal = lp.str * static_cast(params->locallab.spots.at(sp).chrrt) / 100.f;
+
+ if (params->locallab.spots.at(sp).chrrt <= 0.2) {
+ satreal /= 10.f;
+ }
+
+ DiagonalCurve reti_satur({
+ DCT_NURBS,
+ 0, 0,
+ 0.2, 0.2f + satreal / 250.f,
+ 0.6, rtengine::min(1.f, 0.6f + satreal / 250.f),
+ 1, 1
+ });
+
+ if (!lp.invret && call == 2) {
+
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir += 1) {
+ for (int jr = 0; jr < Wd; jr += 1) {
+ const 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;
+
+ if (params->locallab.spots.at(sp).chrrt <= 40.0) { //first step
+ orig[ir][jr] = static_cast(reti_satur.getVal(LIM01(orig[ir][jr] / maxChro))) * maxChro;
+ }
+
+ tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y;
+ tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x;
+ }
+ }
+
+ float minC = std::sqrt(SQR(tmpl->a[0][0]) + SQR(tmpl->b[0][0])) - orig1[0][0];
+ float maxC = minC;
+#ifdef _OPENMP
+ #pragma omp parallel for reduction(min:minC) reduction(max:maxC) schedule(dynamic,16) if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ bufchro[ir][jr] = std::sqrt(SQR(tmpl->a[ir][jr]) + SQR(tmpl->b[ir][jr])) - orig1[ir][jr];
+ minC = rtengine::min(minC, bufchro[ir][jr]);
+ maxC = rtengine::max(maxC, bufchro[ir][jr]);
+ }
+ }
+
+ float coefC = 0.01f * rtengine::max(std::fabs(minC), std::fabs(maxC));
+
+ if (coefC > 0.f) {
+ coefC = 1.f / coefC;
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+ for (int ir = 0; ir < Hd; ir++) {
+ for (int jr = 0; jr < Wd; jr++) {
+ bufchro[ir][jr] *= coefC;
+ }
+ }
+ }
+ }
+
+ if (!lp.invret) {
+ transit_shapedetect_retinex(call, 5, tmpl, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
+
+ if (lp.recur) {
+ original->CopyFrom(transformed, multiThread);
+ float avge;
+ calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
+ }
+ }
+ }
+
+ delete tmpl;
+ delete bufmask;
+ delete bufmaskorigreti;
+
+ if (!lp.enaretiMasktmap && lp.enaretiMask) {
+ if (buforig) {
+ delete buforig;
+ }
+
+ if (buforigmas) {
+ delete buforigmas;
+ }
+ }
+ delete bufreti;
+ }
+ }
+
//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.mulloc[5] != 1.f || lp.clarityml != 0.f || lp.contresid != 0.f || lp.enacbMask || lp.showmaskcbmet == 2 || lp.showmaskcbmet == 3 || lp.showmaskcbmet == 4 || lp.prevdE) && lp.cbdlena) {
@@ -12706,7 +13736,7 @@ void ImProcFunctions::Lab_Local(
}
- transit_shapedetect2(call, 2, bufexporig.get(), bufexpfin.get(), originalmaskvib.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 2, bufexporig.get(), bufexpfin.get(), originalmaskvib.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
}
@@ -12722,234 +13752,6 @@ void ImProcFunctions::Lab_Local(
}
-//Tone mapping
-
- if ((lp.strengt != 0.f || lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4 || lp.prevdE) && lp.tonemapena && !params->epd.enabled) {
- if (call <= 3) { //simpleprocess dcrop improcc
- const int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
- const int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
- const int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
- const int xend = rtengine::min(static_cast(lp.xc + lp.lx) - cx, original->W);
- const int bfh = yend - ystart;
- const int bfw = xend - xstart;
-
- if (bfw >= mDEN && bfh >= mDEN) {
- // printf("OK TM\n");
- array2D buflight(bfw, bfh);
- JaggedArray bufchro(bfw, bfh);
- std::unique_ptr bufgb(new LabImage(bfw, bfh));
- const std::unique_ptr tmp1(new LabImage(bfw, bfh));
- const std::unique_ptr bufgbm(new LabImage(bfw, bfh));
- const std::unique_ptr tmp1m(new LabImage(bfw, bfh));
- std::unique_ptr bufmaskorigtm;
- std::unique_ptr bufmaskblurtm;
- std::unique_ptr originalmasktm;
-
- // if (lp.showmasktmmet == 0 || lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4) {
- if (lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4) {
- bufmaskorigtm.reset(new LabImage(bfw, bfh));
- bufmaskblurtm.reset(new LabImage(bfw, bfh));
- originalmasktm.reset(new LabImage(bfw, bfh));
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = ystart; y < yend; y++) {
- for (int x = xstart; x < xend; x++) {
- bufgb->L[y - ystart][x - xstart] = original->L[y][x];
- bufgb->a[y - ystart][x - xstart] = original->a[y][x];
- bufgb->b[y - ystart][x - xstart] = original->b[y][x];
- bufgbm->L[y - ystart][x - xstart] = original->L[y][x];
- bufgbm->a[y - ystart][x - xstart] = original->a[y][x];
- bufgbm->b[y - ystart][x - xstart] = original->b[y][x];
- }
- }
-
- int inv = 0;
- bool showmaske = false;
- bool enaMask = false;
- bool deltaE = false;
- bool modmask = false;
- bool zero = false;
- bool modif = false;
-
- if (lp.showmasktmmet == 3) {
- showmaske = true;
- }
-
- if (lp.enatmMask) {
- enaMask = true;
- }
-
- if (lp.showmasktmmet == 4) {
- deltaE = true;
- }
-
- if (lp.showmasktmmet == 2) {
- modmask = true;
- }
-
- if (lp.showmasktmmet == 1) {
- modif = true;
- }
-
- if (lp.showmasktmmet == 0) {
- zero = true;
- }
-
- float chrom = lp.chromatm;;
- float rad = lp.radmatm;
- float gamma = lp.gammatm;
- float slope = lp.slomatm;
- float blendm = lp.blendmatm;
- float lap = params->locallab.spots.at(sp).lapmasktm;
- bool pde = params->locallab.spots.at(sp).laplac;
- int lumask = params->locallab.spots.at(sp).lumask;
-
- if (!params->locallab.spots.at(sp).enatmMaskaft) {
- LocwavCurve dummy;
- int sco = params->locallab.spots.at(sp).scopemask;
- int shortcu = 0; //lp.mergemet;// params->locallab.spots.at(sp).shortc;
-
- const float mindE = 2.f + MINSCOPE * sco * lp.thr;
- const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
- const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
- const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
- int shado = 0;
- float amountcd = 0.f;
- float anchorcd = 50.f;
- LocHHmaskCurve lochhhmasCurve;
- const int highl = 0;
-
- maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufgbm.get(), bufmaskorigtm.get(), originalmasktm.get(), original, reserved, inv, lp,
- 0.f, false,
- locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, lochhhmasCurve, false, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, false, 1, 1, 5, 5,
- shortcu, params->locallab.spots.at(sp).deltae, hueref, chromaref, lumaref,
- maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
- );
-
- if (lp.showmasktmmet == 3) {
- showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, bufgbm.get(), transformed, bufmaskorigtm.get(), 0);
-
- return;
- }
- }
-
- if (lp.showmasktmmet == 0 || lp.showmasktmmet == 1 || lp.showmasktmmet == 2 || lp.showmasktmmet == 4 || lp.showmasktmmet == 3 || lp.enatmMask) {
- constexpr int itera = 0;
- ImProcFunctions::EPDToneMaplocal(sp, bufgb.get(), tmp1.get(), itera, sk);//iterate to 0 calculate with edgstopping, improve result, call=1 dcrop we can put iterate to 5
-
- tmp1m->CopyFrom(tmp1.get(), multiThread); //save current result
- bool enatmMasktmap = params->locallab.spots.at(sp).enatmMaskaft;
-
- if (enatmMasktmap) {
- //calculate new values for original, originalmasktm, bufmaskorigtm...in function of tmp1
- LocwavCurve dummy;
- int sco = params->locallab.spots.at(sp).scopemask;
- int shortcu = 0;//lp.mergemet; //params->locallab.spots.at(sp).shortc;
-
- const float mindE = 2.f + MINSCOPE * sco * lp.thr;
- const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
- const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
- const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
- int shado = 0;
- float amountcd = 0.f;
- float anchorcd = 50.f;
- LocHHmaskCurve lochhhmasCurve;
- const int highl = 0;
-
- maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, tmp1.get(), bufmaskorigtm.get(), originalmasktm.get(), original, reserved, inv, lp,
- 0.f, false,
- locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, lochhhmasCurve, false, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, false, 1, 1, 5, 5,
- shortcu, params->locallab.spots.at(sp).deltae, hueref, chromaref, lumaref,
- maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
- );
-
- if (lp.showmasktmmet == 3) {//display mask
- showmask(params->locallab.spots.at(sp).lumask, lp, xstart, ystart, cx, cy, bfw, bfh, tmp1.get(), transformed, bufmaskorigtm.get(), 0);
- return;
- }
-
- }
-
- tmp1->CopyFrom(tmp1m.get(), multiThread); //restore current result
-
-
- float minL = tmp1->L[0][0] - bufgb->L[0][0];
- float maxL = minL;
- float minC = std::sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - std::sqrt(SQR(bufgb->a[0][0]) + SQR(bufgb->b[0][0]));
- float maxC = minC;
-
-#ifdef _OPENMP
- #pragma omp parallel for reduction(max:maxL) reduction(min:minL) reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < bfh; ir++) {
- for (int jr = 0; jr < bfw; jr++) {
- buflight[ir][jr] = tmp1->L[ir][jr] - bufgb->L[ir][jr];
- minL = rtengine::min(minL, buflight[ir][jr]);
- maxL = rtengine::max(maxL, buflight[ir][jr]);
- bufchro[ir][jr] = std::sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - std::sqrt(SQR(bufgb->a[ir][jr]) + SQR(bufgb->b[ir][jr]));
- minC = rtengine::min(minC, bufchro[ir][jr]);
- maxC = rtengine::max(maxC, bufchro[ir][jr]);
- }
- }
-
- float coef = 0.01f * rtengine::max(std::fabs(minL), std::fabs(maxL));
- float coefC = 0.01f * rtengine::max(std::fabs(minC), std::fabs(maxC));
-
- if (coef == 0.f) {
- coef = 1.f;
- } else {
- coef = 1.f / coef;
- }
-
- if (coefC == 0.f) {
- coefC = 1.f;
- } else {
- coefC = 1.f / coefC;
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int y = 0; y < bfh; y++) {
- for (int x = 0; x < bfw; x++) {
- buflight[y][x] *= coef;
- bufchro[y][x] *= coefC;
- }
- }
-
- if(lp.enatmMask && lp.recothrt != 1.f) {
- float hig = lp.higthrt;
- float low = lp.lowthrt;
- float recoth = lp.recothrt;
- float decay = lp.decayt;
- bool invmask = false;
- maskrecov(tmp1.get(), original, bufmaskorigtm.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
- }
-
- // transit_shapedetect_retinex(call, 4, bufgb.get(),bufmaskorigtm.get(), originalmasktm.get(), buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
- transit_shapedetect2(call, 8, bufgb.get(), tmp1.get(), originalmasktm.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
-
- // transit_shapedetect(8, tmp1.get(), originalmasktm.get(), bufchro, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
- bufgb.reset();
-
- if (lp.recur) {
- original->CopyFrom(transformed, multiThread);
- float avge;
- calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
- }
- }
- }
- }
- }
-
-//end TM
-
-
//shadow highlight
bool tonequ = false;
@@ -13138,7 +13940,7 @@ void ImProcFunctions::Lab_Local(
maskrecov(bufexpfin.get(), original, bufmaskorigSH.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
}
- transit_shapedetect2(call, 9, bufexporig.get(), bufexpfin.get(), originalmaskSH.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 9, bufexporig.get(), bufexpfin.get(), originalmaskSH.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
if (lp.recur) {
original->CopyFrom(transformed, multiThread);
@@ -13301,7 +14103,7 @@ void ImProcFunctions::Lab_Local(
}
}
- transit_shapedetect2(call, 3, bufexporig.get(), bufexpfin.get(), nullptr, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 3, bufexporig.get(), bufexpfin.get(), nullptr, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
if (lp.recur) {
original->CopyFrom(transformed, multiThread);
@@ -13764,7 +14566,7 @@ void ImProcFunctions::Lab_Local(
maskrecov(tmp1.get(), original, bufmaskoriglc.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
}
- transit_shapedetect2(call, 10, bufgb.get(), tmp1.get(), originalmasklc.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 10, bufgb.get(), tmp1.get(), originalmasklc.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
tmp1.reset();
}
@@ -13841,708 +14643,6 @@ void ImProcFunctions::Lab_Local(
}
}
- if ((lp.dehaze != 0 || lp.prevdE) && lp.retiena ) {
- int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
- int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
- int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
- int xend = rtengine::min(static_cast(lp.xc + lp.lx) - cx, original->W);
- int bfh = yend - ystart;
- int bfw = xend - xstart;
-
- if (bfh >= mSP && bfw >= mSP) {
- const std::unique_ptr bufexporig(new LabImage(bfw, bfh)); //buffer for data in zone limit
- const std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); //buffer for data in zone limit
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = ystart; y < yend; y++) {
- for (int x = xstart; x < xend; x++) {
- bufexporig->L[y - ystart][x - xstart] = original->L[y][x];
- bufexporig->a[y - ystart][x - xstart] = original->a[y][x];
- bufexporig->b[y - ystart][x - xstart] = original->b[y][x];
- }
- }
-
- bufexpfin->CopyFrom(bufexporig.get(), multiThread);
- //calc dehaze
- const std::unique_ptr tmpImage(new Imagefloat(bfw, bfh));
-
- DehazeParams dehazeParams;
- dehazeParams.enabled = true;
- dehazeParams.strength = lp.dehaze;
- dehazeParams.showDepthMap = false;
- dehazeParams.saturation = lp.dehazeSaturation;
- dehazeParams.depth = lp.depth;
- lab2rgb(*bufexpfin, *tmpImage.get(), params->icm.workingProfile);
- dehazeloc(tmpImage.get(), dehazeParams);
- rgb2lab(*tmpImage.get(), *bufexpfin, params->icm.workingProfile);
-
- transit_shapedetect2(call, 30, bufexporig.get(), bufexpfin.get(), nullptr, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
-
- if (lp.recur) {
- original->CopyFrom(transformed, multiThread);
- float avge;
- calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
- }
- }
- }
-
- lp.invret = false;//always disabled inverse RETI too complex todo !!
-
- if (lp.str >= 0.2f && lp.retiena && call != 2) {
- LabImage *bufreti = nullptr;
- LabImage *bufmask = nullptr;
- LabImage *buforig = nullptr;
- LabImage *buforigmas = nullptr;
- LabImage *bufmaskorigreti = nullptr;
-
- if (TW >= mSP && TH >= mSP) {
-
- array2D buflight(TW, TH);
- JaggedArray bufchro(TW, TH);
-
- int Hd, Wd;
- Hd = TH;
- Wd = TW;
-
- bufreti = new LabImage(TW, TH);
- bufmask = new LabImage(TW, TH);
- bufmaskorigreti = new LabImage(TW, TH);
-
- if (!lp.enaretiMasktmap && lp.enaretiMask) {
- buforig = new LabImage(TW, TH);
- buforigmas = new LabImage(TW, TH);
- // bufmaskorigreti = new LabImage(GW, GH);
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < TH; ir++) //fill with 0
- for (int jr = 0; jr < TW; jr++) {
- bufreti->L[ir][jr] = 0.f;
- bufreti->a[ir][jr] = 0.f;
- bufreti->b[ir][jr] = 0.f;
- buflight[ir][jr] = 0.f;
- bufchro[ir][jr] = 0.f;
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = 0; y < transformed->H ; y++) //{
- for (int x = 0; x < transformed->W; x++) {
- bufreti->L[y][x] = original->L[y][x];
- bufreti->a[y][x] = original->a[y][x];
- bufreti->b[y][x] = original->b[y][x];
- bufmask->L[y][x] = original->L[y][x];
- bufmask->a[y][x] = original->a[y][x];
- bufmask->b[y][x] = original->b[y][x];
-
-
-
- if (!lp.enaretiMasktmap && lp.enaretiMask) {
- buforig->L[y][x] = original->L[y][x];
- buforig->a[y][x] = original->a[y][x];
- buforig->b[y][x] = original->b[y][x];
-
- // bufmaskorigreti->L[y][x] = original->L[y][x];
- // bufmaskorigreti->a[y][x] = original->a[y][x];
- // bufmaskorigreti->b[y][x] = original->b[y][x];
-
-
- }
-
- }
- float raddE = params->locallab.spots.at(sp).softradiusret;
-
- //calc dE and reduction to use in MSR to reduce artifacts
- const float mindE = 4.f + MINSCOPE * lp.sensh * lp.thr;
- const float maxdE = 5.f + MAXSCOPE * lp.sensh * (1 + 0.1f * lp.thr);
- const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
- const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
- const float refa = chromaref * cos(hueref);
- const float refb = chromaref * sin(hueref);
-
- const std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd));
- float** reducDE = *(reducDEBuffer.get());
-
- float ade = 0.01f * raddE;
- float bde = 100.f - raddE;
- float sensibefore = ade * lp.sensh + bde;//we can change sensitivity 0.1 90 or 0.3 70 or 0.4 60
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = 0; y < transformed->H ; y++)
- for (int x = 0; x < transformed->W; x++) {
- float dE = std::sqrt(SQR(refa - bufreti->a[y][x] / 327.68f) + SQR(refb - bufreti->b[y][x] / 327.68f) + SQR(static_cast(lumaref) - bufreti->b[y][x] / 327.68f));
- const float reducdE = calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sensibefore);
- reducDE[y][x] = clipDE(reducdE);
- }
-
- const std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd));
- float** orig = *(origBuffer.get());
-
- const std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd));
- float** orig1 = *(origBuffer1.get());
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#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];
- }
-
- LabImage *tmpl = new LabImage(Wd, Hd);
-
- bool fftw = lp.ftwreti;
- //for Retinex Mask are incorporated in MSR
- int sco = params->locallab.spots.at(sp).scopemask;
- float lumask = params->locallab.spots.at(sp).lumask;
-
- const float mindE2 = 2.f + MINSCOPE * sco * lp.thr;
- const float maxdE2 = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
- const float mindElim2 = 2.f + MINSCOPE * limscope * lp.thr;
- const float maxdElim2 = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
- ImProcFunctions::MSRLocal(call, sp, fftw, 1, reducDE, bufreti, bufmask, buforig, buforigmas, bufmaskorigreti, orig, orig1,
- Wd, Hd, Wd, Hd, params->locallab, sk, locRETgainCcurve, locRETtransCcurve, 0, 4, 1.f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
- locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask,
- lmaskretilocalcurve, localmaskretiutili,
- transformed, lp.enaretiMasktmap, lp.enaretiMask,
- params->locallab.spots.at(sp).deltae, hueref, chromaref, lumaref,
- maxdE2, mindE2, maxdElim2, mindElim2, lp.iterat, limscope, sco, lp.balance, lp.balanceh, lumask);
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#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.equret) { //equilibrate luminance before / after MSR
- float *datain = new float[Hd * Wd];
- float *data = new float[Hd * Wd];
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir += 1)
- for (int jr = 0; jr < Wd; jr += 1) {
- datain[ir * Wd + jr] = orig1[ir][jr];
- data[ir * Wd + jr] = orig[ir][jr];
- }
-
- normalize_mean_dt(data, datain, Hd * Wd, 1.f, 1.f);
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir += 1)
- for (int jr = 0; jr < Wd; jr += 1) {
- tmpl->L[ir][jr] = data[ir * Wd + jr];
- }
-
- delete [] datain;
- delete [] data;
- }
-
- if(lp.enaretiMask && lp.recothrr != 1.f) {
- float hig = lp.higthrr;
- float low = lp.lowthrr;
- float recoth = lp.recothrr;
- float decay = lp.decayr;
- bool invmask = false;
- maskrecov(tmpl, original, bufmaskorigreti, Hd, Wd, 0, 0, hig, low, recoth, decay, invmask, sk, multiThread);
- }
-
- float minL = tmpl->L[0][0] - bufreti->L[0][0];
- float maxL = minL;
-#ifdef _OPENMP
- #pragma omp parallel for reduction(min:minL) reduction(max:maxL) schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- buflight[ir][jr] = tmpl->L[ir][jr] - bufreti->L[ir][jr];
- minL = rtengine::min(minL, buflight[ir][jr]);
- maxL = rtengine::max(maxL, buflight[ir][jr]);
- }
- }
-
- const float coef = 0.01f * rtengine::max(std::fabs(minL), std::fabs(maxL));
-
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- buflight[ir][jr] /= coef;
- }
- }
-
- transit_shapedetect_retinex(call, 4, bufreti, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
-
- if (lp.recur) {
- original->CopyFrom(transformed, multiThread);
- float avge;
- calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
- }
-
- if (params->locallab.spots.at(sp).chrrt > 0) {
-
- if (call == 1) {
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir += 1)
- for (int jr = 0; jr < Wd; jr += 1) {
-
- orig[ir][jr] = std::sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr]));
- orig1[ir][jr] = std::sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr]));
- }
-
- }
-
- float maxChro = orig1[0][0];
-#ifdef _OPENMP
- #pragma omp parallel for reduction(max:maxChro) schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- maxChro = rtengine::max(maxChro, orig1[ir][jr]);
- }
- }
-
- float divchro = maxChro;
-
- //first step change saturation without Retinex ==> gain of time and memory
- float satreal = lp.str * static_cast(params->locallab.spots.at(sp).chrrt) / 100.f;
-
- if (params->locallab.spots.at(sp).chrrt <= 0.2) {
- satreal /= 10.f;
- }
-
- DiagonalCurve reti_satur({
- DCT_NURBS,
- 0, 0,
- 0.2, 0.2f + satreal / 250.f,
- 0.6, rtengine::min(1.f, 0.6f + satreal / 250.f),
- 1, 1
- });
-
- if (call == 1) {
-
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir += 1)
- for (int jr = 0; jr < Wd; jr += 1) {
- const 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;
-
- if (params->locallab.spots.at(sp).chrrt <= 100.0) { //first step
- float buf = LIM01(orig[ir][jr] / divchro);
- buf = reti_satur.getVal(buf);
- buf *= divchro;
- orig[ir][jr] = buf;
- }
-
- tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y;
- tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x;
- }
-
- float minC = std::sqrt(SQR(tmpl->a[0][0]) + SQR(tmpl->b[0][0])) - orig1[0][0];
- float maxC = minC;
-#ifdef _OPENMP
- #pragma omp parallel for reduction(min:minC) reduction(max:maxC) schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- bufchro[ir][jr] = std::sqrt(SQR(tmpl->a[ir][jr]) + SQR(tmpl->b[ir][jr])) - orig1[ir][jr];
- minC = rtengine::min(minC, bufchro[ir][jr]);
- maxC = rtengine::max(maxC, bufchro[ir][jr]);
- }
- }
-
- float coefC = 0.01f * rtengine::max(std::fabs(minC), std::fabs(maxC));
-
- if (coefC > 0.f) {
- coefC = 1.f / coefC;
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- bufchro[ir][jr] *= coefC;
- }
- }
- }
- }
-
- transit_shapedetect_retinex(call, 5, tmpl, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
-
- if (lp.recur) {
- original->CopyFrom(transformed, multiThread);
- float avge;
- calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
- }
- }
-
- delete tmpl;
- delete bufmask;
- delete bufmaskorigreti;
-
- if (!lp.enaretiMasktmap && lp.enaretiMask) {
- if (buforig) {
- delete buforig;
- }
-
- if (buforigmas) {
- delete buforigmas;
- }
- }
- delete bufreti;
- }
- }
-
-
-
- if (lp.str >= 0.2f && lp.retiena && call == 2) {
- int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
- int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
- int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
- int xend = rtengine::min(static_cast(lp.xc + lp.lx) - cx, original->W);
- int bfh = yend - ystart;
- int bfw = xend - xstart;
-
- LabImage *bufreti = nullptr;
- LabImage *bufmask = nullptr;
- LabImage *buforig = nullptr;
- LabImage *buforigmas = nullptr;
- LabImage *bufmaskorigreti = nullptr;
- int bfhr = bfh;
- int bfwr = bfw;
-
- if (bfw >= mSP && bfh > mSP) {
- if (lp.ftwreti) {
- optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
- }
-
- array2D buflight(bfw, bfh);
- JaggedArray bufchro(bfw, bfh);
-
- int Hd, Wd;
- Hd = TH;
- Wd = TW;
-
- if (!lp.invret && call == 2) {
-
- Hd = bfh;
- Wd = bfw;
- bufreti = new LabImage(bfw, bfh);
- bufmask = new LabImage(bfw, bfh);
- bufmaskorigreti = new LabImage(bfw, bfh);
-
- if (!lp.enaretiMasktmap && lp.enaretiMask) {
- buforig = new LabImage(bfw, bfh);
- buforigmas = new LabImage(bfw, bfh);
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#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;
- buflight[ir][jr] = 0.f;
- bufchro[ir][jr] = 0.f;
- }
-
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = ystart; y < yend; y++) {
- for (int x = xstart; x < xend; x++) {
- bufreti->L[y - ystart][x - xstart] = original->L[y][x];
- bufreti->a[y - ystart][x - xstart] = original->a[y][x];
- bufreti->b[y - ystart][x - xstart] = original->b[y][x];
- bufmask->L[y - ystart][x - xstart] = original->L[y][x];
- bufmask->a[y - ystart][x - xstart] = original->a[y][x];
- bufmask->b[y - ystart][x - xstart] = original->b[y][x];
-
- if (!lp.enaretiMasktmap && lp.enaretiMask) {
- buforig->L[y - ystart][x - xstart] = original->L[y][x];
- buforig->a[y - ystart][x - xstart] = original->a[y][x];
- buforig->b[y - ystart][x - xstart] = original->b[y][x];
- }
- }
- }
- }
-
- float raddE = params->locallab.spots.at(sp).softradiusret;
-
- //calc dE and reduction to use in MSR to reduce artifacts
- const float mindE = 4.f + MINSCOPE * lp.sensh * lp.thr;
- const float maxdE = 5.f + MAXSCOPE * lp.sensh * (1 + 0.1f * lp.thr);
- const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
- const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
- const float refa = chromaref * cos(hueref);
- const float refb = chromaref * sin(hueref);
-
- const std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd));
- float** reducDE = *(reducDEBuffer.get());
- float ade = 0.01f * raddE;
- float bde = 100.f - raddE;
- float sensibefore = ade * lp.sensh + bde;//we can change sensitivity 0.1 90 or 0.3 70 or 0.4 60
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = ystart; y < yend ; y++) {
- for (int x = xstart; x < xend; x++) {
- const float dE = std::sqrt(SQR(refa - bufreti->a[y - ystart][x - xstart] / 327.68f) + SQR(refb - bufreti->b[y - ystart][x - xstart] / 327.68f) + SQR(static_cast(lumaref) - bufreti->b[y - ystart][x - xstart] / 327.68f));
- const float reducdE = calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sensibefore);
- reducDE[y - ystart][x - xstart] = clipDE(reducdE);
- }
- }
-
- const std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd));
- float** orig = *(origBuffer.get());
-
- const std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd));
- float** orig1 = *(origBuffer1.get());
-
- LabImage *tmpl = nullptr;
-
- if (!lp.invret && call == 2) {
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#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);
- }
-
- // float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax;
- bool fftw = lp.ftwreti;
- //for Retinex Mask are incorporated in MSR
- int sco = params->locallab.spots.at(sp).scopemask;
- float lumask = params->locallab.spots.at(sp).lumask;
-
- const float mindE2 = 2.f + MINSCOPE * sco * lp.thr;
- const float maxdE2 = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
- const float mindElim2 = 2.f + MINSCOPE * limscope * lp.thr;
- const float maxdElim2 = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
-
- ImProcFunctions::MSRLocal(call, sp, fftw, 1, reducDE, bufreti, bufmask, buforig, buforigmas, bufmaskorigreti, orig, orig1,
- Wd, Hd, bfwr, bfhr, params->locallab, sk, locRETgainCcurve, locRETtransCcurve, 0, 4, 1.f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
- locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask,
- lmaskretilocalcurve, localmaskretiutili,
- transformed, lp.enaretiMasktmap, lp.enaretiMask,
- params->locallab.spots.at(sp).deltae, hueref, chromaref, lumaref,
- maxdE2, mindE2, maxdElim2, mindElim2, lp.iterat, limscope, sco, lp.balance, lp.balanceh, lumask);
-
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#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.equret) { //equilibrate luminance before / after MSR
- const std::unique_ptr datain(new float[Hd * Wd]);
- const std::unique_ptr data(new float[Hd * Wd]);
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir += 1) {
- for (int jr = 0; jr < Wd; jr += 1) {
- datain[ir * Wd + jr] = orig1[ir][jr];
- data[ir * Wd + jr] = orig[ir][jr];
- }
- }
-
- normalize_mean_dt(data.get(), datain.get(), Hd * Wd, 1.f, 1.f);
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir += 1) {
- for (int jr = 0; jr < Wd; jr += 1) {
- tmpl->L[ir][jr] = data[ir * Wd + jr];
- }
- }
- }
- if(lp.enaretiMask && lp.recothrr != 1.f) {
- float hig = lp.higthrr;
- float low = lp.lowthrr;
- float recoth = lp.recothrr;
- float decay = lp.decayr;
- bool invmask = false;
- maskrecov(tmpl, original, bufmaskorigreti, Hd, Wd, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
- }
-
- if (!lp.invret) {
- float minL = tmpl->L[0][0] - bufreti->L[0][0];
- float maxL = minL;
-#ifdef _OPENMP
- #pragma omp parallel for reduction(min:minL) reduction(max:maxL) schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- buflight[ir][jr] = tmpl->L[ir][jr] - bufreti->L[ir][jr];
- minL = rtengine::min(minL, buflight[ir][jr]);
- maxL = rtengine::max(maxL, buflight[ir][jr]);
- }
- }
-
- float coef = 0.01f * rtengine::max(std::fabs(minL), std::fabs(maxL));
-
- if (coef > 0.f) {
- coef = 1.f / coef;
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- buflight[ir][jr] *= coef;
- }
- }
- }
-
- transit_shapedetect_retinex(call, 4, bufreti, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
-
- if (lp.recur) {
- original->CopyFrom(transformed, multiThread);
- float avge;
- calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
- }
- }
-
- if (params->locallab.spots.at(sp).chrrt > 0) {
- if (!lp.invret && call == 2) {
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir += 1) {
- for (int jr = 0; jr < Wd; jr += 1) {
- orig[ir][jr] = std::sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr]));
- orig1[ir][jr] = std::sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr]));
- }
- }
- }
-
- float maxChro = orig1[0][0];
-#ifdef _OPENMP
- #pragma omp parallel for reduction(max:maxChro) schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- maxChro = rtengine::max(maxChro, orig1[ir][jr]);
- }
- }
-
- //first step change saturation without Retinex ==> gain of time and memory
- float satreal = lp.str * static_cast(params->locallab.spots.at(sp).chrrt) / 100.f;
-
- if (params->locallab.spots.at(sp).chrrt <= 0.2) {
- satreal /= 10.f;
- }
-
- DiagonalCurve reti_satur({
- DCT_NURBS,
- 0, 0,
- 0.2, 0.2f + satreal / 250.f,
- 0.6, rtengine::min(1.f, 0.6f + satreal / 250.f),
- 1, 1
- });
-
- if (!lp.invret && call == 2) {
-
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir += 1) {
- for (int jr = 0; jr < Wd; jr += 1) {
- const 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;
-
- if (params->locallab.spots.at(sp).chrrt <= 40.0) { //first step
- orig[ir][jr] = static_cast(reti_satur.getVal(LIM01(orig[ir][jr] / maxChro))) * maxChro;
- }
-
- tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y;
- tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x;
- }
- }
-
- float minC = std::sqrt(SQR(tmpl->a[0][0]) + SQR(tmpl->b[0][0])) - orig1[0][0];
- float maxC = minC;
-#ifdef _OPENMP
- #pragma omp parallel for reduction(min:minC) reduction(max:maxC) schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- bufchro[ir][jr] = std::sqrt(SQR(tmpl->a[ir][jr]) + SQR(tmpl->b[ir][jr])) - orig1[ir][jr];
- minC = rtengine::min(minC, bufchro[ir][jr]);
- maxC = rtengine::max(maxC, bufchro[ir][jr]);
- }
- }
-
- float coefC = 0.01f * rtengine::max(std::fabs(minC), std::fabs(maxC));
-
- if (coefC > 0.f) {
- coefC = 1.f / coefC;
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int ir = 0; ir < Hd; ir++) {
- for (int jr = 0; jr < Wd; jr++) {
- bufchro[ir][jr] *= coefC;
- }
- }
- }
- }
-
- if (!lp.invret) {
- transit_shapedetect_retinex(call, 5, tmpl, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
-
- if (lp.recur) {
- original->CopyFrom(transformed, multiThread);
- float avge;
- calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili);
- }
- }
- }
-
- delete tmpl;
- delete bufmask;
- delete bufmaskorigreti;
-
- if (!lp.enaretiMasktmap && lp.enaretiMask) {
- if (buforig) {
- delete buforig;
- }
-
- if (buforigmas) {
- delete buforigmas;
- }
- }
- delete bufreti;
- }
- }
-
bool enablefat = false;
if (params->locallab.spots.at(sp).fatamount > 1.0) {
@@ -14759,36 +14859,18 @@ void ImProcFunctions::Lab_Local(
datain[y * bfwr + x] = bufexpfin->L[y][x];
}
}
-
FattalToneMappingParams fatParams;
fatParams.enabled = true;
fatParams.threshold = params->locallab.spots.at(sp).fatdetail;
fatParams.amount = params->locallab.spots.at(sp).fatamount;
fatParams.anchor = 50.f; //params->locallab.spots.at(sp).fatanchor;
- const float sigm = params->locallab.spots.at(sp).fatlevel;
- const float mean = params->locallab.spots.at(sp).fatanchor;
+ //const float sigm = 1.f; //params->locallab.spots.at(sp).fatlevel;
+ //const float mean = 1.f;// params->locallab.spots.at(sp).fatanchor;
const std::unique_ptr tmpImagefat(new Imagefloat(bfwr, bfhr));
lab2rgb(*bufexpfin, *(tmpImagefat.get()), params->icm.workingProfile);
ToneMapFattal02(tmpImagefat.get(), fatParams, 3, 0, nullptr, 0, 0, 1);//last parameter = 1 ==>ART algorithm
rgb2lab(*(tmpImagefat.get()), *bufexpfin, params->icm.workingProfile);
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = 0; y < bfhr; y++) {
- for (int x = 0; x < bfwr; x++) {
- dataout[y * bfwr + x] = bufexpfin->L[y][x];
- }
- }
- normalize_mean_dt(dataout.get(), datain.get(), bfwr * bfhr, mean, sigm);
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = 0; y < bfhr; y++) {
- for (int x = 0; x < bfwr; x++) {
- bufexpfin->L[y][x] = dataout[y * bfwr + x];
- }
- }
}
if (lp.laplacexp > 0.1f) {
@@ -14898,7 +14980,7 @@ void ImProcFunctions::Lab_Local(
}
float meansob = 0.f;
- transit_shapedetect2(call, 1, bufexporig.get(), bufexpfin.get(), originalmaskexp.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 1, bufexporig.get(), bufexpfin.get(), originalmaskexp.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
}
if (lp.recur) {
@@ -15961,7 +16043,7 @@ void ImProcFunctions::Lab_Local(
softproc(bufcolreserv.get(), bufcolfin.get(), lp.softradiuscol, bfh, bfw, 0.001, 0.00001, 0.5f, sk, multiThread, 1);
}
float meansob = 0.f;
- transit_shapedetect2(call, 0, bufcolreserv.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 0, bufcolreserv.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
}
if (!nottransit) {
@@ -16044,7 +16126,7 @@ void ImProcFunctions::Lab_Local(
maskrecov(bufcolfin.get(), original, bufmaskblurcol.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
}
float meansob = 0.f;
- transit_shapedetect2(call, 0, bufcolorig.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 0, bufcolorig.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
}
}
@@ -16313,7 +16395,7 @@ void ImProcFunctions::Lab_Local(
float meansob = 0.f;
- transit_shapedetect2(call, 20, bufcolorigsav.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, nullptr, lp, origsav, transformed, cx, cy, sk);
+ transit_shapedetect2(sp, 0.f, 0.f, call, 20, bufcolorigsav.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, nullptr, lp, origsav, transformed, cx, cy, sk);
delete origsav;
origsav = NULL;
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index e65a4e12e..863fbd6e2 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -1065,6 +1065,7 @@ enum ProcEventCode {
EvLocallabSpotavoidrad = 1039,
EvLocallabSpotavoidmun = 1040,
Evlocallabcontthres = 1041,
+ Evlocallabnorm = 1042,
NUMOFEVENTS
};
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 3d6dae89d..9b371a1c8 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -3060,6 +3060,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
1.0,
1.0
},
+ norm(true),
inversex(false),
enaExpMask(false),
enaExpMaskaft(false),
@@ -3607,8 +3608,8 @@ LocallabParams::LocallabSpot::LocallabSpot() :
0.35
},
inversret(false),
- equilret(true),
- loglin(false),
+ equilret(false),
+ loglin(true),
dehazeSaturation(50.0),
softradiusret(40.0),
CCmaskreticurve{
@@ -4297,6 +4298,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& strexp == other.strexp
&& angexp == other.angexp
&& excurve == other.excurve
+ && norm == other.norm
&& inversex == other.inversex
&& enaExpMask == other.enaExpMask
&& enaExpMaskaft == other.enaExpMaskaft
@@ -5942,6 +5944,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->strexp, "Locallab", "Strexp_" + index_str, spot.strexp, keyFile);
saveToKeyfile(!pedited || spot_edited->angexp, "Locallab", "Angexp_" + index_str, spot.angexp, keyFile);
saveToKeyfile(!pedited || spot_edited->excurve, "Locallab", "ExCurve_" + index_str, spot.excurve, keyFile);
+ saveToKeyfile(!pedited || spot_edited->norm, "Locallab", "Norm_" + index_str, spot.norm, keyFile);
saveToKeyfile(!pedited || spot_edited->inversex, "Locallab", "Inversex_" + index_str, spot.inversex, keyFile);
saveToKeyfile(!pedited || spot_edited->enaExpMask, "Locallab", "EnaExpMask_" + index_str, spot.enaExpMask, keyFile);
saveToKeyfile(!pedited || spot_edited->enaExpMaskaft, "Locallab", "EnaExpMaskaft_" + index_str, spot.enaExpMaskaft, keyFile);
@@ -7778,6 +7781,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Strexp_" + index_str, pedited, spot.strexp, spotEdited.strexp);
assignFromKeyfile(keyFile, "Locallab", "Angexp_" + index_str, pedited, spot.angexp, spotEdited.angexp);
assignFromKeyfile(keyFile, "Locallab", "ExCurve_" + index_str, pedited, spot.excurve, spotEdited.excurve);
+ assignFromKeyfile(keyFile, "Locallab", "Norm_" + index_str, pedited, spot.norm, spotEdited.norm);
assignFromKeyfile(keyFile, "Locallab", "Inversex_" + index_str, pedited, spot.inversex, spotEdited.inversex);
assignFromKeyfile(keyFile, "Locallab", "EnaExpMask_" + index_str, pedited, spot.enaExpMask, spotEdited.enaExpMask);
assignFromKeyfile(keyFile, "Locallab", "EnaExpMaskaft_" + index_str, pedited, spot.enaExpMaskaft, spotEdited.enaExpMaskaft);
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index c75d8139b..0df63b2fa 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -1109,6 +1109,7 @@ struct LocallabParams {
double strexp;
double angexp;
std::vector excurve;
+ bool norm;
bool inversex;
bool enaExpMask;
bool enaExpMaskaft;
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index 29af1190d..cb5353054 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -1068,7 +1068,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
AUTOEXP, // Evlocallabdivgr
AUTOEXP, // EvLocallabSpotavoidrad
AUTOEXP, // EvLocallabSpotavoidmun
- AUTOEXP // Evlocallabcontthres
+ AUTOEXP, // Evlocallabcontthres
+ AUTOEXP // Evlocallabnorm
};
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index c8e1a4877..a1c1e6d44 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -951,6 +951,8 @@ private:
const std::unique_ptr reservView(new LabImage(*labView, true));
const std::unique_ptr lastorigView(new LabImage(*labView, true));
+ std::unique_ptr savenormtmView;
+ std::unique_ptr savenormretiView;
LocretigainCurve locRETgainCurve;
LocretitransCurve locRETtransCurve;
LocLHCurve loclhCurve;
@@ -1035,6 +1037,7 @@ private:
}
for (size_t sp = 0; sp < params.locallab.spots.size(); sp++) {
+
// Set local curves of current spot to LUT
locRETgainCurve.Set(params.locallab.spots.at(sp).localTgaincurve);
locRETtransCurve.Set(params.locallab.spots.at(sp).localTtranscurve);
@@ -1122,6 +1125,11 @@ private:
double huere, chromare, lumare, huerefblu, chromarefblu, lumarefblu, sobelre;
int lastsav;
float avge;
+ float meantme;
+ float stdtme;
+ float meanretie;
+ float stdretie;
+
if (params.locallab.spots.at(sp).spotMethod == "exc") {
ipf.calc_ref(sp, reservView.get(), reservView.get(), 0, 0, fw, fh, 1, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge, locwavCurveden, locwavdenutili);
} else {
@@ -1140,7 +1148,7 @@ private:
float Tmax;
// No Locallab mask is shown in exported picture
- ipf.Lab_Local(2, sp, shbuffer, labView, labView, reservView.get(), lastorigView.get(), 0, 0, fw, fh, 1, locRETgainCurve, locRETtransCurve,
+ ipf.Lab_Local(2, sp, shbuffer, labView, labView, reservView.get(), savenormtmView.get(), savenormretiView.get(), lastorigView.get(), 0, 0, fw, fh, 1, locRETgainCurve, locRETtransCurve,
lllocalcurve, locallutili,
cllocalcurve, localclutili,
lclocalcurve, locallcutili,
@@ -1182,7 +1190,9 @@ private:
loclmasCurve_wav,lmasutili_wav,
LHutili, HHutili, CHutili, cclocalcurve, localcutili, rgblocalcurve, localrgbutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
+ minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
+ meantme, stdtme, meanretie, stdretie
+);
if (sp + 1u < params.locallab.spots.size()) {
// do not copy for last spot as it is not needed anymore
diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc
index 51f43157f..c0988ca37 100644
--- a/rtgui/locallabtools.cc
+++ b/rtgui/locallabtools.cc
@@ -2485,8 +2485,9 @@ LocallabExposure::LocallabExposure():
expfat(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_FATFRA")))),
fatamount(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATAMOUNT"), 1., 100., 1., 1.))),
fatdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATDETAIL"), -100., 300., 1., 0.))),
- fatlevel(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATLEVEL"), 0.25, 2.5, 0.05, 1.))),
- fatanchor(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATANCHORA"), 0.1, 3.0, 0.05, 1.))),
+ norm(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EQUIL")))),
+ fatlevel(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATLEVEL"), 0.5, 2.0, 0.01, 1.))),
+ fatanchor(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATANCHORA"), 0.5, 2.0, 0.01, 1.))),
sensiex(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 60))),
structexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUCCOL"), 0, 100, 1, 0))),
blurexpde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))),
@@ -2615,6 +2616,7 @@ LocallabExposure::LocallabExposure():
higthrese->setAdjusterListener(this);
decaye->setAdjusterListener(this);
setExpandAlignProperties(exprecove, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
+ normConn = norm->signal_toggled().connect(sigc::mem_fun(*this, &LocallabExposure::normChanged));
inversexConn = inversex->signal_toggled().connect(sigc::mem_fun(*this, &LocallabExposure::inversexChanged));
inversex->set_tooltip_text(M("TP_LOCALLAB_INVERS_TOOLTIP"));
@@ -2704,8 +2706,9 @@ LocallabExposure::LocallabExposure():
ToolParamBlock* const fatBox = Gtk::manage(new ToolParamBlock());
fatBox->pack_start(*fatamount);
fatBox->pack_start(*fatdetail);
- fatBox->pack_start(*fatlevel);
- fatBox->pack_start(*fatanchor);
+// fatBox->pack_start(*norm);
+// fatBox->pack_start(*fatlevel);
+// fatBox->pack_start(*fatanchor);
// fatFrame->add(*fatBox);
expfat->add(*fatBox, false);
// pack_start(*fatFrame);
@@ -2885,6 +2888,7 @@ void LocallabExposure::disableListener()
expMethodConn.block(true);
exnoiseMethodConn.block(true);
inversexConn.block(true);
+ normConn.block(true);
showmaskexpMethodConn.block(true);
showmaskexpMethodConninv.block(true);
enaExpMaskConn.block(true);
@@ -2898,6 +2902,7 @@ void LocallabExposure::enableListener()
expMethodConn.block(false);
exnoiseMethodConn.block(false);
inversexConn.block(false);
+ normConn.block(false);
showmaskexpMethodConn.block(false);
showmaskexpMethodConninv.block(false);
enaExpMaskConn.block(false);
@@ -2947,10 +2952,10 @@ void LocallabExposure::read(const rtengine::procparams::ProcParams* pp, const Pa
fatamount->setValue(spot.fatamount);
fatdetail->setValue(spot.fatdetail);
- // fatlevel->setValue(spot.fatlevel);
- // fatanchor->setValue(spot.fatanchor);
- fatlevel->setValue(1.);
- fatanchor->setValue(1.);
+ fatlevel->setValue(spot.fatlevel);
+ fatanchor->setValue(spot.fatanchor);
+ // fatlevel->setValue(1.);
+ // fatanchor->setValue(1.);
sensiex->setValue(spot.sensiex);
structexp->setValue(spot.structexp);
blurexpde->setValue(spot.blurexpde);
@@ -2965,6 +2970,7 @@ void LocallabExposure::read(const rtengine::procparams::ProcParams* pp, const Pa
strexp->setValue(spot.strexp);
angexp->setValue(spot.angexp);
softradiusexp->setValue(spot.softradiusexp);
+ norm->set_active(spot.norm);
inversex->set_active(spot.inversex);
enaExpMask->set_active(spot.enaExpMask);
enaExpMaskaft->set_active(spot.enaExpMaskaft);
@@ -3053,6 +3059,7 @@ void LocallabExposure::write(rtengine::procparams::ProcParams* pp, ParamsEdited*
spot.angexp = angexp->getValue();
spot.softradiusexp = softradiusexp->getValue();
spot.inversex = inversex->get_active();
+ spot.norm = norm->get_active();
spot.enaExpMask = enaExpMask->get_active();
spot.enaExpMaskaft = enaExpMaskaft->get_active();
spot.CCmaskexpcurve = CCmaskexpshape->getCurve();
@@ -3429,9 +3436,12 @@ void LocallabExposure::convertParamToNormal()
slomaskexp->setValue(defSpot.slomaskexp);
strmaskexp->setValue(defSpot.strmaskexp);
angmaskexp->setValue(defSpot.angmaskexp);
+// fatlevel->setValue(defSpot.fatlevel);
+// fatanchor->setValue(defSpot.fatanchor);
+ decaye->setValue(defSpot.decaye);
+// norm->set_active(defSpot.enaExpMask);
fatlevel->setValue(defSpot.fatlevel);
fatanchor->setValue(defSpot.fatanchor);
- decaye->setValue(defSpot.decaye);
// Enable all listeners
enableListener();
@@ -3445,7 +3455,7 @@ void LocallabExposure::convertParamToSimple()
disableListener();
fatlevel->setValue(defSpot.fatlevel);
fatanchor->setValue(defSpot.fatanchor);
-
+ norm->set_active(false);
// Set hidden specific GUI widgets in Simple mode to default spot values
strexp->setValue(defSpot.strexp);
angexp->setValue(defSpot.angexp);
@@ -3482,6 +3492,7 @@ void LocallabExposure::updateGUIToMode(const modeType new_type)
maskunusablee->hide();
decaye->hide();
expmaskexp->hide();
+ norm->hide();
fatlevel->hide();
fatanchor->hide();
@@ -3504,6 +3515,7 @@ void LocallabExposure::updateGUIToMode(const modeType new_type)
maskusablee->hide();
maskunusablee->show();
}
+ norm->show();
fatlevel->hide();
fatanchor->hide();
@@ -3526,8 +3538,9 @@ void LocallabExposure::updateGUIToMode(const modeType new_type)
}
blurexpde->show();
- fatlevel->hide();
- fatanchor->hide();
+ norm->show();
+ fatlevel->show();
+ fatanchor->show();
if (!inversex->get_active()) { // Keep widget hidden when invers is toggled
expgradexp->show();
@@ -3592,6 +3605,23 @@ void LocallabExposure::exnoiseMethodChanged()
}
}
+void LocallabExposure::normChanged()
+{
+
+ if (isLocActivated && exp->getEnabled()) {
+ if (listener) {
+ if (norm->get_active()) {
+ listener->panelChanged(Evlocallabnorm,
+ M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")");
+ } else {
+ listener->panelChanged(Evlocallabnorm,
+ M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")");
+ }
+ }
+ }
+}
+
+
void LocallabExposure::inversexChanged()
{
const bool maskPreviewActivated = isMaskViewActive();
@@ -3800,7 +3830,7 @@ LocallabShadow::LocallabShadow():
shadows(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_SHADOWS"), 0, 100, 1, 0))),
s_tonalwidth(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_SHTONALW"), 10, 100, 1, 30))),
sh_radius(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_RADIUS"), 0, 100, 1, 40))),
- sensihs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))),
+ sensihs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))),//unused here, but used for normalize_mean_dt
blurSHde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))),
exprecovs(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI2_EXP")))),
maskusables(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_MASKUSABLE")))),
@@ -3963,7 +3993,7 @@ LocallabShadow::LocallabShadow():
pack_start(*shadows);
pack_start(*s_tonalwidth);
pack_start(*sh_radius);
- // pack_start(*sensihs);
+ // pack_start(*sensihs);//unused here, but used for normalize_mean_dt
pack_start(*blurSHde);
ToolParamBlock* const shBox3 = Gtk::manage(new ToolParamBlock());
shBox3->pack_start(*maskusables, Gtk::PACK_SHRINK, 0);
@@ -4876,7 +4906,7 @@ LocallabVibrance::LocallabVibrance():
protectSkins(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_PROTECTSKINS")))),
avoidColorShift(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_AVOIDCOLORSHIFT")))),
pastSatTog(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_PASTSATTOG")))),
- sensiv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))),
+ sensiv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))),//unused here, but used for normalize_mean_dt
curveEditorGG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL"))),
skinTonesCurve(static_cast(curveEditorGG->addCurve(CT_Diagonal, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES")))),
exprecovv(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI2_EXP")))),
@@ -5027,7 +5057,7 @@ LocallabVibrance::LocallabVibrance():
pack_start(*protectSkins, Gtk::PACK_SHRINK, 0);
pack_start(*avoidColorShift, Gtk::PACK_SHRINK, 0);
pack_start(*pastSatTog, Gtk::PACK_SHRINK, 0);
- // pack_start(*sensiv, Gtk::PACK_SHRINK, 0);
+ // pack_start(*sensiv, Gtk::PACK_SHRINK, 0);//unused here, but used for normalize_mean_dt
pack_start(*curveEditorGG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor
ToolParamBlock* const vibBox3 = Gtk::manage(new ToolParamBlock());
vibBox3->pack_start(*maskusablev, Gtk::PACK_SHRINK, 0);
@@ -6264,7 +6294,7 @@ LocallabBlur::LocallabBlur():
noiselumf0(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINEZERO"), MINCHRO, MAXCHRO, 0.01, 0.))),
noiselumf(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINE"), MINCHRO, MAXCHRO, 0.01, 0.))),
noiselumf2(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINETWO"), MINCHRO, MAXCHRO, 0.01, 0.))),
- noiselumc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMCOARSE"), MINCHRO, MAXCHROCC, 0.01, 0.))),
+ noiselumc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMCOARSE"), MINCHRO, MAXCHROCC, 0.01, 0.))),//unused here, but used for normalize_mean_dt
noiselumdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMDETAIL"), 0., 100., 0.01, 50.))),
noiselequal(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELEQUAL"), -2, 10, 1, 7, Gtk::manage(new RTImage("circle-white-small.png")), Gtk::manage(new RTImage("circle-black-small.png"))))),
LocalcurveEditorwavhue(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_WAVELET_DENOISEHUE"))),
@@ -6605,7 +6635,7 @@ LocallabBlur::LocallabBlur():
// wavBox->pack_start(*noiselumf0);
// wavBox->pack_start(*noiselumf);
// wavBox->pack_start(*noiselumf2);
- // wavBox->pack_start(*noiselumc);
+ // wavBox->pack_start(*noiselumc);//unused here, but used for normalize_mean_dt
wavBox->pack_start(*noiselumdetail);
wavBox->pack_start(*noiselequal);
wavBox->pack_start(*LocalcurveEditorwavhue, Gtk::PACK_SHRINK, 4);
diff --git a/rtgui/locallabtools.h b/rtgui/locallabtools.h
index 4fda00f08..5b80706f5 100644
--- a/rtgui/locallabtools.h
+++ b/rtgui/locallabtools.h
@@ -339,6 +339,7 @@ private:
MyExpander* const expfat;
Adjuster* const fatamount;
Adjuster* const fatdetail;
+ Gtk::CheckButton* const norm;
Adjuster* const fatlevel;
Adjuster* const fatanchor;
Adjuster* const sensiex;
@@ -388,7 +389,7 @@ private:
CurveEditorGroup* const mask2expCurveEditorG;
DiagonalCurveEditor* const Lmaskexpshape;
- sigc::connection expMethodConn, exnoiseMethodConn, inversexConn, showmaskexpMethodConn, showmaskexpMethodConninv, enaExpMaskConn, enaExpMaskaftConn;
+ sigc::connection expMethodConn, exnoiseMethodConn, inversexConn, normConn, showmaskexpMethodConn, showmaskexpMethodConninv, enaExpMaskConn, enaExpMaskaftConn;
public:
LocallabExposure();
@@ -420,6 +421,7 @@ private:
void expMethodChanged();
void exnoiseMethodChanged();
void inversexChanged();
+ void normChanged();
void showmaskexpMethodChanged();
void showmaskexpMethodChangedinv();
void enaExpMaskChanged();
diff --git a/rtgui/locallabtools2.cc b/rtgui/locallabtools2.cc
index fc3eba39e..33e006baa 100644
--- a/rtgui/locallabtools2.cc
+++ b/rtgui/locallabtools2.cc
@@ -126,7 +126,7 @@ LocallabTone::LocallabTone():
estop(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ESTOP"), 0.1, 4., 0.01, 1.4))),
scaltm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCALTM"), 0.1, 10.0, 0.01, 1.0))),
rewei(Gtk::manage(new Adjuster(M("TP_LOCALLAB_REWEI"), 0, 3, 1, 0))),
- softradiustm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))),
+ softradiustm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))),//unused here, but used for normalize_mean_dt
sensitm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 60))),
exprecovt(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI2_EXP")))),
maskusablet(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_MASKUSABLE")))),
@@ -245,7 +245,7 @@ LocallabTone::LocallabTone():
pack_start(*estop);
pack_start(*scaltm);
pack_start(*rewei);
- // pack_start(*softradiustm); // Always bad with TM ??
+ // pack_start(*softradiustm); //unused here, but used for normalize_mean_dt
// pack_start(*sensitm);
ToolParamBlock* const tmBox3 = Gtk::manage(new ToolParamBlock());
tmBox3->pack_start(*maskusablet, Gtk::PACK_SHRINK, 0);
@@ -993,7 +993,7 @@ LocallabRetinex::LocallabRetinex():
retiBox->pack_start(*limd);
retiBox->pack_start(*offs);
ToolParamBlock* const toolretiBox = Gtk::manage(new ToolParamBlock());
- toolretiBox->pack_start(*chrrt);
+ // toolretiBox->pack_start(*chrrt);
toolretiBox->pack_start(*darkness);
toolretiBox->pack_start(*lightnessreti);
toolretiBox->pack_start(*cliptm);
@@ -1249,7 +1249,8 @@ void LocallabRetinex::read(const rtengine::procparams::ProcParams* pp, const Par
scalereti->setValue(spot.scalereti);
limd->setValue(spot.limd);
offs->setValue(spot.offs);
- chrrt->setValue(spot.chrrt);
+ chrrt->setValue(0.);
+ // chrrt->setValue(spot.chrrt);
darkness->setValue(spot.darkness);
lightnessreti->setValue(spot.lightnessreti);
cliptm->setValue(spot.cliptm);
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 4f3726334..1fdefc0a3 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -1178,6 +1178,7 @@ void ParamsEdited::initFrom(const std::vector&
locallab.spots.at(j).strexp = locallab.spots.at(j).strexp && pSpot.strexp == otherSpot.strexp;
locallab.spots.at(j).angexp = locallab.spots.at(j).angexp && pSpot.angexp == otherSpot.angexp;
locallab.spots.at(j).excurve = locallab.spots.at(j).excurve && pSpot.excurve == otherSpot.excurve;
+ locallab.spots.at(j).norm = locallab.spots.at(j).norm && pSpot.norm == otherSpot.norm;
locallab.spots.at(j).inversex = locallab.spots.at(j).inversex && pSpot.inversex == otherSpot.inversex;
locallab.spots.at(j).enaExpMask = locallab.spots.at(j).enaExpMask && pSpot.enaExpMask == otherSpot.enaExpMask;
locallab.spots.at(j).enaExpMaskaft = locallab.spots.at(j).enaExpMaskaft && pSpot.enaExpMaskaft == otherSpot.enaExpMaskaft;
@@ -3710,6 +3711,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.locallab.spots.at(i).excurve = mods.locallab.spots.at(i).excurve;
}
+ if (locallab.spots.at(i).norm) {
+ toEdit.locallab.spots.at(i).norm = mods.locallab.spots.at(i).norm;
+ }
+
if (locallab.spots.at(i).inversex) {
toEdit.locallab.spots.at(i).inversex = mods.locallab.spots.at(i).inversex;
}
@@ -6774,6 +6779,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) :
strexp(v),
angexp(v),
excurve(v),
+ norm(v),
inversex(v),
enaExpMask(v),
enaExpMaskaft(v),
@@ -7345,6 +7351,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v)
strexp = v;
angexp = v;
excurve = v;
+ norm = v;
inversex = v;
enaExpMask = v;
enaExpMaskaft = v;
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index d9087d729..95fc76407 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -517,6 +517,7 @@ public:
bool strexp;
bool angexp;
bool excurve;
+ bool norm;
bool inversex;
bool enaExpMask;
bool enaExpMaskaft;