diff --git a/rtdata/languages/default b/rtdata/languages/default
index f32300899..2cca1b81d 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -1210,6 +1210,9 @@ HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength
HISTORY_MSG_TEMPOUT;CAM02 automatic temperature
HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor
HISTORY_MSG_TRANS_Method;Geometry - Method
+HISTORY_MSG_WAVBALCHROM;Balance chroma
+HISTORY_MSG_WAVCHROMFI;Chroma fine
+HISTORY_MSG_WAVCHROMCO;Chroma coarse
HISTORY_MSG_WAVCLARI;Clarity
HISTORY_MSG_WAVEDGS;Edge stopping
HISTORY_MSG_WAVMERGEC;Merge C
@@ -1217,12 +1220,12 @@ HISTORY_MSG_WAVMERGEL;Merge L
HISTORY_MSG_WAVRADIUS;Radius Shadows-Highlight
HISTORY_MSG_WAVSCALE;Scale
HISTORY_MSG_WAVSHOWMASK;Show wavelet mask
-HISTORY_MSG_WAVSIGMA;Sigma
+HISTORY_MSG_WAVSIGMA;Damper
HISTORY_MSG_WAVSOFTRAD;Soft radius clarity
HISTORY_MSG_WAVSOFTRADEND;Soft radius final
HISTORY_MSG_WAVUSHAMET;Clarity method
HISTORY_MSG_THRESWAV;Balance threshold
-HISTORY_MSG_BLUWAV;Effects
+HISTORY_MSG_BLUWAV;Damper
HISTORY_MSG_WAVOLDSH;Old algorithm
HISTORY_MSG_WAVOFFSET;Offset
HISTORY_MSG_WAVLOWTHR;Threshold low contrast
@@ -3039,12 +3042,13 @@ TP_WAVELET_BALANCE;Contrast balance d/v-h
TP_WAVELET_BALANCE_TOOLTIP;Alters the balance between the wavelet directions: vertical-horizontal and diagonal.\nIf contrast, chroma or residual tone mapping are activated, the effect due to balance is amplified.
TP_WAVELET_BALCHRO;Chroma balance
TP_WAVELET_BALCHRO_TOOLTIP;If enabled, the 'Contrast balance' curve or slider also modifies chroma balance.
+TP_WAVELET_BALCHROM;Chroma balance
TP_WAVELET_BANONE;None
TP_WAVELET_BASLI;Slider
TP_WAVELET_BATYPE;Contrast balance method
TP_WAVELET_BLCURVE;Blur by levels
TP_WAVELET_BLURFRAME;Blur
-TP_WAVELET_BLUWAV;Effects
+TP_WAVELET_BLUWAV;Damper
TP_WAVELET_CBENAB;Toning and Color Balance
TP_WAVELET_CB_TOOLTIP;For strong values product color-toning by combining it or not with levels decomposition 'toning'\nFor low values you can change the white balance of the background (sky, ...) without changing that of the front plane, generally more contrasted
TP_WAVELET_CCURVE;Local contrast
@@ -3054,7 +3058,10 @@ TP_WAVELET_CH3;Link contrast levels
TP_WAVELET_CHCU;Curve
TP_WAVELET_CHR;Chroma-contrast link strength
TP_WAVELET_CHRO;Saturated/pastel threshold
+TP_WAVELET_CHROFRAME;Denoise Chroma
TP_WAVELET_CHROMAFRAME;Chroma
+TP_WAVELET_CHROMCO;Chroma Coarse
+TP_WAVELET_CHROMFI;Chroma Fine
TP_WAVELET_CHRO_TOOLTIP;Sets the wavelet level which will be the threshold between saturated and pastel colors.\n1-x: saturated\nx-9: pastel\n\nIf the value exceeds the amount of wavelet levels you are using then it will be ignored.
TP_WAVELET_CHR_TOOLTIP;Adjusts chroma as a function of "contrast levels" and "chroma-contrast link strength"
TP_WAVELET_CHRWAV;Blur chroma
@@ -3104,7 +3111,7 @@ TP_WAVELET_EDGEDETECTTHR;Threshold low (noise)
TP_WAVELET_EDGEDETECTTHR2;Threshold high (detection)
TP_WAVELET_EDGEDETECTTHR_TOOLTIP;This adjuster lets you target edge detection for example to avoid applying edge sharpness to fine details, such as noise in the sky.
TP_WAVELET_EDGEDETECT_TOOLTIP;Moving the slider to the right increases edge sensitivity. This affects local contrast, edge settings and noise.
-TP_WAVELET_EDEFFECT;Effect
+TP_WAVELET_EDEFFECT;Damper
TP_WAVELET_EDEFFECT_TOOLTIP;This slider controls how wide the range of contrast values are that receive the maximum effect from the tool.\nMaximum value (2.5) disabled the tool
TP_WAVELET_EDGESENSI;Edge sensitivity
TP_WAVELET_EDGREINF_TOOLTIP;Reinforce or reduce the action of the first level, do the opposite to the second level, and leave the rest unchanged.
@@ -3181,8 +3188,8 @@ TP_WAVELET_SETTINGS;Wavelet Settings
TP_WAVELET_SHA;Sharp mask
TP_WAVELET_SHFRAME;Shadows/Highlights
TP_WAVELET_SHOWMASK;Show wavelet 'mask'
-TP_WAVELET_SIGMA;Effects
-TP_WAVELET_SIGMA_TOOLTIP;This slider controls how wide the range of contrast values are that receive the maximum effect from the tool.\n The higher it is, the more contrast values will be strongly modified and the higher the risk to generate artifacts. The lower it is, the more pinpoint will the effect be applied to a certain range of contrast values
+TP_WAVELET_SIGMA;Damper
+TP_WAVELET_SIGMA_TOOLTIP;The effect of the contrast sliders is stronger in medium contrast details, and weaker in high and low contrast details.\n With this slider you can control how quickly the effect dampens towards the extreme contrasts.\n The higher the slider is set, the wider the range of contrasts which will get a strong change, and the higher the risk to generate artifacts.\n The lower it is, the more pinpoint will the effect be applied to a narrow range of contrast values.
TP_WAVELET_SKIN;Skin targetting/protection
TP_WAVELET_SKIN_TOOLTIP;At -100 skin-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 skin-tones are protected while all other tones are affected.
TP_WAVELET_SKY;Sky targetting/protection
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index f0086b2e0..d47a6f60e 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -406,18 +406,22 @@ public:
void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, const LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false);
void RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail); //for DCT
void RGBoutput_tile_row(float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top);
- bool WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels);
- bool WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels);
- bool WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels);
void WaveletDenoiseAll_info(int levwav, const wavelet_decomposition &WaveletCoeffs_a,
const wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb);
+ bool WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels);
+ bool WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels);
+
bool WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels);
+ bool WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels);
+
void ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge);
void ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab = nullptr, bool madCalculated = false);
+
+
void ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b,
int W_ab, int H_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb);
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index df2a46dc8..b509c6fe9 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -138,6 +138,9 @@ struct cont_params {
float edgampl;
int neigh;
bool lipp;
+ float balchrom;
+ float chromfi;
+ float chromco;
};
int wavNestedLevels = 1;
@@ -196,6 +199,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (params->wavelet.BAmethod != "none") {
cp.bam = true;
+
if (params->wavelet.BAmethod == "sli") {
cp.BAmet = 1;
} else if (params->wavelet.BAmethod == "cur") {
@@ -260,7 +264,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
DaubLen = 8;
} else if (params->wavelet.daubcoeffmethod == "10_") {
DaubLen = 12;
- } else /* if (params->wavelet.daubcoeffmethod == "14_") */{
+ } else { /* if (params->wavelet.daubcoeffmethod == "14_") */
DaubLen = 16;
}
@@ -394,6 +398,9 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.val = waparams.edgval;
cp.til = waparams.edgthresh;
cp.eff = waparams.edgeffect;
+ cp.balchrom = waparams.balchrom;
+ cp.chromfi = waparams.chromfi;
+ cp.chromco = waparams.chromco;
cp.conres = waparams.rescon;
cp.conresH = waparams.resconH;
@@ -860,7 +867,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (cp.val > 0 || ref || contr) { //edge
Evaluate2(*Ldecomp, mean, meanN, sigma, sigmaN, MaxP, MaxN);
}
-
+
//init for edge and denoise
float vari[4];
@@ -877,8 +884,8 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
vari[3] = rtengine::max(0.0001f, vari[3]);
float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL
- // WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge);
- WaveletDenoiseAllL (*Ldecomp, noisevarlum, madL, vari, edge, 1);
+ WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+ // WaveletDenoiseAllL (*Ldecomp, noisevarlum, madL, vari, edge, 1);
}
//Flat curve for Contrast=f(H) in levels
@@ -907,6 +914,213 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
+
+ /*
+ float variC[7];
+ float variCb[7];
+
+ float noisecfr = cp.chromfi;
+ float noiseccr = cp.chromco;
+
+ if (cp.balchrom > 0.f) {
+ noisecfr = cp.chromfi * ((100.f + cp.balchrom) / 10.f);
+ noiseccr = cp.chromco + ((100.f + cp.balchrom) / 10.f);
+ }
+
+ float noisecfb = cp.chromfi;
+ float noiseccb = cp.chromco;
+
+ if (cp.balchrom < 0.f) {
+ noisecfb = cp.chromfi * ((100.f - cp.balchrom) / 10.f);
+ noiseccb = cp.chromco * ((100.f - cp.balchrom) / 10.f);
+ }
+
+
+ if (noisecfr < 0.f) {
+ noisecfr = 0.0001f;
+ }
+
+ if (noiseccr < 0.f) {
+ noiseccr = 0.0001f;
+ }
+
+ if (noisecfb < 0.f) {
+ noisecfb = 0.0001f;
+ }
+
+ if (noiseccb < 0.f) {
+ noiseccb = 0.0001f;
+ }
+
+ int edge = 2;
+ variC[0] = SQR(noisecfr);
+ variC[1] = SQR(noisecfr);
+ variC[2] = SQR(noisecfr);
+
+ variC[3] = SQR(noisecfr);
+ variC[4] = SQR(noisecfr);
+ variC[5] = SQR(noiseccr);
+ variC[6] = SQR(noiseccr);
+
+ variCb[0] = SQR(noisecfb);
+ variCb[1] = SQR(noisecfb);
+ variCb[2] = SQR(noisecfb);
+
+ variCb[3] = SQR(noisecfb);
+ variCb[4] = SQR(noisecfb);
+ variCb[5] = SQR(noiseccb);
+ variCb[6] = SQR(noiseccb);
+
+ float k1 = 0.f;
+ float k2 = 0.f;
+ float k3 = 0.f;
+
+ if (cp.chromfi) {
+ k1 = 0.f;
+ k2 = 0.f;
+ k3 = 0.f;
+ } else if (cp.chromfi < 0.3f) {
+ k1 = 0.1f;
+ k2 = 0.0f;
+ k3 = 0.f;
+ } else if (cp.chromfi < 0.5f) {
+ k1 = 0.2f;
+ k2 = 0.1f;
+ k3 = 0.f;
+ } else if (cp.chromfi < 0.8f) {
+ k1 = 0.3f;
+ k2 = 0.25f;
+ k3 = 0.f;
+ } else if (cp.chromfi < 1.f) {
+ k1 = 0.4f;
+ k2 = 0.25f;
+ k3 = 0.1f;
+ } else if (cp.chromfi < 2.f) {
+ k1 = 0.5f;
+ k2 = 0.3f;
+ k3 = 0.15f;
+ } else if (cp.chromfi < 3.f) {
+ k1 = 0.6f;
+ k2 = 0.45f;
+ k3 = 0.3f;
+ } else if (cp.chromfi < 4.f) {
+ k1 = 0.7f;
+ k2 = 0.5f;
+ k3 = 0.4f;
+ } else if (cp.chromfi < 5.f) {
+ k1 = 0.8f;
+ k2 = 0.6f;
+ k3 = 0.5f;
+ } else if (cp.chromfi < 10.f) {
+ k1 = 0.85f;
+ k2 = 0.7f;
+ k3 = 0.6f;
+ } else if (cp.chromfi < 20.f) {
+ k1 = 0.9f;
+ k2 = 0.8f;
+ k3 = 0.7f;
+ } else if (cp.chromfi < 50.f) {
+ k1 = 1.f;
+ k2 = 1.f;
+ k3 = 0.9f;
+
+ } else {
+ k1 = 1.f;
+ k2 = 1.f;
+ k3 = 1.f;
+ }
+
+ float minic = 0.0001f;
+ variC[0] = max(minic, variC[0]);
+ variC[1] = max(minic, k1 * variC[1]);
+ variC[2] = max(minic, k2 * variC[2]);
+ variC[3] = max(minic, k3 * variC[3]);
+
+ variCb[0] = max(minic, variCb[0]);
+ variCb[1] = max(minic, k1 * variCb[1]);
+ variCb[2] = max(minic, k2 * variCb[2]);
+ variCb[3] = max(minic, k3 * variCb[3]);
+
+ float k4 = 0.f;
+ float k5 = 0.f;
+ float k6 = 0.f;
+
+ if (cp.chromco == 0.01f) {
+ k4 = 0.f;
+ k5 = 0.0f;
+ } else if (cp.chromco < 0.2f) {
+ k4 = 0.1f;
+ k5 = 0.0f;
+ } else if (cp.chromco < 0.5f) {
+ k4 = 0.15f;
+ k5 = 0.0f;
+ } else if (cp.chromco < 1.f) {
+ k4 = 0.15f;
+ k5 = 0.1f;
+ } else if (cp.chromco < 3.f) {
+ k4 = 0.3f;
+ k5 = 0.15f;
+ } else if (cp.chromco < 4.f) {
+ k4 = 0.6f;
+ k5 = 0.4f;
+ } else if (cp.chromco < 6.f) {
+ k4 = 0.8f;
+ k5 = 0.6f;
+ } else {
+ k4 = 1.f;
+ k5 = 1.f;
+ }
+
+ variC[4] = max(0.0001f, k4 * variC[4]);
+ variC[5] = max(0.0001f, k5 * variC[5]);
+ variCb[4] = max(0.0001f, k4 * variCb[4]);
+ variCb[5] = max(0.0001f, k5 * variCb[5]);
+
+ if (cp.chromco < 4.f) {
+ k6 = 0.f;
+ } else if (cp.chromco < 5.f) {
+ k6 = 0.4f;
+ } else if (cp.chromco < 6.f) {
+ k6 = 0.7f;
+ } else {
+ k6 = 1.f;
+ }
+
+ variC[6] = max(0.0001f, k6 * variC[6]);
+ variCb[6] = max(0.0001f, k6 * variCb[6]);
+ float nvch = 0.6f;//high value
+ float nvcl = 0.1f;//low value
+
+ if (cp.chromco > 100.f) {
+ nvch = 0.8f;
+ nvcl = 0.4f;
+ }
+
+ float seuil = 4000.f;//low
+ float seuil2 = 15000.f;//high
+ //ac and bc for transition
+ float ac = (nvch - nvcl) / (seuil - seuil2);
+ float bc = nvch - seuil * ac;
+ int GW = labco->W;
+ int GH = labco->H;
+ float* noisevarchrom = new float[GH * GW];
+ //noisevarchrom in function chroma
+ int GW2 = (GW + 1) / 2;
+ float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0);
+ for (int ir = 0; ir < GH; ir++)
+ for (int jr = 0; jr < GW; jr++) {
+ float cN = sqrt(SQR(labco->a[ir][jr]) + SQR(labco->b[ir][jr]));
+
+ if (cN < seuil) {
+ noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = nvch;
+ } else if (cN < seuil2) {
+ noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = ac * cN + bc;
+ } else {
+ noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = nvcl;
+ }
+ }
+ */
+
//Flat curve for H=f(H) in residual image
FlatCurve* hhCurve = new FlatCurve(params->wavelet.hhcurve); //curve H=f(H)
bool hhutili = false;
@@ -972,7 +1186,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) {
Evaluate2(*adecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab);
- WaveletcontAllAB(labco, varhue, varchro, *adecomp,wavblcurve, waOpacityCurveW, cp, true, skip, meanab, sigmaab);
+ WaveletcontAllAB(labco, varhue, varchro, *adecomp, wavblcurve, waOpacityCurveW, cp, true, skip, meanab, sigmaab);
Evaluate2(*bdecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab);
WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip, meanab, sigmaab);
WaveletAandBAllAB(*adecomp, *bdecomp, cp, hhCurve, hhutili);
@@ -984,6 +1198,8 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
+ // delete[] noisevarchrom;
+
if (hhCurve) {
delete hhCurve;
}
@@ -1249,7 +1465,7 @@ void ImProcFunctions::Aver(float * RESTRICT DataList, int datalen, float &averag
int countP = 0, countN = 0;
double averaP = 0.0, averaN = 0.0; // use double precision for large summations
- constexpr float thres = 32.7f;//different fom zero to take into account only data large enough 32.7 = 0.1 in range 0..100 very low value
+ constexpr float thres = 32.7f;//different fom zero to take into account only data large enough 32.7 = 0.1 in range 0..100 very low value
max = 0.f;
min = RT_INFINITY_F;
#ifdef _OPENMP
@@ -1351,51 +1567,54 @@ void ImProcFunctions::Evaluate2(const wavelet_decomposition &WaveletCoeffs_L,
void ImProcFunctions::calceffect(int level, float *mean, float *sigma, float *mea, float effect, float offs)
{
- float rap = 0.f;
- float sig = 1.f;
- if(effect < 1.f) {
- sig = effect;
- }
+ float rap = 0.f;
+ float sig = 1.f;
- if(effect <= 1.f) {
- rap = offs * mean[level] - sig * sigma[level];
- }
-
- if (rap > 0.f) {
- mea[0] = rap;
- } else {
- mea[0] = mean[level] / 6.f;
- }
+ if (effect < 1.f) {
+ sig = effect;
+ }
- rap = 0.f;
- if(effect <= 1.f) {
- rap = offs * mean[level] - 0.5f * sig * sigma[level];
- }
+ if (effect <= 1.f) {
+ rap = offs * mean[level] - sig * sigma[level];
+ }
- if (rap > 0.f) {
- mea[1] = rap;
- } else {
- mea[1] = mean[level] / 4.f;
- }
+ if (rap > 0.f) {
+ mea[0] = rap;
+ } else {
+ mea[0] = mean[level] / 6.f;
+ }
- rap = 0.f;
- if(effect <= 1.f) {
- rap = offs * mean[level] - 0.2f * sig * sigma[level];
- }
-
- if (rap > 0.f) {
- mea[2] = rap;
- } else {
- mea[2] = mean[level] / 2.f;
- }
-
- mea[3] = offs * mean[level]; // 50% data
- mea[4] = offs * mean[level] + effect * sigma[level] / 2.f;
- mea[5] = offs * mean[level] + effect * sigma[level]; //66%
- mea[6] = offs * mean[level] + effect * 1.2f * sigma[level];
- mea[7] = offs * mean[level] + effect * 1.5f * sigma[level]; //
- mea[8] = offs * mean[level] + effect * 2.f * sigma[level]; //95%
- mea[9] = offs * mean[level] + effect * 2.5f * sigma[level]; //99%
+ rap = 0.f;
+
+ if (effect <= 1.f) {
+ rap = offs * mean[level] - 0.5f * sig * sigma[level];
+ }
+
+ if (rap > 0.f) {
+ mea[1] = rap;
+ } else {
+ mea[1] = mean[level] / 4.f;
+ }
+
+ rap = 0.f;
+
+ if (effect <= 1.f) {
+ rap = offs * mean[level] - 0.2f * sig * sigma[level];
+ }
+
+ if (rap > 0.f) {
+ mea[2] = rap;
+ } else {
+ mea[2] = mean[level] / 2.f;
+ }
+
+ mea[3] = offs * mean[level]; // 50% data
+ mea[4] = offs * mean[level] + effect * sigma[level] / 2.f;
+ mea[5] = offs * mean[level] + effect * sigma[level]; //66%
+ mea[6] = offs * mean[level] + effect * 1.2f * sigma[level];
+ mea[7] = offs * mean[level] + effect * 1.5f * sigma[level]; //
+ mea[8] = offs * mean[level] + effect * 2.f * sigma[level]; //95%
+ mea[9] = offs * mean[level] + effect * 2.5f * sigma[level]; //99%
}
void ImProcFunctions::Eval2(float ** WavCoeffs_L, int level,
@@ -1726,7 +1945,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
#pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
#endif
{
- if(contrast != 0.f && cp.resena && max0 > 0.f) { // contrast = 0.f means that all will be multiplied by 1.f, so we can skip this step
+ if (contrast != 0.f && cp.resena && max0 > 0.f) { // contrast = 0.f means that all will be multiplied by 1.f, so we can skip this step
{
#ifdef _OPENMP
@@ -1785,61 +2004,62 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
#ifdef _OPENMP
- #pragma omp barrier
+ #pragma omp barrier
#endif
- if((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
+ if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
#ifdef _OPENMP
- #pragma omp for nowait
+ #pragma omp for nowait
#endif
- for (int i = 0; i < W_L * H_L; i++) {
- float LL = WavCoeffs_L0[i];
- float LL100 = LL / 327.68f;
- float tran = 5.f;//transition
- //shadow
- float alp = 3.f; //increase contrast sahdow in lowlights between 1 and ??
+ for (int i = 0; i < W_L * H_L; i++) {
+ float LL = WavCoeffs_L0[i];
+ float LL100 = LL / 327.68f;
+ float tran = 5.f;//transition
+ //shadow
+ float alp = 3.f; //increase contrast sahdow in lowlights between 1 and ??
- if(cp.th > (100.f - tran)) {
- tran = 100.f - cp.th;
- }
+ if (cp.th > (100.f - tran)) {
+ tran = 100.f - cp.th;
+ }
- if(LL100 < cp.th) {
- float aalp = (1.f - alp) / cp.th; //no changes for LL100 = cp.th
- float kk = aalp * LL100 + alp;
- WavCoeffs_L0[i] *= (1.f + kk * cp.conres / 200.f);
- } else if(LL100 < cp.th + tran) {
- float ath = -cp.conres / tran;
- float bth = cp.conres - ath * cp.th;
- WavCoeffs_L0[i] *= (1.f + (LL100 * ath + bth) / 200.f);
- }
+ if (LL100 < cp.th) {
+ float aalp = (1.f - alp) / cp.th; //no changes for LL100 = cp.th
+ float kk = aalp * LL100 + alp;
+ WavCoeffs_L0[i] *= (1.f + kk * cp.conres / 200.f);
+ } else if (LL100 < cp.th + tran) {
+ float ath = -cp.conres / tran;
+ float bth = cp.conres - ath * cp.th;
+ WavCoeffs_L0[i] *= (1.f + (LL100 * ath + bth) / 200.f);
+ }
- //highlight
- tran = 5.f;
+ //highlight
+ tran = 5.f;
- if(cp.thH < (tran)) {
- tran = cp.thH;
- }
+ if (cp.thH < (tran)) {
+ tran = cp.thH;
+ }
- if(LL100 > cp.thH) {
- WavCoeffs_L0[i] *= (1.f + cp.conresH / 200.f);
- } else if(LL100 > (cp.thH - tran)) {
- float athH = cp.conresH / tran;
- float bthH = cp.conresH - athH * cp.thH;
- WavCoeffs_L0[i] *= (1.f + (LL100 * athH + bthH) / 200.f);
- }
+ if (LL100 > cp.thH) {
+ WavCoeffs_L0[i] *= (1.f + cp.conresH / 200.f);
+ } else if (LL100 > (cp.thH - tran)) {
+ float athH = cp.conresH / tran;
+ float bthH = cp.conresH - athH * cp.thH;
+ WavCoeffs_L0[i] *= (1.f + (LL100 * athH + bthH) / 200.f);
}
}
+ }
//Blur luma
- if(cp.blurres != 0.f && cp.resena) {
+ if (cp.blurres != 0.f && cp.resena) {
float rad = 0.7f * cp.blurres / skip;
float * bef = new float[W_L * H_L];
float * aft = new float[W_L * H_L];
for (int i = 0; i < H_L * W_L; i++) {
- bef[i] = WavCoeffs_L0[i];
+ bef[i] = WavCoeffs_L0[i];
}
+
boxblur(bef, aft, rad, W_L, H_L, false);
for (int i = 0; i < H_L * W_L; i++) {
@@ -1849,7 +2069,11 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
delete[] bef;
delete[] aft;
}
+
//
+ int n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n32;
+ n0 = n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = n9 = n10 = n32 = 0;
+
#ifdef _OPENMP
#pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
#endif
@@ -1996,6 +2220,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
// end
}
+
bool wavcurvecomp = false;//not enable if 0.75
if (wavblcurve) {
@@ -2007,7 +2232,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
#ifdef _OPENMP
- #pragma omp for schedule(dynamic) collapse(2)
+ // #pragma omp for schedule(dynamic) collapse(2)
+ #pragma omp for reduction(+:n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n32) schedule(dynamic) collapse(2)
#endif
for (int dir = 1; dir < 4; dir++) {
@@ -2021,12 +2247,13 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
ContAllL(koeLi, maxkoeLi, true, maxlvl, labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili);
//blur level
float klev = 1.f;
- if(wavblcurve && wavcurvecomp && cp.blena) {
+
+ if (wavblcurve && wavcurvecomp && cp.blena) {
float mea[10];
float effect = cp.bluwav;
float beta = 0.f;
float offs = 1.f;
-
+
calceffect(lvl, mean, sigma, mea, effect, offs);
float * bef = new float[Wlvl_L * Hlvl_L];
@@ -2036,37 +2263,58 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
bef[co] = WavCoeffs_L[dir][co];
float WavCL = std::fabs(WavCoeffs_L[dir][co]);
- if (WavCL < mea[0]) {
- beta = 0.05f;
- } else if (WavCL < mea[1]) {
- beta = 0.2f;
- } else if (WavCL < mea[2]) {
- beta = 0.7f;
- } else if (WavCL < mea[3]) {
- beta = 1.f; //standard
- } else if (WavCL < mea[4]) {
- beta = 1.f;
- } else if (WavCL < mea[5]) {
- beta = 0.8f; //+sigma
- } else if (WavCL < mea[6]) {
- beta = 0.6f;
- } else if (WavCL < mea[7]) {
- beta = 0.4f;
- } else if (WavCL < mea[8]) {
- beta = 0.2f; // + 2 sigma
- } else if (WavCL < mea[9]) {
- beta = 0.1f;
- } else {
- beta = 0.0f;
+ if (WavCL < mea[0]) {
+ beta = 0.05f;
+ n0++;
+
+ if (WavCL < 32.7) {
+ n32++;
}
-
-
+ } else if (WavCL < mea[1]) {
+ beta = 0.2f;
+ n1++;
+ } else if (WavCL < mea[2]) {
+ beta = 0.7f;
+ n2++;
+ } else if (WavCL < mea[3]) {
+ beta = 1.f; //standard
+ n3++;
+ } else if (WavCL < mea[4]) {
+ beta = 1.f;
+ n4++;
+ } else if (WavCL < mea[5]) {
+ beta = 0.8f; //+sigma
+ n5++;
+ } else if (WavCL < mea[6]) {
+ beta = 0.6f;
+ n6++;
+ } else if (WavCL < mea[7]) {
+ beta = 0.4f;
+ n7++;
+ } else if (WavCL < mea[8]) {
+ beta = 0.2f; // + 2 sigma
+ n8++;
+ } else if (WavCL < mea[9]) {
+ beta = 0.1f;
+ n9++;
+ } else {
+ beta = 0.01f;
+ n10++;
+ }
+
+
+ }
+
+ if (settings->verbose) {
+ printf("lvl=%i n0=%i n32=%i n1=%i n2=%i n3=%i n4=%i n5=%i n6=%i n7=%i n8=%i n9=%i n10=%i\n", lvl, n0, n0 - n32, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10);
}
klev = (wavblcurve[lvl * 55.5f]);
float lvr = lvl;
- if(lvr == 0) {
+
+ if (lvr == 0) {
lvr = 1;
}
+
klev *= beta * lvr * 100.f / skip;
boxblur(bef, aft, klev, Wlvl_L, Hlvl_L, false);
@@ -2276,41 +2524,42 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float
}
}
}
-
+
//Blur chroma
- if(cp.blurcres != 0.f && cp.resena) {
- float rad = 0.7f * cp.blurcres / skip;
- float * bef = new float[W_L * H_L];
- float * aft = new float[W_L * H_L];
+ if (cp.blurcres != 0.f && cp.resena) {
+ float rad = 0.7f * cp.blurcres / skip;
+ float * bef = new float[W_L * H_L];
+ float * aft = new float[W_L * H_L];
- for (int i = 0; i < H_L * W_L; i++) {
- bef[i] = WavCoeffs_ab0[i];
- }
- boxblur(bef, aft, rad, W_L, H_L, false);
+ for (int i = 0; i < H_L * W_L; i++) {
+ bef[i] = WavCoeffs_ab0[i];
+ }
- for (int i = 0; i < H_L * W_L; i++) {
- WavCoeffs_ab0[i] = aft[i];
- }
+ boxblur(bef, aft, rad, W_L, H_L, false);
+
+ for (int i = 0; i < H_L * W_L; i++) {
+ WavCoeffs_ab0[i] = aft[i];
+ }
delete[] bef;
delete[] aft;
- }
+ }
- bool wavcurvecomp = false;//not enable if 0.75
+ bool wavcurvecomp = false;//not enable if 0.75
- if (wavblcurve) {
- for (int i = 0; i < 500; i++) {
- if (wavblcurve[i] != 0.) {
- wavcurvecomp = true;
+ if (wavblcurve) {
+ for (int i = 0; i < 500; i++) {
+ if (wavblcurve[i] != 0.) {
+ wavcurvecomp = true;
+ }
}
}
- }
#ifdef _OPENMP
#pragma omp for schedule(dynamic) collapse(2)
#endif
-
+
for (int dir = 1; dir < 4; dir++) {
for (int lvl = 0; lvl < maxlvl; lvl++) {
@@ -2320,55 +2569,58 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float
float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl);
ContAllAB(labco, maxlvl, varhue, varchrom, WavCoeffs_ab, WavCoeffs_ab0, lvl, dir, waOpacityCurveW, cp, Wlvl_ab, Hlvl_ab, useChannelA);
- if(wavblcurve && wavcurvecomp && cp.blena && cp.chrwav > 0.f) {
+ if (wavblcurve && wavcurvecomp && cp.blena && cp.chrwav > 0.f) {
float mea[10];
float effect = cp.bluwav;
float beta = 0.f;
float offs = 1.f;
-
+
calceffect(lvl, meanab, sigmaab, mea, effect, offs);
-
+
float * bef = new float[Wlvl_ab * Hlvl_ab];
float * aft = new float[Wlvl_ab * Hlvl_ab];
float klev;
+
for (int co = 0; co < Hlvl_ab * Wlvl_ab; co++) {
bef[co] = WavCoeffs_ab[dir][co];
- float WavCab = std::fabs(WavCoeffs_ab[dir][co]);
+ float WavCab = std::fabs(WavCoeffs_ab[dir][co]);
+
+ if (WavCab < mea[0]) {
+ beta = 0.05f;
+ } else if (WavCab < mea[1]) {
+ beta = 0.2f;
+ } else if (WavCab < mea[2]) {
+ beta = 0.7f;
+ } else if (WavCab < mea[3]) {
+ beta = 1.f; //standard
+ } else if (WavCab < mea[4]) {
+ beta = 1.f;
+ } else if (WavCab < mea[5]) {
+ beta = 0.8f; //+sigma
+ } else if (WavCab < mea[6]) {
+ beta = 0.6f;
+ } else if (WavCab < mea[7]) {
+ beta = 0.4f;
+ } else if (WavCab < mea[8]) {
+ beta = 0.2f; // + 2 sigma
+ } else if (WavCab < mea[9]) {
+ beta = 0.1f;
+ } else {
+ beta = 0.0f;
+ }
+
- if (WavCab < mea[0]) {
- beta = 0.05f;
- } else if (WavCab < mea[1]) {
- beta = 0.2f;
- } else if (WavCab < mea[2]) {
- beta = 0.7f;
- } else if (WavCab < mea[3]) {
- beta = 1.f; //standard
- } else if (WavCab < mea[4]) {
- beta = 1.f;
- } else if (WavCab < mea[5]) {
- beta = 0.8f; //+sigma
- } else if (WavCab < mea[6]) {
- beta = 0.6f;
- } else if (WavCab < mea[7]) {
- beta = 0.4f;
- } else if (WavCab < mea[8]) {
- beta = 0.2f; // + 2 sigma
- } else if (WavCab < mea[9]) {
- beta = 0.1f;
- } else {
- beta = 0.0f;
- }
-
-
}
- klev = (wavblcurve[lvl * 55.5f]);
+
+ klev = (wavblcurve[lvl * 55.5f]);
float lvr = lvl;
- if(lvr == 0) {
+
+ if (lvr == 0) {
lvr = 1;
}
klev *= beta * cp.chrwav * lvr * 200.f / skip;
-
+
boxblur(bef, aft, klev, Wlvl_ab, Hlvl_ab, false);
for (int co = 0; co < Hlvl_ab * Wlvl_ab; co++) {
@@ -2730,11 +2982,13 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
float mea[10];
float beta = 1.f;
- if(cp.eff < 2.5f) {
+
+ if (cp.eff < 2.5f) {
float effect = cp.eff;
float offs = 1.f;
calceffect(level, mean, sigma, mea, effect, offs);
+
for (int co = 0; co < H_L * W_L; co++) {
float WavCL = std::fabs(WavCoeffs_L[dir][co]);
@@ -2761,14 +3015,14 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
} else {
beta = 0.0f;
}
-
+
}
}
if (cp.val > 0 && cp.edgeena) {
-
-
+
+
float * koe = nullptr;
float maxkoe = 0.f;
@@ -2857,6 +3111,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
float atten01234 = 0.80f;
value *= (atten01234 * scaleskip[1]); //for zoom < 100% reduce strength...I choose level 1...but!!
}
+
value *= beta;
float edge = 1.f;
float lim0 = 20.f; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi
@@ -2867,8 +3122,8 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
if (cp.reinforce != 2) {
const float brepart =
cp.reinforce == 1
- ? 3.f
- : 0.5f;
+ ? 3.f
+ : 0.5f;
const float arepart = -(brepart - 1.f) / (lim0 / 60.f);
if (rad < lim0 / 60.f) {
@@ -3191,7 +3446,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
float red0 = 0.005f * (110.f - lowthr);
float red1 = 0.008f * (110.f - lowthr);
float red2 = 0.011f * (110.f - lowthr);
-
+
for (int i = 0; i < W_L * H_L; i++) {
float kLlev = 1.f;
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 7521332ba..cadb0857d 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -2248,6 +2248,9 @@ WaveletParams::WaveletParams() :
bluemed(0),
greenhigh(0),
bluehigh(0),
+ balchrom(0.),
+ chromfi(0.),
+ chromco(0.),
mergeL(40.),
mergeC(20.),
softrad(0.),
@@ -2320,7 +2323,7 @@ WaveletParams::WaveletParams() :
radius(40),
skinprotect(0.0),
chrwav(0.),
- bluwav(50.0),
+ bluwav(1.0),
hueskin(-5, 25, 170, 120, false),
hueskin2(-260, -250, -130, -140, false),
hllev(50, 75, 100, 98, false),
@@ -2358,6 +2361,9 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& bluemed == other.bluemed
&& greenhigh == other.greenhigh
&& bluehigh == other.bluehigh
+ && balchrom == other.balchrom
+ && chromfi == other.chromfi
+ && chromco == other.chromco
&& mergeL == other.mergeL
&& mergeC == other.mergeC
&& softrad == other.softrad
@@ -4877,6 +4883,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.bluehigh, "Wavelet", "CBbluehigh", wavelet.bluehigh, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.bluemed, "Wavelet", "CBbluemed", wavelet.bluemed, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.bluelow, "Wavelet", "CBbluelow", wavelet.bluelow, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.balchrom, "Wavelet", "Balchrom", wavelet.balchrom, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.chromfi, "Wavelet", "Chromfine", wavelet.chromfi, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.chromco, "Wavelet", "Chromcoarse", wavelet.chromco, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.mergeL, "Wavelet", "MergeL", wavelet.mergeL, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.mergeC, "Wavelet", "MergeC", wavelet.mergeC, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.softrad, "Wavelet", "Softrad", wavelet.softrad, keyFile);
@@ -6555,6 +6564,9 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "CBbluehigh", pedited, wavelet.bluehigh, pedited->wavelet.bluehigh);
assignFromKeyfile(keyFile, "Wavelet", "CBbluemed", pedited, wavelet.bluemed, pedited->wavelet.bluemed);
assignFromKeyfile(keyFile, "Wavelet", "CBbluelow", pedited, wavelet.bluelow, pedited->wavelet.bluelow);
+ assignFromKeyfile(keyFile, "Wavelet", "Balchrom", pedited, wavelet.balchrom, pedited->wavelet.balchrom);
+ assignFromKeyfile(keyFile, "Wavelet", "Chromfine", pedited, wavelet.chromfi, pedited->wavelet.chromfi);
+ assignFromKeyfile(keyFile, "Wavelet", "Chromcoarse", pedited, wavelet.chromco, pedited->wavelet.chromco);
assignFromKeyfile(keyFile, "Wavelet", "MergeL", pedited, wavelet.mergeL, pedited->wavelet.mergeL);
assignFromKeyfile(keyFile, "Wavelet", "MergeC", pedited, wavelet.mergeC, pedited->wavelet.mergeC);
assignFromKeyfile(keyFile, "Wavelet", "Softrad", pedited, wavelet.softrad, pedited->wavelet.softrad);
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 66c37edf4..4a04f9028 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -1673,6 +1673,9 @@ struct WaveletParams {
int bluemed;
int greenhigh;
int bluehigh;
+ double balchrom;
+ double chromfi;
+ double chromco;
double mergeL;
double mergeC;
double softrad;
diff --git a/rtgui/crop.cc b/rtgui/crop.cc
index d9d496523..f092f07a5 100644
--- a/rtgui/crop.cc
+++ b/rtgui/crop.cc
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
*/
+#include
+
#include "crop.h"
#include "options.h"
@@ -46,39 +48,82 @@ inline void get_custom_ratio(int w, int h, double &rw, double &rh)
} // namespace
+class Crop::CropRatios final
+{
+public:
+ CropRatios() :
+ ratios{
+ {M("GENERAL_ASIMAGE"), 0.0},
+ {M("GENERAL_CURRENT"), -1.0},
+ {"3:2", 3.0 / 2.0}, // L1.5, P0.666...
+ {"4:3", 4.0 / 3.0}, // L1.333..., P0.75
+ {"16:9", 16.0 / 9.0}, // L1.777..., P0.5625
+ {"16:10", 16.0 / 10.0}, // L1.6, P0.625
+ {"1:1", 1.0 / 1.0}, // L1, P1
+ {"2:1", 2.0 / 1.0}, // L2, P0.5
+ {"3:1", 3.0 / 1.0}, // L3, P0.333...
+ {"4:1", 4.0 / 1.0}, // L4, P0.25
+ {"5:1", 5.0 / 1.0}, // L5, P0.2
+ {"6:1", 6.0 / 1.0}, // L6, P0.1666...
+ {"7:1", 7.0 / 1.0}, // L7, P0.142...
+ {"4:5", 4.0 / 5.0}, // L1.25, P0.8
+ {"5:7", 5.0 / 7.0}, // L1.4, P0.714...
+ {"6:7", 6.0 / 7.0}, // L1.166..., P0.857...
+ {"6:17", 6.0 / 17.0}, // L2.833..., P0.352...
+ {"24:65 - XPAN", 24.0 / 65.0}, // L2.708..., P0.369...
+ {"1.414 - DIN EN ISO 216", 1.414}, // L1.414, P0.707...
+ {"3.5:5", 3.5 / 5.0}, // L1.428..., P0.7
+ {"8.5:11 - US Letter", 8.5 / 11.0}, // L1.294..., P0.772...
+ {"9.5:12", 9.5 / 12.0}, // L1.263..., P0.791...
+ {"10:12", 10.0 / 12.0}, // L1.2, P0.833...
+ {"11:14", 11.0 / 14.0}, // L1.272..., P0.785...
+ {"11:17 - Tabloid", 11.0 / 17.0}, // L1.545..., P0.647...
+ {"13:19", 13.0 / 19.0}, // L1.461..., P0.684...
+ {"17:22", 17.0 / 22.0}, // L1.294..., P0.772...
+ {"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777...
+ {"64:27", 64.0 / 27.0}, // L2.370..., P0.421...
+ }
+ {
+ }
+
+ std::vector getLabels() const
+ {
+ std::vector res;
+
+ res.reserve(ratios.size());
+
+ for (const auto& ratio : ratios) {
+ res.push_back(ratio.label);
+ }
+
+ return res;
+ }
+
+ double getValue(std::size_t index) const
+ {
+ return
+ index < ratios.size()
+ ? ratios[index].value
+ : ratios[0].value;
+ }
+
+ void updateCurrentRatio(double value)
+ {
+ ratios[1].value = value;
+ }
+
+private:
+ struct CropRatio {
+ Glib::ustring label;
+ double value;
+ };
+
+ std::vector ratios;
+};
+
Crop::Crop():
FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true),
- crop_ratios{
- {M("GENERAL_ASIMAGE"), 0.0},
- {M("GENERAL_CURRENT"), -1.0},
- {"3:2", 3.0 / 2.0}, // L1.5, P0.666...
- {"4:3", 4.0 / 3.0}, // L1.333..., P0.75
- {"16:9", 16.0 / 9.0}, // L1.777..., P0.5625
- {"16:10", 16.0 / 10.0}, // L1.6, P0.625
- {"1:1", 1.0 / 1.0}, // L1, P1
- {"2:1", 2.0 / 1.0}, // L2, P0.5
- {"3:1", 3.0 / 1.0}, // L3, P0.333...
- {"4:1", 4.0 / 1.0}, // L4, P0.25
- {"5:1", 5.0 / 1.0}, // L5, P0.2
- {"6:1", 6.0 / 1.0}, // L6, P0.1666...
- {"7:1", 7.0 / 1.0}, // L7, P0.142...
- {"4:5", 4.0 / 5.0}, // L1.25, P0.8
- {"5:7", 5.0 / 7.0}, // L1.4, P0.714...
- {"6:7", 6.0 / 7.0}, // L1.166..., P0.857...
- {"6:17", 6.0 / 17.0}, // L2.833..., P0.352...
- {"24:65 - XPAN", 24.0 / 65.0}, // L2.708..., P0.369...
- {"1.414 - DIN EN ISO 216", 1.414}, // L1.414, P0.707...
- {"3.5:5", 3.5 / 5.0}, // L1.428..., P0.7
- {"8.5:11 - US Letter", 8.5 / 11.0}, // L1.294..., P0.772...
- {"9.5:12", 9.5 / 12.0}, // L1.263..., P0.791...
- {"10:12", 10.0 / 12.0}, // L1.2, P0.833...
- {"11:14", 11.0 / 14.0}, // L1.272..., P0.785...
- {"11:17 - Tabloid", 11.0 / 17.0}, // L1.545..., P0.647...
- {"13:19", 13.0 / 19.0}, // L1.461..., P0.684...
- {"17:22", 17.0 / 22.0}, // L1.294..., P0.772...
- {"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777...
- {"64:27", 64.0 / 27.0}, // L2.370..., P0.421...
- },
+ crop_ratios(new CropRatios),
opt(0),
wDirty(true),
hDirty(true),
@@ -229,8 +274,8 @@ Crop::Crop():
// ppigrid END
// Populate the combobox
- for (const auto& crop_ratio : crop_ratios) {
- ratio->append (crop_ratio.label);
+ for (const auto& label : crop_ratios->getLabels()) {
+ ratio->append (label);
}
ratio->set_active (0);
@@ -354,7 +399,10 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited)
setDimensions (pp->crop.x + pp->crop.w, pp->crop.y + pp->crop.h);
}
- const bool flip_orientation = pp->crop.fixratio && crop_ratios[ratio->get_active_row_number()].value > 0 && crop_ratios[ratio->get_active_row_number()].value < 1.0;
+ const bool flip_orientation =
+ pp->crop.fixratio
+ && crop_ratios->getValue(ratio->get_active_row_number()) > 0
+ && crop_ratios->getValue(ratio->get_active_row_number()) < 1.0;
if (pp->crop.orientation == "Landscape") {
orientation->set_active (flip_orientation ? 1 : 0);
@@ -469,7 +517,10 @@ void Crop::write (ProcParams* pp, ParamsEdited* pedited)
}
// for historical reasons we store orientation different if ratio is written as 2:3 instead of 3:2, but in GUI 'landscape' is always long side horizontal regardless of the ratio is written short or long side first.
- const bool flip_orientation = fixr->get_active() && crop_ratios[ratio->get_active_row_number()].value > 0 && crop_ratios[ratio->get_active_row_number()].value < 1.0;
+ const bool flip_orientation =
+ fixr->get_active()
+ && crop_ratios->getValue(ratio->get_active_row_number()) > 0
+ && crop_ratios->getValue(ratio->get_active_row_number()) < 1.0;
if (orientation->get_active_row_number() == 0) {
pp->crop.orientation = flip_orientation ? "Portrait" : "Landscape";
@@ -1501,7 +1552,7 @@ double Crop::getRatio () const
return r;
}
- r = crop_ratios[ratio->get_active_row_number()].value;
+ r = crop_ratios->getValue(ratio->get_active_row_number());
if (!r) {
r = maxh <= maxw ? float(maxh)/float(maxw) : float(maxw)/float(maxh);
}
@@ -1539,5 +1590,5 @@ void Crop::updateCurrentRatio()
double rw, rh;
get_custom_ratio(w->get_value(), h->get_value(), rw, rh);
customRatioLabel->set_text(Glib::ustring::compose("%1:%2", rw, rh));
- crop_ratios[1].value = double(w->get_value())/double(h->get_value());
+ crop_ratios->updateCurrentRatio(static_cast(w->get_value()) / static_cast(h->get_value()));
}
diff --git a/rtgui/crop.h b/rtgui/crop.h
index b9221a803..c6636b917 100644
--- a/rtgui/crop.h
+++ b/rtgui/crop.h
@@ -18,7 +18,7 @@
*/
#pragma once
-#include
+#include
#include
@@ -91,16 +91,13 @@ public:
void rotateCrop (int deg, bool hflip, bool vflip);
private:
- struct CropRatio {
- Glib::ustring label;
- double value;
- };
-
- std::vector crop_ratios;
+ class CropRatios;
void adjustCropToRatio();
void updateCurrentRatio();
+ const std::unique_ptr crop_ratios;
+
Gtk::CheckButton* fixr;
MyComboBoxText* ratio;
MyComboBoxText* orientation;
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 483539afd..e9e05b45b 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -496,6 +496,9 @@ void ParamsEdited::set(bool v)
wavelet.bluemed = v;
wavelet.bluelow = v;
wavelet.lipst = v;
+ wavelet.balchrom = v;
+ wavelet.chromfi = v;
+ wavelet.chromco = v;
wavelet.mergeL = v;
wavelet.mergeC = v;
wavelet.softrad = v;
@@ -1555,6 +1558,9 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.bluelow = wavelet.bluelow && p.wavelet.bluelow == other.wavelet.bluelow;
wavelet.lipst = wavelet.lipst && p.wavelet.lipst == other.wavelet.lipst;
wavelet.bluehigh = wavelet.bluehigh && p.wavelet.bluehigh == other.wavelet.bluehigh;
+ wavelet.balchrom = wavelet.balchrom && p.wavelet.balchrom == other.wavelet.balchrom;
+ wavelet.chromfi = wavelet.chromfi && p.wavelet.chromfi == other.wavelet.chromfi;
+ wavelet.chromco = wavelet.chromco && p.wavelet.chromco == other.wavelet.chromco;
wavelet.mergeL = wavelet.mergeL && p.wavelet.mergeL == other.wavelet.mergeL;
wavelet.mergeC = wavelet.mergeC && p.wavelet.mergeC == other.wavelet.mergeC;
wavelet.softrad = wavelet.softrad && p.wavelet.softrad == other.wavelet.softrad;
@@ -5068,6 +5074,18 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.bluelow = mods.wavelet.bluelow;
}
+ if (wavelet.balchrom) {
+ toEdit.wavelet.balchrom = mods.wavelet.balchrom;
+ }
+
+ if (wavelet.chromfi) {
+ toEdit.wavelet.chromfi = mods.wavelet.chromfi;
+ }
+
+ if (wavelet.chromco) {
+ toEdit.wavelet.chromco = mods.wavelet.chromco;
+ }
+
if (wavelet.mergeL) {
toEdit.wavelet.mergeL = mods.wavelet.mergeL;
}
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index f3594cb4e..14265a0f8 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -1027,6 +1027,9 @@ struct WaveletParamsEdited {
bool bluemed;
bool greenhigh;
bool bluehigh;
+ bool balchrom;
+ bool chromfi;
+ bool chromco;
bool mergeL;
bool mergeC;
bool softrad;
diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc
index 5d2de1a02..bc99d0d57 100644
--- a/rtgui/wavelet.cc
+++ b/rtgui/wavelet.cc
@@ -130,6 +130,9 @@ Wavelet::Wavelet() :
edgedetectthr2(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECTTHR2"), -10, 100, 1, 0))),
edgesensi(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGESENSI"), 0, 100, 1, 60))),
edgeampli(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEAMPLI"), 0, 100, 1, 10))),
+ balchrom(Gtk::manage(new Adjuster(M("TP_WAVELET_BALCHROM"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-red-small.png"))))),
+ chromfi(Gtk::manage(new Adjuster(M("TP_WAVELET_CHROMFI"), 0, 100, 1, 0))),
+ chromco(Gtk::manage(new Adjuster(M("TP_WAVELET_CHROMCO"), 0, 100, 1, 0))),
mergeL(Gtk::manage(new Adjuster(M("TP_WAVELET_MERGEL"), -50, 100, 1, 40))),
mergeC(Gtk::manage(new Adjuster(M("TP_WAVELET_MERGEC"), -50, 100, 1, 20))),
softrad(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 100., 0.5, 0.))),
@@ -157,6 +160,7 @@ Wavelet::Wavelet() :
contFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_CONTFRAME")))),
blurFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_BLURFRAME")))),
chromaFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_CHROMAFRAME")))),
+ chroFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_CHROFRAME")))),
wavLabels(Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER))),
labmC(Gtk::manage(new Gtk::Label(M("TP_WAVELET_CTYPE") + ":"))),
labmNP(Gtk::manage(new Gtk::Label(M("TP_WAVELET_NPTYPE") + ":"))),
@@ -179,6 +183,9 @@ Wavelet::Wavelet() :
auto m = ProcEventMapper::getInstance();
EvWavenaclari = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCLARI");
EvWavushamet = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVUSHAMET");
+ EvWavbalchrom = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVBALCHROM");
+ EvWavchromfi = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCHROMFI");
+ EvWavchromco = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCHROMCO");
EvWavmergeL = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVMERGEL");
EvWavmergeC = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVMERGEC");
EvWavsoftrad = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSOFTRAD");
@@ -523,6 +530,19 @@ Wavelet::Wavelet() :
noiseBox->pack_start(*level2noise, Gtk::PACK_SHRINK, 0);
noiseBox->pack_start(*level3noise, Gtk::PACK_SHRINK, 0);
+ balchrom->setAdjusterListener(this);
+ chromfi->setAdjusterListener(this);
+ chromco->setAdjusterListener(this);
+
+ chroFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const chroBox = Gtk::manage(new ToolParamBlock());
+ chroBox->pack_start(*balchrom);
+ chroBox->pack_start(*chromfi);
+ chroBox->pack_start(*chromco);
+ chroFrame->add(*chroBox);
+// noiseBox->pack_start(*chroFrame);
+
+
//Clarity
mergeL->setAdjusterListener(this);
mergeC->setAdjusterListener(this);
@@ -1383,6 +1403,9 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
softrad->setValue(pp->wavelet.softrad);
softradend->setValue(pp->wavelet.softradend);
+ balchrom->setValue(pp->wavelet.balchrom);
+ chromfi->setValue(pp->wavelet.chromfi);
+ chromco->setValue(pp->wavelet.chromco);
level0noise->setValue(pp->wavelet.level0noise);
level1noise->setValue(pp->wavelet.level1noise);
level2noise->setValue(pp->wavelet.level2noise);
@@ -1528,6 +1551,10 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
softrad->setEditedState(pedited->wavelet.softrad ? Edited : UnEdited);
softradend->setEditedState(pedited->wavelet.softradend ? Edited : UnEdited);
+ balchrom->setEditedState(pedited->wavelet.balchrom ? Edited : UnEdited);
+ chromfi->setEditedState(pedited->wavelet.chromfi ? Edited : UnEdited);
+ chromco->setEditedState(pedited->wavelet.chromco ? Edited : UnEdited);
+
median->set_inconsistent(!pedited->wavelet.median);
medianlev->set_inconsistent(!pedited->wavelet.medianlev);
linkedg->set_inconsistent(!pedited->wavelet.linkedg);
@@ -1746,6 +1773,9 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.satlev = satlev->getValue ();
pp->wavelet.strength = (int) strength->getValue();
pp->wavelet.balance = (int) balance->getValue();
+ pp->wavelet.balchrom = balchrom->getValue();
+ pp->wavelet.chromfi = chromfi->getValue();
+ pp->wavelet.chromco = chromco->getValue();
pp->wavelet.greenlow = greenlow->getValue();
pp->wavelet.bluelow = bluelow->getValue();
@@ -1865,6 +1895,9 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.bluemed = bluemed->getEditedState();
pedited->wavelet.greenhigh = greenhigh->getEditedState();
pedited->wavelet.bluehigh = bluehigh->getEditedState();
+ pedited->wavelet.balchrom = balchrom->getEditedState();
+ pedited->wavelet.chromfi = chromfi->getEditedState();
+ pedited->wavelet.chromco = chromco->getEditedState();
pedited->wavelet.mergeL = mergeL->getEditedState();
pedited->wavelet.mergeC = mergeC->getEditedState();
pedited->wavelet.softrad = softrad->getEditedState();
@@ -2096,6 +2129,9 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
level1noise->setDefault (defParams->wavelet.level1noise);
level2noise->setDefault (defParams->wavelet.level2noise);
level3noise->setDefault (defParams->wavelet.level3noise);
+ balchrom->setDefault(defParams->wavelet.balchrom);
+ chromfi->setDefault(defParams->wavelet.chromfi);
+ chromco->setDefault(defParams->wavelet.chromco);
greenlow->setDefault(defParams->wavelet.greenlow);
bluelow->setDefault(defParams->wavelet.bluelow);
@@ -2119,6 +2155,9 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
mergeC->setDefaultEditedState(pedited->wavelet.mergeC ? Edited : UnEdited);
softrad->setDefaultEditedState(pedited->wavelet.softrad ? Edited : UnEdited);
softradend->setDefaultEditedState(pedited->wavelet.softradend ? Edited : UnEdited);
+ balchrom->setDefaultEditedState(pedited->wavelet.balchrom ? Edited : UnEdited);
+ chromfi->setDefaultEditedState(pedited->wavelet.chromfi ? Edited : UnEdited);
+ chromco->setDefaultEditedState(pedited->wavelet.chromco ? Edited : UnEdited);
sigma->setDefault(defParams->wavelet.sigma);
offset->setDefault(defParams->wavelet.offset);
@@ -2912,6 +2951,12 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval)
listener->panelChanged(EvWavgreenhigh, greenhigh->getTextValue());
} else if (a == bluehigh) {
listener->panelChanged(EvWavbluehigh, bluehigh->getTextValue());
+ } else if (a == balchrom) {
+ listener->panelChanged(EvWavbalchrom, balchrom->getTextValue());
+ } else if (a == chromfi) {
+ listener->panelChanged(EvWavchromfi, chromfi->getTextValue());
+ } else if (a == chromco) {
+ listener->panelChanged(EvWavchromco, chromco->getTextValue());
} else if (a == mergeL) {
listener->panelChanged(EvWavmergeL, mergeL->getTextValue());
} else if (a == mergeC) {
diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h
index b73339973..07d2432ac 100644
--- a/rtgui/wavelet.h
+++ b/rtgui/wavelet.h
@@ -70,6 +70,9 @@ public:
private:
rtengine::ProcEvent EvWavenaclari;
rtengine::ProcEvent EvWavushamet;
+ rtengine::ProcEvent EvWavbalchrom;
+ rtengine::ProcEvent EvWavchromfi;
+ rtengine::ProcEvent EvWavchromco;
rtengine::ProcEvent EvWavmergeL;
rtengine::ProcEvent EvWavmergeC;
rtengine::ProcEvent EvWavsoftrad;
@@ -241,6 +244,9 @@ private:
Adjuster* const edgedetectthr2;
Adjuster* const edgesensi;
Adjuster* const edgeampli;
+ Adjuster* const balchrom;
+ Adjuster* const chromfi;
+ Adjuster* const chromco;
Adjuster* const mergeL;
Adjuster* const mergeC;
Adjuster* const softrad;
@@ -285,6 +291,7 @@ private:
Gtk::Frame* const contFrame;
Gtk::Frame* const blurFrame;
Gtk::Frame* const chromaFrame;
+ Gtk::Frame* const chroFrame;
Gtk::Label* const wavLabels;
Gtk::Label* const labmC;