diff --git a/rtdata/languages/default b/rtdata/languages/default
index 3dc8abe67..404c78be0 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -1221,8 +1221,14 @@ HISTORY_MSG_WAVSIGMA;Sigma
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;Maximum blur
HISTORY_MSG_WAVOLDSH;Old algorithm
HISTORY_MSG_WAVOFFSET;Offset
+HISTORY_MSG_BLSHAPE;Blur by level
+HISTORY_MSG_WAVBL;Blur levels
+HISTORY_MSG_BLURWAV;Blur luminance
+HISTORY_MSG_BLURCWAV;Blur chroma
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -3034,6 +3040,9 @@ TP_WAVELET_BALCHRO_TOOLTIP;If enabled, the 'Contrast balance' curve or slider al
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;Maximum Blur
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
@@ -3046,6 +3055,7 @@ TP_WAVELET_CHRO;Saturated/pastel threshold
TP_WAVELET_CHROMAFRAME;Chroma
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
TP_WAVELET_CHSL;Sliders
TP_WAVELET_CHTYPE;Chrominance method
TP_WAVELET_CLA;Clarity
@@ -3056,6 +3066,7 @@ TP_WAVELET_COMPGAMMA;Compression gamma
TP_WAVELET_COMPGAMMA_TOOLTIP;Adjusting the gamma of the residual image allows you to equilibrate the data and histogram.
TP_WAVELET_COMPTM;Tone mapping
TP_WAVELET_CONTEDIT;'After' contrast curve
+TP_WAVELET_CONTFRAME;Contrast - Compression
TP_WAVELET_CONTR;Gamut
TP_WAVELET_CONTRA;Contrast
TP_WAVELET_CONTRAST_MINUS;Contrast -
@@ -3143,7 +3154,7 @@ TP_WAVELET_NPLOW;Low
TP_WAVELET_NPNONE;None
TP_WAVELET_NPTYPE;Neighboring pixels
TP_WAVELET_NPTYPE_TOOLTIP;This algorithm uses the proximity of a pixel and eight of its neighbors. If less difference, edges are reinforced.
-TP_WAVELET_OLDSH;Old algorithm using negatives values
+TP_WAVELET_OLDSH;Algorithm using negatives values
TP_WAVELET_OPACITY;Opacity Blue-Yellow
TP_WAVELET_OPACITYW;Contrast balance d/v-h curve
TP_WAVELET_OPACITYWL;Final local contrast
@@ -3154,6 +3165,8 @@ TP_WAVELET_RADIUS;Radius Shadows - Highlight
TP_WAVELET_RE1;Reinforced
TP_WAVELET_RE2;Unchanged
TP_WAVELET_RE3;Reduced
+TP_WAVELET_RESBLUR;Blur Luminance
+TP_WAVELET_RESBLURC;Blur Chroma
TP_WAVELET_RESCHRO;Intensity
TP_WAVELET_RESCON;Shadows
TP_WAVELET_RESCONH;Highlights
@@ -3161,8 +3174,10 @@ TP_WAVELET_RESID;Residual Image
TP_WAVELET_SAT;Saturated chroma
TP_WAVELET_SETTINGS;Wavelet Settings
TP_WAVELET_SHA;Sharp mask
+TP_WAVELET_SHFRAME;Shadows/Highlights
TP_WAVELET_SHOWMASK;Show wavelet 'mask'
-TP_WAVELET_SIGMA;Sigma
+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_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
@@ -3176,23 +3191,27 @@ TP_WAVELET_THRESHOLD;Highlight levels
TP_WAVELET_THRESHOLD2;Shadow levels
TP_WAVELET_THRESHOLD2_TOOLTIP;Only levels between 9 and 9 minus the value will be affected by the shadow luminance range. Other levels will be fully treated. The highest level possible is limited by the highlight level value (9 minus highlight level value).
TP_WAVELET_THRESHOLD_TOOLTIP;Only levels beyond the chosen value will be affected by the highlight luminance range. Other levels will be fully treated. The chosen value here limits the highest possible value of the shadow levels.
+TP_WAVELET_THRESWAV;Balance Threshold
TP_WAVELET_THRH;Highlights threshold
TP_WAVELET_TILESBIG;Big tiles
TP_WAVELET_TILESFULL;Full image
TP_WAVELET_TILESIZE;Tiling method
TP_WAVELET_TILESLIT;Little tiles
TP_WAVELET_TILES_TOOLTIP;Processing the full image leads to better quality and is the recommended option, while using tiles is a fall-back solution for users with little RAM. Refer to RawPedia for memory requirements.
+TP_WAVELET_BL;Blur levels
TP_WAVELET_TMEDGS;Edge stopping
TP_WAVELET_TMSCALE;Scale
TP_WAVELET_TMSTRENGTH;Compression strength
TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image.
-TP_WAVELET_TMTYPE;Compression method
+TP_WAVELET_TMEDGS;Edge stopping
TP_WAVELET_TON;Toning
+TP_WAVELET_TMTYPE;Compression method
TP_WAVELET_USH;None
TP_WAVELET_USHARP;Clarity method
TP_WAVELET_USHARP_TOOLTIP;Origin : the source file is the file before Wavelet.\nWavelet : the source file is the file including wavelet threatment
TP_WAVELET_USH_TOOLTIP;If you select Sharp-mask, wavelet settings will be automatically positioned :\nBackground=black, Process=below, level=3...you can change level between 1 and 4.\n\nIf you select Clarity, wavelet settings will be automatically positioned :\nBackground=residual, Process=above, level=7..you can change level between 5 and 10 and wavelet levels.
TP_WAVELET_WAVOFFSET;Offset
+TP_WAVELET_OFFSET_TOOLTIP;Offset modifies the balance between shadows and highlights.\n High values will amplify the contrast enhancement of the highlights, while low values will amplify the contrast enhancement of the shadows. Along with a low Max. effect value will help you selecting the contrasts that will be enhanced
TP_WBALANCE_AUTO;Auto
TP_WBALANCE_AUTOITCGREEN;Auto iterate temperature correlation
TP_WBALANCE_AUTOOLD;Auto RGB grey
diff --git a/rtengine/camconst.json b/rtengine/camconst.json
index 44e01ea99..8bed22437 100644
--- a/rtengine/camconst.json
+++ b/rtengine/camconst.json
@@ -1296,7 +1296,8 @@ Camera constants:
},
{ // Quality C
- "make_model": [ "FUJIFILM X100V" ],
+ "make_model": [ "FUJIFILM X100V", "FUJIFILM X-T4" ],
+ "dcraw_matrix": [ 13426,-6334,-1177,-4244,12136,2371,-580,1303,5980 ], // DNG_v12.2 D65
"raw_crop": [ 0, 5, 6252, 4140 ]
},
@@ -1388,11 +1389,6 @@ Camera constants:
"raw_crop": [ 0, 5, 6252, 4176]
},
- { // Quality C, only raw crop
- "make_model": [ "FUJIFILM X-T4" ],
- "raw_crop": [ 0, 5, 6252, 4140]
- },
-
{ // Quality B
"make_model": "FUJIFILM X30",
"dcraw_matrix": [ 12328,-5256,-1144,-4469,12927,1675,-87,1291,4351 ], // DNG_v8.7 D65
diff --git a/rtengine/curves.cc b/rtengine/curves.cc
index 614a9e587..d81cb5780 100644
--- a/rtengine/curves.cc
+++ b/rtengine/curves.cc
@@ -3083,6 +3083,41 @@ void WavCurve::Set(const std::vector &curvePoints)
}
}
+Wavblcurve::Wavblcurve() {}
+
+void Wavblcurve::Reset()
+{
+ lutblcurve.reset();
+}
+
+void Wavblcurve::Set(const Curve &pCurve)
+{
+ if (pCurve.isIdentity()) {
+ Reset(); // raise this value if the quality suffers from this number of samples
+ return;
+ }
+
+ lutblcurve(501); // raise this value if the quality suffers from this number of samples
+
+ for (int i = 0; i < 501; i++) {
+ lutblcurve[i] = pCurve.getVal(double(i) / 500.);
+ }
+}
+
+void Wavblcurve::Set(const std::vector &curvePoints)
+{
+ if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
+ FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue(0.);
+ Set(tcurve);
+ } else {
+ Reset();
+ }
+
+}
+
+
+
WavOpacityCurveRG::WavOpacityCurveRG() {}
diff --git a/rtengine/curves.h b/rtengine/curves.h
index acde8ec85..b88c8457b 100644
--- a/rtengine/curves.h
+++ b/rtengine/curves.h
@@ -1429,6 +1429,30 @@ public:
}
};
+class Wavblcurve
+{
+private:
+ LUTf lutblcurve; // 0xffff range
+ void Set(const Curve &pCurve);
+public:
+ virtual ~Wavblcurve() {};
+ Wavblcurve();
+
+ void Reset();
+ // void Set(const std::vector &curvePoints, bool &opautili);
+ void Set(const std::vector &curvePoints);
+ float operator[](float index) const
+ {
+ return lutblcurve[index];
+ }
+
+ operator bool (void) const
+ {
+ return lutblcurve;
+ }
+};
+
+
class WavOpacityCurveRG
{
private:
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index 2e82f979f..6b02be430 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -1352,6 +1352,7 @@ void Crop::update(int todo)
}
WavCurve wavCLVCurve;
+ Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
@@ -1359,7 +1360,7 @@ void Crop::update(int todo)
LUTf wavclCurve;
- params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
LabImage *unshar = nullptr;
Glib::ustring provis;
LabImage *provradius = nullptr;
@@ -1388,7 +1389,7 @@ void Crop::update(int todo)
unshar = new LabImage(labnCrop->W, labnCrop->H);
provis = params.wavelet.CLmethod;
params.wavelet.CLmethod = "all";
- parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
+ parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
unshar->CopyFrom(labnCrop);
params.wavelet.CLmethod = provis;
@@ -1403,7 +1404,8 @@ void Crop::update(int todo)
parent->ipf.softLight(labnCrop, params.softlight);
- parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
+ parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
+
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
WaveParams.expcontrast = procont;
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index a39458243..3ccfc98ef 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -1463,7 +1463,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if ((params->wavelet.enabled)) {
WaveletParams WaveParams = params->wavelet;
- WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ WaveParams.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
int kall = 0;
LabImage *unshar = nullptr;
Glib::ustring provis;
@@ -1492,7 +1492,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
unshar = new LabImage(pW, pH);
provis = params->wavelet.CLmethod;
params->wavelet.CLmethod = "all";
- ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
+ ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
unshar->CopyFrom(nprevl);
@@ -1506,7 +1506,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
WaveParams.expnoise = false;
}
- ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
+ ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
@@ -1518,10 +1518,12 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
WaveParams.expnoise = pronois;
if (WaveParams.softrad > 0.f) {
+
array2D ble(pW, pH);
array2D guid(pW, pH);
Imagefloat *tmpImage = nullptr;
tmpImage = new Imagefloat(pW, pH);
+
#ifdef _OPENMP
#pragma omp parallel for
#endif
@@ -1544,6 +1546,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
tmpImage->b(ir, jr) = Z;
ble[ir][jr] = Y / 32768.f;
}
+
double epsilmax = 0.0001;
double epsilmin = 0.00001;
double aepsil = (epsilmax - epsilmin) / 90.f;
@@ -1569,6 +1572,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
Color::XYZ2Lab(X, Y, Z, L, a, b);
nprevl->L[ir][jr] = L;
}
+
delete tmpImage;
}
@@ -1659,8 +1663,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
*/
if (WaveParams.softrad > 0.f) {
+
delete provradius;
provradius = NULL;
+
}
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index 7f4eab660..d9164425c 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -139,6 +139,7 @@ protected:
NoiseCurve noiseLCurve;
NoiseCurve noiseCCurve;
WavCurve wavCLVCurve;
+ Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index 7a0bff723..77f43bf84 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -2006,8 +2006,8 @@ void ImProcFunctions::moyeqt(Imagefloat* working, float &moyS, float &eqty)
{
BENCHFUN
- int tHh = working->getHeight();
- int tWw = working->getWidth();
+ const int height = working->getHeight();
+ const int width = working->getWidth();
double moy = 0.0;
double sqrs = 0.0;
@@ -2015,17 +2015,17 @@ void ImProcFunctions::moyeqt(Imagefloat* working, float &moyS, float &eqty)
#pragma omp parallel for reduction(+:moy,sqrs) schedule(dynamic,16)
#endif
- for (int i = 0; i < tHh; i++) {
- for (int j = 0; j < tWw; j++) {
- double s = Color::rgb2s (CLIP (working->r (i, j)), CLIP (working->g (i, j)), CLIP (working->b (i, j)));
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ const double s = Color::rgb2s(CLIP(working->r (i, j)), CLIP(working->g (i, j)), CLIP(working->b (i, j)));
moy += s;
sqrs += SQR(s);
}
}
- moy /= (tHh * tWw);
- sqrs /= (tHh * tWw);
- eqty = sqrt(sqrs - SQR(moy));
+ moy /= (height * width);
+ sqrs /= (height * width);
+ eqty = std::sqrt(std::max(sqrs - SQR(moy), 0.0));
moyS = moy;
}
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index 0f6f0d174..fe4db782e 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -66,6 +66,7 @@ class OpacityCurve;
class PipetteBuffer;
class ToneCurve;
class WavCurve;
+class Wavblcurve;
class WavOpacityCurveBY;
class WavOpacityCurveRG;
class WavOpacityCurveW;
@@ -219,6 +220,7 @@ public:
void EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0);
void CompressDR(float *Source, int W_L, int H_L, float Compression, float DetailBoost);
void Compresslevels(float **Source, int W_L, int H_L, float compression, float detailattenuator, float thres, float mean, float maxp, float meanN, float maxN, float madL);
+ void Compresslevels2(float **Source, int W_L, int H_L, float compression, float detailattenuator, float thres, float mean, float maxp, float meanN, float maxN, float madL);
void ContrastResid(float * WavCoeffs_L0, struct cont_params &cp, int W_L, int H_L, float max0, float min0);
void EPDToneMap(LabImage *lab, unsigned int Iterates = 0, int skip = 1);
@@ -367,13 +369,13 @@ public:
void Tile_calc(int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip);
- void ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, const LUTf &wavclCurve, int skip);
+ void ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const Wavblcurve & wavblcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, const LUTf &wavclCurve, int skip);
- void WaveletcontAllL(LabImage * lab, float **varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_L,
+ void WaveletcontAllL(LabImage * lab, float **varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_L, const Wavblcurve & wavblcurve,
struct cont_params &cp, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili);
void WaveletcontAllLfinal(const wavelet_decomposition &WaveletCoeffs_L, const cont_params &cp, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL);
- void WaveletcontAllAB(LabImage * lab, float **varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_a, const WavOpacityCurveW & waOpacityCurveW,
- struct cont_params &cp, const bool useChannelA);
+ void WaveletcontAllAB(LabImage * lab, float **varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_a, const Wavblcurve & wavblcurve, const WavOpacityCurveW & waOpacityCurveW,
+ struct cont_params &cp, const bool useChannelA, int skip);
void WaveletAandBAllAB(const wavelet_decomposition &WaveletCoeffs_a, const wavelet_decomposition &WaveletCoeffs_b,
const cont_params &cp, FlatCurve* hhcurve, bool hhutili);
void ContAllL(float **koeLi, float *maxkoeLi, bool lipschitz, int maxlvl, LabImage * lab, float **varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp,
@@ -392,6 +394,7 @@ public:
// void calckoe(float ** WavCoeffs_LL, const cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr);
// void calckoe(float ** WavCoeffs_LL, const struct cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr);
void calckoe(float ** WavCoeffs_LL, float gradw, float tloww, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr);
+ void softproc2(const LabImage* bufcolorig, const LabImage* bufcolfin, float rad, int bfh, int bfw, double epsilmax, double epsilmin, float thres, int sk, bool multiThread, int flag);
void Median_Denoise(float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr);
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index e7eca0be7..5f985c617 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -17,7 +17,7 @@
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-// * 2014 - 2019 Jacques Desmis
+// * 2014 - 2019 2020 - Jacques Desmis
// * 2014 Ingo Weyrich
//
@@ -32,7 +32,10 @@
#include "EdgePreservingDecomposition.h"
#include "iccstore.h"
#include "improcfun.h"
+#include "imagefloat.h"
#include "labimage.h"
+#include "gauss.h"
+#include "boxblur.h"
#include "LUT.h"
#include "median.h"
#include "opthelper.h"
@@ -56,11 +59,15 @@ struct cont_params {
float sigm;
int chrom;
int chro;
+ float chrwav;
int contrast;
float th;
float thH;
float conres;
float conresH;
+ float blurres;
+ float blurcres;
+ float bluwav;
float radius;
float chrores;
bool oldsh;
@@ -124,6 +131,7 @@ struct cont_params {
bool finena;
bool toningena;
bool noiseena;
+ bool blena;
int maxilev;
float edgsens;
float edgampl;
@@ -134,7 +142,7 @@ struct cont_params {
int wavNestedLevels = 1;
-void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, const LUTf &wavclCurve, int skip)
+void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const Wavblcurve & wavblcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, const LUTf &wavclCurve, int skip)
{
@@ -204,6 +212,8 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.finena = params->wavelet.expfinal;
cp.toningena = params->wavelet.exptoning;
cp.noiseena = params->wavelet.expnoise;
+ cp.blena = params->wavelet.expbl;
+ cp.chrwav = 0.01f * params->wavelet.chrwav;
if (params->wavelet.Backmethod == "black") {
cp.backm = 0;
@@ -360,7 +370,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
-// if(settings->verbose) printf("Wav mul 0=%f 1=%f 2=%f 3=%f 4=%f 5=%f 6=%f 7=%f 8=%f 9=%f\n",cp.mul[0],cp.mul[1],cp.mul[2],cp.mul[3],cp.mul[4],cp.mul[5],cp.mul[6],cp.mul[7],cp.mul[8],cp.mul[9]);
for (int sc = 0; sc < 9; sc++) { //reduce strength if zoom < 100% for chroma and tuning
if (sc == 0) {
if (scaleskip[sc] < 1.f) {
@@ -389,6 +398,9 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.radius = waparams.radius;
cp.chrores = waparams.reschro;
cp.oldsh = waparams.oldsh;
+ cp.blurres = waparams.resblur;
+ cp.blurcres = waparams.resblurc;
+ cp.bluwav = 0.01f * waparams.bluwav;
//cp.hueres=waparams.reshue;
cp.hueres = 2.f;
cp.th = float(waparams.thr);
@@ -414,13 +426,11 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.numlevS = params->wavelet.threshold2;
int maxlevS = 9 - cp.numlevH;
cp.numlevS = rtengine::min(cp.numlevS, maxlevS);
- //printf("levHigh=%d levShad=%d\n",cp.numlevH,cp.numlevS);
//highlight
cp.b_lhl = static_cast(params->wavelet.hllev.getBottomLeft());
cp.t_lhl = static_cast(params->wavelet.hllev.getTopLeft());
cp.b_rhl = static_cast(params->wavelet.hllev.getBottomRight());
cp.t_rhl = static_cast(params->wavelet.hllev.getTopRight());
- //printf("BL=%f TL=%f BR=%f TR=%f\n",cp.b_lhl,cp.t_lhl,cp.b_rhl,cp.t_rhl);
//pastel
cp.b_lpast = static_cast(params->wavelet.pastlev.getBottomLeft());
cp.t_lpast = static_cast(params->wavelet.pastlev.getTopLeft());
@@ -447,7 +457,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.lev3n = static_cast(params->wavelet.level3noise.getTop());
cp.detectedge = params->wavelet.medianlev;
- //printf("low=%f mean=%f sd=%f max=%f\n",cp.edg_low,cp.edg_mean,cp.edg_sd,cp.edg_max);
int minwin = rtengine::min(imwidth, imheight);
int maxlevelcrop = 9;
@@ -476,7 +485,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
maxlevelcrop = 5;
}
- // printf("minwin=%d maxcrop=%d\n",minwin, maxlevelcrop);
int levwav = params->wavelet.thres;
@@ -556,7 +564,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
levwav = rtengine::min(maxlev2, levwav);
- //printf("levwav = %d\n",levwav);
#ifdef _OPENMP
int numthreads = 1;
int maxnumberofthreadsforwavelet = 0;
@@ -583,7 +590,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
maxnumberofthreadsforwavelet = 8;
}
- //printf("maxNRT=%d\n",maxnumberofthreadsforwavelet);
if ((maxnumberofthreadsforwavelet == 6 || maxnumberofthreadsforwavelet == 8) && levwav == 10) {
maxnumberofthreadsforwavelet -= 2;
}
@@ -593,7 +599,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
- //printf("maxthre=%d\n",maxnumberofthreadsforwavelet);
// Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles
@@ -846,7 +851,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];
@@ -880,8 +885,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
Chutili = true;
}
-
- WaveletcontAllL(labco, varhue, varchro, *Ldecomp, cp, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili);
+ WaveletcontAllL(labco, varhue, varchro, *Ldecomp, wavblcurve, cp, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili);
if (cp.val > 0 || ref || contr || cp.diagcurv) { //edge
Evaluate2(*Ldecomp, mean, meanN, sigma, sigmaN, MaxP, MaxN);
@@ -911,59 +915,53 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (!hhutili) { //always a or b
int levwava = levwav;
- // printf("Levwava before: %d\n",levwava);
if (cp.chrores == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
while (levwava > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwava - 1] == 0.f)) || (cp.CHmet != 2 && (levwava == 10 || (!cp.curv || cp.mulC[levwava - 1] == 0.f))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava - 1] == 0.f)) && ((levwava == 10 || (cp.CHSLmet == 1 && cp.mulC[levwava - 1] == 0.f)))) {
levwava--;
}
}
- //printf("Levwava after: %d\n",levwava);
if (levwava > 0) {
const std::unique_ptr adecomp(new wavelet_decomposition(labco->data + datalen, labco->W, labco->H, levwava, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
if (!adecomp->memoryAllocationFailed) {
- WaveletcontAllAB(labco, varhue, varchro, *adecomp, waOpacityCurveW, cp, true);
+ WaveletcontAllAB(labco, varhue, varchro, *adecomp, wavblcurve, waOpacityCurveW, cp, true, skip);
adecomp->reconstruct(labco->data + datalen, cp.strength);
}
}
int levwavb = levwav;
- //printf("Levwavb before: %d\n",levwavb);
if (cp.chrores == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
while (levwavb > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavb - 1] == 0.f)) || (cp.CHmet != 2 && (levwavb == 10 || (!cp.curv || cp.mulC[levwavb - 1] == 0.f))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb - 1] == 0.f)) && ((levwavb == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavb - 1] == 0.f)))) {
levwavb--;
}
}
- // printf("Levwavb after: %d\n",levwavb);
if (levwavb > 0) {
const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavb, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
if (!bdecomp->memoryAllocationFailed) {
- WaveletcontAllAB(labco, varhue, varchro, *bdecomp, waOpacityCurveW, cp, false);
+ WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip);
bdecomp->reconstruct(labco->data + 2 * datalen, cp.strength);
}
}
} else {// a and b
int levwavab = levwav;
- // printf("Levwavab before: %d\n",levwavab);
if (cp.chrores == 0.f && !hhutili && params->wavelet.CLmethod == "all") { // no processing of residual ab => we probably can reduce the number of levels
while (levwavab > 0 && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavab - 1] == 0.f)) || (cp.CHmet != 2 && (levwavab == 10 || (!cp.curv || cp.mulC[levwavab - 1] == 0.f))))) && (!cp.opaRG || levwavab == 10 || (cp.opaRG && cp.mulopaRG[levwavab - 1] == 0.f)) && ((levwavab == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavab - 1] == 0.f)))) {
levwavab--;
}
}
- // printf("Levwavab after: %d\n",levwavab);
if (levwavab > 0) {
const std::unique_ptr adecomp(new wavelet_decomposition(labco->data + datalen, labco->W, labco->H, levwavab, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavab, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
if (!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) {
- WaveletcontAllAB(labco, varhue, varchro, *adecomp, waOpacityCurveW, cp, true);
- WaveletcontAllAB(labco, varhue, varchro, *bdecomp, waOpacityCurveW, cp, false);
+ WaveletcontAllAB(labco, varhue, varchro, *adecomp,wavblcurve, waOpacityCurveW, cp, true, skip);
+ WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip);
WaveletAandBAllAB(*adecomp, *bdecomp, cp, hhCurve, hhutili);
adecomp->reconstruct(labco->data + datalen, cp.strength);
@@ -1237,7 +1235,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 = 5.f;//different fom zero to take into account only data large enough
+ 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
@@ -1289,7 +1287,7 @@ void ImProcFunctions::Sigma(float * RESTRICT DataList, int datalen, float avera
{
int countP = 0, countN = 0;
double variP = 0.0, variN = 0.0; // use double precision for large summations
- float thres = 5.f;//different fom zero to take into account only data large enough
+ float thres = 32.7f;//different fom zero to take into account only data large enough 32.7 = 0.1 in range 0..100
#ifdef _OPENMP
#pragma omp parallel for reduction(+:variP,variN,countP,countN) num_threads(wavNestedLevels) if(wavNestedLevels>1)
@@ -1553,7 +1551,7 @@ void ImProcFunctions::WaveletcontAllLfinal(const wavelet_decomposition &WaveletC
}
-void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_L,
+void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_L, const Wavblcurve & wavblcurve,
struct cont_params &cp, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili)
{
const int maxlvl = WaveletCoeffs_L.maxlevel();
@@ -1614,7 +1612,6 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
- // printf("MAXmax0=%f MINmin0=%f\n",max0,min0);
//tone mapping
if (cp.tonemap && cp.contmet == 2 && cp.resena) {
@@ -1770,7 +1767,25 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
}
+//Blur luma
+ 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];
+ }
+ boxblur(bef, aft, rad, W_L, H_L, false);
+
+ for (int i = 0; i < H_L * W_L; i++) {
+ WavCoeffs_L0[i] = aft[i];
+ }
+
+ delete bef;
+ delete aft;
+ }
+//
#ifdef _OPENMP
#pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
#endif
@@ -1917,6 +1932,15 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
// end
}
+ bool wavcurvecomp = false;//not enable if 0.75
+
+ if (wavblcurve) {
+ for (int i = 0; i < 500; i++) {
+ if (wavblcurve[i] != 0.) {
+ wavcurvecomp = true;
+ }
+ }
+ }
#ifdef _OPENMP
#pragma omp for schedule(dynamic) collapse(2)
@@ -1931,8 +1955,31 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl);
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 && cp.bluwav > 0.f) {
+ float * bef = new float[Wlvl_L * Hlvl_L];
+ float * aft = new float[Wlvl_L * Hlvl_L];
+ for (int co = 0; co < Hlvl_L * Wlvl_L; co++) {
+ bef[co] = WavCoeffs_L[dir][co];
+ }
+ klev = (wavblcurve[lvl * 55.5f]);
+ float lvr = lvl;
+ if(lvr == 0) {
+ lvr = 1;
+ }
+ klev *= cp.bluwav * lvr * 10.f / skip;
+ boxblur(bef, aft, klev, Wlvl_L, Hlvl_L, false);
+
+ for (int co = 0; co < Hlvl_L * Wlvl_L; co++) {
+ WavCoeffs_L[dir][co] = aft[co];
+ }
+
+ delete bef;
+ delete aft;
+ }
}
}
}
@@ -2009,8 +2056,8 @@ void ImProcFunctions::WaveletAandBAllAB(const wavelet_decomposition &WaveletCoef
}
-void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_ab, const WavOpacityCurveW & waOpacityCurveW,
- struct cont_params &cp, const bool useChannelA)
+void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_ab, const Wavblcurve & wavblcurve, const WavOpacityCurveW & waOpacityCurveW,
+ struct cont_params &cp, const bool useChannelA, int skip)
{
int maxlvl = WaveletCoeffs_ab.maxlevel();
@@ -2132,11 +2179,41 @@ 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];
+
+ 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++) {
+ WavCoeffs_ab0[i] = aft[i];
+ }
+
+ delete bef;
+ delete aft;
+ }
+
+
+ bool wavcurvecomp = false;//not enable if 0.75
+
+ 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++) {
@@ -2145,6 +2222,33 @@ 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 && cp.bluwav > 0.f) {
+ 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];
+ }
+ klev = (wavblcurve[lvl * 55.5f]);
+ float lvr = lvl;
+ if(lvr == 0) {
+ lvr = 1;
+ }
+
+ klev *= cp.bluwav * cp.chrwav * lvr * 20.f / skip;
+
+ boxblur(bef, aft, klev, Wlvl_ab, Hlvl_ab, false);
+
+ for (int co = 0; co < Hlvl_ab * Wlvl_ab; co++) {
+ WavCoeffs_ab[dir][co] = aft[co];
+ }
+
+ delete bef;
+ delete aft;
+ }
+
+
}
}
@@ -2160,7 +2264,6 @@ void ImProcFunctions::calckoe (float ** WavCoeffs_LL, float gradw, float tloww,
{
int borderL = 2;
-// printf("cpedth=%f\n",cp.eddetthr);
if (tloww < 30.f) {
borderL = 1;
@@ -2482,6 +2585,10 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
scaleskip[sc] = scales[sc] / skip;
}
+ if (settings->verbose) {
+ printf("level=%i mean=%f sigma=%f maxp=%f\n", level, mean[level], sigma[level], MaxP[level]);
+ }
+
constexpr float t_r = 40.f;
constexpr float t_l = 10.f;
constexpr float b_r = 75.f;
@@ -3331,7 +3438,6 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
}
if (cp.bam && cp.diag) {
-//printf("OK Chroma\n");
if (cp.opaW && cp.BAmet == 2) {
int iteration = cp.ite;
int itplus = 7 + iteration;
@@ -3536,4 +3642,192 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
}
}
}
+
+void ImProcFunctions::softproc2(const LabImage* bufcolorig, const LabImage* bufcolfin, float rad, int bfh, int bfw, double epsilmax, double epsilmin, float thres, int sk, bool multiThread, int flag)
+{
+ if (flag == 0) {
+ if (rad > 0.f) {
+ array2D ble(bfw, bfh);
+ array2D guid(bfw, bfh);
+ Imagefloat *tmpImage = nullptr;
+ tmpImage = new Imagefloat(bfw, bfh);
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++)
+ for (int jr = 0; jr < bfw; jr++) {
+
+ float X, Y, Z;
+ float L = bufcolorig->L[ir][jr];
+ float a = bufcolorig->a[ir][jr];
+ float b = bufcolorig->b[ir][jr];
+ Color::Lab2XYZ(L, a, b, X, Y, Z);
+
+ guid[ir][jr] = Y / 32768.f;
+ float La = bufcolfin->L[ir][jr];
+ float aa = bufcolfin->a[ir][jr];
+ float ba = bufcolfin->b[ir][jr];
+ Color::Lab2XYZ(La, aa, ba, X, Y, Z);
+ tmpImage->r(ir, jr) = X;
+ tmpImage->g(ir, jr) = Y;
+ tmpImage->b(ir, jr) = Z;
+
+ ble[ir][jr] = Y / 32768.f;
+ }
+
+ double aepsil = (epsilmax - epsilmin) / 90.f;
+ double bepsil = epsilmax - 100.f * aepsil;
+ double epsil = aepsil * 0.1 * rad + bepsil;
+
+ float blur = 10.f / sk * (thres + 0.8f * rad);
+ rtengine::guidedFilter(guid, ble, ble, blur, epsil, multiThread, 4);
+
+
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++)
+ for (int jr = 0; jr < bfw; jr++) {
+ float X = tmpImage->r(ir, jr);
+ float Y = 32768.f * ble[ir][jr];
+ float Z = tmpImage->b(ir, jr);
+ float L, a, b;
+ Color::XYZ2Lab(X, Y, Z, L, a, b);
+ bufcolfin->L[ir][jr] = L;
+ }
+
+ delete tmpImage;
+ }
+ } else if (flag == 1) {
+ if (rad > 0.f) {
+ array2D ble(bfw, bfh);
+ array2D blechro(bfw, bfh);
+ array2D hue(bfw, bfh);
+ array2D guid(bfw, bfh);
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++)
+ for (int jr = 0; jr < bfw; jr++) {
+// hue[ir][jr] = xatan2f(bufcolfin->b[ir][jr], bufcolfin->a[ir][jr]);
+// float chromah = sqrt(SQR(bufcolfin->b[ir][jr]) + SQR(bufcolfin->a[ir][jr]));
+
+ ble[ir][jr] = (bufcolfin->L[ir][jr]) / 32768.f;
+// blechro[ir][jr] = chromah / 32768.f;
+ guid[ir][jr] = bufcolorig->L[ir][jr] / 32768.f;
+ }
+
+ double aepsil = (epsilmax - epsilmin) / 90.f;
+ double bepsil = epsilmax - 100.f * aepsil;
+ double epsil = aepsil * 0.1 * rad + bepsil;
+
+ if (rad != 0.f) {
+ float blur = rad;
+ blur = blur < 0.f ? -1.f / blur : 1.f + blur;
+ // int r1 = max(int(4 / sk * blur + 0.5), 1);
+ int r2 = max(int(25 / sk * blur + 0.5), 1);
+
+ if (rad < 0.f) {
+ epsil = 0.0001;
+ }
+
+ rtengine::guidedFilter(guid, ble, ble, r2, epsil, multiThread);
+// rtengine::guidedFilter(guid, blechro, blechro, r1, 0.5 * epsil, multiThread);
+ }
+
+
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int ir = 0; ir < bfh; ir++)
+ for (int jr = 0; jr < bfw; jr++) {
+ // float2 sincosval = xsincosf(hue[ir][jr]);
+
+ bufcolfin->L[ir][jr] = 32768.f * ble[ir][jr];
+ // bufcolfin->a[ir][jr] = 32768.f * sincosval.y * blechro[ir][jr];
+ // bufcolfin->b[ir][jr] = 32768.f * sincosval.x * blechro[ir][jr];
+ }
+ }
+
+ }
+}
+
+
+void ImProcFunctions::Compresslevels2(float **Source, int W_L, int H_L, float compression, float detailattenuator, float thres, float mean, float maxp, float meanN, float maxN, float madL)
+{
+ //J.Desmis 12-2019
+
+ float exponent;
+
+ if (detailattenuator > 0.f && detailattenuator < 0.05f) {
+ float betemp = expf(-(2.f - detailattenuator + 0.693147f)) - 1.f; //0.69315 = log(2)
+ exponent = 1.2f * xlogf(-betemp);
+ exponent /= 20.f;
+ } else if (detailattenuator >= 0.05f && detailattenuator < 0.25f) {
+ float betemp = expf(-(2.f - detailattenuator + 0.693147f)) - 1.f;
+ exponent = 1.2f * xlogf(-betemp);
+ exponent /= (-75.f * detailattenuator + 23.75f);
+ } else if (detailattenuator >= 0.25f) {
+ float betemp = expf(-(2.f - detailattenuator + 0.693147f)) - 1.f;
+ exponent = 1.2f * xlogf(-betemp);
+ exponent /= (-2.f * detailattenuator + 5.5f);
+ } else {
+ exponent = (compression - 1.0f) / 20.f;
+ }
+
+ exponent += 1.f;
+
+
+ float ap = (thres - 1.f) / (maxp - mean);
+ float bp = 1.f - ap * mean;
+
+ float a0 = (1.33f * thres - 1.f) / (1.f - mean);
+ float b0 = 1.f - a0 * mean;
+
+ float apn = (thres - 1.f) / (maxN - meanN);
+ float bpn = 1.f - apn * meanN;
+
+ float a0n = (1.33f * thres - 1.f) / (1.f - meanN);
+ float b0n = 1.f - a0n * meanN;
+
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < H_L; y++) {
+ for (int x = 0; x < W_L; x++) {
+ float expone = 1.f;
+
+ if (Source[y][x] >= 0.f) {
+
+ if (Source[y][x] > mean) {
+ expone = 1.f + (exponent - 1.f) * (ap * Source[y][x] + bp);
+ } else {
+ expone = 1.f + (exponent - 1.f) * (a0 * Source[y][x] + b0);
+ }
+
+ Source[y][x] = xexpf(xlogf(Source[y][x] + 0.05f * madL) * expone);
+ } else if (Source[y][x] < 0.f) {
+ if (-Source[y][x] > mean) {
+ expone = 1.f + (exponent - 1.f) * (apn * -Source[y][x] + bpn);
+ } else {
+ expone = 1.f + (exponent - 1.f) * (a0n * -Source[y][x] + b0n);
+ }
+
+ Source[y][x] = -xexpf(xlogf(-Source[y][x] + 0.05f * madL) * expone);
+ }
+ }
+ }
+
+}
+
}
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 08ec4916e..bf5f2a4da 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -2164,6 +2164,18 @@ WaveletParams::WaveletParams() :
0.35,
0.35
},
+ blcurve{
+ static_cast(FCT_MinMaxCPoints),
+0.0, 0.0, 0.0, 0.35, 0.5, 0., 0.35, 0.35, 1.0, 0.0, 0.35, 0.35
+/* 0.0,
+ 0.75,
+ 0.35,
+ 0.35,
+ 1.0,
+ 0.75,
+ 0.35,
+ 0.35*/
+ },
opacityCurveRG{
static_cast(FCT_MinMaxCPoints),
0.0,
@@ -2253,6 +2265,7 @@ WaveletParams::WaveletParams() :
c{},
ch{},
expedge(false),
+ expbl(false),
expresid(false),
expfinal(false),
exptoning(false),
@@ -2278,6 +2291,8 @@ WaveletParams::WaveletParams() :
rescon(0),
resconH(0),
reschro(0),
+ resblur(0),
+ resblurc(0),
tmrs(0),
edgs(1.4),
scale(1.),
@@ -2302,6 +2317,8 @@ WaveletParams::WaveletParams() :
thrH(70),
radius(40),
skinprotect(0.0),
+ chrwav(0.),
+ bluwav(50.0),
hueskin(-5, 25, 170, 120, false),
hueskin2(-260, -250, -130, -140, false),
hllev(50, 75, 100, 98, false),
@@ -2320,6 +2337,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
{
return
ccwcurve == other.ccwcurve
+ && blcurve == other.blcurve
&& opacityCurveRG == other.opacityCurveRG
&& opacityCurveBY == other.opacityCurveBY
&& opacityCurveW == other.opacityCurveW
@@ -2363,6 +2381,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
return true;
}()
&& expedge == other.expedge
+ && expbl == other.expbl
&& expresid == other.expresid
&& expfinal == other.expfinal
&& expclari == other.expclari
@@ -2388,6 +2407,8 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& rescon == other.rescon
&& resconH == other.resconH
&& reschro == other.reschro
+ && resblur == other.resblur
+ && resblurc == other.resblurc
&& tmrs == other.tmrs
&& edgs == other.edgs
&& scale == other.scale
@@ -2412,6 +2433,8 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& thrH == other.thrH
&& radius == other.radius
&& skinprotect == other.skinprotect
+ && chrwav == other.chrwav
+ && bluwav == other.bluwav
&& hueskin == other.hueskin
&& hueskin2 == other.hueskin2
&& hllev == other.hllev
@@ -2432,6 +2455,7 @@ bool WaveletParams::operator !=(const WaveletParams& other) const
void WaveletParams::getCurves(
WavCurve& cCurve,
+ Wavblcurve& tCurve,
WavOpacityCurveRG& opacityCurveLUTRG,
WavOpacityCurveBY& opacityCurveLUTBY,
WavOpacityCurveW& opacityCurveLUTW,
@@ -2439,6 +2463,7 @@ void WaveletParams::getCurves(
) const
{
cCurve.Set(this->ccwcurve);
+ tCurve.Set(this->blcurve);
opacityCurveLUTRG.Set(this->opacityCurveRG);
opacityCurveLUTBY.Set(this->opacityCurveBY);
opacityCurveLUTW.Set(this->opacityCurveW);
@@ -4855,6 +4880,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.expcontrast, "Wavelet", "Expcontrast", wavelet.expcontrast, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expchroma, "Wavelet", "Expchroma", wavelet.expchroma, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expedge, "Wavelet", "Expedge", wavelet.expedge, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.expbl, "Wavelet", "expbl", wavelet.expbl, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expresid, "Wavelet", "Expresid", wavelet.expresid, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expfinal, "Wavelet", "Expfinal", wavelet.expfinal, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.exptoning, "Wavelet", "Exptoning", wavelet.exptoning, keyFile);
@@ -4902,6 +4928,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.TMmethod, "Wavelet", "TMMethod", wavelet.TMmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.chro, "Wavelet", "ChromaLink", wavelet.chro, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.ccwcurve, "Wavelet", "ContrastCurve", wavelet.ccwcurve, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.blcurve, "Wavelet", "blcurve", wavelet.blcurve, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.pastlev, "Wavelet", "Pastlev", wavelet.pastlev.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.satlev, "Wavelet", "Satlev", wavelet.satlev.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveRG, "Wavelet", "OpacityCurveRG", wavelet.opacityCurveRG, keyFile);
@@ -4917,6 +4944,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.cbenab, "Wavelet", "CBenab", wavelet.cbenab, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.lipst, "Wavelet", "Lipst", wavelet.lipst, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.skinprotect, "Wavelet", "Skinprotect", wavelet.skinprotect, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.chrwav, "Wavelet", "chrwav", wavelet.chrwav, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.bluwav, "Wavelet", "bluwav", wavelet.bluwav, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.hueskin, "Wavelet", "Hueskin", wavelet.hueskin.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.edgrad, "Wavelet", "Edgrad", wavelet.edgrad, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.edgval, "Wavelet", "Edgval", wavelet.edgval, keyFile);
@@ -4933,6 +4962,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.thrH, "Wavelet", "ThresholdResidHighLight", wavelet.thrH, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.radius, "Wavelet", "Residualradius", wavelet.radius, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.reschro, "Wavelet", "Residualchroma", wavelet.reschro, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.resblur, "Wavelet", "Residualblur", wavelet.resblur, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.resblurc, "Wavelet", "Residualblurc", wavelet.resblurc, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.tmrs, "Wavelet", "ResidualTM", wavelet.tmrs, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.edgs, "Wavelet", "ResidualEDGS", wavelet.edgs, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.scale, "Wavelet", "ResidualSCALE", wavelet.scale, keyFile);
@@ -6559,6 +6590,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "ResidualcontShadow", pedited, wavelet.rescon, pedited->wavelet.rescon);
assignFromKeyfile(keyFile, "Wavelet", "ResidualcontHighlight", pedited, wavelet.resconH, pedited->wavelet.resconH);
assignFromKeyfile(keyFile, "Wavelet", "Residualchroma", pedited, wavelet.reschro, pedited->wavelet.reschro);
+ assignFromKeyfile(keyFile, "Wavelet", "Residualblur", pedited, wavelet.resblur, pedited->wavelet.resblur);
+ assignFromKeyfile(keyFile, "Wavelet", "Residualblurc", pedited, wavelet.resblurc, pedited->wavelet.resblurc);
assignFromKeyfile(keyFile, "Wavelet", "ResidualTM", pedited, wavelet.tmrs, pedited->wavelet.tmrs);
assignFromKeyfile(keyFile, "Wavelet", "ResidualEDGS", pedited, wavelet.edgs, pedited->wavelet.edgs);
assignFromKeyfile(keyFile, "Wavelet", "ResidualSCALE", pedited, wavelet.scale, pedited->wavelet.scale);
@@ -6583,6 +6616,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "ThresholdResidHighLight", pedited, wavelet.thrH, pedited->wavelet.thrH);
assignFromKeyfile(keyFile, "Wavelet", "Residualradius", pedited, wavelet.radius, pedited->wavelet.radius);
assignFromKeyfile(keyFile, "Wavelet", "ContrastCurve", pedited, wavelet.ccwcurve, pedited->wavelet.ccwcurve);
+ assignFromKeyfile(keyFile, "Wavelet", "blcurve", pedited, wavelet.blcurve, pedited->wavelet.blcurve);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveRG", pedited, wavelet.opacityCurveRG, pedited->wavelet.opacityCurveRG);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveBY", pedited, wavelet.opacityCurveBY, pedited->wavelet.opacityCurveBY);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveW", pedited, wavelet.opacityCurveW, pedited->wavelet.opacityCurveW);
@@ -6724,6 +6758,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
assignFromKeyfile(keyFile, "Wavelet", "Skinprotect", pedited, wavelet.skinprotect, pedited->wavelet.skinprotect);
+ assignFromKeyfile(keyFile, "Wavelet", "chrwav", pedited, wavelet.chrwav, pedited->wavelet.chrwav);
+ assignFromKeyfile(keyFile, "Wavelet", "bluwav", pedited, wavelet.bluwav, pedited->wavelet.bluwav);
assignFromKeyfile(keyFile, "Wavelet", "Expcontrast", pedited, wavelet.expcontrast, pedited->wavelet.expcontrast);
assignFromKeyfile(keyFile, "Wavelet", "Expchroma", pedited, wavelet.expchroma, pedited->wavelet.expchroma);
@@ -6754,6 +6790,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
assignFromKeyfile(keyFile, "Wavelet", "Expedge", pedited, wavelet.expedge, pedited->wavelet.expedge);
+ assignFromKeyfile(keyFile, "Wavelet", "expbl", pedited, wavelet.expbl, pedited->wavelet.expbl);
assignFromKeyfile(keyFile, "Wavelet", "Expresid", pedited, wavelet.expresid, pedited->wavelet.expresid);
assignFromKeyfile(keyFile, "Wavelet", "Expfinal", pedited, wavelet.expfinal, pedited->wavelet.expfinal);
assignFromKeyfile(keyFile, "Wavelet", "Exptoning", pedited, wavelet.exptoning, pedited->wavelet.exptoning);
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 21ce833df..4aaefca26 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -40,6 +40,7 @@ class OpacityCurve;
class RetinexgaintransmissionCurve;
class RetinextransmissionCurve;
class WavCurve;
+class Wavblcurve;
class WavOpacityCurveBY;
class WavOpacityCurveRG;
class WavOpacityCurveW;
@@ -1653,6 +1654,7 @@ private:
struct WaveletParams {
std::vector ccwcurve;
+ std::vector blcurve;
std::vector opacityCurveRG;
std::vector opacityCurveBY;
std::vector opacityCurveW;
@@ -1689,6 +1691,7 @@ struct WaveletParams {
int c[9];
int ch[9];
bool expedge;
+ bool expbl;
bool expresid;
bool expfinal;
bool exptoning;
@@ -1715,6 +1718,8 @@ struct WaveletParams {
int rescon;
int resconH;
int reschro;
+ int resblur;
+ int resblurc;
double tmrs;
double edgs;
double scale;
@@ -1739,6 +1744,8 @@ struct WaveletParams {
int thrH;
int radius;
double skinprotect;
+ double chrwav;
+ double bluwav;
Threshold hueskin;
Threshold hueskin2;
Threshold hllev;
@@ -1758,6 +1765,7 @@ struct WaveletParams {
void getCurves(
WavCurve& cCurve,
+ Wavblcurve& tCurve,
WavOpacityCurveRG&
opacityCurveLUTRG,
WavOpacityCurveBY& opacityCurveLUTBY,
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index c961cc659..91a662945 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -1439,6 +1439,7 @@ private:
bool wavcontlutili = false;
WaveletParams WaveParams = params.wavelet;
WavCurve wavCLVCurve;
+ Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
@@ -1462,7 +1463,7 @@ private:
provradius->CopyFrom(labView);
}
- params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1);
@@ -1470,7 +1471,7 @@ private:
unshar = new LabImage(fw, fh);
provis = params.wavelet.CLmethod;
params.wavelet.CLmethod = "all";
- ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
+ ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
unshar->CopyFrom(labView);
params.wavelet.CLmethod = provis;
@@ -1482,7 +1483,7 @@ private:
WaveParams.expnoise = false;
}
- ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
+ ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
WaveParams.expcontrast = procont;
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 2123b0912..2debe14ac 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -524,6 +524,8 @@ void ParamsEdited::set(bool v)
wavelet.offset = v;
wavelet.resconH = v;
wavelet.reschro = v;
+ wavelet.resblur = v;
+ wavelet.resblurc = v;
wavelet.tmrs = v;
wavelet.edgs = v;
wavelet.scale = v;
@@ -553,11 +555,14 @@ void ParamsEdited::set(bool v)
wavelet.hllev = v;
wavelet.bllev = v;
wavelet.edgcont = v;
+ wavelet.chrwav = v;
+ wavelet.bluwav = v;
wavelet.level0noise = v;
wavelet.level1noise = v;
wavelet.level2noise = v;
wavelet.level3noise = v;
wavelet.ccwcurve = v;
+ wavelet.blcurve = v;
wavelet.opacityCurveRG = v;
wavelet.opacityCurveBY = v;
wavelet.opacityCurveW = v;
@@ -577,6 +582,7 @@ void ParamsEdited::set(bool v)
wavelet.expcontrast = v;
wavelet.expchroma = v;
wavelet.expedge = v;
+ wavelet.expbl = v;
wavelet.expresid = v;
wavelet.exptoning = v;
wavelet.expnoise = v;
@@ -1574,6 +1580,8 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.rescon = wavelet.rescon && p.wavelet.rescon == other.wavelet.rescon;
wavelet.resconH = wavelet.resconH && p.wavelet.resconH == other.wavelet.resconH;
wavelet.reschro = wavelet.reschro && p.wavelet.reschro == other.wavelet.reschro;
+ wavelet.resblur = wavelet.resblur && p.wavelet.resblur == other.wavelet.resblur;
+ wavelet.resblurc = wavelet.resblurc && p.wavelet.resblurc == other.wavelet.resblurc;
wavelet.tmrs = wavelet.tmrs && p.wavelet.tmrs == other.wavelet.tmrs;
wavelet.edgs = wavelet.edgs && p.wavelet.edgs == other.wavelet.edgs;
wavelet.scale = wavelet.scale && p.wavelet.scale == other.wavelet.scale;
@@ -1602,6 +1610,8 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.hllev = wavelet.hllev && p.wavelet.hllev == other.wavelet.hllev;
wavelet.bllev = wavelet.bllev && p.wavelet.bllev == other.wavelet.bllev;
wavelet.edgcont = wavelet.edgcont && p.wavelet.edgcont == other.wavelet.edgcont;
+ wavelet.chrwav = wavelet.chrwav && p.wavelet.chrwav == other.wavelet.chrwav;
+ wavelet.bluwav = wavelet.bluwav && p.wavelet.bluwav == other.wavelet.bluwav;
wavelet.level0noise = wavelet.level0noise && p.wavelet.level0noise == other.wavelet.level0noise;
wavelet.level1noise = wavelet.level1noise && p.wavelet.level1noise == other.wavelet.level1noise;
wavelet.level2noise = wavelet.level2noise && p.wavelet.level2noise == other.wavelet.level2noise;
@@ -1609,6 +1619,7 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.pastlev = wavelet.pastlev && p.wavelet.pastlev == other.wavelet.pastlev;
wavelet.satlev = wavelet.satlev && p.wavelet.satlev == other.wavelet.satlev;
wavelet.ccwcurve = wavelet.ccwcurve && p.wavelet.ccwcurve == other.wavelet.ccwcurve;
+ wavelet.blcurve = wavelet.blcurve && p.wavelet.blcurve == other.wavelet.blcurve;
wavelet.opacityCurveRG = wavelet.opacityCurveRG && p.wavelet.opacityCurveRG == other.wavelet.opacityCurveRG;
wavelet.opacityCurveBY = wavelet.opacityCurveBY && p.wavelet.opacityCurveBY == other.wavelet.opacityCurveBY;
wavelet.opacityCurveW = wavelet.opacityCurveW && p.wavelet.opacityCurveW == other.wavelet.opacityCurveW;
@@ -1621,6 +1632,7 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.expcontrast = wavelet.expcontrast && p.wavelet.expcontrast == other.wavelet.expcontrast;
wavelet.expchroma = wavelet.expchroma && p.wavelet.expchroma == other.wavelet.expchroma;
wavelet.expedge = wavelet.expedge && p.wavelet.expedge == other.wavelet.expedge;
+ wavelet.expbl = wavelet.expbl && p.wavelet.expbl == other.wavelet.expbl;
wavelet.expresid = wavelet.expresid && p.wavelet.expresid == other.wavelet.expresid;
wavelet.expfinal = wavelet.expfinal && p.wavelet.expfinal == other.wavelet.expfinal;
wavelet.exptoning = wavelet.exptoning && p.wavelet.exptoning == other.wavelet.exptoning;
@@ -5184,6 +5196,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.edgcont = mods.wavelet.edgcont;
}
+ if (wavelet.chrwav) {
+ toEdit.wavelet.chrwav = mods.wavelet.chrwav;
+ }
+
+ if (wavelet.bluwav) {
+ toEdit.wavelet.bluwav = mods.wavelet.bluwav;
+ }
+
if (wavelet.level0noise) {
toEdit.wavelet.level0noise = mods.wavelet.level0noise;
}
@@ -5212,6 +5232,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve;
}
+ if (wavelet.blcurve) {
+ toEdit.wavelet.blcurve = mods.wavelet.blcurve;
+ }
+
if (wavelet.opacityCurveRG) {
toEdit.wavelet.opacityCurveRG = mods.wavelet.opacityCurveRG;
}
@@ -5253,6 +5277,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.expedge = mods.wavelet.expedge;
}
+ if (wavelet.expbl) {
+ toEdit.wavelet.expbl = mods.wavelet.expbl;
+ }
+
if (wavelet.expresid) {
toEdit.wavelet.expresid = mods.wavelet.expresid;
}
@@ -5313,6 +5341,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.offset = mods.wavelet.offset;
}
+ if (wavelet.resblur) {
+ toEdit.wavelet.resblur = mods.wavelet.resblur;
+ }
+
+ if (wavelet.resblurc) {
+ toEdit.wavelet.resblurc = mods.wavelet.resblurc;
+ }
+
if (wavelet.resconH) {
toEdit.wavelet.resconH = dontforceSet && options.baBehav[ADDSET_WA_RESCONH] ? toEdit.wavelet.resconH + mods.wavelet.resconH : mods.wavelet.resconH;
}
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index 29579b781..af55896d6 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -971,6 +971,8 @@ struct WaveletParamsEdited {
bool rescon;
bool resconH;
bool reschro;
+ bool resblur;
+ bool resblurc;
bool tmrs;
bool edgs;
bool scale;
@@ -1000,11 +1002,14 @@ struct WaveletParamsEdited {
bool hllev;
bool bllev;
bool edgcont;
+ bool chrwav;
+ bool bluwav;
bool level0noise;
bool level1noise;
bool level2noise;
bool level3noise;
bool ccwcurve;
+ bool blcurve;
bool opacityCurveBY;
bool opacityCurveRG;
bool opacityCurveW;
@@ -1027,6 +1032,7 @@ struct WaveletParamsEdited {
bool expcontrast;
bool expchroma;
bool expedge;
+ bool expbl;
bool expresid;
bool expfinal;
bool exptoning;
diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc
index 956c52738..2e444ff3d 100644
--- a/rtgui/wavelet.cc
+++ b/rtgui/wavelet.cc
@@ -63,6 +63,7 @@ Wavelet::Wavelet() :
FoldableToolPanel(this, "wavelet", M("TP_WAVELET_LABEL"), true, true),
curveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CONTEDIT"))),
CCWcurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CCURVE"))),
+ curveEditorbl(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_BLCURVE"))),
curveEditorRES(new CurveEditorGroup(options.lastWaveletCurvesDir)),
curveEditorGAM(new CurveEditorGroup(options.lastWaveletCurvesDir)),
separatorNeutral(Gtk::manage(new Gtk::HSeparator())),
@@ -81,11 +82,14 @@ Wavelet::Wavelet() :
showmask(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_SHOWMASK")))),
oldsh(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_OLDSH")))),
neutralchButton(Gtk::manage(new Gtk::Button(M("TP_WAVELET_NEUTRAL")))),
- sigma(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMA"), 0.2, 2.5, 0.01, 1.))),
+ sigma(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMA"), 0.05, 2.5, 0.01, 1.))),
offset(Gtk::manage(new Adjuster(M("TP_WAVELET_WAVOFFSET"), 0.33, 1.66, 0.01, 1., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))),
rescon(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCON"), -100, 100, 1, 0))),
resconH(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCONH"), -100, 100, 1, 0))),
reschro(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0))),
+ resblur(Gtk::manage(new Adjuster(M("TP_WAVELET_RESBLUR"), 0, 100, 1, 0))),
+ resblurc(Gtk::manage(new Adjuster(M("TP_WAVELET_RESBLURC"), 0, 100, 1, 0))),
+ bluwav(Gtk::manage(new Adjuster(M("TP_WAVELET_BLUWAV"), 0.0, 100.0, 0.5, 50.))),
tmrs(Gtk::manage(new Adjuster(M("TP_WAVELET_TMSTRENGTH"), -1.0, 2.0, 0.01, 0.0))),
edgs(Gtk::manage(new Adjuster(M("TP_WAVELET_TMEDGS"), 0.1, 4.0, 0.01, 1.4))),
scale(Gtk::manage(new Adjuster(M("TP_WAVELET_TMSCALE"), 0.1, 10.0, 0.01, 1.0))),
@@ -128,6 +132,7 @@ Wavelet::Wavelet() :
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.))),
softradend(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 100., 0.5, 0.))),
+ chrwav(Gtk::manage(new Adjuster(M("TP_WAVELET_CHRWAV"), 0., 100., 0., 0.))),
Lmethod(Gtk::manage(new MyComboBoxText())),
CHmethod(Gtk::manage(new MyComboBoxText())),
CHSLmethod(Gtk::manage(new MyComboBoxText())),
@@ -146,6 +151,9 @@ Wavelet::Wavelet() :
chanMixerHLFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_HIGHLIGHT")))),
chanMixerMidFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_MIDTONES")))),
chanMixerShadowsFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_SHADOWS")))),
+ shFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_SHFRAME")))),
+ 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")))),
wavLabels(Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER))),
labmC(Gtk::manage(new Gtk::Label(M("TP_WAVELET_CTYPE") + ":"))),
@@ -161,6 +169,7 @@ Wavelet::Wavelet() :
expsettings(Gtk::manage(new MyExpander(false, M("TP_WAVELET_SETTINGS")))),
exptoning(Gtk::manage(new MyExpander(true, M("TP_WAVELET_TON")))),
expclari(Gtk::manage(new MyExpander(true, M("TP_WAVELET_CLARI")))),
+ expbl(Gtk::manage(new MyExpander(true, M("TP_WAVELET_BL")))),
neutrHBox(Gtk::manage(new Gtk::HBox())),
usharpHBox(Gtk::manage(new Gtk::HBox()))
{
@@ -177,8 +186,14 @@ Wavelet::Wavelet() :
EvWavscale = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSCALE");
EvWavradius = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVRADIUS");
EvWavsigma = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSIGMA");
+ EvWavenabl = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVBL");
+ EvWavchrwav = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_chrwav");
EvWavoldsh = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVOLDSH");
EvWavoffset = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVOFFSET");
+ EvWavbluwav = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLUWAV");
+ EvWavblshape = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLSHAPE");
+ EvWavresblur = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLURWAV");
+ EvWavresblurc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLURCWAV");
expsettings->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings));
@@ -197,6 +212,9 @@ Wavelet::Wavelet() :
expedge->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expedge));
enableEdgeConn = expedge->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Wavelet::enableToggled), expedge));
+ expbl->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expbl));
+ enabletmConn = expbl->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Wavelet::enableToggled), expbl));
+
expgamut->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expgamut));
expresid->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expresid));
@@ -330,14 +348,18 @@ Wavelet::Wavelet() :
correction[i]->setAdjusterListener(this);
levBox->pack_start(*correction[i]);
}
+ levBox->pack_start(*sup);
+ sup->setAdjusterListener(this);
+ Gtk::HSeparator* const separatorcont = Gtk::manage(new Gtk::HSeparator());
+ levBox->pack_start(*separatorcont);
sigma->setAdjusterListener(this);
levBox->pack_start(*sigma, Gtk::PACK_SHRINK);
offset->setAdjusterListener(this);
levBox->pack_start(*offset, Gtk::PACK_SHRINK);
+ sigma->set_tooltip_text(M("TP_WAVELET_SIGMA_TOOLTIP"));
+ offset->set_tooltip_text(M("TP_WAVELET_OFFSET_TOOLTIP"));
- levBox->pack_start(*sup);
- sup->setAdjusterListener(this);
wavLabels->show();
levBox->pack_start(*wavLabels);
@@ -629,6 +651,30 @@ Wavelet::Wavelet() :
edgBox->pack_start(*ctboxES);
+//Blur Wavelet
+ ToolParamBlock* const blBox = Gtk::manage(new ToolParamBlock());
+
+ curveEditorbl->setCurveListener(this);
+
+ blshape = static_cast(curveEditorbl->addCurve(CT_Flat, "", nullptr, false, false));
+
+ blshape->setIdentityValue(0.);
+ blshape->setResetCurve(FlatCurveType(default_params.blcurve.at(0)), default_params.blcurve);
+ blshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CC_TOOLTIP"));
+
+ curveEditorbl->curveListComplete();
+ curveEditorbl->show();
+
+ blBox->pack_start(*bluwav);
+ bluwav->setAdjusterListener(this);
+ blBox->pack_start(*curveEditorbl, Gtk::PACK_SHRINK, 4);
+
+
+ chrwav->setAdjusterListener(this);
+ blBox->pack_start(*chrwav);
+
+
+
// Gamut
ToolParamBlock* const conBox = Gtk::manage(new ToolParamBlock());
@@ -683,28 +729,43 @@ Wavelet::Wavelet() :
ToolParamBlock* const resBox = Gtk::manage(new ToolParamBlock());
oldsh->set_active(true);
oldshConn = oldsh->signal_toggled().connect(sigc::mem_fun(*this, &Wavelet::oldshToggled));
- resBox->pack_start(*oldsh);
+
rescon->setAdjusterListener(this);
- resBox->pack_start(*rescon, Gtk::PACK_SHRINK);
- resBox->pack_start(*thr);
thr->setAdjusterListener(this);
resconH->setAdjusterListener(this);
- resBox->pack_start(*resconH, Gtk::PACK_SHRINK);
thrH->setAdjusterListener(this);
- resBox->pack_start(*thrH, Gtk::PACK_SHRINK);
radius->setAdjusterListener(this);
- resBox->pack_start(*radius, Gtk::PACK_SHRINK);
+ radius->hide();
+
+ shFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const shBox = Gtk::manage(new ToolParamBlock());
+ shBox->pack_start(*oldsh);
+ shBox->pack_start(*rescon, Gtk::PACK_SHRINK);
+ shBox->pack_start(*thr);
+ shBox->pack_start(*resconH, Gtk::PACK_SHRINK);
+ shBox->pack_start(*thrH, Gtk::PACK_SHRINK);
+ shBox->pack_start(*radius, Gtk::PACK_SHRINK);
+ shFrame->add(*shBox);
+ resBox->pack_start(*shFrame);
+
contrast->set_tooltip_text(M("TP_WAVELET_CONTRA_TOOLTIP"));
contrast->setAdjusterListener(this);
- resBox->pack_start(*contrast); //keep the possibility to reinstall
reschro->setAdjusterListener(this);
+ resblur->setAdjusterListener(this);
+ resblurc->setAdjusterListener(this);
+
+ blurFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const blurBox = Gtk::manage(new ToolParamBlock());
+ blurBox->pack_start(*resblur);
+ blurBox->pack_start(*resblurc);
+ blurFrame->add(*blurBox);
chromaFrame->set_label_align(0.025, 0.5);
ToolParamBlock* const chromaBox = Gtk::manage(new ToolParamBlock());
@@ -717,36 +778,42 @@ Wavelet::Wavelet() :
Gtk::HBox* const ctboxTM = Gtk::manage(new Gtk::HBox());
ctboxTM->pack_start(*labmTM, Gtk::PACK_SHRINK, 1);
- Gtk::HSeparator* const separatorR0 = Gtk::manage(new Gtk::HSeparator());
- resBox->pack_start(*separatorR0, Gtk::PACK_SHRINK, 2);
+// Gtk::HSeparator* const separatorR0 = Gtk::manage(new Gtk::HSeparator());
+// resBox->pack_start(*separatorR0, Gtk::PACK_SHRINK, 2);
TMmethod->append(M("TP_WAVELET_COMPCONT"));
TMmethod->append(M("TP_WAVELET_COMPTM"));
TMmethodconn = TMmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::TMmethodChanged));
ctboxTM->pack_start(*TMmethod);
- resBox->pack_start(*ctboxTM);
tmrs->set_tooltip_text(M("TP_WAVELET_TMSTRENGTH_TOOLTIP"));
- resBox->pack_start(*tmrs);
tmrs->setAdjusterListener(this);
gamma->set_tooltip_text(M("TP_WAVELET_COMPGAMMA_TOOLTIP"));
- resBox->pack_start(*gamma);
gamma->setAdjusterListener(this);
//edgs->set_tooltip_text(M("TP_WAVELET_TMEDGS_TOOLTIP"));
- resBox->pack_start(*edgs);
edgs->setAdjusterListener(this);
//scale->set_tooltip_text(M("TP_WAVELET_TMSCALE_TOOLTIP"));
- resBox->pack_start(*scale);
scale->setAdjusterListener(this);
- Gtk::HSeparator* const separatorR1 = Gtk::manage(new Gtk::HSeparator());
- resBox->pack_start(*separatorR1, Gtk::PACK_SHRINK, 2);
+ contFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const contBox = Gtk::manage(new ToolParamBlock());
+ contBox->pack_start(*contrast); //keep the possibility to reinstall
+ contBox->pack_start(*ctboxTM);
+ contBox->pack_start(*tmrs);
+ contBox->pack_start(*gamma);
+ contBox->pack_start(*edgs);
+ contBox->pack_start(*scale);
+ contFrame->add(*contBox);
+ resBox->pack_start(*contFrame);
+
+// Gtk::HSeparator* const separatorR1 = Gtk::manage(new Gtk::HSeparator());
+// resBox->pack_start(*separatorR1, Gtk::PACK_SHRINK, 2);
hueskin2->set_tooltip_markup(M("TP_WAVELET_HUESKY_TOOLTIP"));
hueskin2->setBgGradient(milestones);
@@ -760,6 +827,7 @@ Wavelet::Wavelet() :
const std::vector milestones3 = makeWholeHueRange();
curveEditorRES->setCurveListener(this);
+ resBox->pack_start(*blurFrame);
resBox->pack_start(*chromaFrame);
hhshape = static_cast(curveEditorRES->addCurve(CT_Flat, M("TP_WAVELET_CURVEEDITOR_HH")));
@@ -948,6 +1016,10 @@ Wavelet::Wavelet() :
expedge->setLevel(2);
pack_start(*expedge);
+ expbl->add(*blBox, false);
+ expbl->setLevel(2);
+ pack_start(*expbl);
+
expclari->add(*clariBox, false);
expclari->setLevel(2);
pack_start(*expclari);
@@ -968,6 +1040,7 @@ Wavelet::~Wavelet()
delete opaCurveEditorG;
delete opacityCurveEditorG;
+ delete curveEditorbl;
delete CCWcurveEditorG;
delete curveEditorRES;
delete curveEditorGAM;
@@ -1186,6 +1259,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
Lmethod->set_active(selectedLevel == -1 ? 4 : selectedLevel);
ccshape->setCurve(pp->wavelet.ccwcurve);
+ blshape->setCurve(pp->wavelet.blcurve);
opacityShapeRG->setCurve(pp->wavelet.opacityCurveRG);
opacityShapeBY->setCurve(pp->wavelet.opacityCurveBY);
opacityShape->setCurve(pp->wavelet.opacityCurveW);
@@ -1196,6 +1270,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
expcontrast->setEnabled(pp->wavelet.expcontrast);
expchroma->setEnabled(pp->wavelet.expchroma);
expedge->setEnabled(pp->wavelet.expedge);
+ expbl->setEnabled(pp->wavelet.expbl);
expresid->setEnabled(pp->wavelet.expresid);
expfinal->setEnabled(pp->wavelet.expfinal);
exptoning->setEnabled(pp->wavelet.exptoning);
@@ -1249,6 +1324,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
rescon->setValue(pp->wavelet.rescon);
resconH->setValue(pp->wavelet.resconH);
reschro->setValue(pp->wavelet.reschro);
+ resblur->setValue(pp->wavelet.resblur);
+ resblurc->setValue(pp->wavelet.resblurc);
tmrs->setValue(pp->wavelet.tmrs);
edgs->setValue(pp->wavelet.edgs);
scale->setValue(pp->wavelet.scale);
@@ -1280,6 +1357,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
pastlev->setValue(pp->wavelet.pastlev);
satlev->setValue(pp->wavelet.satlev);
edgcont->setValue(pp->wavelet.edgcont);
+ chrwav->setValue(pp->wavelet.chrwav);
+ bluwav->setValue(pp->wavelet.bluwav);
greenlow->setValue(pp->wavelet.greenlow);
bluelow->setValue(pp->wavelet.bluelow);
@@ -1377,9 +1456,11 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
set_inconsistent(multiImage && !pedited->wavelet.enabled);
ccshape->setUnChanged(!pedited->wavelet.ccwcurve);
+ blshape->setUnChanged(!pedited->wavelet.blcurve);
expcontrast->set_inconsistent(!pedited->wavelet.expcontrast);
expchroma->set_inconsistent(!pedited->wavelet.expchroma);
expedge->set_inconsistent(!pedited->wavelet.expedge);
+ expbl->set_inconsistent(!pedited->wavelet.expbl);
expresid->set_inconsistent(!pedited->wavelet.expresid);
expfinal->set_inconsistent(!pedited->wavelet.expfinal);
expclari->set_inconsistent(!pedited->wavelet.expclari);
@@ -1402,6 +1483,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
offset->setEditedState(pedited->wavelet.offset ? Edited : UnEdited);
resconH->setEditedState(pedited->wavelet.resconH ? Edited : UnEdited);
reschro->setEditedState(pedited->wavelet.reschro ? Edited : UnEdited);
+ resblur->setEditedState(pedited->wavelet.resblur ? Edited : UnEdited);
+ resblurc->setEditedState(pedited->wavelet.resblurc ? Edited : UnEdited);
tmrs->setEditedState(pedited->wavelet.tmrs ? Edited : UnEdited);
edgs->setEditedState(pedited->wavelet.edgs ? Edited : UnEdited);
scale->setEditedState(pedited->wavelet.scale ? Edited : UnEdited);
@@ -1453,6 +1536,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
satlev->setEditedState(pedited->wavelet.satlev ? Edited : UnEdited);
strength->setEditedState(pedited->wavelet.strength ? Edited : UnEdited);
edgcont->setEditedState(pedited->wavelet.edgcont ? Edited : UnEdited);
+ chrwav->setEditedState(pedited->wavelet.chrwav ? Edited : UnEdited);
+ bluwav->setEditedState(pedited->wavelet.bluwav ? Edited : UnEdited);
level0noise->setEditedState(pedited->wavelet.level0noise ? Edited : UnEdited);
level1noise->setEditedState(pedited->wavelet.level1noise ? Edited : UnEdited);
level2noise->setEditedState(pedited->wavelet.level2noise ? Edited : UnEdited);
@@ -1508,6 +1593,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
//BackmethodUpdateUI();
CLmethodUpdateUI();
lipstUpdateUI();
+ oldshToggled();
//TilesmethodUpdateUI();
//daubcoeffmethodUpdateUI();
//DirmethodUpdateUI();
@@ -1558,6 +1644,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
void Wavelet::setEditProvider(EditDataProvider *provider)
{
ccshape->setEditProvider(provider);
+ blshape->setEditProvider(provider);
opacityShapeRG->setEditProvider(provider);
opacityShapeBY->setEditProvider(provider);
opacityShape->setEditProvider(provider);
@@ -1570,6 +1657,7 @@ void Wavelet::setEditProvider(EditDataProvider *provider)
void Wavelet::autoOpenCurve()
{
ccshape->openIfNonlinear();
+ blshape->openIfNonlinear();
//opacityShapeRG->openIfNonlinear();
//opacityShapeBY->openIfNonlinear();
}
@@ -1587,6 +1675,8 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.rescon = rescon->getValue();
pp->wavelet.resconH = resconH->getValue();
pp->wavelet.reschro = reschro->getValue();
+ pp->wavelet.resblur = resblur->getValue();
+ pp->wavelet.resblurc = resblurc->getValue();
pp->wavelet.tmrs = tmrs->getValue();
pp->wavelet.edgs = edgs->getValue();
pp->wavelet.scale = scale->getValue();
@@ -1622,11 +1712,14 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.hllev = hllev->getValue ();
pp->wavelet.bllev = bllev->getValue ();
pp->wavelet.edgcont = edgcont->getValue ();
+ pp->wavelet.chrwav = chrwav->getValue();
+ pp->wavelet.bluwav = bluwav->getValue();
pp->wavelet.level0noise = level0noise->getValue ();
pp->wavelet.level1noise = level1noise->getValue ();
pp->wavelet.level2noise = level2noise->getValue ();
pp->wavelet.level3noise = level3noise->getValue ();
pp->wavelet.ccwcurve = ccshape->getCurve();
+ pp->wavelet.blcurve = blshape->getCurve();
pp->wavelet.opacityCurveRG = opacityShapeRG->getCurve();
pp->wavelet.opacityCurveBY = opacityShapeBY->getCurve();
pp->wavelet.opacityCurveW = opacityShape->getCurve();
@@ -1651,6 +1744,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.expcontrast = expcontrast->getEnabled();
pp->wavelet.expchroma = expchroma->getEnabled();
pp->wavelet.expedge = expedge->getEnabled();
+ pp->wavelet.expbl = expbl->getEnabled();
pp->wavelet.expresid = expresid->getEnabled();
pp->wavelet.expfinal = expfinal->getEnabled();
pp->wavelet.exptoning = exptoning->getEnabled();
@@ -1700,6 +1794,8 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.rescon = rescon->getEditedState();
pedited->wavelet.resconH = resconH->getEditedState();
pedited->wavelet.reschro = reschro->getEditedState();
+ pedited->wavelet.resblur = resblur->getEditedState();
+ pedited->wavelet.resblurc = resblurc->getEditedState();
pedited->wavelet.tmrs = tmrs->getEditedState();
pedited->wavelet.edgs = edgs->getEditedState();
pedited->wavelet.scale = scale->getEditedState();
@@ -1727,7 +1823,10 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.skinprotect = skinprotect->getEditedState();
pedited->wavelet.hllev = hllev->getEditedState();
pedited->wavelet.ccwcurve = !ccshape->isUnChanged();
+ pedited->wavelet.blcurve = !blshape->isUnChanged();
pedited->wavelet.edgcont = edgcont->getEditedState();
+ pedited->wavelet.chrwav = chrwav->getEditedState();
+ pedited->wavelet.bluwav = bluwav->getEditedState();
pedited->wavelet.level0noise = level0noise->getEditedState();
pedited->wavelet.level1noise = level1noise->getEditedState();
pedited->wavelet.level2noise = level2noise->getEditedState();
@@ -1758,6 +1857,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.expcontrast = !expcontrast->get_inconsistent();
pedited->wavelet.expchroma = !expchroma->get_inconsistent();
pedited->wavelet.expedge = !expedge->get_inconsistent();
+ pedited->wavelet.expbl = !expbl->get_inconsistent();
pedited->wavelet.expresid = !expresid->get_inconsistent();
pedited->wavelet.expfinal = !expfinal->get_inconsistent();
pedited->wavelet.exptoning = !exptoning->get_inconsistent();
@@ -1899,6 +1999,8 @@ void Wavelet::curveChanged(CurveEditor* ce)
if (listener && getEnabled()) {
if (ce == ccshape) {
listener->panelChanged(EvWavCCCurve, M("HISTORY_CUSTOMCURVE"));
+ } else if (ce == blshape) {
+ listener->panelChanged(EvWavblshape, M("HISTORY_CUSTOMCURVE"));
} else if (ce == opacityShapeRG) {
listener->panelChanged(EvWavColor, M("HISTORY_CUSTOMCURVE"));
} else if (ce == opacityShapeBY) {
@@ -1936,6 +2038,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
rescon->setDefault(defParams->wavelet.rescon);
resconH->setDefault(defParams->wavelet.resconH);
reschro->setDefault(defParams->wavelet.reschro);
+ resblur->setDefault(defParams->wavelet.resblur);
+ resblurc->setDefault(defParams->wavelet.resblurc);
tmrs->setDefault(defParams->wavelet.tmrs);
edgs->setDefault(defParams->wavelet.edgs);
scale->setDefault(defParams->wavelet.scale);
@@ -1966,6 +2070,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
pastlev->setDefault (defParams->wavelet.pastlev);
satlev->setDefault (defParams->wavelet.satlev);
edgcont->setDefault (defParams->wavelet.edgcont);
+ chrwav->setDefault(defParams->wavelet.chrwav);
+ bluwav->setDefault(defParams->wavelet.bluwav);
level0noise->setDefault (defParams->wavelet.level0noise);
level1noise->setDefault (defParams->wavelet.level1noise);
level2noise->setDefault (defParams->wavelet.level2noise);
@@ -1999,6 +2105,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
rescon->setDefault(defParams->wavelet.rescon);
resconH->setDefault(defParams->wavelet.resconH);
reschro->setDefault(defParams->wavelet.reschro);
+ resblur->setDefault(defParams->wavelet.resblur);
+ resblurc->setDefault(defParams->wavelet.resblurc);
tmrs->setDefault(defParams->wavelet.tmrs);
edgs->setDefault(defParams->wavelet.edgs);
scale->setDefault(defParams->wavelet.scale);
@@ -2030,6 +2138,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
pastlev->setDefaultEditedState(pedited->wavelet.pastlev ? Edited : UnEdited);
satlev->setDefaultEditedState(pedited->wavelet.satlev ? Edited : UnEdited);
edgcont->setDefaultEditedState(pedited->wavelet.edgcont ? Edited : UnEdited);
+ chrwav->setDefaultEditedState(pedited->wavelet.chrwav ? Edited : UnEdited);
+ bluwav->setDefaultEditedState(pedited->wavelet.bluwav ? Edited : UnEdited);
strength->setDefaultEditedState(pedited->wavelet.strength ? Edited : UnEdited);
balance->setDefaultEditedState(pedited->wavelet.balance ? Edited : UnEdited);
iter->setDefaultEditedState(pedited->wavelet.iter ? Edited : UnEdited);
@@ -2051,6 +2161,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
rescon->setDefaultEditedState(Irrelevant);
resconH->setDefaultEditedState(Irrelevant);
reschro->setDefaultEditedState(Irrelevant);
+ resblur->setDefaultEditedState(Irrelevant);
+ resblurc->setDefaultEditedState(Irrelevant);
tmrs->setDefaultEditedState(Irrelevant);
edgs->setDefaultEditedState(Irrelevant);
scale->setDefaultEditedState(Irrelevant);
@@ -2080,6 +2192,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
hllev->setDefaultEditedState(Irrelevant);
bllev->setDefaultEditedState(Irrelevant);
edgcont->setDefaultEditedState(Irrelevant);
+ chrwav->setDefaultEditedState(Irrelevant);
+ bluwav->setDefaultEditedState(Irrelevant);
level0noise->setDefaultEditedState(Irrelevant);
level1noise->setDefaultEditedState(Irrelevant);
level2noise->setDefaultEditedState(Irrelevant);
@@ -2573,6 +2687,7 @@ void Wavelet::setBatchMode(bool batchMode)
opacityCurveEditorG->setBatchMode(batchMode);
opacityCurveEditorW->setBatchMode(batchMode);
opacityCurveEditorWL->setBatchMode(batchMode);
+ curveEditorbl->setBatchMode(batchMode);
curveEditorRES->setBatchMode(batchMode);
curveEditorGAM->setBatchMode(batchMode);
sigma->showEditedCB();
@@ -2580,6 +2695,8 @@ void Wavelet::setBatchMode(bool batchMode)
rescon->showEditedCB();
resconH->showEditedCB();
reschro->showEditedCB();
+ resblur->showEditedCB();
+ resblurc->showEditedCB();
tmrs->showEditedCB();
edgs->showEditedCB();
scale->showEditedCB();
@@ -2611,6 +2728,8 @@ void Wavelet::setBatchMode(bool batchMode)
pastlev->showEditedCB();
satlev->showEditedCB();
edgcont->showEditedCB();
+ chrwav->showEditedCB();
+ bluwav->showEditedCB();
strength->showEditedCB();
balance->showEditedCB();
iter->showEditedCB();
@@ -2666,6 +2785,10 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval)
listener->panelChanged(EvWavresconH, resconH->getTextValue());
} else if (a == reschro) {
listener->panelChanged(EvWavreschro, reschro->getTextValue());
+ } else if (a == resblur) {
+ listener->panelChanged(EvWavresblur, resblur->getTextValue());
+ } else if (a == resblurc) {
+ listener->panelChanged(EvWavresblurc, resblurc->getTextValue());
} else if (a == tmrs) {
adjusterUpdateUI(a);
listener->panelChanged(EvWavtmrs, tmrs->getTextValue());
@@ -2775,6 +2898,10 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval)
listener->panelChanged(EvWavgreenlow, greenlow->getTextValue());
} else if (a == bluelow) {
listener->panelChanged(EvWavbluelow, bluelow->getTextValue());
+ } else if (a == chrwav) {
+ listener->panelChanged(EvWavchrwav, chrwav->getTextValue());
+ } else if (a == bluwav) {
+ listener->panelChanged(EvWavbluwav, bluwav->getTextValue());
}
if ((a == correction[0] || a == correction[1] || a == correction[2] || a == correction[3] || a == correction[4] || a == correction[5] || a == correction[6] || a == correction[7] || a == correction[8])) {
@@ -3328,6 +3455,7 @@ void Wavelet::foldAllButMe(GdkEventButton* event, MyExpander *expander)
exptoning->set_expanded(exptoning == expander);
expnoise->set_expanded(expnoise == expander);
expedge->set_expanded(expedge == expander);
+ expbl->set_expanded(expbl == expander);
expgamut->set_expanded(expgamut == expander);
expresid->set_expanded(expresid == expander);
expfinal->set_expanded(expfinal == expander);
@@ -3350,6 +3478,8 @@ void Wavelet::enableToggled(MyExpander *expander)
event = EvWavenanoise;
} else if (expander == expedge) {
event = EvWavenaedge;
+ } else if (expander == expbl) {
+ event = EvWavenabl;
} else if (expander == expresid) {
event = EvWavenares;
} else if (expander == expfinal) {
@@ -3412,6 +3542,7 @@ void Wavelet::writeOptions(std::vector &tpOpen)
tpOpen.push_back(exptoning->get_expanded());
tpOpen.push_back(expnoise->get_expanded());
tpOpen.push_back(expedge->get_expanded());
+ tpOpen.push_back(expbl->get_expanded());
tpOpen.push_back(expgamut->get_expanded());
tpOpen.push_back(expresid->get_expanded());
tpOpen.push_back(expfinal->get_expanded());
@@ -3427,6 +3558,7 @@ void Wavelet::updateToolState(const std::vector& tpOpen)
exptoning->set_expanded(false);
expnoise->set_expanded(false);
expedge->set_expanded(false);
+ expbl->set_expanded(false);
expgamut->set_expanded(false);
expresid->set_expanded(false);
expfinal->set_expanded(false);
@@ -3434,17 +3566,18 @@ void Wavelet::updateToolState(const std::vector& tpOpen)
return;
}
- if (tpOpen.size() >= 10) {
+ if (tpOpen.size() >= 11) {
expsettings->set_expanded(tpOpen[0]);
expcontrast->set_expanded(tpOpen[1]);
expchroma->set_expanded(tpOpen[2]);
exptoning->set_expanded(tpOpen[3]);
expnoise->set_expanded(tpOpen[4]);
expedge->set_expanded(tpOpen[5]);
- expgamut->set_expanded(tpOpen[6]);
- expresid->set_expanded(tpOpen[7]);
- expfinal->set_expanded(tpOpen[8]);
- expclari->set_expanded(tpOpen.at(9));
+ expbl->set_expanded(tpOpen[6]);
+ expgamut->set_expanded(tpOpen[7]);
+ expresid->set_expanded(tpOpen[8]);
+ expfinal->set_expanded(tpOpen[9]);
+ expclari->set_expanded(tpOpen[10]);
}
}
diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h
index 94b88fd5c..67a45b5ac 100644
--- a/rtgui/wavelet.h
+++ b/rtgui/wavelet.h
@@ -79,8 +79,14 @@ private:
rtengine::ProcEvent EvWavscale;
rtengine::ProcEvent EvWavradius;
rtengine::ProcEvent EvWavsigma;
+ rtengine::ProcEvent EvWavenabl;
+ rtengine::ProcEvent EvWavchrwav;
rtengine::ProcEvent EvWavoldsh;
rtengine::ProcEvent EvWavoffset;
+ rtengine::ProcEvent EvWavbluwav;
+ rtengine::ProcEvent EvWavblshape;
+ rtengine::ProcEvent EvWavresblur;
+ rtengine::ProcEvent EvWavresblurc;
void foldAllButMe(GdkEventButton* event, MyExpander *expander);
@@ -143,6 +149,7 @@ private:
CurveEditorGroup* const curveEditorG;
CurveEditorGroup* const CCWcurveEditorG;
+ CurveEditorGroup* const curveEditorbl;
CurveEditorGroup* const curveEditorRES;
CurveEditorGroup* const curveEditorGAM;
Gtk::HSeparator* const separatorNeutral;
@@ -161,6 +168,7 @@ private:
DiagonalCurveEditor* clshape;
FlatCurveEditor* ccshape;
+ FlatCurveEditor* blshape;
Gtk::CheckButton* const median;
Gtk::CheckButton* const medianlev;
Gtk::CheckButton* const linkedg;
@@ -179,6 +187,9 @@ private:
Adjuster* const rescon;
Adjuster* const resconH;
Adjuster* const reschro;
+ Adjuster* const resblur;
+ Adjuster* const resblurc;
+ Adjuster* const bluwav;
Adjuster* const tmrs;
Adjuster* const edgs;
Adjuster* const scale;
@@ -199,6 +210,7 @@ private:
Adjuster* const strength;
Adjuster* const balance;
Adjuster* const iter;
+
Adjuster* greenlow;
Adjuster* bluelow;
Adjuster* greenmed;
@@ -229,6 +241,7 @@ private:
Adjuster* const mergeC;
Adjuster* const softrad;
Adjuster* const softradend;
+ Adjuster* const chrwav;
MyComboBoxText* const Lmethod;
sigc::connection Lmethodconn;
@@ -264,6 +277,9 @@ private:
Gtk::Frame* const chanMixerHLFrame;
Gtk::Frame* const chanMixerMidFrame;
Gtk::Frame* const chanMixerShadowsFrame;
+ Gtk::Frame* const shFrame;
+ Gtk::Frame* const contFrame;
+ Gtk::Frame* const blurFrame;
Gtk::Frame* const chromaFrame;
Gtk::Label* const wavLabels;
@@ -280,11 +296,12 @@ private:
MyExpander* const expsettings;
MyExpander* const exptoning;
MyExpander* const expclari;
+ MyExpander* const expbl;
Gtk::HBox* const neutrHBox;
Gtk::HBox* const usharpHBox;
- sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enableFinalConn, enableclariConn;
+ sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enabletmConn, enableFinalConn, enableclariConn;
sigc::connection enableNoiseConn, enableResidConn, enableToningConn;
sigc::connection medianConn, avoidConn, tmrConn, medianlevConn, linkedgConn, lipstConn, cbenabConn, neutralconn, showmaskConn, oldshConn;
sigc::connection neutralPressedConn;