diff --git a/CMakeLists.txt b/CMakeLists.txt
index e3ae3b7ff..7d66109e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -128,6 +128,10 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PROC_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=unused-label")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=delete-incomplete")
+# Do net set math errno, as we never check its value.
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-math-errno")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-math-errno")
+
# Special treatment for x87 and x86-32 SSE (see GitHub issue #4324)
include(FindX87Math)
if(HAVE_X87_MATH)
@@ -665,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/dcpprofiles/CANON EOS 5D MARK IV.dcp b/rtdata/dcpprofiles/CANON EOS 5D MARK IV.dcp
new file mode 100644
index 000000000..80407fb21
Binary files /dev/null and b/rtdata/dcpprofiles/CANON EOS 5D MARK IV.dcp differ
diff --git a/rtdata/dcpprofiles/CANON EOS M6 MARK II.dcp b/rtdata/dcpprofiles/CANON EOS M6 MARK II.dcp
new file mode 100644
index 000000000..9a877f02f
Binary files /dev/null and b/rtdata/dcpprofiles/CANON EOS M6 MARK II.dcp differ
diff --git a/rtdata/dcpprofiles/CANON EOS R.dcp b/rtdata/dcpprofiles/CANON EOS R.dcp
new file mode 100644
index 000000000..6ea5302e2
Binary files /dev/null and b/rtdata/dcpprofiles/CANON EOS R.dcp differ
diff --git a/rtdata/dcpprofiles/CANON POWERSHOT G1 X MARK II.dcp b/rtdata/dcpprofiles/CANON POWERSHOT G1 X MARK II.dcp
new file mode 100644
index 000000000..656649fd9
Binary files /dev/null and b/rtdata/dcpprofiles/CANON POWERSHOT G1 X MARK II.dcp differ
diff --git a/rtdata/dcpprofiles/FUJIFILM X-A5.dcp b/rtdata/dcpprofiles/FUJIFILM X-A5.dcp
new file mode 100644
index 000000000..c6e88d789
Binary files /dev/null and b/rtdata/dcpprofiles/FUJIFILM X-A5.dcp differ
diff --git a/rtdata/dcpprofiles/FUJIFILM X-H1.dcp b/rtdata/dcpprofiles/FUJIFILM X-H1.dcp
new file mode 100644
index 000000000..e3abc07f1
Binary files /dev/null and b/rtdata/dcpprofiles/FUJIFILM X-H1.dcp differ
diff --git a/rtdata/dcpprofiles/FUJIFILM X-PRO3.dcp b/rtdata/dcpprofiles/FUJIFILM X-PRO3.dcp
new file mode 100644
index 000000000..bfbaff9e5
Binary files /dev/null and b/rtdata/dcpprofiles/FUJIFILM X-PRO3.dcp differ
diff --git a/rtdata/dcpprofiles/FUJIFILM X-T3.dcp b/rtdata/dcpprofiles/FUJIFILM X-T3.dcp
new file mode 100644
index 000000000..5024f38a9
Binary files /dev/null and b/rtdata/dcpprofiles/FUJIFILM X-T3.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D500.dcp b/rtdata/dcpprofiles/NIKON D500.dcp
new file mode 100644
index 000000000..c25294439
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D500.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D5300.dcp b/rtdata/dcpprofiles/NIKON D5300.dcp
new file mode 100644
index 000000000..2c7566c8c
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D5300.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D610.dcp b/rtdata/dcpprofiles/NIKON D610.dcp
new file mode 100644
index 000000000..a5a05ca34
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D610.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D7100.dcp b/rtdata/dcpprofiles/NIKON D7100.dcp
new file mode 100644
index 000000000..332157fc9
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D7100.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D7500.dcp b/rtdata/dcpprofiles/NIKON D7500.dcp
new file mode 100644
index 000000000..5e6cb2c64
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D7500.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D800.dcp b/rtdata/dcpprofiles/NIKON D800.dcp
new file mode 100644
index 000000000..5f0ebba8c
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D800.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D850.dcp b/rtdata/dcpprofiles/NIKON D850.dcp
new file mode 100644
index 000000000..806e1e9bb
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D850.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON Z 50.dcp b/rtdata/dcpprofiles/NIKON Z 50.dcp
new file mode 100644
index 000000000..beca667a7
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON Z 50.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON Z 6.dcp b/rtdata/dcpprofiles/NIKON Z 6.dcp
new file mode 100644
index 000000000..eeb45a6b8
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON Z 6.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON Z 7.dcp b/rtdata/dcpprofiles/NIKON Z 7.dcp
new file mode 100644
index 000000000..19fb7bba6
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON Z 7.dcp differ
diff --git a/rtdata/dcpprofiles/OLYMPUS E-M5MARKII.dcp b/rtdata/dcpprofiles/OLYMPUS E-M5MARKII.dcp
new file mode 100644
index 000000000..c3f670bfb
Binary files /dev/null and b/rtdata/dcpprofiles/OLYMPUS E-M5MARKII.dcp differ
diff --git a/rtdata/dcpprofiles/PENTAX K-50.dcp b/rtdata/dcpprofiles/PENTAX K-50.dcp
new file mode 100644
index 000000000..3205c7579
Binary files /dev/null and b/rtdata/dcpprofiles/PENTAX K-50.dcp differ
diff --git a/rtdata/dcpprofiles/SONY ILCE-6400.dcp b/rtdata/dcpprofiles/SONY ILCE-6400.dcp
new file mode 100644
index 000000000..8c5fcfec4
Binary files /dev/null and b/rtdata/dcpprofiles/SONY ILCE-6400.dcp differ
diff --git a/rtdata/dcpprofiles/SONY ILCE-6600.dcp b/rtdata/dcpprofiles/SONY ILCE-6600.dcp
new file mode 100644
index 000000000..8c802d150
Binary files /dev/null and b/rtdata/dcpprofiles/SONY ILCE-6600.dcp differ
diff --git a/rtdata/dcpprofiles/SONY ILCE-7RM4.dcp b/rtdata/dcpprofiles/SONY ILCE-7RM4.dcp
new file mode 100644
index 000000000..e473fa496
Binary files /dev/null and b/rtdata/dcpprofiles/SONY ILCE-7RM4.dcp differ
diff --git a/rtdata/dcpprofiles/SONY ILCE-9.dcp b/rtdata/dcpprofiles/SONY ILCE-9.dcp
new file mode 100644
index 000000000..c07315812
Binary files /dev/null and b/rtdata/dcpprofiles/SONY ILCE-9.dcp differ
diff --git a/rtdata/languages/default b/rtdata/languages/default
index a6abadaa6..9d9e841a2 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
@@ -752,6 +752,7 @@ HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength
HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold
HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold
HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative
+HISTORY_MSG_FILMNEGATIVE_FILMBASE;Film base color
HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values
HISTORY_MSG_HISTMATCHING;Auto-matched tone curve
HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries
@@ -760,6 +761,7 @@ HISTORY_MSG_ICM_OUTPUT_TYPE;Output - Type
HISTORY_MSG_ICM_WORKING_GAMMA;Working - Gamma
HISTORY_MSG_ICM_WORKING_SLOPE;Working - Slope
HISTORY_MSG_ICM_WORKING_TRC_METHOD;Working - TRC method
+HISTORY_MSG_ILLUM;Illuminant
HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount
HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness
HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast
@@ -791,6 +793,10 @@ HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength
HISTORY_MSG_TEMPOUT;CAM02 automatic temperature
HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor
HISTORY_MSG_TRANS_Method;Geometry - Method
+HISTORY_MSG_WAVBALCHROM;Equalizer chrominance
+HISTORY_MSG_WAVBALLUM;Equalizer luminance
+HISTORY_MSG_WAVCHROMFI;Chroma fine
+HISTORY_MSG_WAVCHROMCO;Chroma coarse
HISTORY_MSG_WAVCLARI;Clarity
HISTORY_MSG_WAVEDGS;Edge stopping
HISTORY_MSG_WAVMERGEC;Merge C
@@ -798,10 +804,26 @@ HISTORY_MSG_WAVMERGEL;Merge L
HISTORY_MSG_WAVRADIUS;Radius Shadows-Highlight
HISTORY_MSG_WAVSCALE;Scale
HISTORY_MSG_WAVSHOWMASK;Show wavelet mask
-HISTORY_MSG_WAVSIGMA;Sigma
+HISTORY_MSG_WAVSIGMA;Damper
HISTORY_MSG_WAVSOFTRAD;Soft radius clarity
HISTORY_MSG_WAVSOFTRADEND;Soft radius final
HISTORY_MSG_WAVUSHAMET;Clarity method
+HISTORY_MSG_THRESWAV;Balance threshold
+HISTORY_MSG_BLUWAV;Damper
+HISTORY_MSG_WAVOLDSH;Old algorithm
+HISTORY_MSG_WAVOFFSET;Offset
+HISTORY_MSG_WAVLOWTHR;Threshold low contrast
+HISTORY_MSG_BLSHAPE;Blur by level
+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
@@ -1440,6 +1462,16 @@ TP_COLORAPP_GAMUT;Gamut control (L*a*b*)
TP_COLORAPP_GAMUT_TOOLTIP;Allow gamut control in L*a*b* mode.
TP_COLORAPP_HUE;Hue (h)
TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0° and 360°.
+TP_COLORAPP_ILLUM;Illuminant
+TP_COLORAPP_ILLUM_TOOLTIP;Select the illuminant closest to the shooting conditions.\nIn general D50, but it can change depending on the time and lattitude.
+TP_COLORAPP_ILA;Incandescent StdA 2856K
+TP_COLORAPP_IL41;D41
+TP_COLORAPP_IL50;D50
+TP_COLORAPP_IL55;D55
+TP_COLORAPP_IL60;D60
+TP_COLORAPP_IL65;D65
+TP_COLORAPP_IL75;D75
+TP_COLORAPP_ILFREE;Free
TP_COLORAPP_LABEL;CIE Color Appearance Model 2002
TP_COLORAPP_LABEL_CAM02;Image Adjustments
TP_COLORAPP_LABEL_SCENE;Scene Conditions
@@ -1452,7 +1484,7 @@ TP_COLORAPP_MODEL_TOOLTIP;White-Point Model.\n\nWB [RT] + [output]: RT's
TP_COLORAPP_NEUTRAL;Reset
TP_COLORAPP_NEUTRAL_TIP;Reset all sliders checkbox and curves to their default values
TP_COLORAPP_PRESETCAT02;Preset cat02 automatic
-TP_COLORAPP_PRESETCAT02_TIP;Set combobox, sliders, temp, green so that Cat02 automatic is preset.\nYou must change Cat02 adaptation Viewing conditions if need.\nYou can change Temperature and Tint Viewing conditions if need, and other settings if need.
+TP_COLORAPP_PRESETCAT02_TIP;Set combobox, sliders, temp, green so that Cat02 automatic is preset.\nYou can change illuminant shooting conditions.\nYou must change Cat02 adaptation Viewing conditions if need.\nYou can change Temperature and Tint Viewing conditions if need, and other settings if need.
TP_COLORAPP_RSTPRO;Red & skin-tones protection
TP_COLORAPP_RSTPRO_TOOLTIP;Red & skin-tones protection affects both sliders and curves.
TP_COLORAPP_SURROUND;Surround
@@ -1469,7 +1501,8 @@ TP_COLORAPP_TCMODE_LABEL2;Curve mode 2
TP_COLORAPP_TCMODE_LABEL3;Curve chroma mode
TP_COLORAPP_TCMODE_LIGHTNESS;Lightness
TP_COLORAPP_TCMODE_SATUR;Saturation
-TP_COLORAPP_TEMP_TOOLTIP;To select an illuminant, always set Tint=1.\n\nA temp=2856\nD50 temp=5003\nD55 temp=5503\nD65 temp=6504\nD75 temp=7504
+TP_COLORAPP_TEMP_TOOLTIP;To select an illuminant, always set Tint=1.\n\nA temp=2856\nD41 temp=4100\nD50 temp=5003\nD55 temp=5503\nD60 temp=6000\nD65 temp=6504\nD75 temp=7504
+TP_COLORAPP_TEMP2_TOOLTIP;Either symmetrical mode temp = White balance.\nEither select illuminant always set Tint=1.\n\nA temp=2856\nD41 temp=4100\nD50 temp=5003\nD55 temp=5503\nD60 temp=6000\nD65 temp=6504\nD75 temp=7504
TP_COLORAPP_TEMPOUT_TOOLTIP;Disable to chnage temperature and tint
TP_COLORAPP_TONECIE;Tone mapping using CIECAM02
TP_COLORAPP_TONECIE_TOOLTIP;If this option is disabled, tone mapping is done in L*a*b* space.\nIf this option is enabled, tone mapping is done using CIECAM02.\nThe Tone Mapping tool must be enabled for this setting to take effect.
@@ -1669,6 +1702,9 @@ TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard
TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points
TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
TP_FILMNEGATIVE_BLUE;Blue ratio
+TP_FILMNEGATIVE_FILMBASE_PICK;Pick film base color
+TP_FILMNEGATIVE_FILMBASE_TOOLTIP;Pick a spot of unexposed film (eg. the border between frames), to get the actual film base color values, and save them in the processing profile.\nThis makes it easy to get a more consistent color balance when batch-processing multiple pictures from the same roll.\nAlso use this when the converted image is extremely dark, bright, or color-unbalanced.
+TP_FILMNEGATIVE_FILMBASE_VALUES;Film base RGB:
TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
TP_FILMNEGATIVE_LABEL;Film Negative
@@ -2124,11 +2160,16 @@ TP_WAVELET_BACKGROUND;Background
TP_WAVELET_BACUR;Curve
TP_WAVELET_BALANCE;Contrast balance d/v-h
TP_WAVELET_BALANCE_TOOLTIP;Alters the balance between the wavelet directions: vertical-horizontal and diagonal.\nIf contrast, chroma or residual tone mapping are activated, the effect due to balance is amplified.
-TP_WAVELET_BALCHRO;Chroma balance
+TP_WAVELET_BALCHRO;Chrominance balance
TP_WAVELET_BALCHRO_TOOLTIP;If enabled, the 'Contrast balance' curve or slider also modifies chroma balance.
+TP_WAVELET_BALCHROM;Denoise Equalizer Blue-Red
+TP_WAVELET_BALLUM;Denoise Equalizer White-Black
TP_WAVELET_BANONE;None
TP_WAVELET_BASLI;Slider
TP_WAVELET_BATYPE;Contrast balance method
+TP_WAVELET_BLCURVE;Blur by levels
+TP_WAVELET_BLURFRAME;Blur
+TP_WAVELET_BLUWAV;Damper
TP_WAVELET_CBENAB;Toning and Color Balance
TP_WAVELET_CB_TOOLTIP;For strong values product color-toning by combining it or not with levels decomposition 'toning'\nFor low values you can change the white balance of the background (sky, ...) without changing that of the front plane, generally more contrasted
TP_WAVELET_CCURVE;Local contrast
@@ -2138,9 +2179,13 @@ TP_WAVELET_CH3;Link contrast levels
TP_WAVELET_CHCU;Curve
TP_WAVELET_CHR;Chroma-contrast link strength
TP_WAVELET_CHRO;Saturated/pastel threshold
+TP_WAVELET_CHROFRAME;Denoise Chrominance
TP_WAVELET_CHROMAFRAME;Chroma
+TP_WAVELET_CHROMCO;Chrominance Coarse
+TP_WAVELET_CHROMFI;Chrominance Fine
TP_WAVELET_CHRO_TOOLTIP;Sets the wavelet level which will be the threshold between saturated and pastel colors.\n1-x: saturated\nx-9: pastel\n\nIf the value exceeds the amount of wavelet levels you are using then it will be ignored.
TP_WAVELET_CHR_TOOLTIP;Adjusts chroma as a function of "contrast levels" and "chroma-contrast link strength"
+TP_WAVELET_CHRWAV;Blur chroma
TP_WAVELET_CHSL;Sliders
TP_WAVELET_CHTYPE;Chrominance method
TP_WAVELET_CLA;Clarity
@@ -2151,8 +2196,10 @@ TP_WAVELET_COMPGAMMA;Compression gamma
TP_WAVELET_COMPGAMMA_TOOLTIP;Adjusting the gamma of the residual image allows you to equilibrate the data and histogram.
TP_WAVELET_COMPTM;Tone mapping
TP_WAVELET_CONTEDIT;'After' contrast curve
+TP_WAVELET_CONTFRAME;Contrast - Compression
TP_WAVELET_CONTR;Gamut
TP_WAVELET_CONTRA;Contrast
+TP_WAVELET_CONTRASTEDIT;Finer - Coarser levels
TP_WAVELET_CONTRAST_MINUS;Contrast -
TP_WAVELET_CONTRAST_PLUS;Contrast +
TP_WAVELET_CONTRA_TOOLTIP;Changes contrast of the residual image.
@@ -2172,6 +2219,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
@@ -2185,6 +2233,8 @@ TP_WAVELET_EDGEDETECTTHR;Threshold low (noise)
TP_WAVELET_EDGEDETECTTHR2;Threshold high (detection)
TP_WAVELET_EDGEDETECTTHR_TOOLTIP;This adjuster lets you target edge detection for example to avoid applying edge sharpness to fine details, such as noise in the sky.
TP_WAVELET_EDGEDETECT_TOOLTIP;Moving the slider to the right increases edge sensitivity. This affects local contrast, edge settings and noise.
+TP_WAVELET_EDEFFECT;Damper
+TP_WAVELET_EDEFFECT_TOOLTIP;This slider controls how wide the range of contrast values are that receive the maximum effect from the tool.\nMaximum value (2.5) disabled the tool
TP_WAVELET_EDGESENSI;Edge sensitivity
TP_WAVELET_EDGREINF_TOOLTIP;Reinforce or reduce the action of the first level, do the opposite to the second level, and leave the rest unchanged.
TP_WAVELET_EDGTHRESH;Detail
@@ -2195,10 +2245,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
@@ -2208,10 +2260,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
@@ -2222,7 +2274,8 @@ 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
TP_WAVELET_MEDILEV;Edge detection
@@ -2232,21 +2285,28 @@ 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
TP_WAVELET_NPTYPE;Neighboring pixels
TP_WAVELET_NPTYPE_TOOLTIP;This algorithm uses the proximity of a pixel and eight of its neighbors. If less difference, edges are reinforced.
+TP_WAVELET_OLDSH;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
@@ -2254,8 +2314,11 @@ TP_WAVELET_RESID;Residual Image
TP_WAVELET_SAT;Saturated chroma
TP_WAVELET_SETTINGS;Wavelet Settings
TP_WAVELET_SHA;Sharp mask
+TP_WAVELET_SHFRAME;Shadows/Highlights
TP_WAVELET_SHOWMASK;Show wavelet 'mask'
-TP_WAVELET_SIGMA;Sigma
+TP_WAVELET_SIGMA;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.
TP_WAVELET_SKY;Sky targetting/protection
@@ -2265,26 +2328,33 @@ 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;Big tiles
+TP_WAVELET_TILESBIG;Tiles
TP_WAVELET_TILESFULL;Full image
TP_WAVELET_TILESIZE;Tiling method
TP_WAVELET_TILESLIT;Little tiles
TP_WAVELET_TILES_TOOLTIP;Processing the full image leads to better quality and is the recommended option, while using tiles is a fall-back solution for users with little RAM. Refer to RawPedia for memory requirements.
+TP_WAVELET_BL;Blur levels
TP_WAVELET_TMEDGS;Edge stopping
TP_WAVELET_TMSCALE;Scale
TP_WAVELET_TMSTRENGTH;Compression strength
TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image.
-TP_WAVELET_TMTYPE;Compression method
+TP_WAVELET_TMEDGS;Edge stopping
TP_WAVELET_TON;Toning
+TP_WAVELET_TONFRAME;Excluded Colors
+TP_WAVELET_TMTYPE;Compression method
TP_WAVELET_USH;None
TP_WAVELET_USHARP;Clarity method
TP_WAVELET_USHARP_TOOLTIP;Origin : the source file is the file before Wavelet.\nWavelet : the source file is the file including wavelet threatment
TP_WAVELET_USH_TOOLTIP;If you select Sharp-mask, wavelet settings will be automatically positioned :\nBackground=black, Process=below, level=3...you can change level between 1 and 4.\n\nIf you select Clarity, wavelet settings will be automatically positioned :\nBackground=residual, Process=above, level=7..you can change level between 5 and 10 and wavelet levels.
+TP_WAVELET_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
diff --git a/rtdata/themes/RawTherapee-GTK3-20_.css b/rtdata/themes/RawTherapee-GTK3-20_.css
index a5f52a769..bdadc00db 100644
--- a/rtdata/themes/RawTherapee-GTK3-20_.css
+++ b/rtdata/themes/RawTherapee-GTK3-20_.css
@@ -565,7 +565,7 @@ button.text-button.toggle:hover:checked {
.drawingarea {
border-radius: 0;
background-color: #2A2A2A;
- border: 0.0833333333333333em solid #1D1D1D;
+ border: 0.0833333333333333em solid #888888;
}
.drawingarea:disabled {
background-color: #444;
diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc
index 9120fe0ad..ab06f92f2 100644
--- a/rtengine/FTblockDN.cc
+++ b/rtengine/FTblockDN.cc
@@ -63,8 +63,8 @@
namespace rtengine
{
-// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
Structure of the algorithm:
@@ -483,7 +483,6 @@ enum nrquality {QUALITY_STANDARD, QUALITY_HIGH};
void ImProcFunctions::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)
{
BENCHFUN
-
//#ifdef _DEBUG
MyTime t1e, t2e;
t1e.set();
@@ -550,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();
@@ -1183,6 +1182,7 @@ BENCHFUN
} else {
madL[lvl][dir - 1] = SQR(MadRgb(WavCoeffs_L[dir], Wlvl_L * Hlvl_L));
}
+
}
}
}
@@ -1200,16 +1200,16 @@ BENCHFUN
if (!memoryAllocationFailed) {
if (nrQuality == QUALITY_STANDARD) {
- if (!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb)) { //enhance mode
+ if (!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, nullptr, 0, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb, denoiseNestedLevels)) { //enhance mode
memoryAllocationFailed = true;
}
} else { /*if (nrQuality==QUALITY_HIGH)*/
- if (!WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb)) { //enhance mode
+ if (!WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *adecomp, noisevarchrom, madL, nullptr, 0, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb, denoiseNestedLevels)) { //enhance mode
memoryAllocationFailed = true;
}
if (!memoryAllocationFailed) {
- if (!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb)) {
+ if (!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, nullptr, 0, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb, denoiseNestedLevels)) {
memoryAllocationFailed = true;
}
}
@@ -1237,16 +1237,16 @@ BENCHFUN
if (!memoryAllocationFailed) {
if (nrQuality == QUALITY_STANDARD) {
- if (!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb)) { //enhance mode
+ if (!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, nullptr, 0, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb, denoiseNestedLevels)) { //enhance mode
memoryAllocationFailed = true;
}
} else { /*if (nrQuality==QUALITY_HIGH)*/
- if (!WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb)) { //enhance mode
+ if (!WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, nullptr, 0, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb, denoiseNestedLevels)) { //enhance mode
memoryAllocationFailed = true;
}
if (!memoryAllocationFailed) {
- if (!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb)) {
+ if (!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, nullptr, 0, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb, denoiseNestedLevels)) {
memoryAllocationFailed = true;
}
}
@@ -1273,16 +1273,16 @@ BENCHFUN
int edge = 0;
if (nrQuality == QUALITY_STANDARD) {
- if (!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, nullptr, edge)) { //enhance mode
+ if (!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, nullptr, edge, denoiseNestedLevels)) { //enhance mode
memoryAllocationFailed = true;
}
} else { /*if (nrQuality==QUALITY_HIGH)*/
- if (!WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL)) { //enhance mode
+ if (!WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL, nullptr, edge, denoiseNestedLevels)) { //enhance mode
memoryAllocationFailed = true;
}
if (!memoryAllocationFailed) {
- if (!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, nullptr, edge)) {
+ if (!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, nullptr, edge, denoiseNestedLevels)) {
memoryAllocationFailed = true;
}
}
@@ -1354,9 +1354,11 @@ BENCHFUN
#else
int subThread = 0;
#endif
+// float blurbuffer[TS * TS] ALIGNED64;
float *Lblox = LbloxArray[subThread];
float *fLblox = fLbloxArray[subThread];
float pBuf[width + TS + 2 * blkrad * offset] ALIGNED16;
+// float nbrwt[TS * TS] ALIGNED64;
#ifdef _OPENMP
#pragma omp for
#endif
@@ -1432,6 +1434,7 @@ BENCHFUN
for (int hblk = 0; hblk < numblox_W; ++hblk) {
RGBtile_denoise(fLblox, hblk, noisevar_Ldetail);
+ // RGBtile_denoise(fLblox, hblk, noisevar_Ldetail, nbrwt, blurbuffer);
}//end of horizontal block loop
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1448,8 +1451,14 @@ BENCHFUN
//add row of blocks to output image tile
RGBoutput_tile_row(Lblox, Ldetail, tilemask_out, height, width, topproc);
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
}//end of vertical block loop
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
}
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#ifdef _OPENMP
#pragma omp parallel for num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1)
@@ -2036,6 +2045,13 @@ BENCHFUN
}//end of main RGB_denoise
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+//void ImProcFunctions::RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer) //for DCT
void ImProcFunctions::RGBtile_denoise(float* fLblox, int hblproc, float noisevar_Ldetail) //for DCT
{
float nbrwt[TS * TS] ALIGNED64;
@@ -2062,6 +2078,10 @@ void ImProcFunctions::RGBtile_denoise(float* fLblox, int hblproc, float noisevar
}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
void ImProcFunctions::RGBoutput_tile_row(float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top)
{
const int numblox_W = ceil((static_cast(width)) / (offset));
@@ -2189,11 +2209,19 @@ void ImProcFunctions::Noise_residualAB(const wavelet_decomposition &WaveletCoeff
chmaxresid = maxresid;
}
-bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3])
+bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels)
{
int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5);
const float eps = 0.01f;
+ if (edge == 1 || edge == 3 || edge == 4) {
+ maxlvl = 4; //for refine denoise edge wavelet
+ }
+
+ if (edge == 2) {
+ maxlvl = 7; //for locallab denoise
+ }
+
int maxWL = 0, maxHL = 0;
for (int lvl = 0; lvl < maxlvl; ++lvl) {
@@ -2204,6 +2232,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
if (WaveletCoeffs_L.level_H(lvl) > maxHL) {
maxHL = WaveletCoeffs_L.level_H(lvl);
}
+
}
bool memoryAllocationFailed = false;
@@ -2234,14 +2263,52 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl);
if (lvl == maxlvl - 1) {
- int edge = 0;
- ShrinkAllL(WaveletCoeffs_L, buffer, lvl, dir, noisevarlum, madL[lvl], nullptr, edge);
- } else {
+ // int edge = 0;
+ ShrinkAllL(WaveletCoeffs_L, buffer, lvl, dir, noisevarlum, madL[lvl], vari, edge);
+ } else {
//simple wavelet shrinkage
float * sfave = buffer[0] + 32;
float * sfaved = buffer[2] + 96;
float mad_Lr = madL[lvl][dir - 1];
+ /*
+ if ((edge == 1 || edge == 2 || edge == 3) && vari) {
+ noisevarlum = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer
+
+ for (int i = 0; i < Wlvl_L * Hlvl_L; ++i) {
+ noisevarlum[i] = vari[lvl];
+ }
+ }
+ */
+ float *nvl = nullptr;
+ nvl = new float[Hlvl_L * Wlvl_L];
+
+ for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
+ nvl[i] = 0.f;
+ }
+ if ((edge == 1 || edge == 2 || edge == 3) && 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) {
+ nvl[i] = vari[lvl];
+ }
+ }
+
+ if (edge == 2 || edge == 4) {
+ for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
+ nvl[i] = vari[lvl] * SQR(noisevarlum[i]);
+ }
+ }
+
+ }
+
+ else {
+ for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
+ nvl[i] = noisevarlum[i];
+ }
+
+ }
+
float levelFactor = mad_Lr * 5.f / (lvl + 1);
#ifdef __SSE2__
@@ -2253,14 +2320,14 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
int coeffloc_L;
for (coeffloc_L = 0; coeffloc_L < Hlvl_L * Wlvl_L - 3; coeffloc_L += 4) {
- mad_Lv = LVFU(noisevarlum[coeffloc_L]) * levelFactorv;
+ mad_Lv = LVFU(nvl[coeffloc_L]) * levelFactorv;
mag_Lv = SQRV(LVFU(WavCoeffs_L[dir][coeffloc_L]));
STVFU(sfave[coeffloc_L], mag_Lv / (mag_Lv + mad_Lv * xexpf(-mag_Lv / (mad_Lv * ninev)) + epsv));
}
for (; coeffloc_L < Hlvl_L * Wlvl_L; ++coeffloc_L) {
float mag_L = SQR(WavCoeffs_L[dir][coeffloc_L]);
- sfave[coeffloc_L] = mag_L / (mag_L + levelFactor * noisevarlum[coeffloc_L] * xexpf(-mag_L / (9.f * levelFactor * noisevarlum[coeffloc_L])) + eps);
+ sfave[coeffloc_L] = mag_L / (mag_L + levelFactor * nvl[coeffloc_L] * xexpf(-mag_L / (9.f * levelFactor * nvl[coeffloc_L])) + eps);
}
#else
@@ -2270,12 +2337,13 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
int coeffloc_L = i * Wlvl_L + j;
float mag_L = SQR(WavCoeffs_L[dir][coeffloc_L]);
- sfave[coeffloc_L] = mag_L / (mag_L + levelFactor * noisevarlum[coeffloc_L] * xexpf(-mag_L / (9.f * levelFactor * noisevarlum[coeffloc_L])) + eps);
+ sfave[coeffloc_L] = mag_L / (mag_L + levelFactor * nvl[coeffloc_L] * xexpf(-mag_L / (9.f * levelFactor * nvl[coeffloc_L])) + eps);
}
}
#endif
boxblur(sfave, sfaved, lvl + 2, Wlvl_L, Hlvl_L, false); //increase smoothness by locally averaging shrinkage
+
#ifdef __SSE2__
vfloat sfavev;
vfloat sf_Lv;
@@ -2306,7 +2374,9 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
}
#endif
+ delete [] nvl;
}
+
}
}
}
@@ -2321,11 +2391,20 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &W
return (!memoryAllocationFailed);
}
-bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab,
- float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb)
+
+bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels)
+
{
int maxlvl = WaveletCoeffs_L.maxlevel();
+ if (local == 2) {
+ maxlvl = 7; //for local denoise
+ }
+
+ if (local == 3) {
+ maxlvl = 4; //for shape detection
+ }
+
if (autoch && noisevar_ab <= 0.001f) {
noisevar_ab = 0.02f;
}
@@ -2393,14 +2472,36 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &
float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl);
if (lvl == maxlvl - 1) {
- ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], madab[lvl], true);
+ ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], nullptr, 0, madab[lvl], true);
} else {
//simple wavelet shrinkage
+ float noisevarfc;
float mad_Lr = madL[lvl][dir - 1];
- float mad_abr = useNoiseCCurve ? noisevar_ab * madab[lvl][dir - 1] : SQR(noisevar_ab) * madab[lvl][dir - 1];
+ float *nvc = nullptr;
+ nvc = new float[Hlvl_ab * Wlvl_ab];
- if (noisevar_ab > 0.001f) {
+ if ((local == 2 || local == 3) && variC && useNoiseCCurve) {
+ noisevarfc = variC[lvl];
+
+ for (int p = 0; p < Hlvl_ab * Wlvl_ab; p++) {
+ nvc[p] = 10.f * sqrt(variC[lvl]) * SQR(1.f + 4.f * noisevarchrom[p]);
+ }
+
+ } else {
+ noisevarfc = noisevar_ab;
+
+ for (int p = 0; p < Hlvl_ab * Wlvl_ab; p++) {
+ nvc[p] = noisevarchrom[p];
+ }
+
+ }
+
+
+ // float mad_abr = useNoiseCCurve ? noisevar_ab * madab[lvl][dir - 1] : SQR(noisevar_ab) * madab[lvl][dir - 1];
+ float mad_abr = useNoiseCCurve ? noisevarfc * madab[lvl][dir - 1] : SQR(noisevarfc) * madab[lvl][dir - 1];
+
+ if (noisevarfc > 0.001f) {
#ifdef __SSE2__
vfloat onev = F2V(1.f);
@@ -2412,7 +2513,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &
int coeffloc_ab;
for (coeffloc_ab = 0; coeffloc_ab < Hlvl_ab * Wlvl_ab - 3; coeffloc_ab += 4) {
- mad_abv = LVFU(noisevarchrom[coeffloc_ab]) * mad_abrv;
+ mad_abv = LVFU(nvc[coeffloc_ab]) * mad_abrv;
tempabv = LVFU(WavCoeffs_ab[dir][coeffloc_ab]);
mag_Lv = LVFU(WavCoeffs_L[dir][coeffloc_ab]);
@@ -2425,7 +2526,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &
for (; coeffloc_ab < Hlvl_ab * Wlvl_ab; ++coeffloc_ab) {
float mag_L = SQR(WavCoeffs_L[dir][coeffloc_ab ]);
float mag_ab = SQR(WavCoeffs_ab[dir][coeffloc_ab]);
- WavCoeffs_ab[dir][coeffloc_ab] *= SQR(1.f - xexpf(-(mag_ab / (noisevarchrom[coeffloc_ab] * mad_abr)) - (mag_L / (9.f * mad_Lr)))/*satfactor_a*/);
+ WavCoeffs_ab[dir][coeffloc_ab] *= SQR(1.f - xexpf(-(mag_ab / (nvc[coeffloc_ab] * mad_abr)) - (mag_L / (9.f * mad_Lr)))/*satfactor_a*/);
}//now chrominance coefficients are denoised
#else
@@ -2437,7 +2538,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &
float mag_L = SQR(WavCoeffs_L[dir][coeffloc_ab ]);
float mag_ab = SQR(WavCoeffs_ab[dir][coeffloc_ab]);
- WavCoeffs_ab[dir][coeffloc_ab] *= SQR(1.f - xexpf(-(mag_ab / (noisevarchrom[coeffloc_ab] * mad_abr)) - (mag_L / (9.f * mad_Lr)))/*satfactor_a*/);
+ WavCoeffs_ab[dir][coeffloc_ab] *= SQR(1.f - xexpf(-(mag_ab / (nvc[coeffloc_ab] * mad_abr)) - (mag_L / (9.f * mad_Lr)))/*satfactor_a*/);
}
}//now chrominance coefficients are denoised
@@ -2445,9 +2546,12 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &
#endif
}
+ delete [] nvc;
+
}
}
}
+
}
for (int i = 2; i >= 0; i--) {
@@ -2459,16 +2563,20 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &
}
-bool ImProcFunctions::WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge)//mod JD
+bool ImProcFunctions::WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels)//mod JD
{
int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5);
- if (edge == 1) {
+ if (edge == 1 || edge == 3) {
maxlvl = 4; //for refine denoise edge wavelet
}
+ if (edge == 2) {
+ maxlvl = 7; //for locallab denoise
+ }
+
int maxWL = 0, maxHL = 0;
for (int lvl = 0; lvl < maxlvl; ++lvl) {
@@ -2517,11 +2625,20 @@ bool ImProcFunctions::WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoe
bool ImProcFunctions::WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab,
- float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb)//mod JD
+ float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels)//mod JD
{
int maxlvl = WaveletCoeffs_L.maxlevel();
+
+ if (local == 2) {
+ maxlvl = 7; //for local denoise
+ }
+
+ if (local == 3) {
+ maxlvl = 4; //for shape detection
+ }
+
int maxWL = 0, maxHL = 0;
for (int lvl = 0; lvl < maxlvl; ++lvl) {
@@ -2555,7 +2672,7 @@ bool ImProcFunctions::WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCo
for (int lvl = 0; lvl < maxlvl; ++lvl) {
for (int dir = 1; dir < 4; ++dir) {
- ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl]);
+ ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], variC, local, nullptr, 0);
}
}
}
@@ -2569,8 +2686,6 @@ bool ImProcFunctions::WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCo
return (!memoryAllocationFailed);
}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir,
@@ -2582,7 +2697,7 @@ void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, f
float * sfave = buffer[0] + 32;
float * sfaved = buffer[1] + 64;
- float * blurBuffer = buffer[2] + 96;
+// float * blurBuffer = buffer[2] + 96;
const int W_L = WaveletCoeffs_L.level_W(level);
const int H_L = WaveletCoeffs_L.level_H(level);
@@ -2591,30 +2706,54 @@ void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, f
const float mad_L = madL[dir - 1] ;
const float levelFactor = mad_L * 5.f / static_cast(level + 1);
- if (edge == 1 && vari) {
- noisevarlum = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer
+ float *nvl = nullptr;
+ nvl = new float[ H_L * W_L];
- for (int i = 0; i < W_L * H_L; ++i) {
- noisevarlum[i] = vari[level];
- }
+ for (int i = 0; i < W_L * H_L; ++i) {
+ nvl[i] = 0.f;
}
+ if ((edge == 1 || edge == 2 || edge == 3) && 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) {
+ nvl[i] = vari[level]; //* SQR(1.f + 4.f * noisevarchrom[p]);
+ }
+ }
+
+ if (edge == 2 || edge == 4) {
+ for (int i = 0; i < W_L * H_L; ++i) {
+ nvl[i] = vari[level] * SQR(noisevarlum[i]);
+ }
+ }
+
+ }
+
+ else {
+ for (int i = 0; i < W_L * H_L; ++i) {
+ nvl[i] = noisevarlum[i];
+ }
+
+ }
int i = 0;
#ifdef __SSE2__
const vfloat levelFactorv = F2V(levelFactor);
const vfloat ninev = F2V(9.f);
const vfloat epsv = F2V(eps);
- for (; i < W_L * H_L - 3; i += 4) {
- const vfloat mad_Lv = LVFU(noisevarlum[i]) * levelFactorv;
+
+ for (i = 0; i < W_L * H_L - 3; i += 4) {
+ // const vfloat mad_Lv = LVFU(noisevarlum[i]) * levelFactorv;
+ const vfloat mad_Lv = LVFU(nvl[i]) * levelFactorv;
const vfloat magv = SQRV(LVFU(WavCoeffs_L[dir][i]));
STVFU(sfave[i], magv / (magv + mad_Lv * xexpf(-magv / (ninev * mad_Lv)) + epsv));
}
+
#endif
// few remaining pixels
for (; i < W_L * H_L; ++i) {
- const float mag = SQR(WavCoeffs_L[dir][i]);
- sfave[i] = mag / (mag + levelFactor * noisevarlum[i] * xexpf(-mag / (9 * levelFactor * noisevarlum[i])) + eps);
+ float mag = SQR(WavCoeffs_L[dir][i]);
+ sfave[i] = mag / (mag + levelFactor * nvl[i] * xexpf(-mag / (9 * levelFactor * nvl[i])) + eps);
}
boxblur(sfave, sfaved, level + 2, W_L, H_L, false); //increase smoothness by locally averaging shrinkage
@@ -2634,12 +2773,15 @@ void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, f
//use smoothed shrinkage unless local shrinkage is much less
WavCoeffs_L[dir][i] *= (SQR(sfaved[i]) + SQR(sf)) / (sfaved[i] + sf + eps);
}//now luminance coefficients are denoised
+
+ delete [] nvl;
+
}
-void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
- float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch,
- bool denoiseMethodRgb, float * madL, float * madaab, bool madCalculated)
+void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition & WaveletCoeffs_L, const wavelet_decomposition & WaveletCoeffs_ab, float **buffer, int level, int dir,
+ float * noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch,
+ bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab, bool madCalculated)
{
//simple wavelet shrinkage
@@ -2651,6 +2793,7 @@ void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L,
float * sfaveab = buffer[0] + 32;
float * sfaveabd = buffer[1] + 64;
+ // float * blurBuffer = buffer[2] + 96;
int W_ab = WaveletCoeffs_ab.level_W(level);
int H_ab = WaveletCoeffs_ab.level_H(level);
@@ -2670,9 +2813,30 @@ void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L,
madab = SQR(MadRgb(WavCoeffs_ab[dir], W_ab * H_ab));
}
}
+ float noisevarfc;
- if (noisevar_ab > 0.001f) {
- madab = useNoiseCCurve ? madab : madab * noisevar_ab;
+ float *nvc = nullptr;
+ nvc = new float[ H_ab * W_ab];
+
+ if ((local == 2 || local == 3) && variC && useNoiseCCurve) {
+ noisevarfc = variC[level];
+ for (int p = 0; p < H_ab * W_ab; p++) {
+ nvc[p] = 10.f * sqrt(variC[level]) * SQR(1.f + 4.f * noisevarchrom[p]);
+ }
+
+ } else {
+ noisevarfc = noisevar_ab;
+
+ for (int p = 0; p < H_ab * W_ab; p++) {
+ nvc[p] = noisevarchrom[p];
+ }
+
+ }
+
+ // printf("varfc=%f nvc0=%f nvc1=%f nvc2=%f\n", noisevarfc, nvc[10], nvc[H_ab * W_ab /3], nvc[H_ab * W_ab /2]);
+ if (noisevarfc > 0.001f) {//noisevar_ab
+ //madab = useNoiseCCurve ? madab : madab * noisevar_ab;
+ madab = useNoiseCCurve ? madab : madab * noisevarfc;
#ifdef __SSE2__
vfloat onev = F2V(1.f);
vfloat mad_abrv = F2V(madab);
@@ -2680,10 +2844,11 @@ void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L,
vfloat rmadLm9v = onev / F2V(mad_L * 9.f);
vfloat mad_abv ;
vfloat mag_Lv, mag_abv;
+
int coeffloc_ab;
for (coeffloc_ab = 0; coeffloc_ab < H_ab * W_ab - 3; coeffloc_ab += 4) {
- mad_abv = LVFU(noisevarchrom[coeffloc_ab]) * mad_abrv;
+ mad_abv = LVFU(nvc[coeffloc_ab]) * mad_abrv;
mag_Lv = LVFU(WavCoeffs_L[dir][coeffloc_ab]);
mag_abv = SQRV(LVFU(WavCoeffs_ab[dir][coeffloc_ab]));
@@ -2695,7 +2860,7 @@ void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L,
for (; coeffloc_ab < H_ab * W_ab; ++coeffloc_ab) {
float mag_L = SQR(WavCoeffs_L[dir][coeffloc_ab]);
float mag_ab = SQR(WavCoeffs_ab[dir][coeffloc_ab]);
- sfaveab[coeffloc_ab] = (1.f - xexpf(-(mag_ab / (noisevarchrom[coeffloc_ab] * madab)) - (mag_L / (9.f * mad_L))));
+ sfaveab[coeffloc_ab] = (1.f - xexpf(-(mag_ab / (nvc[coeffloc_ab] * madab)) - (mag_L / (9.f * mad_L))));
}//now chrominance coefficients are denoised
#else
@@ -2705,13 +2870,14 @@ void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L,
int coeffloc_ab = i * W_ab + j;
float mag_L = SQR(WavCoeffs_L[dir][coeffloc_ab]);
float mag_ab = SQR(WavCoeffs_ab[dir][coeffloc_ab]);
- sfaveab[coeffloc_ab] = (1.f - xexpf(-(mag_ab / (noisevarchrom[coeffloc_ab] * madab)) - (mag_L / (9.f * mad_L))));
+ sfaveab[coeffloc_ab] = (1.f - xexpf(-(mag_ab / (nvc[coeffloc_ab] * madab)) - (mag_L / (9.f * mad_L))));
}
}//now chrominance coefficients are denoised
#endif
-
boxblur(sfaveab, sfaveabd, level + 2, W_ab, H_ab, false); //increase smoothness by locally averaging shrinkage
+
+// boxblur(sfaveab, sfaveabd, blurBuffer, level + 2, level + 2, W_ab, H_ab); //increase smoothness by locally averaging shrinkage
#ifdef __SSE2__
vfloat epsv = F2V(eps);
vfloat sfabv;
@@ -2749,12 +2915,13 @@ void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L,
#endif
}
+ delete [] nvc;
}
void ImProcFunctions::ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b,
- int W_ab, int H_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut,
- float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
- float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb)
+ int W_ab, int H_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float & chaut, int &Nb, float & redaut, float & blueaut,
+ float & maxredaut, float & maxblueaut, float & minredaut, float & minblueaut, int schoice, int lvl, float & chromina, float & sigma, float & lumema, float & sigma_L, float & redyel, float & skinc, float & nsknc,
+ float & maxchred, float & maxchblue, float & minchred, float & minchblue, int &nb, float & chau, float & chred, float & chblue, bool denoiseMethodRgb)
{
//simple wavelet shrinkage
@@ -2869,9 +3036,9 @@ void ImProcFunctions::ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b,
}
-void ImProcFunctions::WaveletDenoiseAll_info(int levwav, const wavelet_decomposition &WaveletCoeffs_a,
- const wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice,
- float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb)
+void ImProcFunctions::WaveletDenoiseAll_info(int levwav, const wavelet_decomposition & WaveletCoeffs_a,
+ const wavelet_decomposition & WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float & chaut, int &Nb, float & redaut, float & blueaut, float & maxredaut, float & maxblueaut, float & minredaut, float & minblueaut, int schoice,
+ float & chromina, float & sigma, float & lumema, float & sigma_L, float & redyel, float & skinc, float & nsknc, float & maxchred, float & maxchblue, float & minchred, float & minchblue, int &nb, float & chau, float & chred, float & chblue, bool denoiseMethodRgb)
{
int maxlvl = levwav;
@@ -2914,7 +3081,7 @@ void ImProcFunctions::RGB_denoise_infoGamCurve(const procparams::DirPyrDenoisePa
}
}
-void ImProcFunctions::calcautodn_info(float &chaut, float &delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc)
+void ImProcFunctions::calcautodn_info(float & chaut, float & delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc)
{
float reducdelta = 1.f;
diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc
index 36aa96030..aab2a252c 100644
--- a/rtengine/camconst.cc
+++ b/rtengine/camconst.cc
@@ -2,20 +2,25 @@
* This file is part of RawTherapee.
*/
#include "camconst.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
#include
#include
#include
+
#include "settings.h"
#include "rt_math.h"
-#include
-#include
// cJSON is a very minimal JSON parser lib in C, not for threaded stuff etc, so if we're going to use JSON more than just
// here we should probably replace cJSON with something beefier.
#include "cJSON.h"
-#include
-#include
-#include
namespace rtengine
{
@@ -30,66 +35,70 @@ CameraConst::CameraConst() : pdafOffset(0)
}
-bool
-CameraConst::parseApertureScaling(CameraConst *cc, void *ji_)
+bool CameraConst::parseApertureScaling(CameraConst *cc, const void *ji_)
{
- cJSON *ji = (cJSON *)ji_;
+ const cJSON *ji = static_cast(ji_);
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"ranges\":\"aperture_scaling\" must be an array\n");
return false;
}
- for (ji = ji->child; ji != nullptr; ji = ji->next) {
- cJSON *js = cJSON_GetObjectItem(ji, "aperture");
+ for (ji = ji->child; ji; ji = ji->next) {
+ const cJSON *js = cJSON_GetObjectItem(ji, "aperture");
if (!js) {
fprintf(stderr, "missing \"ranges\":\"aperture_scaling\":\"aperture\" object item.\n");
return false;
- } else if (js->type != cJSON_Number) {
+ }
+
+ if (js->type != cJSON_Number) {
fprintf(stderr, "\"ranges\":\"aperture_scaling\":\"aperture\" must be a number.\n");
return false;
}
- float aperture = (float)js->valuedouble;
+ const float aperture = js->valuedouble;
js = cJSON_GetObjectItem(ji, "scale_factor");
if (!js) {
fprintf(stderr, "missing \"ranges\":\"aperture_scaling\":\"scale_factor\" object item.\n");
return false;
- } else if (js->type != cJSON_Number) {
+ }
+
+ if (js->type != cJSON_Number) {
fprintf(stderr, "\"ranges\":\"aperture_scaling\":\"scale_factor\" must be a number.\n");
return false;
}
- float scale_factor = (float)js->valuedouble;
- cc->mApertureScaling.insert(std::pair(aperture, scale_factor));
+ const float scale_factor = js->valuedouble;
+ cc->mApertureScaling.emplace(aperture, scale_factor);
}
return true;
}
-bool
-CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_)
+bool CameraConst::parseLevels(CameraConst *cc, int bw, const void *ji_)
{
- cJSON *ji = (cJSON *)ji_;
+ const cJSON *ji = static_cast(ji_);
if (ji->type == cJSON_Number) {
- struct camera_const_levels lvl;
+ camera_const_levels lvl;
lvl.levels[0] = lvl.levels[1] = lvl.levels[2] = lvl.levels[3] = ji->valueint;
- cc->mLevels[bw].insert(std::pair(0, lvl));
+ cc->mLevels[bw].emplace(0, lvl);
return true;
- } else if (ji->type != cJSON_Array) {
+ }
+
+ if (ji->type != cJSON_Array) {
fprintf(stderr, "\"ranges\":\"%s\" must be a number or an array\n", bw ? "white" : "black");
return false;
}
if (ji->child->type == cJSON_Number) {
- struct camera_const_levels lvl;
+ camera_const_levels lvl;
int i;
- cJSON *js;
+ const cJSON *js;
- for (js = ji->child, i = 0; js != nullptr && i < 4; js = js->next, i++) {
+ for (js = ji->child, i = 0; js && i < 4; js = js->next, i++) {
lvl.levels[i] = js->valueint;
}
@@ -97,39 +106,36 @@ CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_)
lvl.levels[3] = lvl.levels[1]; // G2 = G1
} else if (i == 1) {
lvl.levels[3] = lvl.levels[2] = lvl.levels[1] = lvl.levels[0];
- } else if (i != 4 || js != nullptr) {
+ } else if (i != 4 || js) {
fprintf(stderr, "\"ranges\":\"%s\" array must have 1, 3 or 4 numbers.\n", bw ? "white" : "black");
return false;
}
- cc->mLevels[bw].insert(std::pair(0, lvl));
+ cc->mLevels[bw].emplace(0, lvl);
return true;
}
- for (ji = ji->child; ji != nullptr; ji = ji->next) {
- int iso[1000] = { 0 };
- int iso_count = 0;
- cJSON *js = cJSON_GetObjectItem(ji, "iso");
+ for (ji = ji->child; ji; ji = ji->next) {
+ const cJSON *js = cJSON_GetObjectItem(ji, "iso");
if (!js) {
fprintf(stderr, "missing \"ranges\":\"%s\":\"iso\" object item.\n", bw ? "white" : "black");
return false;
- } else if (js->type == cJSON_Number) {
- iso[0] = js->valueint;
- iso_count = 1;
- } else if (js->type == cJSON_Array) {
- int i;
+ }
- for (js = js->child, i = 0; js != nullptr && i < 1000; js = js->next, i++) {
+ std::vector isos;
+
+ if (js->type == cJSON_Number) {
+ isos.push_back(js->valueint);
+ } else if (js->type == cJSON_Array) {
+ for (js = js->child; js; js = js->next) {
if (js->type != cJSON_Number) {
fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be a number or an array of numbers.\n", bw ? "white" : "black");
return false;
}
- iso[i] = js->valueint;
+ isos.push_back(js->valueint);
}
-
- iso_count = i;
} else {
fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be an array or a number.\n", bw ? "white" : "black");
return false;
@@ -142,14 +148,14 @@ CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_)
return false;
}
- struct camera_const_levels lvl;
+ camera_const_levels lvl;
if (js->type == cJSON_Number) {
lvl.levels[0] = lvl.levels[1] = lvl.levels[2] = lvl.levels[3] = js->valueint;
} else if (js->type == cJSON_Array) {
int i;
- for (js = js->child, i = 0; js != nullptr && i < 4; js = js->next, i++) {
+ for (js = js->child, i = 0; js && i < 4; js = js->next, i++) {
if (js->type != cJSON_Number) {
fprintf(stderr, "\"ranges\":\"%s\":\"levels\" must be a number or an array of numbers.\n", bw ? "white" : "black");
return false;
@@ -162,7 +168,7 @@ CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_)
lvl.levels[3] = lvl.levels[1]; // G2 = G1
} else if (i == 1) {
lvl.levels[3] = lvl.levels[2] = lvl.levels[1] = lvl.levels[0];
- } else if (i != 4 || js != nullptr) {
+ } else if (i != 4 || js) {
fprintf(stderr, "\"ranges\":\"%s\":\"levels\" array must have 1, 3 or 4 numbers.\n", bw ? "white" : "black");
return false;
}
@@ -171,40 +177,38 @@ CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_)
return false;
}
- for (int i = 0; i < iso_count; i++) {
- cc->mLevels[bw].insert(std::pair(iso[i], lvl));
+ for (auto iso : isos) {
+ cc->mLevels[bw].emplace(iso, lvl);
}
}
return true;
}
-CameraConst *
-CameraConst::parseEntry(void *cJSON_, const char *make_model)
+CameraConst* CameraConst::parseEntry(const void *cJSON_, const char *make_model)
{
- cJSON *js, *ji, *jranges;
- js = (cJSON *)cJSON_;
+ const cJSON *js = static_cast(cJSON_);
- CameraConst *cc = new CameraConst;
+ std::unique_ptr cc(new CameraConst);
cc->make_model = make_model;
- ji = cJSON_GetObjectItem(js, "dcraw_matrix");
+ const cJSON *ji = cJSON_GetObjectItem(js, "dcraw_matrix");
if (ji) {
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"dcraw_matrix\" must be an array\n");
- goto parse_error;
+ return nullptr;
}
int i;
- for (i = 0, ji = ji->child; i < 12 && ji != nullptr; i++, ji = ji->next) {
+ for (i = 0, ji = ji->child; i < 12 && ji; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"dcraw_matrix\" array must contain numbers\n");
- goto parse_error;
+ return nullptr;
}
- cc->dcraw_matrix[i] = (short)ji->valueint;
+ cc->dcraw_matrix[i] = ji->valueint;
}
}
@@ -213,23 +217,23 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model)
if (ji) {
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"raw_crop\" must be an array\n");
- goto parse_error;
+ return nullptr;
}
int i;
- for (i = 0, ji = ji->child; i < 4 && ji != nullptr; i++, ji = ji->next) {
+ for (i = 0, ji = ji->child; i < 4 && ji; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"raw_crop\" array must contain numbers\n");
- goto parse_error;
+ return nullptr;
}
cc->raw_crop[i] = ji->valueint;
}
- if (i != 4 || ji != nullptr) {
+ if (i != 4 || ji) {
fprintf(stderr, "\"raw_crop\" must contain 4 numbers\n");
- goto parse_error;
+ return nullptr;
}
}
@@ -238,15 +242,15 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model)
if (ji) {
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"masked_areas\" must be an array\n");
- goto parse_error;
+ return nullptr;
}
int i;
- for (i = 0, ji = ji->child; i < 8 * 4 && ji != nullptr; i++, ji = ji->next) {
+ for (i = 0, ji = ji->child; i < 2 * 4 && ji; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"masked_areas\" array must contain numbers\n");
- goto parse_error;
+ return nullptr;
}
cc->raw_mask[i / 4][i % 4] = ji->valueint;
@@ -254,27 +258,23 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model)
if (i % 4 != 0) {
fprintf(stderr, "\"masked_areas\" array length must be divisible by 4\n");
- goto parse_error;
+ return nullptr;
}
}
- jranges = cJSON_GetObjectItem(js, "ranges");
+ const cJSON *jranges = cJSON_GetObjectItem(js, "ranges");
if (jranges) {
ji = cJSON_GetObjectItem(jranges, "black");
- if (ji) {
- if (!parseLevels(cc, 0, ji)) {
- goto parse_error;
- }
+ if (ji && !parseLevels(cc.get(), 0, ji)) {
+ return nullptr;
}
ji = cJSON_GetObjectItem(jranges, "white");
- if (ji) {
- if (!parseLevels(cc, 1, ji)) {
- goto parse_error;
- }
+ if (ji && !parseLevels(cc.get(), 1, ji)) {
+ return nullptr;
}
ji = cJSON_GetObjectItem(jranges, "white_max");
@@ -282,32 +282,28 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model)
if (ji) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"ranges\":\"white_max\" must be a number\n");
- goto parse_error;
+ return nullptr;
}
- cc->white_max = (int)ji->valueint;
+ cc->white_max = ji->valueint;
}
ji = cJSON_GetObjectItem(jranges, "aperture_scaling");
- if (ji) {
- if (!parseApertureScaling(cc, ji)) {
- goto parse_error;
- }
+ if (ji && !parseApertureScaling(cc.get(), ji)) {
+ return nullptr;
}
}
for (int bw = 0; bw < 2; bw++) {
- struct camera_const_levels lvl;
+ camera_const_levels lvl;
if (!cc->get_Levels(lvl, bw, 0, 0)) {
- std::map::iterator it;
- it = cc->mLevels[bw].begin();
+ const auto it = cc->mLevels[bw].cbegin();
- if (it != cc->mLevels[bw].end()) {
+ if (it != cc->mLevels[bw].cend()) {
// insert levels with lowest iso as the default (iso 0)
- struct camera_const_levels lvl = it->second;
- cc->mLevels[bw].insert(std::pair(0, lvl));
+ cc->mLevels[bw].emplace(0, it->second);
}
}
}
@@ -317,13 +313,13 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model)
if (ji) {
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"pdaf_pattern\" must be an array\n");
- goto parse_error;
+ return nullptr;
}
- for (ji = ji->child; ji != nullptr; ji = ji->next) {
+ for (ji = ji->child; ji; ji = ji->next) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"pdaf_pattern\" array must contain numbers\n");
- goto parse_error;
+ return nullptr;
}
cc->pdafPattern.push_back(ji->valueint);
@@ -335,7 +331,7 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model)
if (ji) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"pdaf_offset\" must contain a number\n");
- goto parse_error;
+ return nullptr;
}
cc->pdafOffset = ji->valueint;
@@ -346,27 +342,21 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model)
if (ji) {
if (ji->type != cJSON_False && ji->type != cJSON_True) {
fprintf(stderr, "\"global_green_equilibration\" must be a boolean\n");
- goto parse_error;
+ return nullptr;
}
cc->globalGreenEquilibration = (ji->type == cJSON_True);
}
- return cc;
-
-parse_error:
- delete cc;
- return nullptr;
+ return cc.release();
}
-bool
-CameraConst::has_dcrawMatrix()
+bool CameraConst::has_dcrawMatrix() const
{
return dcraw_matrix[0] != 0;
}
-void
-CameraConst::update_dcrawMatrix(const short *other)
+void CameraConst::update_dcrawMatrix(const short *other)
{
if (!other) {
return;
@@ -377,8 +367,7 @@ CameraConst::update_dcrawMatrix(const short *other)
}
}
-const short *
-CameraConst::get_dcrawMatrix()
+const short* CameraConst::get_dcrawMatrix() const
{
if (!has_dcrawMatrix()) {
return nullptr;
@@ -387,44 +376,35 @@ CameraConst::get_dcrawMatrix()
return dcraw_matrix;
}
-bool
-CameraConst::has_pdafPattern()
-{
- return pdafPattern.size() > 0;
-}
-
-std::vector
-CameraConst::get_pdafPattern()
+const std::vector& CameraConst::get_pdafPattern() const
{
return pdafPattern;
}
-void
-CameraConst::update_pdafPattern(const std::vector &other)
+void CameraConst::update_pdafPattern(const std::vector &other)
{
if (other.empty()) {
return;
}
+
pdafPattern = other;
}
-void
-CameraConst::update_pdafOffset(int other)
+void CameraConst::update_pdafOffset(int other)
{
if (other == 0) {
return;
}
+
pdafOffset = other;
}
-bool
-CameraConst::has_rawCrop()
+bool CameraConst::has_rawCrop() const
{
return raw_crop[0] != 0 || raw_crop[1] != 0 || raw_crop[2] != 0 || raw_crop[3] != 0;
}
-void
-CameraConst::get_rawCrop(int& left_margin, int& top_margin, int& width, int& height)
+void CameraConst::get_rawCrop(int& left_margin, int& top_margin, int& width, int& height) const
{
left_margin = raw_crop[0];
top_margin = raw_crop[1];
@@ -432,22 +412,20 @@ CameraConst::get_rawCrop(int& left_margin, int& top_margin, int& width, int& hei
height = raw_crop[3];
}
-bool
-CameraConst::has_rawMask(int idx)
+bool CameraConst::has_rawMask(int idx) const
{
- if (idx < 0 || idx > 7) {
+ if (idx < 0 || idx > 1) {
return false;
}
return (raw_mask[idx][0] | raw_mask[idx][1] | raw_mask[idx][2] | raw_mask[idx][3]) != 0;
}
-void
-CameraConst::get_rawMask(int idx, int& top, int& left, int& bottom, int& right)
+void CameraConst::get_rawMask(int idx, int& top, int& left, int& bottom, int& right) const
{
top = left = bottom = right = 0;
- if (idx < 0 || idx > 7) {
+ if (idx < 0 || idx > 1) {
return;
}
@@ -457,38 +435,30 @@ CameraConst::get_rawMask(int idx, int& top, int& left, int& bottom, int& right)
right = raw_mask[idx][3];
}
-void
-CameraConst::update_Levels(const CameraConst *other)
+void CameraConst::update_Levels(const CameraConst *other)
{
if (!other) {
return;
}
- if (other->mLevels[0].size()) {
- mLevels[0].clear();
+ if (!other->mLevels[0].empty()) {
mLevels[0] = other->mLevels[0];
}
- if (other->mLevels[1].size()) {
- mLevels[1].clear();
+ if (!other->mLevels[1].empty()) {
mLevels[1] = other->mLevels[1];
}
- if (other->mApertureScaling.size()) {
- mApertureScaling.clear();
+ if (!other->mApertureScaling.empty()) {
mApertureScaling = other->mApertureScaling;
}
if (other->white_max) {
white_max = other->white_max;
}
-
-// for (std::map::iterator i=other->mLevels[0].begin(); i!=other->mLevels[0].end(); i++) {
-// }
}
-void
-CameraConst::update_Crop(CameraConst *other)
+void CameraConst::update_Crop(CameraConst *other)
{
if (!other) {
return;
@@ -499,18 +469,16 @@ CameraConst::update_Crop(CameraConst *other)
}
}
-bool
-CameraConst::get_Levels(struct camera_const_levels & lvl, int bw, int iso, float fnumber)
+bool CameraConst::get_Levels(camera_const_levels & lvl, int bw, int iso, float fnumber) const
{
- std::map::iterator it;
- it = mLevels[bw].find(iso);
+ std::map::const_iterator it = mLevels[bw].find(iso);
if (it == mLevels[bw].end()) {
- std::map::iterator best_it = mLevels[bw].begin();
+ auto best_it = mLevels[bw].cbegin();
if (iso > 0) {
for (it = mLevels[bw].begin(); it != mLevels[bw].end(); ++it) {
- if (abs(it->first - iso) <= abs(best_it->first - iso)) {
+ if (std::abs(it->first - iso) <= std::abs(best_it->first - iso)) {
best_it = it;
} else {
break;
@@ -527,35 +495,34 @@ CameraConst::get_Levels(struct camera_const_levels & lvl, int bw, int iso, float
lvl = it->second;
- if (bw == 1 && fnumber > 0 && mApertureScaling.size() > 0) {
- std::map::iterator it;
- it = mApertureScaling.find(fnumber);
+ if (bw == 1 && fnumber > 0 && !mApertureScaling.empty()) {
+ std::map::const_iterator scaleIt = mApertureScaling.find(fnumber);
- if (it == mApertureScaling.end()) {
+ if (scaleIt == mApertureScaling.end()) {
// fnumber may be an exact aperture, eg 1.414, or a rounded eg 1.4. In our map we
// should have rounded numbers so we translate and retry the lookup
// table with traditional 1/3 stop f-number rounding used by most cameras, we only
// have in the range 0.7 - 10.0, but aperture scaling rarely happen past f/4.0
- const float fn_tab[8][3] = {
- { 0.7, 0.8, 0.9 },
- { 1.0, 1.1, 1.2 },
- { 1.4, 1.6, 1.8 },
- { 2.0, 2.2, 2.5 },
- { 2.8, 3.2, 3.5 },
- { 4.0, 4.5, 5.0 },
- { 5.6, 6.3, 7.1 },
- { 8.0, 9.0, 10.0 }
+ constexpr float fn_tab[8][3] = {
+ { 0.7f, 0.8f, 0.9f },
+ { 1.f, 1.1f, 1.2f },
+ { 1.4f, 1.6f, 1.8f },
+ { 2.f, 2.2f, 2.5f },
+ { 2.8f, 3.2f, 3.5f },
+ { 4.f, 4.5f, 5.f },
+ { 5.6f, 6.3f, 7.1f },
+ { 8.f, 9.f, 10.f }
};
for (int avh = 0; avh < 8; avh++) {
for (int k = 0; k < 3; k++) {
- float av = (avh - 1) + (float)k / 3;
- float aperture = sqrtf(powf(2, av));
+ const float av = (avh - 1) + k / 3.f;
+ const float aperture = std::sqrt(std::pow(2.f, av));
if (fnumber > aperture * 0.97f && fnumber < aperture / 0.97f) {
fnumber = fn_tab[avh][k];
- it = mApertureScaling.find(fnumber);
+ scaleIt = mApertureScaling.find(fnumber);
avh = 7;
break;
}
@@ -563,20 +530,18 @@ CameraConst::get_Levels(struct camera_const_levels & lvl, int bw, int iso, float
}
}
- float scaling = 1.0;
+ float scaling = 1.f;
- if (it == mApertureScaling.end()) {
- std::map::reverse_iterator it;
-
- for (it = mApertureScaling.rbegin(); it != mApertureScaling.rend(); ++it) {
- if (it->first > fnumber) {
- scaling = it->second;
+ if (scaleIt == mApertureScaling.end()) {
+ for (auto entry = mApertureScaling.crbegin(); entry != mApertureScaling.crend(); ++entry) {
+ if (entry->first > fnumber) {
+ scaling = entry->second;
} else {
break;
}
}
} else {
- scaling = it->second;
+ scaling = scaleIt->second;
}
if (scaling > 1.f) {
@@ -593,24 +558,22 @@ CameraConst::get_Levels(struct camera_const_levels & lvl, int bw, int iso, float
return true;
}
-int
-CameraConst::get_BlackLevel(const int idx, const int iso_speed)
+int CameraConst::get_BlackLevel(const int idx, const int iso_speed) const
{
assert(idx >= 0 && idx <= 3);
- struct camera_const_levels lvl;
+ camera_const_levels lvl;
- if (!get_Levels(lvl, 0, iso_speed, 0.0)) {
+ if (!get_Levels(lvl, 0, iso_speed, 0.f)) {
return -1;
}
return lvl.levels[idx];
}
-int
-CameraConst::get_WhiteLevel(const int idx, const int iso_speed, const float fnumber)
+int CameraConst::get_WhiteLevel(const int idx, const int iso_speed, const float fnumber) const
{
assert(idx >= 0 && idx <= 3);
- struct camera_const_levels lvl;
+ camera_const_levels lvl;
if (!get_Levels(lvl, 1, iso_speed, fnumber)) {
return -1;
@@ -619,48 +582,44 @@ CameraConst::get_WhiteLevel(const int idx, const int iso_speed, const float fnum
return lvl.levels[idx];
}
-bool
-CameraConst::has_globalGreenEquilibration()
+bool CameraConst::has_globalGreenEquilibration() const
{
return globalGreenEquilibration >= 0;
}
-bool
-CameraConst::get_globalGreenEquilibration()
+bool CameraConst::get_globalGreenEquilibration() const
{
return globalGreenEquilibration > 0;
}
-void
-CameraConst::update_globalGreenEquilibration(bool other)
+void CameraConst::update_globalGreenEquilibration(bool other)
{
globalGreenEquilibration = (other ? 1 : 0);
}
-bool
-CameraConstantsStore::parse_camera_constants_file(const Glib::ustring& filename_)
+bool CameraConstantsStore::parse_camera_constants_file(const Glib::ustring& filename_)
{
// read the file into a single long string
const char *filename = filename_.c_str();
FILE *stream = fopen(filename, "rt");
- if (stream == nullptr) {
+ if (!stream) {
fprintf(stderr, "Could not open camera constants file \"%s\": %s\n", filename, strerror(errno));
return false;
}
- size_t bufsize = 16384;
- size_t increment = 2 * bufsize;
+ size_t bufsize = 262144;
+ size_t increment = bufsize;
size_t datasize = 0, ret;
char *buf = (char *)malloc(bufsize);
- while ((ret = fread(&buf[datasize], 1, bufsize - datasize, stream)) != 0) {
+ while ((ret = fread(&buf[datasize], 1, bufsize - datasize - 1, stream)) != 0) {
datasize += ret;
- if (datasize == bufsize) { // we need more memory
+ if (datasize == bufsize - 1) { // we need more memory
bufsize += increment;
void *temp = realloc(buf, bufsize); // try to realloc buffer with new size
- if(!temp) { // realloc failed
+ if (!temp) { // realloc failed
temp = malloc(bufsize); // alloc now buffer
if (temp) { // alloc worked
memcpy(temp, buf, bufsize - increment); // copy old buffer content to new buffer
@@ -683,17 +642,13 @@ CameraConstantsStore::parse_camera_constants_file(const Glib::ustring& filename_
fclose(stream);
- if(datasize == bufsize) {
- buf = (char *)realloc(buf, datasize + 1);
- }
-
buf[datasize] = '\0';
// remove comments
cJSON_Minify(buf);
// parse
- cJSON *jsroot = cJSON_Parse(buf);
+ cJSON* const jsroot = cJSON_Parse(buf);
if (!jsroot) {
char str[128];
@@ -711,20 +666,16 @@ CameraConstantsStore::parse_camera_constants_file(const Glib::ustring& filename_
}
free(buf);
- /*{
- char *js_str = cJSON_Print(jsroot);
- printf("%s\n", js_str);
- free(js_str);
- }*/
- cJSON *js = cJSON_GetObjectItem(jsroot, "camera_constants");
+
+ const cJSON *js = cJSON_GetObjectItem(jsroot, "camera_constants");
if (!js) {
fprintf(stderr, "missing \"camera_constants\" object item\n");
goto parse_error;
}
- for (js = js->child; js != nullptr; js = js->next) {
- cJSON *ji = cJSON_GetObjectItem(js, "make_model");
+ for (js = js->child; js; js = js->next) {
+ const cJSON *ji = cJSON_GetObjectItem(js, "make_model");
if (!ji) {
fprintf(stderr, "missing \"make_model\" object item\n");
@@ -738,30 +689,30 @@ CameraConstantsStore::parse_camera_constants_file(const Glib::ustring& filename_
is_array = true;
}
- while (ji != nullptr) {
+ while (ji) {
if (ji->type != cJSON_String) {
fprintf(stderr, "\"make_model\" must be a string or an array of strings\n");
goto parse_error;
}
- CameraConst *cc = CameraConst::parseEntry((void *)js, ji->valuestring);
+ CameraConst* const cc = CameraConst::parseEntry((const void *)js, ji->valuestring);
if (!cc) {
goto parse_error;
}
- Glib::ustring make_model(ji->valuestring);
- make_model = make_model.uppercase();
+ std::string make_model(ji->valuestring);
+ std::transform(make_model.begin(), make_model.end(), make_model.begin(), ::toupper);
- const auto ret = mCameraConstants.emplace(make_model, cc);
+ const auto entry = mCameraConstants.emplace(make_model, cc);
- if(ret.second) { // entry inserted into map
+ if (entry.second) { // entry inserted into map
if (settings->verbose) {
printf("Add camera constants for \"%s\"\n", make_model.c_str());
}
} else {
// The CameraConst already exist for this camera make/model -> we merge the values
- CameraConst *existingcc = ret.first->second;
+ CameraConst* const existingcc = entry.first->second;
// updating the dcraw matrix
existingcc->update_dcrawMatrix(cc->get_dcrawMatrix());
@@ -813,29 +764,26 @@ void CameraConstantsStore::init(const Glib::ustring& baseDir, const Glib::ustrin
{
parse_camera_constants_file(Glib::build_filename(baseDir, "camconst.json"));
- Glib::ustring userFile(Glib::build_filename(userSettingsDir, "camconst.json"));
+ const Glib::ustring userFile(Glib::build_filename(userSettingsDir, "camconst.json"));
if (Glib::file_test(userFile, Glib::FILE_TEST_EXISTS)) {
parse_camera_constants_file(userFile);
}
}
-CameraConstantsStore *
-CameraConstantsStore::getInstance()
+CameraConstantsStore* CameraConstantsStore::getInstance()
{
static CameraConstantsStore instance_;
return &instance_;
}
-CameraConst *
-CameraConstantsStore::get(const char make[], const char model[])
+const CameraConst* CameraConstantsStore::get(const char make[], const char model[]) const
{
- Glib::ustring key(make);
+ std::string key(make);
key += " ";
key += model;
- key = key.uppercase();
- std::map::iterator it;
- it = mCameraConstants.find(key);
+ std::transform(key.begin(), key.end(), key.begin(), ::toupper);
+ const auto it = mCameraConstants.find(key);
if (it == mCameraConstants.end()) {
return nullptr;
diff --git a/rtengine/camconst.h b/rtengine/camconst.h
index 3af05ab01..aa0702439 100644
--- a/rtengine/camconst.h
+++ b/rtengine/camconst.h
@@ -27,35 +27,34 @@ private:
std::string make_model;
short dcraw_matrix[12];
int raw_crop[4];
- int raw_mask[8][4];
+ int raw_mask[2][4];
int white_max;
- std::map mLevels[2];
+ std::map mLevels[2];
std::map mApertureScaling;
std::vector pdafPattern;
int pdafOffset;
int globalGreenEquilibration;
CameraConst();
- static bool parseLevels(CameraConst *cc, int bw, void *ji);
- static bool parseApertureScaling(CameraConst *cc, void *ji);
- bool get_Levels(struct camera_const_levels & lvl, int bw, int iso, float fnumber);
+ static bool parseLevels(CameraConst *cc, int bw, const void *ji);
+ static bool parseApertureScaling(CameraConst *cc, const void *ji);
+ bool get_Levels(camera_const_levels & lvl, int bw, int iso, float fnumber) const;
public:
- static CameraConst *parseEntry(void *cJSON, const char *make_model);
- bool has_dcrawMatrix(void);
- bool has_pdafPattern(void);
+ static CameraConst *parseEntry(const void *cJSON, const char *make_model);
+ bool has_dcrawMatrix(void) const;
void update_dcrawMatrix(const short *other);
- const short *get_dcrawMatrix(void);
- std::vector get_pdafPattern();
- int get_pdafOffset() {return pdafOffset;}
- bool has_rawCrop(void);
- void get_rawCrop(int& left_margin, int& top_margin, int& width, int& height);
- bool has_rawMask(int idx);
- void get_rawMask(int idx, int& top, int& left, int& bottom, int& right);
- int get_BlackLevel(int idx, int iso_speed);
- int get_WhiteLevel(int idx, int iso_speed, float fnumber);
- bool has_globalGreenEquilibration();
- bool get_globalGreenEquilibration();
+ const short *get_dcrawMatrix(void) const;
+ const std::vector& get_pdafPattern() const;
+ int get_pdafOffset() const {return pdafOffset;};
+ bool has_rawCrop(void) const;
+ void get_rawCrop(int& left_margin, int& top_margin, int& width, int& height) const;
+ bool has_rawMask(int idx) const;
+ void get_rawMask(int idx, int& top, int& left, int& bottom, int& right) const;
+ int get_BlackLevel(int idx, int iso_speed) const;
+ int get_WhiteLevel(int idx, int iso_speed, float fnumber) const;
+ bool has_globalGreenEquilibration() const;
+ bool get_globalGreenEquilibration() const;
void update_Levels(const CameraConst *other);
void update_Crop(CameraConst *other);
void update_pdafPattern(const std::vector &other);
@@ -75,7 +74,7 @@ public:
~CameraConstantsStore();
void init(const Glib::ustring& baseDir, const Glib::ustring& userSettingsDir);
static CameraConstantsStore *getInstance(void);
- CameraConst *get(const char make[], const char model[]);
+ const CameraConst *get(const char make[], const char model[]) const;
};
}
diff --git a/rtengine/camconst.json b/rtengine/camconst.json
index f58167478..5fc7d4062 100644
--- a/rtengine/camconst.json
+++ b/rtengine/camconst.json
@@ -1240,6 +1240,12 @@ Camera constants:
"ranges": { "white": 4050 } // nominal 4080-4093
},
+ { // Quality C, only raw crop
+ "make_model": "Canon PowerShot SX70 HS",
+ "dcraw_matrix" : [18285, -8907, -1951, -1845, 10688, 1323, 364, 1101, 5139], // taken from ART
+ "raw_crop": [ 96, 17, 5248, 3932 ]
+ },
+
{ // Quality C
"make_model": "Canon PowerShot SX150 IS",
"dcraw_matrix": [ 13481, -4867, -1063, -2074, 9960, 2472, -170, 1474, 3894 ], // Adobe DNG Converter 11.1 ColorMatrix1 (there is only one matrix and illuminant, and it's for daylight)
@@ -1265,6 +1271,7 @@ Camera constants:
{ // Quality C
"make_model": "FUJIFILM GFX 100",
+ "dcraw_matrix" : [16212, -8423, -1583, -4336, 12583, 1937, -195, 726, 6199], // taken from ART
"raw_crop": [ 0, 2, 11664, 8734 ]
},
@@ -1288,6 +1295,12 @@ Camera constants:
"ranges": { "white": 16100 }
},
+ { // Quality C
+ "make_model": [ "FUJIFILM X100V", "FUJIFILM X-T4" ],
+ "dcraw_matrix": [ 13426,-6334,-1177,-4244,12136,2371,-580,1303,5980 ], // DNG_v12.2 D65
+ "raw_crop": [ 0, 5, 6252, 4140 ]
+ },
+
{ // Quality C
"make_model": "Fujifilm X10",
"ranges": { "white": 3788 }
@@ -1345,6 +1358,7 @@ Camera constants:
{ // Quality C
"make_model": [ "FUJIFILM X-T100" ],
+ "dcraw_matrix" : [11673, -4760, -1041, -3988, 12058, 2166, -771, 1417, 5568], // taken from ART
"ranges": { "white": 16100 }
},
@@ -1370,7 +1384,8 @@ Camera constants:
},
{ // Quality C, only raw crop
- "make_model": [ "FUJIFILM X-T3", "FUJIFILM X-T30" ],
+ "make_model": [ "FUJIFILM X-T3", "FUJIFILM X-T30", "FUJIFILM X-PRO3" ],
+ "dcraw_matrix": [ 13426,-6334,-1177,-4244,12136,2371,-580,1303,5980 ], // DNG_v11, standard_v2 d65
"raw_crop": [ 0, 5, 6252, 4176]
},
@@ -1386,6 +1401,11 @@ Camera constants:
"ranges": { "white": 4040 }
},
+ { // Quality B, Matrix from ART
+ "make_model" : "LEICA D-LUX 7",
+ "dcraw_matrix" : [11577, -4230, -1106, -3967, 12211, 1957, -758, 1762, 5610]
+ },
+
{ // Quality B, Matrix from Adobe's dcp D65 instead of the internal in Leica's DNG
"make_model": "LEICA Q (Typ 116)",
"dcraw_matrix": [ 10068,-4043,-1068,-5319,14268,1044,-765,1701,6522 ], // DCP D65
@@ -1408,6 +1428,11 @@ Camera constants:
"raw_crop": [ 0, 0, 0, -18 ] // 18 rows at bottom are garbage
},
+ { // Quality B, Matrix from ART
+ "make_model" : "LEICA V-LUX 5",
+ "dcraw_matrix" : [9803, -4185, -992, -4066, 12578, 1628, -838, 1824, 5288]
+ },
+
{ // Quality C
"make_model": "LG mobile LG-H815",
"dcraw_matrix": [ 5859,547,-1250,-6484,15547,547,-2422,5625,3906 ], // DNG D65
@@ -1515,7 +1540,7 @@ Camera constants:
{ // Quality B
"make_model": "NIKON COOLPIX P1000",
"dcraw_matrix": [ 14294, -6116, -1333, -1628, 10219, 1637, -14, 1158, 5022 ], // ColorMatrix2 from Adobe DNG Converter 11.4
- "ranges": { "black": 200, "white": 4093 }
+ "ranges": { "black": 200, "white": 4087 }
},
{ // Quality B, no LENR samples
@@ -1768,6 +1793,7 @@ Camera constants:
{ // Quality C, only raw crop
"make_model": "OLYMPUS TG-6",
+ "dcraw_matrix" : [10899, -3832, -1082, -2112, 10736, 1575, -267, 1452, 5269], // taken from ART
"raw_crop": [ 0, 0, -24, 0 ] // 24 pixels at right are garbage
},
diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc
index ec8641fc0..2780fcc84 100644
--- a/rtengine/colortemp.cc
+++ b/rtengine/colortemp.cc
@@ -33,7 +33,7 @@
namespace rtengine
{
-static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer.
+static const double cie_colour_match_jd2[97][3] = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer.
{0.0000000, 0.000000, 0.000000}, {0.0000000, 0.000000, 0.000000}, {0.0001299, 0.0003917, 0.0006061},
{0.0002321, 0.000006965, 0.001086}, {0.0004149, 0.00001239, 0.001946}, {0.0007416, 0.00002202, 0.003846},
{0.001368, 0.000039, 0.006450001}, {0.002236, 0.000064, 0.01054999}, {0.004243, 0.000120, 0.02005001},
@@ -69,6 +69,108 @@ static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desm
{0.000001251141, 0.00000045181, 0.000000}
};
+
+static double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 10° Standard Observer.
+{0.000000000000, 0.000000000000, 0.000000000000},
+{0.000000000000, 0.000000000000, 0.000000000000},
+{0.000000122200, 0.000000013398, 0.000000535027},
+{0.000000919270, 0.000000100650, 0.000004028300},
+{0.000005958600, 0.000000651100, 0.000026143700},
+{0.000033266000, 0.000003625000, 0.000146220000},
+{0.000159952000, 0.000017364000, 0.000704776000},
+{0.000662440000, 0.000071560000, 0.002927800000},
+{0.002361600000, 0.000253400000, 0.010482200000},
+{0.007242300000, 0.000768500000, 0.032344000000},
+{0.019109700000, 0.002004400000, 0.086010900000},
+{0.043400000000, 0.004509000000, 0.197120000000},
+{0.084736000000, 0.008756000000, 0.389366000000},
+{0.140638000000, 0.014456000000, 0.656760000000},
+{0.204492000000, 0.021391000000, 0.972542000000},
+{0.264737000000, 0.029497000000, 1.282500000000},
+{0.314679000000, 0.038676000000, 1.553480000000},
+{0.357719000000, 0.049602000000, 1.798500000000},
+{0.383734000000, 0.062077000000, 1.967280000000},
+{0.386726000000, 0.074704000000, 2.027300000000},
+{0.370702000000, 0.089456000000, 1.994800000000},
+{0.342957000000, 0.106256000000, 1.900700000000},
+{0.302273000000, 0.128201000000, 1.745370000000},
+{0.254085000000, 0.152761000000, 1.554900000000},
+{0.195618000000, 0.185190000000, 1.317560000000},
+{0.132349000000, 0.219940000000, 1.030200000000},
+{0.080507000000, 0.253589000000, 0.772125000000},
+{0.041072000000, 0.297665000000, 0.570060000000},
+{0.016172000000, 0.339133000000, 0.415254000000},
+{0.005132000000, 0.395379000000, 0.302356000000},
+{0.003816000000, 0.460777000000, 0.218502000000},
+{0.015444000000, 0.531360000000, 0.159249000000},
+{0.037465000000, 0.606741000000, 0.112044000000},
+{0.071358000000, 0.685660000000, 0.082248000000},
+{0.117749000000, 0.761757000000, 0.060709000000},
+{0.172953000000, 0.823330000000, 0.043050000000},
+{0.236491000000, 0.875211000000, 0.030451000000},
+{0.304213000000, 0.923810000000, 0.020584000000},
+{0.376772000000, 0.961988000000, 0.013676000000},
+{0.451584000000, 0.982200000000, 0.007918000000},
+{0.529826000000, 0.991761000000, 0.003988000000},
+{0.616053000000, 0.999110000000, 0.001091000000},
+{0.793832000000, 0.982380000000, 0.000000000000},
+{0.878655000000, 0.955552000000, 0.000000000000},
+{0.951162000000, 0.915175000000, 0.000000000000},
+{1.014160000000, 0.868934000000, 0.000000000000},
+{1.074300000000, 0.825623000000, 0.000000000000},
+{1.118520000000, 0.777405000000, 0.000000000000},
+{1.134300000000, 0.720353000000, 0.000000000000},
+{1.123990000000, 0.658341000000, 0.000000000000},
+{1.089100000000, 0.593878000000, 0.000000000000},
+{1.030480000000, 0.527963000000, 0.000000000000},
+{0.950740000000, 0.461834000000, 0.000000000000},
+{0.856297000000, 0.398057000000, 0.000000000000},
+{0.754930000000, 0.339554000000, 0.000000000000},
+{0.647467000000, 0.283493000000, 0.000000000000},
+{0.535110000000, 0.228254000000, 0.000000000000},
+{0.431567000000, 0.179828000000, 0.000000000000},
+{0.343690000000, 0.140211000000, 0.000000000000},
+{0.268329000000, 0.107633000000, 0.000000000000},
+{0.204300000000, 0.081187000000, 0.000000000000},
+{0.152568000000, 0.060281000000, 0.000000000000},
+{0.112210000000, 0.044096000000, 0.000000000000},
+{0.081260600000, 0.031800400000, 0.000000000000},
+{0.057930000000, 0.022601700000, 0.000000000000},
+{0.040850800000, 0.015905100000, 0.000000000000},
+{0.028623000000, 0.011130300000, 0.000000000000},
+{0.019941300000, 0.007748800000, 0.000000000000},
+{0.013842000000, 0.005375100000, 0.000000000000},
+{0.009576880000, 0.003717740000, 0.000000000000},
+{0.006605200000, 0.002564560000, 0.000000000000},
+{0.004552630000, 0.001768470000, 0.000000000000},
+{0.003144700000, 0.001222390000, 0.000000000000},
+{0.002174960000, 0.000846190000, 0.000000000000},
+{0.001505700000, 0.000586440000, 0.000000000000},
+{0.001044760000, 0.000407410000, 0.000000000000},
+{0.000727450000, 0.000284041000, 0.000000000000},
+{0.000508258000, 0.000198730000, 0.000000000000},
+{0.000356380000, 0.000139550000, 0.000000000000},
+{0.000250969000, 0.000098428000, 0.000000000000},
+{0.000177730000, 0.000069819000, 0.000000000000},
+{0.000126390000, 0.000049737000, 0.000000000000},
+{0.000090151000, 0.000035540500, 0.000000000000},
+{0.000064525800, 0.000025486000, 0.000000000000},
+{0.000046339000, 0.000018338400, 0.000000000000},
+{0.000033411700, 0.000013249000, 0.000000000000},
+{0.000024209000, 0.000009619600, 0.000000000000},
+{0.000017611500, 0.000007012800, 0.000000000000},
+{0.000012855000, 0.000005129800, 0.000000000000},
+{0.000009413630, 0.000003764730, 0.000000000000},
+{0.000006913000, 0.000002770810, 0.000000000000},
+{0.000005093470, 0.000002046130, 0.000000000000},
+{0.000003767100, 0.000001516770, 0.000000000000},
+{0.000002795310, 0.000001128090, 0.000000000000},
+{0.000002082000, 0.000000842160, 0.000000000000},
+{0.000001553140, 0.000000629700, 0.000000000000}
+};
+
+
+
ColorTemp::ColorTemp (double t, double g, double e, const std::string &m) : temp(t), green(g), equal(e), method(m)
{
clip (temp, green, equal);
@@ -2408,7 +2510,66 @@ const double ColorTemp::Colorlab_n80_26_spect[97] = {
-0.2047, -0.205, -0.2069, -0.208, -0.2099, -0.21, -0.2115, -0.21, -0.2106, -0.209, -0.2086,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
};
+/*
+//0,1767000 0,2207000 0,3142000 0,5269000 0,7018000 0,7605000 0,7580000 0,7366000 0,7182000 0,6929000 0,6661000 0,6542000
+//0,6420000 0,6085000 0,5752000 0,5728000 0,5723000 0,5318000 0,4982000 0,5226000 0,5670000 0,5929000 0,5977000 0,5975000
+//0,6002000 0,6065000 0,6177000 0,6352000 0,6526000 0,6623000 0,6633000 0,6593000 0,6517000 0,6479000 0,6607000 0,6908000
+const double ColorTemp::JDC468_greyc14_66_spect[97] = {
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.1767, 0.19, 0.2207, 0.25, 0.3142, 0.40, 0.5269, 0.63, 0.7018, 0.73, 0.7605, 0.76, 0.7580, 0.74, 0.7366, 0.725, 0.7182, 0.705, 0.6929, 0.68, 0.6661, 0.66, 0.6542, 0.65,
+ 0.642, 0.62, 0.6085, 0.585, 0.5752, 0.573, 0.5728, 0.573, 0.5723, 0.555, 0.5318, 0.51, 0.4982, 0.51, 0.5226, 0.54, 0.5670, 0.58, 0.5929, 0.594, 0.5977, 0.597, 0.5975, 0.6,
+ 0.6002, 0.602, 0.6065, 0.61, 0.6177, 0.62, 0.6352, 0.64, 0.6526, 0.66, 0.6623, 0.662, 0.6633, 0.66, 0.6593, 0.653, 0.6517, 0.65, 0.6479, 0.65, 0.6607, 0.69, 0.6908,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+};
+//0,1325000 0,1637000 0,2222000 0,3492000 0,4523000 0,4897000 0,4918000 0,4840000 0,4761000 0,4638000 0,4538000 0,4582000
+// 0,4588000 0,4360000 0,4091000 0,4101000 0,4128000 0,3785000 0,3494000 0,3720000 0,4122000 0,4339000 0,4362000 0,4355000
+// 0,4395000 0,4475000 0,4606000 0,4807000 0,5006000 0,5125000 0,5145000 0,5112000 0,5029000 0,4992000 0,5150000 0,5526000
+
+const double ColorTemp::JDC468_greym13_325_spect[97] = {
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.1325, 0.15, 0.1637, 0.2, 0.2222, 0.28, 0.3492, 0.40, 0.4523, 0.47, 0.4897, 0.49, 0.4918, 0.49, 0.4840, 0.48, 0.4761, 0.47, 0.4638, 0.46, 0.4538, 0.455, 0.4582, 0.458,
+ 0.4588, 0.45, 0.4360, 0.42, 0.4091, 0.41, 0.4101, 0.411, 0.4128, 0.405, 0.3785, 0.36, 0.3494, 0.36, 0.3720, 0.41, 0.4122, 0.425, 0.4339, 0.435, 0.4362, 0.597, 0.4355, 0.437,
+ 0.4395, 0.44, 0.4475, 0.45, 0.4606, 0.47, 0.4807, 0.49, 0.5006, 0.51, 0.5125, 0.513, 0.5145, 0.512, 0.5112, 0.51, 0.5029, 0.5, 0.4992, 0.51, 0.5150, 0.53, 0.5526,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+};
+
+//0,0823000 0,1036000 0,1337000 0,1966000 0,2468000 0,2679000 0,2728000 0,2726000 0,2724000 0,2698000 0,2705000 0,2810000
+// 0,2879000 0,2756000 0,2586000 0,2601000 0,2617000 0,2357000 0,2124000 0,2241000 0,2471000 0,2581000 0,2569000 0,2548000
+// 0,2579000 0,2653000 0,2765000 0,2941000 0,3126000 0,3230000 0,3238000 0,3189000 0,3091000 0,3043000 0,3200000 0,3579000
+
+const double ColorTemp::JDC468_greyf26_156_spect[97] = {
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0823, 0.1, 0.1036, 0.11, 0.1337, 0.16, 0.1966, 0.22, 0.2468, 0.255, 0.2679, 0.27, 0.2728, 0.273, 0.2726, 0.273, 0.2724, 0.271, 0.2698, 0.27, 0.2705, 0.275, 0.2810, 0.285,
+ 0.2879, 0.28, 0.2756, 0.26, 0.2586, 0.26, 0.2601, 0.261, 0.2617, 0.25, 0.2357, 0.22, 0.2124, 0.22, 0.2241, 0.23, 0.2471, 0.25, 0.2581, 0.278, 0.2569, 0.255, 0.2548, 0.255,
+ 0.2579, 0.26, 0.2653, 0.27, 0.2765, 0.28, 0.2941, 0.30, 0.3126, 0.32, 0.3230, 0.323, 0.3238, 0.32, 0.3189, 0.31, 0.3091, 0.302, 0.3043, 0.31, 0.3200, 0.34, 0.3579,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+};
+*/
+//A1 0.0912 0.1228 0.1712 0.2978 0.3713 0.4241 0.4861 0.5255 0.5355 0.5363 0.5237 0.5251
+// 0.5722 0.6554 0.6936 0.6675 0.6203 0.5651 0.5116 0.4825 0.4714 0.4866 0.5320 0.5729
+// 0.5968 0.6069 0.6131 0.6198 0.6285 0.6325 0.6316 0.6282 0.6227 0.6196 0.6215 0.6337
+
+const double ColorTemp::Colorlab_n80_5_9_5_9spect[97] = {
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0912, 0.1, 0.1228, 0.15, 0.1712, 0.2, 0.2978, 0.32, 0.3713, 0.41, 0.4241, 0.44, 0.4861, 0.51, 0.5255, 0.53, 0.5355, 0.534, 0.5363, 0.53, 0.5237, 0.524, 0.5251, 0.56,
+ 0.5722, 0.6, 0.6554, 0.67, 0.6936, 0.67, 0.6675, 0.65, 0.6203, 0.6, 0.5651, 0.54, 0.5116, 0.5, 0.4825, 0.48, 0.4714, 0.48, 0.4866, 0.5, 0.5320, 0.55, 0.5729, 0.58,
+ 0.5968, 0.6, 0.6069, 0.61, 0.6131, 0.615, 0.6198, 0.62, 0.6285, 0.63, 0.6325, 0.632, 0.6316, 0.63, 0.6282, 0.625, 0.6227, 0.62, 0.6196, 0.62, 0.6215, 0.63, 0.6337,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+};
+/*
+//A2 0.0385 0.0514 0.0711 0.1229 0.1528 0.1744 0.1999 0.2163 0.2209 0.2216 0.2167 0.2185
+//0.2414 0.2813 0.3012 0.2922 0.2734 0.2511 0.2292 0.2173 0.2127 0.2183 0.2354 0.2508
+//0.2599 0.2637 0.2662 0.2689 0.2725 0.2742 0.2738 0.2724 0.2701 0.2689 0.2697 0.2747
+
+const double ColorTemp::Colorlab_n57_5_6_9spect[97] = {
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0385, 0.04, 0.0514, 0.06, 0.0711, 0.1, 0.1229, 0.14, 0.1528, 0.16, 0.1744, 0.18, 0.1999, 0.2, 0.2163, 0.22, 0.2209, 0.221, 0.2216, 0.22, 0.2167, 0.216, 0.2185, 0.23,
+ 0.2414, 0.26, 0.2813, 0.3, 0.3012, 0.3, 0.2922, 0.28, 0.2734, 0.26, 0.2511, 0.24, 0.2292, 0.22, 0.2173, 0.215, 0.2127, 0.215, 0.2183, 0.22, 0.2354, 0.24, 0.2508, 0.255,
+ 0.2599, 0.26, 0.2637, 0.263, 0.2662, 0.267, 0.2689, 0.27, 0.2725, 0.273, 0.2742, 0.274, 0.2738, 0.273, 0.2724, 0.271, 0.2701, 0.27, 0.2689, 0.269, 0.2697, 0.27, 0.2747,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+};
+*/
/*
* Name: XYZtoCorColorTemp.c
*
@@ -3230,6 +3391,7 @@ this values are often called xBar yBar zBar and are characteristics of a color /
values cie_colour_match[][3] = 2° Standard Observer x2, y2, z2
E.g. for 380nm: x2=0.001368 y2=0.000039 z2=0.006451 round in J.Walker to 0.0014 0.0000 0.0065 above
I have increase precision used by J.Walker and pass to 350nm to 830nm
+And also add 10° standard observer
*/
void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, double &y, double &z)
@@ -3288,6 +3450,7 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou
values cie_colour_match[][3] = 2° Standard Observer x2, y2, z2
E.g. for 380nm: x2=0.001368 y2=0.000039 z2=0.006451 round in J.Walker to 0.0014 0.0000 0.0065 above
I have increased the precision used by J.Walker and pass from 350nm to 830nm
+ And also add standard observer 10°
*/
for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) {
double Me = get_spectral_color(lambda, spec_intens);
@@ -3449,7 +3612,10 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
J570_NeuQ1_spect, J570_NeuS7_spect,
J570_NeuV10_spect, J570_NeuW18_spect, J570_NeuZ14_spect, //189
J570_NeuC18_spect, J570_NeuD17_spect, J570_NeuJ11_spect, J570_NeuL4_spect, Colorlab_n72_n2_spect,
- Colorlab_10_n70_spect, Colorlab_n33_n70_spect, Colorlab_n8_n74_spect, Colorlab_19_n69_spect, Colorlab_n80_10_spect, Colorlab_n80_26_spect
+ Colorlab_10_n70_spect, Colorlab_n33_n70_spect, Colorlab_n8_n74_spect, Colorlab_19_n69_spect, Colorlab_n80_10_spect, Colorlab_n80_26_spect,
+ Colorlab_n80_5_9_5_9spect //, Colorlab_n57_5_6_9spect
+
+ /*JDC468_greyc14_66_spect, JDC468_greym13_325_spect, JDC468_greyf26_156_spect*/
};
@@ -3459,7 +3625,7 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
double ZZ;
} WbTxyz;
//probbaly can be "passed" with rawimagesource.cc but I don't know how to do.
- constexpr WbTxyz Txyz[118] = {//temperature Xwb Zwb 118 values x wb and y wb are calculated after
+ constexpr WbTxyz Txyz[118] = {//temperature Xwb Zwb 118 values - same table as in Rawimagesource.cc x wb and y wb are calculated after
{2001., 1.273842, 0.145295},
{2101., 1.244008, 0.167533},
{2201., 1.217338, 0.190697},
@@ -3595,6 +3761,22 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
Refxyz[i].Zref = 0.f;
}
+ if (settings->verbose) {
+ if (settings->itcwb_stdobserver10 == false) {
+ printf("Use standard observer 2°\n");
+ } else {
+ printf("Use standard observer 10°\n");
+ }
+ }
+
+ if (settings->itcwb_stdobserver10 == false) {
+ for (int i = 0; i < 97; i++) {
+ cie_colour_match_jd[i][0] = cie_colour_match_jd2[i][0];
+ cie_colour_match_jd[i][1] = cie_colour_match_jd2[i][1];;
+ cie_colour_match_jd[i][2] = cie_colour_match_jd2[i][2];
+ }
+ }
+
if (separated) {
const double tempw = Txyz[repref].Tem;
diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h
index 5feed9d26..89c324490 100644
--- a/rtengine/colortemp.h
+++ b/rtengine/colortemp.h
@@ -367,7 +367,14 @@ public:
static const double Colorlab_19_n69_spect[97];
static const double Colorlab_n80_10_spect[97];
static const double Colorlab_n80_26_spect[97];
-
+ static const double Colorlab_n80_5_9_5_9spect[97];
+// static const double Colorlab_n57_5_6_9spect[97];
+
+ /*
+ static const double JDC468_greyc14_66_spect[97];
+ static const double JDC468_greym13_325_spect[97];
+ static const double JDC468_greyf26_156_spect[97];
+ */
static void spectrum_to_xyz_daylight (double _m1, double _m2, double &x, double &y, double &z);
static void spectrum_to_xyz_blackbody (double _temp, double &x, double &y, double &z);
static void spectrum_to_xyz_preset (const double* spec_intens, double &x, double &y, double &z);
diff --git a/rtengine/curves.cc b/rtengine/curves.cc
index a2b5d1d2b..ebb23e754 100644
--- a/rtengine/curves.cc
+++ b/rtengine/curves.cc
@@ -1209,6 +1209,41 @@ void WavCurve::Set(const std::vector &curvePoints)
}
}
+Wavblcurve::Wavblcurve() {}
+
+void Wavblcurve::Reset()
+{
+ lutblcurve.reset();
+}
+
+void Wavblcurve::Set(const Curve &pCurve)
+{
+ if (pCurve.isIdentity()) {
+ Reset(); // raise this value if the quality suffers from this number of samples
+ return;
+ }
+
+ lutblcurve(501); // raise this value if the quality suffers from this number of samples
+
+ for (int i = 0; i < 501; i++) {
+ lutblcurve[i] = pCurve.getVal(double(i) / 500.);
+ }
+}
+
+void Wavblcurve::Set(const std::vector &curvePoints)
+{
+ if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
+ FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ tcurve.setIdentityValue(0.);
+ Set(tcurve);
+ } else {
+ Reset();
+ }
+
+}
+
+
+
WavOpacityCurveRG::WavOpacityCurveRG() {}
@@ -1243,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 c5bb0c18f..0fb58cc9e 100644
--- a/rtengine/curves.h
+++ b/rtengine/curves.h
@@ -627,6 +627,30 @@ public:
}
};
+class Wavblcurve
+{
+private:
+ LUTf lutblcurve; // 0xffff range
+ void Set(const Curve &pCurve);
+public:
+ virtual ~Wavblcurve() {};
+ Wavblcurve();
+
+ void Reset();
+ // void Set(const std::vector &curvePoints, bool &opautili);
+ void Set(const std::vector &curvePoints);
+ float operator[](float index) const
+ {
+ return lutblcurve[index];
+ }
+
+ operator bool (void) const
+ {
+ return lutblcurve;
+ }
+};
+
+
class WavOpacityCurveRG
{
private:
@@ -649,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/dcraw.cc b/rtengine/dcraw.cc
index 0858bdaaa..edb7dc317 100644
--- a/rtengine/dcraw.cc
+++ b/rtengine/dcraw.cc
@@ -1,7 +1,6 @@
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
-#pragma GCC diagnostic ignored "-Wunused-macros"
#if (__GNUC__ >= 6)
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
#endif
@@ -63,12 +62,8 @@
$Date: 2018/06/01 20:36:25 $
*/
-#define DCRAW_VERSION "9.28"
+//#define DCRAW_VERSION "9.28"
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#define _USE_MATH_DEFINES
#include
#include
#include
@@ -95,8 +90,12 @@
#ifdef WIN32
#include
#include
+#ifndef strcasecmp
#define strcasecmp stricmp
+#endif
+#ifndef strncasecmp
#define strncasecmp strnicmp
+#endif
typedef __int64 INT64;
typedef unsigned __int64 UINT64;
#else
@@ -6899,7 +6898,7 @@ it under the terms of the one of two licenses as you choose:
break;
case 50778:
case 50779:
- if( get2() == 21 )
+ if( get2() != 17 ) // 17 is Standard light A
cm_D65 = (tag-50778);
break;
case 50829: /* ActiveArea */
@@ -9097,6 +9096,8 @@ void CLASS adobe_coeff (const char *make, const char *model)
if (load_raw == &CLASS sony_arw2_load_raw) { // RT: arw2 scale fix
black <<= 2;
tiff_bps += 2;
+ } else if (load_raw == &CLASS panasonic_load_raw) {
+ tiff_bps = RT_pana_info.bpp;
}
{ /* Check for RawTherapee table overrides and extensions */
int black_level, white_level;
@@ -10047,6 +10048,9 @@ canon_a5:
} else if (!strncmp(model, "X-A3", 4) || !strncmp(model, "X-A5", 4)) {
width = raw_width = 6016;
height = raw_height = 4014;
+ } else if (!strcmp(model, "X-Pro3") || !strcmp(model, "X-T3") || !strcmp(model, "X-T30")) {
+ width = raw_width = 6384;
+ height = raw_height = 4182;
}
top_margin = (raw_height - height) >> 2 << 1;
left_margin = (raw_width - width ) >> 2 << 1;
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index 243ea1b62..8bf27b53d 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -967,13 +967,15 @@ 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, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
LabImage *unshar = nullptr;
Glib::ustring provis;
LabImage *provradius = nullptr;
@@ -1002,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, 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;
@@ -1015,7 +1017,7 @@ void Crop::update(int todo)
WaveParams.expnoise = false;
}
- parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
+ parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
WaveParams.expcontrast = procont;
@@ -1028,7 +1030,7 @@ void Crop::update(int todo)
array2D ble(labnCrop->W, labnCrop->H);
array2D guid(labnCrop->W, labnCrop->H);
Imagefloat *tmpImage = nullptr;
- tmpImage = new Imagefloat(labnCrop->W, labnCrop->W);
+ tmpImage = new Imagefloat(labnCrop->W, labnCrop->H);
#ifdef _OPENMP
#pragma omp parallel for
diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc
index c7de3c483..6d4fe1ad6 100644
--- a/rtengine/filmnegativeproc.cc
+++ b/rtengine/filmnegativeproc.cc
@@ -35,6 +35,9 @@
namespace
{
+using rtengine::ST_BAYER;
+using rtengine::ST_FUJI_XTRANS;
+using rtengine::settings;
bool channelsAvg(
const rtengine::RawImage* ri,
@@ -43,17 +46,16 @@ bool channelsAvg(
const float* cblacksom,
rtengine::Coord spotPos,
int spotSize,
- const rtengine::procparams::FilmNegativeParams& params,
std::array& avgs
)
{
avgs = {}; // Channel averages
- if (ri->getSensorType() != rtengine::ST_BAYER && ri->getSensorType() != rtengine::ST_FUJI_XTRANS) {
+ if (ri->getSensorType() != ST_BAYER && ri->getSensorType() != ST_FUJI_XTRANS) {
return false;
}
- if (rtengine::settings->verbose) {
+ if (settings->verbose) {
printf("Spot coord: x=%d y=%d\n", spotPos.x, spotPos.y);
}
@@ -69,9 +71,10 @@ bool channelsAvg(
}
std::array pxCount = {}; // Per-channel sample counts
+
for (int c = x1; c < x2; ++c) {
for (int r = y1; r < y2; ++r) {
- const int ch = ri->getSensorType() == rtengine::ST_BAYER ? ri->FC(r,c) : ri->XTRANSFC(r,c);
+ const int ch = ri->getSensorType() == ST_BAYER ? ri->FC(r, c) : ri->XTRANSFC(r, c);
++pxCount[ch];
@@ -88,6 +91,112 @@ bool channelsAvg(
return true;
}
+void calcMedians(
+ const rtengine::RawImage* ri,
+ float** data,
+ int x1, int y1, int x2, int y2,
+ std::array& meds
+)
+{
+
+ MyTime t1, t2, t3;
+ t1.set();
+
+ // Channel vectors to calculate medians
+ std::array, 3> cvs;
+
+ // Sample one every 5 pixels, and push the value in the appropriate channel vector.
+ // Choose an odd step, not a multiple of the CFA size, to get a chance to visit each channel.
+ if (ri->getSensorType() == ST_BAYER) {
+ for (int row = y1; row < y2; row += 5) {
+ const int c0 = ri->FC(row, x1 + 0);
+ const int c1 = ri->FC(row, x1 + 5);
+ int col = x1;
+
+ for (; col < x2 - 5; col += 10) {
+ cvs[c0].push_back(data[row][col]);
+ cvs[c1].push_back(data[row][col + 5]);
+ }
+
+ if (col < x2) {
+ cvs[c0].push_back(data[row][col]);
+ }
+ }
+ } else if (ri->getSensorType() == ST_FUJI_XTRANS) {
+ for (int row = y1; row < y2; row += 5) {
+ const std::array cs = {
+ ri->XTRANSFC(row, x1 + 0),
+ ri->XTRANSFC(row, x1 + 5),
+ ri->XTRANSFC(row, x1 + 10),
+ ri->XTRANSFC(row, x1 + 15),
+ ri->XTRANSFC(row, x1 + 20),
+ ri->XTRANSFC(row, x1 + 25)
+ };
+ int col = x1;
+
+ for (; col < x2 - 25; col += 30) {
+ for (int c = 0; c < 6; ++c) {
+ cvs[cs[c]].push_back(data[row][col + c * 5]);
+ }
+ }
+
+ for (int c = 0; col < x2; col += 5, ++c) {
+ cvs[cs[c]].push_back(data[row][col]);
+ }
+ }
+ }
+
+ t2.set();
+
+ if (settings->verbose) {
+ printf("Median vector fill loop time us: %d\n", t2.etime(t1));
+ }
+
+ t2.set();
+
+ for (int c = 0; c < 3; ++c) {
+ // Find median values for each channel
+ if (!cvs[c].empty()) {
+ rtengine::findMinMaxPercentile(cvs[c].data(), cvs[c].size(), 0.5f, meds[c], 0.5f, meds[c], true);
+ }
+ }
+
+ t3.set();
+
+ if (settings->verbose) {
+ printf("Sample count: R=%zu, G=%zu, B=%zu\n", cvs[0].size(), cvs[1].size(), cvs[2].size());
+ printf("Median calc time us: %d\n", t3.etime(t2));
+ }
+
+}
+
+std::array calcWBMults(
+ const rtengine::ColorTemp& wb,
+ const rtengine::ImageMatrices& imatrices,
+ const rtengine::RawImage *ri,
+ const float ref_pre_mul[4])
+{
+ std::array wb_mul;
+ double r, g, b;
+ wb.getMultipliers(r, g, b);
+ wb_mul[0] = imatrices.cam_rgb[0][0] * r + imatrices.cam_rgb[0][1] * g + imatrices.cam_rgb[0][2] * b;
+ wb_mul[1] = imatrices.cam_rgb[1][0] * r + imatrices.cam_rgb[1][1] * g + imatrices.cam_rgb[1][2] * b;
+ wb_mul[2] = imatrices.cam_rgb[2][0] * r + imatrices.cam_rgb[2][1] * g + imatrices.cam_rgb[2][2] * b;
+
+ for (int c = 0; c < 3; ++c) {
+ wb_mul[c] = ri->get_pre_mul(c) / wb_mul[c] / ref_pre_mul[c];
+ }
+
+ // Normalize max channel gain to 1.0
+ float mg = rtengine::max(wb_mul[0], wb_mul[1], wb_mul[2]);
+
+ for (int c = 0; c < 3; ++c) {
+ wb_mul[c] /= mg;
+ }
+
+ return wb_mul;
+}
+
}
bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D spotB, int tran, const procparams::FilmNegativeParams ¤tParams, std::array& newExps)
@@ -104,21 +213,29 @@ bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D s
std::array clearVals;
std::array denseVals;
+ // Get channel averages in the two spots, sampling from the original ri->data buffer.
+ // NOTE: rawData values might be affected by CA corection, FlatField, etc, so:
+ // rawData[y][x] == (ri->data[y][x] - cblacksom[c]) * scale_mul[c]
+ // is not always true. To calculate exponents on the exact values, we should keep
+ // a copy of the rawData buffer after preprocessing. Worth the memory waste?
+
// Sample first spot
transformPosition(spotA.x, spotA.y, tran, spot.x, spot.y);
- if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, currentParams, clearVals)) {
+
+ if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, clearVals)) {
return false;
}
// Sample second spot
transformPosition(spotB.x, spotB.y, tran, spot.x, spot.y);
- if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, currentParams, denseVals)) {
+
+ if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, denseVals)) {
return false;
}
// Detect which one is the dense spot, based on green channel
if (clearVals[1] < denseVals[1]) {
- std::swap(clearVals, denseVals);
+ std::swap(clearVals, denseVals);
}
if (settings->verbose) {
@@ -152,7 +269,32 @@ bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D s
return true;
}
-void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams ¶ms)
+bool rtengine::RawImageSource::getRawSpotValues(Coord2D spotCoord, int spotSize, int tran, const procparams::FilmNegativeParams ¶ms, std::array& rawValues)
+{
+ Coord spot;
+ transformPosition(spotCoord.x, spotCoord.y, tran, spot.x, spot.y);
+
+ if (settings->verbose) {
+ printf("Transformed coords: %d,%d\n", spot.x, spot.y);
+ }
+
+ if (spotSize < 4) {
+ return false;
+ }
+
+ // Calculate averages of raw unscaled channels
+ if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, rawValues)) {
+ return false;
+ }
+
+ if (settings->verbose) {
+ printf("Raw spot values: R=%g, G=%g, B=%g\n", rawValues[0], rawValues[1], rawValues[2]);
+ }
+
+ return true;
+}
+
+void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams ¶ms, std::array& filmBaseValues)
{
// BENCHFUNMICRO
@@ -168,92 +310,114 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ
static_cast(-params.blueRatio * params.greenExp)
};
- MyTime t1, t2, t3,t4, t5;
-
- t1.set();
-
- // Channel vectors to calculate medians
- std::array, 3> cvs;
-
- // Sample one every 5 pixels, and push the value in the appropriate channel vector.
- // Choose an odd step, not a multiple of the CFA size, to get a chance to visit each channel.
- if (ri->getSensorType() == ST_BAYER) {
- for (int row = 0; row < H; row += 5) {
- const int c0 = ri->FC(row, 0);
- const int c1 = ri->FC(row, 5);
- int col = 0;
- for (; col < W - 5; col += 10) {
- cvs[c0].push_back(rawData[row][col]);
- cvs[c1].push_back(rawData[row][col + 5]);
- }
- if (col < W) {
- cvs[c0].push_back(rawData[row][col]);
- }
- }
- }
- else if (ri->getSensorType() == ST_FUJI_XTRANS) {
- for (int row = 0; row < H; row += 5) {
- const std::array cs = {
- ri->XTRANSFC(row, 0),
- ri->XTRANSFC(row, 5),
- ri->XTRANSFC(row, 10),
- ri->XTRANSFC(row, 15),
- ri->XTRANSFC(row, 20),
- ri->XTRANSFC(row, 25)
- };
- int col = 0;
- for (; col < W - 25; col += 30) {
- for (int c = 0; c < 6; ++c) {
- cvs[cs[c]].push_back(rawData[row][col + c * 5]);
- }
- }
- for (int c = 0; col < W; col += 5, ++c) {
- cvs[cs[c]].push_back(rawData[row][col]);
- }
- }
- }
-
constexpr float MAX_OUT_VALUE = 65000.f;
- t2.set();
+ // Get multipliers for a known, fixed WB setting, that will be the starting point
+ // for balancing the converted image.
+ const std::array wb_mul = calcWBMults(
+ ColorTemp(3500., 1., 1., "Custom"), imatrices, ri, ref_pre_mul);
- if (settings->verbose) {
- printf("Median vector fill loop time us: %d\n", t2.etime(t1));
+
+ if (rtengine::settings->verbose) {
+ printf("Fixed WB mults: %g %g %g\n", wb_mul[0], wb_mul[1], wb_mul[2]);
}
- t2.set();
+ // Compensation factor to restore the non-autoWB initialGain (see RawImageSource::load)
+ const float autoGainComp = camInitialGain / initialGain;
- std::array medians; // Channel median values
- std::array mults = {
- 1.f,
- 1.f,
- 1.f
- }; // Channel normalization multipliers
+ std::array mults; // Channel normalization multipliers
+
+ // If film base values are set in params, use those
+ if (filmBaseValues[0] <= 0.f) {
+ // ...otherwise, the film negative tool might have just been enabled on this image,
+ // whithout any previous setting. So, estimate film base values from channel medians
+
+ std::array medians;
+
+ // Special value for backwards compatibility with profiles saved by RT 5.7
+ const bool oldChannelScaling = filmBaseValues[0] == -1.f;
+
+ // If using the old channel scaling method, get medians from the whole current image,
+ // reading values from the already-scaled rawData buffer.
+ if (oldChannelScaling) {
+ calcMedians(ri, rawData, 0, 0, W, H, medians);
+ } else {
+ // Cut 20% border from medians calculation. It will probably contain outlier values
+ // from the film holder, which will bias the median result.
+ const int bW = W * 20 / 100;
+ const int bH = H * 20 / 100;
+ calcMedians(ri, rawData, bW, bH, W - bW, H - bH, medians);
+ }
+
+ // Un-scale rawData medians
+ for (int c = 0; c < 3; ++c) {
+ medians[c] /= scale_mul[c];
+ }
+
+ if (settings->verbose) {
+ printf("Channel medians: R=%g, G=%g, B=%g\n", medians[0], medians[1], medians[2]);
+ }
+
+ for (int c = 0; c < 3; ++c) {
+
+ // Estimate film base values, so that in the output data, each channel
+ // median will correspond to 1/24th of MAX.
+ filmBaseValues[c] = pow_F(24.f / 512.f, 1.f / exps[c]) * medians[c];
+
+ if (oldChannelScaling) {
+ // If using the old channel scaling method, apply WB multipliers here to undo their
+ // effect later, since fixed wb compensation was not used in previous version.
+ // Also, undo the effect of the autoGainComp factor (see below).
+ filmBaseValues[c] /= pow_F((wb_mul[c] / autoGainComp), 1.f / exps[c]);// / autoGainComp;
+ }
- for (int c = 0; c < 3; ++c) {
- // Find median values for each channel
- if (!cvs[c].empty()) {
- findMinMaxPercentile(cvs[c].data(), cvs[c].size(), 0.5f, medians[c], 0.5f, medians[c], true);
- medians[c] = pow_F(rtengine::max(medians[c], 1.f), exps[c]);
- // Determine the channel multiplier so that N times the median becomes 65k. This clips away
- // the values in the dark border surrounding the negative (due to the film holder, for example),
- // the reciprocal of which have blown up to stellar values.
- mults[c] = MAX_OUT_VALUE / (medians[c] * 24.f);
}
}
- t3.set();
+
+ // Calculate multipliers based on previously obtained film base input values.
+
+ // Apply current scaling coefficients to raw, unscaled base values.
+ std::array fb = {
+ filmBaseValues[0] * scale_mul[0],
+ filmBaseValues[1] * scale_mul[1],
+ filmBaseValues[2] * scale_mul[2]
+ };
if (settings->verbose) {
- printf("Sample count: %zu, %zu, %zu\n", cvs[0].size(), cvs[1].size(), cvs[2].size());
- printf("Medians: %g %g %g\n", static_cast(medians[0]), static_cast(medians[1]), static_cast(medians[2]));
- printf("Computed multipliers: %g %g %g\n", static_cast(mults[0]), static_cast(mults[1]), static_cast(mults[2]));
- printf("Median calc time us: %d\n", t3.etime(t2));
+ printf("Input film base values: %g %g %g\n", fb[0], fb[1], fb[2]);
}
+ for (int c = 0; c < 3; ++c) {
+ // Apply channel exponents, to obtain the corresponding base values in the output data
+ fb[c] = pow_F(rtengine::max(fb[c], 1.f), exps[c]);
+
+ // Determine the channel multiplier so that the film base value is 1/512th of max.
+ mults[c] = (MAX_OUT_VALUE / 512.f) / fb[c];
+
+ // Un-apply the fixed WB multipliers, to reverse their effect later in the WB tool.
+ // This way, the output image will be adapted to this fixed WB setting
+ mults[c] /= wb_mul[c];
+
+ // Also compensate for the initialGain difference between the default scaling (forceAutoWB=true)
+ // and the non-autoWB scaling (see camInitialGain).
+ // This effectively restores camera scaling multipliers, and gives us stable multipliers
+ // (not depending on image content).
+ mults[c] *= autoGainComp;
+
+ }
+
+ if (settings->verbose) {
+ printf("Output film base values: %g %g %g\n", static_cast(fb[0]), static_cast(fb[1]), static_cast(fb[2]));
+ printf("Computed multipliers: %g %g %g\n", static_cast(mults[0]), static_cast(mults[1]), static_cast(mults[2]));
+ }
+
+
constexpr float CLIP_VAL = 65535.f;
- t3.set();
+ MyTime t1, t2, t3;
+
+ t1.set();
if (ri->getSensorType() == ST_BAYER) {
#ifdef __SSE2__
@@ -264,6 +428,7 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16)
#endif
+
for (int row = 0; row < H; ++row) {
int col = 0;
// Avoid trouble with zeroes, minimum pixel value is 1.
@@ -274,14 +439,18 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ
#ifdef __SSE2__
const vfloat expsv = _mm_setr_ps(exps0, exps1, exps0, exps1);
const vfloat multsv = _mm_setr_ps(mult0, mult1, mult0, mult1);
+
for (; col < W - 3; col += 4) {
STVFU(rawData[row][col], vminf(multsv * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv), clipv));
}
+
#endif // __SSE2__
+
for (; col < W - 1; col += 2) {
rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), CLIP_VAL);
rawData[row][col + 1] = rtengine::min(mult1 * pow_F(rtengine::max(rawData[row][col + 1], 1.f), exps1), CLIP_VAL);
}
+
if (col < W) {
rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), CLIP_VAL);
}
@@ -295,6 +464,7 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16)
#endif
+
for (int row = 0; row < H; row ++) {
int col = 0;
// Avoid trouble with zeroes, minimum pixel value is 1.
@@ -321,30 +491,34 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ
const vfloat multsv0 = _mm_setr_ps(multsc[0], multsc[1], multsc[2], multsc[3]);
const vfloat multsv1 = _mm_setr_ps(multsc[4], multsc[5], multsc[0], multsc[1]);
const vfloat multsv2 = _mm_setr_ps(multsc[2], multsc[3], multsc[4], multsc[5]);
+
for (; col < W - 11; col += 12) {
STVFU(rawData[row][col], vminf(multsv0 * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0), clipv));
STVFU(rawData[row][col + 4], vminf(multsv1 * pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1), clipv));
STVFU(rawData[row][col + 8], vminf(multsv2 * pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2), clipv));
}
+
#endif // __SSE2__
+
for (; col < W - 5; col += 6) {
for (int c = 0; c < 6; ++c) {
rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), CLIP_VAL);
}
}
+
for (int c = 0; col < W; col++, c++) {
rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), CLIP_VAL);
}
}
}
- t4.set();
+ t2.set();
if (settings->verbose) {
- printf("Pow loop time us: %d\n", t4.etime(t3));
+ printf("Pow loop time us: %d\n", t2.etime(t1));
}
- t4.set();
+ t2.set();
PixelsMap bitmapBads(W, H);
@@ -354,6 +528,7 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ
#ifdef _OPENMP
#pragma omp parallel for reduction(+:totBP) schedule(dynamic,16)
#endif
+
for (int i = 0; i < H; ++i) {
for (int j = 0; j < W; ++j) {
if (rawData[i][j] >= MAX_OUT_VALUE) {
@@ -367,11 +542,11 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ
interpolateBadPixelsBayer(bitmapBads, rawData);
}
- }
- else if (ri->getSensorType() == ST_FUJI_XTRANS) {
+ } else if (ri->getSensorType() == ST_FUJI_XTRANS) {
#ifdef _OPENMP
#pragma omp parallel for reduction(+:totBP) schedule(dynamic,16)
#endif
+
for (int i = 0; i < H; ++i) {
for (int j = 0; j < W; ++j) {
if (rawData[i][j] >= MAX_OUT_VALUE) {
@@ -386,10 +561,10 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ
}
}
- t5.set();
+ t3.set();
if (settings->verbose) {
printf("Bad pixels count: %d\n", totBP);
- printf("Bad pixels interpolation time us: %d\n", t5.etime(t4));
+ printf("Bad pixels interpolation time us: %d\n", t3.etime(t2));
}
}
diff --git a/rtengine/filmnegativethumb.cc b/rtengine/filmnegativethumb.cc
index 003fab8e0..57f2601f9 100644
--- a/rtengine/filmnegativethumb.cc
+++ b/rtengine/filmnegativethumb.cc
@@ -18,6 +18,7 @@
*/
#include
+#include "colortemp.h"
#include "LUT.h"
#include "rtengine.h"
#include "rtthumbnail.h"
@@ -29,70 +30,179 @@
#define BENCHMARK
#include "StopWatch.h"
+namespace
+{
+
+using rtengine::Imagefloat;
+using rtengine::findMinMaxPercentile;
+
+
+void calcMedians(
+ const Imagefloat* baseImg,
+ const int x1, const int y1,
+ const int x2, const int y2,
+ float &rmed, float &gmed, float &bmed
+)
+{
+ // Channel vectors to calculate medians
+ std::vector rv, gv, bv;
+
+ const int sz = std::max(0, (y2 - y1) * (x2 - x1));
+ rv.reserve(sz);
+ gv.reserve(sz);
+ bv.reserve(sz);
+
+ for (int i = y1; i < y2; i++) {
+ for (int j = x1; j < x2; j++) {
+ rv.push_back(baseImg->r(i, j));
+ gv.push_back(baseImg->g(i, j));
+ bv.push_back(baseImg->b(i, j));
+ }
+ }
+
+ // Calculate channel medians from whole image
+ findMinMaxPercentile(rv.data(), rv.size(), 0.5f, rmed, 0.5f, rmed, true);
+ findMinMaxPercentile(gv.data(), gv.size(), 0.5f, gmed, 0.5f, gmed, true);
+ findMinMaxPercentile(bv.data(), bv.size(), 0.5f, bmed, 0.5f, bmed, true);
+}
+
+}
+
void rtengine::Thumbnail::processFilmNegative(
const procparams::ProcParams ¶ms,
const Imagefloat* baseImg,
- const int rwidth, const int rheight,
- float &rmi, float &gmi, float &bmi
-) {
+ const int rwidth, const int rheight
+)
+{
// Channel exponents
const float rexp = -params.filmNegative.redRatio * params.filmNegative.greenExp;
const float gexp = -params.filmNegative.greenExp;
const float bexp = -params.filmNegative.blueRatio * params.filmNegative.greenExp;
- // Need to calculate channel averages, to fake the same conditions
- // found in rawimagesource, where get_ColorsCoeff is called with
- // forceAutoWB=true.
- float rsum = 0.f, gsum = 0.f, bsum = 0.f;
-
- // Channel vectors to calculate medians
- std::vector rv, gv, bv;
-
- for (int i = 0; i < rheight; i++) {
- for (int j = 0; j < rwidth; j++) {
- const float r = baseImg->r(i, j);
- const float g = baseImg->g(i, j);
- const float b = baseImg->b(i, j);
-
- rsum += r;
- gsum += g;
- bsum += b;
-
- rv.push_back(r);
- gv.push_back(g);
- bv.push_back(b);
- }
- }
-
- const float ravg = rsum / (rheight*rwidth);
- const float gavg = gsum / (rheight*rwidth);
- const float bavg = bsum / (rheight*rwidth);
-
- // Shifting current WB multipliers, based on channel averages.
- rmi /= (gavg/ravg);
- // gmi /= (gAvg/gAvg); green chosen as reference channel
- bmi /= (gavg/bavg);
-
- float rmed, gmed, bmed;
- findMinMaxPercentile(rv.data(), rv.size(), 0.5f, rmed, 0.5f, rmed, true);
- findMinMaxPercentile(gv.data(), gv.size(), 0.5f, gmed, 0.5f, gmed, true);
- findMinMaxPercentile(bv.data(), bv.size(), 0.5f, bmed, 0.5f, bmed, true);
-
- rmed = powf(rmed, rexp);
- gmed = powf(gmed, gexp);
- bmed = powf(bmed, bexp);
+ // Calculate output multipliers
+ float rmult, gmult, bmult;
const float MAX_OUT_VALUE = 65000.f;
- const float rmult = (MAX_OUT_VALUE / (rmed * 24)) ;
- const float gmult = (MAX_OUT_VALUE / (gmed * 24)) ;
- const float bmult = (MAX_OUT_VALUE / (bmed * 24)) ;
+
+ // For backwards compatibility with profiles saved by RT 5.7
+ const bool oldChannelScaling = params.filmNegative.redBase == -1.f;
+
+ // If the film base values are not set in params, estimate multipliers from each channel's median value.
+ if (params.filmNegative.redBase <= 0.f) {
+
+ // Channel medians
+ float rmed, gmed, bmed;
+
+ if (oldChannelScaling) {
+ // If using the old method, calculate nedians on the whole image
+ calcMedians(baseImg, 0, 0, rwidth, rheight, rmed, gmed, bmed);
+ } else {
+ // The new method cuts out a 20% border from medians calculation.
+ const int bW = rwidth * 20 / 100;
+ const int bH = rheight * 20 / 100;
+ calcMedians(baseImg, bW, bH, rwidth - bW, rheight - bH, rmed, gmed, bmed);
+ }
+
+ if (settings->verbose) {
+ printf("Thumbnail input channel medians: %g %g %g\n", rmed, gmed, bmed);
+ }
+
+ // Calculate output medians
+ rmed = powf(rmed, rexp);
+ gmed = powf(gmed, gexp);
+ bmed = powf(bmed, bexp);
+
+ // Calculate output multipliers so that the median value is 1/24 of the output range.
+ rmult = (MAX_OUT_VALUE / 24.f) / rmed;
+ gmult = (MAX_OUT_VALUE / 24.f) / gmed;
+ bmult = (MAX_OUT_VALUE / 24.f) / bmed;
+
+ } else {
+
+ // Read film-base values from params
+ float rbase = params.filmNegative.redBase;
+ float gbase = params.filmNegative.greenBase;
+ float bbase = params.filmNegative.blueBase;
+
+ // Reconstruct scale_mul coefficients from thumbnail metadata:
+ // redMultiplier / camwbRed is pre_mul[0]
+ // pre_mul[0] * scaleGain is scale_mul[0]
+ // Apply channel scaling to raw (unscaled) input base values, to
+ // match with actual (scaled) data in baseImg
+ rbase *= (redMultiplier / camwbRed) * scaleGain;
+ gbase *= (greenMultiplier / camwbGreen) * scaleGain;
+ bbase *= (blueMultiplier / camwbBlue) * scaleGain;
+
+ if (settings->verbose) {
+ printf("Thumbnail input film base values: %g %g %g\n", rbase, gbase, bbase);
+ }
+
+ // Apply exponents to get output film base values
+ rbase = powf(rbase, rexp);
+ gbase = powf(gbase, gexp);
+ bbase = powf(bbase, bexp);
+
+ if (settings->verbose) {
+ printf("Thumbnail output film base values: %g %g %g\n", rbase, gbase, bbase);
+ }
+
+ // Calculate multipliers so that film base value is 1/512th of the output range.
+ rmult = (MAX_OUT_VALUE / 512.f) / rbase;
+ gmult = (MAX_OUT_VALUE / 512.f) / gbase;
+ bmult = (MAX_OUT_VALUE / 512.f) / bbase;
+
+ }
+
+
+ if (oldChannelScaling) {
+ // Need to calculate channel averages, to fake the same conditions
+ // found in rawimagesource, where get_ColorsCoeff is called with
+ // forceAutoWB=true.
+ float rsum = 0.f, gsum = 0.f, bsum = 0.f;
+
+ for (int i = 0; i < rheight; i++) {
+ for (int j = 0; j < rwidth; j++) {
+ rsum += baseImg->r(i, j);
+ gsum += baseImg->g(i, j);
+ bsum += baseImg->b(i, j);
+ }
+ }
+
+ const float ravg = rsum / (rheight * rwidth);
+ const float gavg = gsum / (rheight * rwidth);
+ const float bavg = bsum / (rheight * rwidth);
+
+ // Shifting current WB multipliers, based on channel averages.
+ rmult /= gavg / ravg;
+ // gmult /= gAvg / gAvg; green chosen as reference channel
+ bmult /= gavg / bavg;
+
+ } else {
+
+ // Get and un-apply multipliers to adapt the thumbnail to a known fixed WB setting,
+ // as in the main image processing.
+
+ double r, g, b;
+ ColorTemp(3500., 1., 1., "Custom").getMultipliers(r, g, b);
+ //iColorMatrix is cam_rgb
+ const double rm = camwbRed / (iColorMatrix[0][0] * r + iColorMatrix[0][1] * g + iColorMatrix[0][2] * b);
+ const double gm = camwbGreen / (iColorMatrix[1][0] * r + iColorMatrix[1][1] * g + iColorMatrix[1][2] * b);
+ const double bm = camwbBlue / (iColorMatrix[2][0] * r + iColorMatrix[2][1] * g + iColorMatrix[2][2] * b);
+
+ // Normalize max WB multiplier to 1.f
+ const double m = max(rm, gm, bm);
+ rmult /= rm / m;
+ gmult /= gm / m;
+ bmult /= bm / m;
+ }
+
if (settings->verbose) {
- printf("Thumbnail channel medians: %g %g %g\n", static_cast(rmed), static_cast(gmed), static_cast(bmed));
printf("Thumbnail computed multipliers: %g %g %g\n", static_cast(rmult), static_cast(gmult), static_cast(bmult));
}
+
#ifdef __SSE2__
const vfloat clipv = F2V(MAXVALF);
const vfloat rexpv = F2V(rexp);
@@ -109,12 +219,15 @@ void rtengine::Thumbnail::processFilmNegative(
float *bline = baseImg->b(i);
int j = 0;
#ifdef __SSE2__
- for (; j < rwidth - 3; j +=4) {
+
+ for (; j < rwidth - 3; j += 4) {
STVFU(rline[j], vminf(rmultv * pow_F(LVFU(rline[j]), rexpv), clipv));
STVFU(gline[j], vminf(gmultv * pow_F(LVFU(gline[j]), gexpv), clipv));
STVFU(bline[j], vminf(bmultv * pow_F(LVFU(bline[j]), bexpv), clipv));
}
+
#endif
+
for (; j < rwidth; ++j) {
rline[j] = CLIP(rmult * pow_F(rline[j], rexp));
gline[j] = CLIP(gmult * pow_F(gline[j], gexp));
diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc
index 9d7024bff..6b2be1713 100644
--- a/rtengine/iccstore.cc
+++ b/rtengine/iccstore.cc
@@ -635,7 +635,7 @@ public:
MyMutex::MyLock lock(mutex);
- for (const auto profile : fileProfiles) {
+ for (const auto& profile : fileProfiles) {
if (
(
type == ICCStore::ProfileType::MONITOR
diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h
index d1008837d..ea049d37c 100644
--- a/rtengine/imagesource.h
+++ b/rtengine/imagesource.h
@@ -92,8 +92,9 @@ public:
~ImageSource () override {}
virtual int load (const Glib::ustring &fname) = 0;
virtual void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) {};
- virtual void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) {};
+ virtual void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms, std::array& filmBaseValues) {};
virtual bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const procparams::FilmNegativeParams& currentParams, std::array& newExps) { return false; };
+ virtual bool getRawSpotValues (Coord2D spot, int spotSize, int tran, const procparams::FilmNegativeParams ¶ms, std::array& rawValues) { return false; };
virtual void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache = false) {};
virtual void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {};
virtual void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {};
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 15d477fdc..5261675a0 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -44,6 +44,22 @@
#include
#endif
+namespace
+{
+using rtengine::Coord2D;
+Coord2D translateCoord(const rtengine::ImProcFunctions& ipf, int fw, int fh, int x, int y) {
+
+ const std::vector points = {Coord2D(x, y)};
+
+ std::vector red;
+ std::vector green;
+ std::vector blue;
+ ipf.transCoord(fw, fh, points, red, green, blue);
+
+ return green[0];
+}
+
+}
namespace rtengine
{
@@ -300,7 +316,15 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
)
&& params->filmNegative.enabled
) {
- imgsrc->filmNegativeProcess(params->filmNegative);
+ std::array filmBaseValues = {
+ static_cast(params->filmNegative.redBase),
+ static_cast(params->filmNegative.greenBase),
+ static_cast(params->filmNegative.blueBase)
+ };
+ imgsrc->filmNegativeProcess(params->filmNegative, filmBaseValues);
+ if (filmNegListener && params->filmNegative.redBase <= 0.f) {
+ filmNegListener->filmBaseValuesChanged(filmBaseValues);
+ }
}
}
@@ -434,7 +458,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
currWB = imgsrc->getWB();
lastAwbauto = ""; //reinitialize auto
} else if (autowb) {
- if (lastAwbEqual != params->wb.equal || lastAwbTempBias != params->wb.tempBias || lastAwbauto != params->wb.method) {
+ if (params->wb.method == "autitcgreen" || lastAwbEqual != params->wb.equal || lastAwbTempBias != params->wb.tempBias || lastAwbauto != params->wb.method) {
double rm, gm, bm;
double tempitc = 5000.f;
double greenitc = 1.;
@@ -867,7 +891,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if ((params->wavelet.enabled)) {
WaveletParams WaveParams = params->wavelet;
- WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ WaveParams.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
int kall = 0;
LabImage *unshar = nullptr;
Glib::ustring provis;
@@ -896,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, 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);
@@ -910,7 +934,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
WaveParams.expnoise = false;
}
- ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
+ ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
@@ -922,10 +946,12 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
WaveParams.expnoise = pronois;
if (WaveParams.softrad > 0.f) {
+
array2D ble(pW, pH);
array2D guid(pW, pH);
Imagefloat *tmpImage = nullptr;
tmpImage = new Imagefloat(pW, pH);
+
#ifdef _OPENMP
#pragma omp parallel for
#endif
@@ -948,6 +974,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
tmpImage->b(ir, jr) = Z;
ble[ir][jr] = Y / 32768.f;
}
+
double epsilmax = 0.0001;
double epsilmin = 0.00001;
double aepsil = (epsilmax - epsilmin) / 90.f;
@@ -973,6 +1000,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
Color::XYZ2Lab(X, Y, Z, L, a, b);
nprevl->L[ir][jr] = L;
}
+
delete tmpImage;
}
@@ -1063,8 +1091,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
*/
if (WaveParams.softrad > 0.f) {
+
delete provradius;
provradius = NULL;
+
}
@@ -1158,7 +1188,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
if (params->colorappearance.enabled && params->colorappearance.presetcat02 && params->colorappearance.autotempout) {
- acListener->wbCamChanged(params->wb.temperature, params->wb.green); //real temp and tint
+ // acListener->wbCamChanged(params->wb.temperature, params->wb.green); //real temp and tint
+ acListener->wbCamChanged(params->wb.temperature, 1.f); //real temp and tint = 1.
}
} else {
@@ -1474,27 +1505,22 @@ bool ImProcCoordinator::getFilmNegativeExponents(int xA, int yA, int xB, int yB,
{
MyMutex::MyLock lock(mProcessing);
- const auto xlate =
- [this](int x, int y) -> Coord2D
- {
- const std::vector points = {Coord2D(x, y)};
-
- std::vector red;
- std::vector green;
- std::vector blue;
- ipf.transCoord(fw, fh, points, red, green, blue);
-
- return green[0];
- };
-
const int tr = getCoarseBitMask(params->coarse);
- const Coord2D p1 = xlate(xA, yA);
- const Coord2D p2 = xlate(xB, yB);
+ const Coord2D p1 = translateCoord(ipf, fw, fh, xA, yA);
+ const Coord2D p2 = translateCoord(ipf, fw, fh, xB, yB);
return imgsrc->getFilmNegativeExponents(p1, p2, tr, params->filmNegative, newExps);
}
+bool ImProcCoordinator::getRawSpotValues(int x, int y, int spotSize, std::array& rawValues)
+{
+ MyMutex::MyLock lock(mProcessing);
+
+ return imgsrc->getRawSpotValues(translateCoord(ipf, fw, fh, x, y), spotSize,
+ getCoarseBitMask(params->coarse), params->filmNegative, rawValues);
+}
+
void ImProcCoordinator::getAutoCrop(double ratio, int &x, int &y, int &w, int &h)
{
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index 454294beb..e4858c76b 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -139,7 +139,9 @@ protected:
NoiseCurve noiseLCurve;
NoiseCurve noiseCCurve;
WavCurve wavCLVCurve;
+ Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
+ WavOpacityCurveSH waOpacityCurveSH;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
WavOpacityCurveWL waOpacityCurveWL;
@@ -174,6 +176,7 @@ protected:
AutoRadiusListener *pdSharpenAutoRadiusListener;
FrameCountListener *frameCountListener;
ImageTypeListener *imageTypeListener;
+ FilmNegListener *filmNegListener;
AutoColorTonListener* actListener;
AutoChromaListener* adnListener;
@@ -280,6 +283,7 @@ public:
void getCamWB (double& temp, double& green) override;
void getSpotWB (int x, int y, int rectSize, double& temp, double& green) override;
bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array& newExps) override;
+ bool getRawSpotValues(int x, int y, int spotSize, std::array& rawValues) override;
void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) override;
bool getHighQualComputed() override;
void setHighQualComputed() override;
@@ -388,6 +392,11 @@ public:
imageTypeListener = itl;
}
+ void setFilmNegListener (FilmNegListener* fnl) override
+ {
+ filmNegListener = fnl;
+ }
+
void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) override;
InitialImage* getInitialImage () override
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index 9fe16769c..aa5515e79 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -1989,8 +1989,8 @@ void ImProcFunctions::moyeqt (Imagefloat* working, float &moyS, float &eqty)
{
BENCHFUN
- int tHh = working->getHeight();
- int tWw = working->getWidth();
+ const int height = working->getHeight();
+ const int width = working->getWidth();
double moy = 0.0;
double sqrs = 0.0;
@@ -1998,17 +1998,17 @@ void ImProcFunctions::moyeqt (Imagefloat* working, float &moyS, float &eqty)
#pragma omp parallel for reduction(+:moy,sqrs) schedule(dynamic,16)
#endif
- for (int i = 0; i < tHh; i++) {
- for (int j = 0; j < tWw; j++) {
- double s = Color::rgb2s (CLIP (working->r (i, j)), CLIP (working->g (i, j)), CLIP (working->b (i, j)));
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ const double s = Color::rgb2s(CLIP(working->r (i, j)), CLIP(working->g (i, j)), CLIP(working->b (i, j)));
moy += s;
sqrs += SQR(s);
}
}
- moy /= (tHh * tWw);
- sqrs /= (tHh * tWw);
- eqty = sqrt (sqrs - SQR (moy));
+ moy /= (height * width);
+ sqrs /= (height * width);
+ eqty = std::sqrt(std::max(sqrs - SQR(moy), 0.0));
moyS = moy;
}
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index a06670b72..b7d7c41e5 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -53,7 +53,9 @@ class OpacityCurve;
class PipetteBuffer;
class ToneCurve;
class WavCurve;
+class Wavblcurve;
class WavOpacityCurveBY;
+class WavOpacityCurveSH;
class WavOpacityCurveRG;
class WavOpacityCurveW;
class WavOpacityCurveWL;
@@ -200,32 +202,32 @@ 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 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,
- struct cont_params &cp, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili);
+ void 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, 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 WavOpacityCurveW & waOpacityCurveW,
- struct cont_params &cp, const bool useChannelA);
+ void WaveletcontAllAB(LabImage * lab, float **varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_a, const Wavblcurve & wavblcurve, const WavOpacityCurveW & waOpacityCurveW,
+ struct cont_params &cp, const bool useChannelA, int skip, 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);
void Aver(float * HH_Coeffs, int datalen, float &averagePlus, float &averageNeg, float &max, float &min);
void Sigma(float * HH_Coeffs, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg);
void calckoe(float ** WavCoeffs_LL, const cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr);
-
-
void Median_Denoise(float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr);
void 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);
@@ -233,18 +235,22 @@ public:
void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, const LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false);
void RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail); //for DCT
void RGBoutput_tile_row(float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top);
- bool WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge);
- bool WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
+
void WaveletDenoiseAll_info(int levwav, const wavelet_decomposition &WaveletCoeffs_a,
const wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb);
- bool WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]);
- bool WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab,
- const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
+ bool WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels);
+ bool WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels);
+
+ bool WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels);
+ bool WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels);
+
void ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge);
void ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
- float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * madaab = nullptr, bool madCalculated = false);
+ float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab = nullptr, bool madCalculated = false);
+
+
void ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b,
int W_ab, int H_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb);
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index 758a9147b..0fc947aea 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -17,7 +17,7 @@
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-// * 2014 - 2019 Jacques Desmis
+// * 2014 - 2019 2020 - Jacques Desmis
// * 2014 Ingo Weyrich
//
@@ -32,7 +32,10 @@
#include "EdgePreservingDecomposition.h"
#include "iccstore.h"
#include "improcfun.h"
+#include "imagefloat.h"
#include "labimage.h"
+#include "gauss.h"
+#include "boxblur.h"
#include "LUT.h"
#include "median.h"
#include "opthelper.h"
@@ -56,13 +59,18 @@ struct cont_params {
float sigm;
int chrom;
int chro;
+ float chrwav;
int contrast;
float th;
float thH;
float conres;
float conresH;
+ float blurres;
+ float blurcres;
+ float bluwav;
float radius;
float chrores;
+ bool oldsh;
float hueres;
float sky;
float b_l, t_l, b_r, t_r;
@@ -74,6 +82,7 @@ struct cont_params {
float b_lpast, t_lpast, b_rpast, t_rpast;
float b_lsat, t_lsat, b_rsat, t_rsat;
int rad;
+ float eff;
int val;
int til;
int numlevH, numlevS;
@@ -104,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;
@@ -123,17 +136,35 @@ struct cont_params {
bool finena;
bool toningena;
bool noiseena;
+ bool blena;
int maxilev;
float edgsens;
float edgampl;
int neigh;
bool lipp;
+ float ballum;
+ 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 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)
{
@@ -177,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;
@@ -186,6 +221,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (params->wavelet.BAmethod != "none") {
cp.bam = true;
+
if (params->wavelet.BAmethod == "sli") {
cp.BAmet = 1;
} else if (params->wavelet.BAmethod == "cur") {
@@ -203,6 +239,8 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.finena = params->wavelet.expfinal;
cp.toningena = params->wavelet.exptoning;
cp.noiseena = params->wavelet.expnoise;
+ cp.blena = params->wavelet.expbl;
+ cp.chrwav = 0.01f * params->wavelet.chrwav;
if (params->wavelet.Backmethod == "black") {
cp.backm = 0;
@@ -248,7 +286,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
DaubLen = 8;
} else if (params->wavelet.daubcoeffmethod == "10_") {
DaubLen = 12;
- } else /* if (params->wavelet.daubcoeffmethod == "14_") */{
+ } else { /* if (params->wavelet.daubcoeffmethod == "14_") */
DaubLen = 16;
}
@@ -293,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;
}
@@ -359,7 +411,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
-// if(settings->verbose) printf("Wav mul 0=%f 1=%f 2=%f 3=%f 4=%f 5=%f 6=%f 7=%f 8=%f 9=%f\n",cp.mul[0],cp.mul[1],cp.mul[2],cp.mul[3],cp.mul[4],cp.mul[5],cp.mul[6],cp.mul[7],cp.mul[8],cp.mul[9]);
for (int sc = 0; sc < 9; sc++) { //reduce strength if zoom < 100% for chroma and tuning
if (sc == 0) {
if (scaleskip[sc] < 1.f) {
@@ -382,11 +433,20 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.rad = waparams.edgrad;
cp.val = waparams.edgval;
cp.til = waparams.edgthresh;
+ cp.eff = waparams.edgeffect;
+ cp.balchrom = waparams.balchrom;
+ cp.chromfi = 0.1f * waparams.chromfi;
+ cp.chromco = 0.1f * waparams.chromco;
+ cp.ballum = waparams.ballum;
cp.conres = waparams.rescon;
cp.conresH = waparams.resconH;
cp.radius = waparams.radius;
cp.chrores = waparams.reschro;
+ cp.oldsh = waparams.oldsh;
+ cp.blurres = waparams.resblur;
+ cp.blurcres = waparams.resblurc;
+ cp.bluwav = waparams.bluwav;
//cp.hueres=waparams.reshue;
cp.hueres = 2.f;
cp.th = float(waparams.thr);
@@ -409,16 +469,14 @@ 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);
- //printf("levHigh=%d levShad=%d\n",cp.numlevH,cp.numlevS);
+ 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());
cp.b_rhl = static_cast(params->wavelet.hllev.getBottomRight());
cp.t_rhl = static_cast(params->wavelet.hllev.getTopRight());
- //printf("BL=%f TL=%f BR=%f TR=%f\n",cp.b_lhl,cp.t_lhl,cp.b_rhl,cp.t_rhl);
//pastel
cp.b_lpast = static_cast(params->wavelet.pastlev.getBottomLeft());
cp.t_lpast = static_cast(params->wavelet.pastlev.getTopLeft());
@@ -445,7 +503,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.lev3n = static_cast(params->wavelet.level3noise.getTop());
cp.detectedge = params->wavelet.medianlev;
- //printf("low=%f mean=%f sd=%f max=%f\n",cp.edg_low,cp.edg_mean,cp.edg_sd,cp.edg_max);
int minwin = rtengine::min(imwidth, imheight);
int maxlevelcrop = 9;
@@ -474,7 +531,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
maxlevelcrop = 5;
}
- // printf("minwin=%d maxcrop=%d\n",minwin, maxlevelcrop);
int levwav = params->wavelet.thres;
@@ -484,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
@@ -504,10 +555,11 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
realtile = 22;
}
- if (params->wavelet.Tilesmethod == "lit") {
- realtile = 12;
- }
-
+ /*
+ if (params->wavelet.Tilesmethod == "lit") {
+ realtile = 12;
+ }
+ */
int tilesize = 128 * realtile;
int overlap = (int) tilesize * 0.125f;
int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip;
@@ -554,7 +606,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
levwav = rtengine::min(maxlev2, levwav);
- //printf("levwav = %d\n",levwav);
#ifdef _OPENMP
int numthreads = 1;
int maxnumberofthreadsforwavelet = 0;
@@ -581,7 +632,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
maxnumberofthreadsforwavelet = 8;
}
- //printf("maxNRT=%d\n",maxnumberofthreadsforwavelet);
if ((maxnumberofthreadsforwavelet == 6 || maxnumberofthreadsforwavelet == 8) && levwav == 10) {
maxnumberofthreadsforwavelet -= 2;
}
@@ -591,7 +641,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
- //printf("maxthre=%d\n",maxnumberofthreadsforwavelet);
// Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles
@@ -636,6 +685,13 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
float MaxP[10];
float MaxN[10];
+ float meanab[10];
+ float meanNab[10];
+ float sigmaab[10];
+ float sigmaNab[10];
+ float MaxPab[10];
+ float MaxNab[10];
+
array2D varchro(tilewidth, tileheight);
float** varhue = new float*[tileheight];
@@ -644,6 +700,8 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
varhue[i] = new float[tilewidth];
}
+
+
#ifdef _OPENMP
#pragma omp for schedule(dynamic) collapse(2)
#endif
@@ -677,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++) {
@@ -736,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++) {
@@ -796,27 +854,58 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
ref0 = true;
}
- if (cp.contrast == 0.f && !cp.tonemap && cp.conres == 0.f && cp.conresH == 0.f && cp.val == 0 && !ref0 && params->wavelet.CLmethod == "all") { // no processing of residual L or edge=> we probably can reduce the number of levels
+ bool wavcurvecomp = false;//not enable if 0.75
+
+ if (wavblcurve) {
+ for (int i = 0; i < 500; i++) {
+ if (wavblcurve[i] != 0.) {
+ wavcurvecomp = true;
+ }
+ }
+ }
+
+ bool exblurL = cp.blena && wavcurvecomp;
+
+ if (exblurL) {
+ if (cp.mul[0] == 0.f) {
+ cp.mul[0] = 0.01f;//to always enable WaveletcontAllL if no contrast is nead
+ }
+ }
+
+ if (!exblurL && cp.contrast == 0.f && cp.blurres == 0.f && !cp.tonemap && cp.conres == 0.f && cp.conresH == 0.f && cp.val == 0 && !ref0 && params->wavelet.CLmethod == "all") { // no processing of residual L or edge=> we probably can reduce the number of levels
while (levwavL > 0 && cp.mul[levwavL - 1] == 0.f) { // cp.mul[level] == 0.f means no changes to level
levwavL--;
}
}
+ if (cp.chromfi > 0.f || cp.chromco > 0.f) {
+ if (levwavL < 7) {
+ levwavL = 7;
+ }
+ }
+
if (levwavL < 4) {
levwavL = 4; //to allow edge => I always allocate 3 (4) levels..because if user select wavelet it is to do something !!
}
+ if (settings->verbose) {
+ printf("Level decomp L=%i\n", levwavL);
+ }
+
+ bool usechrom = cp.chromfi > 0.f || cp.chromco > 0.f;
+
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));
if (!Ldecomp->memoryAllocationFailed) {
+ float madL[10][3];
- float madL[8][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 < 4; lvl++) {
+ for (int lvl = 0; lvl < levwavL; lvl++) {
for (int dir = 1; dir < 4; dir++) {
int Wlvl_L = Ldecomp->level_W(lvl);
int Hlvl_L = Ldecomp->level_H(lvl);
@@ -824,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);
+ }
}
}
@@ -848,20 +941,73 @@ 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) {
+ kr3 = 0.f;
+ } else if (cp.lev3n < 30.f) {
+ kr3 = 0.5f;
+ } else if (cp.lev3n < 70.f) {
+ kr3 = 0.7f;
+ } else {
+ kr3 = 1.f;
+ }
if ((cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f) && cp.noiseena) {
int edge = 1;
- 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, vari[3]);
- float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL
+ 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]);
- WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge);
+ 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;
+ float* noisevarlum = new float[GHL * GWL];
+ int GW2L = (GWL + 1) / 2;
+
+ float nvlh[13] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.7f, 0.5f}; //high value
+ float nvll[13] = {0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.7f, 0.8f, 1.f, 1.f, 1.f}; //low value
+
+ float seuillow = 3000.f;//low
+ float seuilhigh = 18000.f;//high
+ int i = 10 - cp.ballum;
+ float ac = (nvlh[i] - nvll[i]) / (seuillow - seuilhigh);
+ float bc = nvlh[i] - seuillow * ac;
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+
+#endif
+
+ for (int ir = 0; ir < GHL; ir++)
+ for (int jr = 0; jr < GWL; jr++) {
+ float lN = labco->L[ir][jr];
+
+ if (lN < seuillow) {
+ noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = nvlh[i];
+ } else if (lN < seuilhigh) {
+ noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = ac * lN + bc;
+ } else {
+ noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = nvll[i];
+ }
+ }
+
+ if (cp.lev3n < 20.f) {
+ WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+ } else {
+ WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+
+ WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+ }
}
//Flat curve for Contrast=f(H) in levels
@@ -877,101 +1023,382 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
Chutili = true;
}
-
- WaveletcontAllL(labco, varhue, varchro, *Ldecomp, cp, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili);
+ WaveletcontAllL(labco, varhue, varchro, *Ldecomp, wavblcurve, cp, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, waOpacityCurveSH, ChCurve, Chutili);
if (cp.val > 0 || ref || contr || cp.diagcurv) { //edge
Evaluate2(*Ldecomp, mean, meanN, sigma, sigmaN, MaxP, MaxN);
}
WaveletcontAllLfinal(*Ldecomp, cp, mean, sigma, MaxP, waOpacityCurveWL);
+
//Evaluate2(*Ldecomp, cp, ind, mean, meanN, sigma, sigmaN, MaxP, MaxN, madL);
+ /*
+ Ldecomp->reconstruct(labco->data, cp.strength);
+ }
+ }
+ */
+ if (!usechrom) {
+ Ldecomp->reconstruct(labco->data, cp.strength);
+ }
- Ldecomp->reconstruct(labco->data, cp.strength);
- }
- }
+ float variC[7];
+ float variCb[7];
- //Flat curve for H=f(H) in residual image
- FlatCurve* hhCurve = new FlatCurve(params->wavelet.hhcurve); //curve H=f(H)
- bool hhutili = false;
+ float noisecfr = cp.chromfi;
+ float noiseccr = cp.chromco;
- if (!hhCurve || hhCurve->isIdentity()) {
- if (hhCurve) {
- delete hhCurve;
- hhCurve = nullptr;
- }
- } else {
- hhutili = true;
- }
+ if (cp.balchrom > 0.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 - 0.1f * cp.balchrom;
+ noiseccb = cp.chromco - 0.1f * cp.balchrom;
+ }
- if (!hhutili) { //always a or b
- int levwava = levwav;
+ if (noisecfr < 0.f) {
+ noisecfr = 0.00001f;
+ }
- // printf("Levwava before: %d\n",levwava);
- if (cp.chrores == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
- while (levwava > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwava - 1] == 0.f)) || (cp.CHmet != 2 && (levwava == 10 || (!cp.curv || cp.mulC[levwava - 1] == 0.f))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava - 1] == 0.f)) && ((levwava == 10 || (cp.CHSLmet == 1 && cp.mulC[levwava - 1] == 0.f)))) {
- levwava--;
+ if (noiseccr < 0.f) {
+ noiseccr = 0.00001f;
+ }
+
+ if (noisecfb < 0.f) {
+ noisecfb = 0.00001f;
+ }
+
+ if (noiseccb < 0.f) {
+ noiseccb = 0.0001f;
+ }
+
+ int edge = 2;
+ variC[0] = SQR(noisecfr);
+ variC[1] = SQR(noisecfr);
+ variC[2] = SQR(noisecfr);
+
+ variC[3] = SQR(noisecfr);
+ variC[4] = SQR(noisecfr);
+ variC[5] = SQR(noiseccr);
+ variC[6] = SQR(noiseccr);
+
+ variCb[0] = SQR(noisecfb);
+ variCb[1] = SQR(noisecfb);
+ variCb[2] = SQR(noisecfb);
+
+ variCb[3] = SQR(noisecfb);
+ variCb[4] = SQR(noisecfb);
+ variCb[5] = SQR(noiseccb);
+ variCb[6] = SQR(noiseccb);
+
+ float k1 = 0.f;
+ float k2 = 0.f;
+ float k3 = 0.f;
+
+ if (cp.chromfi < 0.2f) {
+ k1 = 0.05f;
+ k2 = 0.f;
+ k3 = 0.f;
+ } else if (cp.chromfi < 0.3f) {
+ k1 = 0.1f;
+ k2 = 0.0f;
+ k3 = 0.f;
+ } else if (cp.chromfi < 0.5f) {
+ k1 = 0.2f;
+ k2 = 0.1f;
+ k3 = 0.f;
+ } else if (cp.chromfi < 0.8f) {
+ k1 = 0.3f;
+ k2 = 0.25f;
+ k3 = 0.f;
+ } else if (cp.chromfi < 1.f) {
+ k1 = 0.4f;
+ k2 = 0.25f;
+ k3 = 0.1f;
+ } else if (cp.chromfi < 2.f) {
+ k1 = 0.5f;
+ k2 = 0.3f;
+ k3 = 0.15f;
+ } else if (cp.chromfi < 3.f) {
+ k1 = 0.6f;
+ k2 = 0.45f;
+ k3 = 0.3f;
+ } else if (cp.chromfi < 4.f) {
+ k1 = 0.7f;
+ k2 = 0.5f;
+ k3 = 0.4f;
+ } else if (cp.chromfi < 5.f) {
+ k1 = 0.8f;
+ k2 = 0.6f;
+ k3 = 0.5f;
+ } else if (cp.chromfi < 6.f) {
+ k1 = 0.85f;
+ k2 = 0.7f;
+ k3 = 0.6f;
+ } else if (cp.chromfi < 8.f) {
+ k1 = 0.9f;
+ k2 = 0.8f;
+ k3 = 0.7f;
+ } else if (cp.chromfi < 10.f) {
+ k1 = 1.f;
+ k2 = 1.f;
+ k3 = 0.9f;
+
+ } else {
+ k1 = 1.f;
+ k2 = 1.f;
+ k3 = 1.f;
+ }
+
+ float minic = 0.000001f;
+ variC[0] = max(minic, variC[0]);
+ variC[1] = max(minic, k1 * variC[1]);
+ variC[2] = max(minic, k2 * variC[2]);
+ variC[3] = max(minic, k3 * variC[3]);
+
+ variCb[0] = max(minic, variCb[0]);
+ variCb[1] = max(minic, k1 * variCb[1]);
+ variCb[2] = max(minic, k2 * variCb[2]);
+ variCb[3] = max(minic, k3 * variCb[3]);
+
+ float k4 = 0.f;
+ float k5 = 0.f;
+ float k6 = 0.f;
+
+ if (cp.chromco < 0.2f) {
+ k4 = 0.1f;
+ k5 = 0.02f;
+ } else if (cp.chromco < 0.5f) {
+ k4 = 0.15f;
+ k5 = 0.05f;
+ } else if (cp.chromco < 1.f) {
+ k4 = 0.15f;
+ k5 = 0.1f;
+ } else if (cp.chromco < 3.f) {
+ k4 = 0.3f;
+ k5 = 0.15f;
+ } else if (cp.chromco < 4.f) {
+ k4 = 0.6f;
+ k5 = 0.4f;
+ } else if (cp.chromco < 6.f) {
+ k4 = 0.8f;
+ k5 = 0.6f;
+ } else {
+ k4 = 1.f;
+ k5 = 1.f;
+ }
+
+ variC[4] = max(0.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;
+ } else if (cp.chromco < 5.f) {
+ k6 = 0.4f;
+ } else if (cp.chromco < 6.f) {
+ k6 = 0.7f;
+ } else {
+ k6 = 1.f;
+ }
+
+ variC[6] = max(0.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]);
+ }
+ */
+ float nvch = 0.6f;//high value
+ float nvcl = 0.1f;//low value
+
+ if (cp.chromco > 30.f) {
+ nvch = 0.8f;
+ nvcl = 0.4f;
+ }
+
+ float seuil = 4000.f;//low
+ float seuil2 = 15000.f;//high
+ //ac and bc for transition
+ float ac = (nvch - nvcl) / (seuil - seuil2);
+ float bc = nvch - seuil * ac;
+ int GW = labco->W;
+ int GH = labco->H;
+ float* noisevarchrom = new float[GH * GW];
+ //noisevarchrom in function chroma
+ int GW2 = (GW + 1) / 2;
+ float noisevarab_r = 100.f;
+
+ for (int ir = 0; ir < GH; ir++)
+ for (int jr = 0; jr < GW; jr++) {
+ float cN = sqrt(SQR(labco->a[ir][jr]) + SQR(labco->b[ir][jr]));
+
+ if (cN < seuil) {
+ noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = nvch;
+ } else if (cN < seuil2) {
+ noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = ac * cN + bc;
+ } else {
+ noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = nvcl;
+ }
+ }
+
+
+ //Flat curve for H=f(H) in residual image
+ FlatCurve* hhCurve = new FlatCurve(params->wavelet.hhcurve); //curve H=f(H)
+ bool hhutili = false;
+
+ if (!hhCurve || hhCurve->isIdentity()) {
+ if (hhCurve) {
+ delete hhCurve;
+ hhCurve = nullptr;
+ }
+ } else {
+ hhutili = true;
+ }
+
+ bool exblurab = cp.chrwav > 0.f && exblurL;
+
+ if (!hhutili) { //always a or b
+ int levwava = levwav;
+
+ if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
+ while (levwava > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwava - 1] == 0.f)) || (cp.CHmet != 2 && (levwava == 10 || (!cp.curv || cp.mulC[levwava - 1] == 0.f))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava - 1] == 0.f)) && ((levwava == 10 || (cp.CHSLmet == 1 && cp.mulC[levwava - 1] == 0.f)))) {
+ levwava--;
+ }
+ }
+
+ if (cp.chromfi > 0.f || cp.chromco > 0.f) {
+ if (levwava < 7) {
+ levwava = 7;
+ }
+ }
+
+ if (settings->verbose) {
+ printf("Leval decomp a=%i\n", levwava);
+ }
+
+ if (levwava > 0) {
+ const std::unique_ptr adecomp(new wavelet_decomposition(labco->data + datalen, labco->W, labco->H, levwava, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+
+ if (!adecomp->memoryAllocationFailed) {
+ 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);
+ adecomp->reconstruct(labco->data + datalen, cp.strength);
+ }
+ }
+
+ int levwavb = levwav;
+
+ if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
+ while (levwavb > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavb - 1] == 0.f)) || (cp.CHmet != 2 && (levwavb == 10 || (!cp.curv || cp.mulC[levwavb - 1] == 0.f))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb - 1] == 0.f)) && ((levwavb == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavb - 1] == 0.f)))) {
+ levwavb--;
+ }
+ }
+
+ if (cp.chromfi > 0.f || cp.chromco > 0.f) {
+ if (levwavb < 7) {
+ levwavb = 7;
+ }
+ }
+
+ if (settings->verbose) {
+ printf("Leval decomp b=%i\n", levwavb);
+ }
+
+
+ if (levwavb > 0) {
+ const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavb, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+
+ if (!bdecomp->memoryAllocationFailed) {
+ 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);
+ WaveletcontAllAB(labco, varhue, varchro, *bdecomp, wavblcurve, waOpacityCurveW, cp, false, skip, meanab, sigmaab);
+ bdecomp->reconstruct(labco->data + 2 * datalen, cp.strength);
+ }
+ }
+ } else {// a and b
+ int levwavab = levwav;
+
+ if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && !hhutili && params->wavelet.CLmethod == "all") { // no processing of residual ab => we probably can reduce the number of levels
+ while (levwavab > 0 && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavab - 1] == 0.f)) || (cp.CHmet != 2 && (levwavab == 10 || (!cp.curv || cp.mulC[levwavab - 1] == 0.f))))) && (!cp.opaRG || levwavab == 10 || (cp.opaRG && cp.mulopaRG[levwavab - 1] == 0.f)) && ((levwavab == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavab - 1] == 0.f)))) {
+ levwavab--;
+ }
+ }
+
+ if (cp.chromfi > 0.f || cp.chromco > 0.f) {
+ if (levwavab < 7) {
+ levwavab = 7;
+ }
+ }
+
+ if (levwavab > 0) {
+ const std::unique_ptr adecomp(new wavelet_decomposition(labco->data + datalen, labco->W, labco->H, levwavab, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+ const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavab, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+
+ if (!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) {
+ 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);
+ 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);
+
+ 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);
+
+ }
+ }
+ }
+
+ delete[] noisevarchrom;
+
+ if (hhCurve) {
+ delete hhCurve;
+ }
+
+ if (usechrom) {
+ Ldecomp->reconstruct(labco->data, cp.strength);
}
}
-
- //printf("Levwava after: %d\n",levwava);
- if (levwava > 0) {
- const std::unique_ptr adecomp(new wavelet_decomposition(labco->data + datalen, labco->W, labco->H, levwava, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
-
- if (!adecomp->memoryAllocationFailed) {
- WaveletcontAllAB(labco, varhue, varchro, *adecomp, waOpacityCurveW, cp, true);
- adecomp->reconstruct(labco->data + datalen, cp.strength);
- }
- }
-
- int levwavb = levwav;
-
- //printf("Levwavb before: %d\n",levwavb);
- if (cp.chrores == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
- while (levwavb > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavb - 1] == 0.f)) || (cp.CHmet != 2 && (levwavb == 10 || (!cp.curv || cp.mulC[levwavb - 1] == 0.f))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb - 1] == 0.f)) && ((levwavb == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavb - 1] == 0.f)))) {
- levwavb--;
- }
- }
-
- // printf("Levwavb after: %d\n",levwavb);
- if (levwavb > 0) {
- const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavb, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
-
- if (!bdecomp->memoryAllocationFailed) {
- WaveletcontAllAB(labco, varhue, varchro, *bdecomp, waOpacityCurveW, cp, false);
- bdecomp->reconstruct(labco->data + 2 * datalen, cp.strength);
- }
- }
- } else {// a and b
- int levwavab = levwav;
-
- // printf("Levwavab before: %d\n",levwavab);
- if (cp.chrores == 0.f && !hhutili && params->wavelet.CLmethod == "all") { // no processing of residual ab => we probably can reduce the number of levels
- while (levwavab > 0 && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavab - 1] == 0.f)) || (cp.CHmet != 2 && (levwavab == 10 || (!cp.curv || cp.mulC[levwavab - 1] == 0.f))))) && (!cp.opaRG || levwavab == 10 || (cp.opaRG && cp.mulopaRG[levwavab - 1] == 0.f)) && ((levwavab == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavab - 1] == 0.f)))) {
- levwavab--;
- }
- }
-
- // printf("Levwavab after: %d\n",levwavab);
- if (levwavab > 0) {
- const std::unique_ptr adecomp(new wavelet_decomposition(labco->data + datalen, labco->W, labco->H, levwavab, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
- const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavab, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
-
- if (!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) {
- WaveletcontAllAB(labco, varhue, varchro, *adecomp, waOpacityCurveW, cp, true);
- WaveletcontAllAB(labco, varhue, varchro, *bdecomp, waOpacityCurveW, cp, false);
- WaveletAandBAllAB(*adecomp, *bdecomp, cp, hhCurve, hhutili);
-
- adecomp->reconstruct(labco->data + datalen, cp.strength);
- bdecomp->reconstruct(labco->data + 2 * datalen, cp.strength);
-
- }
- }
- }
-
- if (hhCurve) {
- delete hhCurve;
}
if (numtiles > 1 || (numtiles == 1 /*&& cp.avoi*/)) { //in all case since I add contrast curve
@@ -1012,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++) {
@@ -1200,10 +1627,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
- constexpr double epsilmax = 0.001;
- constexpr double epsilmin = 0.0001;
- constexpr double aepsil = (epsilmax - epsilmin) / 90.f;
- constexpr double bepsil = epsilmax - 100.f * aepsil;
+ constexpr double epsilmax = 0.002;
+ constexpr double epsilmin = 0.0005;
+ constexpr double aepsil = 0.01f * (epsilmax - epsilmin);
+ constexpr double bepsil = epsilmin;
const double epsil = aepsil * waparams.softradend + bepsil;
const float blur = 10.f / scale * (0.001f + 0.8f * waparams.softradend);
@@ -1227,6 +1654,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
+
void ImProcFunctions::Aver(float * RESTRICT DataList, int datalen, float &averagePlus, float &averageNeg, float &max, float &min)
{
@@ -1234,11 +1662,11 @@ void ImProcFunctions::Aver(float * RESTRICT DataList, int datalen, float &averag
int countP = 0, countN = 0;
double averaP = 0.0, averaN = 0.0; // use double precision for large summations
- constexpr float thres = 5.f;//different fom zero to take into account only data large enough
+ constexpr float thres = 32.7f;//different fom zero to take into account only data large enough 32.7 = 0.1 in range 0..100 very low value
max = 0.f;
min = RT_INFINITY_F;
#ifdef _OPENMP
- #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;
@@ -1286,10 +1714,10 @@ void ImProcFunctions::Sigma(float * RESTRICT DataList, int datalen, float avera
{
int countP = 0, countN = 0;
double variP = 0.0, variN = 0.0; // use double precision for large summations
- float thres = 5.f;//different fom zero to take into account only data large enough
+ float thres = 32.7f;//different fom zero to take into account only data large enough 32.7 = 0.1 in range 0..100
#ifdef _OPENMP
- #pragma omp parallel for reduction(+:variP,variN,countP,countN) num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel for reduction(+:variP,variN,countP,countN) num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
for (int i = 0; i < datalen; i++) {
@@ -1333,6 +1761,59 @@ void ImProcFunctions::Evaluate2(const wavelet_decomposition &WaveletCoeffs_L,
}
}
+
+void ImProcFunctions::calceffect(int level, float *mean, float *sigma, float *mea, float effect, float offs)
+{
+ float rap = 0.f;
+ float sig = 1.f;
+
+ if (effect < 1.f) {
+ sig = effect;
+ }
+
+ if (effect <= 1.f) {
+ rap = offs * mean[level] - sig * sigma[level];
+ }
+
+ if (rap > 0.f) {
+ mea[0] = rap;
+ } else {
+ mea[0] = mean[level] / 6.f;
+ }
+
+ rap = 0.f;
+
+ if (effect <= 1.f) {
+ rap = offs * mean[level] - 0.5f * sig * sigma[level];
+ }
+
+ if (rap > 0.f) {
+ mea[1] = rap;
+ } else {
+ mea[1] = mean[level] / 4.f;
+ }
+
+ rap = 0.f;
+
+ if (effect <= 1.f) {
+ rap = offs * mean[level] - 0.2f * sig * sigma[level];
+ }
+
+ if (rap > 0.f) {
+ mea[2] = rap;
+ } else {
+ mea[2] = mean[level] / 2.f;
+ }
+
+ mea[3] = offs * mean[level]; // 50% data
+ mea[4] = offs * mean[level] + effect * sigma[level] / 2.f;
+ mea[5] = offs * mean[level] + effect * sigma[level]; //66%
+ mea[6] = offs * mean[level] + effect * 1.2f * sigma[level];
+ mea[7] = offs * mean[level] + effect * 1.5f * sigma[level]; //
+ mea[8] = offs * mean[level] + effect * 2.f * sigma[level]; //95%
+ mea[9] = offs * mean[level] + effect * 2.5f * sigma[level]; //99%
+}
+
void ImProcFunctions::Eval2(float ** WavCoeffs_L, int level,
int W_L, int H_L, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN)
{
@@ -1343,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]);
}
@@ -1480,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)
{
@@ -1550,8 +2031,8 @@ void ImProcFunctions::WaveletcontAllLfinal(const wavelet_decomposition &WaveletC
}
-void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_L,
- struct cont_params &cp, int skip, float *mean, float *sigma, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili)
+void 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, const WavOpacityCurveSH & waOpacityCurveSH, FlatCurve* ChCurve, bool Chutili)
{
const int maxlvl = WaveletCoeffs_L.maxlevel();
const int W_L = WaveletCoeffs_L.level_W(0);
@@ -1565,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++) {
@@ -1573,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;
@@ -1611,7 +2092,6 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
- // printf("MAXmax0=%f MINmin0=%f\n",max0,min0);
//tone mapping
if (cp.tonemap && cp.contmet == 2 && cp.resena) {
@@ -1659,10 +2139,10 @@ 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
+ if (contrast != 0.f && cp.resena && max0 > 0.f) { // contrast = 0.f means that all will be multiplied by 1.f, so we can skip this step
{
#ifdef _OPENMP
@@ -1689,7 +2169,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
}
- if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
+ if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
LabImage *temp = nullptr;
temp = new LabImage(W_L, H_L);
#ifdef _OPENMP
@@ -1720,9 +2200,85 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
+#ifdef _OPENMP
+ #pragma omp barrier
+#endif
+
+ if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
+#ifdef _OPENMP
+ #pragma omp for nowait
+#endif
+
+ for (int i = 0; i < W_L * H_L; i++) {
+ float LL = WavCoeffs_L0[i];
+ float LL100 = LL / 327.68f;
+ float tran = 5.f;//transition
+ //shadow
+
+ 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);
+ } else if (LL100 < cp.th + tran) {
+ float ath = -cp.conres / tran;
+ float bth = cp.conres - ath * cp.th;
+ WavCoeffs_L0[i] *= (1.f + (LL100 * ath + bth) / 200.f);
+ }
+
+ //highlight
+ tran = 5.f;
+
+ if (cp.thH < (tran)) {
+ tran = cp.thH;
+ }
+
+ if (LL100 > cp.thH) {
+ WavCoeffs_L0[i] *= (1.f + cp.conresH / 200.f);
+ } else if (LL100 > (cp.thH - tran)) {
+ float athH = cp.conresH / tran;
+ float bthH = cp.conresH - athH * cp.thH;
+ WavCoeffs_L0[i] *= (1.f + (LL100 * athH + bthH) / 200.f);
+ }
+ }
+ }
+
+//Blur luma
+ if (cp.blurres != 0.f && cp.resena) {
+ int minWL = min(W_L, H_L);
+
+ //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;
+ }
+ }
+
+//
+ int n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n32;
+ n0 = n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = n9 = n10 = n32 = 0;
#ifdef _OPENMP
- #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1)
+ #pragma omp parallel num_threads(wavNestedLevels) if (wavNestedLevels>1)
#endif
{
//enabled Lipschitz..replace simple by complex edge detection
@@ -1823,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) {
@@ -1839,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) {
@@ -1865,8 +2409,19 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
// end
}
+ bool wavcurvecomp = false;//not enable if 0.75
+
+ if (wavblcurve) {
+ for (int i = 0; i < 500; i++) {
+ if (wavblcurve[i] != 0.) {
+ wavcurvecomp = true;
+ }
+ }
+ }
+
#ifdef _OPENMP
- #pragma omp for schedule(dynamic) collapse(2)
+ // #pragma omp for schedule(dynamic) collapse(2)
+ #pragma omp for reduction(+:n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n32) schedule(dynamic) collapse(2)
#endif
for (int dir = 1; dir < 4; dir++) {
@@ -1877,9 +2432,87 @@ 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);
+// 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);
+
+ 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);
+
+ 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]);
+
+ if (WavCL < mea[0]) {
+ beta[co] = 0.05f;
+ n0++;
+
+ 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++;
+ }
+ }
+
+ 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 *= beta * 100.f / skip;
+ klev *= 100.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;
+ }
}
}
}
@@ -1901,7 +2534,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__
@@ -1956,8 +2589,8 @@ void ImProcFunctions::WaveletAandBAllAB(const wavelet_decomposition &WaveletCoef
}
-void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_ab, const WavOpacityCurveW & waOpacityCurveW,
- struct cont_params &cp, const bool useChannelA)
+void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float **varchrom, const wavelet_decomposition &WaveletCoeffs_ab, const Wavblcurve & wavblcurve, const WavOpacityCurveW & waOpacityCurveW,
+ struct cont_params &cp, const bool useChannelA, int skip, float *meanab, float *sigmaab)
{
int maxlvl = WaveletCoeffs_ab.maxlevel();
@@ -1967,7 +2600,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
@@ -2002,20 +2635,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);
@@ -2080,6 +2699,43 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float
}
}
+//Blur chroma
+ if (cp.blurcres != 0.f && cp.resena) {
+ int minWL = min(W_L, H_L);
+
+ //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;
+ }
+ }
+
+
+ bool wavcurvecomp = false;//not enable if 0.75
+
+ if (wavblcurve) {
+ for (int i = 0; i < 500; i++) {
+ if (wavblcurve[i] != 0.) {
+ wavcurvecomp = true;
+ }
+ }
+ }
+
#ifdef _OPENMP
#pragma omp for schedule(dynamic) collapse(2)
#endif
@@ -2091,7 +2747,73 @@ 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);
+
+ 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];
+
+ 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 * 100.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;
+ }
+
+
}
}
@@ -2106,15 +2828,14 @@ void ImProcFunctions::calckoe(float ** WavCoeffs_LL, const cont_params& cp, floa
{
int borderL = 2;
-// printf("cpedth=%f\n",cp.eddetthr);
if (cp.eddetthr < 30.f) {
borderL = 1;
// 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));
}
}
@@ -2162,9 +2883,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
@@ -2212,21 +2931,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
@@ -2242,9 +2946,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
@@ -2267,22 +2968,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;
@@ -2416,7 +3117,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);
@@ -2428,6 +3129,10 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
scaleskip[sc] = scales[sc] / skip;
}
+ if (settings->verbose) {
+ printf("level=%i mean=%f sigma=%f maxp=%f\n", level, mean[level], sigma[level], MaxP[level]);
+ }
+
constexpr float t_r = 40.f;
constexpr float t_l = 10.f;
constexpr float b_r = 75.f;
@@ -2436,7 +3141,53 @@ 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;
+ 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);
+
+ 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.0f;
+ }
+
+ }
+ }
+
+
if (cp.val > 0 && cp.edgeena) {
+
+
float * koe = nullptr;
float maxkoe = 0.f;
@@ -2526,6 +3277,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;
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);
@@ -2535,8 +3287,8 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
if (cp.reinforce != 2) {
const float brepart =
cp.reinforce == 1
- ? 3.f
- : 0.5f;
+ ? 3.f
+ : 0.5f;
const float arepart = -(brepart - 1.f) / (lim0 / 60.f);
if (rad < lim0 / 60.f) {
@@ -2590,7 +3342,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
@@ -2685,7 +3437,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
@@ -2802,7 +3554,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]);
}
}
}
@@ -2810,6 +3562,9 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
if (!lipschitz) {
delete [] koe;
}
+ if (!(cp.bam && cp.finena)) {
+ beta.reset();
+ }
}
@@ -2845,69 +3600,54 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float *maxkoeLi, bool lipschitz
const float skinprot = params->wavelet.skinprotect;
const float skinprotneg = -skinprot;
const float factorHard = (1.f - skinprotneg / 100.f);
+ const float offs = params->wavelet.offset;
+ const float lowthr = params->wavelet.lowthr;
+ float mea[10];
+ float effect = cp.sigm;
+ float lbeta;
- //to adjust increase contrast with local contrast
-
- //for each pixel and each level
- float beta;
- float mea[9];
- float rap = mean[level] - 2.f * cp.sigm * sigma[level];
-
- if (rap > 0.f) {
- mea[0] = rap;
- } else {
- mea[0] = mean[level] / 6.f;
- }
-
- rap = mean[level] - cp.sigm * sigma[level];
-
- if (rap > 0.f) {
- mea[1] = rap;
- } else {
- mea[1] = mean[level] / 2.f;
- }
-
- mea[2] = mean[level]; // 50% data
- mea[3] = mean[level] + cp.sigm * sigma[level] / 2.f;
- mea[4] = mean[level] + cp.sigm * sigma[level]; //66%
- mea[5] = mean[level] + cp.sigm * 1.2f * sigma[level];
- mea[6] = mean[level] + cp.sigm * 1.5f * sigma[level]; //
- mea[7] = mean[level] + cp.sigm * 2.f * sigma[level]; //95%
- mea[8] = mean[level] + cp.sigm * 2.5f * sigma[level]; //99%
+ calceffect(level, mean, sigma, mea, effect, offs);
bool useChromAndHue = (skinprot != 0.f || cp.HSmet);
float modchro;
+ float red0 = 0.005f * (110.f - lowthr);
+ float red1 = 0.008f * (110.f - lowthr);
+ float red2 = 0.011f * (110.f - lowthr);
+
for (int i = 0; i < W_L * H_L; i++) {
- float kLlev = 1.f;
+ 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.6f; //preserve very low contrast (sky...)
+ lbeta = 0.4f * red0;//preserve very low contrast (sky...)
} else if (WavCL < mea[1]) {
- beta = 0.8f;
+ lbeta = 0.5f * red1;
} else if (WavCL < mea[2]) {
- beta = 1.f; //standard
+ lbeta = 0.7f * red2;
} else if (WavCL < mea[3]) {
- beta = 1.f;
+ lbeta = 1.f; //standard
} else if (WavCL < mea[4]) {
- beta = 0.8f; //+sigma
+ lbeta = 1.f;
} else if (WavCL < mea[5]) {
- beta = 0.6f;
+ lbeta = 0.8f; //+sigma
} else if (WavCL < mea[6]) {
- beta = 0.4f;
+ lbeta = 0.6f;
} else if (WavCL < mea[7]) {
- beta = 0.2f; // + 2 sigma
+ lbeta = 0.4f;
} else if (WavCL < mea[8]) {
- beta = 0.1f;
+ lbeta = 0.2f; // + 2 sigma
+ } else if (WavCL < mea[9]) {
+ lbeta = 0.1f;
} else {
- beta = 0.0f;
+ lbeta = 0.0f;
}
}
@@ -2967,9 +3707,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];
@@ -2980,35 +3721,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);
}
}
@@ -3017,6 +3763,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;
@@ -3028,7 +3808,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;
}
@@ -3036,8 +3816,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;
@@ -3053,7 +3833,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]);
}
}
}
@@ -3069,7 +3849,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;
}
@@ -3077,8 +3857,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;
@@ -3112,11 +3892,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
@@ -3125,7 +3904,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];
@@ -3137,9 +3916,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;
@@ -3147,7 +3960,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
@@ -3156,9 +3968,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;
}
}
@@ -3167,14 +3980,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
@@ -3194,7 +4041,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;
@@ -3260,15 +4107,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) {
@@ -3276,7 +4220,6 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
}
if (cp.bam && cp.diag) {
-//printf("OK Chroma\n");
if (cp.opaW && cp.BAmet == 2) {
int iteration = cp.ite;
int itplus = 7 + iteration;
@@ -3288,7 +4231,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;
}
@@ -3296,8 +4239,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;
@@ -3329,7 +4272,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;
}
@@ -3337,8 +4280,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;
@@ -3481,4 +4424,5 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
}
}
}
+
}
diff --git a/rtengine/pdaflinesfilter.cc b/rtengine/pdaflinesfilter.cc
index 1eddbc1ea..b5c72f7f4 100644
--- a/rtengine/pdaflinesfilter.cc
+++ b/rtengine/pdaflinesfilter.cc
@@ -177,7 +177,7 @@ PDAFLinesFilter::PDAFLinesFilter(RawImage *ri):
gthresh_ = new PDAFGreenEqulibrateThreshold(W_, H_);
CameraConstantsStore* ccs = CameraConstantsStore::getInstance();
- CameraConst *cc = ccs->get(ri_->get_maker().c_str(), ri_->get_model().c_str());
+ const CameraConst *cc = ccs->get(ri_->get_maker().c_str(), ri_->get_model().c_str());
if (cc) {
pattern_ = cc->get_pdafPattern();
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 97dfc2fe7..f34476839 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -1374,6 +1374,7 @@ ColorAppearanceParams::ColorAppearanceParams() :
adaplum(16),
badpixsl(0),
wbmodel("RawT"),
+ illum("i50"),
algo("No"),
contrast(0.0),
qcontrast(0.0),
@@ -1392,7 +1393,7 @@ ColorAppearanceParams::ColorAppearanceParams() :
autotempout(true),
ybout(18),
greenout(1.0),
- tempsc(5000),
+ tempsc(5003),
greensc(1.0),
presetcat02(false)
{
@@ -1421,6 +1422,7 @@ bool ColorAppearanceParams::operator ==(const ColorAppearanceParams& other) cons
&& adaplum == other.adaplum
&& badpixsl == other.badpixsl
&& wbmodel == other.wbmodel
+ && illum == other.illum
&& algo == other.algo
&& contrast == other.contrast
&& qcontrast == other.qcontrast
@@ -2146,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),
@@ -2162,6 +2168,21 @@ WaveletParams::WaveletParams() :
0.35,
0.35
},
+ blcurve{
+ static_cast(FCT_MinMaxCPoints),
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.35,
+ 0.5,
+ 0.,
+ 0.35,
+ 0.35,
+ 1.0,
+ 0.0,
+ 0.35,
+ 0.35
+ },
opacityCurveRG{
static_cast(FCT_MinMaxCPoints),
0.0,
@@ -2173,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,
@@ -2234,6 +2274,10 @@ WaveletParams::WaveletParams() :
bluemed(0),
greenhigh(0),
bluehigh(0),
+ ballum(7.),
+ balchrom(0.),
+ chromfi(0.),
+ chromco(0.),
mergeL(40.),
mergeC(20.),
softrad(0.),
@@ -2241,20 +2285,32 @@ WaveletParams::WaveletParams() :
lipst(false),
avoid(false),
showmask(false),
+ oldsh(true),
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),
c{},
ch{},
expedge(false),
+ expbl(false),
expresid(false),
expfinal(false),
exptoning(false),
expnoise(false),
expclari(false),
+ labgridALow(0.0),
+ labgridBLow(0.0),
+ labgridAHigh(0.0),
+ labgridBHigh(0.0),
Lmethod(4),
CLmethod("all"),
Backmethod("grey"),
@@ -2271,9 +2327,13 @@ WaveletParams::WaveletParams() :
Dirmethod("all"),
HSmethod("with"),
sigma(1.0),
+ offset(1.0),
+ lowthr(40.0),
rescon(0),
resconH(0),
reschro(0),
+ resblur(0),
+ resblurc(0),
tmrs(0),
edgs(1.4),
scale(1.),
@@ -2284,7 +2344,7 @@ WaveletParams::WaveletParams() :
chroma(5),
chro(0),
threshold(5),
- threshold2(4),
+ threshold2(5),
edgedetect(90),
edgedetectthr(20),
edgedetectthr2(0),
@@ -2292,12 +2352,15 @@ WaveletParams::WaveletParams() :
edgeampli(10),
contrast(0),
edgrad(15),
+ edgeffect(1.0),
edgval(0),
edgthresh(10),
thr(30),
thrH(70),
radius(40),
skinprotect(0.0),
+ chrwav(0.),
+ bluwav(1.0),
hueskin(-5, 25, 170, 120, false),
hueskin2(-260, -250, -130, -140, false),
hllev(50, 75, 100, 98, false),
@@ -2316,7 +2379,9 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
{
return
ccwcurve == other.ccwcurve
+ && blcurve == other.blcurve
&& opacityCurveRG == other.opacityCurveRG
+ && opacityCurveSH == other.opacityCurveSH
&& opacityCurveBY == other.opacityCurveBY
&& opacityCurveW == other.opacityCurveW
&& opacityCurveWL == other.opacityCurveWL
@@ -2334,6 +2399,10 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& bluemed == other.bluemed
&& greenhigh == other.greenhigh
&& bluehigh == other.bluehigh
+ && ballum == other.ballum
+ && balchrom == other.balchrom
+ && chromfi == other.chromfi
+ && chromco == other.chromco
&& mergeL == other.mergeL
&& mergeC == other.mergeC
&& softrad == other.softrad
@@ -2341,10 +2410,21 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& lipst == other.lipst
&& avoid == other.avoid
&& showmask == other.showmask
+ && oldsh == other.oldsh
&& 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
@@ -2357,6 +2437,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
return true;
}()
&& expedge == other.expedge
+ && expbl == other.expbl
&& expresid == other.expresid
&& expfinal == other.expfinal
&& expclari == other.expclari
@@ -2378,9 +2459,13 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& Dirmethod == other.Dirmethod
&& HSmethod == other.HSmethod
&& sigma == other.sigma
+ && offset == other.offset
+ && lowthr == other.lowthr
&& rescon == other.rescon
&& resconH == other.resconH
&& reschro == other.reschro
+ && resblur == other.resblur
+ && resblurc == other.resblurc
&& tmrs == other.tmrs
&& edgs == other.edgs
&& scale == other.scale
@@ -2399,12 +2484,15 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& edgeampli == other.edgeampli
&& contrast == other.contrast
&& edgrad == other.edgrad
+ && edgeffect == other.edgeffect
&& edgval == other.edgval
&& edgthresh == other.edgthresh
&& thr == other.thr
&& thrH == other.thrH
&& radius == other.radius
&& skinprotect == other.skinprotect
+ && chrwav == other.chrwav
+ && bluwav == other.bluwav
&& hueskin == other.hueskin
&& hueskin2 == other.hueskin2
&& hllev == other.hllev
@@ -2425,14 +2513,18 @@ bool WaveletParams::operator !=(const WaveletParams& other) const
void WaveletParams::getCurves(
WavCurve& cCurve,
+ Wavblcurve& tCurve,
WavOpacityCurveRG& opacityCurveLUTRG,
+ WavOpacityCurveSH& opacityCurveLUTSH,
WavOpacityCurveBY& opacityCurveLUTBY,
WavOpacityCurveW& opacityCurveLUTW,
WavOpacityCurveWL& opacityCurveLUTWL
) const
{
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);
@@ -2865,7 +2957,10 @@ FilmNegativeParams::FilmNegativeParams() :
enabled(false),
redRatio(1.36),
greenExp(1.5),
- blueRatio(0.86)
+ blueRatio(0.86),
+ redBase(0),
+ greenBase(0),
+ blueBase(0)
{
}
@@ -2873,9 +2968,12 @@ bool FilmNegativeParams::operator ==(const FilmNegativeParams& other) const
{
return
enabled == other.enabled
- && redRatio == other.redRatio
+ && redRatio == other.redRatio
&& greenExp == other.greenExp
- && blueRatio == other.blueRatio;
+ && blueRatio == other.blueRatio
+ && redBase == other.redBase
+ && greenBase == other.greenBase
+ && blueBase == other.blueBase;
}
bool FilmNegativeParams::operator !=(const FilmNegativeParams& other) const
@@ -3232,6 +3330,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->colorappearance.adaplum, "Color appearance", "AdaptLum", colorappearance.adaplum, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.badpixsl, "Color appearance", "Badpixsl", colorappearance.badpixsl, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.wbmodel, "Color appearance", "Model", colorappearance.wbmodel, keyFile);
+ saveToKeyfile(!pedited || pedited->colorappearance.illum, "Color appearance", "Illum", colorappearance.illum, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.algo, "Color appearance", "Algorithm", colorappearance.algo, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.jlight, "Color appearance", "J-Light", colorappearance.jlight, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.qbright, "Color appearance", "Q-Bright", colorappearance.qbright, keyFile);
@@ -3488,6 +3587,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);
@@ -3502,6 +3607,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.bluehigh, "Wavelet", "CBbluehigh", wavelet.bluehigh, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.bluemed, "Wavelet", "CBbluemed", wavelet.bluemed, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.bluelow, "Wavelet", "CBbluelow", wavelet.bluelow, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.ballum, "Wavelet", "Ballum", wavelet.ballum, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.balchrom, "Wavelet", "Balchrom", wavelet.balchrom, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.chromfi, "Wavelet", "Chromfine", wavelet.chromfi, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.chromco, "Wavelet", "Chromcoarse", wavelet.chromco, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.mergeL, "Wavelet", "MergeL", wavelet.mergeL, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.mergeC, "Wavelet", "MergeC", wavelet.mergeC, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.softrad, "Wavelet", "Softrad", wavelet.softrad, keyFile);
@@ -3509,11 +3618,16 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.expcontrast, "Wavelet", "Expcontrast", wavelet.expcontrast, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expchroma, "Wavelet", "Expchroma", wavelet.expchroma, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expedge, "Wavelet", "Expedge", wavelet.expedge, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.expbl, "Wavelet", "expbl", wavelet.expbl, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expresid, "Wavelet", "Expresid", wavelet.expresid, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expfinal, "Wavelet", "Expfinal", wavelet.expfinal, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.exptoning, "Wavelet", "Exptoning", wavelet.exptoning, keyFile);
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;
@@ -3556,9 +3670,11 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.TMmethod, "Wavelet", "TMMethod", wavelet.TMmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.chro, "Wavelet", "ChromaLink", wavelet.chro, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.ccwcurve, "Wavelet", "ContrastCurve", wavelet.ccwcurve, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.blcurve, "Wavelet", "blcurve", wavelet.blcurve, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.pastlev, "Wavelet", "Pastlev", wavelet.pastlev.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.satlev, "Wavelet", "Satlev", wavelet.satlev.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveRG, "Wavelet", "OpacityCurveRG", wavelet.opacityCurveRG, keyFile);
+ 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);
@@ -3571,20 +3687,28 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.cbenab, "Wavelet", "CBenab", wavelet.cbenab, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.lipst, "Wavelet", "Lipst", wavelet.lipst, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.skinprotect, "Wavelet", "Skinprotect", wavelet.skinprotect, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.chrwav, "Wavelet", "chrwav", wavelet.chrwav, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.bluwav, "Wavelet", "bluwav", wavelet.bluwav, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.hueskin, "Wavelet", "Hueskin", wavelet.hueskin.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.edgrad, "Wavelet", "Edgrad", wavelet.edgrad, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.edgeffect, "Wavelet", "Edgeffect", wavelet.edgeffect, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.edgval, "Wavelet", "Edgval", wavelet.edgval, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.edgthresh, "Wavelet", "ThrEdg", wavelet.edgthresh, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.avoid, "Wavelet", "AvoidColorShift", wavelet.avoid, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.showmask, "Wavelet", "Showmask", wavelet.showmask, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.oldsh, "Wavelet", "Oldsh", wavelet.oldsh, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.tmr, "Wavelet", "TMr", wavelet.tmr, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.sigma, "Wavelet", "Sigma", wavelet.sigma, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.offset, "Wavelet", "Offset", wavelet.offset, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.lowthr, "Wavelet", "Lowthr", wavelet.lowthr, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.rescon, "Wavelet", "ResidualcontShadow", wavelet.rescon, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.resconH, "Wavelet", "ResidualcontHighlight", wavelet.resconH, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.thr, "Wavelet", "ThresholdResidShadow", wavelet.thr, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.thrH, "Wavelet", "ThresholdResidHighLight", wavelet.thrH, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.radius, "Wavelet", "Residualradius", wavelet.radius, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.reschro, "Wavelet", "Residualchroma", wavelet.reschro, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.resblur, "Wavelet", "Residualblur", wavelet.resblur, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.resblurc, "Wavelet", "Residualblurc", wavelet.resblurc, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.tmrs, "Wavelet", "ResidualTM", wavelet.tmrs, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.edgs, "Wavelet", "ResidualEDGS", wavelet.edgs, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.scale, "Wavelet", "ResidualSCALE", wavelet.scale, keyFile);
@@ -3749,6 +3873,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->filmNegative.redRatio, "Film Negative", "RedRatio", filmNegative.redRatio, keyFile);
saveToKeyfile(!pedited || pedited->filmNegative.greenExp, "Film Negative", "GreenExponent", filmNegative.greenExp, keyFile);
saveToKeyfile(!pedited || pedited->filmNegative.blueRatio, "Film Negative", "BlueRatio", filmNegative.blueRatio, keyFile);
+ saveToKeyfile(!pedited || pedited->filmNegative.baseValues, "Film Negative", "RedBase", filmNegative.redBase, keyFile);
+ 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);
@@ -4229,6 +4356,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Color appearance", "AdaptLum", pedited, colorappearance.adaplum, pedited->colorappearance.adaplum);
assignFromKeyfile(keyFile, "Color appearance", "Badpixsl", pedited, colorappearance.badpixsl, pedited->colorappearance.badpixsl);
assignFromKeyfile(keyFile, "Color appearance", "Model", pedited, colorappearance.wbmodel, pedited->colorappearance.wbmodel);
+ assignFromKeyfile(keyFile, "Color appearance", "Illum", pedited, colorappearance.illum, pedited->colorappearance.illum);
assignFromKeyfile(keyFile, "Color appearance", "Algorithm", pedited, colorappearance.algo, pedited->colorappearance.algo);
assignFromKeyfile(keyFile, "Color appearance", "J-Light", pedited, colorappearance.jlight, pedited->colorappearance.jlight);
assignFromKeyfile(keyFile, "Color appearance", "Q-Bright", pedited, colorappearance.qbright, pedited->colorappearance.qbright);
@@ -4653,6 +4781,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);
@@ -4664,6 +4798,10 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "CBbluehigh", pedited, wavelet.bluehigh, pedited->wavelet.bluehigh);
assignFromKeyfile(keyFile, "Wavelet", "CBbluemed", pedited, wavelet.bluemed, pedited->wavelet.bluemed);
assignFromKeyfile(keyFile, "Wavelet", "CBbluelow", pedited, wavelet.bluelow, pedited->wavelet.bluelow);
+ assignFromKeyfile(keyFile, "Wavelet", "Ballum", pedited, wavelet.ballum, pedited->wavelet.ballum);
+ assignFromKeyfile(keyFile, "Wavelet", "Balchrom", pedited, wavelet.balchrom, pedited->wavelet.balchrom);
+ assignFromKeyfile(keyFile, "Wavelet", "Chromfine", pedited, wavelet.chromfi, pedited->wavelet.chromfi);
+ assignFromKeyfile(keyFile, "Wavelet", "Chromcoarse", pedited, wavelet.chromco, pedited->wavelet.chromco);
assignFromKeyfile(keyFile, "Wavelet", "MergeL", pedited, wavelet.mergeL, pedited->wavelet.mergeL);
assignFromKeyfile(keyFile, "Wavelet", "MergeC", pedited, wavelet.mergeC, pedited->wavelet.mergeC);
assignFromKeyfile(keyFile, "Wavelet", "Softrad", pedited, wavelet.softrad, pedited->wavelet.softrad);
@@ -4671,7 +4809,12 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "Lipst", pedited, wavelet.lipst, pedited->wavelet.lipst);
assignFromKeyfile(keyFile, "Wavelet", "AvoidColorShift", pedited, wavelet.avoid, pedited->wavelet.avoid);
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;
@@ -4700,9 +4843,13 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "HSMethod", pedited, wavelet.HSmethod, pedited->wavelet.HSmethod);
assignFromKeyfile(keyFile, "Wavelet", "DirMethod", pedited, wavelet.Dirmethod, pedited->wavelet.Dirmethod);
assignFromKeyfile(keyFile, "Wavelet", "Sigma", pedited, wavelet.sigma, pedited->wavelet.sigma);
+ assignFromKeyfile(keyFile, "Wavelet", "Offset", pedited, wavelet.offset, pedited->wavelet.offset);
+ assignFromKeyfile(keyFile, "Wavelet", "Lowthr", pedited, wavelet.lowthr, pedited->wavelet.lowthr);
assignFromKeyfile(keyFile, "Wavelet", "ResidualcontShadow", pedited, wavelet.rescon, pedited->wavelet.rescon);
assignFromKeyfile(keyFile, "Wavelet", "ResidualcontHighlight", pedited, wavelet.resconH, pedited->wavelet.resconH);
assignFromKeyfile(keyFile, "Wavelet", "Residualchroma", pedited, wavelet.reschro, pedited->wavelet.reschro);
+ assignFromKeyfile(keyFile, "Wavelet", "Residualblur", pedited, wavelet.resblur, pedited->wavelet.resblur);
+ assignFromKeyfile(keyFile, "Wavelet", "Residualblurc", pedited, wavelet.resblurc, pedited->wavelet.resblurc);
assignFromKeyfile(keyFile, "Wavelet", "ResidualTM", pedited, wavelet.tmrs, pedited->wavelet.tmrs);
assignFromKeyfile(keyFile, "Wavelet", "ResidualEDGS", pedited, wavelet.edgs, pedited->wavelet.edgs);
assignFromKeyfile(keyFile, "Wavelet", "ResidualSCALE", pedited, wavelet.scale, pedited->wavelet.scale);
@@ -4721,13 +4868,16 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "ChromaLink", pedited, wavelet.chro, pedited->wavelet.chro);
assignFromKeyfile(keyFile, "Wavelet", "Contrast", pedited, wavelet.contrast, pedited->wavelet.contrast);
assignFromKeyfile(keyFile, "Wavelet", "Edgrad", pedited, wavelet.edgrad, pedited->wavelet.edgrad);
+ assignFromKeyfile(keyFile, "Wavelet", "Edgeffect", pedited, wavelet.edgeffect, pedited->wavelet.edgeffect);
assignFromKeyfile(keyFile, "Wavelet", "Edgval", pedited, wavelet.edgval, pedited->wavelet.edgval);
assignFromKeyfile(keyFile, "Wavelet", "ThrEdg", pedited, wavelet.edgthresh, pedited->wavelet.edgthresh);
assignFromKeyfile(keyFile, "Wavelet", "ThresholdResidShadow", pedited, wavelet.thr, pedited->wavelet.thr);
assignFromKeyfile(keyFile, "Wavelet", "ThresholdResidHighLight", pedited, wavelet.thrH, pedited->wavelet.thrH);
assignFromKeyfile(keyFile, "Wavelet", "Residualradius", pedited, wavelet.radius, pedited->wavelet.radius);
assignFromKeyfile(keyFile, "Wavelet", "ContrastCurve", pedited, wavelet.ccwcurve, pedited->wavelet.ccwcurve);
+ assignFromKeyfile(keyFile, "Wavelet", "blcurve", pedited, wavelet.blcurve, pedited->wavelet.blcurve);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveRG", pedited, wavelet.opacityCurveRG, pedited->wavelet.opacityCurveRG);
+ assignFromKeyfile(keyFile, "Wavelet", "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);
@@ -4868,6 +5018,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
assignFromKeyfile(keyFile, "Wavelet", "Skinprotect", pedited, wavelet.skinprotect, pedited->wavelet.skinprotect);
+ assignFromKeyfile(keyFile, "Wavelet", "chrwav", pedited, wavelet.chrwav, pedited->wavelet.chrwav);
+ assignFromKeyfile(keyFile, "Wavelet", "bluwav", pedited, wavelet.bluwav, pedited->wavelet.bluwav);
assignFromKeyfile(keyFile, "Wavelet", "Expcontrast", pedited, wavelet.expcontrast, pedited->wavelet.expcontrast);
assignFromKeyfile(keyFile, "Wavelet", "Expchroma", pedited, wavelet.expchroma, pedited->wavelet.expchroma);
@@ -4898,6 +5050,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
assignFromKeyfile(keyFile, "Wavelet", "Expedge", pedited, wavelet.expedge, pedited->wavelet.expedge);
+ assignFromKeyfile(keyFile, "Wavelet", "expbl", pedited, wavelet.expbl, pedited->wavelet.expbl);
assignFromKeyfile(keyFile, "Wavelet", "Expresid", pedited, wavelet.expresid, pedited->wavelet.expresid);
assignFromKeyfile(keyFile, "Wavelet", "Expfinal", pedited, wavelet.expfinal, pedited->wavelet.expfinal);
assignFromKeyfile(keyFile, "Wavelet", "Exptoning", pedited, wavelet.exptoning, pedited->wavelet.exptoning);
@@ -5334,6 +5487,24 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Film Negative", "RedRatio", pedited, filmNegative.redRatio, pedited->filmNegative.redRatio);
assignFromKeyfile(keyFile, "Film Negative", "GreenExponent", pedited, filmNegative.greenExp, pedited->filmNegative.greenExp);
assignFromKeyfile(keyFile, "Film Negative", "BlueRatio", pedited, filmNegative.blueRatio, pedited->filmNegative.blueRatio);
+ if (ppVersion >= 347) {
+ bool r, g, b;
+ assignFromKeyfile(keyFile, "Film Negative", "RedBase", pedited, filmNegative.redBase, r);
+ assignFromKeyfile(keyFile, "Film Negative", "GreenBase", pedited, filmNegative.greenBase, g);
+ assignFromKeyfile(keyFile, "Film Negative", "BlueBase", pedited, filmNegative.blueBase, b);
+ if (pedited) {
+ pedited->filmNegative.baseValues = r || g || b;
+ }
+ } else {
+ // Backwards compatibility with film negative in RT 5.7: use special film base value -1,
+ // to signal that the old channel scaling method should be used.
+ filmNegative.redBase = -1.f;
+ filmNegative.greenBase = -1.f;
+ filmNegative.blueBase = -1.f;
+ if (pedited) {
+ pedited->filmNegative.baseValues = true;
+ }
+ }
}
if (keyFile.has_group("RAW Preprocess WB")) {
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index a737d5776..cc786cb1a 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -40,7 +40,9 @@ class OpacityCurve;
class RetinexgaintransmissionCurve;
class RetinextransmissionCurve;
class WavCurve;
+class Wavblcurve;
class WavOpacityCurveBY;
+class WavOpacityCurveSH;
class WavOpacityCurveRG;
class WavOpacityCurveW;
class WavOpacityCurveWL;
@@ -661,6 +663,7 @@ struct ColorAppearanceParams {
double adaplum;
int badpixsl;
Glib::ustring wbmodel;
+ Glib::ustring illum;
Glib::ustring algo;
double contrast;
double qcontrast;
@@ -1184,7 +1187,10 @@ 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;
@@ -1202,6 +1208,10 @@ struct WaveletParams {
int bluemed;
int greenhigh;
int bluehigh;
+ double ballum;
+ double balchrom;
+ double chromfi;
+ double chromco;
double mergeL;
double mergeC;
double softrad;
@@ -1210,21 +1220,35 @@ struct WaveletParams {
bool lipst;
bool avoid;
bool showmask;
+ bool oldsh;
bool tmr;
int strength;
int balance;
+ double sigmafin;
+ double sigmaton;
+ double sigmacol;
+ double sigmadir;
+ double rangeab;
+ double protab;
int iter;
bool expcontrast;
bool expchroma;
int c[9];
int ch[9];
bool expedge;
+ bool expbl;
bool expresid;
bool expfinal;
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;
@@ -1241,9 +1265,13 @@ struct WaveletParams {
Glib::ustring Dirmethod;
Glib::ustring HSmethod;
double sigma;
+ double offset;
+ double lowthr;
int rescon;
int resconH;
int reschro;
+ int resblur;
+ int resblurc;
double tmrs;
double edgs;
double scale;
@@ -1262,12 +1290,15 @@ struct WaveletParams {
int edgeampli;
int contrast;
int edgrad;
+ double edgeffect;
int edgval;
int edgthresh;
int thr;
int thrH;
int radius;
double skinprotect;
+ double chrwav;
+ double bluwav;
Threshold hueskin;
Threshold hueskin2;
Threshold hllev;
@@ -1287,8 +1318,9 @@ struct WaveletParams {
void getCurves(
WavCurve& cCurve,
- WavOpacityCurveRG&
- opacityCurveLUTRG,
+ Wavblcurve& tCurve,
+ WavOpacityCurveRG& opacityCurveLUTRG,
+ WavOpacityCurveSH& opacityCurveLUTSH,
WavOpacityCurveBY& opacityCurveLUTBY,
WavOpacityCurveW& opacityCurveLUTW,
WavOpacityCurveWL& opacityCurveLUTWL
@@ -1558,6 +1590,10 @@ struct FilmNegativeParams {
double greenExp;
double blueRatio;
+ double redBase;
+ double greenBase;
+ double blueBase;
+
FilmNegativeParams();
bool operator ==(const FilmNegativeParams& other) const;
diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc
index 34d5d961c..c2df70468 100644
--- a/rtengine/rawimage.cc
+++ b/rtengine/rawimage.cc
@@ -524,7 +524,7 @@ int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, Pro
}
CameraConstantsStore* ccs = CameraConstantsStore::getInstance();
- CameraConst *cc = ccs->get(make, model);
+ const CameraConst *cc = ccs->get(make, model);
if (raw_image) {
if (cc && cc->has_rawCrop()) {
@@ -850,42 +850,18 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is
short trans[12]; // set first value to 0 for no change
} table[] = {
- {
- "Canon EOS 5D Mark III", -1, 0x3a98, /* RT */
- { 6722, -635, -963, -4287, 12460, 2028, -908, 2162, 5668 }
- },
{
"Canon EOS 5D", -1, 0xe6c, /* RT */
{ 6319, -793, -614, -5809, 13342, 2738, -1132, 1559, 7971 }
},
- {
- "Canon EOS 6D", -1, 0x3c82,
- { 7034, -804, -1014, -4420, 12564, 2058, -851, 1994, 5758 }
- },
- {
- "Canon EOS 7D", -1, 0x3510, /* RT - Colin Walker */
- { 5962, -171, -732, -4189, 12307, 2099, -911, 1981, 6304 }
- },
{
"Canon EOS 20D", -1, 0xfff, /* RT */
{ 7590, -1646, -673, -4697, 12411, 2568, -627, 1118, 7295 }
},
- {
- "Canon EOS 40D", -1, 0x3f60, /* RT */
- { 6070, -531, -883, -5763, 13647, 2315, -1533, 2582, 6801 }
- },
- {
- "Canon EOS 60D", -1, 0x2ff7, /* RT - Colin Walker */
- { 5678, -179, -718, -4389, 12381, 2243, -869, 1819, 6380 }
- },
{
"Canon EOS 450D", -1, 0x390d, /* RT */
{ 6246, -1272, -523, -5075, 12357, 3075, -1035, 1825, 7333 }
},
- {
- "Canon EOS 550D", -1, 0x3dd7, /* RT - Lebedev*/
- { 6519, -772, -703, -4994, 12737, 2519, -1387, 2492, 6175 }
- },
{
"Canon EOS-1D Mark III", 0, 0x3bb0, /* RT */
{ 7406, -1592, -646, -4856, 12457, 2698, -432, 726, 7921 }
@@ -894,18 +870,10 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is
"Canon PowerShot G10", -1, -1, /* RT */
{ 12535, -5030, -796, -2711, 10134, 3006, -413, 1605, 5264 }
},
- {
- "Canon PowerShot G12", -1, -1, /* RT */
- { 12222, -4097, -1380, -2876, 11016, 2130, -888, 1630, 4434 }
- },
-
-
{
"Fujifilm X100", -1, -1, /* RT - Colin Walker */
{ 10841, -3288, -807, -4652, 12552, 2344, -642, 1355, 7206 }
},
-
-
{
"Nikon D200", -1, 0xfbc, /* RT */
{ 8498, -2633, -295, -5423, 12869, 2860, -777, 1077, 8124 }
@@ -918,32 +886,14 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is
"Nikon D3100", -1, -1, /* RT */
{ 7729, -2212, -481, -5709, 13148, 2858, -1295, 1908, 8936 }
},
- {
- "Nikon D3S", -1, -1, /* RT */
- { 8792, -2663, -344, -5221, 12764, 2752, -1491, 2165, 8121 }
- },
{
"Nikon D5200", -1, -1, // color matrix copied from D5200 DNG D65 matrix
{ 8322, -3112, -1047, -6367, 14342, 2179, -988, 1638, 6394 }
},
- {
- "Nikon D7000", -1, -1, /* RT - Tanveer(tsk1979) */
- { 7530, -1942, -255, -4318, 11390, 3362, -926, 1694, 7649 }
- },
{
"Nikon D7100", -1, -1, // color matrix and WP copied from D7100 DNG D65 matrix
{ 8322, -3112, -1047, -6367, 14342, 2179, -988, 1638, 6394 }
},
- {
- "Nikon D700", -1, -1, /* RT */
- { 8364, -2503, -352, -6307, 14026, 2492, -1134, 1512, 8156 }
- },
- {
- "Nikon COOLPIX A", -1, 0x3e00, // color matrix and WP copied from "COOLPIX A" DNG D65 matrix
- { 8198, -2239, -724, -4871, 12389, 2798, -1043, 205, 7181 }
- },
-
-
{
"Olympus E-30", -1, 0xfbc, /* RT - Colin Walker */
{ 8510, -2355, -693, -4819, 12520, 2578, -1029, 2067, 7752 }
@@ -984,69 +934,14 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is
"Olympus XZ-1", -1, -1, /* RT - Colin Walker */
{ 8665, -2247, -762, -2424, 10372, 2382, -1011, 2286, 5189 }
},
-
-
- /* since Dcraw_v9.21 Panasonic BlackLevel is read from exif (tags 0x001c BlackLevelRed, 0x001d BlackLevelGreen, 0x001e BlackLevelBlue
- and we define here the needed offset of around 15. The total BL is BL + BLoffset (cblack + black) */
-
- {
- "Panasonic DMC-FZ150", 15, 0xfd2, /* RT */
- { 10435, -3208, -72, -2293, 10506, 2067, -486, 1725, 4682 }
- },
- {
- "Panasonic DMC-G10", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */
- { 8310, -1811, -960, -4941, 12990, 2151, -1378, 2468, 6860 }
- },
- {
- "Panasonic DMC-G1", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */
- { 7477, -1615, -651, -5016, 12769, 2506, -1380, 2475, 7240 }
- },
- {
- "Panasonic DMC-G2", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */
- { 8310, -1811, -960, -4941, 12990, 2151, -1378, 2468, 6860 }
- },
- {
- "Panasonic DMC-G3", 15, 0xfdc, /* RT - Colin Walker - WL 4060 */
- { 6051, -1406, -671, -4015, 11505, 2868, -1654, 2667, 6219 }
- },
- {
- "Panasonic DMC-G5", 15, 0xfdc, /* RT - WL 4060 */
- { 7122, -2092, -419, -4643, 11769, 3283, -1363, 2413, 5944 }
- },
- {
- "Panasonic DMC-GF1", 15, 0xf50, /* RT - Colin Walker - Variable WL 3920 - 4080 */
- { 7863, -2080, -668, -4623, 12331, 2578, -1020, 2066, 7266 }
- },
- {
- "Panasonic DMC-GF2", 15, 0xfd2, /* RT - Colin Walker - WL 4050 */
- { 7694, -1791, -745, -4917, 12818, 2332, -1221, 2322, 7197 }
- },
- {
- "Panasonic DMC-GF3", 15, 0xfd2, /* RT - Colin Walker - WL 4050 */
- { 8074, -1846, -861, -5026, 12999, 2239, -1320, 2375, 7422 }
- },
- {
- "Panasonic DMC-GH1", 15, 0xf5a, /* RT - Colin Walker - variable WL 3930 - 4080 */
- { 6360, -1557, -375, -4201, 11504, 3086, -1378, 2518, 5843 }
- },
- {
- "Panasonic DMC-GH2", 15, 0xf5a, /* RT - Colin Walker - variable WL 3930 - 4080 */
-// { 6855,-1765,-456,-4223,11600,2996,-1450,2602,5761 } }, disabled due to problems with underwater WB
- { 7780, -2410, -806, -3913, 11724, 2484, -1018, 2390, 5298 }
- }, // dcraw original
-
{
"Pentax K200D", -1, -1, /* RT */
{ 10962, -4428, -542, -5486, 13023, 2748, -569, 842, 8390 }
},
-
-
{
"Leica Camera AG M9 Digital Camera", -1, -1, /* RT */
{ 7181, -1706, -55, -3557, 11409, 2450, -621, 2072, 7533 }
},
-
-
{
"SONY NEX-3", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */
{ 5145, -741, -123, -4915, 12310, 2945, -794, 1489, 6906 }
@@ -1104,7 +999,7 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is
{
// test if we have any information in the camera constants store, if so we take that.
rtengine::CameraConstantsStore* ccs = rtengine::CameraConstantsStore::getInstance();
- rtengine::CameraConst *cc = ccs->get(make, model);
+ const rtengine::CameraConst *cc = ccs->get(make, model);
if (cc) {
if (RT_blacklevel_from_constant == ThreeValBool::T) {
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index a37e94c62..f94070f2d 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1457,7 +1457,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
[&]() -> bool
{
CameraConstantsStore *ccs = CameraConstantsStore::getInstance();
- CameraConst *cc = ccs->get(ri->get_maker().c_str(), ri->get_model().c_str());
+ const CameraConst *cc = ccs->get(ri->get_maker().c_str(), ri->get_model().c_str());
return cc && cc->get_globalGreenEquilibration();
};
@@ -3901,9 +3901,9 @@ void RawImageSource::getRowStartEnd (int x, int &start, int &end)
static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const array2D & yc, const array2D & Yc, LUTf &xxx, LUTf &yyy, LUTf &YYY, LUTu &histxy)
{
- //calculate histogram x y in a rane of 158 colors
+ //calculate histogram x y in a range of 190 colors
//this "choice" are guided by generally colors who are in nature skin, sky, etc. in those cases "steps" are small
- // of course we can chnage to be more precise
+ // of course we can change to be more precise
#ifdef _OPENMP
#pragma omp parallel
#endif
@@ -4004,279 +4004,345 @@ static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const ar
nh = 32;
} else if (yc[y][x] < 0.32f) {
nh = 33;
- } else if (yc[y][x] < 0.34f) {
+ } else if (yc[y][x] < 0.33f) {
nh = 34;
- } else if (yc[y][x] < 0.37f) {
+ } else if (yc[y][x] < 0.335f) {
nh = 35;
- } else if (yc[y][x] < 0.4f) {
+ } else if (yc[y][x] < 0.34f) {
nh = 36;
- } else if (yc[y][x] < 0.45f) {
+ } else if (yc[y][x] < 0.35f) {
nh = 37;
- } else if (yc[y][x] < 0.5f) {
+ } else if (yc[y][x] < 0.37f) {
nh = 38;
- } else if (yc[y][x] < 0.55f) {
+ } else if (yc[y][x] < 0.4f) {
nh = 39;
- } else if (yc[y][x] < 0.7f) {
+ } else if (yc[y][x] < 0.45f) {
nh = 40;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 41;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 42;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 43;
}
} else if (xc[y][x] < 0.335f && yc[y][x] > 0.1f) {//neutral
if (yc[y][x] < 0.2f) {
- nh = 41;
- } else if (yc[y][x] < 0.24f) {
- nh = 42;
- } else if (yc[y][x] < 0.29f) {
- nh = 43;
- } else if (yc[y][x] < 0.32f) {
nh = 44;
- } else if (yc[y][x] < 0.33f) {
+ } else if (yc[y][x] < 0.24f) {
nh = 45;
- } else if (yc[y][x] < 0.34f) {
+ } else if (yc[y][x] < 0.29f) {
nh = 46;
- } else if (yc[y][x] < 0.35f) {
+ } else if (yc[y][x] < 0.32f) {
nh = 47;
- } else if (yc[y][x] < 0.36f) {
+ } else if (yc[y][x] < 0.33f) {
nh = 48;
- } else if (yc[y][x] < 0.37f) {
- nh = 47;
- } else if (yc[y][x] < 0.38f) {
- nh = 48;
- } else if (yc[y][x] < 0.4f) {
+ } else if (yc[y][x] < 0.335f) {
nh = 49;
- } else if (yc[y][x] < 0.45f) {
+ } else if (yc[y][x] < 0.34f) {
nh = 50;
- } else if (yc[y][x] < 0.5f) {
+ } else if (yc[y][x] < 0.345f) {
nh = 51;
- } else if (yc[y][x] < 0.55f) {
+ } else if (yc[y][x] < 0.35f) {
nh = 52;
- } else if (yc[y][x] < 0.7f) {
+ } else if (yc[y][x] < 0.355f) {
nh = 53;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 54;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 55;
+ } else if (yc[y][x] < 0.38f) {
+ nh = 56;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 57;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 58;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 59;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 60;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 61;
+ }
+ } else if (xc[y][x] < 0.340f && yc[y][x] > 0.1f) {//neutral
+ if (yc[y][x] < 0.2f) {
+ nh = 62;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 63;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 64;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 65;
+ } else if (yc[y][x] < 0.325f) {
+ nh = 66;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 67;
+ } else if (yc[y][x] < 0.335f) {
+ nh = 68;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 69;
+ } else if (yc[y][x] < 0.345f) {
+ nh = 70;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 71;
+ } else if (yc[y][x] < 0.355f) {
+ nh = 72;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 73;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 74;
+ } else if (yc[y][x] < 0.38f) {
+ nh = 75;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 76;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 77;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 78;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 79;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 80;
}
} else if (xc[y][x] < 0.345f && yc[y][x] > 0.1f) {//neutral 37
if (yc[y][x] < 0.2f) {
- nh = 54;
+ nh = 81;
} else if (yc[y][x] < 0.24f) {
- nh = 55;
+ nh = 82;
} else if (yc[y][x] < 0.29f) {
- nh = 56;
+ nh = 83;
} else if (yc[y][x] < 0.32f) {
- nh = 57;
- } else if (yc[y][x] < 0.33f) {//34
- nh = 58;
+ nh = 84;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 85;
+ } else if (yc[y][x] < 0.335f) {
+ nh = 86;
} else if (yc[y][x] < 0.34f) {
- nh = 59;
- } else if (yc[y][x] < 0.35f) {//34
- nh = 60;
- } else if (yc[y][x] < 0.36f) {//34
- nh = 61;
+ nh = 87;
+ } else if (yc[y][x] < 0.345f) {
+ nh = 88;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 89;
+ } else if (yc[y][x] < 0.355f) {
+ nh = 90;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 91;
} else if (yc[y][x] < 0.37f) {
- nh = 62;
+ nh = 92;
} else if (yc[y][x] < 0.38f) {
- nh = 63;
+ nh = 93;
} else if (yc[y][x] < 0.39f) {
- nh = 64;
+ nh = 94;
} else if (yc[y][x] < 0.4f) {
- nh = 65;
+ nh = 95;
} else if (yc[y][x] < 0.42f) {
- nh = 66;
+ nh = 96;
} else if (yc[y][x] < 0.45f) {
- nh = 67;
+ nh = 97;
} else if (yc[y][x] < 0.48f) {
- nh = 68;
+ nh = 98;
} else if (yc[y][x] < 0.5f) {
- nh = 69;
+ nh = 99;
} else if (yc[y][x] < 0.55f) {
- nh = 70;
+ nh = 100;
} else if (yc[y][x] < 0.65f) {
- nh = 71;
+ nh = 101;
}
} else if (xc[y][x] < 0.355f && yc[y][x] > 0.1f) {//neutral 37
if (yc[y][x] < 0.2f) {
- nh = 72;
+ nh = 102;
} else if (yc[y][x] < 0.24f) {
- nh = 73;
+ nh = 103;
} else if (yc[y][x] < 0.29f) {
- nh = 74;
+ nh = 104;
} else if (yc[y][x] < 0.32f) {
- nh = 75;
- } else if (yc[y][x] < 0.33f) {//34
- nh = 76;
+ nh = 105;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 106;
+ } else if (yc[y][x] < 0.335f) {
+ nh = 107;
} else if (yc[y][x] < 0.34f) {
- nh = 77;
- } else if (yc[y][x] < 0.35f) {//34
- nh = 78;
- } else if (yc[y][x] < 0.36f) {//34
- nh = 79;
+ nh = 108;
+ } else if (yc[y][x] < 0.345f) {
+ nh = 109;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 110;
+ } else if (yc[y][x] < 0.355f) {
+ nh = 111;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 112;
} else if (yc[y][x] < 0.37f) {
- nh = 80;
+ nh = 113;
} else if (yc[y][x] < 0.38f) {
- nh = 81;
+ nh = 114;
} else if (yc[y][x] < 0.39f) {
- nh = 82;
+ nh = 115;
} else if (yc[y][x] < 0.4f) {
- nh = 83;
+ nh = 116;
} else if (yc[y][x] < 0.42f) {
- nh = 84;
+ nh = 117;
} else if (yc[y][x] < 0.45f) {
- nh = 85;
+ nh = 118;
} else if (yc[y][x] < 0.48f) {
- nh = 86;
+ nh = 119;
} else if (yc[y][x] < 0.5f) {
- nh = 87;
+ nh = 120;
} else if (yc[y][x] < 0.55f) {
- nh = 88;
+ nh = 121;
} else if (yc[y][x] < 0.65f) {
- nh = 89;
+ nh = 122;
}
} else if (xc[y][x] < 0.365f && yc[y][x] > 0.15f) { //0.4
if (yc[y][x] < 0.2f) {
- nh = 90;
- } else if (yc[y][x] < 0.24f) {
- nh = 91;
- } else if (yc[y][x] < 0.29f) {
- nh = 92;
- } else if (yc[y][x] < 0.32f) {
- nh = 93;
- } else if (yc[y][x] < 0.33f) {
- nh = 94;
- } else if (yc[y][x] < 0.34f) {
- nh = 95;
- } else if (yc[y][x] < 0.36f) {
- nh = 96;
- } else if (yc[y][x] < 0.37f) {
- nh = 97;
- } else if (yc[y][x] < 0.38f) {
- nh = 98;
- } else if (yc[y][x] < 0.39f) {
- nh = 99;
- } else if (yc[y][x] < 0.4f) {
- nh = 100;
- } else if (yc[y][x] < 0.42f) {
- nh = 101;
- } else if (yc[y][x] < 0.45f) {
- nh = 102;
- } else if (yc[y][x] < 0.5f) {
- nh = 103;
- } else if (yc[y][x] < 0.55f) {
- nh = 104;
- } else if (yc[y][x] < 0.63f) {
- nh = 105;
- }
- } else if (xc[y][x] < 0.405f && yc[y][x] > 0.15f) {//45
- if (yc[y][x] < 0.2f) {
- nh = 106;
- } else if (yc[y][x] < 0.24f) {
- nh = 107;
- } else if (yc[y][x] < 0.29f) {
- nh = 108;
- } else if (yc[y][x] < 0.32f) {
- nh = 109;
- } else if (yc[y][x] < 0.34f) {
- nh = 110;
- } else if (yc[y][x] < 0.37f) {
- nh = 111;
- } else if (yc[y][x] < 0.4f) {
- nh = 112;
- } else if (yc[y][x] < 0.45f) {
- nh = 113;
- } else if (yc[y][x] < 0.5f) {
- nh = 114;
- } else if (yc[y][x] < 0.55f) {
- nh = 115;
- } else if (yc[y][x] < 0.6f) {
- nh = 116;
- }
- } else if (xc[y][x] < 0.445f && yc[y][x] > 0.15f) {//45
- if (yc[y][x] < 0.2f) {
- nh = 117;
- } else if (yc[y][x] < 0.24f) {
- nh = 118;
- } else if (yc[y][x] < 0.29f) {
- nh = 119;
- } else if (yc[y][x] < 0.32f) {
- nh = 120;
- } else if (yc[y][x] < 0.34f) {
- nh = 121;
- } else if (yc[y][x] < 0.37f) {
- nh = 122;
- } else if (yc[y][x] < 0.4f) {
nh = 123;
- } else if (yc[y][x] < 0.45f) {
- nh = 124;
- } else if (yc[y][x] < 0.5f) {
- nh = 125;
- } else if (yc[y][x] < 0.55f) {
- nh = 126;
- } else if (yc[y][x] < 0.58f) {
- nh = 127;
- }
- } else if (xc[y][x] < 0.495f && yc[y][x] > 0.15f) {
- if (yc[y][x] < 0.2f) {
- nh = 128;
} else if (yc[y][x] < 0.24f) {
- nh = 129;
+ nh = 124;
} else if (yc[y][x] < 0.29f) {
- nh = 130;
+ nh = 125;
} else if (yc[y][x] < 0.32f) {
- nh = 131;
+ nh = 126;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 127;
} else if (yc[y][x] < 0.34f) {
- nh = 132;
+ nh = 128;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 129;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 130;
} else if (yc[y][x] < 0.37f) {
+ nh = 131;
+ } else if (yc[y][x] < 0.38f) {
+ nh = 132;
+ } else if (yc[y][x] < 0.39f) {
nh = 133;
} else if (yc[y][x] < 0.4f) {
nh = 134;
- } else if (yc[y][x] < 0.45f) {
+ } else if (yc[y][x] < 0.42f) {
nh = 135;
- } else if (yc[y][x] < 0.5f) {
+ } else if (yc[y][x] < 0.45f) {
nh = 136;
- } else if (yc[y][x] < 0.55f) {
+ } else if (yc[y][x] < 0.5f) {
nh = 137;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 138;
+ } else if (yc[y][x] < 0.63f) {
+ nh = 139;
+ }
+ } else if (xc[y][x] < 0.405f && yc[y][x] > 0.15f) {//45
+ if (yc[y][x] < 0.2f) {
+ nh = 140;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 141;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 142;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 143;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 144;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 145;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 146;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 147;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 148;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 149;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 150;
+ }
+ } else if (xc[y][x] < 0.445f && yc[y][x] > 0.15f) {//45
+ if (yc[y][x] < 0.2f) {
+ nh = 151;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 152;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 153;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 154;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 155;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 156;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 157;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 158;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 159;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 160;
+ } else if (yc[y][x] < 0.58f) {
+ nh = 161;
+ }
+ } else if (xc[y][x] < 0.495f && yc[y][x] > 0.15f) {
+ if (yc[y][x] < 0.2f) {
+ nh = 162;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 163;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 164;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 165;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 166;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 167;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 168;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 169;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 170;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 171;
}
} else if (xc[y][x] < 0.545f && yc[y][x] > 0.15f) {
if (yc[y][x] < 0.2f) {
- nh = 138;
+ nh = 172;
} else if (yc[y][x] < 0.24f) {
- nh = 139;
+ nh = 173;
} else if (yc[y][x] < 0.29f) {
- nh = 140;
+ nh = 174;
} else if (yc[y][x] < 0.32f) {
- nh = 141;
+ nh = 175;
} else if (yc[y][x] < 0.34f) {
- nh = 142;
+ nh = 176;
} else if (yc[y][x] < 0.37f) {
- nh = 143;
+ nh = 177;
} else if (yc[y][x] < 0.4f) {
- nh = 144;
+ nh = 178;
} else if (yc[y][x] < 0.45f) {
- nh = 145;
+ nh = 179;
} else if (yc[y][x] < 0.5f) {
- nh = 146;
+ nh = 180;
}
} else if (xc[y][x] < 0.595f && yc[y][x] > 0.15f) {
if (yc[y][x] < 0.22f) {
- nh = 147;
+ nh = 181;
} else if (yc[y][x] < 0.25f) {
- nh = 148;
+ nh = 182;
} else if (yc[y][x] < 0.3f) {
- nh = 149;
+ nh = 183;
} else if (yc[y][x] < 0.35f) {
- nh = 150;
+ nh = 184;
} else if (yc[y][x] < 0.4f) {
- nh = 151;
+ nh = 185;
} else if (yc[y][x] < 0.45f) {
- nh = 152;
+ nh = 186;
}
} else if (xc[y][x] < 0.65f && yc[y][x] > 0.12f) {
if (yc[y][x] < 0.25f) {
- nh = 153;
+ nh = 187;
} else if (yc[y][x] < 0.3f) {
- nh = 154;
+ nh = 188;
} else if (yc[y][x] < 0.35f) {
- nh = 155;
+ nh = 189;
} else if (yc[y][x] < 0.45f) {
- nh = 156;
+ nh = 190;
}
} else if (xc[y][x] < 0.75f && yc[y][x] > 0.1f) {
- nh = 157;
+ nh = 191;
}
if (nh >= 0) {
histxythr[nh]++;
@@ -4350,21 +4416,22 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
Copyright (c) Jacques Desmis 6 - 2018 jdesmis@gmail.com
Copyright (c) Ingo Weyrich 3 - 2020 (heckflosse67@gmx.de)
- This algorithm try to find temperature correlation between 20 to 200 color between 200 spectral color and about 20 to 55 color found in the image, I just found the idea in the web "correlate with chroma" instead of RGB grey point,but I don't use any algo found on the web.
+ This algorithm try to find temperature correlation between 20 to 201 color between 201 spectral color and about 20 to 55 color found in the image between 192, I just found the idea in the web "correlate with chroma" instead of RGB grey point,but I don't use any algo found on the web.
I have test many many algorithms to find the first one that work :)
Probably (sure) there are improvement to do...
- I have create a table temperature with temp and white point with 100 values between 2000K and 12000K we can obviously change these values, more...with different steps
- I have create or recuparate and transformed 200 spectral colors from Colorchecker24, others color and my 468 colors target, or from web flowers, etc. with a step of 5nm, I think it is large enough.
- I think this value of 200 is now complete: I tested correlation with 60, 90, 100, 120, 155...better student increase with number of color, but now it seems stabilized
+ I have create a table temperature with temp and white point with 118 values between 2000K and 12000K we can obviously change these values, more...with different steps
+ I have create a table for tint (green)with 134 values between 0.4 to 4.
+ I have create or recuparate and transformed 201 spectral colors from Colorchecker24, others color and my 468 colors target, or from web flowers, etc. with a step of 5nm, I think it is large enough.
+ I think this value of 201 is now complete: I tested correlation with 60, 90, 100, 120, 155...better student increase with number of color, but now it seems stabilized
Of course we can increase this number :)
1) for the current raw file we create a table for each temp of RGB multipliers
2) then, I choose the "camera temp" to initialize calculation (why not)
- 3) for this temp, I calculated XYZ values for the 200 spectral datas
- 4) then I create for the image an "histogram", but for xyY (Cie 1931 color space)
- 5) for each pixel (in fact to accelerate only 1/10 for and 1/10 for y), I determine for each couple xy, the number of occurences
+ 3) for this temp, I calculated XYZ values for the 201 spectral datas
+ 4) then I create for the image an "histogram", but for xyY (CIE 1931 color space or CIE 1964 (default))
+ 5) for each pixel (in fact to accelerate only 1/5 for and 1/5 for y), I determine for each couple xy, the number of occurences, can be change by Itcwb_precis to 3 or 9
6) I sort this result in ascending order
7) in option we can sort in another manner to take into account chroma : chromax = x - white point x, chromay = y - white point y
8) then I compare this result, with spectral datas found above in 3) with deltaE (limited to chroma)
@@ -4383,10 +4450,9 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
20) between these green limits, we make slightly vary temp (settings in options) and recalculated RGB multipliers
21) with this multipliers for the RGB color find in histogram we recalculate xyY
22) we re-adjust references color for these xyY from 20)
- 23) we add if chroma image is very low, k colors to degrad correlation
- 24) then find all Student correlation for each couple green / temp
- 25) sort these Student values, and choose the minimum
- 26) then for the 3 better couple "temp / green" choose the one where green is nearest from 1.
+ 23) then find all Student correlation for each couple green / temp
+ 24) sort these Student values, and choose the minimum
+ 25) then for the 3 better couple "temp / green" choose the one where green is nearest from 1.
Some variables or function are not used, keep in case of
I have test with cat02 but result are not stable enough ! why ??, therefore cat02 neutralized
@@ -4397,7 +4463,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
You can used it in images :flowers, landscape, portrait, skin, where illuminants are "normal" (daylight, blackbody)
You must avoid when illuminant is non standard (fluorescent, LED...) and also, when the subject is lost in the image (some target to generate profiles).
- You can change 4 parameters in option.cc
+ You can change parameters in option.cc
Itcwb_thres : 34 by default ==> number of color used in final algorithm - between 10 and max 55
Itcwb_sort : false by default, can improve algorithm if true, ==> sort value in something near chroma order, instead of histogram number
Itcwb_greenrange : 0 amplitude of green variation - between 0 to 2
@@ -4405,6 +4471,8 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
Itcwb_forceextra : false - if true force algorithm "extra" ("extra" is used when camera wbsettings are wrong) to all images
Itcwb_sizereference : 3 by default, can be set to 5 ==> size of reference color compare to size of histogram real color
itcwb_delta : 1 by default can be set between 0 to 5 ==> delta temp to build histogram xy - if camera temp is not probably good
+ itcwb_stdobserver10 : true by default - use standard observer 10°, false = standard observer 2°
+ itcwb_precis : 5 by default - can be set to 3 or 9 - 3 best sampling but more time...9 "old" settings - but low differences in times with 3 instead of 9 about twice time 160ms instead of 80ms for a big raw file
*/
// BENCHFUN
@@ -4431,14 +4499,30 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
float snedecor;//1. actually but put in case of confiance interval
} WbGreen;
//green (tint) values between 0.4 to 4.0
- constexpr WbGreen gree[118] = {//symmetric coefficient between 0.717 and 1.40
+ constexpr WbGreen gree[134] = {//symmetric coefficient between 0.717 and 1.40
{0.400, 1.f},
+ {0.420, 1.f},
+ {0.440, 1.f},
+ {0.460, 1.f},
+ {0.480, 1.f},
{0.500, 1.f},
+ {0.520, 1.f},
+ {0.540, 1.f},
{0.550, 1.f},
+ {0.560, 1.f},
+ {0.570, 1.f},
+ {0.580, 1.f},
+ {0.590, 1.f},
{0.600, 1.f},
- {0.625, 1.f},
+ {0.610, 1.f},
+ {0.620, 1.f},
+ {0.630, 1.f},
+ {0.640, 1.f},
{0.650, 1.f},
- {0.675, 1.f},
+ {0.660, 1.f},
+ {0.670, 1.f},
+ {0.680, 1.f},
+ {0.690, 1.f},
{0.700, 1.f},
{0.714, 1.f},
{0.727, 1.f},
@@ -4471,7 +4555,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{0.971, 1.f},
{0.980, 1.f},
{0.990, 1.f},
- {1.000, 1.f},//39
+ {1.000, 1.f},//55
{1.010, 1.f},
{1.020, 1.f},
{1.030, 1.f},
@@ -4558,8 +4642,8 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
int end;
} RangeGreen;
- constexpr RangeGreen Rangestandard = {8, 70};
- constexpr RangeGreen Rangeextended = {4, 77};
+ constexpr RangeGreen Rangestandard = {24, 86};
+ constexpr RangeGreen Rangeextended = {15, 93};
const RangeGreen Rangemax = {0, N_g};
RangeGreen Rangegreenused;
@@ -4581,7 +4665,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
//I don't know how to pass this structure to Colortemp !
// X and Z values calculate for each temp between 2000K to 12000K, so no result after 12000K !
//of course we can change the step between each temp if need
- constexpr WbTxyz Txyz[118] = {//temperature Xwb Zwb 118 values x wb and y wb are calculated after
+ constexpr WbTxyz Txyz[118] = {//temperature Xwb Zwb 118 values x wb and y wb are calculated after, Xwb and Ywb calculated with a spreadsheet
{2001., 1.273842, 0.145295},
{2101., 1.244008, 0.167533},
{2201., 1.217338, 0.190697},
@@ -4702,7 +4786,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{12001., 0.960440, 1.601019}
};
const int N_t = sizeof(Txyz) / sizeof(Txyz[0]); //number of temperature White point
- constexpr int Nc = 200 + 1;//200 number of reference spectral colors, I think it is enough to retrieve good values
+ constexpr int Nc = 201 + 1;//201 number of reference spectral colors, I think it is enough to retrieve good values
array2D Tx(N_t, Nc);
array2D Ty(N_t, Nc);
array2D Tz(N_t, Nc);
@@ -4718,7 +4802,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
float gmm[N_t];
float bmm[N_t];
- constexpr int siza = 158;//size of histogram
+ constexpr int siza = 192;//size of histogram
//tempref and greenref are camera wb values.
// I used them by default to select good spectral values !!
@@ -4801,7 +4885,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
array2D reff_spect_xx_camera(N_t, 2 * Nc + 2);
//here we select the good spectral color inside the 113 values
- //call tempxy to calculate for 200 color references Temp and XYZ with cat02
+ //call tempxy to calculate for 201 color references Temp and XYZ with cat02
ColorTemp::tempxy(separated, repref, Tx, Ty, Tz, Ta, Tb, TL, TX, TY, TZ, wbpar); //calculate chroma xy (xyY) for Z known colors on under 200 illuminants
@@ -4936,7 +5020,9 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
}
estimchrom /= sizcu4;
-
+ if (settings->verbose) {
+ printf("estimchrom=%f\n", estimchrom);
+ }
if (settings->itcwb_sort) { //sort in ascending with chroma values
std::sort(wbchro, wbchro + sizcu4, wbchro[0]);
}
@@ -4958,8 +5044,8 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
//calculate deltaE xx to find best values of spectrals datas - limited to chroma values
int maxnb = rtengine::LIM(settings->itcwb_sizereference, 1, 5);
- if (settings->itcwb_thres > 39) {
- maxnb = 200 / settings->itcwb_thres;
+ if (settings->itcwb_thres > 55) {
+ maxnb = 201 / settings->itcwb_thres;
}
for (int nb = 1; nb <= maxnb; ++nb) { //max 5 iterations for Itcwb_thres=33, after trial 3 is good in most cases but in some cases 5
@@ -5051,7 +5137,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
}
}
- if (extra) {//always used because I amde this choice, brings better results
+ if (extra) {//always used because I made this choice, brings better results
struct Tempgreen {
float student;
int tempref;
@@ -5066,7 +5152,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
for (int i = 0; i < N_g; ++i) {//init variables with
Tgstud[i].student = 1000.f;//max value to initialize
Tgstud[i].tempref = 57;//5002K
- Tgstud[i].greenref = 39;// 1.f
+ Tgstud[i].greenref = 55;// 1.f
}
@@ -5115,14 +5201,6 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
reff_spect_xxyy_prov[2 * j + 1][tt] = Ty[j][tt] / (Tx[j][tt] + Ty[j][tt] + Tz[j][tt]); // y from xyY
}
- //degrade correllation with color high chroma, but not too much...seems not good, but keep in case of??
- if (estimchrom < 0.025f) {//very smal value of chroma for image
-
- good_spectral[0] = true;//blue
- good_spectral[11] = true;//green
- good_spectral[62] = true;//red
- }
-
int kkg = -1;
for (int i = 0; i < Nc ; ++i) {
if (good_spectral[i]) {
@@ -5158,13 +5236,13 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
int goodrefprov;
float studprov;
const int goodref0 = Tgstud[0].tempref;
- const int greengood0 = Tgstud[0].greenref - 39;//39 green = 1
+ const int greengood0 = Tgstud[0].greenref - 55;//55 green = 1
const float stud0 = Tgstud[0].student;
const int goodref1 = Tgstud[1].tempref;
const float stud1 = Tgstud[1].student;
- const int greengood1 = Tgstud[1].greenref - 39;
+ const int greengood1 = Tgstud[1].greenref - 55;
const int goodref2 = Tgstud[2].tempref;
- const int greengood2 = Tgstud[2].greenref - 39;
+ const int greengood2 = Tgstud[2].greenref - 55;
const float stud2 = Tgstud[2].student;
if (std::fabs(greengood2) < std::fabs(greengood1)) {
@@ -5180,18 +5258,21 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
if (std::fabs(greengoodprov) < std::fabs(greengood0)) {
goodref = goodrefprov;
- greengood = greengoodprov + 39;
+ greengood = greengoodprov + 55;
studgood = studprov;
} else {
goodref = goodref0;
- greengood = greengood0 + 39;
+ greengood = greengood0 + 55;
studgood = stud0;
}
tempitc = Txyz[goodref].Tem;
greenitc = gree[greengood].green;
-
+ if (estimchrom < 0.025f) {
+ float ac = -2.40f * estimchrom + 0.06f;//small empirical correction, maximum 0.06 if chroma=0 for all image, currently for very low chroma +0.02
+ greenitc += ac;
+ }
}
avg_rm = 10000.f * rmm[goodref];
@@ -5216,7 +5297,7 @@ void RawImageSource::WBauto(double & tempref, double & greenref, array2D
if (wbpar.method == "autitcgreen") {
bool extra = false;
- if (greenref > 0.77 && greenref < 1.3) {// 0/77 and 1.3 arbitraties values
+ if (greenref > 0.5 && greenref < 1.3) {// 0.5 and 1.3 arbitraties values
greenitc = greenref;
if (settings->itcwb_forceextra) {
@@ -5237,8 +5318,17 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int
{
// BENCHFUN
//used by auto WB local to calculate red, green, blue in local region
- const int bfw = W / 10 + ((W % 10) > 0 ? 1 : 0);// 10 arbitrary value ; perhaps 4 or 5 or 20
- const int bfh = H / 10 + ((H % 10) > 0 ? 1 : 0);
+ int precision = 5;
+ if (settings->itcwb_precis == 5) {
+ precision = 5;
+ } else if (settings->itcwb_precis < 5) {
+ precision = 3;
+ } else if (settings->itcwb_precis > 5) {
+ precision = 9;
+ }
+
+ const int bfw = W / precision + ((W % precision) > 0 ? 1 : 0);// 5 arbitrary value can be change to 3 or 9 ;
+ const int bfh = H / precision + ((H % precision) > 0 ? 1 : 0);
if (! greenloc) {
greenloc(bfw, bfh);
@@ -5288,9 +5378,9 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int
#pragma omp parallel for
#endif
for (int i = 0; i < bfh; ++i) {
- const int ii = i * 10;
+ const int ii = i * precision;
if (ii < H) {
- for (int j = 0, jj = 0; jj < W; ++j, jj += 10) {
+ for (int j = 0, jj = 0; j < bfw; ++j, jj += precision) {
redloc[i][j] = red[ii][jj] * multip;
greenloc[i][j] = green[ii][jj] * multip;
blueloc[i][j] = blue[ii][jj] * multip;
@@ -5490,8 +5580,17 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
if (wbpar.method == "autitcgreen") {
bool twotimes = false;
- const int bfw = W / 10 + ((W % 10) > 0 ? 1 : 0);// 10 arbitrary value ; perhaps 4 or 5 or 20
- const int bfh = H / 10 + ((H % 10) > 0 ? 1 : 0);
+ int precision = 5;
+ if (settings->itcwb_precis == 5) {
+ precision = 5;
+ } else if (settings->itcwb_precis < 5) {
+ precision = 3;
+ } else if (settings->itcwb_precis > 5) {
+ precision = 9;
+ }
+
+ const int bfw = W / precision + ((W % precision) > 0 ? 1 : 0);// 5 arbitrary value can be change to 3 or 9 ;
+ const int bfh = H / precision + ((H % precision) > 0 ? 1 : 0);
WBauto(tempref, greenref, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, tempitc, greenitc, studgood, twotimes, wbpar, begx, begy, yEn, xEn, cx, cy, cmp, raw);
}
diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h
index 71478fbed..770c18ae3 100644
--- a/rtengine/rawimagesource.h
+++ b/rtengine/rawimagesource.h
@@ -124,8 +124,9 @@ public:
int load(const Glib::ustring &fname) override { return load(fname, false); }
int load(const Glib::ustring &fname, bool firstFrameOnly);
void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) override;
- void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) override;
+ void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms, std::array& filmBaseValues) override;
bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const procparams::FilmNegativeParams ¤tParams, std::array& newExps) override;
+ bool getRawSpotValues(Coord2D spot, int spotSize, int tran, const procparams::FilmNegativeParams ¶ms, std::array& rawValues) override;
void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache = false) override;
void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) override;
void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) override;
diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h
index e6074d50b..028cedec9 100644
--- a/rtengine/rtengine.h
+++ b/rtengine/rtengine.h
@@ -439,6 +439,13 @@ public:
};
+class FilmNegListener
+{
+public:
+ virtual ~FilmNegListener() = default;
+ virtual void filmBaseValuesChanged(std::array rgb) = 0;
+};
+
/** This class represents a detailed part of the image (looking through a kind of window).
* It can be created and destroyed with the appropriate members of StagedImageProcessor.
* Several crops can be assigned to the same image. */
@@ -524,6 +531,8 @@ public:
virtual void getCamWB (double& temp, double& green) = 0;
virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) = 0;
virtual bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array& newExps) = 0;
+ virtual bool getRawSpotValues (int x, int y, int spotSize, std::array& rawValues) = 0;
+
virtual void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) = 0;
virtual void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) = 0;
@@ -548,6 +557,7 @@ public:
virtual void setRetinexListener (RetinexListener* l) = 0;
virtual void setWaveletListener (WaveletListener* l) = 0;
virtual void setImageTypeListener (ImageTypeListener* l) = 0;
+ virtual void setFilmNegListener (FilmNegListener* l) = 0;
virtual void setMonitorProfile (const Glib::ustring& monitorProfile, RenderingIntent intent) = 0;
virtual void getMonitorProfile (Glib::ustring& monitorProfile, RenderingIntent& intent) const = 0;
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index a063d965b..e8126be36 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -594,6 +594,8 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati
tpp->defGain = 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]);
tpp->defGain *= std::pow(2, ri->getBaselineExposure());
+ tpp->scaleGain = scale_mul[0] / pre_mul[0]; // used to reconstruct scale_mul from filmnegativethumb.cc
+
tpp->gammaCorrected = true;
unsigned filter = ri->get_filters();
@@ -1042,6 +1044,7 @@ Thumbnail::Thumbnail () :
scaleForSave (8192),
gammaCorrected (false),
colorMatrix{},
+ scaleGain (1.0),
isRaw (true)
{
}
@@ -1179,7 +1182,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
Imagefloat* baseImg = resizeTo (rwidth, rheight, interp, thumbImg);
if (isRaw && params.filmNegative.enabled) {
- processFilmNegative(params, baseImg, rwidth, rheight, rmi, gmi, bmi);
+ processFilmNegative(params, baseImg, rwidth, rheight);
}
if (params.coarse.rotate) {
@@ -2122,6 +2125,10 @@ bool Thumbnail::readData (const Glib::ustring& fname)
colorMatrix[i][j] = cm[ix++];
}
}
+
+ if (keyFile.has_key ("LiveThumbData", "ScaleGain")) {
+ scaleGain = keyFile.get_double ("LiveThumbData", "ScaleGain");
+ }
}
return true;
@@ -2173,6 +2180,7 @@ bool Thumbnail::writeData (const Glib::ustring& fname)
keyFile.set_boolean ("LiveThumbData", "GammaCorrected", gammaCorrected);
Glib::ArrayHandle cm ((double*)colorMatrix, 9, Glib::OWNERSHIP_NONE);
keyFile.set_double_list ("LiveThumbData", "ColorMatrix", cm);
+ keyFile.set_double ("LiveThumbData", "ScaleGain", scaleGain);
keyData = keyFile.to_data ();
diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h
index ccca1c582..a0033d35f 100644
--- a/rtengine/rtthumbnail.h
+++ b/rtengine/rtthumbnail.h
@@ -75,8 +75,9 @@ class Thumbnail
int scaleForSave;
bool gammaCorrected;
double colorMatrix[3][3];
+ double scaleGain;
- void processFilmNegative(const procparams::ProcParams& params, const Imagefloat* baseImg, int rwidth, int rheight, float &rmi, float &gmi, float &bmi);
+ void processFilmNegative(const procparams::ProcParams& params, const Imagefloat* baseImg, int rwidth, int rheight);
public:
diff --git a/rtengine/settings.h b/rtengine/settings.h
index 38e66c8ac..529336cbc 100644
--- a/rtengine/settings.h
+++ b/rtengine/settings.h
@@ -7,8 +7,8 @@
* 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,
+itcw *
* 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.
@@ -88,6 +88,8 @@ public:
bool itcwb_forceextra;
int itcwb_sizereference;
int itcwb_delta;
+ bool itcwb_stdobserver10;
+ int itcwb_precis;
enum class ThumbnailInspectorMode {
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 6b9d86baf..a53902737 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -221,7 +221,12 @@ private:
// After preprocess, run film negative processing if enabled
if ((imgsrc->getSensorType() == ST_BAYER || (imgsrc->getSensorType() == ST_FUJI_XTRANS)) && params.filmNegative.enabled) {
- imgsrc->filmNegativeProcess (params.filmNegative);
+ std::array filmBaseValues = {
+ static_cast(params.filmNegative.redBase),
+ static_cast(params.filmNegative.greenBase),
+ static_cast(params.filmNegative.blueBase)
+ };
+ imgsrc->filmNegativeProcess (params.filmNegative, filmBaseValues);
}
if (pl) {
@@ -1120,7 +1125,9 @@ private:
bool wavcontlutili = false;
WaveletParams WaveParams = params.wavelet;
WavCurve wavCLVCurve;
+ Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
+ WavOpacityCurveSH waOpacityCurveSH;
WavOpacityCurveBY waOpacityCurveBY;
WavOpacityCurveW waOpacityCurveW;
WavOpacityCurveWL waOpacityCurveWL;
@@ -1143,7 +1150,7 @@ private:
provradius->CopyFrom(labView);
}
- params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1);
@@ -1151,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, 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;
@@ -1163,7 +1170,7 @@ private:
WaveParams.expnoise = false;
}
- ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
+ ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, 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/colorappearance.cc b/rtgui/colorappearance.cc
index ace7affd6..bdbe3de3a 100644
--- a/rtgui/colorappearance.cc
+++ b/rtgui/colorappearance.cc
@@ -33,7 +33,7 @@
#define MINTEMP0 2000 //1200
#define MAXTEMP0 12000 //12000
-#define CENTERTEMP0 5000
+#define CENTERTEMP0 5003
#define MINGREEN0 0.8
#define MAXGREEN0 1.2
@@ -221,6 +221,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
auto m = ProcEventMapper::getInstance();
Evcatpreset = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_CAT02PRESET");
EvCATAutotempout = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_TEMPOUT");
+ EvCATillum = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ILLUM");
//preset button cat02
presetcat02 = Gtk::manage (new Gtk::CheckButton (M ("TP_COLORAPP_PRESETCAT02")));
presetcat02->set_tooltip_markup (M("TP_COLORAPP_PRESETCAT02_TIP"));
@@ -241,7 +242,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
p1VBox = Gtk::manage ( new Gtk::VBox());
p1VBox->set_spacing (2);
- degree = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 100.));
+ degree = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 90.));
if (degree->delay < options.adjusterMaxDelay) {
degree->delay = options.adjusterMaxDelay;
@@ -285,6 +286,26 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
wbmHBox->pack_start (*wbmodel);
p1VBox->pack_start (*wbmHBox);
+
+ Gtk::HBox* illumHBox = Gtk::manage (new Gtk::HBox ());
+ illumHBox->set_spacing (2);
+ illumHBox->set_tooltip_markup (M ("TP_COLORAPP_ILLUM_TOOLTIP"));
+ Gtk::Label* illumLab = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_ILLUM") + ":"));
+ illumHBox->pack_start (*illumLab, Gtk::PACK_SHRINK);
+ illum = Gtk::manage (new MyComboBoxText ());
+ illum->append (M ("TP_COLORAPP_ILA"));
+ illum->append (M ("TP_COLORAPP_IL41"));
+ illum->append (M ("TP_COLORAPP_IL50"));
+ illum->append (M ("TP_COLORAPP_IL55"));
+ illum->append (M ("TP_COLORAPP_IL60"));
+ illum->append (M ("TP_COLORAPP_IL65"));
+ illum->append (M ("TP_COLORAPP_IL75"));
+ illum->append (M ("TP_COLORAPP_ILFREE"));
+
+ illum->set_active (0);
+ illumHBox->pack_start (*illum);
+ p1VBox->pack_start (*illumHBox);
+
Gtk::Image* itempL = Gtk::manage (new RTImage ("circle-blue-small.png"));
Gtk::Image* itempR = Gtk::manage (new RTImage ("circle-yellow-small.png"));
Gtk::Image* igreenL = Gtk::manage (new RTImage ("circle-magenta-small.png"));
@@ -608,7 +629,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
// Gtk::Image* iblueredL = Gtk::manage (new RTImage ("circle-blue-small.png"));
// Gtk::Image* iblueredR = Gtk::manage (new RTImage ("circle-red-small.png"));
- degreeout = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 100.));
+ degreeout = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 90.));
if (degreeout->delay < options.adjusterMaxDelay) {
degreeout->delay = options.adjusterMaxDelay;
@@ -626,7 +647,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
tempout = Gtk::manage (new Adjuster (M ("TP_WBALANCE_TEMPERATURE"), MINTEMP0, MAXTEMP0, 5, CENTERTEMP0, itempR1, itempL1, &wbSlider2Temp, &wbTemp2Slider));
greenout = Gtk::manage (new Adjuster (M ("TP_WBALANCE_GREEN"), MINGREEN0, MAXGREEN0, 0.001, 1.0, igreenR1, igreenL1));
ybout = Gtk::manage (new Adjuster (M ("TP_COLORAPP_MEANLUMINANCE"), 5, 90, 1, 18));
- tempout->set_tooltip_markup (M ("TP_COLORAPP_TEMP_TOOLTIP"));
+ tempout->set_tooltip_markup (M ("TP_COLORAPP_TEMP2_TOOLTIP"));
tempout->throwOnButtonRelease();
tempout->addAutoButton (M ("TP_COLORAPP_TEMPOUT_TOOLTIP"));
@@ -701,6 +722,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
// surrconn = surrsource->signal_toggled().connect ( sigc::mem_fun (*this, &ColorAppearance::surrsource_toggled) );
wbmodelconn = wbmodel->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::wbmodelChanged) );
+ illumconn = illum->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::illumChanged) );
algoconn = algo->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::algoChanged) );
surroundconn = surround->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::surroundChanged) );
surrsrcconn = surrsrc->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::surrsrcChanged) );
@@ -777,6 +799,7 @@ void ColorAppearance::neutral_pressed ()
greensc->resetValue (false);
badpixsl->resetValue (false);
wbmodel->set_active (0);
+ illum->set_active (2);
toneCurveMode->set_active (0);
toneCurveMode2->set_active (0);
toneCurveMode3->set_active (0);
@@ -824,7 +847,7 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited)
presetcat02->set_active(pp->colorappearance.presetcat02);
nexttemp = pp->wb.temperature;
- nextgreen = pp->wb.green;
+ nextgreen = 1.; //pp->wb.green;
if (pedited) {
degree->setEditedState (pedited->colorappearance.degree ? Edited : UnEdited);
@@ -938,6 +961,32 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited)
// Have to be manually called to handle initial state update
wbmodelChanged();
+ illumconn.block (true);
+
+ if (pedited && !pedited->colorappearance.illum) {
+ illum->set_active (8);
+ } else if (pp->colorappearance.illum == "iA") {
+ illum->set_active (0);
+ } else if (pp->colorappearance.illum == "i41") {
+ illum->set_active (1);
+ } else if (pp->colorappearance.illum == "i50") {
+ illum->set_active (2);
+ } else if (pp->colorappearance.illum == "i55") {
+ illum->set_active (3);
+ } else if (pp->colorappearance.illum == "i60") {
+ illum->set_active (4);
+ } else if (pp->colorappearance.illum == "i65") {
+ illum->set_active (5);
+ } else if (pp->colorappearance.illum == "i75") {
+ illum->set_active (6);
+ } else if (pp->colorappearance.illum == "ifree") {
+ illum->set_active (7);
+ }
+
+ illumconn.block (false);
+ // Have to be manually called to handle initial state update
+ illumChanged();
+
algoconn.block (true);
if (pedited && !pedited->colorappearance.algo) {
@@ -1123,6 +1172,7 @@ void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited)
pedited->colorappearance.surround = surround->get_active_text() != M ("GENERAL_UNCHANGED");
pedited->colorappearance.surrsrc = surrsrc->get_active_text() != M ("GENERAL_UNCHANGED");
pedited->colorappearance.wbmodel = wbmodel->get_active_text() != M ("GENERAL_UNCHANGED");
+ pedited->colorappearance.illum = illum->get_active_text() != M ("GENERAL_UNCHANGED");
pedited->colorappearance.algo = algo->get_active_text() != M ("GENERAL_UNCHANGED");
// pedited->colorappearance.surrsource = !surrsource->get_inconsistent();
pedited->colorappearance.gamut = !gamut->get_inconsistent();
@@ -1173,7 +1223,24 @@ void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited)
pp->colorappearance.wbmodel = "RawTCAT02";
} else if (wbmodel->get_active_row_number() == 2) {
pp->colorappearance.wbmodel = "free";
+ }
+ if (illum->get_active_row_number() == 0) {
+ pp->colorappearance.illum = "iA";
+ } else if (illum->get_active_row_number() == 1) {
+ pp->colorappearance.illum = "i41";
+ } else if (illum->get_active_row_number() == 2) {
+ pp->colorappearance.illum = "i50";
+ } else if (illum->get_active_row_number() == 3) {
+ pp->colorappearance.illum = "i55";
+ } else if (illum->get_active_row_number() == 4) {
+ pp->colorappearance.illum = "i60";
+ } else if (illum->get_active_row_number() == 5) {
+ pp->colorappearance.illum = "i65";
+ } else if (illum->get_active_row_number() == 6) {
+ pp->colorappearance.illum = "i75";
+ } else if (illum->get_active_row_number() == 7) {
+ pp->colorappearance.illum = "ifree";
}
if (algo->get_active_row_number() == 0) {
@@ -1358,6 +1425,7 @@ void ColorAppearance::presetcat02pressed ()
greensc->resetValue (false);
badpixsl->resetValue (false);
wbmodel->set_active (0);
+ illum->set_active (2);
toneCurveMode->set_active (0);
toneCurveMode2->set_active (0);
toneCurveMode3->set_active (0);
@@ -1369,6 +1437,7 @@ void ColorAppearance::presetcat02pressed ()
gamutconn.block (false);
degree->setAutoValue (true);
degree->resetValue (false);
+ degree->setValue(90);
adapscen->resetValue (false);
adapscen->setAutoValue (true);
degreeout->resetValue (false);
@@ -1383,7 +1452,7 @@ void ColorAppearance::presetcat02pressed ()
ybscen->setValue(18);
surround->set_active (0);
adaplum->setValue(400.);
- degreeout->setValue(70);
+ degreeout->setValue(90);
ybout->setValue(18);
tempout->setValue (nexttemp);
greenout->setValue (nextgreen);
@@ -1426,6 +1495,7 @@ void ColorAppearance::presetcat02pressed ()
ybscen->setAutoValue (true);
surrsrc->set_active (0);
wbmodel->set_active (0);
+ illum->set_active (2);
tempsc->resetValue (false);
greensc->resetValue (false);
adapscen->resetValue (false);
@@ -1883,13 +1953,17 @@ void ColorAppearance::surroundChanged ()
void ColorAppearance::wbmodelChanged ()
{
if (wbmodel->get_active_row_number() == 0 || wbmodel->get_active_row_number() == 1) {
+ illum->hide();
tempsc->hide();
greensc->hide();
+ tempsc->setValue (5003);
+ greensc->setValue (1);
}
if (wbmodel->get_active_row_number() == 2) {
tempsc->show();
greensc->show();
+ illum->show();
}
if (listener && (multiImage || getEnabled()) ) {
@@ -1897,6 +1971,47 @@ void ColorAppearance::wbmodelChanged ()
}
}
+void ColorAppearance::illumChanged ()
+{
+ if (illum->get_active_row_number() == 0) {
+ tempsc->setValue (2856);
+ tempsc->set_sensitive(false);
+ greensc->set_sensitive(false);
+ } else if (illum->get_active_row_number() == 1) {
+ tempsc->setValue (4100);
+ tempsc->set_sensitive(false);
+ greensc->set_sensitive(false);
+ } else if (illum->get_active_row_number() == 2) {
+ tempsc->setValue (5003);
+ tempsc->set_sensitive(false);
+ greensc->set_sensitive(false);
+ } else if (illum->get_active_row_number() == 3) {
+ tempsc->setValue (5503);
+ tempsc->set_sensitive(false);
+ greensc->set_sensitive(false);
+ } else if (illum->get_active_row_number() == 4) {
+ tempsc->setValue (6000);
+ tempsc->set_sensitive(false);
+ greensc->set_sensitive(false);
+ } else if (illum->get_active_row_number() == 5) {
+ tempsc->setValue (6504);
+ tempsc->set_sensitive(false);
+ greensc->set_sensitive(false);
+ } else if (illum->get_active_row_number() == 6) {
+ tempsc->setValue (7504);
+ tempsc->set_sensitive(false);
+ greensc->set_sensitive(false);
+ } else if (illum->get_active_row_number() == 7) {
+ tempsc->set_sensitive(true);
+ greensc->set_sensitive(true);
+ }
+
+ if (listener && (multiImage || getEnabled()) ) {
+ listener->panelChanged (EvCATillum, illum->get_active_text ());
+ }
+}
+
+
void ColorAppearance::algoChanged ()
{
@@ -1999,6 +2114,7 @@ void ColorAppearance::setBatchMode (bool batchMode)
surround->append (M ("GENERAL_UNCHANGED"));
surrsrc->append (M ("GENERAL_UNCHANGED"));
wbmodel->append (M ("GENERAL_UNCHANGED"));
+ illum->append (M ("GENERAL_UNCHANGED"));
algo->append (M ("GENERAL_UNCHANGED"));
toneCurveMode->append (M ("GENERAL_UNCHANGED"));
toneCurveMode2->append (M ("GENERAL_UNCHANGED"));
diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h
index 863787118..c326b06f9 100644
--- a/rtgui/colorappearance.h
+++ b/rtgui/colorappearance.h
@@ -53,6 +53,7 @@ public:
void surroundChanged ();
void surrsrcChanged ();
void wbmodelChanged ();
+ void illumChanged ();
void algoChanged ();
void surrsource_toggled ();
void gamut_toggled ();
@@ -102,6 +103,7 @@ public:
private:
rtengine::ProcEvent Evcatpreset;
rtengine::ProcEvent EvCATAutotempout;
+ rtengine::ProcEvent EvCATillum;
bool bgTTipQuery (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
bool srTTipQuery (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
void foldAllButMe (GdkEventButton* event, MyExpander *expander);
@@ -156,6 +158,8 @@ private:
sigc::connection surroundconn;
MyComboBoxText* wbmodel;
sigc::connection wbmodelconn;
+ MyComboBoxText* illum;
+ sigc::connection illumconn;
MyComboBoxText* algo;
sigc::connection algoconn;
sigc::connection surrconn;
diff --git a/rtgui/crop.cc b/rtgui/crop.cc
index d9d496523..48d1e09af 100644
--- a/rtgui/crop.cc
+++ b/rtgui/crop.cc
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
*/
+#include
+
#include "crop.h"
#include "options.h"
@@ -46,39 +48,82 @@ inline void get_custom_ratio(int w, int h, double &rw, double &rh)
} // namespace
+class Crop::CropRatios final
+{
+public:
+ CropRatios() :
+ ratios{
+ {M("GENERAL_ASIMAGE"), 0.0},
+ {M("GENERAL_CURRENT"), -1.0},
+ {"3:2", 3.0 / 2.0}, // L1.5, P0.666...
+ {"4:3", 4.0 / 3.0}, // L1.333..., P0.75
+ {"16:9", 16.0 / 9.0}, // L1.777..., P0.5625
+ {"16:10", 16.0 / 10.0}, // L1.6, P0.625
+ {"1:1", 1.0 / 1.0}, // L1, P1
+ {"2:1", 2.0 / 1.0}, // L2, P0.5
+ {"3:1", 3.0 / 1.0}, // L3, P0.333...
+ {"4:1", 4.0 / 1.0}, // L4, P0.25
+ {"5:1", 5.0 / 1.0}, // L5, P0.2
+ {"6:1", 6.0 / 1.0}, // L6, P0.1666...
+ {"7:1", 7.0 / 1.0}, // L7, P0.142...
+ {"4:5", 4.0 / 5.0}, // L1.25, P0.8
+ {"5:7", 5.0 / 7.0}, // L1.4, P0.714...
+ {"6:7", 6.0 / 7.0}, // L1.166..., P0.857...
+ {"6:17", 6.0 / 17.0}, // L2.833..., P0.352...
+ {"24:65 - XPAN", 24.0 / 65.0}, // L2.708..., P0.369...
+ {"1.414 - DIN EN ISO 216", 1.414}, // L1.414, P0.707...
+ {"3.5:5", 3.5 / 5.0}, // L1.428..., P0.7
+ {"8.5:11 - US Letter", 8.5 / 11.0}, // L1.294..., P0.772...
+ {"9.5:12", 9.5 / 12.0}, // L1.263..., P0.791...
+ {"10:12", 10.0 / 12.0}, // L1.2, P0.833...
+ {"11:14", 11.0 / 14.0}, // L1.272..., P0.785...
+ {"11:17 - Tabloid", 11.0 / 17.0}, // L1.545..., P0.647...
+ {"13:19", 13.0 / 19.0}, // L1.461..., P0.684...
+ {"17:22", 17.0 / 22.0}, // L1.294..., P0.772...
+ {"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777...
+ {"64:27", 64.0 / 27.0}, // L2.370..., P0.421...
+ }
+ {
+ }
+
+ std::vector getLabels() const
+ {
+ std::vector res;
+
+ res.reserve(ratios.size());
+
+ for (const auto& ratio : ratios) {
+ res.push_back(ratio.label);
+ }
+
+ return res;
+ }
+
+ double getValue(std::size_t index) const
+ {
+ return
+ index < ratios.size()
+ ? ratios[index].value
+ : ratios[0].value;
+ }
+
+ void updateCurrentRatio(double value)
+ {
+ ratios[1].value = value;
+ }
+
+private:
+ struct CropRatio {
+ Glib::ustring label;
+ double value;
+ };
+
+ std::vector ratios;
+};
+
Crop::Crop():
FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true),
- crop_ratios{
- {M("GENERAL_ASIMAGE"), 0.0},
- {M("GENERAL_CURRENT"), -1.0},
- {"3:2", 3.0 / 2.0}, // L1.5, P0.666...
- {"4:3", 4.0 / 3.0}, // L1.333..., P0.75
- {"16:9", 16.0 / 9.0}, // L1.777..., P0.5625
- {"16:10", 16.0 / 10.0}, // L1.6, P0.625
- {"1:1", 1.0 / 1.0}, // L1, P1
- {"2:1", 2.0 / 1.0}, // L2, P0.5
- {"3:1", 3.0 / 1.0}, // L3, P0.333...
- {"4:1", 4.0 / 1.0}, // L4, P0.25
- {"5:1", 5.0 / 1.0}, // L5, P0.2
- {"6:1", 6.0 / 1.0}, // L6, P0.1666...
- {"7:1", 7.0 / 1.0}, // L7, P0.142...
- {"4:5", 4.0 / 5.0}, // L1.25, P0.8
- {"5:7", 5.0 / 7.0}, // L1.4, P0.714...
- {"6:7", 6.0 / 7.0}, // L1.166..., P0.857...
- {"6:17", 6.0 / 17.0}, // L2.833..., P0.352...
- {"24:65 - XPAN", 24.0 / 65.0}, // L2.708..., P0.369...
- {"1.414 - DIN EN ISO 216", 1.414}, // L1.414, P0.707...
- {"3.5:5", 3.5 / 5.0}, // L1.428..., P0.7
- {"8.5:11 - US Letter", 8.5 / 11.0}, // L1.294..., P0.772...
- {"9.5:12", 9.5 / 12.0}, // L1.263..., P0.791...
- {"10:12", 10.0 / 12.0}, // L1.2, P0.833...
- {"11:14", 11.0 / 14.0}, // L1.272..., P0.785...
- {"11:17 - Tabloid", 11.0 / 17.0}, // L1.545..., P0.647...
- {"13:19", 13.0 / 19.0}, // L1.461..., P0.684...
- {"17:22", 17.0 / 22.0}, // L1.294..., P0.772...
- {"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777...
- {"64:27", 64.0 / 27.0}, // L2.370..., P0.421...
- },
+ crop_ratios(new CropRatios),
opt(0),
wDirty(true),
hDirty(true),
@@ -229,8 +274,8 @@ Crop::Crop():
// ppigrid END
// Populate the combobox
- for (const auto& crop_ratio : crop_ratios) {
- ratio->append (crop_ratio.label);
+ for (const auto& label : crop_ratios->getLabels()) {
+ ratio->append (label);
}
ratio->set_active (0);
@@ -354,7 +399,10 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited)
setDimensions (pp->crop.x + pp->crop.w, pp->crop.y + pp->crop.h);
}
- const bool flip_orientation = pp->crop.fixratio && crop_ratios[ratio->get_active_row_number()].value > 0 && crop_ratios[ratio->get_active_row_number()].value < 1.0;
+ const bool flip_orientation =
+ pp->crop.fixratio
+ && crop_ratios->getValue(ratio->get_active_row_number()) > 0
+ && crop_ratios->getValue(ratio->get_active_row_number()) < 1.0;
if (pp->crop.orientation == "Landscape") {
orientation->set_active (flip_orientation ? 1 : 0);
@@ -469,7 +517,10 @@ void Crop::write (ProcParams* pp, ParamsEdited* pedited)
}
// for historical reasons we store orientation different if ratio is written as 2:3 instead of 3:2, but in GUI 'landscape' is always long side horizontal regardless of the ratio is written short or long side first.
- const bool flip_orientation = fixr->get_active() && crop_ratios[ratio->get_active_row_number()].value > 0 && crop_ratios[ratio->get_active_row_number()].value < 1.0;
+ const bool flip_orientation =
+ fixr->get_active()
+ && crop_ratios->getValue(ratio->get_active_row_number()) > 0
+ && crop_ratios->getValue(ratio->get_active_row_number()) < 1.0;
if (orientation->get_active_row_number() == 0) {
pp->crop.orientation = flip_orientation ? "Portrait" : "Landscape";
@@ -561,6 +612,11 @@ void Crop::doresetCrop ()
yDirty = true;
wDirty = true;
hDirty = true;
+
+ // Reset ratio, ratio lock and orientation as well
+ ratio->set_active(0);
+ orientation->set_active(2);
+ fixr->set_active(true);
int X = 0;
int Y = 0;
@@ -1501,7 +1557,7 @@ double Crop::getRatio () const
return r;
}
- r = crop_ratios[ratio->get_active_row_number()].value;
+ r = crop_ratios->getValue(ratio->get_active_row_number());
if (!r) {
r = maxh <= maxw ? float(maxh)/float(maxw) : float(maxw)/float(maxh);
}
@@ -1539,5 +1595,5 @@ void Crop::updateCurrentRatio()
double rw, rh;
get_custom_ratio(w->get_value(), h->get_value(), rw, rh);
customRatioLabel->set_text(Glib::ustring::compose("%1:%2", rw, rh));
- crop_ratios[1].value = double(w->get_value())/double(h->get_value());
+ crop_ratios->updateCurrentRatio(static_cast(w->get_value()) / static_cast(h->get_value()));
}
diff --git a/rtgui/crop.h b/rtgui/crop.h
index b9221a803..c6636b917 100644
--- a/rtgui/crop.h
+++ b/rtgui/crop.h
@@ -18,7 +18,7 @@
*/
#pragma once
-#include
+#include
#include
@@ -91,16 +91,13 @@ public:
void rotateCrop (int deg, bool hflip, bool vflip);
private:
- struct CropRatio {
- Glib::ustring label;
- double value;
- };
-
- std::vector crop_ratios;
+ class CropRatios;
void adjustCropToRatio();
void updateCurrentRatio();
+ const std::unique_ptr crop_ratios;
+
Gtk::CheckButton* fixr;
MyComboBoxText* ratio;
MyComboBoxText* orientation;
diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc
index 6a0d41878..1a82c4a94 100644
--- a/rtgui/editorpanel.cc
+++ b/rtgui/editorpanel.cc
@@ -172,7 +172,7 @@ private:
const std::vector profiles = rtengine::ICCStore::getInstance()->getProfiles (rtengine::ICCStore::ProfileType::MONITOR);
- for (const auto profile : profiles) {
+ for (const auto& profile : profiles) {
profileBox.append (profile);
}
diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc
index 90cedf148..1b105a3ec 100644
--- a/rtgui/filmnegative.cc
+++ b/rtgui/filmnegative.cc
@@ -44,6 +44,17 @@ Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring
return adj;
}
+Glib::ustring formatBaseValues(const std::array& rgb)
+{
+ if (rgb[0] <= 0.f && rgb[1] <= 0.f && rgb[2] <= 0.f) {
+ return "- - -";
+ } else {
+ return Glib::ustring::format(std::fixed, std::setprecision(1), rgb[0]) + " " +
+ Glib::ustring::format(std::fixed, std::setprecision(1), rgb[1]) + " " +
+ Glib::ustring::format(std::fixed, std::setprecision(1), rgb[2]);
+ }
+}
+
}
FilmNegative::FilmNegative() :
@@ -51,12 +62,17 @@ FilmNegative::FilmNegative() :
EditSubscriber(ET_OBJECTS),
evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_VALUES")),
evFilmNegativeEnabled(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED")),
+ evFilmBaseValues(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_FILMBASE")),
+ filmBaseValues({0.f, 0.f, 0.f}),
fnp(nullptr),
greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 1.5)), // master exponent (green channel)
redRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 0.3, 3, (2.04 / 1.5))), // ratio of red exponent to master exponent
blueRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 0.3, 3, (1.29 / 1.5))), // ratio of blue exponent to master exponent
spotgrid(Gtk::manage(new Gtk::Grid())),
- spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK"))))
+ spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK")))),
+ filmBaseLabel(Gtk::manage(new Gtk::Label(M("TP_FILMNEGATIVE_FILMBASE_VALUES"), Gtk::ALIGN_START))),
+ filmBaseValuesLabel(Gtk::manage(new Gtk::Label("- - -"))),
+ filmBaseSpotButton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_FILMBASE_PICK"))))
{
spotgrid->get_style_context()->add_class("grid-spacing");
setExpandAlignProperties(spotgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
@@ -64,7 +80,10 @@ FilmNegative::FilmNegative() :
setExpandAlignProperties(spotbutton, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
spotbutton->get_style_context()->add_class("independent");
spotbutton->set_tooltip_text(M("TP_FILMNEGATIVE_GUESS_TOOLTIP"));
- spotbutton->set_image (*Gtk::manage (new RTImage ("color-picker-small.png")));
+ spotbutton->set_image(*Gtk::manage(new RTImage("color-picker-small.png")));
+
+ filmBaseSpotButton->set_tooltip_text(M("TP_FILMNEGATIVE_FILMBASE_TOOLTIP"));
+ setExpandAlignProperties(filmBaseValuesLabel, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
// TODO make spot size configurable ?
@@ -81,7 +100,7 @@ FilmNegative::FilmNegative() :
// spotsize->set_active(0);
// spotsize->append ("4");
- spotgrid->attach (*spotbutton, 0, 1, 1, 1);
+ spotgrid->attach(*spotbutton, 0, 1, 1, 1);
// spotgrid->attach (*slab, 1, 0, 1, 1);
// spotgrid->attach (*wbsizehelper, 2, 0, 1, 1);
@@ -90,13 +109,26 @@ FilmNegative::FilmNegative() :
pack_start(*blueRatio, Gtk::PACK_SHRINK, 0);
pack_start(*spotgrid, Gtk::PACK_SHRINK, 0);
+ Gtk::HSeparator* const sep = Gtk::manage(new Gtk::HSeparator());
+ sep->get_style_context()->add_class("grid-row-separator");
+ pack_start(*sep, Gtk::PACK_SHRINK, 0);
+
+ Gtk::Grid* const fbGrid = Gtk::manage(new Gtk::Grid());
+ fbGrid->attach(*filmBaseLabel, 0, 0, 1, 1);
+ fbGrid->attach(*filmBaseValuesLabel, 1, 0, 1, 1);
+ pack_start(*fbGrid, Gtk::PACK_SHRINK, 0);
+
+ pack_start(*filmBaseSpotButton, Gtk::PACK_SHRINK, 0);
+
spotbutton->signal_toggled().connect(sigc::mem_fun(*this, &FilmNegative::editToggled));
// spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) );
+ filmBaseSpotButton->signal_toggled().connect(sigc::mem_fun(*this, &FilmNegative::baseSpotToggled));
+
// Editing geometry; create the spot rectangle
Rectangle* const spotRect = new Rectangle();
spotRect->filled = false;
-
+
visibleGeometry.push_back(spotRect);
// Stick a dummy rectangle over the whole image in mouseOverGeometry.
@@ -134,6 +166,14 @@ void FilmNegative::read(const rtengine::procparams::ProcParams* pp, const Params
greenExp->setValue(pp->filmNegative.greenExp);
blueRatio->setValue(pp->filmNegative.blueRatio);
+ filmBaseValues[0] = pp->filmNegative.redBase;
+ filmBaseValues[1] = pp->filmNegative.greenBase;
+ filmBaseValues[2] = pp->filmNegative.blueBase;
+
+ // If base values are not set in params, estimated values will be passed in later
+ // (after processing) via FilmNegListener
+ filmBaseValuesLabel->set_text(formatBaseValues(filmBaseValues));
+
enableListener();
}
@@ -142,14 +182,23 @@ void FilmNegative::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped
pp->filmNegative.redRatio = redRatio->getValue();
pp->filmNegative.greenExp = greenExp->getValue();
pp->filmNegative.blueRatio = blueRatio->getValue();
+
pp->filmNegative.enabled = getEnabled();
if (pedited) {
pedited->filmNegative.redRatio = redRatio->getEditedState();
pedited->filmNegative.greenExp = greenExp->getEditedState();
pedited->filmNegative.blueRatio = blueRatio->getEditedState();
+ pedited->filmNegative.baseValues = filmBaseValues[0] != pp->filmNegative.redBase
+ || filmBaseValues[1] != pp->filmNegative.greenBase
+ || filmBaseValues[2] != pp->filmNegative.blueBase;
pedited->filmNegative.enabled = !get_inconsistent();
}
+
+ pp->filmNegative.redBase = filmBaseValues[0];
+ pp->filmNegative.greenBase = filmBaseValues[1];
+ pp->filmNegative.blueBase = filmBaseValues[2];
+
}
void FilmNegative::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited)
@@ -172,8 +221,8 @@ void FilmNegative::setDefaults(const rtengine::procparams::ProcParams* defParams
void FilmNegative::setBatchMode(bool batchMode)
{
if (batchMode) {
- spotConn.disconnect();
removeIfThere(this, spotgrid, false);
+ removeIfThere(this, filmBaseSpotButton, false);
ToolPanel::setBatchMode(batchMode);
redRatio->showEditedCB();
greenExp->showEditedCB();
@@ -205,16 +254,20 @@ void FilmNegative::enabledChanged()
if (listener) {
if (get_inconsistent()) {
listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_UNCHANGED"));
- }
- else if (getEnabled()) {
+ } else if (getEnabled()) {
listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_ENABLED"));
- }
- else {
+ } else {
listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_DISABLED"));
}
}
}
+void FilmNegative::filmBaseValuesChanged(std::array rgb)
+{
+ filmBaseValues = rgb;
+ filmBaseValuesLabel->set_text(formatBaseValues(filmBaseValues));
+}
+
void FilmNegative::setFilmNegProvider(FilmNegProvider* provider)
{
fnp = provider;
@@ -227,7 +280,7 @@ void FilmNegative::setEditProvider(EditDataProvider* provider)
CursorShape FilmNegative::getCursor(int objectID) const
{
- return CSSpotWB;
+ return CSSpotWB;
}
bool FilmNegative::mouseOver(int modifierKey)
@@ -246,31 +299,57 @@ bool FilmNegative::button1Pressed(int modifierKey)
EditSubscriber::action = EditSubscriber::Action::NONE;
if (listener) {
- refSpotCoords.push_back(provider->posImage);
+ if (spotbutton->get_active()) {
- if (refSpotCoords.size() == 2) {
- // User has selected 2 reference gray spots. Calculating new exponents
- // from channel values and updating parameters.
+ refSpotCoords.push_back(provider->posImage);
- std::array newExps;
- if (fnp->getFilmNegativeExponents(refSpotCoords[0], refSpotCoords[1], newExps)) {
+ if (refSpotCoords.size() == 2) {
+ // User has selected 2 reference gray spots. Calculating new exponents
+ // from channel values and updating parameters.
+
+ std::array newExps;
+
+ if (fnp->getFilmNegativeExponents(refSpotCoords[0], refSpotCoords[1], newExps)) {
+ disableListener();
+ // Leaving green exponent unchanged, setting red and blue exponents based on
+ // the ratios between newly calculated exponents.
+ redRatio->setValue(newExps[0] / newExps[1]);
+ blueRatio->setValue(newExps[2] / newExps[1]);
+ enableListener();
+
+ if (listener && getEnabled()) {
+ listener->panelChanged(
+ evFilmNegativeExponents,
+ Glib::ustring::compose(
+ "Ref=%1\nR=%2\nB=%3",
+ greenExp->getValue(),
+ redRatio->getValue(),
+ blueRatio->getValue()
+ )
+ );
+ }
+ }
+
+ switchOffEditMode();
+ }
+
+ } else if (filmBaseSpotButton->get_active()) {
+
+ std::array newBaseLev;
+
+ if (fnp->getRawSpotValues(provider->posImage, 32, newBaseLev)) {
disableListener();
- // Leaving green exponent unchanged, setting red and blue exponents based on
- // the ratios between newly calculated exponents.
- redRatio->setValue(newExps[0] / newExps[1]);
- blueRatio->setValue(newExps[2] / newExps[1]);
+
+ filmBaseValues = newBaseLev;
+
enableListener();
+ const Glib::ustring vs = formatBaseValues(filmBaseValues);
+
+ filmBaseValuesLabel->set_text(vs);
+
if (listener && getEnabled()) {
- listener->panelChanged(
- evFilmNegativeExponents,
- Glib::ustring::compose(
- "Ref=%1\nR=%2\nB=%3",
- greenExp->getValue(),
- redRatio->getValue(),
- blueRatio->getValue()
- )
- );
+ listener->panelChanged(evFilmBaseValues, vs);
}
}
@@ -292,11 +371,38 @@ void FilmNegative::switchOffEditMode()
refSpotCoords.clear();
unsubscribe();
spotbutton->set_active(false);
+ filmBaseSpotButton->set_active(false);
}
void FilmNegative::editToggled()
{
if (spotbutton->get_active()) {
+
+ filmBaseSpotButton->set_active(false);
+ refSpotCoords.clear();
+
+ subscribe();
+
+ int w, h;
+ getEditProvider()->getImageSize(w, h);
+
+ // Stick a dummy rectangle over the whole image in mouseOverGeometry.
+ // This is to make sure the getCursor() call is fired everywhere.
+ Rectangle* const imgRect = static_cast(mouseOverGeometry.at(0));
+ imgRect->setXYWH(0, 0, w, h);
+ } else {
+ refSpotCoords.clear();
+ unsubscribe();
+ }
+}
+
+void FilmNegative::baseSpotToggled()
+{
+ if (filmBaseSpotButton->get_active()) {
+
+ spotbutton->set_active(false);
+ refSpotCoords.clear();
+
subscribe();
int w, h;
diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h
index bca155ceb..0810a8c57 100644
--- a/rtgui/filmnegative.h
+++ b/rtgui/filmnegative.h
@@ -33,13 +33,15 @@ public:
virtual ~FilmNegProvider() = default;
virtual bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) = 0;
+ virtual bool getRawSpotValues(rtengine::Coord spot, int spotSize, std::array& rawValues) = 0;
};
class FilmNegative final :
public ToolParamBlock,
public AdjusterListener,
public FoldableToolPanel,
- public EditSubscriber
+ public EditSubscriber,
+ public rtengine::FilmNegListener
{
public:
FilmNegative();
@@ -53,6 +55,8 @@ public:
void adjusterChanged(Adjuster* a, double newval) override;
void enabledChanged() override;
+ void filmBaseValuesChanged(std::array rgb) override;
+
void setFilmNegProvider(FilmNegProvider* provider);
void setEditProvider(EditDataProvider* provider) override;
@@ -66,12 +70,16 @@ public:
private:
void editToggled();
+ void baseSpotToggled();
const rtengine::ProcEvent evFilmNegativeExponents;
const rtengine::ProcEvent evFilmNegativeEnabled;
+ const rtengine::ProcEvent evFilmBaseValues;
std::vector refSpotCoords;
+ std::array filmBaseValues;
+
FilmNegProvider* fnp;
Adjuster* const greenExp;
@@ -80,5 +88,9 @@ private:
Gtk::Grid* const spotgrid;
Gtk::ToggleButton* const spotbutton;
- sigc::connection spotConn;
+
+ Gtk::Label* const filmBaseLabel;
+ Gtk::Label* const filmBaseValuesLabel;
+ Gtk::ToggleButton* const filmBaseSpotButton;
+
};
diff --git a/rtgui/mydiagonalcurve.cc b/rtgui/mydiagonalcurve.cc
index ac7976b7e..ce6c6f3ec 100644
--- a/rtgui/mydiagonalcurve.cc
+++ b/rtgui/mydiagonalcurve.cc
@@ -323,7 +323,7 @@ void MyDiagonalCurve::draw (int handle)
// draw the grid lines:
cr->set_line_width (1.0 * s);
c = style->get_border_color(state);
- cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue());
+ cr->set_source_rgba (c.get_red(), c.get_green(), c.get_blue(), 0.3);
cr->set_antialias (Cairo::ANTIALIAS_NONE);
for (int i = 0; i <= 10; i++) {
diff --git a/rtgui/options.cc b/rtgui/options.cc
index 3cf0a9497..7ae6c24aa 100644
--- a/rtgui/options.cc
+++ b/rtgui/options.cc
@@ -597,6 +597,8 @@ void Options::setDefaults()
rtSettings.itcwb_forceextra = true;
rtSettings.itcwb_sizereference = 3;//between 1 and 5
rtSettings.itcwb_delta = 1;//between 0 and 5
+ rtSettings.itcwb_stdobserver10 = true;
+ rtSettings.itcwb_precis = 5;//3 or 5 or 9
rtSettings.protectred = 60;
rtSettings.protectredh = 0.3;
@@ -1513,6 +1515,10 @@ void Options::readFromFile(Glib::ustring fname)
rtSettings.itcwb_forceextra = keyFile.get_boolean("Color Management", "Itcwb_forceextra");
}
+ if (keyFile.has_key("Color Management", "Itcwb_stdobserver10")) {
+ rtSettings.itcwb_stdobserver10 = keyFile.get_boolean("Color Management", "Itcwb_stdobserver10");
+ }
+
if (keyFile.has_key("Color Management", "Itcwb_greenrange")) {
rtSettings.itcwb_greenrange = keyFile.get_integer("Color Management", "Itcwb_greenrange");
}
@@ -1529,6 +1535,9 @@ void Options::readFromFile(Glib::ustring fname)
rtSettings.itcwb_delta = keyFile.get_integer("Color Management", "Itcwb_delta");
}
+ if (keyFile.has_key("Color Management", "Itcwb_precis")) {
+ rtSettings.itcwb_precis = keyFile.get_integer("Color Management", "Itcwb_precis");
+ }
//if (keyFile.has_key ("Color Management", "Colortoningab")) rtSettings.colortoningab = keyFile.get_double("Color Management", "Colortoningab");
//if (keyFile.has_key ("Color Management", "Decaction")) rtSettings.decaction = keyFile.get_double("Color Management", "Decaction");
@@ -2201,6 +2210,8 @@ void Options::saveToFile(Glib::ustring fname)
keyFile.set_boolean("Color Management", "Itcwb_forceextra", rtSettings.itcwb_forceextra);
keyFile.set_integer("Color Management", "Itcwb_sizereference", rtSettings.itcwb_sizereference);
keyFile.set_integer("Color Management", "Itcwb_delta", rtSettings.itcwb_delta);
+ keyFile.set_boolean("Color Management", "Itcwb_stdobserver10", rtSettings.itcwb_stdobserver10);
+ keyFile.set_integer("Color Management", "Itcwb_precis", rtSettings.itcwb_precis);
//keyFile.set_double ("Color Management", "Colortoningab", rtSettings.colortoningab);
//keyFile.set_double ("Color Management", "Decaction", rtSettings.decaction);
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index c7ab5f1c5..511aefaa7 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -219,6 +219,7 @@ void ParamsEdited::set(bool v)
colorappearance.adaplum = v;
colorappearance.badpixsl = v;
colorappearance.wbmodel = v;
+ colorappearance.illum = v;
colorappearance.algo = v;
colorappearance.jlight = v;
@@ -474,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;
@@ -485,6 +492,10 @@ void ParamsEdited::set(bool v)
wavelet.bluemed = v;
wavelet.bluelow = v;
wavelet.lipst = v;
+ wavelet.ballum = v;
+ wavelet.balchrom = v;
+ wavelet.chromfi = v;
+ wavelet.chromco = v;
wavelet.mergeL = v;
wavelet.mergeC = v;
wavelet.softrad = v;
@@ -493,6 +504,7 @@ void ParamsEdited::set(bool v)
wavelet.ushamethod = v;
wavelet.avoid = v;
wavelet.showmask = v;
+ wavelet.oldsh = v;
wavelet.tmr = v;
wavelet.Lmethod = v;
wavelet.CLmethod = v;
@@ -508,9 +520,13 @@ void ParamsEdited::set(bool v)
wavelet.HSmethod = v;
wavelet.Dirmethod = v;
wavelet.sigma = v;
- wavelet.rescon = v;
+ wavelet.sigma = v;
+ wavelet.offset = v;
+ wavelet.lowthr = v;
wavelet.resconH = v;
wavelet.reschro = v;
+ wavelet.resblur = v;
+ wavelet.resblurc = v;
wavelet.tmrs = v;
wavelet.edgs = v;
wavelet.scale = v;
@@ -529,6 +545,7 @@ void ParamsEdited::set(bool v)
wavelet.chro = v;
wavelet.contrast = v;
wavelet.edgrad = v;
+ wavelet.edgeffect = v;
wavelet.edgval = v;
wavelet.edgthresh = v;
wavelet.thr = v;
@@ -540,11 +557,15 @@ void ParamsEdited::set(bool v)
wavelet.hllev = v;
wavelet.bllev = v;
wavelet.edgcont = v;
+ wavelet.chrwav = v;
+ wavelet.bluwav = v;
wavelet.level0noise = v;
wavelet.level1noise = v;
wavelet.level2noise = v;
wavelet.level3noise = v;
wavelet.ccwcurve = v;
+ wavelet.blcurve = v;
+ wavelet.opacityCurveSH = v;
wavelet.opacityCurveRG = v;
wavelet.opacityCurveBY = v;
wavelet.opacityCurveW = v;
@@ -564,9 +585,14 @@ void ParamsEdited::set(bool v)
wavelet.expcontrast = v;
wavelet.expchroma = v;
wavelet.expedge = v;
+ wavelet.expbl = v;
wavelet.expresid = v;
wavelet.exptoning = v;
wavelet.expnoise = v;
+ wavelet.labgridALow = v;
+ wavelet.labgridBLow = v;
+ wavelet.labgridAHigh = v;
+ wavelet.labgridBHigh = v;
for (int i = 0; i < 9; i++) {
wavelet.c[i] = v;
@@ -608,6 +634,7 @@ void ParamsEdited::set(bool v)
filmNegative.redRatio = v;
filmNegative.greenExp = v;
filmNegative.blueRatio = v;
+ filmNegative.baseValues = v;
raw.preprocessWB.mode = v;
exif = v;
@@ -813,6 +840,7 @@ void ParamsEdited::initFrom(const std::vector&
colorappearance.adaplum = colorappearance.adaplum && p.colorappearance.adaplum == other.colorappearance.adaplum;
colorappearance.badpixsl = colorappearance.badpixsl && p.colorappearance.badpixsl == other.colorappearance.badpixsl;
colorappearance.wbmodel = colorappearance.wbmodel && p.colorappearance.wbmodel == other.colorappearance.wbmodel;
+ colorappearance.illum = colorappearance.illum && p.colorappearance.illum == other.colorappearance.illum;
colorappearance.algo = colorappearance.algo && p.colorappearance.algo == other.colorappearance.algo;
colorappearance.jlight = colorappearance.jlight && p.colorappearance.jlight == other.colorappearance.jlight;
colorappearance.qbright = colorappearance.qbright && p.colorappearance.qbright == other.colorappearance.qbright;
@@ -1070,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;
@@ -1082,6 +1116,10 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.bluelow = wavelet.bluelow && p.wavelet.bluelow == other.wavelet.bluelow;
wavelet.lipst = wavelet.lipst && p.wavelet.lipst == other.wavelet.lipst;
wavelet.bluehigh = wavelet.bluehigh && p.wavelet.bluehigh == other.wavelet.bluehigh;
+ wavelet.ballum = wavelet.ballum && p.wavelet.ballum == other.wavelet.ballum;
+ wavelet.balchrom = wavelet.balchrom && p.wavelet.balchrom == other.wavelet.balchrom;
+ wavelet.chromfi = wavelet.chromfi && p.wavelet.chromfi == other.wavelet.chromfi;
+ wavelet.chromco = wavelet.chromco && p.wavelet.chromco == other.wavelet.chromco;
wavelet.mergeL = wavelet.mergeL && p.wavelet.mergeL == other.wavelet.mergeL;
wavelet.mergeC = wavelet.mergeC && p.wavelet.mergeC == other.wavelet.mergeC;
wavelet.softrad = wavelet.softrad && p.wavelet.softrad == other.wavelet.softrad;
@@ -1089,6 +1127,7 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.ushamethod = wavelet.ushamethod && p.wavelet.ushamethod == other.wavelet.ushamethod;
wavelet.avoid = wavelet.avoid && p.wavelet.avoid == other.wavelet.avoid;
wavelet.showmask = wavelet.showmask && p.wavelet.showmask == other.wavelet.showmask;
+ wavelet.oldsh = wavelet.oldsh && p.wavelet.oldsh == other.wavelet.oldsh;
wavelet.tmr = wavelet.tmr && p.wavelet.tmr == other.wavelet.tmr;
wavelet.Lmethod = wavelet.Lmethod && p.wavelet.Lmethod == other.wavelet.Lmethod;
wavelet.CLmethod = wavelet.CLmethod && p.wavelet.CLmethod == other.wavelet.CLmethod;
@@ -1104,9 +1143,13 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.HSmethod = wavelet.HSmethod && p.wavelet.HSmethod == other.wavelet.HSmethod;
wavelet.Dirmethod = wavelet.Dirmethod && p.wavelet.Dirmethod == other.wavelet.Dirmethod;
wavelet.sigma = wavelet.sigma && p.wavelet.sigma == other.wavelet.sigma;
+ wavelet.offset = wavelet.offset && p.wavelet.offset == other.wavelet.offset;
+ wavelet.lowthr = wavelet.lowthr && p.wavelet.lowthr == other.wavelet.lowthr;
wavelet.rescon = wavelet.rescon && p.wavelet.rescon == other.wavelet.rescon;
wavelet.resconH = wavelet.resconH && p.wavelet.resconH == other.wavelet.resconH;
wavelet.reschro = wavelet.reschro && p.wavelet.reschro == other.wavelet.reschro;
+ wavelet.resblur = wavelet.resblur && p.wavelet.resblur == other.wavelet.resblur;
+ wavelet.resblurc = wavelet.resblurc && p.wavelet.resblurc == other.wavelet.resblurc;
wavelet.tmrs = wavelet.tmrs && p.wavelet.tmrs == other.wavelet.tmrs;
wavelet.edgs = wavelet.edgs && p.wavelet.edgs == other.wavelet.edgs;
wavelet.scale = wavelet.scale && p.wavelet.scale == other.wavelet.scale;
@@ -1125,6 +1168,7 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.chro = wavelet.chro && p.wavelet.chro == other.wavelet.chro;
wavelet.contrast = wavelet.contrast && p.wavelet.contrast == other.wavelet.contrast;
wavelet.edgrad = wavelet.edgrad && p.wavelet.edgrad == other.wavelet.edgrad;
+ wavelet.edgeffect = wavelet.edgeffect && p.wavelet.edgeffect == other.wavelet.edgeffect;
wavelet.edgval = wavelet.edgval && p.wavelet.edgval == other.wavelet.edgval;
wavelet.edgthresh = wavelet.edgthresh && p.wavelet.edgthresh == other.wavelet.edgthresh;
wavelet.thr = wavelet.thr && p.wavelet.thr == other.wavelet.thr;
@@ -1135,6 +1179,8 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.hllev = wavelet.hllev && p.wavelet.hllev == other.wavelet.hllev;
wavelet.bllev = wavelet.bllev && p.wavelet.bllev == other.wavelet.bllev;
wavelet.edgcont = wavelet.edgcont && p.wavelet.edgcont == other.wavelet.edgcont;
+ wavelet.chrwav = wavelet.chrwav && p.wavelet.chrwav == other.wavelet.chrwav;
+ wavelet.bluwav = wavelet.bluwav && p.wavelet.bluwav == other.wavelet.bluwav;
wavelet.level0noise = wavelet.level0noise && p.wavelet.level0noise == other.wavelet.level0noise;
wavelet.level1noise = wavelet.level1noise && p.wavelet.level1noise == other.wavelet.level1noise;
wavelet.level2noise = wavelet.level2noise && p.wavelet.level2noise == other.wavelet.level2noise;
@@ -1142,6 +1188,8 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.pastlev = wavelet.pastlev && p.wavelet.pastlev == other.wavelet.pastlev;
wavelet.satlev = wavelet.satlev && p.wavelet.satlev == other.wavelet.satlev;
wavelet.ccwcurve = wavelet.ccwcurve && p.wavelet.ccwcurve == other.wavelet.ccwcurve;
+ wavelet.blcurve = wavelet.blcurve && p.wavelet.blcurve == other.wavelet.blcurve;
+ wavelet.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;
@@ -1154,11 +1202,16 @@ void ParamsEdited::initFrom(const std::vector&
wavelet.expcontrast = wavelet.expcontrast && p.wavelet.expcontrast == other.wavelet.expcontrast;
wavelet.expchroma = wavelet.expchroma && p.wavelet.expchroma == other.wavelet.expchroma;
wavelet.expedge = wavelet.expedge && p.wavelet.expedge == other.wavelet.expedge;
+ wavelet.expbl = wavelet.expbl && p.wavelet.expbl == other.wavelet.expbl;
wavelet.expresid = wavelet.expresid && p.wavelet.expresid == other.wavelet.expresid;
wavelet.expfinal = wavelet.expfinal && p.wavelet.expfinal == other.wavelet.expfinal;
wavelet.exptoning = wavelet.exptoning && p.wavelet.exptoning == other.wavelet.exptoning;
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];
@@ -1196,6 +1249,9 @@ void ParamsEdited::initFrom(const std::vector&
filmNegative.redRatio = filmNegative.redRatio && p.filmNegative.redRatio == other.filmNegative.redRatio;
filmNegative.greenExp = filmNegative.greenExp && p.filmNegative.greenExp == other.filmNegative.greenExp;
filmNegative.blueRatio = filmNegative.blueRatio && p.filmNegative.blueRatio == other.filmNegative.blueRatio;
+ 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???
@@ -2012,6 +2068,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.colorappearance.wbmodel = mods.colorappearance.wbmodel;
}
+ if (colorappearance.illum) {
+ toEdit.colorappearance.illum = mods.colorappearance.illum;
+ }
+
if (colorappearance.algo) {
toEdit.colorappearance.algo = mods.colorappearance.algo;
}
@@ -2853,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;
}
@@ -2861,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;
}
@@ -2905,6 +3005,22 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.bluelow = mods.wavelet.bluelow;
}
+ if (wavelet.ballum) {
+ toEdit.wavelet.ballum = mods.wavelet.ballum;
+ }
+
+ if (wavelet.balchrom) {
+ toEdit.wavelet.balchrom = mods.wavelet.balchrom;
+ }
+
+ if (wavelet.chromfi) {
+ toEdit.wavelet.chromfi = mods.wavelet.chromfi;
+ }
+
+ if (wavelet.chromco) {
+ toEdit.wavelet.chromco = mods.wavelet.chromco;
+ }
+
if (wavelet.mergeL) {
toEdit.wavelet.mergeL = mods.wavelet.mergeL;
}
@@ -2941,6 +3057,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.showmask = mods.wavelet.showmask;
}
+ if (wavelet.oldsh) {
+ toEdit.wavelet.oldsh = mods.wavelet.oldsh;
+ }
+
if (wavelet.tmr) {
toEdit.wavelet.tmr = mods.wavelet.tmr;
}
@@ -3033,6 +3153,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.edgcont = mods.wavelet.edgcont;
}
+ if (wavelet.chrwav) {
+ toEdit.wavelet.chrwav = mods.wavelet.chrwav;
+ }
+
+ if (wavelet.bluwav) {
+ toEdit.wavelet.bluwav = mods.wavelet.bluwav;
+ }
+
if (wavelet.level0noise) {
toEdit.wavelet.level0noise = mods.wavelet.level0noise;
}
@@ -3061,6 +3189,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve;
}
+ if (wavelet.blcurve) {
+ toEdit.wavelet.blcurve = mods.wavelet.blcurve;
+ }
+
+ if (wavelet.opacityCurveSH) {
+ toEdit.wavelet.opacityCurveSH = mods.wavelet.opacityCurveSH;
+ }
+
if (wavelet.opacityCurveRG) {
toEdit.wavelet.opacityCurveRG = mods.wavelet.opacityCurveRG;
}
@@ -3102,6 +3238,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.expedge = mods.wavelet.expedge;
}
+ if (wavelet.expbl) {
+ toEdit.wavelet.expbl = mods.wavelet.expbl;
+ }
+
if (wavelet.expresid) {
toEdit.wavelet.expresid = mods.wavelet.expresid;
}
@@ -3158,6 +3298,26 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.sigma = mods.wavelet.sigma;
}
+ if (wavelet.offset) {
+ toEdit.wavelet.offset = mods.wavelet.offset;
+ }
+
+ if (wavelet.lowthr) {
+ toEdit.wavelet.lowthr = mods.wavelet.lowthr;
+ }
+
+ if (wavelet.resblur) {
+ toEdit.wavelet.resblur = mods.wavelet.resblur;
+ }
+
+ if (wavelet.edgeffect) {
+ toEdit.wavelet.edgeffect = mods.wavelet.edgeffect;
+ }
+
+ if (wavelet.resblurc) {
+ toEdit.wavelet.resblurc = mods.wavelet.resblurc;
+ }
+
if (wavelet.resconH) {
toEdit.wavelet.resconH = dontforceSet && options.baBehav[ADDSET_WA_RESCONH] ? toEdit.wavelet.resconH + mods.wavelet.resconH : mods.wavelet.resconH;
}
@@ -3342,6 +3502,12 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.filmNegative.blueRatio = mods.filmNegative.blueRatio;
}
+ if (filmNegative.baseValues) {
+ toEdit.filmNegative.redBase = mods.filmNegative.redBase;
+ toEdit.filmNegative.greenBase = mods.filmNegative.greenBase;
+ toEdit.filmNegative.blueBase = mods.filmNegative.blueBase;
+ }
+
if (raw.preprocessWB.mode) {
toEdit.raw.preprocessWB.mode = mods.raw.preprocessWB.mode;
}
@@ -3392,7 +3558,7 @@ bool RetinexParamsEdited::isUnchanged() const
bool FilmNegativeParamsEdited::isUnchanged() const
{
- return enabled && redRatio && greenExp && blueRatio;
+ return enabled && redRatio && greenExp && blueRatio && baseValues;
}
bool CaptureSharpeningParamsEdited::isUnchanged() const
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index 8b4cf1241..306b25ae7 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -275,6 +275,7 @@ struct ColorAppearanceParamsEdited {
bool ybscen;
bool badpixsl;
bool wbmodel;
+ bool illum;
bool algo;
bool jlight;
bool qbright;
@@ -498,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;
@@ -507,6 +514,7 @@ struct WaveletParamsEdited {
bool ushamethod;
bool avoid;
bool showmask;
+ bool oldsh;
bool tmr;
bool c[9];
bool ch[9];
@@ -524,9 +532,13 @@ struct WaveletParamsEdited {
bool daubcoeffmethod;
bool Dirmethod;
bool sigma;
+ bool offset;
+ bool lowthr;
bool rescon;
bool resconH;
bool reschro;
+ bool resblur;
+ bool resblurc;
bool tmrs;
bool edgs;
bool scale;
@@ -545,6 +557,7 @@ struct WaveletParamsEdited {
bool chroma;
bool contrast;
bool edgrad;
+ bool edgeffect;
bool edgval;
bool edgthresh;
bool thr;
@@ -556,11 +569,15 @@ struct WaveletParamsEdited {
bool hllev;
bool bllev;
bool edgcont;
+ bool chrwav;
+ bool bluwav;
bool level0noise;
bool level1noise;
bool level2noise;
bool level3noise;
bool ccwcurve;
+ bool blcurve;
+ bool opacityCurveSH;
bool opacityCurveBY;
bool opacityCurveRG;
bool opacityCurveW;
@@ -576,6 +593,10 @@ struct WaveletParamsEdited {
bool bluemed;
bool greenhigh;
bool bluehigh;
+ bool ballum;
+ bool balchrom;
+ bool chromfi;
+ bool chromco;
bool mergeL;
bool mergeC;
bool softrad;
@@ -583,11 +604,17 @@ struct WaveletParamsEdited {
bool expcontrast;
bool expchroma;
bool expedge;
+ bool expbl;
bool expresid;
bool expfinal;
bool exptoning;
bool expnoise;
bool expclari;
+ bool labgridALow;
+ bool labgridBLow;
+ bool labgridAHigh;
+ bool labgridBHigh;
+
};
struct DirPyrEqualizerParamsEdited {
@@ -720,6 +747,7 @@ struct FilmNegativeParamsEdited {
bool redRatio;
bool greenExp;
bool blueRatio;
+ bool baseValues;
bool isUnchanged() const;
};
diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc
index 8c49323c5..c2f3340e5 100644
--- a/rtgui/partialpastedlg.cc
+++ b/rtgui/partialpastedlg.cc
@@ -993,6 +993,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
filterPE.filmNegative.redRatio = falsePE.filmNegative.redRatio;
filterPE.filmNegative.greenExp = falsePE.filmNegative.greenExp;
filterPE.filmNegative.blueRatio = falsePE.filmNegative.blueRatio;
+ filterPE.filmNegative.baseValues = falsePE.filmNegative.baseValues;
}
if (!captureSharpening->get_active ()) {
diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h
index 89f93ed44..6a670733b 100644
--- a/rtgui/ppversion.h
+++ b/rtgui/ppversion.h
@@ -1,11 +1,13 @@
#pragma once
// This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes
-#define PPVERSION 346
+#define PPVERSION 347
#define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified
/*
Log of version changes
+ 347 2019-11-17
+ added special values in filmNegative for backwards compatibility with previous channel scaling method
346 2019-01-01
changed microcontrast uniformity
345 2018-10-21
diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc
index 083444342..5268948cc 100644
--- a/rtgui/preferences.cc
+++ b/rtgui/preferences.cc
@@ -778,7 +778,7 @@ Gtk::Widget* Preferences::getColorManPanel ()
const std::vector profiles = rtengine::ICCStore::getInstance ()->getProfiles (rtengine::ICCStore::ProfileType::MONITOR);
- for (const auto profile : profiles) {
+ for (const auto& profile : profiles) {
if (profile.find("file:") != 0) {
std::string fileis_RTv4 = profile.substr(0, 4);
@@ -847,7 +847,7 @@ Gtk::Widget* Preferences::getColorManPanel ()
const std::vector prtprofiles = rtengine::ICCStore::getInstance ()->getProfiles (rtengine::ICCStore::ProfileType::PRINTER);
- for (const auto prtprofile : prtprofiles) {
+ for (const auto& prtprofile : prtprofiles) {
prtProfile->append (prtprofile);
}
diff --git a/rtgui/profilestorecombobox.cc b/rtgui/profilestorecombobox.cc
index bb294189f..a6085e7a9 100644
--- a/rtgui/profilestorecombobox.cc
+++ b/rtgui/profilestorecombobox.cc
@@ -182,7 +182,7 @@ Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry (const ProfileStoreEntry *p
Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, const Glib::ustring &name) const
{
- for (const auto iter : childs) {
+ for (const auto& iter : childs) {
const Gtk::TreeModel::Row row = *iter;
// Hombre: is there a smarter way of knowing if this row has childs?
const ProfileStoreEntry *pse = row[methodColumns.profileStoreEntry];
@@ -309,7 +309,7 @@ Gtk::TreeIter ProfileStoreComboBox::getRowFromLabel (const Glib::ustring &name)
const Gtk::TreeModel::Children childs = refTreeModel->children();
if (!name.empty()) {
- for (const auto iter : childs) {
+ for (const auto& iter : childs) {
const Gtk::TreeModel::Row currRow = *iter;
const ProfileStoreEntry *pse = currRow[methodColumns.profileStoreEntry];
diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc
index 8e7ed8071..0237a0917 100644
--- a/rtgui/toolpanelcoord.cc
+++ b/rtgui/toolpanelcoord.cc
@@ -614,6 +614,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool
ipc->setSizeListener (crop);
ipc->setSizeListener (resize);
ipc->setImageTypeListener (this);
+ ipc->setFilmNegListener (filmNegative);
flatfield->setShortcutPath (Glib::path_get_dirname (ipc->getInitialImage()->getFileName()));
icm->setRawMeta (raw, (const rtengine::FramesData*)pMetaData);
@@ -1078,3 +1079,8 @@ bool ToolPanelCoordinator::getFilmNegativeExponents(rtengine::Coord spotA, rteng
{
return ipc && ipc->getFilmNegativeExponents(spotA.x, spotA.y, spotB.x, spotB.y, newExps);
}
+
+bool ToolPanelCoordinator::getRawSpotValues(rtengine::Coord spot, int spotSize, std::array& rawValues)
+{
+ return ipc && ipc->getRawSpotValues(spot.x, spot.y, spotSize, rawValues);
+}
\ No newline at end of file
diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h
index e61d1a12e..9773a2407 100644
--- a/rtgui/toolpanelcoord.h
+++ b/rtgui/toolpanelcoord.h
@@ -299,6 +299,7 @@ public:
// FilmNegProvider interface
bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) override;
+ bool getRawSpotValues(rtengine::Coord spot, int spotSize, std::array& rawValues) override;
// rotatelistener interface
void straightenRequested () override;
diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc
index 7d9a65f2a..53c7ef90b 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,7 +63,9 @@ 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)),
curveEditorGAM(new CurveEditorGroup(options.lastWaveletCurvesDir)),
separatorNeutral(Gtk::manage(new Gtk::HSeparator())),
@@ -79,11 +82,17 @@ Wavelet::Wavelet() :
avoid(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_AVOID")))),
tmr(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_BALCHRO")))),
showmask(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_SHOWMASK")))),
+ oldsh(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_OLDSH")))),
neutralchButton(Gtk::manage(new Gtk::Button(M("TP_WAVELET_NEUTRAL")))),
- sigma(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMA"), 0.2, 2.5, 0.01, 1.))),
- rescon(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCON"), 0, 100, 1, 0))),
- resconH(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCONH"), 0, 100, 1, 0))),
+ sigma(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGMA"), 0.05, 2.5, 0.01, 1.))),
+ offset(Gtk::manage(new Adjuster(M("TP_WAVELET_WAVOFFSET"), 0.33, 1.66, 0.01, 1., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))),
+ lowthr(Gtk::manage(new Adjuster(M("TP_WAVELET_WAVLOWTHR"), 20., 100., 0.5, 40.))),
+ rescon(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCON"), -100, 100, 1, 0))),
+ resconH(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCONH"), -100, 100, 1, 0))),
reschro(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0))),
+ resblur(Gtk::manage(new Adjuster(M("TP_WAVELET_RESBLUR"), 0, 100, 1, 0))),
+ resblurc(Gtk::manage(new Adjuster(M("TP_WAVELET_RESBLURC"), 0, 100, 1, 0))),
+ bluwav(Gtk::manage(new Adjuster(M("TP_WAVELET_BLUWAV"), 0.05, 2.5, 0.5, 1.))),
tmrs(Gtk::manage(new Adjuster(M("TP_WAVELET_TMSTRENGTH"), -1.0, 2.0, 0.01, 0.0))),
edgs(Gtk::manage(new Adjuster(M("TP_WAVELET_TMEDGS"), 0.1, 4.0, 0.01, 1.4))),
scale(Gtk::manage(new Adjuster(M("TP_WAVELET_TMSCALE"), 0.1, 10.0, 0.01, 1.0))),
@@ -99,11 +108,18 @@ Wavelet::Wavelet() :
radius(Gtk::manage(new Adjuster(M("TP_WAVELET_RADIUS"), 0, 100, 1, 40))),
skinprotect(Gtk::manage(new Adjuster(M("TP_WAVELET_SKIN"), -100, 100, 1, 0.))),
edgrad(Gtk::manage(new Adjuster(M("TP_WAVELET_EDRAD"), 0, 100, 1, 15))),
+ edgeffect(Gtk::manage(new Adjuster(M("TP_WAVELET_EDEFFECT"), 0.05, 2.5, 0.01, 1.))),
edgval(Gtk::manage(new Adjuster(M("TP_WAVELET_EDVAL"), 0, 100, 1, 0))),
edgthresh(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGTHRESH"), -50, 100, 1, 10))),
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))),
@@ -116,16 +132,22 @@ 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))),
edgesensi(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGESENSI"), 0, 100, 1, 60))),
edgeampli(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEAMPLI"), 0, 100, 1, 10))),
+ ballum(Gtk::manage(new Adjuster(M("TP_WAVELET_BALLUM"), -2., 10., 0.5, 7., Gtk::manage(new RTImage("circle-white-small.png")), Gtk::manage(new RTImage("circle-black-small.png"))))),
+ balchrom(Gtk::manage(new Adjuster(M("TP_WAVELET_BALCHROM"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-red-small.png"))))),
+ chromfi(Gtk::manage(new Adjuster(M("TP_WAVELET_CHROMFI"), 0.0, 150., 0.01, 0.))),
+ chromco(Gtk::manage(new Adjuster(M("TP_WAVELET_CHROMCO"), 0, 100., 0.01, 0.))),
mergeL(Gtk::manage(new Adjuster(M("TP_WAVELET_MERGEL"), -50, 100, 1, 40))),
mergeC(Gtk::manage(new Adjuster(M("TP_WAVELET_MERGEC"), -50, 100, 1, 20))),
softrad(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 100., 0.5, 0.))),
softradend(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 100., 0.5, 0.))),
+ chrwav(Gtk::manage(new Adjuster(M("TP_WAVELET_CHRWAV"), 0., 100., 0.5, 0.))),
Lmethod(Gtk::manage(new MyComboBoxText())),
CHmethod(Gtk::manage(new MyComboBoxText())),
CHSLmethod(Gtk::manage(new MyComboBoxText())),
@@ -144,7 +166,14 @@ Wavelet::Wavelet() :
chanMixerHLFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_HIGHLIGHT")))),
chanMixerMidFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_MIDTONES")))),
chanMixerShadowsFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_SHADOWS")))),
+ shFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_SHFRAME")))),
+ contFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_CONTFRAME")))),
+ blurFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_BLURFRAME")))),
chromaFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_CHROMAFRAME")))),
+ 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") + ":"))),
@@ -159,6 +188,7 @@ Wavelet::Wavelet() :
expsettings(Gtk::manage(new MyExpander(false, M("TP_WAVELET_SETTINGS")))),
exptoning(Gtk::manage(new MyExpander(true, M("TP_WAVELET_TON")))),
expclari(Gtk::manage(new MyExpander(true, M("TP_WAVELET_CLARI")))),
+ expbl(Gtk::manage(new MyExpander(true, M("TP_WAVELET_BL")))),
neutrHBox(Gtk::manage(new Gtk::HBox())),
usharpHBox(Gtk::manage(new Gtk::HBox()))
{
@@ -166,6 +196,10 @@ Wavelet::Wavelet() :
auto m = ProcEventMapper::getInstance();
EvWavenaclari = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCLARI");
EvWavushamet = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVUSHAMET");
+ EvWavballum = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVBALLUM");
+ EvWavbalchrom = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVBALCHROM");
+ EvWavchromfi = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCHROMFI");
+ EvWavchromco = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVCHROMCO");
EvWavmergeL = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVMERGEL");
EvWavmergeC = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVMERGEC");
EvWavsoftrad = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSOFTRAD");
@@ -175,6 +209,26 @@ Wavelet::Wavelet() :
EvWavscale = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSCALE");
EvWavradius = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVRADIUS");
EvWavsigma = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSIGMA");
+ EvWavenabl = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVBL");
+ EvWavchrwav = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_chrwav");
+ EvWavoldsh = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVOLDSH");
+ EvWavoffset = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVOFFSET");
+ EvWavlowthr = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVLOWTHR");
+ EvWavbluwav = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLUWAV");
+ EvWavblshape = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLSHAPE");
+ EvWavresblur = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLURWAV");
+ EvWavresblurc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_BLURCWAV");
+ 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));
@@ -193,6 +247,9 @@ Wavelet::Wavelet() :
expedge->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expedge));
enableEdgeConn = expedge->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Wavelet::enableToggled), expedge));
+ expbl->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expbl));
+ enabletmConn = expbl->signal_enabled_toggled().connect(sigc::bind(sigc::mem_fun(this, &Wavelet::enableToggled), expbl));
+
expgamut->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expgamut));
expresid->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Wavelet::foldAllButMe), expresid));
@@ -214,7 +271,7 @@ Wavelet::Wavelet() :
Tilesmethod->append(M("TP_WAVELET_TILESFULL"));
Tilesmethod->append(M("TP_WAVELET_TILESBIG"));
- Tilesmethod->append(M("TP_WAVELET_TILESLIT"));
+// Tilesmethod->append(M("TP_WAVELET_TILESLIT"));
Tilesmethodconn = Tilesmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::TilesmethodChanged));
Tilesmethod->set_tooltip_text(M("TP_WAVELET_TILES_TOOLTIP"));
Gtk::HBox* const tilesizeHBox = Gtk::manage(new Gtk::HBox());
@@ -326,12 +383,21 @@ Wavelet::Wavelet() :
correction[i]->setAdjusterListener(this);
levBox->pack_start(*correction[i]);
}
+ levBox->pack_start(*sup);
+ sup->setAdjusterListener(this);
+ Gtk::HSeparator* const separatorcont = Gtk::manage(new Gtk::HSeparator());
+ levBox->pack_start(*separatorcont);
sigma->setAdjusterListener(this);
levBox->pack_start(*sigma, Gtk::PACK_SHRINK);
+ offset->setAdjusterListener(this);
+ levBox->pack_start(*offset, Gtk::PACK_SHRINK);
+ sigma->set_tooltip_text(M("TP_WAVELET_SIGMA_TOOLTIP"));
+ offset->set_tooltip_text(M("TP_WAVELET_OFFSET_TOOLTIP"));
+ lowthr->setAdjusterListener(this);
+ lowthr->set_tooltip_text(M("TP_WAVELET_LOWTHR_TOOLTIP"));
+ levBox->pack_start(*lowthr, Gtk::PACK_SHRINK);
- levBox->pack_start(*sup);
- sup->setAdjusterListener(this);
wavLabels->show();
levBox->pack_start(*wavLabels);
@@ -359,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);
@@ -407,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));
@@ -440,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);
@@ -459,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();
@@ -483,12 +589,28 @@ Wavelet::Wavelet() :
level3noise->setAdjusterListener(this);
level3noise->setUpdatePolicy(RTUP_DYNAMIC);
+ ballum->setAdjusterListener(this);
+ noiseBox->pack_start(*ballum);
noiseBox->pack_start(*level0noise, Gtk::PACK_SHRINK, 0);
noiseBox->pack_start(*level1noise, Gtk::PACK_SHRINK, 0);
noiseBox->pack_start(*level2noise, Gtk::PACK_SHRINK, 0);
noiseBox->pack_start(*level3noise, Gtk::PACK_SHRINK, 0);
+ balchrom->setAdjusterListener(this);
+ chromfi->setAdjusterListener(this);
+ chromco->setAdjusterListener(this);
+
+ chroFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const chroBox = Gtk::manage(new ToolParamBlock());
+ chroBox->pack_start(*balchrom);
+ chroBox->pack_start(*chromfi);
+ chroBox->pack_start(*chromco);
+ chroFrame->add(*chroBox);
+ noiseBox->pack_start(*chroFrame);
+ noiseBox->set_tooltip_text(M("TP_WAVELET_NOISE_TOOLTIP"));
+
+
//Clarity
mergeL->setAdjusterListener(this);
mergeC->setAdjusterListener(this);
@@ -517,6 +639,10 @@ Wavelet::Wavelet() :
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);
edgrad->set_tooltip_markup(M("TP_WAVELET_EDRAD_TOOLTIP"));
@@ -623,6 +749,30 @@ Wavelet::Wavelet() :
edgBox->pack_start(*ctboxES);
+//Blur Wavelet
+ ToolParamBlock* const blBox = Gtk::manage(new ToolParamBlock());
+
+ curveEditorbl->setCurveListener(this);
+
+ blshape = static_cast(curveEditorbl->addCurve(CT_Flat, "", nullptr, false, false));
+
+ blshape->setIdentityValue(0.);
+ blshape->setResetCurve(FlatCurveType(default_params.blcurve.at(0)), default_params.blcurve);
+ blshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CC_TOOLTIP"));
+
+ curveEditorbl->curveListComplete();
+ curveEditorbl->show();
+
+ blBox->pack_start(*bluwav);
+ bluwav->setAdjusterListener(this);
+ blBox->pack_start(*curveEditorbl, Gtk::PACK_SHRINK, 4);
+
+
+ chrwav->setAdjusterListener(this);
+ blBox->pack_start(*chrwav);
+
+
+
// Gamut
ToolParamBlock* const conBox = Gtk::manage(new ToolParamBlock());
@@ -675,27 +825,47 @@ Wavelet::Wavelet() :
// Residual Image
ToolParamBlock* const resBox = Gtk::manage(new ToolParamBlock());
+ oldsh->set_active(true);
+ oldshConn = oldsh->signal_toggled().connect(sigc::mem_fun(*this, &Wavelet::oldshToggled));
+
rescon->setAdjusterListener(this);
- resBox->pack_start(*rescon, Gtk::PACK_SHRINK);
- resBox->pack_start(*thr);
thr->setAdjusterListener(this);
resconH->setAdjusterListener(this);
- resBox->pack_start(*resconH, Gtk::PACK_SHRINK);
thrH->setAdjusterListener(this);
- resBox->pack_start(*thrH, Gtk::PACK_SHRINK);
radius->setAdjusterListener(this);
- resBox->pack_start(*radius, Gtk::PACK_SHRINK);
+ radius->hide();
+
+ shFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const shBox = Gtk::manage(new ToolParamBlock());
+ shBox->pack_start(*oldsh);
+ shBox->pack_start(*rescon, Gtk::PACK_SHRINK);
+ shBox->pack_start(*thr);
+ shBox->pack_start(*resconH, Gtk::PACK_SHRINK);
+ shBox->pack_start(*thrH, Gtk::PACK_SHRINK);
+ shBox->pack_start(*radius, Gtk::PACK_SHRINK);
+ shFrame->add(*shBox);
+ resBox->pack_start(*shFrame);
+
contrast->set_tooltip_text(M("TP_WAVELET_CONTRA_TOOLTIP"));
contrast->setAdjusterListener(this);
- resBox->pack_start(*contrast); //keep the possibility to reinstall
reschro->setAdjusterListener(this);
+ resblur->setAdjusterListener(this);
+ resblurc->setAdjusterListener(this);
+
+ blurFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const blurBox = Gtk::manage(new ToolParamBlock());
+ blurBox->pack_start(*resblur);
+ blurBox->pack_start(*resblurc);
+ blurFrame->add(*blurBox);
+ 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());
@@ -708,36 +878,42 @@ Wavelet::Wavelet() :
Gtk::HBox* const ctboxTM = Gtk::manage(new Gtk::HBox());
ctboxTM->pack_start(*labmTM, Gtk::PACK_SHRINK, 1);
- Gtk::HSeparator* const separatorR0 = Gtk::manage(new Gtk::HSeparator());
- resBox->pack_start(*separatorR0, Gtk::PACK_SHRINK, 2);
+// Gtk::HSeparator* const separatorR0 = Gtk::manage(new Gtk::HSeparator());
+// resBox->pack_start(*separatorR0, Gtk::PACK_SHRINK, 2);
TMmethod->append(M("TP_WAVELET_COMPCONT"));
TMmethod->append(M("TP_WAVELET_COMPTM"));
TMmethodconn = TMmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::TMmethodChanged));
ctboxTM->pack_start(*TMmethod);
- resBox->pack_start(*ctboxTM);
tmrs->set_tooltip_text(M("TP_WAVELET_TMSTRENGTH_TOOLTIP"));
- resBox->pack_start(*tmrs);
tmrs->setAdjusterListener(this);
gamma->set_tooltip_text(M("TP_WAVELET_COMPGAMMA_TOOLTIP"));
- resBox->pack_start(*gamma);
gamma->setAdjusterListener(this);
//edgs->set_tooltip_text(M("TP_WAVELET_TMEDGS_TOOLTIP"));
- resBox->pack_start(*edgs);
edgs->setAdjusterListener(this);
//scale->set_tooltip_text(M("TP_WAVELET_TMSCALE_TOOLTIP"));
- resBox->pack_start(*scale);
scale->setAdjusterListener(this);
- Gtk::HSeparator* const separatorR1 = Gtk::manage(new Gtk::HSeparator());
- resBox->pack_start(*separatorR1, Gtk::PACK_SHRINK, 2);
+ contFrame->set_label_align(0.025, 0.5);
+ ToolParamBlock* const contBox = Gtk::manage(new ToolParamBlock());
+ contBox->pack_start(*contrast); //keep the possibility to reinstall
+ contBox->pack_start(*ctboxTM);
+ contBox->pack_start(*tmrs);
+ contBox->pack_start(*gamma);
+ contBox->pack_start(*edgs);
+ contBox->pack_start(*scale);
+ contFrame->add(*contBox);
+ resBox->pack_start(*contFrame);
+
+// Gtk::HSeparator* const separatorR1 = Gtk::manage(new Gtk::HSeparator());
+// resBox->pack_start(*separatorR1, Gtk::PACK_SHRINK, 2);
hueskin2->set_tooltip_markup(M("TP_WAVELET_HUESKY_TOOLTIP"));
hueskin2->setBgGradient(milestones);
@@ -751,6 +927,7 @@ Wavelet::Wavelet() :
const std::vector milestones3 = makeWholeHueRange();
curveEditorRES->setCurveListener(this);
+ resBox->pack_start(*blurFrame);
resBox->pack_start(*chromaFrame);
hhshape = static_cast(curveEditorRES->addCurve(CT_Flat, M("TP_WAVELET_CURVEEDITOR_HH")));
@@ -864,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);
@@ -873,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();
@@ -891,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);
@@ -939,6 +1126,10 @@ Wavelet::Wavelet() :
expedge->setLevel(2);
pack_start(*expedge);
+ expbl->add(*blBox, false);
+ expbl->setLevel(2);
+ pack_start(*expbl);
+
expclari->add(*clariBox, false);
expclari->setLevel(2);
pack_start(*expclari);
@@ -958,7 +1149,9 @@ Wavelet::~Wavelet()
idle_register.destroy();
delete opaCurveEditorG;
+ delete curveEditorC;
delete opacityCurveEditorG;
+ delete curveEditorbl;
delete CCWcurveEditorG;
delete curveEditorRES;
delete curveEditorGAM;
@@ -1004,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)
{
@@ -1145,8 +1345,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
Tilesmethod->set_active(0);
} else if (pp->wavelet.Tilesmethod == "big") {
Tilesmethod->set_active(1);
- } else if (pp->wavelet.Tilesmethod == "lit") {
- Tilesmethod->set_active(2);
+// } else if (pp->wavelet.Tilesmethod == "lit") {
+// Tilesmethod->set_active(2);
}
//daubcoeffmethod->set_active (4);
@@ -1177,7 +1377,9 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
Lmethod->set_active(selectedLevel == -1 ? 4 : selectedLevel);
ccshape->setCurve(pp->wavelet.ccwcurve);
+ blshape->setCurve(pp->wavelet.blcurve);
opacityShapeRG->setCurve(pp->wavelet.opacityCurveRG);
+ opacityShapeSH->setCurve(pp->wavelet.opacityCurveSH);
opacityShapeBY->setCurve(pp->wavelet.opacityCurveBY);
opacityShape->setCurve(pp->wavelet.opacityCurveW);
opacityShapeWL->setCurve(pp->wavelet.opacityCurveWL);
@@ -1187,6 +1389,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
expcontrast->setEnabled(pp->wavelet.expcontrast);
expchroma->setEnabled(pp->wavelet.expchroma);
expedge->setEnabled(pp->wavelet.expedge);
+ expbl->setEnabled(pp->wavelet.expbl);
expresid->setEnabled(pp->wavelet.expresid);
expfinal->setEnabled(pp->wavelet.expfinal);
exptoning->setEnabled(pp->wavelet.exptoning);
@@ -1200,6 +1403,9 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
showmaskConn.block(true);
showmask->set_active(pp->wavelet.showmask);
showmaskConn.block(false);
+ oldshConn.block(true);
+ oldsh->set_active(pp->wavelet.oldsh);
+ oldshConn.block(false);
tmrConn.block(true);
tmr->set_active(pp->wavelet.tmr);
tmrConn.block(false);
@@ -1230,11 +1436,16 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
lastlipst = pp->wavelet.lipst;
lastavoid = pp->wavelet.avoid;
lastshowmask = pp->wavelet.showmask;
+ lastoldsh = pp->wavelet.oldsh;
lasttmr = pp->wavelet.tmr;
sigma->setValue(pp->wavelet.sigma);
+ offset->setValue(pp->wavelet.offset);
+ lowthr->setValue(pp->wavelet.lowthr);
rescon->setValue(pp->wavelet.rescon);
resconH->setValue(pp->wavelet.resconH);
reschro->setValue(pp->wavelet.reschro);
+ resblur->setValue(pp->wavelet.resblur);
+ resblurc->setValue(pp->wavelet.resblurc);
tmrs->setValue(pp->wavelet.tmrs);
edgs->setValue(pp->wavelet.edgs);
scale->setValue(pp->wavelet.scale);
@@ -1246,6 +1457,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
chro->setValue(pp->wavelet.chro);
contrast->setValue(pp->wavelet.contrast);
edgrad->setValue(pp->wavelet.edgrad);
+ edgeffect->setValue(pp->wavelet.edgeffect);
edgval->setValue(pp->wavelet.edgval);
edgthresh->setValue(pp->wavelet.edgthresh);
thr->setValue(pp->wavelet.thr);
@@ -1266,6 +1478,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
pastlev->setValue(pp->wavelet.pastlev);
satlev->setValue(pp->wavelet.satlev);
edgcont->setValue(pp->wavelet.edgcont);
+ chrwav->setValue(pp->wavelet.chrwav);
+ bluwav->setValue(pp->wavelet.bluwav);
greenlow->setValue(pp->wavelet.greenlow);
bluelow->setValue(pp->wavelet.bluelow);
@@ -1277,7 +1491,12 @@ 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);
+ chromfi->setValue(pp->wavelet.chromfi);
+ chromco->setValue(pp->wavelet.chromco);
level0noise->setValue(pp->wavelet.level0noise);
level1noise->setValue(pp->wavelet.level1noise);
level2noise->setValue(pp->wavelet.level2noise);
@@ -1285,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]);
@@ -1360,18 +1585,22 @@ 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);
+ blshape->setUnChanged(!pedited->wavelet.blcurve);
expcontrast->set_inconsistent(!pedited->wavelet.expcontrast);
expchroma->set_inconsistent(!pedited->wavelet.expchroma);
expedge->set_inconsistent(!pedited->wavelet.expedge);
+ expbl->set_inconsistent(!pedited->wavelet.expbl);
expresid->set_inconsistent(!pedited->wavelet.expresid);
expfinal->set_inconsistent(!pedited->wavelet.expfinal);
expclari->set_inconsistent(!pedited->wavelet.expclari);
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);
@@ -1380,12 +1609,17 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
clshape->setUnChanged(!pedited->wavelet.wavclCurve);
avoid->set_inconsistent(!pedited->wavelet.avoid);
showmask->set_inconsistent(!pedited->wavelet.showmask);
+ oldsh->set_inconsistent(!pedited->wavelet.oldsh);
tmr->set_inconsistent(!pedited->wavelet.tmr);
edgthresh->setEditedState(pedited->wavelet.edgthresh ? Edited : UnEdited);
rescon->setEditedState(pedited->wavelet.rescon ? Edited : UnEdited);
sigma->setEditedState(pedited->wavelet.sigma ? Edited : UnEdited);
+ offset->setEditedState(pedited->wavelet.offset ? Edited : UnEdited);
+ lowthr->setEditedState(pedited->wavelet.lowthr ? Edited : UnEdited);
resconH->setEditedState(pedited->wavelet.resconH ? Edited : UnEdited);
reschro->setEditedState(pedited->wavelet.reschro ? Edited : UnEdited);
+ resblur->setEditedState(pedited->wavelet.resblur ? Edited : UnEdited);
+ resblurc->setEditedState(pedited->wavelet.resblurc ? Edited : UnEdited);
tmrs->setEditedState(pedited->wavelet.tmrs ? Edited : UnEdited);
edgs->setEditedState(pedited->wavelet.edgs ? Edited : UnEdited);
scale->setEditedState(pedited->wavelet.scale ? Edited : UnEdited);
@@ -1395,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);
@@ -1416,6 +1656,11 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
softrad->setEditedState(pedited->wavelet.softrad ? Edited : UnEdited);
softradend->setEditedState(pedited->wavelet.softradend ? Edited : UnEdited);
+ ballum->setEditedState(pedited->wavelet.ballum ? Edited : UnEdited);
+ balchrom->setEditedState(pedited->wavelet.balchrom ? Edited : UnEdited);
+ chromfi->setEditedState(pedited->wavelet.chromfi ? Edited : UnEdited);
+ chromco->setEditedState(pedited->wavelet.chromco ? Edited : UnEdited);
+
median->set_inconsistent(!pedited->wavelet.median);
medianlev->set_inconsistent(!pedited->wavelet.medianlev);
linkedg->set_inconsistent(!pedited->wavelet.linkedg);
@@ -1424,6 +1669,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
lipst->set_inconsistent(!pedited->wavelet.lipst);
contrast->setEditedState(pedited->wavelet.contrast ? Edited : UnEdited);
edgrad->setEditedState(pedited->wavelet.edgrad ? Edited : UnEdited);
+ edgeffect->setEditedState(pedited->wavelet.edgeffect ? Edited : UnEdited);
edgval->setEditedState(pedited->wavelet.edgval ? Edited : UnEdited);
thr->setEditedState(pedited->wavelet.thr ? Edited : UnEdited);
thrH->setEditedState(pedited->wavelet.thrH ? Edited : UnEdited);
@@ -1437,6 +1683,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
satlev->setEditedState(pedited->wavelet.satlev ? Edited : UnEdited);
strength->setEditedState(pedited->wavelet.strength ? Edited : UnEdited);
edgcont->setEditedState(pedited->wavelet.edgcont ? Edited : UnEdited);
+ chrwav->setEditedState(pedited->wavelet.chrwav ? Edited : UnEdited);
+ bluwav->setEditedState(pedited->wavelet.bluwav ? Edited : UnEdited);
level0noise->setEditedState(pedited->wavelet.level0noise ? Edited : UnEdited);
level1noise->setEditedState(pedited->wavelet.level1noise ? Edited : UnEdited);
level2noise->setEditedState(pedited->wavelet.level2noise ? Edited : UnEdited);
@@ -1492,6 +1740,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
//BackmethodUpdateUI();
CLmethodUpdateUI();
lipstUpdateUI();
+ oldshToggled();
//TilesmethodUpdateUI();
//daubcoeffmethodUpdateUI();
//DirmethodUpdateUI();
@@ -1542,7 +1791,9 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
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);
@@ -1554,6 +1805,7 @@ void Wavelet::setEditProvider(EditDataProvider *provider)
void Wavelet::autoOpenCurve()
{
ccshape->openIfNonlinear();
+ blshape->openIfNonlinear();
//opacityShapeRG->openIfNonlinear();
//opacityShapeBY->openIfNonlinear();
}
@@ -1564,11 +1816,16 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.enabled = getEnabled();
pp->wavelet.avoid = avoid->get_active();
pp->wavelet.showmask = showmask->get_active();
+ pp->wavelet.oldsh = oldsh->get_active();
pp->wavelet.tmr = tmr->get_active();
pp->wavelet.sigma = sigma->getValue();
+ pp->wavelet.offset = offset->getValue();
+ pp->wavelet.lowthr = lowthr->getValue();
pp->wavelet.rescon = rescon->getValue();
pp->wavelet.resconH = resconH->getValue();
pp->wavelet.reschro = reschro->getValue();
+ pp->wavelet.resblur = resblur->getValue();
+ pp->wavelet.resblurc = resblurc->getValue();
pp->wavelet.tmrs = tmrs->getValue();
pp->wavelet.edgs = edgs->getValue();
pp->wavelet.scale = scale->getValue();
@@ -1586,6 +1843,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.lipst = lipst->get_active();
pp->wavelet.contrast = contrast->getValue();
pp->wavelet.edgrad = edgrad->getValue();
+ pp->wavelet.edgeffect = edgeffect->getValue();
pp->wavelet.edgval = edgval->getValue();
pp->wavelet.edgthresh = edgthresh->getValue();
pp->wavelet.thr = thr->getValue();
@@ -1604,12 +1862,16 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.hllev = hllev->getValue ();
pp->wavelet.bllev = bllev->getValue ();
pp->wavelet.edgcont = edgcont->getValue ();
+ pp->wavelet.chrwav = chrwav->getValue();
+ pp->wavelet.bluwav = bluwav->getValue();
pp->wavelet.level0noise = level0noise->getValue ();
pp->wavelet.level1noise = level1noise->getValue ();
pp->wavelet.level2noise = level2noise->getValue ();
pp->wavelet.level3noise = level3noise->getValue ();
pp->wavelet.ccwcurve = ccshape->getCurve();
+ pp->wavelet.blcurve = blshape->getCurve();
pp->wavelet.opacityCurveRG = opacityShapeRG->getCurve();
+ pp->wavelet.opacityCurveSH = opacityShapeSH->getCurve();
pp->wavelet.opacityCurveBY = opacityShapeBY->getCurve();
pp->wavelet.opacityCurveW = opacityShape->getCurve();
pp->wavelet.opacityCurveWL = opacityShapeWL->getCurve();
@@ -1619,6 +1881,15 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.satlev = satlev->getValue ();
pp->wavelet.strength = (int) strength->getValue();
pp->wavelet.balance = (int) balance->getValue();
+ pp->wavelet.balchrom = balchrom->getValue();
+ pp->wavelet.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();
@@ -1633,6 +1904,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.expcontrast = expcontrast->getEnabled();
pp->wavelet.expchroma = expchroma->getEnabled();
pp->wavelet.expedge = expedge->getEnabled();
+ pp->wavelet.expbl = expbl->getEnabled();
pp->wavelet.expresid = expresid->getEnabled();
pp->wavelet.expfinal = expfinal->getEnabled();
pp->wavelet.exptoning = exptoning->getEnabled();
@@ -1641,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();
@@ -1654,6 +1932,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.enabled = !get_inconsistent();
pedited->wavelet.avoid = !avoid->get_inconsistent();
pedited->wavelet.showmask = !showmask->get_inconsistent();
+ pedited->wavelet.oldsh = !oldsh->get_inconsistent();
pedited->wavelet.tmr = !tmr->get_inconsistent();
pedited->wavelet.median = !median->get_inconsistent();
pedited->wavelet.medianlev = !medianlev->get_inconsistent();
@@ -1677,9 +1956,13 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.Dirmethod = Dirmethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->wavelet.edgthresh = edgthresh->getEditedState();
pedited->wavelet.sigma = sigma->getEditedState();
+ pedited->wavelet.offset = offset->getEditedState();
+ pedited->wavelet.lowthr = lowthr->getEditedState();
pedited->wavelet.rescon = rescon->getEditedState();
pedited->wavelet.resconH = resconH->getEditedState();
pedited->wavelet.reschro = reschro->getEditedState();
+ pedited->wavelet.resblur = resblur->getEditedState();
+ pedited->wavelet.resblurc = resblurc->getEditedState();
pedited->wavelet.tmrs = tmrs->getEditedState();
pedited->wavelet.edgs = edgs->getEditedState();
pedited->wavelet.scale = scale->getEditedState();
@@ -1698,6 +1981,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.chro = chro->getEditedState();
pedited->wavelet.contrast = contrast->getEditedState();
pedited->wavelet.edgrad = edgrad->getEditedState();
+ pedited->wavelet.edgeffect = edgeffect->getEditedState();
pedited->wavelet.edgval = edgval->getEditedState();
pedited->wavelet.thr = thr->getEditedState();
pedited->wavelet.thrH = thrH->getEditedState();
@@ -1707,12 +1991,16 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.skinprotect = skinprotect->getEditedState();
pedited->wavelet.hllev = hllev->getEditedState();
pedited->wavelet.ccwcurve = !ccshape->isUnChanged();
+ pedited->wavelet.blcurve = !blshape->isUnChanged();
pedited->wavelet.edgcont = edgcont->getEditedState();
+ pedited->wavelet.chrwav = chrwav->getEditedState();
+ pedited->wavelet.bluwav = bluwav->getEditedState();
pedited->wavelet.level0noise = level0noise->getEditedState();
pedited->wavelet.level1noise = level1noise->getEditedState();
pedited->wavelet.level2noise = level2noise->getEditedState();
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();
@@ -1728,21 +2016,33 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.bluemed = bluemed->getEditedState();
pedited->wavelet.greenhigh = greenhigh->getEditedState();
pedited->wavelet.bluehigh = bluehigh->getEditedState();
+ pedited->wavelet.ballum = ballum->getEditedState();
+ pedited->wavelet.balchrom = balchrom->getEditedState();
+ pedited->wavelet.chromfi = chromfi->getEditedState();
+ pedited->wavelet.chromco = chromco->getEditedState();
pedited->wavelet.mergeL = mergeL->getEditedState();
pedited->wavelet.mergeC = mergeC->getEditedState();
pedited->wavelet.softrad = softrad->getEditedState();
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();
pedited->wavelet.expedge = !expedge->get_inconsistent();
+ pedited->wavelet.expbl = !expbl->get_inconsistent();
pedited->wavelet.expresid = !expresid->get_inconsistent();
pedited->wavelet.expfinal = !expfinal->get_inconsistent();
pedited->wavelet.exptoning = !exptoning->get_inconsistent();
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();
@@ -1844,8 +2144,8 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pp->wavelet.Tilesmethod = "full";
} else if (Tilesmethod->get_active_row_number() == 1) {
pp->wavelet.Tilesmethod = "big";
- } else if (Tilesmethod->get_active_row_number() == 2) {
- pp->wavelet.Tilesmethod = "lit";
+// } else if (Tilesmethod->get_active_row_number() == 2) {
+// pp->wavelet.Tilesmethod = "lit";
}
if (daubcoeffmethod->get_active_row_number() == 0) {
@@ -1879,8 +2179,12 @@ void Wavelet::curveChanged(CurveEditor* ce)
if (listener && getEnabled()) {
if (ce == ccshape) {
listener->panelChanged(EvWavCCCurve, M("HISTORY_CUSTOMCURVE"));
+ } else if (ce == blshape) {
+ listener->panelChanged(EvWavblshape, M("HISTORY_CUSTOMCURVE"));
} else if (ce == opacityShapeRG) {
listener->panelChanged(EvWavColor, M("HISTORY_CUSTOMCURVE"));
+ } else if (ce == opacityShapeSH) {
+ listener->panelChanged(EvWavlevelshc, M("HISTORY_CUSTOMCURVE"));
} else if (ce == opacityShapeBY) {
listener->panelChanged(EvWavOpac, M("HISTORY_CUSTOMCURVE"));
} else if (ce == opacityShape) {
@@ -1911,10 +2215,20 @@ 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);
resconH->setDefault(defParams->wavelet.resconH);
reschro->setDefault(defParams->wavelet.reschro);
+ resblur->setDefault(defParams->wavelet.resblur);
+ resblurc->setDefault(defParams->wavelet.resblurc);
tmrs->setDefault(defParams->wavelet.tmrs);
edgs->setDefault(defParams->wavelet.edgs);
scale->setDefault(defParams->wavelet.scale);
@@ -1933,6 +2247,7 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
chro->setDefault(defParams->wavelet.chro);
contrast->setDefault(defParams->wavelet.contrast);
edgrad->setDefault(defParams->wavelet.edgrad);
+ edgeffect->setDefault(defParams->wavelet.edgeffect);
edgval->setDefault(defParams->wavelet.edgval);
edgthresh->setDefault(defParams->wavelet.edgthresh);
thr->setDefault(defParams->wavelet.thr);
@@ -1945,10 +2260,17 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit
pastlev->setDefault (defParams->wavelet.pastlev);
satlev->setDefault (defParams->wavelet.satlev);
edgcont->setDefault (defParams->wavelet.edgcont);
+ chrwav->setDefault(defParams->wavelet.chrwav);
+ bluwav->setDefault(defParams->wavelet.bluwav);
level0noise->setDefault (defParams->wavelet.level0noise);
level1noise->setDefault