diff --git a/CMakeLists.txt b/CMakeLists.txt
index cbddde251..7d66109e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -669,7 +669,14 @@ if(WIN32)
elseif(APPLE)
set(
ABOUT_COMMAND_WITH_ARGS
- cmake -DPROJECT_SOURCE_DIR:STRING=${PROJECT_SOURCE_DIR} -P ${PROJECT_SOURCE_DIR}/UpdateInfo.cmake -DSYSTEM:STRING=Apple -DCXX_FLAGS:STRING=${CXX_FLAGS} -DLFLAGS:STRING=${LFLAGS} -DCOMPILER_INFO:STRING=${COMPILER_INFO} -DCACHE_NAME_SUFFIX:STRING=${CACHE_NAME_SUFFIX})
+ cmake
+ -DPROJECT_SOURCE_DIR:STRING=${PROJECT_SOURCE_DIR}
+ -DCACHE_NAME_SUFFIX:STRING=${CACHE_NAME_SUFFIX}
+ -P ${PROJECT_SOURCE_DIR}/UpdateInfo.cmake
+ -DSYSTEM:STRING=Apple
+ -DCXX_FLAGS:STRING=${CXX_FLAGS}
+ -DLFLAGS:STRING=${LFLAGS}
+ -DCOMPILER_INFO:STRING=${COMPILER_INFO})
else()
list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Linux
-DCXX_FLAGS:STRING=${CXX_FLAGS} -DLFLAGS:STRING=${LFLAGS}
diff --git a/rtdata/languages/default b/rtdata/languages/default
index 8b03dd439..e4c3a3a08 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -567,10 +567,10 @@ HISTORY_MSG_314;W - Gamut - Reduce artifacts
HISTORY_MSG_315;W - Residual - Contrast
HISTORY_MSG_316;W - Gamut - Skin tar/prot
HISTORY_MSG_317;W - Gamut - Skin hue
-HISTORY_MSG_318;W - Contrast - Highlight levels
-HISTORY_MSG_319;W - Contrast - Highlight range
-HISTORY_MSG_320;W - Contrast - Shadow range
-HISTORY_MSG_321;W - Contrast - Shadow levels
+HISTORY_MSG_318;W - Contrast - Fine levels
+HISTORY_MSG_319;W - Contrast - Fine range
+HISTORY_MSG_320;W - Contrast - Coarse range
+HISTORY_MSG_321;W - Contrast - Coarse levels
HISTORY_MSG_322;W - Gamut - Avoid color shift
HISTORY_MSG_323;W - ES - Local contrast
HISTORY_MSG_324;W - Chroma - Pastel
@@ -779,6 +779,7 @@ HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - Corner radius boost
HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion
HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction
HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter
+HISTORY_MSG_PREPROCWB_MODE;Preprocess WB Mode
HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold
HISTORY_MSG_RAWCACORR_AUTOIT;Raw CA Correction - Iterations
HISTORY_MSG_RAWCACORR_COLORSHIFT;Raw CA Correction - Avoid color shift
@@ -817,6 +818,12 @@ HISTORY_MSG_WAVBL;Blur levels
HISTORY_MSG_BLURWAV;Blur luminance
HISTORY_MSG_BLURCWAV;Blur chroma
HISTORY_MSG_EDGEFFECT;Edge Damper
+HISTORY_MSG_SIGMAFIN;Final contrast Damper
+HISTORY_MSG_SIGMATON;Toning Damper
+HISTORY_MSG_SIGMACOL;Chroma Damper
+HISTORY_MSG_SIGMADIR;Dir Damper
+HISTORY_MSG_RANGEAB;Range ab
+HISTORY_MSG_PROTAB;Protection
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -1049,6 +1056,7 @@ PARTIALPASTE_PREPROCESS_GREENEQUIL;Green equilibration
PARTIALPASTE_PREPROCESS_HOTPIXFILT;Hot pixel filter
PARTIALPASTE_PREPROCESS_LINEDENOISE;Line noise filter
PARTIALPASTE_PREPROCESS_PDAFLINESFILTER;PDAF lines filter
+PARTIALPASTE_PREPROCWB;Preprocess White Balance
PARTIALPASTE_PRSHARPENING;Post-resize sharpening
PARTIALPASTE_RAWCACORR_AUTO;CA auto-correction
PARTIALPASTE_RAWCACORR_AVOIDCOLORSHIFT;CA avoid color shift
@@ -1872,6 +1880,10 @@ TP_PREPROCESS_LINEDENOISE_DIRECTION_PDAF_LINES;Horizontal only on PDAF rows
TP_PREPROCESS_LINEDENOISE_DIRECTION_VERTICAL;Vertical
TP_PREPROCESS_NO_FOUND;None found
TP_PREPROCESS_PDAFLINESFILTER;PDAF lines filter
+TP_PREPROCWB_LABEL;Preprocess White Balance
+TP_PREPROCWB_MODE;Mode
+TP_PREPROCWB_MODE_AUTO;Auto
+TP_PREPROCWB_MODE_CAMERA;Camera
TP_PRSHARPENING_LABEL;Post-Resize Sharpening
TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions.
TP_RAWCACORR_AUTO;Auto-correction
@@ -2188,10 +2200,12 @@ TP_WAVELET_CONTEDIT;'After' contrast curve
TP_WAVELET_CONTFRAME;Contrast - Compression
TP_WAVELET_CONTR;Gamut
TP_WAVELET_CONTRA;Contrast
+TP_WAVELET_CONTRASTEDIT;Finer - Coarser levels
TP_WAVELET_CONTRAST_MINUS;Contrast -
TP_WAVELET_CONTRAST_PLUS;Contrast +
TP_WAVELET_CONTRA_TOOLTIP;Changes contrast of the residual image.
TP_WAVELET_CTYPE;Chrominance control
+TP_WAVELET_CURVEEDITOR_BL_TOOLTIP;Disabled if zoom > about 300%
TP_WAVELET_CURVEEDITOR_CC_TOOLTIP;Modifies local contrast as a function of the original local contrast (abscissa).\nLow abscissa values represent small local contrast (real values about 10..20).\n50% abscissa represents average local contrast (real value about 100..300).\n66% abscissa represents standard deviation of local contrast (real value about 300..800).\n100% abscissa represents maximum local contrast (real value about 3000..8000).
TP_WAVELET_CURVEEDITOR_CH;Contrast levels=f(Hue)
TP_WAVELET_CURVEEDITOR_CH_TOOLTIP;Modifies each level's contrast as a function of hue.\nTake care not to overwrite changes made with the Gamut sub-tool's hue controls.\nThe curve will only have an effect when wavelet contrast level sliders are non-zero.
@@ -2207,6 +2221,7 @@ TP_WAVELET_DAUB6;D6 - standard plus
TP_WAVELET_DAUB10;D10 - medium
TP_WAVELET_DAUB14;D14 - high
TP_WAVELET_DAUB_TOOLTIP;Changes Daubechies coefficients:\nD4 = Standard,\nD14 = Often best performance, 10% more time-intensive.\n\nAffects edge detection as well as the general quality of the firsts levels. However the quality is not strictly related to this coefficient and can vary with images and uses.
+TP_WAVELET_DIRFRAME;Directional contrast
TP_WAVELET_DONE;Vertical
TP_WAVELET_DTHR;Diagonal
TP_WAVELET_DTWO;Horizontal
@@ -2232,10 +2247,12 @@ TP_WAVELET_EDSL;Threshold Sliders
TP_WAVELET_EDTYPE;Local contrast method
TP_WAVELET_EDVAL;Strength
TP_WAVELET_FINAL;Final Touchup
+TP_WAVELET_FINCFRAME;Final Local Contrast
TP_WAVELET_FINEST;Finest
-TP_WAVELET_HIGHLIGHT;Highlight luminance range
+TP_WAVELET_HIGHLIGHT;Finer levels luminance range
+TP_WAVELET_FINCOAR_TOOLTIP;The left (positive) part of the curve acts on the finer levels (increase).\nThe 2 points on the abscissa represent the respective action limits of finer and coarser levels 5 and 6 (default).\nThe right (negative) part of the curve acts on the coarser levels (increase).\nAvoid moving the left part of the curve with negative values. Avoid moving the right part of the curve with positives values
TP_WAVELET_HS1;Whole luminance range
-TP_WAVELET_HS2;Shadows/Highlights
+TP_WAVELET_HS2;Selective luminance range
TP_WAVELET_HUESKIN;Skin hue
TP_WAVELET_HUESKIN_TOOLTIP;The bottom points set the beginning of the transition zone, and the upper points the end of it, where the effect is at its maximum.\n\nIf you need to move the area significantly, or if there are artifacts, then the white balance is incorrect.
TP_WAVELET_HUESKY;Sky hue
@@ -2245,10 +2262,10 @@ TP_WAVELET_ITER_TOOLTIP;Left: increase low levels and reduce high levels,\nRight
TP_WAVELET_LABEL;Wavelet Levels
TP_WAVELET_LARGEST;Coarsest
TP_WAVELET_LEVCH;Chroma
-TP_WAVELET_LEVDIR_ALL;All levels in all directions
-TP_WAVELET_LEVDIR_INF;Below or equal the level
+TP_WAVELET_LEVDIR_ALL;All levels, in all directions
+TP_WAVELET_LEVDIR_INF;Finer details levels, with selected level
TP_WAVELET_LEVDIR_ONE;One level
-TP_WAVELET_LEVDIR_SUP;Above the level
+TP_WAVELET_LEVDIR_SUP;Coarser details levels, without selected level
TP_WAVELET_LEVELS;Wavelet levels
TP_WAVELET_LEVELS_TOOLTIP;Choose the number of detail levels the image is to be decomposed into. More levels require more RAM and require a longer processing time.
TP_WAVELET_LEVF;Contrast
@@ -2259,7 +2276,7 @@ TP_WAVELET_LEVTWO;Level 3
TP_WAVELET_LEVZERO;Level 1
TP_WAVELET_LINKEDG;Link with Edge Sharpness' Strength
TP_WAVELET_LIPST;Enhanced algoritm
-TP_WAVELET_LOWLIGHT;Shadow luminance range
+TP_WAVELET_LOWLIGHT;Coarser levels luminance range
TP_WAVELET_LOWTHR_TOOLTIP;Prevents amplification of fine textures and noise
TP_WAVELET_MEDGREINF;First level
TP_WAVELET_MEDI;Reduce artifacts in blue sky
@@ -2270,6 +2287,7 @@ TP_WAVELET_MERGEL;Merge Luma
TP_WAVELET_NEUTRAL;Neutral
TP_WAVELET_NOIS;Denoise
TP_WAVELET_NOISE;Denoise and Refine
+TP_WAVELET_NOISE_TOOLTIP;If level 4 luminance denoise superior to 20, mode Agressive is used.\nIf chrominance coarse superior to 20, mode Agressive is used.
TP_WAVELET_NPHIGH;High
TP_WAVELET_NPLOW;Low
TP_WAVELET_NPNONE;None
@@ -2278,16 +2296,19 @@ TP_WAVELET_NPTYPE_TOOLTIP;This algorithm uses the proximity of a pixel and eight
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
+TP_WAVELET_OPACITYWL;Local contrast
TP_WAVELET_OPACITYWL_TOOLTIP;Modify the final local contrast at the end of the wavelet treatment.\n\nThe left side represents the smallest local contrast, progressing to the largest local contrast on the right.
TP_WAVELET_PASTEL;Pastel chroma
TP_WAVELET_PROC;Process
+TP_WAVELET_PROTAB;Protection
TP_WAVELET_RADIUS;Radius Shadows - Highlight
+TP_WAVELET_RANGEAB;Range a and b %
TP_WAVELET_RE1;Reinforced
TP_WAVELET_RE2;Unchanged
TP_WAVELET_RE3;Reduced
TP_WAVELET_RESBLUR;Blur Luminance
TP_WAVELET_RESBLURC;Blur Chroma
+TP_WAVELET_RESBLUR_TOOLTIP;Disabled if zoom > about 500%
TP_WAVELET_RESCHRO;Intensity
TP_WAVELET_RESCON;Shadows
TP_WAVELET_RESCONH;Highlights
@@ -2298,6 +2319,7 @@ TP_WAVELET_SHA;Sharp mask
TP_WAVELET_SHFRAME;Shadows/Highlights
TP_WAVELET_SHOWMASK;Show wavelet 'mask'
TP_WAVELET_SIGMA;Damper
+TP_WAVELET_SIGMAFIN;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.
@@ -2308,10 +2330,10 @@ TP_WAVELET_STREN;Strength
TP_WAVELET_STRENGTH;Strength
TP_WAVELET_SUPE;Extra
TP_WAVELET_THR;Shadows threshold
-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_THRESHOLD;Finer levels
+TP_WAVELET_THRESHOLD2;Coarser levels
+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. : All levels from level 1 up to the chosen value will only be affected within the Finer levels luminance range.\nAll other levels will have the whole range of luminances affected, unless the Coarser levels setting limits it.\nThe chosen value in this slider becomes the minimum possible value of the Coarser 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). : Only levels between the chosen value and level 9/Extra will be affected by the Coarser levels luminance range.\nAll other levels will have the whole range of luminances affected, unless the Finer levels setting limits it.\nThe lower level possible that will be considered by the algorithm is limited by the Finer levels value.
TP_WAVELET_THRESWAV;Balance Threshold
TP_WAVELET_THRH;Highlights threshold
TP_WAVELET_TILESBIG;Tiles
@@ -2326,6 +2348,7 @@ TP_WAVELET_TMSTRENGTH;Compression strength
TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image.
TP_WAVELET_TMEDGS;Edge stopping
TP_WAVELET_TON;Toning
+TP_WAVELET_TONFRAME;Excluded Colors
TP_WAVELET_TMTYPE;Compression method
TP_WAVELET_USH;None
TP_WAVELET_USHARP;Clarity method
@@ -2335,9 +2358,9 @@ TP_WAVELET_WAVLOWTHR;Low contrast threshold
TP_WAVELET_WAVOFFSET;Offset
TP_WAVELET_OFFSET_TOOLTIP;Offset modifies the balance between shadows and highlights.\nHigh values here will amplify the contrast change of the highlights, whereas low values will amplify the contrast change of the shadows.\nAlong with a low Damper value you will able to select the contrasts that will be enhanced.
TP_WBALANCE_AUTO;Auto
-TP_WBALANCE_AUTOITCGREEN;Auto iterate temperature correlation
-TP_WBALANCE_AUTOOLD;Auto RGB grey
-TP_WBALANCE_AUTO_HEADER;Autos
+TP_WBALANCE_AUTOITCGREEN;Temperature correlation
+TP_WBALANCE_AUTOOLD;RGB grey
+TP_WBALANCE_AUTO_HEADER;Automatic
TP_WBALANCE_CAMERA;Camera
TP_WBALANCE_CLOUDY;Cloudy
TP_WBALANCE_CUSTOM;Custom
@@ -2379,8 +2402,8 @@ TP_WBALANCE_SOLUX41;Solux 4100K
TP_WBALANCE_SOLUX47;Solux 4700K (vendor)
TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery)
TP_WBALANCE_SPOTWB;Use the pipette to pick the white balance from a neutral patch in the preview.
-TP_WBALANCE_STUDLABEL;Student Itcwb: %1
-TP_WBALANCE_STUDLABEL_TOOLTIP;Display calculated Student correlation\nThe lower the student value, the better the correlation\nValues below 0.002 are excellent\nValues below 0.005 are very good\nValues below 0.01 are good\nValues below 0.05 are good enough\nValues above 0.5 are poor\nVery good Student test results does not mean that the WB is good, if the illuminant is non-standard the results are erratic.\nStudent=1000 means the calculations were not restarted but results are probably goods, use previous results
+TP_WBALANCE_STUDLABEL;Correlation factor: %1
+TP_WBALANCE_STUDLABEL_TOOLTIP;Display calculated Student correlation.\nLower values are better, where <0.005 is excellent,\n<0.01 is good, and >0.5 is poor.\nLow values do not mean that the white balance is good:\nif the illuminant is non-standard the results can be erratic.\nA value of 1000 means previous calculations are used and\nthe resultsare probably good.
TP_WBALANCE_TEMPBIAS;AWB temperature bias
TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias".
TP_WBALANCE_TEMPERATURE;Temperature
diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc
index 894c72ce2..89e4c1b8d 100644
--- a/rtengine/FTblockDN.cc
+++ b/rtengine/FTblockDN.cc
@@ -549,7 +549,7 @@ BENCHFUN
const float noisevarL = (useNoiseLCurve && (denoiseMethodRgb || !isRAW)) ? SQR(((noiseluma + 1.f) / 125.f) * (10.f + (noiseluma + 1.f) / 25.f)) : SQR((noiseluma / 125.f) * (1.f + noiseluma / 25.f));
const bool denoiseLuminance = (noisevarL > 0.00001f);
- //printf("NL=%f \n",noisevarL);
+// printf("NL=%f \n",noisevarL);
if (useNoiseLCurve || useNoiseCCurve) {
int hei = calclum->getHeight();
int wid = calclum->getWidth();
@@ -2214,7 +2214,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5);
const float eps = 0.01f;
- if (edge == 1 || edge == 3 || edge == 4) {
+ if (edge == 1 || edge == 3 || edge == 4 || edge == 5) {
maxlvl = 4; //for refine denoise edge wavelet
}
@@ -2286,7 +2286,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
nvl[i] = 0.f;
}
- if ((edge == 1 || edge == 2 || edge == 3) && vari) {
+ if ((edge == 1 || edge == 2 || edge == 3 || edge == 5) && vari) {
// nvl = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer
if ((edge == 1 || edge == 3)) {
for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
@@ -2294,7 +2294,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
}
}
- if (edge == 2 || edge == 4) {
+ if (edge == 2 || edge == 4 || edge == 5) {
for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
nvl[i] = vari[lvl] * SQR(noisevarlum[i]);
}
@@ -2569,7 +2569,7 @@ bool ImProcFunctions::WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoe
int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5);
- if (edge == 1 || edge == 3) {
+ if (edge == 1 || edge == 3 || edge == 5) {
maxlvl = 4; //for refine denoise edge wavelet
}
@@ -2713,7 +2713,7 @@ void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, f
nvl[i] = 0.f;
}
- if ((edge == 1 || edge == 2 || edge == 3) && vari) {
+ if ((edge == 1 || edge == 2 || edge == 3 || edge == 5) && vari) {
// nvl = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer
if ((edge == 1 || edge == 3)) {
for (int i = 0; i < W_L * H_L; ++i) {
@@ -2721,7 +2721,7 @@ void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, f
}
}
- if (edge == 2 || edge == 4) {
+ if (edge == 2 || edge == 4 || edge == 5) {
for (int i = 0; i < W_L * H_L; ++i) {
nvl[i] = vari[level] * SQR(noisevarlum[i]);
}
diff --git a/rtengine/canon_cr3_decoder.cc b/rtengine/canon_cr3_decoder.cc
index d9a10900c..f9850189c 100644
--- a/rtengine/canon_cr3_decoder.cc
+++ b/rtengine/canon_cr3_decoder.cc
@@ -3042,11 +3042,11 @@ bool crxSetupImageData(
void crxFreeImageData(CrxImage* img)
{
- CrxTile* tile = img->tiles;
- const int nTiles = img->tileRows * img->tileCols;
-
if (img->tiles) {
- for (std::int32_t curTile = 0; curTile < nTiles; curTile++, tile++) {
+ CrxTile* const tile = img->tiles;
+ const int nTiles = img->tileRows * img->tileCols;
+
+ for (std::int32_t curTile = 0; curTile < nTiles; ++curTile) {
if (tile[curTile].comps) {
for (std::int32_t curPlane = 0; curPlane < img->nPlanes; ++curPlane) {
crxFreeSubbandData(img, tile[curTile].comps + curPlane);
diff --git a/rtengine/curves.cc b/rtengine/curves.cc
index 14711c730..ebb23e754 100644
--- a/rtengine/curves.cc
+++ b/rtengine/curves.cc
@@ -1278,6 +1278,43 @@ void WavOpacityCurveRG::Set(const std::vector &curvePoints)
}
+WavOpacityCurveSH::WavOpacityCurveSH() {}
+
+void WavOpacityCurveSH::Reset()
+{
+ lutOpacityCurveSH.reset();
+}
+
+void WavOpacityCurveSH::Set(const Curve &pCurve)
+{
+ if (pCurve.isIdentity()) {
+ Reset(); // raise this value if the quality suffers from this number of samples
+ return;
+ }
+
+ lutOpacityCurveSH(501); // raise this value if the quality suffers from this number of samples
+
+ for (int i = 0; i < 501; i++) {
+ lutOpacityCurveSH[i] = pCurve.getVal(double(i) / 500.);
+ }
+}
+
+void WavOpacityCurveSH::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();
+ }
+
+}
+
+
+
+
+
WavOpacityCurveBY::WavOpacityCurveBY() {}
void WavOpacityCurveBY::Reset()
diff --git a/rtengine/curves.h b/rtengine/curves.h
index 03fa3e812..0fb58cc9e 100644
--- a/rtengine/curves.h
+++ b/rtengine/curves.h
@@ -673,6 +673,32 @@ public:
return lutOpacityCurveRG;
}
};
+
+class WavOpacityCurveSH
+{
+private:
+ LUTf lutOpacityCurveSH; // 0xffff range
+ void Set(const Curve &pCurve);
+public:
+ virtual ~WavOpacityCurveSH() {};
+ WavOpacityCurveSH();
+
+ void Reset();
+ // void Set(const std::vector &curvePoints, bool &opautili);
+ void Set(const std::vector &curvePoints);
+ float operator[](float index) const
+ {
+ return lutOpacityCurveSH[index];
+ }
+
+ operator bool (void) const
+ {
+ return lutOpacityCurveSH;
+ }
+};
+
+
+
class WavOpacityCurveBY
{
private:
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index 11bf19edf..8bf27b53d 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -969,12 +969,13 @@ void Crop::update(int todo)
WavCurve wavCLVCurve;
Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
+ WavOpacityCurveSH waOpacityCurveSH;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
WavOpacityCurveWL waOpacityCurveWL;
LUTf wavclCurve;
- params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
LabImage *unshar = nullptr;
Glib::ustring provis;
LabImage *provradius = nullptr;
@@ -1003,7 +1004,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, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
+ parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
unshar->CopyFrom(labnCrop);
params.wavelet.CLmethod = provis;
@@ -1016,7 +1017,7 @@ void Crop::update(int todo)
WaveParams.expnoise = false;
}
- parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
+ parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, 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 f68616b96..5261675a0 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -891,7 +891,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if ((params->wavelet.enabled)) {
WaveletParams WaveParams = params->wavelet;
- WaveParams.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ WaveParams.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
int kall = 0;
LabImage *unshar = nullptr;
Glib::ustring provis;
@@ -920,7 +920,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, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
+ ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
unshar->CopyFrom(nprevl);
@@ -934,7 +934,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
WaveParams.expnoise = false;
}
- ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
+ ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index e17d88183..e4858c76b 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -141,6 +141,7 @@ protected:
WavCurve wavCLVCurve;
Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
+ WavOpacityCurveSH waOpacityCurveSH;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
WavOpacityCurveWL waOpacityCurveWL;
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index d003df644..b7d7c41e5 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -55,6 +55,7 @@ class ToneCurve;
class WavCurve;
class Wavblcurve;
class WavOpacityCurveBY;
+class WavOpacityCurveSH;
class WavOpacityCurveRG;
class WavOpacityCurveW;
class WavOpacityCurveWL;
@@ -188,7 +189,6 @@ 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 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);
@@ -202,25 +202,25 @@ public:
int pitch, int scale, const int luma, const int chroma/*, LUTf & Lcurve, LUTf & abcurve*/);
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 Wavblcurve & wavblcurve, 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 WavOpacityCurveSH & waOpacityCurveSH, 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, 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);
+ struct cont_params &cp, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveSH & waOpacityCurveSH, 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 Wavblcurve & wavblcurve, const WavOpacityCurveW & waOpacityCurveW,
- struct cont_params &cp, const bool useChannelA, int skip, float *meanab, float *sigmaab);
+ struct cont_params &cp, const bool useChannelA, int skip, float *meanab, float *sigmaab);
void WaveletAandBAllAB(const wavelet_decomposition &WaveletCoeffs_a, const wavelet_decomposition &WaveletCoeffs_b,
- const cont_params &cp, FlatCurve* hhcurve, bool hhutili);
+ 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,
- int W_L, int H_L, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili);
- void finalContAllL(float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, const cont_params &cp,
- int W_L, int H_L, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL);
+ int W_L, int H_L, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveSH & waOpacityCurveSH, FlatCurve* ChCurve, bool Chutili);
+ void finalContAllL(float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, const cont_params &cp,
+ int W_L, int H_L, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL);
void ContAllAB(LabImage * lab, int maxlvl, float **varhue, float **varchrom, float ** WavCoeffs_a, float * WavCoeffs_a0, int level, int dir, const WavOpacityCurveW & waOpacityCurveW, struct cont_params &cp,
- int W_ab, int H_ab, const bool useChannelA);
+ int W_ab, int H_ab, const bool useChannelA, float *meanab, float *sigmaab);
void Evaluate2(const wavelet_decomposition &WaveletCoeffs_L,
- float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN);
+ float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN);
void Eval2(float ** WavCoeffs_L, int level,
- int W_L, int H_L, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN);
+ int W_L, int H_L, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN);
void calceffect(int level, float *mean, float *sigma, float *mea, float effect, float offs);
@@ -228,9 +228,6 @@ public:
void Sigma(float * HH_Coeffs, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg);
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 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);
void Median_Denoise(float **src, float **dst, float upperBound, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr);
void RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve, const NoiseCurve & noiseCCurve, float &nresi, float &highresi);
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index 39de7c938..47bd0f08a 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -113,6 +113,10 @@ struct cont_params {
int TMmeth;
float tmstrength;
float balan;
+ float sigmafin;
+ float sigmaton;
+ float sigmacol;
+ float sigmadir;
int ite;
int contmet;
bool opaW;
@@ -142,12 +146,25 @@ struct cont_params {
float balchrom;
float chromfi;
float chromco;
+ float factor;
+ float scaling;
+ float scaledirect;
+ float a_scale;
+ float a_base;
+ float b_scale;
+ float b_base;
+ float a_high;
+ float a_low;
+ float b_high;
+ float b_low;
+ float rangeab;
+ float protab;
};
int wavNestedLevels = 1;
-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)
+void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const Wavblcurve & wavblcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveSH & waOpacityCurveSH, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, const LUTf &wavclCurve, int skip)
{
@@ -191,6 +208,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.ite = params->wavelet.iter;
cp.tonemap = params->wavelet.tmrs != 0;
cp.bam = false;
+ cp.sigmafin = params->wavelet.sigmafin;
+ cp.sigmaton = params->wavelet.sigmaton;
+ cp.sigmacol = params->wavelet.sigmacol;
+ cp.sigmadir = params->wavelet.sigmadir;
if (params->wavelet.TMmethod == "cont") {
cp.contmet = 1;
@@ -310,6 +331,20 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.mulC[m] = waparams.ch[m];
}
+ cp.factor = WaveletParams::LABGRID_CORR_MAX * 3.276f;
+ cp.scaling = WaveletParams::LABGRID_CORR_SCALE;
+ cp.scaledirect = WaveletParams::LABGRIDL_DIRECT_SCALE;
+ cp.a_scale = (params->wavelet.labgridAHigh - params->wavelet.labgridALow) / cp.factor / cp.scaling;
+ cp.a_base = params->wavelet.labgridALow / cp.scaling;
+ cp.b_scale = (params->wavelet.labgridBHigh - params->wavelet.labgridBLow) / cp.factor / cp.scaling;
+ cp.b_base = params->wavelet.labgridBLow / cp.scaling;
+ cp.a_high = 3.276f * params->wavelet.labgridAHigh;
+ cp.a_low = 3.276f * params->wavelet.labgridALow;
+ cp.b_high = 3.276f * params->wavelet.labgridBHigh;
+ cp.b_low = 3.276f * params->wavelet.labgridBLow;
+ cp.rangeab = params->wavelet.rangeab;
+ cp.protab = params->wavelet.protab;
+
if (waOpacityCurveRG) {
cp.opaRG = true;
}
@@ -434,9 +469,9 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.t_lsl = static_cast(params->wavelet.bllev.getTopLeft());
cp.b_rsl = static_cast(params->wavelet.bllev.getBottomRight());
cp.t_rsl = static_cast(params->wavelet.bllev.getTopRight());
- cp.numlevS = params->wavelet.threshold2;
- int maxlevS = 9 - cp.numlevH;
- cp.numlevS = rtengine::min(cp.numlevS, maxlevS);
+ cp.numlevS = 9 - params->wavelet.threshold2;
+ int maxlevS = cp.numlevH;
+ cp.numlevS = rtengine::max(cp.numlevS, maxlevS);
//highlight
cp.b_lhl = static_cast(params->wavelet.hllev.getBottomLeft());
cp.t_lhl = static_cast(params->wavelet.hllev.getTopLeft());
@@ -505,11 +540,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
levwav = rtengine::min(maxlevelcrop, levwav);
- // determine number of levels to process.
- // for(levwav=rtengine::min(maxlevelcrop,levwav);levwav>0;levwav--)
- // if(cp.mul[levwav-1]!=0.f || cp.curv)
- // if(cp.mul[levwav-1]!=0.f)
- // break;
// I suppress this fonctionality ==> crash for level < 3
if (levwav < 1) {
return; // nothing to do
@@ -705,7 +735,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
#ifdef _OPENMP
- #pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel for num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
for (int i = tiletop; i < tilebottom; i++) {
@@ -764,7 +794,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
#ifdef _OPENMP
- #pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel for num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
for (int i = 1; i < hei - 1; i++) {
@@ -866,13 +896,13 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (levwavL > 0) {
const std::unique_ptr Ldecomp(new wavelet_decomposition(labco->data, labco->W, labco->H, levwavL, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
- float madL[10][3];
if (!Ldecomp->memoryAllocationFailed) {
+ float madL[10][3];
// float madL[8][3];
#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic) collapse(2) num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel for schedule(dynamic) collapse(2) num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
for (int lvl = 0; lvl < levwavL; lvl++) {
@@ -883,6 +913,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
float ** WavCoeffs_L = Ldecomp->level_coeffs(lvl);
madL[lvl][dir - 1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L * Hlvl_L));
+
+ if (settings->verbose) {
+ printf("sqrt madL=%f lvl=%i dir=%i\n", sqrt(madL[lvl][dir - 1]), lvl, dir - 1);
+ }
}
}
@@ -907,10 +941,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
//init for edge and denoise
float vari[4];
- vari[0] = 8.f * SQR((cp.lev0n / 125.f) * (1.f + cp.lev0n / 25.f));
- vari[1] = 8.f * SQR((cp.lev1n / 125.f) * (1.f + cp.lev1n / 25.f));
- vari[2] = 8.f * SQR((cp.lev2n / 125.f) * (1.f + cp.lev2n / 25.f));
- vari[3] = 8.f * SQR((cp.lev3n / 125.f) * (1.f + cp.lev3n / 25.f));
+ vari[0] = 0.8f * SQR((cp.lev0n / 125.f) * (1.f + cp.lev0n / 25.f));
+ vari[1] = 0.8f * SQR((cp.lev1n / 125.f) * (1.f + cp.lev1n / 25.f));
+ vari[2] = 0.8f * SQR((cp.lev2n / 125.f) * (1.f + cp.lev2n / 25.f));
+ vari[3] = 0.8f * SQR((cp.lev3n / 125.f) * (1.f + cp.lev3n / 25.f));
float kr3 = 1.f;
if (cp.lev3n < 10.f) {
@@ -924,11 +958,16 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
if ((cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f) && cp.noiseena) {
- int edge = 4;
- vari[0] = rtengine::max(0.0001f, vari[0]);
- vari[1] = rtengine::max(0.0001f, vari[1]);
- vari[2] = rtengine::max(0.0001f, vari[2]);
- vari[3] = rtengine::max(0.0001f, kr3 * vari[3]);
+ int edge = 5;
+ vari[0] = rtengine::max(0.000001f, vari[0]);
+ vari[1] = rtengine::max(0.000001f, vari[1]);
+ vari[2] = rtengine::max(0.000001f, vari[2]);
+ vari[3] = rtengine::max(0.000001f, kr3 * vari[3]);
+
+ if (settings->verbose) {
+ printf("LUM var0=%f var1=%f var2=%f var3=%f\n", vari[0], vari[1], vari[2], vari[3]);
+ }
+
// float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL
int GWL = labco->W;
int GHL = labco->H;
@@ -962,7 +1001,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
- if (cp.lev3n < 0.5f) {
+ if (cp.lev3n < 20.f) {
WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
} else {
WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
@@ -984,7 +1023,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
Chutili = true;
}
- WaveletcontAllL(labco, varhue, varchro, *Ldecomp, wavblcurve, cp, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili);
+ WaveletcontAllL(labco, varhue, varchro, *Ldecomp, wavblcurve, cp, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, waOpacityCurveSH, ChCurve, Chutili);
if (cp.val > 0 || ref || contr || cp.diagcurv) { //edge
Evaluate2(*Ldecomp, mean, meanN, sigma, sigmaN, MaxP, MaxN);
@@ -1009,29 +1048,29 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
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);
+ noisecfr = cp.chromfi + 0.1f * cp.balchrom;
+ noiseccr = cp.chromco + 0.1f * cp.balchrom;
}
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);
+ noisecfb = cp.chromfi - 0.1f * cp.balchrom;
+ noiseccb = cp.chromco - 0.1f * cp.balchrom;
}
if (noisecfr < 0.f) {
- noisecfr = 0.0001f;
+ noisecfr = 0.00001f;
}
if (noiseccr < 0.f) {
- noiseccr = 0.0001f;
+ noiseccr = 0.00001f;
}
if (noisecfb < 0.f) {
- noisecfb = 0.0001f;
+ noisecfb = 0.00001f;
}
if (noiseccb < 0.f) {
@@ -1062,7 +1101,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
float k3 = 0.f;
if (cp.chromfi < 0.2f) {
- k1 = 0.f;
+ k1 = 0.05f;
k2 = 0.f;
k3 = 0.f;
} else if (cp.chromfi < 0.3f) {
@@ -1116,7 +1155,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
k3 = 1.f;
}
- float minic = 0.0001f;
+ float minic = 0.000001f;
variC[0] = max(minic, variC[0]);
variC[1] = max(minic, k1 * variC[1]);
variC[2] = max(minic, k2 * variC[2]);
@@ -1131,15 +1170,12 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
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) {
+ if (cp.chromco < 0.2f) {
k4 = 0.1f;
- k5 = 0.0f;
+ k5 = 0.02f;
} else if (cp.chromco < 0.5f) {
k4 = 0.15f;
- k5 = 0.0f;
+ k5 = 0.05f;
} else if (cp.chromco < 1.f) {
k4 = 0.15f;
k5 = 0.1f;
@@ -1157,10 +1193,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
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]);
+ variC[4] = max(0.000001f, k4 * variC[4]);
+ variC[5] = max(0.000001f, k5 * variC[5]);
+ variCb[4] = max(0.000001f, k4 * variCb[4]);
+ variCb[5] = max(0.000001f, k5 * variCb[5]);
if (cp.chromco < 4.f) {
k6 = 0.f;
@@ -1172,8 +1208,13 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
k6 = 1.f;
}
- variC[6] = max(0.0001f, k6 * variC[6]);
- variCb[6] = max(0.0001f, k6 * variCb[6]);
+ variC[6] = max(0.00001f, k6 * variC[6]);
+ variCb[6] = max(0.00001f, k6 * variCb[6]);
+
+ if (settings->verbose) {
+ printf("CHRO var0=%f va1=%f va2=%f va3=%f va4=%f val5=%f va6=%f\n", variC[0], variC[1], variC[2], variC[3], variC[4], variC[5], variC[6]);
+ }
+
/*
for (int y = 0; y < 7; y++) {
printf("y=%i madL=%f varia=%f variab=%f\n", y, madL[y][1], variC[y], variCb[y]);
@@ -1251,7 +1292,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
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) {
- if (cp.noiseena && (cp.chromfi > 0.f || cp.chromfi > 0.f)) {
+ if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f )) {
+ WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
+ } else if (cp.chromfi > 0.f && cp.chromco >= 2.f){
+
WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
}
@@ -1285,7 +1329,9 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
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) {
- if (cp.noiseena && (cp.chromfi > 0.f || cp.chromfi > 0.f)) {
+ if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f )) {
+ WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
+ } else if (cp.chromfi > 0.f && cp.chromco >= 2.f){
WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
}
@@ -1315,21 +1361,26 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
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) {
- if (cp.noiseena && (cp.chromfi > 0.f || cp.chromfi > 0.f)) {
+ if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f)) {
+ WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
+ } else if (cp.chromfi > 0.f && cp.chromco >= 2.f){
WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
}
Evaluate2(*adecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab);
- WaveletcontAllAB(labco, varhue, varchro, *adecomp, wavblcurve, waOpacityCurveW, cp, true, skip, meanab, sigmaab);
- WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
- WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
+ WaveletcontAllAB(labco, varhue, varchro, *adecomp, wavblcurve, waOpacityCurveW, cp, true, skip, meanab, sigmaab);
+ if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f)) {
+ WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
+ } else if (cp.chromfi > 0.f && cp.chromco >= 2.f){
+ WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
+ WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
+ }
+
Evaluate2(*bdecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab);
- if (cp.noiseena && (cp.chromfi > 0.f || cp.chromfi > 0.f)) {
- WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip, meanab, sigmaab);
- WaveletAandBAllAB(*adecomp, *bdecomp, cp, hhCurve, hhutili);
- }
+ WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip, meanab, sigmaab);
+ WaveletAandBAllAB(*adecomp, *bdecomp, cp, hhCurve, hhutili);
adecomp->reconstruct(labco->data + datalen, cp.strength);
bdecomp->reconstruct(labco->data + 2 * datalen, cp.strength);
@@ -1388,7 +1439,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
bool highlight = params->toneCurve.hrenabled;
#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel for schedule(dynamic,16) num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
for (int i = tiletop; i < tilebottom; i++) {
@@ -1615,7 +1666,7 @@ void ImProcFunctions::Aver(float * RESTRICT DataList, int datalen, float &averag
max = 0.f;
min = RT_INFINITY_F;
#ifdef _OPENMP
- #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
{
float lmax = 0.f, lmin = 0.f;
@@ -1666,7 +1717,7 @@ void ImProcFunctions::Sigma(float * RESTRICT DataList, int datalen, float avera
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)
+ #pragma omp parallel for reduction(+:variP,variN,countP,countN) num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
for (int i = 0; i < datalen; i++) {
@@ -1773,7 +1824,7 @@ void ImProcFunctions::Eval2(float ** WavCoeffs_L, int level,
float AvL, AvN, SL, SN, maxLP, maxLN;
for (int dir = 1; dir < 4; dir++) {
- Aver(WavCoeffs_L[dir], W_L * H_L, avLP[dir], avLN[dir], maxL[dir], minL[dir]);
+ Aver(WavCoeffs_L[dir], W_L * H_L, avLP[dir], avLN[dir], maxL[dir], minL[dir]);
Sigma(WavCoeffs_L[dir], W_L * H_L, avLP[dir], avLN[dir], sigP[dir], sigN[dir]);
}
@@ -1910,7 +1961,7 @@ void ImProcFunctions::ContrastResid(float * WavCoeffs_L0, struct cont_params &cp
-void ImProcFunctions::EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0)
+void ImProcFunctions::EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0)
{
@@ -1981,7 +2032,7 @@ void ImProcFunctions::WaveletcontAllLfinal(const wavelet_decomposition &WaveletC
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)
+ struct cont_params &cp, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveSH & waOpacityCurveSH, FlatCurve* ChCurve, bool Chutili)
{
const int maxlvl = WaveletCoeffs_L.maxlevel();
const int W_L = WaveletCoeffs_L.level_W(0);
@@ -1995,7 +2046,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
if (contrast != 0.f || (cp.tonemap && cp.resena)) { // contrast = 0.f means that all will be multiplied by 1.f, so we can skip this step
#ifdef _OPENMP
- #pragma omp parallel for reduction(+:avedbl) num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel for reduction(+:avedbl) num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
for (int i = 0; i < W_L * H_L; i++) {
@@ -2003,7 +2054,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
#ifdef _OPENMP
- #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
{
float lminL = FLT_MAX;
@@ -2088,7 +2139,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
#ifdef _OPENMP
- #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #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
@@ -2163,13 +2214,13 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
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 (LL100 < cp.th) {
+ constexpr float alp = 3.f; //increase contrast sahdow in lowlights between 1 and ??
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);
@@ -2198,22 +2249,28 @@ 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];
+ int minWL = min(W_L, H_L);
- for (int i = 0; i < H_L * W_L; i++) {
- bef[i] = WavCoeffs_L0[i];
+ //printf("skip=%i WL=%i HL=%i min=%i\n", skip, W_L, H_L, minWL);
+ if (minWL > 140) { //disabled if too low windows
+ constexpr float k = 0.5f;
+ float rad = k * 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;
}
-
- 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;
}
//
@@ -2221,7 +2278,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
n0 = n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = n9 = n10 = n32 = 0;
#ifdef _OPENMP
- #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
{
//enabled Lipschitz..replace simple by complex edge detection
@@ -2322,12 +2379,10 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
//if not no edge or reduction
float bet = 1.f;
- //if(cp.lip3) {//enhance algorithm
if (alph > eddlipinfl && beta < 0.85f * eddlipinfl) { //0.85 arbitrary value ==> eliminate from edge if H V D too different
bet = beta;
}
- //}
float AmpLip = 1.f;
if (alph > eddlipinfl) {
@@ -2338,16 +2393,6 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
kampli = AmpLip / aamp;
}
- // comparison betwwen pixel and neighbours to do ==> I think 3 dir above is better
- /* if(cp.lip3){
- koeLi[lvl*3][i*W_L + j] = (koeLi[lvl*3][i*W_L + j] + koeLi[lvl*3][(i-1)*W_L + j] + koeLi[lvl*3][(i+1)*W_L + j]
- + koeLi[lvl*3][i*W_L + j+1] + koeLi[lvl*3][i*W_L + j-1] + koeLi[lvl*3][(i-1)*W_L + j-1]
- + koeLi[lvl*3][(i-1)*W_L + j+1] +koeLi[lvl*3][(i+1)*W_L + j-1] +koeLi[lvl*3][(i+1)*W_L + j+1])/9.f;
- }
- */
- // apply to each direction Wavelet level : horizontal / vertiacle / diagonal
- //interm += SQR(koeLi[lvl*3 + dir-1][i*W_L + j]);
-
interm *= kampli;
if (interm < cp.eddetthr / eddlow) {
@@ -2387,83 +2432,88 @@ 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;
+// 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);
+ 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, waOpacityCurveSH, ChCurve, Chutili);
+ int minWL = min(Wlvl_L, Hlvl_L);
- if (wavblcurve && wavcurvecomp && cp.blena) {
- // printf("Blur level L\n");
- float mea[10];
- float effect = cp.bluwav;
- float beta = 0.f;
- float offs = 1.f;
+ if(minWL > 180) {
+ if (wavblcurve && wavcurvecomp && cp.blena) {
+ // printf("Blur level L\n");
+ float mea[10];
+ const float effect = cp.bluwav;
+ constexpr float offs = 1.f;
+ float * beta = new float[Wlvl_L * Hlvl_L];
- calceffect(lvl, mean, sigma, mea, effect, offs);
+ calceffect(lvl, mean, sigma, mea, effect, offs);
- float * bef = new float[Wlvl_L * Hlvl_L];
- float * aft = new float[Wlvl_L * Hlvl_L];
+ 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];
- float WavCL = std::fabs(WavCoeffs_L[dir][co]);
+ for (int co = 0; co < Hlvl_L * Wlvl_L; co++) {
+ bef[co] = WavCoeffs_L[dir][co];
+ float WavCL = std::fabs(WavCoeffs_L[dir][co]);
- if (WavCL < mea[0]) {
- beta = 0.05f;
- n0++;
+ if (WavCL < mea[0]) {
+ beta[co] = 0.05f;
+ n0++;
- if (WavCL < 32.7) {
- n32++;
+ if (WavCL < 32.7) {
+ n32++;
+ }
+ } else if (WavCL < mea[1]) {
+ beta[co] = 0.2f;
+ n1++;
+ } else if (WavCL < mea[2]) {
+ beta[co] = 0.7f;
+ n2++;
+ } else if (WavCL < mea[3]) {
+ beta[co] = 1.f; //standard
+ n3++;
+ } else if (WavCL < mea[4]) {
+ beta[co] = 1.f;
+ n4++;
+ } else if (WavCL < mea[5]) {
+ beta[co] = 0.8f; //+sigma
+ n5++;
+ } else if (WavCL < mea[6]) {
+ beta[co] = 0.6f;
+ n6++;
+ } else if (WavCL < mea[7]) {
+ beta[co] = 0.4f;
+ n7++;
+ } else if (WavCL < mea[8]) {
+ beta[co] = 0.2f; // + 2 sigma
+ n8++;
+ } else if (WavCL < mea[9]) {
+ beta[co] = 0.1f;
+ n9++;
+ } else {
+ beta[co] = 0.01f;
+ n10++;
}
- } 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);
+ }
+ float klev = (wavblcurve[lvl * 55.5f]);
+
+ //blur level
+ klev *= 80.f / skip;
+ boxblur(bef, aft, klev, Wlvl_L, Hlvl_L, false);
+
+ for (int co = 0; co < Hlvl_L * Wlvl_L; co++) {
+ aft[co] = bef[co] * (1.f - beta[co]) + aft[co] * beta[co];
+ WavCoeffs_L[dir][co] = aft[co];
+ }
+
+ delete[] bef;
+ delete[] aft;
+ delete[] beta;
}
-
- 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]);
-
- klev *= beta * 100.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;
}
}
}
@@ -2486,7 +2536,7 @@ void ImProcFunctions::WaveletAandBAllAB(const wavelet_decomposition &WaveletCoef
float * WavCoeffs_a0 = WaveletCoeffs_a.coeff0;
float * WavCoeffs_b0 = WaveletCoeffs_b.coeff0;
#ifdef _OPENMP
- #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
{
#ifdef __SSE2__
@@ -2542,7 +2592,7 @@ void ImProcFunctions::WaveletAandBAllAB(const wavelet_decomposition &WaveletCoef
}
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, float *meanab, float *sigmaab)
+ struct cont_params &cp, const bool useChannelA, int skip, float *meanab, float *sigmaab)
{
int maxlvl = WaveletCoeffs_ab.maxlevel();
@@ -2552,7 +2602,7 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float
float * WavCoeffs_ab0 = WaveletCoeffs_ab.coeff0;
#ifdef _OPENMP
- #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
{
if (cp.chrores != 0.f && cp.resena) { // cp.chrores == 0.f means all will be multiplied by 1.f, so we can skip the processing of residual
@@ -2587,20 +2637,6 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float
if ((modhue > cp.t_ry || modhue < cp.t_ly)) {
scale = (100.f + cp.sky) / 100.1f;
}
-
- /* else if((modhue >= cp.t_ry && modhue < cp.b_ry)) {
- scale=(100.f+cp.sky)/100.1f;
- float ar=(scale-1.f)/(cp.t_ry- cp.b_ry);
- float br=scale-cp.t_ry*ar;
- scale=ar*modhue+br;
- }
- else if((modhue > cp.b_ly && modhue < cp.t_ly)) {
- scale=(100.f+cp.sky)/100.1f;
- float al=(scale-1.f)/(-cp.b_ly + cp.t_ly);
- float bl=scale-cp.t_ly*al;
- scale=al*modhue+bl;
- }
- */
}
WavCoeffs_ab0[i] *= (1.f + cp.chrores * (scale) / 100.f);
@@ -2667,22 +2703,28 @@ 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];
+ int minWL = min(W_L, H_L);
- for (int i = 0; i < H_L * W_L; i++) {
- bef[i] = WavCoeffs_ab0[i];
+ //printf("skip=%i WL=%i HL=%i min=%i\n", skip, W_L, H_L, minWL);
+ if (minWL > 140) { //disabled if too low windows
+ constexpr float k = 0.5f;
+ float rad = k * 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;
}
-
- 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;
}
@@ -2707,67 +2749,75 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float
int Hlvl_ab = WaveletCoeffs_ab.level_H(lvl);
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);
+ ContAllAB(labco, maxlvl, varhue, varchrom, WavCoeffs_ab, WavCoeffs_ab0, lvl, dir, waOpacityCurveW, cp, Wlvl_ab, Hlvl_ab, useChannelA, meanab, sigmaab);
+ int minWL = min(Wlvl_ab, Hlvl_ab);
+
+ if(minWL > 180) {
+ 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 offs = 1.f;
+ float * beta = new float[Wlvl_ab * Hlvl_ab];
- 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]);
-
- 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;
+ for (int co = 0; co < Wlvl_ab * Hlvl_ab; co++) {
+ beta[co] = 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]);
+
+ if (WavCab < mea[0]) {
+ beta[co] = 0.05f;
+ } else if (WavCab < mea[1]) {
+ beta[co] = 0.2f;
+ } else if (WavCab < mea[2]) {
+ beta[co] = 0.7f;
+ } else if (WavCab < mea[3]) {
+ beta[co] = 1.f; //standard
+ } else if (WavCab < mea[4]) {
+ beta[co] = 1.f;
+ } else if (WavCab < mea[5]) {
+ beta[co] = 0.8f; //+sigma
+ } else if (WavCab < mea[6]) {
+ beta[co] = 0.6f;
+ } else if (WavCab < mea[7]) {
+ beta[co] = 0.4f;
+ } else if (WavCab < mea[8]) {
+ beta[co] = 0.2f; // + 2 sigma
+ } else if (WavCab < mea[9]) {
+ beta[co] = 0.1f;
+ } else {
+ beta[co] = 0.0f;
+ }
+
+
+ }
+
+ klev = (wavblcurve[lvl * 55.5f]);
+
+ klev *= cp.chrwav * 80.f / skip;
+
+ boxblur(bef, aft, klev, Wlvl_ab, Hlvl_ab, false);
+
+ for (int co = 0; co < Hlvl_ab * Wlvl_ab; co++) {
+ aft[co] = bef[co] * (1.f - beta[co]) + aft[co] * beta[co];
+ WavCoeffs_ab[dir][co] = aft[co];
+ }
+
+ delete[] bef;
+ delete[] aft;
+ delete[] beta;
}
-
- klev = (wavblcurve[lvl * 55.5f]);
-
- klev *= beta * cp.chrwav * 100.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;
}
-
}
}
@@ -2788,8 +2838,8 @@ void ImProcFunctions::calckoe(float ** WavCoeffs_LL, const cont_params& cp, floa
// I calculate coefficients with r size matrix 3x3 r=1 ; 5x5 r=2; 7x7 r=3
/*
float k[2*r][2*r];
- for(int i=1;i<=(2*r+1);i++) {
- for(int j=1;j<=(2*r+1);j++) {
+ for (int i=1;i<=(2*r+1);i++) {
+ for (int j=1;j<=(2*r+1);j++) {
k[i][j]=(1.f/6.283*sigma*sigma)*exp(-SQR(i-r-1)+SQR(j-r-1)/2.f*SQR(sigma));
}
}
@@ -2837,9 +2887,7 @@ void ImProcFunctions::calckoe(float ** WavCoeffs_LL, const cont_params& cp, floa
else if (cp.eddetthr >= 75.f) {
borderL = 2;
- //if(cp.lip3 && level > 1) {
if (level > 1) { // do not activate 5x5 if level 0 or 1
-
for (int i = 2; i < H_L - 2; i++) {
for (int j = 2; j < W_L - 2; j++) {
// Gaussian 1.1
@@ -2887,21 +2935,6 @@ void ImProcFunctions::calckoe(float ** WavCoeffs_LL, const cont_params& cp, floa
}
-
- /*
- // I suppress these 2 convolutions ==> lees good results==> probably because structure data different and also I compare to original value which have + and -
- for(int i = borderL; i < H_L-borderL; i++ ) {//[-1 0 1] x==>j
- for(int j = borderL; j < W_L-borderL; j++) {
- tmC[i][j]=- WavCoeffs_LL[dir][(i)*W_L + j-1] + WavCoeffs_LL[dir][(i)*W_L + j+1];
- }
- }
- for(int i = borderL; i < H_L-borderL; i++ ) {//[1 0 -1] y==>i
- for(int j = borderL; j < W_L-borderL; j++) {
- tmC[i][j]= - WavCoeffs_LL[dir][(i-1)*W_L + j] + WavCoeffs_LL[dir][(i+1)*W_L + j];
- }
- }
- */
-
float thr = 40.f; //avoid artifact eg. noise...to test
float thr2 = 1.5f * edd; //edd can be modified in option ed_detect
thr2 += cp.eddet / 30.f; //to test
@@ -2917,9 +2950,6 @@ void ImProcFunctions::calckoe(float ** WavCoeffs_LL, const cont_params& cp, floa
for (int j = borderL; j < W_L - borderL; j++) {
// my own algo : probably a little false, but simpler as Lipschitz !
// Thr2 = maximum of the function ==> Lipsitch says = probably edge
-// float temp = WavCoeffs_LL[dir][i*W_L + j];
-// if(temp>=0.f && temp < thr) temp = thr;
-// if(temp < 0.f && temp > -thr) temp = -thr;
float temp = rtengine::max(std::fabs(WavCoeffs_LL[dir][i * W_L + j]), thr);
koeLi[level * 3 + dir - 1][i * W_L + j] = rtengine::min(thr2, std::fabs(tmC[i][j] / temp)); // limit maxi
@@ -2942,22 +2972,22 @@ void ImProcFunctions::finalContAllL(float ** WavCoeffs_L, float * WavCoeffs_L0,
if (cp.diagcurv && cp.finena && MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { //curve
float insigma = 0.666f; //SD
float logmax = log(MaxP[level]); //log Max
- float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max
+ float rapX = (mean[level] + cp.sigmafin * sigma[level]) / MaxP[level]; //rapport between sD / max
float inx = log(insigma);
float iny = log(rapX);
float rap = inx / iny; //koef
- float asig = 0.166f / sigma[level];
+ float asig = 0.166f / (sigma[level] * cp.sigmafin);
float bsig = 0.5f - asig * mean[level];
float amean = 0.5f / mean[level];
#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic, W_L * 16) num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel for schedule(dynamic, W_L * 16) num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
for (int i = 0; i < W_L * H_L; i++) {
float absciss;
- if (std::fabs(WavCoeffs_L[dir][i]) >= (mean[level] + sigma[level])) { //for max
+ if (std::fabs(WavCoeffs_L[dir][i]) >= (mean[level] + cp.sigmafin * sigma[level])) { //for max
float valcour = xlogf(std::fabs(WavCoeffs_L[dir][i]));
float valc = valcour - logmax;
float vald = valc * rap;
@@ -3091,7 +3121,7 @@ void ImProcFunctions::finalContAllL(float ** WavCoeffs_L, float * WavCoeffs_L0,
}
void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz, int maxlvl, LabImage * labco, float ** varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp,
- int W_L, int H_L, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili)
+ int W_L, int H_L, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveSH & waOpacityCurveSH, FlatCurve* ChCurve, bool Chutili)
{
assert(level >= 0);
assert(maxlvl > level);
@@ -3115,12 +3145,16 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
constexpr float aedstr = (eddstrength - 1.f) / 90.f;
constexpr float bedstr = 1.f - 10.f * aedstr;
- float mea[10];
- float beta = 1.f;
+ std::unique_ptr beta(new float[W_L * H_L]);
+
+ for (int co = 0; co < H_L * W_L; co++) {
+ beta[co] = 1.f;
+ }
if (cp.eff < 2.5f) {
float effect = cp.eff;
float offs = 1.f;
+ float mea[10];
calceffect(level, mean, sigma, mea, effect, offs);
@@ -3128,27 +3162,27 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
float WavCL = std::fabs(WavCoeffs_L[dir][co]);
if (WavCL < mea[0]) {
- beta = 0.05f;
+ beta[co] = 0.05f;
} else if (WavCL < mea[1]) {
- beta = 0.2f;
+ beta[co] = 0.2f;
} else if (WavCL < mea[2]) {
- beta = 0.7f;
+ beta[co] = 0.7f;
} else if (WavCL < mea[3]) {
- beta = 1.f; //standard
+ beta[co] = 1.f; //standard
} else if (WavCL < mea[4]) {
- beta = 1.f;
+ beta[co] = 1.f;
} else if (WavCL < mea[5]) {
- beta = 0.8f; //+sigma
+ beta[co] = 0.8f; //+sigma
} else if (WavCL < mea[6]) {
- beta = 0.6f;
+ beta[co] = 0.6f;
} else if (WavCL < mea[7]) {
- beta = 0.4f;
+ beta[co] = 0.4f;
} else if (WavCL < mea[8]) {
- beta = 0.2f; // + 2 sigma
+ beta[co] = 0.2f; // + 2 sigma
} else if (WavCL < mea[9]) {
- beta = 0.1f;
+ beta[co] = 0.1f;
} else {
- beta = 0.0f;
+ beta[co] = 0.0f;
}
}
@@ -3247,7 +3281,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
value *= (atten01234 * scaleskip[1]); //for zoom < 100% reduce strength...I choose level 1...but!!
}
- value *= beta;
+ // value *= beta;
float edge = 1.f;
float lim0 = 20.f; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi
float lev = float (level);
@@ -3312,7 +3346,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
float edgePrecalc = 1.f + refin; //estimate edge "pseudo variance"
if (cp.EDmet == 2 && MaxP[level] > 0.f) { //curve
- // if(exa) {//curve
+ // if (exa) {//curve
float insigma = 0.666f; //SD
float logmax = log(MaxP[level]); //log Max
float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max
@@ -3407,7 +3441,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
edge = rtengine::max(edge, 1.f);
}
- WavCoeffs_L[dir][k] *= edge;
+ WavCoeffs_L[dir][k] *= (1.f + (edge - 1.f) * beta[k]);
}
}
} else if (cp.EDmet == 1) { //threshold adjuster
@@ -3524,7 +3558,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
}
}
- WavCoeffs_L[dir][k] *= edge;
+ WavCoeffs_L[dir][k] *= (1.f + (edge - 1.f) * beta[k]);
}
}
}
@@ -3532,6 +3566,9 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
if (!lipschitz) {
delete [] koe;
}
+ if (!(cp.bam && cp.finena)) {
+ beta.reset();
+ }
}
@@ -3571,7 +3608,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
const float lowthr = params->wavelet.lowthr;
float mea[10];
float effect = cp.sigm;
- float beta;
+ float lbeta;
calceffect(level, mean, sigma, mea, effect, offs);
@@ -3583,37 +3620,38 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
float red2 = 0.011f * (110.f - lowthr);
for (int i = 0; i < W_L * H_L; i++) {
- float kLlev = 1.f;
+ float kLlevH = 1.f;
+ float kLlevS = 1.f;
if (cpMul < 0.f) {
- beta = 1.f; // disabled for negatives values "less contrast"
+ lbeta = 1.f; // disabled for negatives values "less contrast"
} else {
float WavCL = std::fabs(WavCoeffs_L[dir][i]);
//reduction amplification: max action between mean / 2 and mean + sigma
// arbitrary coefficient, we can add a slider !!
if (WavCL < mea[0]) {
- beta = 0.4f * red0;//preserve very low contrast (sky...)
+ lbeta = 0.4f * red0;//preserve very low contrast (sky...)
} else if (WavCL < mea[1]) {
- beta = 0.5f * red1;
+ lbeta = 0.5f * red1;
} else if (WavCL < mea[2]) {
- beta = 0.7f * red2;
+ lbeta = 0.7f * red2;
} else if (WavCL < mea[3]) {
- beta = 1.f; //standard
+ lbeta = 1.f; //standard
} else if (WavCL < mea[4]) {
- beta = 1.f;
+ lbeta = 1.f;
} else if (WavCL < mea[5]) {
- beta = 0.8f; //+sigma
+ lbeta = 0.8f; //+sigma
} else if (WavCL < mea[6]) {
- beta = 0.6f;
+ lbeta = 0.6f;
} else if (WavCL < mea[7]) {
- beta = 0.4f;
+ lbeta = 0.4f;
} else if (WavCL < mea[8]) {
- beta = 0.2f; // + 2 sigma
+ lbeta = 0.2f; // + 2 sigma
} else if (WavCL < mea[9]) {
- beta = 0.1f;
+ lbeta = 0.1f;
} else {
- beta = 0.0f;
+ lbeta = 0.0f;
}
}
@@ -3673,9 +3711,10 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
//linear transition HL
float diagacc = 1.f;
- float alpha = (1024.f + 15.f * (float) cpMul * scale * scale2 * beta * diagacc) / 1024.f ;
+ float alpha = (1024.f + 15.f * (float) cpMul * scale * scale2 * lbeta * diagacc) / 1024.f ;
- if (cp.HSmet && cp.contena) {
+ // if (cp.HSmet && cp.contena) {
+ if (cp.HSmet && cp.contena && waOpacityCurveSH) {
float aaal = (1.f - alpha) / ((cp.b_lhl - cp.t_lhl) * kH[level]);
float bbal = 1.f - aaal * cp.b_lhl * kH[level];
float aaar = (alpha - 1.f) / (cp.t_rhl - cp.b_rhl) * kH[level];
@@ -3686,35 +3725,40 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
float aaarS = (alpha - 1.f) / (cp.t_rsl - cp.b_rsl);
float bbbrS = 1.f - cp.b_rsl * aaarS;
- if (level <= cp.numlevH) { //in function of levels
+// if (level <= cp.numlevH) { //in function of levels
+ float klevred = 2.f * (waOpacityCurveSH[level * 55.5f] - 0.5f);
+ if(klevred > 0.f && level <= 6) {// level < 6 to avoid bad use of the curve if user put negative values positives
if ((LL100 > cp.t_lhl * kH[level] && LL100 < cp.t_rhl * kH[level])) {
- kLlev = alpha;
+ kLlevH = alpha;
} else if ((LL100 > cp.b_lhl * kH[level] && LL100 <= cp.t_lhl * kH[level])) {
- kLlev = aaal * LL100 + bbal;
+ kLlevH = aaal * LL100 + bbal;
} else if ((LL100 > cp.t_rhl * kH[level] && LL100 <= cp.b_rhl * kH[level])) {
- kLlev = aaar * LL100 + bbbr;
+ kLlevH = aaar * LL100 + bbbr;
} else {
- kLlev = 1.f;
+ kLlevH = 1.f;
}
+ kLlevH = 1.f + (kLlevH - 1.f) * klevred;
}
- if (level >= (9 - cp.numlevS)) {
+ // if (level >= (9 - cp.numlevS)) {
+ if(klevred < 0.f && level >= 3) {//level > 3 to avoid bad use of the curve if user put positives values negatives
if ((LL100 > cp.t_lsl && LL100 < cp.t_rsl)) {
- kLlev = alpha;
+ kLlevS = alpha;
} else if ((LL100 > cp.b_lsl && LL100 <= cp.t_lsl)) {
- kLlev = aaalS * LL100 + bbalS;
+ kLlevS = aaalS * LL100 + bbalS;
} else if ((LL100 > cp.t_rsl && LL100 <= cp.b_rsl)) {
- kLlev = aaarS * LL100 + bbbrS;
+ kLlevS = aaarS * LL100 + bbbrS;
} else {
- kLlev = 1.f;
+ kLlevS = 1.f;
}
+ kLlevS = 1.f - (kLlevS - 1.f) * klevred;
}
} else {
- kLlev = alpha;
+ kLlevH = kLlevS = alpha;
}
- WavCoeffs_L[dir][i] *= (kLlev);
+ WavCoeffs_L[dir][i] *= (kLlevH * kLlevS);
}
}
@@ -3723,6 +3767,40 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
}
if (cp.bam && cp.finena) {
+ const float effect = cp.sigmadir;
+ constexpr float offs = 1.f;
+ float mea[10];
+
+ 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]);
+
+ if (WavCL < mea[0]) {
+ beta[co] = 0.05f;
+ } else if (WavCL < mea[1]) {
+ beta[co] = 0.2f;
+ } else if (WavCL < mea[2]) {
+ beta[co] = 0.7f;
+ } else if (WavCL < mea[3]) {
+ beta[co] = 1.f; //standard
+ } else if (WavCL < mea[4]) {
+ beta[co] = 1.f;
+ } else if (WavCL < mea[5]) {
+ beta[co] = 0.8f; //+sigma
+ } else if (WavCL < mea[6]) {
+ beta[co] = 0.6f;
+ } else if (WavCL < mea[7]) {
+ beta[co] = 0.4f;
+ } else if (WavCL < mea[8]) {
+ beta[co] = 0.2f; // + 2 sigma
+ } else if (WavCL < mea[9]) {
+ beta[co] = 0.1f;
+ } else {
+ beta[co] = 0.01f;
+ }
+ }
+
if (cp.opaW && cp.BAmet == 2) {
int iteration = cp.ite;
int itplus = 7 + iteration;
@@ -3734,7 +3812,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
it = itmoins;
} else if (level == med) {
it = 7;
- } else { /*if(level > med)*/
+ } else { /*if (level > med)*/
it = itplus;
}
@@ -3742,8 +3820,8 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
//float bal = cp.balan;//-100 +100
float kba = 1.f;
- // if(dir <3) kba= 1.f + bal/600.f;
- // if(dir==3) kba = 1.f - bal/300.f;
+ // if (dir <3) kba= 1.f + bal/600.f;
+ // if (dir==3) kba = 1.f - bal/300.f;
for (int i = 0; i < W_L * H_L; i++) {
int ii = i / W_L;
int jj = i - ii * W_L;
@@ -3759,7 +3837,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
kba = 1.f - k2;
}
- WavCoeffs_L[dir][i] *= (kba);
+ WavCoeffs_L[dir][i] *= (1.f + (kba - 1.f) * beta[i]);
}
}
}
@@ -3775,7 +3853,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
it = itmoins;
} else if (level == med) {
it = 7;
- } else { /*if(level > med)*/
+ } else { /*if (level > med)*/
it = itplus;
}
@@ -3783,8 +3861,8 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
float bal = cp.balan;//-100 +100
float kba = 1.f;
- // if(dir <3) kba= 1.f + bal/600.f;
- // if(dir==3) kba = 1.f - bal/300.f;
+ // if (dir <3) kba= 1.f + bal/600.f;
+ // if (dir==3) kba = 1.f - bal/300.f;
for (int i = 0; i < W_L * H_L; i++) {
int ii = i / W_L;
int jj = i - ii * W_L;
@@ -3818,11 +3896,10 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
kba = 1.f - bal / k2;
}
- WavCoeffs_L[dir][i] *= (kba);
+ WavCoeffs_L[dir][i] *= (1.f + (kba - 1.f) * beta[i]);
}
}
}
-
}
// to see each level of wavelet ...level from 0 to 8
@@ -3831,7 +3908,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
}
void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, float **varchrom, float ** WavCoeffs_ab, float * WavCoeffs_ab0, int level, int dir, const WavOpacityCurveW & waOpacityCurveW, struct cont_params &cp,
- int W_ab, int H_ab, const bool useChannelA)
+ int W_ab, int H_ab, const bool useChannelA, float *meanab, float *sigmaab)
{
float cpMul = cp.mul[level];
@@ -3843,9 +3920,43 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
//to adjust increase contrast with local contrast
bool useSkinControl = (skinprot != 0.f);
- float alphaC = (1024.f + 15.f * cpMul * cpChrom / 50.f) / 1024.f ;
+
+ float mea[10];
+ float effect = cp.sigmacol;
+ float betaab;
+ float offs = 1.f;
+
+ calceffect(level, meanab, sigmaab, mea, effect, offs);
for (int i = 0; i < W_ab * H_ab; i++) {
+ float WavCab = std::fabs(WavCoeffs_ab[dir][i]);
+
+ if (WavCab < mea[0]) {
+ betaab = 0.05f;
+ } else if (WavCab < mea[1]) {
+ betaab = 0.2f;
+ } else if (WavCab < mea[2]) {
+ betaab = 0.7f;
+ } else if (WavCab < mea[3]) {
+ betaab = 1.f; //standard
+ } else if (WavCab < mea[4]) {
+ betaab = 1.f;
+ } else if (WavCab < mea[5]) {
+ betaab = 0.8f; //+sigma
+ } else if (WavCab < mea[6]) {
+ betaab = 0.6f;
+ } else if (WavCab < mea[7]) {
+ betaab = 0.4f;
+ } else if (WavCab < mea[8]) {
+ betaab = 0.2f; // + 2 sigma
+ } else if (WavCab < mea[9]) {
+ betaab = 0.1f;
+ } else {
+ betaab = 0.0f;
+ }
+
+ float scale = 1.f;
+
if (useSkinControl) {
int ii = i / W_ab;
int jj = i - ii * W_ab;
@@ -3853,7 +3964,6 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
float modhue = varhue[ii][jj];
float modchro = varchrom[ii * 2][jj * 2];
// hue chroma skin with initial lab data
- float scale = 1.f;
if (skinprot > 0.f) {
Color::SkinSatCbdl2(LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); //0 for skin and extand
@@ -3862,9 +3972,10 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
scale = (scale == 1.f) ? factorHard : 1.f;
}
- alphaC = (1024.f + 15.f * cpMul * cpChrom * scale / 50.f) / 1024.f ;
}
+ const float alphaC = (1024.f + 15.f * cpMul * cpChrom * betaab * scale / 50.f) / 1024.f ;
+
WavCoeffs_ab[dir][i] *= alphaC;
}
}
@@ -3873,14 +3984,48 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
float cpMulC = cp.mulC[level];
- // if( (cp.curv || cp.CHSLmet==1) && cp.CHmet!=2 && level < 9 && cpMulC != 0.f) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip
+ // if ( (cp.curv || cp.CHSLmet==1) && cp.CHmet!=2 && level < 9 && cpMulC != 0.f) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip
if (cp.CHmet != 2 && level < 9 && cpMulC != 0.f && cp.chromena) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip
const float skinprot = params->wavelet.skinprotect;
const float skinprotneg = -skinprot;
const float factorHard = (1.f - skinprotneg / 100.f);
bool useSkinControl = (skinprot != 0.f);
+
+ float mea[10];
+ float effect = cp.sigmacol;
+ float betaab;
+ float offs = 1.f;
+
+ calceffect(level, meanab, sigmaab, mea, effect, offs);
+
for (int i = 0; i < W_ab * H_ab; i++) {
+ float WavCab = std::fabs(WavCoeffs_ab[dir][i]);
+
+ if (WavCab < mea[0]) {
+ betaab = 0.05f;
+ } else if (WavCab < mea[1]) {
+ betaab = 0.2f;
+ } else if (WavCab < mea[2]) {
+ betaab = 0.7f;
+ } else if (WavCab < mea[3]) {
+ betaab = 1.f; //standard
+ } else if (WavCab < mea[4]) {
+ betaab = 1.f;
+ } else if (WavCab < mea[5]) {
+ betaab = 0.8f; //+sigma
+ } else if (WavCab < mea[6]) {
+ betaab = 0.6f;
+ } else if (WavCab < mea[7]) {
+ betaab = 0.4f;
+ } else if (WavCab < mea[8]) {
+ betaab = 0.2f; // + 2 sigma
+ } else if (WavCab < mea[9]) {
+ betaab = 0.1f;
+ } else {
+ betaab = 0.0f;
+ }
+
int ii = i / W_ab;
int jj = i - ii * W_ab;
//WL and W_ab are identical
@@ -3900,7 +4045,7 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
}
}
- float beta = (1024.f + 20.f * cpMulC * scale) / 1024.f ;
+ float beta = (1024.f + 20.f * cpMulC * scale * betaab) / 1024.f ;
if (beta < 0.02f) {
beta = 0.02f;
@@ -3966,15 +4111,112 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
}
if ((useOpacity && level < 9 && mulOpacity != 0.f) && cp.toningena) { //toning
+ float mea[10];
+ float effect = cp.sigmaton;
+ float betaab;
+ float offs = 1.f;
+ float protec = 0.01f * (100.f - cp.protab);
+ float aref1 = cp.a_high;
+ float bref1 = cp.b_high;
+ float aref2 = cp.a_low;
+ float bref2 = cp.b_low;
- float beta = (1024.f + 20.f * mulOpacity) / 1024.f ;
+ float kk = 100.f;
+ float arefplus1 = aref1 + cp.rangeab * kk;
+ float arefmoins1 = aref1 - cp.rangeab * kk;
+ float brefplus1 = bref1 + cp.rangeab * kk;
+ float brefmoins1 = bref1 - cp.rangeab * kk;
- //float beta = (1000.f * mulOpacity);
- for (int i = 0; i < W_ab * H_ab; i++) {
- WavCoeffs_ab[dir][i] *= beta;
+ float arefplus2 = aref2 + cp.rangeab * kk;
+ float arefmoins2 = aref2 - cp.rangeab * kk;
+ float brefplus2 = bref2 + cp.rangeab * kk;
+ float brefmoins2 = bref2 - cp.rangeab * kk;
+
+ calceffect(level, meanab, sigmaab, mea, effect, offs);
+
+ for (int co = 0; co < W_ab * H_ab; co++) {
+ float WavCab = std::fabs(WavCoeffs_ab[dir][co]);
+
+ if (WavCab < mea[0]) {
+ betaab = 0.05f;
+ } else if (WavCab < mea[1]) {
+ betaab = 0.2f;
+ } else if (WavCab < mea[2]) {
+ betaab = 0.7f;
+ } else if (WavCab < mea[3]) {
+ betaab = 1.f; //standard
+ } else if (WavCab < mea[4]) {
+ betaab = 1.f;
+ } else if (WavCab < mea[5]) {
+ betaab = 0.8f; //+sigma
+ } else if (WavCab < mea[6]) {
+ betaab = 0.6f;
+ } else if (WavCab < mea[7]) {
+ betaab = 0.4f;
+ } else if (WavCab < mea[8]) {
+ betaab = 0.2f; // + 2 sigma
+ } else if (WavCab < mea[9]) {
+ betaab = 0.1f;
+ } else {
+ betaab = 0.0f;
+ }
+
+ float kreduc1 = 1.f;
+ float kreduc2 = 1.f;
+ int ii = co / W_ab;
+ int jj = co - ii * W_ab;
+
+ // cp.protab = 0.f;// always disabled provisory...
+ if (cp.protab > 0.f) {
+ if (useChannelA) {
+ if ((labco->a[ii * 2][jj * 2] > arefmoins1) && (labco->a[ii * 2][jj * 2] < arefplus1)) {
+ kreduc1 = 0.5f * protec;
+
+ if ((labco->a[ii * 2][jj * 2] > 0.8f * arefmoins1) && (labco->a[ii * 2][jj * 2] < 0.8f * arefplus1)) {
+ kreduc1 = protec;
+ }
+ }
+
+ } else {
+ if ((labco->b[ii * 2][jj * 2] > brefmoins1) && (labco->b[ii * 2][jj * 2] < brefplus1)) {
+ kreduc1 = 0.5f * protec;
+
+ if ((labco->b[ii * 2][jj * 2] > 0.8f * brefmoins1) && (labco->b[ii * 2][jj * 2] < 0.8f * brefplus1)) {
+ kreduc1 = protec;
+ }
+ }
+ }
+
+ if (useChannelA) {
+ if ((labco->a[ii * 2][jj * 2] > arefmoins2) && (labco->a[ii * 2][jj * 2] < arefplus2)) {
+ kreduc2 = 0.5f * protec;
+
+ if ((labco->a[ii * 2][jj * 2] > 0.8f * arefmoins2) && (labco->a[ii * 2][jj * 2] < 0.8f * arefplus2)) {
+ kreduc2 = protec;
+ }
+
+ }
+ } else {
+ if ((labco->b[ii * 2][jj * 2] > brefmoins2) && (labco->b[ii * 2][jj * 2] < brefplus2)) {
+ kreduc2 = 0.5f * protec;
+
+ if ((labco->b[ii * 2][jj * 2] > brefmoins2) && (labco->b[ii * 2][jj * 2] < brefplus2)) {
+ kreduc2 = protec;
+ }
+ }
+ }
+
+ }
+
+
+ // printf("pa1=%f pa2=%f\n", kreduc1, kredu2);
+
+
+ float beta = (1024.f + 50.f * mulOpacity * betaab * kreduc1 * kreduc2) / 1024.f ;
+
+ WavCoeffs_ab[dir][co] *= beta;
}
- // WavCoeffs_ab[dir][i] += beta;
}
if (waOpacityCurveW) {
@@ -3993,7 +4235,7 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
it = itmoins;
} else if (level == med) {
it = 7;
- } else { /*if(level > med)*/
+ } else { /*if (level > med)*/
it = itplus;
}
@@ -4001,8 +4243,8 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
//float bal = cp.balan;//-100 +100
float kba = 1.f;
- // if(dir <3) kba= 1.f + bal/600.f;
- // if(dir==3) kba = 1.f - bal/300.f;
+ // if (dir <3) kba= 1.f + bal/600.f;
+ // if (dir==3) kba = 1.f - bal/300.f;
for (int i = 0; i < W_ab * H_ab; i++) {
int ii = i / W_ab;
int jj = i - ii * W_ab;
@@ -4034,7 +4276,7 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
it = itmoins;
} else if (level == med) {
it = 7;
- } else { /*if(level > med)*/
+ } else { /*if (level > med)*/
it = itplus;
}
@@ -4042,8 +4284,8 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
float bal = cp.balan;//-100 +100
float kba = 1.f;
- // if(dir <3) kba= 1.f + bal/600.f;
- // if(dir==3) kba = 1.f - bal/300.f;
+ // if (dir <3) kba= 1.f + bal/600.f;
+ // if (dir==3) kba = 1.f - bal/300.f;
for (int i = 0; i < W_ab * H_ab; i++) {
int ii = i / W_ab;
int jj = i - ii * W_ab;
@@ -4187,191 +4429,4 @@ 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 00a261056..56cccb4bb 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -2148,6 +2148,10 @@ bool ColorManagementParams::operator !=(const ColorManagementParams& other) cons
return !(*this == other);
}
+const double WaveletParams::LABGRID_CORR_MAX = 12800.f;
+const double WaveletParams::LABGRID_CORR_SCALE = 3.276f;
+const double WaveletParams::LABGRIDL_DIRECT_SCALE = 41950.;
+
WaveletParams::WaveletParams() :
ccwcurve{
static_cast(FCT_MinMaxCPoints),
@@ -2166,15 +2170,18 @@ WaveletParams::WaveletParams() :
},
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*/
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.35,
+ 0.5,
+ 0.,
+ 0.35,
+ 0.35,
+ 1.0,
+ 0.0,
+ 0.35,
+ 0.35
},
opacityCurveRG{
static_cast(FCT_MinMaxCPoints),
@@ -2187,6 +2194,25 @@ WaveletParams::WaveletParams() :
0.35,
0.35
},
+ opacityCurveSH{
+ static_cast(FCT_MinMaxCPoints),
+ 0.0,
+ 1.,
+ 0.35,
+ 0.35,
+ 0.4,
+ 0.5,
+ 0.35,
+ 0.35,
+ 0.5,
+ 0.5,
+ 0.35,
+ 0.35,
+ 1.,
+ 0.,
+ 0.35,
+ 0.35
+ },
opacityCurveBY{
static_cast(FCT_MinMaxCPoints),
0.0,
@@ -2263,6 +2289,12 @@ WaveletParams::WaveletParams() :
tmr(false),
strength(100),
balance(0),
+ sigmafin(1.0),
+ sigmaton(1.0),
+ sigmacol(1.0),
+ sigmadir(1.0),
+ rangeab(20.0),
+ protab(0.0),
iter(0),
expcontrast(false),
expchroma(false),
@@ -2275,6 +2307,10 @@ WaveletParams::WaveletParams() :
exptoning(false),
expnoise(false),
expclari(false),
+ labgridALow(0.0),
+ labgridBLow(0.0),
+ labgridAHigh(0.0),
+ labgridBHigh(0.0),
Lmethod(4),
CLmethod("all"),
Backmethod("grey"),
@@ -2308,7 +2344,7 @@ WaveletParams::WaveletParams() :
chroma(5),
chro(0),
threshold(5),
- threshold2(4),
+ threshold2(5),
edgedetect(90),
edgedetectthr(20),
edgedetectthr2(0),
@@ -2345,6 +2381,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
ccwcurve == other.ccwcurve
&& blcurve == other.blcurve
&& opacityCurveRG == other.opacityCurveRG
+ && opacityCurveSH == other.opacityCurveSH
&& opacityCurveBY == other.opacityCurveBY
&& opacityCurveW == other.opacityCurveW
&& opacityCurveWL == other.opacityCurveWL
@@ -2377,7 +2414,17 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& tmr == other.tmr
&& strength == other.strength
&& balance == other.balance
+ && sigmafin == other.sigmafin
+ && sigmaton == other.sigmaton
+ && sigmacol == other.sigmacol
+ && sigmadir == other.sigmadir
+ && rangeab == other.rangeab
+ && protab == other.protab
&& iter == other.iter
+ && labgridALow == other.labgridALow
+ && labgridBLow == other.labgridBLow
+ && labgridAHigh == other.labgridAHigh
+ && labgridBHigh == other.labgridBHigh
&& expcontrast == other.expcontrast
&& expchroma == other.expchroma
&& [this, &other]() -> bool
@@ -2468,6 +2515,7 @@ void WaveletParams::getCurves(
WavCurve& cCurve,
Wavblcurve& tCurve,
WavOpacityCurveRG& opacityCurveLUTRG,
+ WavOpacityCurveSH& opacityCurveLUTSH,
WavOpacityCurveBY& opacityCurveLUTBY,
WavOpacityCurveW& opacityCurveLUTW,
WavOpacityCurveWL& opacityCurveLUTWL
@@ -2476,6 +2524,7 @@ void WaveletParams::getCurves(
cCurve.Set(this->ccwcurve);
tCurve.Set(this->blcurve);
opacityCurveLUTRG.Set(this->opacityCurveRG);
+ opacityCurveLUTSH.Set(this->opacityCurveSH);
opacityCurveLUTBY.Set(this->opacityCurveBY);
opacityCurveLUTW.Set(this->opacityCurveW);
opacityCurveLUTWL.Set(this->opacityCurveWL);
@@ -2807,6 +2856,23 @@ Glib::ustring RAWParams::XTransSensor::getMethodString(Method method)
return getMethodStrings()[toUnderlying(method)];
}
+
+RAWParams::PreprocessWB::PreprocessWB() :
+ mode(Mode::AUTO)
+{
+}
+
+bool RAWParams::PreprocessWB::operator ==(const PreprocessWB& other) const
+{
+ return mode == other.mode;
+}
+
+bool RAWParams::PreprocessWB::operator !=(const PreprocessWB& other) const
+{
+ return !(*this == other);
+}
+
+
RAWParams::RAWParams() :
df_autoselect(false),
ff_AutoSelect(false),
@@ -2845,6 +2911,7 @@ bool RAWParams::operator ==(const RAWParams& other) const
&& cared == other.cared
&& cablue == other.cablue
&& expos == other.expos
+ && preprocessWB == other.preprocessWB
&& hotPixelFilter == other.hotPixelFilter
&& deadPixelFilter == other.deadPixelFilter
&& hotdeadpix_thresh == other.hotdeadpix_thresh;
@@ -3521,6 +3588,12 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.enabled, "Wavelet", "Enabled", wavelet.enabled, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.strength, "Wavelet", "Strength", wavelet.strength, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.balance, "Wavelet", "Balance", wavelet.balance, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.sigmafin, "Wavelet", "Sigmafin", wavelet.sigmafin, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.sigmaton, "Wavelet", "Sigmaton", wavelet.sigmaton, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.sigmacol, "Wavelet", "Sigmacol", wavelet.sigmacol, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.sigmadir, "Wavelet", "Sigmadir", wavelet.sigmadir, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.rangeab, "Wavelet", "Rangeab", wavelet.rangeab, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.protab, "Wavelet", "Protab", wavelet.protab, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.iter, "Wavelet", "Iter", wavelet.iter, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.thres, "Wavelet", "MaxLev", wavelet.thres, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.Tilesmethod, "Wavelet", "TilesMethod", wavelet.Tilesmethod, keyFile);
@@ -3552,6 +3625,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.exptoning, "Wavelet", "Exptoning", wavelet.exptoning, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expnoise, "Wavelet", "Expnoise", wavelet.expnoise, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expclari, "Wavelet", "Expclari", wavelet.expclari, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.labgridALow, "Wavelet", "LabGridALow", wavelet.labgridALow, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.labgridBLow, "Wavelet", "LabGridBLow", wavelet.labgridBLow, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.labgridAHigh, "Wavelet", "LabGridAHigh", wavelet.labgridAHigh, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.labgridBHigh, "Wavelet", "LabGridBHigh", wavelet.labgridBHigh, keyFile);
for (int i = 0; i < 9; i++) {
std::stringstream ss;
@@ -3598,6 +3675,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
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);
+ saveToKeyfile(!pedited || pedited->wavelet.opacityCurveSH, "Wavelet", "Levalshc", wavelet.opacityCurveSH, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveBY, "Wavelet", "OpacityCurveBY", wavelet.opacityCurveBY, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveW, "Wavelet", "OpacityCurveW", wavelet.opacityCurveW, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveWL, "Wavelet", "OpacityCurveWL", wavelet.opacityCurveWL, keyFile);
@@ -3800,6 +3878,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->filmNegative.baseValues, "Film Negative", "GreenBase", filmNegative.greenBase, keyFile);
saveToKeyfile(!pedited || pedited->filmNegative.baseValues, "Film Negative", "BlueBase", filmNegative.blueBase, keyFile);
+// Preprocess WB
+ saveToKeyfile(!pedited || pedited->raw.preprocessWB.mode, "RAW Preprocess WB", "Mode", toUnderlying(raw.preprocessWB.mode), keyFile);
+
// EXIF change list
if (!pedited || pedited->exif) {
for (ExifPairs::const_iterator i = exif.begin(); i != exif.end(); ++i) {
@@ -4701,6 +4782,12 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "Enabled", pedited, wavelet.enabled, pedited->wavelet.enabled);
assignFromKeyfile(keyFile, "Wavelet", "Strength", pedited, wavelet.strength, pedited->wavelet.strength);
assignFromKeyfile(keyFile, "Wavelet", "Balance", pedited, wavelet.balance, pedited->wavelet.balance);
+ assignFromKeyfile(keyFile, "Wavelet", "Sigmafin", pedited, wavelet.sigmafin, pedited->wavelet.sigmafin);
+ assignFromKeyfile(keyFile, "Wavelet", "Sigmaton", pedited, wavelet.sigmaton, pedited->wavelet.sigmaton);
+ assignFromKeyfile(keyFile, "Wavelet", "Sigmacol", pedited, wavelet.sigmacol, pedited->wavelet.sigmacol);
+ assignFromKeyfile(keyFile, "Wavelet", "Sigmadir", pedited, wavelet.sigmadir, pedited->wavelet.sigmadir);
+ assignFromKeyfile(keyFile, "Wavelet", "Rangeab", pedited, wavelet.rangeab, pedited->wavelet.rangeab);
+ assignFromKeyfile(keyFile, "Wavelet", "Protab", pedited, wavelet.protab, pedited->wavelet.protab);
assignFromKeyfile(keyFile, "Wavelet", "Iter", pedited, wavelet.iter, pedited->wavelet.iter);
assignFromKeyfile(keyFile, "Wavelet", "Median", pedited, wavelet.median, pedited->wavelet.median);
assignFromKeyfile(keyFile, "Wavelet", "Medianlev", pedited, wavelet.medianlev, pedited->wavelet.medianlev);
@@ -4725,6 +4812,10 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "Showmask", pedited, wavelet.showmask, pedited->wavelet.showmask);
assignFromKeyfile(keyFile, "Wavelet", "Oldsh", pedited, wavelet.oldsh, pedited->wavelet.oldsh);
assignFromKeyfile(keyFile, "Wavelet", "TMr", pedited, wavelet.tmr, pedited->wavelet.tmr);
+ assignFromKeyfile(keyFile, "Wavelet", "LabGridALow", pedited, wavelet.labgridALow, pedited->wavelet.labgridALow);
+ assignFromKeyfile(keyFile, "Wavelet", "LabGridBLow", pedited, wavelet.labgridBLow, pedited->wavelet.labgridBLow);
+ assignFromKeyfile(keyFile, "Wavelet", "LabGridAHigh", pedited, wavelet.labgridAHigh, pedited->wavelet.labgridAHigh);
+ assignFromKeyfile(keyFile, "Wavelet", "LabGridBHigh", pedited, wavelet.labgridBHigh, pedited->wavelet.labgridBHigh);
if (ppVersion < 331) { // wavelet.Lmethod was a string before version 331
Glib::ustring temp;
@@ -4787,6 +4878,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
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", "Levelshc", pedited, wavelet.opacityCurveSH, pedited->wavelet.opacityCurveSH);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveBY", pedited, wavelet.opacityCurveBY, pedited->wavelet.opacityCurveBY);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveW", pedited, wavelet.opacityCurveW, pedited->wavelet.opacityCurveW);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveWL", pedited, wavelet.opacityCurveWL, pedited->wavelet.opacityCurveWL);
@@ -5416,6 +5508,16 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
}
+ if (keyFile.has_group("RAW Preprocess WB")) {
+ if (keyFile.has_key("RAW Preprocess WB", "Mode")) {
+ raw.preprocessWB.mode = RAWParams::PreprocessWB::Mode(keyFile.get_integer("RAW Preprocess WB", "Mode"));
+
+ if (pedited) {
+ pedited->raw.preprocessWB.mode = true;
+ }
+ }
+ }
+
if (keyFile.has_group("MetaData")) {
int mode = int(MetaDataParams::TUNNEL);
assignFromKeyfile(keyFile, "MetaData", "Mode", pedited, mode, pedited->metadata.mode);
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index f33214d44..4e7f6d3ff 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -42,6 +42,7 @@ class RetinextransmissionCurve;
class WavCurve;
class Wavblcurve;
class WavOpacityCurveBY;
+class WavOpacityCurveSH;
class WavOpacityCurveRG;
class WavOpacityCurveW;
class WavOpacityCurveWL;
@@ -1187,7 +1188,9 @@ private:
struct WaveletParams {
std::vector ccwcurve;
std::vector blcurve;
+ std::vector levelshc;
std::vector opacityCurveRG;
+ std::vector opacityCurveSH;
std::vector opacityCurveBY;
std::vector opacityCurveW;
std::vector opacityCurveWL;
@@ -1221,6 +1224,12 @@ struct WaveletParams {
bool tmr;
int strength;
int balance;
+ double sigmafin;
+ double sigmaton;
+ double sigmacol;
+ double sigmadir;
+ double rangeab;
+ double protab;
int iter;
bool expcontrast;
bool expchroma;
@@ -1233,7 +1242,13 @@ struct WaveletParams {
bool exptoning;
bool expnoise;
bool expclari;
-
+ double labgridALow;
+ double labgridBLow;
+ double labgridAHigh;
+ double labgridBHigh;
+ static const double LABGRID_CORR_MAX;
+ static const double LABGRID_CORR_SCALE;
+ static const double LABGRIDL_DIRECT_SCALE;
int Lmethod;
Glib::ustring CLmethod;
Glib::ustring Backmethod;
@@ -1304,8 +1319,8 @@ struct WaveletParams {
void getCurves(
WavCurve& cCurve,
Wavblcurve& tCurve,
- WavOpacityCurveRG&
- opacityCurveLUTRG,
+ WavOpacityCurveRG& opacityCurveLUTRG,
+ WavOpacityCurveSH& opacityCurveLUTSH,
WavOpacityCurveBY& opacityCurveLUTBY,
WavOpacityCurveW& opacityCurveLUTW,
WavOpacityCurveWL& opacityCurveLUTWL
@@ -1538,6 +1553,22 @@ struct RAWParams {
// exposure before interpolation
double expos;
+ struct PreprocessWB {
+ enum class Mode {
+ CAMERA = 0,
+ AUTO
+ };
+
+ Mode mode;
+
+ PreprocessWB();
+
+ bool operator ==(const PreprocessWB& other) const;
+ bool operator !=(const PreprocessWB& other) const;
+ };
+
+ PreprocessWB preprocessWB;
+
bool hotPixelFilter;
bool deadPixelFilter;
int hotdeadpix_thresh;
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index a599f9a22..4f78dfbdb 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1161,25 +1161,8 @@ int RawImageSource::load (const Glib::ustring &fname, bool firstFrameOnly)
double cam_b = imatrices.rgb_cam[2][0] * camwb_red + imatrices.rgb_cam[2][1] * camwb_green + imatrices.rgb_cam[2][2] * camwb_blue;
camera_wb = ColorTemp (cam_r, cam_g, cam_b, 1.); // as shot WB
- ColorTemp ReferenceWB;
- double ref_r, ref_g, ref_b;
- {
- // ...then we re-get the constants but now with auto which gives us better demosaicing and CA auto-correct
- // performance for strange white balance settings (such as UniWB)
- ri->get_colorsCoeff(ref_pre_mul, scale_mul, c_black, true);
- refwb_red = ri->get_pre_mul(0) / ref_pre_mul[0];
- refwb_green = ri->get_pre_mul(1) / ref_pre_mul[1];
- refwb_blue = ri->get_pre_mul(2) / ref_pre_mul[2];
- initialGain = max(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]);
- ref_r = imatrices.rgb_cam[0][0] * refwb_red + imatrices.rgb_cam[0][1] * refwb_green + imatrices.rgb_cam[0][2] * refwb_blue;
- ref_g = imatrices.rgb_cam[1][0] * refwb_red + imatrices.rgb_cam[1][1] * refwb_green + imatrices.rgb_cam[1][2] * refwb_blue;
- ref_b = imatrices.rgb_cam[2][0] * refwb_red + imatrices.rgb_cam[2][1] * refwb_green + imatrices.rgb_cam[2][2] * refwb_blue;
- ReferenceWB = ColorTemp (ref_r, ref_g, ref_b, 1.);
- }
-
if (settings->verbose) {
printf("Raw As Shot White balance: temp %f, tint %f\n", camera_wb.getTemp(), camera_wb.getGreen());
- printf("Raw Reference (auto) white balance: temp %f, tint %f, multipliers [%f %f %f | %f %f %f]\n", ReferenceWB.getTemp(), ReferenceWB.getGreen(), ref_r, ref_g, ref_b, refwb_red, refwb_blue, refwb_green);
}
/*{
@@ -1249,6 +1232,28 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
MyTime t1, t2;
t1.set();
+ {
+ // Recalculate the scaling coefficients, using auto WB if selected in the Preprocess WB param.
+ // Auto WB gives us better demosaicing and CA auto-correct performance for strange white balance settings (such as UniWB)
+ float dummy_cblk[4] = { 0.f }; // Avoid overwriting c_black, see issue #5676
+ ri->get_colorsCoeff( ref_pre_mul, scale_mul, dummy_cblk, raw.preprocessWB.mode == RAWParams::PreprocessWB::Mode::AUTO);
+
+ refwb_red = ri->get_pre_mul(0) / ref_pre_mul[0];
+ refwb_green = ri->get_pre_mul(1) / ref_pre_mul[1];
+ refwb_blue = ri->get_pre_mul(2) / ref_pre_mul[2];
+ initialGain = max(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]);
+
+ const double ref_r = imatrices.rgb_cam[0][0] * refwb_red + imatrices.rgb_cam[0][1] * refwb_green + imatrices.rgb_cam[0][2] * refwb_blue;
+ const double ref_g = imatrices.rgb_cam[1][0] * refwb_red + imatrices.rgb_cam[1][1] * refwb_green + imatrices.rgb_cam[1][2] * refwb_blue;
+ const double ref_b = imatrices.rgb_cam[2][0] * refwb_red + imatrices.rgb_cam[2][1] * refwb_green + imatrices.rgb_cam[2][2] * refwb_blue;
+ const ColorTemp ReferenceWB = ColorTemp (ref_r, ref_g, ref_b, 1.);
+
+ if (settings->verbose) {
+ printf("Raw Reference white balance: temp %f, tint %f, multipliers [%f %f %f | %f %f %f]\n", ReferenceWB.getTemp(), ReferenceWB.getGreen(), ref_r, ref_g, ref_b, refwb_red, refwb_blue, refwb_green);
+ }
+ }
+
+
Glib::ustring newDF = raw.dark_frame;
RawImage *rid = nullptr;
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 14a594ac2..a53902737 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -1127,6 +1127,7 @@ private:
WavCurve wavCLVCurve;
Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
+ WavOpacityCurveSH waOpacityCurveSH;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
WavOpacityCurveWL waOpacityCurveWL;
@@ -1149,7 +1150,7 @@ private:
provradius->CopyFrom(labView);
}
- params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1);
@@ -1157,7 +1158,7 @@ private:
unshar = new LabImage(fw, fh);
provis = params.wavelet.CLmethod;
params.wavelet.CLmethod = "all";
- ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
+ ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
unshar->CopyFrom(labView);
params.wavelet.CLmethod = provis;
@@ -1169,7 +1170,7 @@ private:
WaveParams.expnoise = false;
}
- ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
+ ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
WaveParams.expcontrast = procont;
diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc
index 06604ade5..95b46c2b9 100644
--- a/rtexif/rtexif.cc
+++ b/rtexif/rtexif.cc
@@ -1510,8 +1510,6 @@ int Tag::toInt (int ofs, TagType astype) const
return attrib->interpreter->toInt (this, ofs, astype);
}
- int a;
-
if (astype == INVALID) {
astype = type;
}
@@ -1537,10 +1535,15 @@ int Tag::toInt (int ofs, TagType astype) const
case LONG:
return (int)sget4 (value + ofs, getOrder());
- case SRATIONAL:
- case RATIONAL:
- a = (int)sget4 (value + ofs + 4, getOrder());
+ case SRATIONAL: {
+ int a = (int)sget4 (value + ofs + 4, getOrder());
return a == 0 ? 0 : (int)sget4 (value + ofs, getOrder()) / a;
+ }
+
+ case RATIONAL: {
+ uint32_t a = (uint32_t)sget4 (value + ofs + 4, getOrder());
+ return a == 0 ? 0 : (uint32_t)sget4 (value + ofs, getOrder()) / a;
+ }
case FLOAT:
return (int)toDouble (ofs);
@@ -1589,10 +1592,14 @@ double Tag::toDouble (int ofs) const
return (double) ((int)sget4 (value + ofs, getOrder()));
case SRATIONAL:
- case RATIONAL:
ud = (int)sget4 (value + ofs, getOrder());
dd = (int)sget4 (value + ofs + 4, getOrder());
- return dd == 0. ? 0. : (double)ud / (double)dd;
+ return dd == 0. ? 0. : ud / dd;
+
+ case RATIONAL:
+ ud = (uint32_t)sget4 (value + ofs, getOrder());
+ dd = (uint32_t)sget4 (value + ofs + 4, getOrder());
+ return dd == 0. ? 0. : ud / dd;
case FLOAT:
conv.i = sget4 (value + ofs, getOrder());
@@ -1735,10 +1742,13 @@ void Tag::toString (char* buffer, int ofs) const
break;
case SRATIONAL:
- case RATIONAL:
sprintf (b, "%d/%d", (int)sget4 (value + 8 * i + ofs, getOrder()), (int)sget4 (value + 8 * i + ofs + 4, getOrder()));
break;
+ case RATIONAL:
+ sprintf (b, "%u/%u", (uint32_t)sget4 (value + 8 * i + ofs, getOrder()), (uint32_t)sget4 (value + 8 * i + ofs + 4, getOrder()));
+ break;
+
case FLOAT:
sprintf (b, "%g", toDouble (8 * i + ofs));
break;
diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h
index 1a956a4a5..5084f70de 100644
--- a/rtexif/rtexif.h
+++ b/rtexif/rtexif.h
@@ -434,13 +434,18 @@ public:
case LONG:
return (double) ((int)sget4 (t->getValue() + ofs, t->getOrder()));
- case SRATIONAL:
- case RATIONAL: {
+ case SRATIONAL: {
const double dividend = (int)sget4 (t->getValue() + ofs, t->getOrder());
const double divisor = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
return divisor == 0. ? 0. : dividend / divisor;
}
+ case RATIONAL: {
+ const double dividend = (uint32_t)sget4 (t->getValue() + ofs, t->getOrder());
+ const double divisor = (uint32_t)sget4 (t->getValue() + ofs + 4, t->getOrder());
+ return divisor == 0. ? 0. : dividend / divisor;
+ }
+
case FLOAT:
return double (sget4 (t->getValue() + ofs, t->getOrder()));
@@ -454,8 +459,6 @@ public:
// Get the value as an int
virtual int toInt (const Tag* t, int ofs = 0, TagType astype = INVALID)
{
- int a;
-
if (astype == INVALID || astype == AUTO) {
astype = t->getType();
}
@@ -480,10 +483,15 @@ public:
case LONG:
return (int)sget4 (t->getValue() + ofs, t->getOrder());
- case SRATIONAL:
- case RATIONAL:
- a = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
+ case SRATIONAL: {
+ int a = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
return a == 0 ? 0 : (int)sget4 (t->getValue() + ofs, t->getOrder()) / a;
+ }
+
+ case RATIONAL: {
+ uint32_t a = (uint32_t)sget4 (t->getValue() + ofs + 4, t->getOrder());
+ return a == 0 ? 0 : (uint32_t)sget4 (t->getValue() + ofs, t->getOrder()) / a;
+ }
case FLOAT:
return (int)toDouble (t, ofs);
diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt
index 828151338..52459f712 100644
--- a/rtgui/CMakeLists.txt
+++ b/rtgui/CMakeLists.txt
@@ -113,6 +113,7 @@ set(NONCLISOURCEFILES
popuptogglebutton.cc
preferences.cc
preprocess.cc
+ preprocesswb.cc
previewhandler.cc
previewloader.cc
previewmodepanel.cc
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 6a25a9d64..511aefaa7 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -475,6 +475,12 @@ void ParamsEdited::set(bool v)
wavelet.strength = v;
wavelet.balance = v;
wavelet.iter = v;
+ wavelet.sigmafin = v;
+ wavelet.sigmaton = v;
+ wavelet.sigmacol = v;
+ wavelet.sigmadir = v;
+ wavelet.rangeab = v;
+ wavelet.protab = v;
wavelet.median = v;
wavelet.medianlev = v;
wavelet.linkedg = v;
@@ -559,6 +565,7 @@ void ParamsEdited::set(bool v)
wavelet.level3noise = v;
wavelet.ccwcurve = v;
wavelet.blcurve = v;
+ wavelet.opacityCurveSH = v;
wavelet.opacityCurveRG = v;
wavelet.opacityCurveBY = v;
wavelet.opacityCurveW = v;
@@ -582,6 +589,10 @@ void ParamsEdited::set(bool v)
wavelet.expresid = v;
wavelet.exptoning = v;
wavelet.expnoise = v;
+ wavelet.labgridALow = v;
+ wavelet.labgridBLow = v;
+ wavelet.labgridAHigh = v;
+ wavelet.labgridBHigh = v;
for (int i = 0; i < 9; i++) {
wavelet.c[i] = v;
@@ -624,6 +635,7 @@ void ParamsEdited::set(bool v)
filmNegative.greenExp = v;
filmNegative.blueRatio = v;
filmNegative.baseValues = v;
+ raw.preprocessWB.mode = v;
exif = v;
iptc = v;
@@ -1086,6 +1098,12 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.strength = wavelet.strength && p.wavelet.strength == other.wavelet.strength;
wavelet.balance = wavelet.balance && p.wavelet.balance == other.wavelet.balance;
wavelet.iter = wavelet.iter && p.wavelet.iter == other.wavelet.iter;
+ wavelet.sigmafin = wavelet.sigmafin && p.wavelet.sigmafin == other.wavelet.sigmafin;
+ wavelet.sigmaton = wavelet.sigmaton && p.wavelet.sigmaton == other.wavelet.sigmaton;
+ wavelet.sigmacol = wavelet.sigmacol && p.wavelet.sigmacol == other.wavelet.sigmacol;
+ wavelet.sigmadir = wavelet.sigmadir && p.wavelet.sigmadir == other.wavelet.sigmadir;
+ wavelet.rangeab = wavelet.rangeab && p.wavelet.rangeab == other.wavelet.rangeab;
+ wavelet.protab = wavelet.protab && p.wavelet.protab == other.wavelet.protab;
wavelet.median = wavelet.median && p.wavelet.median == other.wavelet.median;
wavelet.medianlev = wavelet.medianlev && p.wavelet.medianlev == other.wavelet.medianlev;
wavelet.linkedg = wavelet.linkedg && p.wavelet.linkedg == other.wavelet.linkedg;
@@ -1171,6 +1189,7 @@ void ParamsEdited::initFrom(const std::vector&
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.opacityCurveSH = wavelet.opacityCurveSH && p.wavelet.opacityCurveSH == other.wavelet.opacityCurveSH;
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;
@@ -1189,6 +1208,10 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.exptoning = wavelet.exptoning && p.wavelet.exptoning == other.wavelet.exptoning;
wavelet.expnoise = wavelet.expnoise && p.wavelet.expnoise == other.wavelet.expnoise;
wavelet.expclari = wavelet.expclari && p.wavelet.expclari == other.wavelet.expclari;
+ wavelet.labgridALow = wavelet.labgridALow && p.wavelet.labgridALow == other.wavelet.labgridALow;
+ wavelet.labgridBLow = wavelet.labgridBLow && p.wavelet.labgridBLow == other.wavelet.labgridBLow;
+ wavelet.labgridAHigh = wavelet.labgridAHigh && p.wavelet.labgridAHigh == other.wavelet.labgridAHigh;
+ wavelet.labgridBHigh = wavelet.labgridBHigh && p.wavelet.labgridBHigh == other.wavelet.labgridBHigh;
for (int level = 0; level < 9; ++level) {
wavelet.c[level] = wavelet.c[level] && p.wavelet.c[level] == other.wavelet.c[level];
@@ -1229,6 +1252,7 @@ void ParamsEdited::initFrom(const std::vector&
filmNegative.baseValues = filmNegative.baseValues && p.filmNegative.redBase == other.filmNegative.redBase
&& p.filmNegative.greenBase == other.filmNegative.greenBase
&& p.filmNegative.blueBase == other.filmNegative.blueBase;
+ raw.preprocessWB.mode = raw.preprocessWB.mode && p.raw.preprocessWB.mode == other.raw.preprocessWB.mode;
// How the hell can we handle that???
// exif = exif && p.exif==other.exif
@@ -2889,6 +2913,22 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.enabled = mods.wavelet.enabled;
}
+ if (wavelet.labgridALow) {
+ toEdit.wavelet.labgridALow = mods.wavelet.labgridALow;
+ }
+
+ if (wavelet.labgridBLow) {
+ toEdit.wavelet.labgridBLow = mods.wavelet.labgridBLow;
+ }
+
+ if (wavelet.labgridAHigh) {
+ toEdit.wavelet.labgridAHigh = mods.wavelet.labgridAHigh;
+ }
+
+ if (wavelet.labgridBHigh) {
+ toEdit.wavelet.labgridBHigh = mods.wavelet.labgridBHigh;
+ }
+
if (wavelet.strength) {
toEdit.wavelet.strength = mods.wavelet.strength;
}
@@ -2897,6 +2937,30 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.balance = mods.wavelet.balance;
}
+ if (wavelet.sigmafin) {
+ toEdit.wavelet.sigmafin = mods.wavelet.sigmafin;
+ }
+
+ if (wavelet.sigmaton) {
+ toEdit.wavelet.sigmaton = mods.wavelet.sigmaton;
+ }
+
+ if (wavelet.sigmacol) {
+ toEdit.wavelet.sigmacol = mods.wavelet.sigmacol;
+ }
+
+ if (wavelet.sigmadir) {
+ toEdit.wavelet.sigmadir = mods.wavelet.sigmadir;
+ }
+
+ if (wavelet.rangeab) {
+ toEdit.wavelet.rangeab = mods.wavelet.rangeab;
+ }
+
+ if (wavelet.protab) {
+ toEdit.wavelet.protab = mods.wavelet.protab;
+ }
+
if (wavelet.iter) {
toEdit.wavelet.iter = mods.wavelet.iter;
}
@@ -3129,6 +3193,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.blcurve = mods.wavelet.blcurve;
}
+ if (wavelet.opacityCurveSH) {
+ toEdit.wavelet.opacityCurveSH = mods.wavelet.opacityCurveSH;
+ }
+
if (wavelet.opacityCurveRG) {
toEdit.wavelet.opacityCurveRG = mods.wavelet.opacityCurveRG;
}
@@ -3440,6 +3508,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.filmNegative.blueBase = mods.filmNegative.blueBase;
}
+ if (raw.preprocessWB.mode) {
+ toEdit.raw.preprocessWB.mode = mods.raw.preprocessWB.mode;
+ }
+
// Exif changes are added to the existing ones
if (exif) {
for (procparams::ExifPairs::const_iterator i = mods.exif.begin(); i != mods.exif.end(); ++i) {
@@ -3492,4 +3564,9 @@ bool FilmNegativeParamsEdited::isUnchanged() const
bool CaptureSharpeningParamsEdited::isUnchanged() const
{
return enabled && contrast && autoContrast && autoRadius && deconvradius && deconvradiusOffset && deconviter && deconvitercheck;
+}
+
+bool RAWParamsEdited::PreprocessWBParamsEdited::isUnchanged() const
+{
+ return mode;
}
\ No newline at end of file
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index 1feedd774..306b25ae7 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -499,6 +499,12 @@ struct WaveletParamsEdited {
bool strength;
bool balance;
bool iter;
+ bool sigmafin;
+ bool sigmaton;
+ bool sigmacol;
+ bool sigmadir;
+ bool rangeab;
+ bool protab;
bool median;
bool medianlev;
bool linkedg;
@@ -571,6 +577,7 @@ struct WaveletParamsEdited {
bool level3noise;
bool ccwcurve;
bool blcurve;
+ bool opacityCurveSH;
bool opacityCurveBY;
bool opacityCurveRG;
bool opacityCurveW;
@@ -603,6 +610,11 @@ struct WaveletParamsEdited {
bool exptoning;
bool expnoise;
bool expclari;
+ bool labgridALow;
+ bool labgridBLow;
+ bool labgridAHigh;
+ bool labgridBHigh;
+
};
struct DirPyrEqualizerParamsEdited {
@@ -714,6 +726,14 @@ struct RAWParamsEdited {
bool ff_clipControl;
bool exPos;
+ struct PreprocessWBParamsEdited {
+ bool mode;
+
+ bool isUnchanged() const;
+ };
+
+ PreprocessWBParamsEdited preprocessWB;
+
bool isUnchanged() const;
};
diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc
index b31852af2..c2f3340e5 100644
--- a/rtgui/partialpastedlg.cc
+++ b/rtgui/partialpastedlg.cc
@@ -138,6 +138,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
filmNegative = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_FILMNEGATIVE")) );
//---
captureSharpening = Gtk::manage (new Gtk::CheckButton (M("TP_PDSHARPENING_LABEL")) );
+ //---
+ raw_preprocwb = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCWB")));
Gtk::VBox* vboxes[8];
Gtk::HSeparator* hseps[8];
@@ -240,6 +242,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
vboxes[7]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0);
vboxes[7]->pack_start (*raw_expos, Gtk::PACK_SHRINK, 2);
vboxes[7]->pack_start (*raw_black, Gtk::PACK_SHRINK, 2);
+ vboxes[7]->pack_start (*raw_preprocwb, Gtk::PACK_SHRINK, 2);
vboxes[7]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0);
vboxes[7]->pack_start (*df_file, Gtk::PACK_SHRINK, 2);
vboxes[7]->pack_start (*df_AutoSelect, Gtk::PACK_SHRINK, 2);
@@ -407,6 +410,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
filmNegativeConn = filmNegative->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
//---
captureSharpeningConn = captureSharpening->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
+ //---
+ raw_preprocwbConn = raw_preprocwb->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
add_button (M("GENERAL_OK"), Gtk::RESPONSE_OK);
add_button (M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL);
@@ -480,6 +485,7 @@ void PartialPasteDlg::rawToggled ()
ConnectionBlocker raw_ca_avoid_colourshiftBlocker(raw_ca_avoid_colourshiftconn);
ConnectionBlocker filmNegativeBlocker(filmNegativeConn);
ConnectionBlocker captureSharpeningBlocker(captureSharpeningConn);
+ ConnectionBlocker raw_preprocwbBlocker(raw_preprocwbConn);
raw->set_inconsistent (false);
@@ -510,6 +516,7 @@ void PartialPasteDlg::rawToggled ()
raw_ca_avoid_colourshift->set_active (raw->get_active ());
filmNegative->set_active (raw->get_active());
captureSharpening->set_active (raw->get_active());
+ raw_preprocwb->set_active (raw->get_active());
}
void PartialPasteDlg::basicToggled ()
@@ -1000,6 +1007,10 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
filterPE.pdsharpening.deconvitercheck = falsePE.pdsharpening.deconvitercheck;
}
+ if (!raw_preprocwb->get_active ()) {
+ filterPE.raw.preprocessWB.mode = falsePE.raw.preprocessWB.mode;
+ }
+
if (dstPE) {
*dstPE = filterPE;
}
diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h
index 75e18e83c..e835ec779 100644
--- a/rtgui/partialpastedlg.h
+++ b/rtgui/partialpastedlg.h
@@ -142,6 +142,7 @@ public:
Gtk::CheckButton* filmNegative;
Gtk::CheckButton* captureSharpening;
+ Gtk::CheckButton* raw_preprocwb;
sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, advancedConn;
@@ -155,6 +156,7 @@ public:
sigc::connection raw_caredblueConn, raw_ca_autocorrectConn, raw_ca_avoid_colourshiftconn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_pdaf_lines_filterConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_borderConn, raw_imagenumConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_pixelshiftConn, raw_dcb_enhanceConn, raw_exposConn, raw_blackConn;
sigc::connection filmNegativeConn;
sigc::connection captureSharpeningConn;
+ sigc::connection raw_preprocwbConn;
public:
PartialPasteDlg (const Glib::ustring &title, Gtk::Window* parent);
diff --git a/rtgui/preprocesswb.cc b/rtgui/preprocesswb.cc
new file mode 100644
index 000000000..170371318
--- /dev/null
+++ b/rtgui/preprocesswb.cc
@@ -0,0 +1,97 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2020 Alberto Romei
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#include
+
+#include "preprocesswb.h"
+#include "eventmapper.h"
+
+#include "guiutils.h"
+#include "options.h"
+
+#include "../rtengine/procparams.h"
+
+using namespace rtengine;
+using namespace rtengine::procparams;
+
+PreprocessWB::PreprocessWB() :
+ FoldableToolPanel(this, "preprocesswb", M("TP_PREPROCWB_LABEL")),
+ evPreprocessWBMode(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_PREPROCWB_MODE")),
+ mode(Gtk::manage(new MyComboBoxText()))
+{
+ Gtk::HBox *hb = Gtk::manage(new Gtk::HBox());
+ hb->pack_start(*Gtk::manage(new Gtk::Label(M("TP_PREPROCWB_MODE") + ": ")), Gtk::PACK_SHRINK, 0);
+
+ mode->append(M("TP_PREPROCWB_MODE_CAMERA"));
+ mode->append(M("TP_PREPROCWB_MODE_AUTO"));
+
+ hb->pack_start(*mode);
+
+ mode->set_active(0);
+ mode->signal_changed().connect(sigc::mem_fun(*this, &PreprocessWB::modeChanged));
+
+ mode->show();
+
+ pack_start(*hb, Gtk::PACK_SHRINK, 4);
+}
+
+void PreprocessWB::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited)
+{
+ disableListener();
+
+ mode->set_active(int(pp->raw.preprocessWB.mode));
+
+ enableListener();
+}
+
+void PreprocessWB::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited)
+{
+ if (mode->get_active_row_number() != 2) {
+ pp->raw.preprocessWB.mode = RAWParams::PreprocessWB::Mode(mode->get_active_row_number());
+ }
+
+ if (pedited) {
+ pedited->raw.preprocessWB.mode = mode->get_active_row_number() != 2; // UNCHANGED entry, see setBatchMode
+ }
+
+}
+
+void PreprocessWB::setBatchMode(bool batchMode)
+{
+ ToolPanel::setBatchMode(batchMode);
+
+ if (batchMode) {
+ mode->append(M("GENERAL_UNCHANGED"));
+ mode->set_active_text(M("GENERAL_UNCHANGED"));
+ }
+}
+
+void PreprocessWB::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited)
+{
+}
+
+void PreprocessWB::trimValues(rtengine::procparams::ProcParams* pp)
+{
+}
+
+void PreprocessWB::modeChanged()
+{
+ if (listener) {
+ listener->panelChanged(evPreprocessWBMode, mode->get_active_text());
+ }
+}
diff --git a/rtgui/preprocesswb.h b/rtgui/preprocesswb.h
new file mode 100644
index 000000000..343d2e9e9
--- /dev/null
+++ b/rtgui/preprocesswb.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2020 Alberto Romei
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#pragma once
+
+#include
+
+#include "adjuster.h"
+#include "toolpanel.h"
+
+class PreprocessWB final:
+ public ToolParamBlock,
+ public FoldableToolPanel
+{
+
+private:
+ const rtengine::ProcEvent evPreprocessWBMode;
+
+ MyComboBoxText* mode;
+
+public:
+
+ PreprocessWB();
+
+ void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override;
+ void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override;
+ void setBatchMode(bool batchMode) override;
+ void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override;
+ void setAdjusterBehavior(bool add);
+ void trimValues(rtengine::procparams::ProcParams* pp) override;
+ void modeChanged();
+};
diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc
index a9c3231d4..0237a0917 100644
--- a/rtgui/toolpanelcoord.cc
+++ b/rtgui/toolpanelcoord.cc
@@ -92,6 +92,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit
flatfield = Gtk::manage (new FlatField ());
rawcacorrection = Gtk::manage (new RAWCACorr ());
rawexposure = Gtk::manage (new RAWExposure ());
+ preprocessWB = Gtk::manage (new PreprocessWB ());
bayerrawexposure = Gtk::manage (new BayerRAWExposure ());
xtransrawexposure = Gtk::manage (new XTransRAWExposure ());
fattal = Gtk::manage (new FattalToneMapping ());
@@ -155,6 +156,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit
addfavoritePanel (sensorxtrans->getPackBox(), xtransprocess, 2);
addfavoritePanel (sensorxtrans->getPackBox(), xtransrawexposure, 2);
addfavoritePanel (rawPanel, rawexposure);
+ addfavoritePanel (rawPanel, preprocessWB);
addfavoritePanel (rawPanel, preprocess);
addfavoritePanel (rawPanel, darkframe);
addfavoritePanel (rawPanel, flatfield);
@@ -357,6 +359,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt
sensorxtrans->FoldableToolPanel::hide();
xtransprocess->FoldableToolPanel::hide();
xtransrawexposure->FoldableToolPanel::hide();
+ preprocessWB->FoldableToolPanel::hide();
preprocess->FoldableToolPanel::hide();
flatfield->FoldableToolPanel::show();
filmNegative->FoldableToolPanel::hide();
@@ -377,6 +380,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt
sensorxtrans->FoldableToolPanel::hide();
xtransprocess->FoldableToolPanel::hide();
xtransrawexposure->FoldableToolPanel::hide();
+ preprocessWB->FoldableToolPanel::hide();
preprocess->FoldableToolPanel::hide();
flatfield->FoldableToolPanel::hide();
filmNegative->FoldableToolPanel::hide();
@@ -398,6 +402,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt
sensorxtrans->FoldableToolPanel::hide();
xtransprocess->FoldableToolPanel::hide();
xtransrawexposure->FoldableToolPanel::hide();
+ preprocessWB->FoldableToolPanel::hide();
preprocess->FoldableToolPanel::hide();
flatfield->FoldableToolPanel::hide();
filmNegative->FoldableToolPanel::hide();
diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h
index 1b51bca31..9773a2407 100644
--- a/rtgui/toolpanelcoord.h
+++ b/rtgui/toolpanelcoord.h
@@ -59,6 +59,7 @@
#include "perspective.h"
#include "pparamschangelistener.h"
#include "preprocess.h"
+#include "preprocesswb.h"
#include "profilechangelistener.h"
#include "prsharpening.h"
#include "rawcacorrection.h"
@@ -155,6 +156,7 @@ protected:
FlatField* flatfield;
RAWCACorr* rawcacorrection;
RAWExposure* rawexposure;
+ PreprocessWB* preprocessWB;
BayerRAWExposure* bayerrawexposure;
XTransRAWExposure* xtransrawexposure;
FattalToneMapping *fattal;
diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc
index af159d480..2dc4aa05c 100644
--- a/rtgui/wavelet.cc
+++ b/rtgui/wavelet.cc
@@ -27,6 +27,7 @@
#include "rtimage.h"
#include "options.h"
#include "eventmapper.h"
+#include "labgrid.h"
#include "../rtengine/color.h"
using namespace rtengine;
@@ -62,6 +63,7 @@ std::vector makeWholeHueRange()
Wavelet::Wavelet() :
FoldableToolPanel(this, "wavelet", M("TP_WAVELET_LABEL"), true, true),
curveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CONTEDIT"))),
+ curveEditorC(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CONTRASTEDIT"))),
CCWcurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CCURVE"))),
curveEditorbl(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_BLCURVE"))),
curveEditorRES(new CurveEditorGroup(options.lastWaveletCurvesDir)),
@@ -112,6 +114,12 @@ Wavelet::Wavelet() :
strength(Gtk::manage(new Adjuster(M("TP_WAVELET_STRENGTH"), 0, 100, 1, 100))),
balance(Gtk::manage(new Adjuster(M("TP_WAVELET_BALANCE"), -30, 100, 1, 0))),
iter(Gtk::manage(new Adjuster(M("TP_WAVELET_ITER"), -3, 3, 1, 0))),
+ sigmafin(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMAFIN"), 0.025, 2.5, 0.01, 1.))),
+ sigmaton(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMAFIN"), 0.025, 2.5, 0.01, 1.))),
+ sigmacol(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMAFIN"), 0.025, 2.5, 0.01, 1.))),
+ sigmadir(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMAFIN"), 0.025, 2.5, 0.01, 1.))),
+ rangeab(Gtk::manage(new Adjuster(M("TP_WAVELET_RANGEAB"), 0., 100., 0.1, 20.))),
+ protab(Gtk::manage(new Adjuster(M("TP_WAVELET_PROTAB"), 0., 100., 0.5, 0.))),
hueskin(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_HUESKIN"), -314., 314., -5., 25., 170., 120., 0, false))),
hueskin2(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_HUESKY"), -314., 314., -260., -250, -130., -140., 0, false))),
hllev(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_HIGHLIGHT"), 0., 100., 50., 75., 100., 98., 0, false))),
@@ -124,7 +132,8 @@ Wavelet::Wavelet() :
level2noise(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_LEVTWO"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., nullptr, false))),
level3noise(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_LEVTHRE"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., nullptr, false))),
threshold(Gtk::manage(new Adjuster(M("TP_WAVELET_THRESHOLD"), 1, 9, 1, 5))),
- threshold2(Gtk::manage(new Adjuster(M("TP_WAVELET_THRESHOLD2"), 1, 9, 1, 4))),
+ // threshold2(Gtk::manage(new Adjuster(M("TP_WAVELET_THRESHOLD2"), 1, 9, 1, 4))),
+ threshold2(Gtk::manage(new Adjuster(M("TP_WAVELET_THRESHOLD2"), 1, 9, 1, 5))),
edgedetect(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECT"), 0, 100, 1, 90))),
edgedetectthr(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECTTHR"), 0, 100, 1, 20))),
edgedetectthr2(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECTTHR2"), -10, 100, 1, 0))),
@@ -162,6 +171,9 @@ Wavelet::Wavelet() :
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")))),
+ fincFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_FINCFRAME")))),
+ dirFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_DIRFRAME")))),
+ tonFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_TONFRAME")))),
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") + ":"))),
@@ -207,6 +219,17 @@ Wavelet::Wavelet() :
EvWavresblur = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLURWAV");
EvWavresblurc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLURCWAV");
EvWavedgeffect = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_EDGEFFECT");
+ EvWavsigmafin = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_SIGMAFIN");
+ EvWavsigmaton = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_SIGMATON");
+ EvWavsigmacol = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_SIGMACOL");
+ EvWavsigmadir = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_SIGMADIR");
+ EvWavLabGridValue = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVLABGRID_VALUE");
+ EvWavrangeab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_RANGEAB");
+ EvWavprotab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_PROTAB");
+ EvWavlevelshc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_LEVELSHC");
+
+ labgrid = Gtk::manage(new LabGrid(EvWavLabGridValue, M("TP_WAVELET_LABGRID_VALUES")));
+
expsettings->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings));
expcontrast->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expcontrast));
@@ -402,11 +425,25 @@ Wavelet::Wavelet() :
threshold2->setAdjusterListener(this);
threshold2->set_tooltip_text(M("TP_WAVELET_THRESHOLD2_TOOLTIP"));
+ const WaveletParams default_params;
+
+ curveEditorC->setCurveListener(this);
+ curveEditorC->set_tooltip_text(M("TP_WAVELET_FINCOAR_TOOLTIP"));
+
+
+ opacityShapeSH = static_cast(curveEditorC->addCurve(CT_Flat, "", nullptr, false, false));
+ opacityShapeSH->setIdentityValue(0.);
+ opacityShapeSH->setResetCurve(FlatCurveType(default_params.opacityCurveSH.at(0)), default_params.opacityCurveSH);
+
+ curveEditorC->curveListComplete();
+ curveEditorC->show();
+
contrastSHVBox->pack_start(*HSmethod);
contrastSHVBox->pack_start(*hllev);
- contrastSHVBox->pack_start(*threshold);
+ // contrastSHVBox->pack_start(*threshold);
contrastSHVBox->pack_start(*bllev);
- contrastSHVBox->pack_start(*threshold2);
+// contrastSHVBox->pack_start(*threshold2);
+ contrastSHVBox->pack_start(*curveEditorC);
Gtk::Frame* const contrastSHFrame = Gtk::manage(new Gtk::Frame(M("TP_WAVELET_APPLYTO")));
contrastSHFrame->add(*contrastSHVBox);
levBox->pack_start(*contrastSHFrame);
@@ -450,8 +487,10 @@ Wavelet::Wavelet() :
chBox->pack_start(*satlev);
chro->set_tooltip_text(M("TP_WAVELET_CHR_TOOLTIP"));
- chBox->pack_start(*chro);
chro->setAdjusterListener(this);
+ sigmacol->setAdjusterListener(this);
+ chBox->pack_start(*chro);
+ chBox->pack_start(*sigmacol);
Gtk::HBox* const buttonchBox = Gtk::manage(new Gtk::HBox(true, 10));
neutralchPressedConn = neutralchButton->signal_pressed().connect(sigc::mem_fun(*this, &Wavelet::neutralchPressed));
@@ -483,17 +522,35 @@ Wavelet::Wavelet() :
// Toning
ToolParamBlock* const tonBox = Gtk::manage(new ToolParamBlock());
+ sigmaton->setAdjusterListener(this);
+ rangeab->setAdjusterListener(this);
+ protab->setAdjusterListener(this);
opaCurveEditorG->setCurveListener(this);
- const WaveletParams default_params;
+// const WaveletParams default_params;
opacityShapeRG = static_cast(opaCurveEditorG->addCurve(CT_Flat, "", nullptr, false, false));
opacityShapeRG->setIdentityValue(0.);
opacityShapeRG->setResetCurve(FlatCurveType(default_params.opacityCurveRG.at(0)), default_params.opacityCurveRG);
+ //from green to magenta
+ std::vector mileston = {
+ GradientMilestone(0., 0., 1., 0.),
+ GradientMilestone(1., 1., 0., 1.)
+ };
+ opacityShapeRG->setLeftBarBgGradient(mileston);
opaCurveEditorG->curveListComplete();
opaCurveEditorG->show();
+ tonBox->pack_start(*sigmaton);
+
+ tonFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const ton2Box = Gtk::manage(new ToolParamBlock());
+ ton2Box->pack_start(*labgrid, Gtk::PACK_EXPAND_WIDGET, 2);
+ ton2Box->pack_start(*rangeab);
+ ton2Box->pack_start(*protab);
+ tonFrame->add(*ton2Box);
+ tonBox->pack_start(*tonFrame);
tonBox->pack_start(*opaCurveEditorG, Gtk::PACK_SHRINK, 2);
@@ -502,6 +559,12 @@ Wavelet::Wavelet() :
opacityShapeBY = static_cast(opacityCurveEditorG->addCurve(CT_Flat, "", nullptr, false, false));
opacityShapeBY->setIdentityValue(0.);
opacityShapeBY->setResetCurve(FlatCurveType(default_params.opacityCurveBY.at(0)), default_params.opacityCurveBY);
+ //from blue to yellow
+ mileston = {
+ GradientMilestone(0., 0., 0., 1.),
+ GradientMilestone(1., 1., 1., 0.)
+ };
+ opacityShapeBY->setLeftBarBgGradient(mileston);
opacityCurveEditorG->curveListComplete();
opacityCurveEditorG->show();
@@ -545,6 +608,7 @@ Wavelet::Wavelet() :
chroBox->pack_start(*chromco);
chroFrame->add(*chroBox);
noiseBox->pack_start(*chroFrame);
+ noiseBox->set_tooltip_text(M("TP_WAVELET_NOISE_TOOLTIP"));
//Clarity
@@ -571,13 +635,13 @@ Wavelet::Wavelet() :
// Edge Sharpness
ToolParamBlock* const edgBox = Gtk::manage(new ToolParamBlock());
- edgeffect->setAdjusterListener(this);
- edgBox->pack_start(*edgeffect);
- edgeffect->set_tooltip_markup(M("TP_WAVELET_EDEFFECT_TOOLTIP"));
edgval->setAdjusterListener(this);
edgBox->pack_start(*edgval);
+ edgeffect->setAdjusterListener(this);
+ edgBox->pack_start(*edgeffect);
+ edgeffect->set_tooltip_markup(M("TP_WAVELET_EDEFFECT_TOOLTIP"));
edgrad->setAdjusterListener(this);
edgBox->pack_start(*edgrad);
@@ -694,7 +758,7 @@ Wavelet::Wavelet() :
blshape->setIdentityValue(0.);
blshape->setResetCurve(FlatCurveType(default_params.blcurve.at(0)), default_params.blcurve);
- blshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CC_TOOLTIP"));
+ blshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_BL_TOOLTIP"));
curveEditorbl->curveListComplete();
curveEditorbl->show();
@@ -800,6 +864,8 @@ Wavelet::Wavelet() :
blurBox->pack_start(*resblur);
blurBox->pack_start(*resblurc);
blurFrame->add(*blurBox);
+ resblur->set_tooltip_text(M("TP_WAVELET_RESBLUR_TOOLTIP"));
+ resblurc->set_tooltip_text(M("TP_WAVELET_RESBLUR_TOOLTIP"));
chromaFrame->set_label_align(0.025, 0.5);
ToolParamBlock* const chromaBox = Gtk::manage(new ToolParamBlock());
@@ -975,8 +1041,9 @@ Wavelet::Wavelet() :
iter->setAdjusterListener(this);
iter->set_tooltip_text(M("TP_WAVELET_ITER_TOOLTIP"));
+ sigmadir->setAdjusterListener(this);
- Gtk::HSeparator* const separatorbalend = Gtk::manage(new Gtk::HSeparator());
+// Gtk::HSeparator* const separatorbalend = Gtk::manage(new Gtk::HSeparator());
opacityCurveEditorWL->setCurveListener(this);
@@ -984,6 +1051,8 @@ Wavelet::Wavelet() :
opacityShapeWL->setIdentityValue(0.);
opacityShapeWL->setResetCurve(FlatCurveType(default_params.opacityCurveWL.at(0)), default_params.opacityCurveWL);
opacityShapeWL->setTooltip(M("TP_WAVELET_OPACITYWL_TOOLTIP"));
+ opacityShapeWL->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}});
+ sigmafin->setAdjusterListener(this);
// This will add the reset button at the end of the curveType buttons
opacityCurveEditorWL->curveListComplete();
@@ -1002,19 +1071,26 @@ Wavelet::Wavelet() :
tmr->set_tooltip_text(M("TP_WAVELET_BALCHRO_TOOLTIP"));
tmrConn = tmr->signal_toggled().connect(sigc::mem_fun(*this, &Wavelet::tmrToggled));
+ fincFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const fincBox = Gtk::manage(new ToolParamBlock());
+ fincBox->pack_start(*opacityCurveEditorWL, Gtk::PACK_SHRINK, 2);
+ fincBox->pack_start(*sigmafin);
+ fincFrame->add(*fincBox);
+
+ dirFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const dirBox = Gtk::manage(new ToolParamBlock());
+ dirBox->pack_start(*ctboxBA);
+ dirBox->pack_start(*balance);
+ dirBox->pack_start(*opacityCurveEditorW, Gtk::PACK_SHRINK, 2);
+ dirBox->pack_start(*iter);
+ dirBox->pack_start(*sigmadir);
+ dirBox->pack_start(*tmr);
+ dirFrame->add(*dirBox);
+
ToolParamBlock* const finalBox = Gtk::manage(new ToolParamBlock());
+ finalBox->pack_start(*dirFrame);
- finalBox->pack_start(*ctboxBA);
- finalBox->pack_start(*balance);
-
- finalBox->pack_start(*opacityCurveEditorW, Gtk::PACK_SHRINK, 2);
-
- finalBox->pack_start(*iter);
-
- finalBox->pack_start(*tmr);
- finalBox->pack_start(*separatorbalend, Gtk::PACK_SHRINK, 2);
- finalBox->pack_start(*opacityCurveEditorWL, Gtk::PACK_SHRINK, 2);
-
+ finalBox->pack_start(*fincFrame);
finalBox->pack_start(*curveEditorG, Gtk::PACK_SHRINK, 4);
finalBox->pack_start(*softradend);
@@ -1073,6 +1149,7 @@ Wavelet::~Wavelet()
idle_register.destroy();
delete opaCurveEditorG;
+ delete curveEditorC;
delete opacityCurveEditorG;
delete curveEditorbl;
delete CCWcurveEditorG;
@@ -1120,6 +1197,13 @@ void Wavelet::neutral_pressed()
}
}
+void Wavelet::setListener(ToolPanelListener *tpl)
+{
+ ToolPanel::setListener(tpl);
+ labgrid->setListener(tpl);
+}
+
+
void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
{
@@ -1295,6 +1379,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
ccshape->setCurve(pp->wavelet.ccwcurve);
blshape->setCurve(pp->wavelet.blcurve);
opacityShapeRG->setCurve(pp->wavelet.opacityCurveRG);
+ opacityShapeSH->setCurve(pp->wavelet.opacityCurveSH);
opacityShapeBY->setCurve(pp->wavelet.opacityCurveBY);
opacityShape->setCurve(pp->wavelet.opacityCurveW);
opacityShapeWL->setCurve(pp->wavelet.opacityCurveWL);
@@ -1406,6 +1491,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
mergeC->setValue(pp->wavelet.mergeC);
softrad->setValue(pp->wavelet.softrad);
softradend->setValue(pp->wavelet.softradend);
+ labgrid->setParams(pp->wavelet.labgridALow / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridBLow / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridAHigh / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridBHigh / WaveletParams::LABGRID_CORR_MAX, false);
ballum->setValue(pp->wavelet.ballum);
balchrom->setValue(pp->wavelet.balchrom);
@@ -1418,6 +1504,12 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
strength->setValue(pp->wavelet.strength);
balance->setValue(pp->wavelet.balance);
iter->setValue(pp->wavelet.iter);
+ sigmafin->setValue(pp->wavelet.sigmafin);
+ sigmaton->setValue(pp->wavelet.sigmaton);
+ sigmacol->setValue(pp->wavelet.sigmacol);
+ sigmadir->setValue(pp->wavelet.sigmadir);
+ rangeab->setValue(pp->wavelet.rangeab);
+ protab->setValue(pp->wavelet.protab);
for (int i = 0; i < 9; i++) {
correction[i]->setValue(pp->wavelet.c[i]);
@@ -1493,6 +1585,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
if (!pedited->wavelet.ushamethod) {
ushamethod->set_active_text(M("GENERAL_UNCHANGED"));
}
+ labgrid->setEdited(pedited->wavelet.labgridALow || pedited->wavelet.labgridBLow || pedited->wavelet.labgridAHigh || pedited->wavelet.labgridBHigh);
set_inconsistent(multiImage && !pedited->wavelet.enabled);
ccshape->setUnChanged(!pedited->wavelet.ccwcurve);
@@ -1507,6 +1600,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
exptoning->set_inconsistent(!pedited->wavelet.exptoning);
expnoise->set_inconsistent(!pedited->wavelet.expnoise);
opacityShapeRG->setCurve(pp->wavelet.opacityCurveRG);
+ opacityShapeSH->setCurve(pp->wavelet.opacityCurveSH);
opacityShapeBY->setCurve(pp->wavelet.opacityCurveBY);
opacityShape->setCurve(pp->wavelet.opacityCurveW);
opacityShapeWL->setCurve(pp->wavelet.opacityCurveWL);
@@ -1535,6 +1629,12 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
thres->setEditedState(pedited->wavelet.thres ? Edited : UnEdited);
balance->setEditedState(pedited->wavelet.balance ? Edited : UnEdited);
iter->setEditedState(pedited->wavelet.iter ? Edited : UnEdited);
+ sigmafin->setEditedState(pedited->wavelet.sigmafin ? Edited : UnEdited);
+ sigmaton->setEditedState(pedited->wavelet.sigmaton ? Edited : UnEdited);
+ sigmacol->setEditedState(pedited->wavelet.sigmacol ? Edited : UnEdited);
+ sigmadir->setEditedState(pedited->wavelet.sigmadir ? Edited : UnEdited);
+ rangeab->setEditedState(pedited->wavelet.rangeab ? Edited : UnEdited);
+ protab->setEditedState(pedited->wavelet.protab ? Edited : UnEdited);
threshold->setEditedState(pedited->wavelet.threshold ? Edited : UnEdited);
threshold2->setEditedState(pedited->wavelet.threshold2 ? Edited : UnEdited);
edgedetect->setEditedState(pedited->wavelet.edgedetect ? Edited : UnEdited);
@@ -1693,6 +1793,7 @@ void Wavelet::setEditProvider(EditDataProvider *provider)
ccshape->setEditProvider(provider);
blshape->setEditProvider(provider);
opacityShapeRG->setEditProvider(provider);
+ opacityShapeSH->setEditProvider(provider);
opacityShapeBY->setEditProvider(provider);
opacityShape->setEditProvider(provider);
opacityShapeWL->setEditProvider(provider);
@@ -1770,6 +1871,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.ccwcurve = ccshape->getCurve();
pp->wavelet.blcurve = blshape->getCurve();
pp->wavelet.opacityCurveRG = opacityShapeRG->getCurve();
+ pp->wavelet.opacityCurveSH = opacityShapeSH->getCurve();
pp->wavelet.opacityCurveBY = opacityShapeBY->getCurve();
pp->wavelet.opacityCurveW = opacityShape->getCurve();
pp->wavelet.opacityCurveWL = opacityShapeWL->getCurve();
@@ -1783,6 +1885,11 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.ballum = ballum->getValue();
pp->wavelet.chromfi = chromfi->getValue();
pp->wavelet.chromco = chromco->getValue();
+ labgrid->getParams(pp->wavelet.labgridALow, pp->wavelet.labgridBLow, pp->wavelet.labgridAHigh, pp->wavelet.labgridBHigh);
+ pp->wavelet.labgridALow *= WaveletParams::LABGRID_CORR_MAX;
+ pp->wavelet.labgridAHigh *= WaveletParams::LABGRID_CORR_MAX;
+ pp->wavelet.labgridBLow *= WaveletParams::LABGRID_CORR_MAX;
+ pp->wavelet.labgridBHigh *= WaveletParams::LABGRID_CORR_MAX;
pp->wavelet.greenlow = greenlow->getValue();
pp->wavelet.bluelow = bluelow->getValue();
@@ -1806,6 +1913,12 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.iter = (int) iter->getValue();
pp->wavelet.wavclCurve = clshape->getCurve();
+ pp->wavelet.sigmafin = sigmafin->getValue();
+ pp->wavelet.sigmaton = sigmaton->getValue();
+ pp->wavelet.sigmacol = sigmacol->getValue();
+ pp->wavelet.sigmadir = sigmadir->getValue();
+ pp->wavelet.rangeab = rangeab->getValue();
+ pp->wavelet.protab = protab->getValue();
for (int i = 0; i < 9; i++) {
pp->wavelet.c[i] = (int) correction[i]->getValue();
@@ -1887,6 +2000,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.level2noise = level2noise->getEditedState();
pedited->wavelet.level3noise = level3noise->getEditedState();
pedited->wavelet.opacityCurveRG = !opacityShapeRG->isUnChanged();
+ pedited->wavelet.opacityCurveSH = !opacityShapeSH->isUnChanged();
pedited->wavelet.opacityCurveBY = !opacityShapeBY->isUnChanged();
pedited->wavelet.opacityCurveW = !opacityShape->isUnChanged();
pedited->wavelet.opacityCurveWL = !opacityShapeWL->isUnChanged();
@@ -1912,6 +2026,12 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.softradend = softradend->getEditedState();
pedited->wavelet.balance = balance->getEditedState();
pedited->wavelet.iter = iter->getEditedState();
+ pedited->wavelet.sigmafin = sigmafin->getEditedState();
+ pedited->wavelet.sigmaton = sigmaton->getEditedState();
+ pedited->wavelet.sigmacol = sigmacol->getEditedState();
+ pedited->wavelet.sigmadir = sigmadir->getEditedState();
+ pedited->wavelet.rangeab = rangeab->getEditedState();
+ pedited->wavelet.protab = protab->getEditedState();
pedited->wavelet.wavclCurve = !clshape->isUnChanged();
pedited->wavelet.expcontrast = !expcontrast->get_inconsistent();
pedited->wavelet.expchroma = !expchroma->get_inconsistent();
@@ -1922,6 +2042,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.exptoning = !exptoning->get_inconsistent();
pedited->wavelet.expnoise = !expnoise->get_inconsistent();
pedited->wavelet.expclari = !expclari->get_inconsistent();
+ pedited->wavelet.labgridALow = pedited->wavelet.labgridBLow = pedited->wavelet.labgridAHigh = pedited->wavelet.labgridBHigh = labgrid->getEdited();
for (int i = 0; i < 9; i++) {
pedited->wavelet.c[i] = correction[i]->getEditedState();
@@ -2062,6 +2183,8 @@ void Wavelet::curveChanged(CurveEditor* ce)
listener->panelChanged(EvWavblshape, M("HISTORY_CUSTOMCURVE"));
} else if (ce == opacityShapeRG) {
listener->panelChanged(EvWavColor, M("HISTORY_CUSTOMCURVE"));
+ } else if (ce == opacityShapeSH) {
+ listener->panelChanged(EvWavlevelshc, M("HISTORY_CUSTOMCURVE"));
} else if (ce == opacityShapeBY) {
listener->panelChanged(EvWavOpac, M("HISTORY_CUSTOMCURVE"));
} else if (ce == opacityShape) {
@@ -2092,7 +2215,13 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
strength->setDefault(defParams->wavelet.strength);
balance->setDefault(defParams->wavelet.balance);
iter->setDefault(defParams->wavelet.iter);
+ sigmafin->setDefault(defParams->wavelet.sigmafin);
+ sigmaton->setDefault(defParams->wavelet.sigmaton);
+ sigmacol->setDefault(defParams->wavelet.sigmacol);
+ sigmadir->setDefault(defParams->wavelet.sigmadir);
sigma->setDefault(defParams->wavelet.sigma);
+ rangeab->setDefault(defParams->wavelet.rangeab);
+ protab->setDefault(defParams->wavelet.protab);
offset->setDefault(defParams->wavelet.offset);
lowthr->setDefault(defParams->wavelet.lowthr);
rescon->setDefault(defParams->wavelet.rescon);
@@ -2141,6 +2270,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
balchrom->setDefault(defParams->wavelet.balchrom);
chromfi->setDefault(defParams->wavelet.chromfi);
chromco->setDefault(defParams->wavelet.chromco);
+ labgrid->setDefault(defParams->wavelet.labgridALow / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridBLow / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridAHigh / WaveletParams::LABGRID_CORR_MAX, defParams->wavelet.labgridBHigh / WaveletParams::LABGRID_CORR_MAX);
greenlow->setDefault(defParams->wavelet.greenlow);
bluelow->setDefault(defParams->wavelet.bluelow);
@@ -2168,6 +2298,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
balchrom->setDefaultEditedState(pedited->wavelet.balchrom ? Edited : UnEdited);
chromfi->setDefaultEditedState(pedited->wavelet.chromfi ? Edited : UnEdited);
chromco->setDefaultEditedState(pedited->wavelet.chromco ? Edited : UnEdited);
+ labgrid->setEdited((pedited->wavelet.labgridALow || pedited->wavelet.labgridBLow || pedited->wavelet.labgridAHigh || pedited->wavelet.labgridBHigh) ? Edited : UnEdited);
sigma->setDefault(defParams->wavelet.sigma);
offset->setDefault(defParams->wavelet.offset);
@@ -2214,6 +2345,12 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
strength->setDefaultEditedState(pedited->wavelet.strength ? Edited : UnEdited);
balance->setDefaultEditedState(pedited->wavelet.balance ? Edited : UnEdited);
iter->setDefaultEditedState(pedited->wavelet.iter ? Edited : UnEdited);
+ sigmafin->setDefaultEditedState(pedited->wavelet.sigmafin ? Edited : UnEdited);
+ sigmaton->setDefaultEditedState(pedited->wavelet.sigmaton ? Edited : UnEdited);
+ sigmacol->setDefaultEditedState(pedited->wavelet.sigmacol ? Edited : UnEdited);
+ sigmadir->setDefaultEditedState(pedited->wavelet.sigmadir ? Edited : UnEdited);
+ rangeab->setDefaultEditedState(pedited->wavelet.rangeab ? Edited : UnEdited);
+ protab->setDefaultEditedState(pedited->wavelet.protab ? Edited : UnEdited);
level0noise->setDefaultEditedState(pedited->wavelet.level0noise ? Edited : UnEdited);
level1noise->setDefaultEditedState(pedited->wavelet.level1noise ? Edited : UnEdited);
level2noise->setDefaultEditedState(pedited->wavelet.level2noise ? Edited : UnEdited);
@@ -2276,6 +2413,13 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
strength->setDefaultEditedState(Irrelevant);
balance->setDefaultEditedState(Irrelevant);
iter->setDefaultEditedState(Irrelevant);
+ sigmafin->setDefaultEditedState(Irrelevant);
+ sigmaton->setDefaultEditedState(Irrelevant);
+ sigmacol->setDefaultEditedState(Irrelevant);
+ sigmadir->setDefaultEditedState(Irrelevant);
+ rangeab->setDefaultEditedState(Irrelevant);
+ protab->setDefaultEditedState(Irrelevant);
+ labgrid->setEdited(Edited);
for (int i = 0; i < 9; i++) {
correction[i]->setDefaultEditedState(Irrelevant);
@@ -2348,11 +2492,13 @@ void Wavelet::HSmethodUpdateUI()
bllev->hide();
threshold->hide();
threshold2->hide();
+ curveEditorC->hide();
} else { //with
hllev->show();
bllev->show();
threshold->show();
threshold2->show();
+ curveEditorC->show();
}
}
}
@@ -2371,6 +2517,7 @@ void Wavelet::CHmethodUpdateUI()
if (!batchMode) {
if (CHmethod->get_active_row_number() == 0) {
CHSLmethod->show();
+ // sigmacol->show();
pastlev->hide();
satlev->hide();
chroma->hide();
@@ -2390,6 +2537,7 @@ void Wavelet::CHmethodUpdateUI()
}
} else if (CHmethod->get_active_row_number() == 1) {
CHSLmethod->show();
+ // sigmacol->show();
pastlev->show();
satlev->show();
chroma->show();
@@ -2409,6 +2557,7 @@ void Wavelet::CHmethodUpdateUI()
}
} else {
chro->show();
+ // sigmacol->hide();
pastlev->hide();
satlev->hide();
chroma->hide();
@@ -2510,15 +2659,18 @@ void Wavelet::BAmethodUpdateUI()
balance->hide();
opacityCurveEditorW->hide();
iter->hide();
+ tmr->hide();
} else if (BAmethod->get_active_row_number() == 1) { //sli
opacityCurveEditorW->hide();
balance->show();
iter->show();
+ tmr->show();
} else if (BAmethod->get_active_row_number() == 2) { //CU
opacityCurveEditorW->show();
balance->hide();
iter->show();
+ tmr->show();
}
}
}
@@ -2757,6 +2909,7 @@ void Wavelet::setBatchMode(bool batchMode)
Dirmethod->append(M("GENERAL_UNCHANGED"));
CCWcurveEditorG->setBatchMode(batchMode);
opaCurveEditorG->setBatchMode(batchMode);
+ curveEditorC->setBatchMode(batchMode);
opacityCurveEditorG->setBatchMode(batchMode);
opacityCurveEditorW->setBatchMode(batchMode);
opacityCurveEditorWL->setBatchMode(batchMode);
@@ -2808,6 +2961,12 @@ void Wavelet::setBatchMode(bool batchMode)
strength->showEditedCB();
balance->showEditedCB();
iter->showEditedCB();
+ sigmafin->showEditedCB();
+ sigmaton->showEditedCB();
+ sigmacol->showEditedCB();
+ sigmadir->showEditedCB();
+ rangeab->showEditedCB();
+ protab->showEditedCB();
level0noise->showEditedCB();
level1noise->showEditedCB();
level2noise->showEditedCB();
@@ -2957,6 +3116,18 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval)
listener->panelChanged(EvWavbalance, balance->getTextValue());
} else if (a == iter) {
listener->panelChanged(EvWaviter, iter->getTextValue());
+ } else if (a == sigmafin) {
+ listener->panelChanged(EvWavsigmafin, sigmafin->getTextValue());
+ } else if (a == sigmaton) {
+ listener->panelChanged(EvWavsigmaton, sigmaton->getTextValue());
+ } else if (a == rangeab) {
+ listener->panelChanged(EvWavrangeab, rangeab->getTextValue());
+ } else if (a == protab) {
+ listener->panelChanged(EvWavprotab, protab->getTextValue());
+ } else if (a == sigmacol) {
+ listener->panelChanged(EvWavsigmacol, sigmacol->getTextValue());
+ } else if (a == sigmadir) {
+ listener->panelChanged(EvWavsigmadir, sigmadir->getTextValue());
} else if (a == greenhigh) {
listener->panelChanged(EvWavgreenhigh, greenhigh->getTextValue());
} else if (a == bluehigh) {
diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h
index d1b4bb7c3..c6a0a6b85 100644
--- a/rtgui/wavelet.h
+++ b/rtgui/wavelet.h
@@ -33,6 +33,7 @@ class CurveEditorGroup;
class DiagonalCurveEditor;
class EditDataProvider;
class FlatCurveEditor;
+class LabGrid;
class Wavelet final :
public ToolParamBlock,
@@ -93,8 +94,19 @@ private:
rtengine::ProcEvent EvWavresblur;
rtengine::ProcEvent EvWavresblurc;
rtengine::ProcEvent EvWavedgeffect;
+ rtengine::ProcEvent EvWavsigmafin;
+ rtengine::ProcEvent EvWavsigmaton;
+ rtengine::ProcEvent EvWavsigmacol;
+ rtengine::ProcEvent EvWavsigmadir;
+ rtengine::ProcEvent EvWavLabGridValue;
+ rtengine::ProcEvent EvWavrangeab;
+ rtengine::ProcEvent EvWavprotab;
+ rtengine::ProcEvent EvWavlevelshc;
+
+ LabGrid *labgrid;
void foldAllButMe(GdkEventButton* event, MyExpander *expander);
+ void setListener(ToolPanelListener *tpl) override;
void colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) override;
void BAmethodChanged();
@@ -153,6 +165,8 @@ private:
void enableToggled(MyExpander* expander);
CurveEditorGroup* const curveEditorG;
+ CurveEditorGroup* const curveEditorC;
+ FlatCurveEditor* opacityShapeSH;
CurveEditorGroup* const CCWcurveEditorG;
CurveEditorGroup* const curveEditorbl;
@@ -218,7 +232,13 @@ private:
Adjuster* const strength;
Adjuster* const balance;
Adjuster* const iter;
-
+ Adjuster* const sigmafin;
+ Adjuster* const sigmaton;
+ Adjuster* const sigmacol;
+ Adjuster* const sigmadir;
+ Adjuster* const rangeab;
+ Adjuster* const protab;
+
Adjuster* greenlow;
Adjuster* bluelow;
Adjuster* greenmed;
@@ -294,6 +314,9 @@ private:
Gtk::Frame* const blurFrame;
Gtk::Frame* const chromaFrame;
Gtk::Frame* const chroFrame;
+ Gtk::Frame* const fincFrame;
+ Gtk::Frame* const dirFrame;
+ Gtk::Frame* const tonFrame;
Gtk::Label* const wavLabels;
Gtk::Label* const labmC;
diff --git a/tools/INSTALL.readme b/tools/INSTALL.readme
new file mode 100644
index 000000000..a4f19ec3c
--- /dev/null
+++ b/tools/INSTALL.readme
@@ -0,0 +1,3 @@
+To install the RawTherapee application, open the .dmg and drag the RawTherapee app onto the /Applications folder.
+
+To use the optional rawtherapee-cli command line interface, move rawtherapee-cli into a folder in your $PATH and install the RawTherapee app as above.
diff --git a/tools/osx/macosx_bundle.sh b/tools/osx/macosx_bundle.sh
index 9258810c0..bc1a2dc3b 100644
--- a/tools/osx/macosx_bundle.sh
+++ b/tools/osx/macosx_bundle.sh
@@ -236,6 +236,11 @@ ditto {"${LOCAL_PREFIX}/local","${RESOURCES}"}/share/icons/Adwaita/index.theme
"${LOCAL_PREFIX}/local/bin/gtk-update-icon-cache" "${RESOURCES}/share/icons/Adwaita"
ditto "${LOCAL_PREFIX}/local/share/icons/hicolor" "${RESOURCES}/share/icons/hicolor"
+# fix libfreetype install name
+for lib in "${LIB}"/*; do
+ install_name_tool -change libfreetype.6.dylib "${LIB}"/libfreetype.6.dylib "${lib}"
+done
+
# pixbuf loaders & immodules
msg "Build GTK3 databases:"
"${LOCAL_PREFIX}"/local/bin/gdk-pixbuf-query-loaders "${LIB}"/libpix*.so > "${ETC}"/gtk-3.0/gdk-pixbuf.loaders
@@ -259,11 +264,11 @@ ditto "${PROJECT_SOURCE_DIR}/rtdata/fonts" "${ETC}/fonts"
ditto "${PROJECT_SOURCE_DATA_DIR}/"{rawtherapee,profile}.icns "${RESOURCES}"
ditto "${PROJECT_SOURCE_DATA_DIR}/PkgInfo" "${CONTENTS}"
install -m 0644 "${PROJECT_SOURCE_DATA_DIR}/Info.plist.in" "${CONTENTS}/Info.plist"
+install -m 0644 "${PROJECT_SOURCE_DATA_DIR}/cliInfo.plist.in" "${LIB}/Info.plist"
sed -i "" -e "s|@version@|${PROJECT_FULL_VERSION}|
s|@shortVersion@|${PROJECT_VERSION}|
s|@arch@|${arch}|" \
"${CONTENTS}/Info.plist"
-plutil -convert binary1 "${CONTENTS}/Info.plist"
update-mime-database -V "${RESOURCES}/share/mime"
msg "Build glib database:"
@@ -279,23 +284,25 @@ ModifyInstallNames
# fix @rpath in Frameworks
msg "Registering @rpath in Frameworks folder."
-for frameworklibs in "${LIB}"/*{dylib,so}; do
+for frameworklibs in "${LIB}"/*{dylib,so,cli}; do
install_name_tool -delete_rpath ${LOCAL_PREFIX}/local/lib "${frameworklibs}"
install_name_tool -add_rpath /Applications/"${LIB}" "${frameworklibs}"
done
install_name_tool -delete_rpath RawTherapee.app/Contents/Frameworks "${EXECUTABLE}"-cli
-install_name_tool -add_rpath @executable_path "${EXECUTABLE}"-cli
+install_name_tool -add_rpath /Applications/"${LIB}" "${EXECUTABLE}"-cli
+ditto "${EXECUTABLE}"-cli "${APP}"/..
# Codesign the app
if [[ -n $CODESIGNID ]]; then
msg "Codesigning Application."
- install -m 0644 "${PROJECT_SOURCE_DATA_DIR}"/rt.entitlements "${CMAKE_BUILD_TYPE}"/rt.entitlements
- plutil -convert binary1 "${CMAKE_BUILD_TYPE}"/rt.entitlements
+ iconv -f UTF-8 -t ASCII "${PROJECT_SOURCE_DATA_DIR}"/rt.entitlements > "${CMAKE_BUILD_TYPE}"/rt.entitlements
+ iconv -f UTF-8 -t ASCII "${PROJECT_SOURCE_DATA_DIR}"/rt-cli.entitlements > "${CMAKE_BUILD_TYPE}"/rt-cli.entitlements
mv "${EXECUTABLE}"-cli "${LIB}"
- for frameworklibs in "${LIB}"/*; do
- codesign -v -s "${CODESIGNID}" -i com.rawtherapee.RawTherapee --force --verbose -o runtime --timestamp "${frameworklibs}"
+ for frameworklibs in "${LIB}"/*{dylib,so}; do
+ codesign -v -s "${CODESIGNID}" -i com.rawtherapee.RawTherapee --force --verbose -o runtime --timestamp --entitlements "${CMAKE_BUILD_TYPE}"/rt.entitlements "${frameworklibs}"
done
- codesign --timestamp --strict -v -s "${CODESIGNID}" -i com.rawtherapee.RawTherapee -o runtime --entitlements "${CMAKE_BUILD_TYPE}"/rt.entitlements "${APP}"
+ codesign --force -v -s "${CODESIGNID}" -i com.rawtherapee.RawTherapee -o runtime --entitlements "${CMAKE_BUILD_TYPE}"/rt-cli.entitlements "${LIB}"/rawtherapee-cli
+ codesign --deep --timestamp --strict -v -s "${CODESIGNID}" -i com.rawtherapee.RawTherapee -o runtime --entitlements "${CMAKE_BUILD_TYPE}"/rt.entitlements "${APP}"
spctl -a -vvvv "${APP}"
fi
@@ -345,7 +352,7 @@ function CreateDmg {
CreateWebloc 'Report Bug' 'https://github.com/Beep6581/RawTherapee/issues/new'
# Disk image name
- dmg_name="${PROJECT_NAME// /_}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_FULL_VERSION}"
+ dmg_name="${PROJECT_NAME}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_FULL_VERSION}"
lower_build_type="$(tr '[:upper:]' '[:lower:]' <<< "$CMAKE_BUILD_TYPE")"
if [[ $lower_build_type != release ]]; then
dmg_name="${dmg_name}_${lower_build_type}"
@@ -390,6 +397,7 @@ function CreateDmg {
xcrun stapler staple "${dmg_name}.dmg" # staple the ticket
xcrun stapler validate -v "${dmg_name}.dmg"
echo "dmg Notarization success"
+ rm *dmg.zip
break
elif [[ $status1 = "in" ]]; then
echo "dmg Notarization still in progress, sleeping for 15 seconds and trying again"
@@ -404,10 +412,12 @@ function CreateDmg {
# Zip disk image for redistribution
msg "Zipping disk image for redistribution:"
- zip "${dmg_name}.zip" "${dmg_name}.dmg"
- rm "${dmg_name}.dmg"
- msg "Removing disk image caches:"
- rm -rf "${srcDir}"
+ mkdir "${PROJECT_NAME}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_FULL_VERSION}_folder"
+ ditto {"${PROJECT_NAME}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_FULL_VERSION}.dmg","rawtherapee-cli","${PROJECT_SOURCE_DATA_DIR}/INSTALL.readme.rtf"} "${PROJECT_NAME}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_FULL_VERSION}_folder"
+ zip -r "${PROJECT_NAME}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_FULL_VERSION}.zip" "${PROJECT_NAME}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_FULL_VERSION}_folder/"
+ # rm "${dmg_name}.dmg"
+ # msg "Removing disk image caches:"
+ # rm -rf "${srcDir}"
}
CreateDmg
msg "Finishing build:"
diff --git a/tools/osx/rt.entitlements b/tools/osx/rt.entitlements
index c571f1f41..8fc97c7da 100644
--- a/tools/osx/rt.entitlements
+++ b/tools/osx/rt.entitlements
@@ -1,19 +1,16 @@
+
-
- application-identifier
- com.rawtherapee.RawTherapee
- com.apple.security.temporary-exception.files.absolute-path.read-write
-
- /
-
- com.apple.security.cs.allow-dyld-environment-variables
-
- com.apple.security.files.user-selected.read-write
-
- com.apple.security.app-sandbox
-
- com.apple.security.files.downloads.read-write
-
-
-
\ No newline at end of file
+
+ com.apple.application-identifier
+ com.rawtherapee.RawTherapee
+ com.apple.security.app-sandbox
+
+ com.apple.security.cs.allow-dyld-environment-variables
+
+ com.apple.security.temporary-exception.files.absolute-path.read-write
+
+ /
+
+
+