Merge from dev

This commit is contained in:
Lawrence Lee 2020-08-08 22:02:29 -07:00
commit 2f06f56d9c
31 changed files with 866 additions and 329 deletions

View File

@ -15,6 +15,7 @@ Development contributors, in last name alphabetical order:
Maciek Dworak
Michael Ezra
Flössie
Rüdiger Franke
Jean-Christophe Frisch
Ilias Giarimis
Alberto Griggio

View File

@ -45,7 +45,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION
endif()
# Warning for GCC 10, which causes problems #5749:
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "10.0")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "10.1")
message(STATUS "WARNING: gcc ${CMAKE_CXX_COMPILER_VERSION} is known to miscompile RawTherapee when using -ftree-loop-vectorize, forcing the option to be off")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-tree-loop-vectorize")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-loop-vectorize")

View File

@ -2653,6 +2653,8 @@ TP_WAVELET_CHR_TOOLTIP;Ajuste le chroma en fonction des "niveaux de contraste" e
TP_WAVELET_CHSL;Curseurs
TP_WAVELET_CHTYPE;Méthode de chrominance
TP_WAVELET_COLORT;Opacité Rouge-Vert
TP_WAVELET_COMPLEX_TOOLTIP;Standard: lapplication dispose du nécessaire pour assurer les opérations courantes, linterface graphique est simplifiée.\nAvancé: toutes les fonctionnalités sont présentes, certaines nécessitent un apprentissage important
TP_WAVELET_COMPEXPERT;Avancé
TP_WAVELET_COMPCONT;Contraste
TP_WAVELET_COMPGAMMA;Compression gamma
TP_WAVELET_COMPGAMMA_TOOLTIP;Ajuster le gamma de l'image résiduelle vous permet d'équiilibrer les données de l'histogramme.

View File

@ -569,10 +569,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 - 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_318;W - Contrast - Finer levels
HISTORY_MSG_319;W - Contrast - Finer range
HISTORY_MSG_320;W - Contrast - Coarser range
HISTORY_MSG_321;W - Contrast - Coarser levels
HISTORY_MSG_322;W - Gamut - Avoid color shift
HISTORY_MSG_323;W - ES - Local contrast
HISTORY_MSG_324;W - Chroma - Pastel
@ -636,14 +636,14 @@ HISTORY_MSG_381;PRS RLD - Radius
HISTORY_MSG_382;PRS RLD - Amount
HISTORY_MSG_383;PRS RLD - Damping
HISTORY_MSG_384;PRS RLD - Iterations
HISTORY_MSG_385;W - Residual - Color Balance
HISTORY_MSG_385;W - Residual - Color balance
HISTORY_MSG_386;W - Residual - CB green high
HISTORY_MSG_387;W - Residual - CB blue high
HISTORY_MSG_388;W - Residual - CB green mid
HISTORY_MSG_389;W - Residual - CB blue mid
HISTORY_MSG_390;W - Residual - CB green low
HISTORY_MSG_391;W - Residual - CB blue low
HISTORY_MSG_392;W - Residual - Color Balance
HISTORY_MSG_392;W - Residual - Color balance
HISTORY_MSG_393;DCP - Look table
HISTORY_MSG_394;DCP - Baseline exposure
HISTORY_MSG_395;DCP - Base table
@ -1199,7 +1199,7 @@ HISTORY_MSG_956;Local - CH Curve
HISTORY_MSG_BLSHAPE;Blur by level
HISTORY_MSG_BLURCWAV;Blur chroma
HISTORY_MSG_BLURWAV;Blur luminance
HISTORY_MSG_BLUWAV;Attenuation Response
HISTORY_MSG_BLUWAV;Attenuation response
HISTORY_MSG_CAT02PRESET;Cat02 automatic preset
HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors
HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction
@ -1216,6 +1216,8 @@ HISTORY_MSG_COLORTONING_LABREGION_POWER;CT - region power
HISTORY_MSG_COLORTONING_LABREGION_SATURATION;CT - Saturation
HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - region show mask
HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - region slope
HISTORY_MSG_COMPLEX;Wavelet complexity
HISTORY_MSG_COMPLEXRETI;Retinex complexity
HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth
HISTORY_MSG_DEHAZE_ENABLED;Haze Removal
HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only
@ -1223,7 +1225,7 @@ HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Dehaze - Show depth map
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_EDGEFFECT;Edge Attenuation Response
HISTORY_MSG_EDGEFFECT;Edge Attenuation response
HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative
HISTORY_MSG_FILMNEGATIVE_FILMBASE;Film base color
HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values
@ -1270,10 +1272,10 @@ HISTORY_MSG_RESIZE_ALLOWUPSCALING;Resize - Allow upscaling
HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius
HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold
HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace
HISTORY_MSG_SIGMACOL;Chroma Attenuation Response
HISTORY_MSG_SIGMADIR;Dir Attenuation Response
HISTORY_MSG_SIGMAFIN;Final contrast Attenuation Response
HISTORY_MSG_SIGMATON;Toning Attenuation Response
HISTORY_MSG_SIGMACOL;Chroma Attenuation response
HISTORY_MSG_SIGMADIR;Dir Attenuation response
HISTORY_MSG_SIGMAFIN;Final contrast Attenuation response
HISTORY_MSG_SIGMATON;Toning Attenuation response
HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light
HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength
HISTORY_MSG_TEMPOUT;CAM02 automatic temperature
@ -1292,10 +1294,10 @@ HISTORY_MSG_WAVMERGEC;Merge C
HISTORY_MSG_WAVMERGEL;Merge L
HISTORY_MSG_WAVOFFSET;Offset
HISTORY_MSG_WAVOLDSH;Old algorithm
HISTORY_MSG_WAVRADIUS;Radius Shadows-Highlight
HISTORY_MSG_WAVRADIUS;Radius shadows-highlights
HISTORY_MSG_WAVSCALE;Scale
HISTORY_MSG_WAVSHOWMASK;Show wavelet mask
HISTORY_MSG_WAVSIGMA;Attenuation Response
HISTORY_MSG_WAVSIGMA;Attenuation response
HISTORY_MSG_WAVSOFTRAD;Soft radius clarity
HISTORY_MSG_WAVSOFTRADEND;Soft radius final
HISTORY_MSG_WAVUSHAMET;Clarity method
@ -3237,18 +3239,18 @@ TP_WAVELET_6;Level 6
TP_WAVELET_7;Level 7
TP_WAVELET_8;Level 8
TP_WAVELET_9;Level 9
TP_WAVELET_APPLYTO;Apply To
TP_WAVELET_APPLYTO;Apply to
TP_WAVELET_AVOID;Avoid color shift
TP_WAVELET_B0;Black
TP_WAVELET_B1;Grey
TP_WAVELET_B1;Gray
TP_WAVELET_B2;Residual
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;Chrominance balance
TP_WAVELET_BALCHROM;Denoise Equalizer Blue-yellow Red-green
TP_WAVELET_BALANCE_TOOLTIP;Alters the balance between the vertical, horizontal and diagonal wavelet directions: .\nActivating contrast, chroma or residual tone mapping amplifies the effect due to balance
TP_WAVELET_BALCHRO_TOOLTIP;If enabled, the 'Contrast balance' curve or slider also modifies chroma balance.
TP_WAVELET_BALCHROM;Denoise equalizer blue-yellow red-green
TP_WAVELET_BALLUM;Denoise Equalizer White-Black
TP_WAVELET_BANONE;None
TP_WAVELET_BASLI;Slider
@ -3256,9 +3258,9 @@ TP_WAVELET_BATYPE;Contrast balance method
TP_WAVELET_BL;Blur levels
TP_WAVELET_BLCURVE;Blur by levels
TP_WAVELET_BLURFRAME;Blur
TP_WAVELET_BLUWAV;Attenuation Response
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_BLUWAV;Attenuation response
TP_WAVELET_CBENAB;Toning and Color balance
TP_WAVELET_CB_TOOLTIP;With high values you can create special effects, similar to those achieved with the Chroma Module, but focused on the residual image\nWith moderate values you can manually correct the white balance
TP_WAVELET_CCURVE;Local contrast
TP_WAVELET_CH1;Whole chroma range
TP_WAVELET_CH2;Saturated/pastel
@ -3266,7 +3268,7 @@ 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_CHROFRAME;Denoise chrominance
TP_WAVELET_CHROMAFRAME;Chroma
TP_WAVELET_CHROMCO;Chrominance Coarse
TP_WAVELET_CHROMFI;Chrominance Fine
@ -3277,10 +3279,14 @@ TP_WAVELET_CHSL;Sliders
TP_WAVELET_CHTYPE;Chrominance method
TP_WAVELET_CLA;Clarity
TP_WAVELET_CLARI;Sharp-mask and Clarity
TP_WAVELET_COLORT;Opacity Red-Green
TP_WAVELET_COLORT;Opacity red-green
TP_WAVELET_COMPCONT;Contrast
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_COMPLEXLAB;Complexity
TP_WAVELET_COMPLEX_TOOLTIP;Standard: shows a reduced set of tools suitable for most processing operations.\nAdvanced: shows the complete set of tools for advanced processing operations
TP_WAVELET_COMPNORMAL;Standard
TP_WAVELET_COMPEXPERT;Advanced
TP_WAVELET_COMPTM;Tone mapping
TP_WAVELET_CONTEDIT;'After' contrast curve
TP_WAVELET_CONTFRAME;Contrast - Compression
@ -3289,16 +3295,16 @@ TP_WAVELET_CONTRA;Contrast
TP_WAVELET_CONTRASTEDIT;Finer - Coarser levels
TP_WAVELET_CONTRAST_MINUS;Contrast -
TP_WAVELET_CONTRAST_PLUS;Contrast +
TP_WAVELET_CONTRA_TOOLTIP;Changes contrast of the residual image.
TP_WAVELET_CONTRA_TOOLTIP;Changes the residual image contrast.
TP_WAVELET_CTYPE;Chrominance control
TP_WAVELET_CURVEEDITOR_BL_TOOLTIP;Disabled if zoom > about 300%
TP_WAVELET_CURVEEDITOR_CC_TOOLTIP;Modifies local contrast as a function of the original local contrast (abscissa).\nLow abscissa values represent small local contrast (real values about 10..20).\n50% abscissa represents average local contrast (real value about 100..300).\n66% abscissa represents standard deviation of local contrast (real value about 300..800).\n100% abscissa represents maximum local contrast (real value about 3000..8000).
TP_WAVELET_CURVEEDITOR_CH;Contrast levels=f(Hue)
TP_WAVELET_CURVEEDITOR_CH_TOOLTIP;Modifies each level's contrast as a function of hue.\nTake care not to overwrite changes made with the Gamut sub-tool's hue controls.\nThe curve will only have an effect when wavelet contrast level sliders are non-zero.
TP_WAVELET_CURVEEDITOR_CL;L
TP_WAVELET_CURVEEDITOR_CL_TOOLTIP;Applies a final contrast luminance curve at the end of the wavelet treatment.
TP_WAVELET_CURVEEDITOR_CL_TOOLTIP;Applies a final contrast-luminance curve at the end of the wavelet processing.
TP_WAVELET_CURVEEDITOR_HH;HH
TP_WAVELET_CURVEEDITOR_HH_TOOLTIP;Modifies the residual image's hue as a function of hue.
TP_WAVELET_CURVEEDITOR_HH_TOOLTIP;Modifies the residual image hue as a function of hue.
TP_WAVELET_DALL;All directions
TP_WAVELET_DAUB;Edge performance
TP_WAVELET_DAUB2;D2 - low
@ -3307,34 +3313,34 @@ TP_WAVELET_DAUB6;D6 - standard plus
TP_WAVELET_DAUB10;D10 - medium
TP_WAVELET_DAUB14;D14 - high
TP_WAVELET_DAUBLOCAL;Wavelet Edge performance
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_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 first levels. However the quality is not strictly related to this coefficient and can vary depending on image and use.
TP_WAVELET_DIRFRAME;Directional contrast
TP_WAVELET_DONE;Vertical
TP_WAVELET_DTHR;Diagonal
TP_WAVELET_DTWO;Horizontal
TP_WAVELET_EDCU;Curve
TP_WAVELET_EDEFFECT;Attenuation Response
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_EDEFFECT;Attenuation response
TP_WAVELET_EDEFFECT_TOOLTIP;This slider selects the range of contrast values that will receive the full effect of any adjustment
TP_WAVELET_EDGCONT;Local contrast
TP_WAVELET_EDGCONT_TOOLTIP;Adjusting the points to the left decreases contrast, and to the right increases it.\nBottom-left, top-left, top-right and bottom-right represent respectively local contrast for low values, mean, mean+stdev and maxima.
TP_WAVELET_EDGCONT_TOOLTIP;Adjusting the points to the left decreases contrast, and to the right increases it.\nBottom-left, top-left, top-right and bottom-right represent respectively local contrast for low values, mean, mean+std. dev. and maxima.
TP_WAVELET_EDGE;Edge Sharpness
TP_WAVELET_EDGEAMPLI;Base amplification
TP_WAVELET_EDGEDETECT;Gradient sensitivity
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_EDGEDETECTTHR2;Edge enhancement
TP_WAVELET_EDGEDETECTTHR_TOOLTIP;This slider sets a threshold below which finer details won't be considered as an edge
TP_WAVELET_EDGEDETECT_TOOLTIP;Moving the slider to the right increases edge sensitivity. This affects local contrast, edge settings and noise.
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
TP_WAVELET_EDGTHRESH_TOOLTIP;Change the repartition between the first levels and the others. The higher the threshold the more the action is centered on the first levels. Be careful with negative values, they increase the action of high levels and can introduce artifacts.
TP_WAVELET_EDRAD;Radius
TP_WAVELET_EDRAD_TOOLTIP;This radius adjustment is very different from those in other sharpening tools. Its value is compared to each level through a complex function. In this sense, a value of zero still has an effect.
TP_WAVELET_EDSL;Threshold Sliders
TP_WAVELET_EDRAD_TOOLTIP;This adjustment controls the local enhancement. A value of zero still has an effect
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_FINCFRAME;Final local contrast
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_FINEST;Finest
TP_WAVELET_HIGHLIGHT;Finer levels luminance range
@ -3342,7 +3348,7 @@ TP_WAVELET_HS1;Whole luminance range
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 <b>white balance is incorrect</b>.
TP_WAVELET_HUESKY;Sky hue
TP_WAVELET_HUESKY;Hue range
TP_WAVELET_HUESKY_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 <b>white balance is incorrect</b>.
TP_WAVELET_ITER;Delta balance levels
TP_WAVELET_ITER_TOOLTIP;Left: increase low levels and reduce high levels,\nRight: reduce low levels and increase high levels.
@ -3350,18 +3356,18 @@ 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;Finer details levels, with selected level
TP_WAVELET_LEVDIR_INF;Finer detail levels, including selected level
TP_WAVELET_LEVDIR_ONE;One level
TP_WAVELET_LEVDIR_SUP;Coarser details levels, without selected level
TP_WAVELET_LEVDIR_SUP;Coarser detail levels, excluding 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_LEVELS_TOOLTIP;Choose the number of wavelet decomposition levels for the image.\nMore levels require more RAM and require a longer processing time.
TP_WAVELET_LEVF;Contrast
TP_WAVELET_LEVLABEL;Preview maximum possible levels = %1
TP_WAVELET_LEVONE;Level 2
TP_WAVELET_LEVTHRE;Level 4
TP_WAVELET_LEVTWO;Level 3
TP_WAVELET_LEVZERO;Level 1
TP_WAVELET_LINKEDG;Link with Edge Sharpness' Strength
TP_WAVELET_LINKEDG;Link to Edge Sharpness Strength
TP_WAVELET_LIPST;Enhanced algoritm
TP_WAVELET_LOWLIGHT;Coarser levels luminance range
TP_WAVELET_LOWTHR_TOOLTIP;Prevents amplification of fine textures and noise
@ -3369,7 +3375,7 @@ TP_WAVELET_MEDGREINF;First level
TP_WAVELET_MEDI;Reduce artifacts in blue sky
TP_WAVELET_MEDILEV;Edge detection
TP_WAVELET_MEDILEV_TOOLTIP;When you enable Edge Detection, it is recommanded:\n- to disabled low contrast levels to avoid artifacts,\n- to use high values of gradient sensitivity.\n\nYou can modulate the strength with 'refine' from Denoise and Refine.
TP_WAVELET_MERGEC;Merge Chroma
TP_WAVELET_MERGEC;Merge chroma
TP_WAVELET_MERGEL;Merge Luma
TP_WAVELET_NEUTRAL;Neutral
TP_WAVELET_NOIS;Denoise
@ -3380,24 +3386,24 @@ 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_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 Attenuation Response value you will able to select the contrasts that will be enhanced.
TP_WAVELET_OFFSET_TOOLTIP;Offset modifies the balance between low contrast and high contrast details.\nHigh values will amplify contrast changes to the higher contrast details, whereas low values will amplify contrast changes to low contrast details.\nBy using a low Attenuation response value you can select which contrast values will be enhanced.
TP_WAVELET_OLDSH;Algorithm using negatives values
TP_WAVELET_OPACITY;Opacity Blue-Yellow
TP_WAVELET_OPACITY;Opacity blue-yellow
TP_WAVELET_OPACITYW;Contrast balance d/v-h curve
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_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;Blur luminance
TP_WAVELET_RESBLURC;Blur chroma
TP_WAVELET_RESBLUR_TOOLTIP;Disabled if zoom > about 500%
TP_WAVELET_RESCHRO;Intensity
TP_WAVELET_RESCHRO;Strength
TP_WAVELET_RESCON;Shadows
TP_WAVELET_RESCONH;Highlights
TP_WAVELET_RESID;Residual Image
@ -3406,15 +3412,15 @@ TP_WAVELET_SETTINGS;Wavelet Settings
TP_WAVELET_SHA;Sharp mask
TP_WAVELET_SHFRAME;Shadows/Highlights
TP_WAVELET_SHOWMASK;Show wavelet 'mask'
TP_WAVELET_SIGMA;Attenuation Response
TP_WAVELET_SIGMAFIN;Attenuation Response
TP_WAVELET_SIGMA;Attenuation response
TP_WAVELET_SIGMAFIN;Attenuation response
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 the effect will be pinpointed towards 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
TP_WAVELET_SKY_TOOLTIP;At -100 sky-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 sky-tones are protected while all other tones are affected.
TP_WAVELET_SOFTRAD;Soft Radius
TP_WAVELET_STREN;Strength
TP_WAVELET_SKY;Hue targetting/protection
TP_WAVELET_SKY_TOOLTIP;Allows you to target or protect a range of hues.\nAt -100 selected hues are targetted.\nAt 0 all hues are treated equally.\nAt +100 selected hues are protected while all other hues are targetted.
TP_WAVELET_SOFTRAD;Soft radius
TP_WAVELET_STREN;Refine
TP_WAVELET_STRENGTH;Strength
TP_WAVELET_SUPE;Extra
TP_WAVELET_THR;Shadows threshold
@ -3422,7 +3428,7 @@ TP_WAVELET_THRESHOLD;Finer levels
TP_WAVELET_THRESHOLD2;Coarser levels
TP_WAVELET_THRESHOLD2_TOOLTIP;Only levels from the chosen value to the selected number of wavelet levels will be affected by the Shadow luminance range.
TP_WAVELET_THRESHOLD_TOOLTIP;Only levels below and including the chosen value will be affected by the Highlight luminance range.
TP_WAVELET_THRESWAV;Balance Threshold
TP_WAVELET_THRESWAV;Balance threshold
TP_WAVELET_THRH;Highlights threshold
TP_WAVELET_TILESBIG;Tiles
TP_WAVELET_TILESFULL;Full image
@ -3435,11 +3441,11 @@ 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_TON;Toning
TP_WAVELET_TONFRAME;Excluded Colors
TP_WAVELET_TONFRAME;Excluded colors
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_USH_TOOLTIP;If you select Sharp-mask, you can choose any level (in Settings) from 1 to 4 for processing.\nIf you select Clarity, you can choose any level (in Settings) between 5 and Extra.
TP_WAVELET_WAVLOWTHR;Low contrast threshold
TP_WAVELET_WAVOFFSET;Offset
TP_WBALANCE_AUTO;Auto

View File

@ -123,7 +123,7 @@ float* RawImageSource::CA_correct_RT(
double cared,
double cablue,
bool avoidColourshift,
const array2D<float> &rawData,
array2D<float> &rawData,
double* fitParamsTransfer,
bool fitParamsIn,
bool fitParamsOut,
@ -1291,7 +1291,7 @@ float* RawImageSource::CA_correct_RT(
for (int i = 0; i < H - 2 * cb; ++i) {
const int firstCol = fc(cfa, i, 0) & 1;
const int colour = fc(cfa, i, firstCol);
const array2D<float>* nonGreen = colour == 0 ? redFactor : blueFactor;
array2D<float>* nonGreen = colour == 0 ? redFactor : blueFactor;
int j = firstCol;
#ifdef __SSE2__
for (; j < W - 7 - 2 * cb; j += 8) {
@ -1325,7 +1325,7 @@ float* RawImageSource::CA_correct_RT(
const int ngRow = 1 - (fc(cfa, 0, 0) & 1);
const int ngCol = fc(cfa, ngRow, 0) & 1;
const int colour = fc(cfa, ngRow, ngCol);
const array2D<float>* nonGreen = colour == 0 ? redFactor : blueFactor;
array2D<float>* nonGreen = colour == 0 ? redFactor : blueFactor;
for (int i = 0; i < (H + 1 - 2 * cb) / 2; ++i) {
(*nonGreen)[i][(W - 2 * cb + 1) / 2 - 1] = (*nonGreen)[i][(W - 2* cb + 1) / 2 - 2];
}

View File

@ -27,7 +27,7 @@
*
* creates an array which is valid within the normal C/C++ scope "{ ... }"
*
* access to elements is a simple as:
* access to elements is as simple as:
*
* array2D<float> my_array (10,10); // creates 10x10 array of floats
* value = my_array[3][5];
@ -48,25 +48,20 @@
* array2D<float> my_array ; // empty container.
* my_array(10,10) ; // resize to 10x10 array
* my_array(10,10,ARRAY2D_CLEAR_DATA) ; // resize to 10x10 and clear data
* my_array(10,10,ARRAY2D_CLEAR_DATA|ARRAY2D_LOCK_DATA) ; same but set a lock on changes
*
* !! locked arrays cannot be resized and cannot be unlocked again !!
*/
#pragma once
#include <csignal> // for raise()
#include <cassert>
#include <cstring>
#include <sys/types.h>
#include <vector>
#include "noncopyable.h"
// flags for use
#define ARRAY2D_LOCK_DATA 1
#define ARRAY2D_CLEAR_DATA 2
#define ARRAY2D_BYREFERENCE 4
#define ARRAY2D_VERBOSE 8
constexpr unsigned int ARRAY2D_CLEAR_DATA = 1;
constexpr unsigned int ARRAY2D_BYREFERENCE = 2;
#include <cstring>
#include <cstdio>
#include "noncopyable.h"
template<typename T>
class array2D :
@ -74,249 +69,158 @@ class array2D :
{
private:
int x, y, owner;
unsigned int flags;
T ** ptr;
T * data;
bool lock; // useful lock to ensure data is not changed anymore.
void ar_realloc(int w, int h, int offset = 0)
ssize_t width;
std::vector<T*> rows;
std::vector<T> buffer;
void initRows(ssize_t h, int offset = 0)
{
if ((ptr) && ((h > y) || (4 * h < y))) {
delete[] ptr;
ptr = nullptr;
rows.resize(h);
T* start = buffer.data() + offset;
for (ssize_t i = 0; i < h; ++i) {
rows[i] = start + width * i;
}
}
if ((data) && (((h * w) > (x * y)) || ((h * w) < ((x * y) / 4)))) {
delete[] data;
data = nullptr;
}
if (ptr == nullptr) {
ptr = new T*[h];
}
if (data == nullptr) {
data = new T[h * w + offset];
}
x = w;
y = h;
for (int i = 0; i < h; i++) {
ptr[i] = data + offset + w * i;
}
owner = 1;
void ar_realloc(ssize_t w, ssize_t h, int offset = 0)
{
width = w;
buffer.resize(h * width + offset);
initRows(h, offset);
}
public:
// use as empty declaration, resize before use!
// very useful as a member object
array2D() :
x(0), y(0), owner(0), flags(0), ptr(nullptr), data(nullptr), lock(false)
{
//printf("got empty array2D init\n");
}
array2D() : width(0) {}
// creator type1
array2D(int w, int h, unsigned int flgs = 0)
array2D(int w, int h, unsigned int flags = 0) : width(w)
{
flags = flgs;
lock = flags & ARRAY2D_LOCK_DATA;
data = new T[h * w];
owner = 1;
x = w;
y = h;
ptr = new T*[h];
for (int i = 0; i < h; i++) {
ptr[i] = data + i * w;
}
if (flags & ARRAY2D_CLEAR_DATA) {
memset(data, 0, w * h * sizeof(T));
buffer.resize(h * width, 0);
} else {
buffer.resize(h * width);
}
initRows(h);
}
// creator type 2
array2D(int w, int h, T ** source, unsigned int flgs = 0)
array2D(int w, int h, T ** source, unsigned int flags = 0) : width(w)
{
flags = flgs;
//if (lock) { printf("array2D attempt to overwrite data\n");raise(SIGSEGV);}
lock = flags & ARRAY2D_LOCK_DATA;
// when by reference
// TODO: improve this code with ar_realloc()
owner = (flags & ARRAY2D_BYREFERENCE) ? 0 : 1;
if (owner) {
data = new T[h * w];
} else {
data = nullptr;
}
x = w;
y = h;
ptr = new T*[h];
for (int i = 0; i < h; i++) {
if (owner) {
ptr[i] = data + i * w;
for (int j = 0; j < w; j++) {
ptr[i][j] = source[i][j];
rows.resize(h);
if (!(flags & ARRAY2D_BYREFERENCE)) {
buffer.resize(h * width);
T* start = buffer.data();
for (ssize_t i = 0; i < h; ++i) {
rows[i] = start + i * width;
for (ssize_t j = 0; j < width; ++j) {
rows[i][j] = source[i][j];
}
} else {
ptr[i] = source[i];
}
}
}
// destructor
~array2D()
{
if (flags & ARRAY2D_VERBOSE) {
printf(" deleting array2D size %dx%d \n", x, y);
}
if ((owner) && (data)) {
delete[] data;
}
if (ptr) {
delete[] ptr;
} else {
for (ssize_t i = 0; i < h; ++i) {
rows[i] = source[i];
}
}
}
void fill(const T val, bool multiThread = false)
{
const ssize_t height = rows.size();
#ifdef _OPENMP
#pragma omp parallel for if(multiThread)
#endif
for (int i = 0; i < x * y; ++i) {
data[i] = val;
for (ssize_t i = 0; i < width * height; ++i) {
buffer[i] = val;
}
}
void free()
{
if ((owner) && (data)) {
delete[] data;
data = nullptr;
}
if (ptr) {
delete [] ptr;
ptr = nullptr;
}
buffer.clear();
rows.clear();
}
// use with indices
T * operator[](int index) const
T * operator[](int index)
{
assert((index >= 0) && (index < y));
return ptr[index];
assert((index >= 0) && (index < rows.size()));
return rows[index];
}
const T * operator[](int index) const
{
assert((index >= 0) && (index < rows.size()));
return rows[index];
}
// use as pointer to T**
operator T**()
{
return ptr;
return rows.data();
}
// use as pointer to T**
operator const T* const *()
operator const T* const *() const
{
return ptr;
return rows.data();
}
// use as pointer to data
// use as pointer to buffer
operator T*()
{
// only if owner this will return a valid pointer
return data;
return buffer.data();
}
operator const T*() const
{
// only if owner this will return a valid pointer
return buffer.data();
}
// useful within init of parent object
// or use as resize of 2D array
void operator()(int w, int h, unsigned int flgs = 0, int offset = 0)
void operator()(int w, int h, unsigned int flags = 0, int offset = 0)
{
flags = flgs;
if (flags & ARRAY2D_VERBOSE) {
printf("got init request %dx%d flags=%u\n", w, h, flags);
printf("previous was data %p ptr %p \n", data, ptr);
}
if (lock) { // our object was locked so don't allow a change.
printf("got init request but object was locked!\n");
raise( SIGSEGV);
}
lock = flags & ARRAY2D_LOCK_DATA;
ar_realloc(w, h, offset);
if (flags & ARRAY2D_CLEAR_DATA) {
memset(data + offset, 0, static_cast<unsigned long>(w) * h * sizeof(T));
fill(0);
}
}
// import from flat data
void operator()(int w, int h, T* copy, unsigned int flgs = 0)
int getWidth() const
{
flags = flgs;
if (flags & ARRAY2D_VERBOSE) {
printf("got init request %dx%d flags=%u\n", w, h, flags);
printf("previous was data %p ptr %p \n", data, ptr);
}
if (lock) { // our object was locked so don't allow a change.
printf("got init request but object was locked!\n");
raise( SIGSEGV);
}
lock = flags & ARRAY2D_LOCK_DATA;
ar_realloc(w, h);
memcpy(data, copy, w * h * sizeof(T));
return width;
}
int width() const
int getHeight() const
{
return x;
}
int height() const
{
return y;
return rows.size();
}
operator bool()
{
return (x > 0 && y > 0);
return (width > 0 && !rows.empty());
}
};
template<typename T, const size_t num>
class multi_array2D
class multi_array2D : public rtengine::NonCopyable
{
private:
array2D<T> list[num];
public:
multi_array2D(int x, int y, int flags = 0, int offset = 0)
multi_array2D(int width, int height, int flags = 0, int offset = 0)
{
for (size_t i = 0; i < num; i++) {
list[i](x, y, flags, (i + 1) * offset);
for (size_t i = 0; i < num; ++i) {
list[i](width, height, flags, (i + 1) * offset);
}
}
~multi_array2D()
{
//printf("trying to delete the list of array2D objects\n");
}
array2D<T> & operator[](int index)
{
assert(static_cast<size_t>(index) < num);

View File

@ -1401,9 +1401,17 @@ Camera constants:
"ranges": { "white": [ 16105, 16270, 16082 ] } // These values are the lowest pixel values >16000 for all ISOs. LENR has a negligble effect.
// No aperture scaling data provided, but likely negligible
},
{ // Quality C, only raw crop
"make_model": [ "FUJIFILM X-T3", "FUJIFILM X-T30", "FUJIFILM X-PRO3", "FUJIFILM X100V", "FUJIFILM X-T4" ],
{ // Quality A, samples provided by Daniel Catalina (#5839) and pi99y (#5860)
"make_model": [ "FUJIFILM X-T3", "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],
"white": [ 16170, 16275, 16170 ] // typical safe-margins with LENR
// negligible aperture scaling effect
},
{ // Quality B
"make_model": [ "FUJIFILM X-T30", "FUJIFILM X100V", "FUJIFILM X-T4" ],
"dcraw_matrix": [ 13426,-6334,-1177,-4244,12136,2371,-580,1303,5980 ], // DNG_v11, standard_v2 d65
"raw_crop": [ 0, 5, 6252, 4176]
},
@ -2747,6 +2755,12 @@ Camera constants:
"ranges": { "black": 0, "white": 64400 }
},
{ // Quality B
"make_model": ["HASSELBLAD NEX-7", "SONY NEX-7"], // Hasselblad NEX-7 also known as Hasselblad Lunar
"dcraw_matrix": [ 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 ], // adobe DNGv12.2 d65
"ranges": { "black": 512, "white": 16372 } // Typical white level (samples provided by @ggc on Pixls, influence from LENR unknown
},
{ // Quality A for tested CFV, the other models have the same sensor (16 megapixel square sensor)
"make_model": [ "Hasselblad V96C", "Hasselblad CFV", "Hasselblad CFV-II" ],
"dcraw_matrix": [ 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809 ] // borrowed from Adobe's DNG converter

View File

@ -1772,7 +1772,7 @@ void Color::RGB2Lab(float *R, float *G, float *B, float *L, float *a, float *b,
}
}
void Color::RGB2L(float *R, float *G, float *B, float *L, const float wp[3][3], int width)
void Color::RGB2L(const float *R, const float *G, const float *B, float *L, const float wp[3][3], int width)
{
#ifdef __SSE2__

View File

@ -623,7 +623,7 @@ public:
static void XYZ2Lab(float x, float y, float z, float &L, float &a, float &b);
static void RGB2Lab(float *X, float *Y, float *Z, float *L, float *a, float *b, const float wp[3][3], int width);
static void Lab2RGBLimit(float *L, float *a, float *b, float *R, float *G, float *B, const float wp[3][3], float limit, float afactor, float bfactor, int width);
static void RGB2L(float *X, float *Y, float *Z, float *L, const float wp[3][3], int width);
static void RGB2L(const float *R, const float *G, const float *B, float *L, const float wp[3][3], int width);
/**
* @brief Convert Lab in Yuv

View File

@ -82,8 +82,8 @@ int calculate_subsampling(int w, int h, int r)
void guidedFilter(const array2D<float> &guide, const array2D<float> &src, array2D<float> &dst, int r, float epsilon, bool multithread, int subsampling)
{
const int W = src.width();
const int H = src.height();
const int W = src.getWidth();
const int H = src.getHeight();
if (subsampling <= 0) {
subsampling = calculate_subsampling(W, H, r);
@ -94,8 +94,8 @@ void guidedFilter(const array2D<float> &guide, const array2D<float> &src, array2
const auto apply =
[=](Op op, array2D<float> &res, const array2D<float> &a, const array2D<float> &b, const array2D<float> &c=array2D<float>()) -> void
{
const int w = res.width();
const int h = res.height();
const int w = res.getWidth();
const int h = res.getHeight();
#ifdef _OPENMP
#pragma omp parallel for if (multithread)
@ -142,12 +142,12 @@ void guidedFilter(const array2D<float> &guide, const array2D<float> &src, array2
const auto f_subsample =
[=](array2D<float> &d, const array2D<float> &s) -> void
{
if (d.width() == s.width() && d.height() == s.height()) {
if (d.getWidth() == s.getWidth() && d.getHeight() == s.getHeight()) {
#ifdef _OPENMP
# pragma omp parallel for if (multithread)
#endif
for (int y = 0; y < s.height(); ++y) {
for (int x = 0; x < s.width(); ++x) {
for (int y = 0; y < s.getHeight(); ++y) {
for (int x = 0; x < s.getWidth(); ++x) {
d[y][x] = s[y][x];
}
}
@ -164,9 +164,9 @@ void guidedFilter(const array2D<float> &guide, const array2D<float> &src, array2
const auto f_mean =
[multithread](array2D<float> &d, array2D<float> &s, int rad) -> void
{
rad = LIM(rad, 0, (min(s.width(), s.height()) - 1) / 2 - 1);
// boxblur(s, d, rad, s.width(), s.height(), multithread);
boxblur(static_cast<float**>(s), static_cast<float**>(d), rad, s.width(), s.height(), multithread);
rad = LIM(rad, 0, (min(s.getWidth(), s.getHeight()) - 1) / 2 - 1);
// boxblur(s, d, rad, s.getWidth(), s.getHeight(), multithread);
boxblur(static_cast<float**>(s), static_cast<float**>(d), rad, s.getWidth(), s.getHeight(), multithread);
};
array2D<float> I1(w, h);
@ -225,10 +225,10 @@ void guidedFilter(const array2D<float> &guide, const array2D<float> &src, array2
DEBUG_DUMP(meanb);
// speedup by heckflosse67
const int Ws = meana.width();
const int Hs = meana.height();
const int Wd = q.width();
const int Hd = q.height();
const int Ws = meana.getWidth();
const int Hs = meana.getHeight();
const int Wd = q.getWidth();
const int Hd = q.getHeight();
const float col_scale = float(Ws) / float(Wd);
const float row_scale = float(Hs) / float(Hd);
@ -249,8 +249,8 @@ void guidedFilterLog(const array2D<float> &guide, float base, array2D<float> &ch
#ifdef _OPENMP
# pragma omp parallel for if (multithread)
#endif
for (int y = 0; y < chan.height(); ++y) {
for (int x = 0; x < chan.width(); ++x) {
for (int y = 0; y < chan.getHeight(); ++y) {
for (int x = 0; x < chan.getWidth(); ++x) {
chan[y][x] = xlin2log(max(chan[y][x], 0.f), base);
}
}
@ -260,8 +260,8 @@ void guidedFilterLog(const array2D<float> &guide, float base, array2D<float> &ch
#ifdef _OPENMP
# pragma omp parallel for if (multithread)
#endif
for (int y = 0; y < chan.height(); ++y) {
for (int x = 0; x < chan.width(); ++x) {
for (int y = 0; y < chan.getHeight(); ++y) {
for (int x = 0; x < chan.getWidth(); ++x) {
chan[y][x] = xlog2lin(max(chan[y][x], 0.f), base);
}
}

View File

@ -103,10 +103,10 @@ void restore(Imagefloat *rgb, float maxval, bool multithread)
}
}
int get_dark_channel(const array2D<float> &R, const array2D<float> &G, const array2D<float> &B, const array2D<float> &dst, int patchsize, const float ambient[3], bool clip, bool multithread, float strength)
int get_dark_channel(const array2D<float> &R, const array2D<float> &G, const array2D<float> &B, array2D<float> &dst, int patchsize, const float ambient[3], bool clip, bool multithread, float strength)
{
const int W = R.width();
const int H = R.height();
const int W = R.getWidth();
const int H = R.getHeight();
#ifdef _OPENMP
#pragma omp parallel for if (multithread)
@ -162,10 +162,10 @@ int get_dark_channel(const array2D<float> &R, const array2D<float> &G, const arr
return (W / patchsize + ((W % patchsize) > 0)) * (H / patchsize + ((H % patchsize) > 0));
}
int get_dark_channel_downsized(const array2D<float> &R, const array2D<float> &G, const array2D<float> &B, const array2D<float> &dst, int patchsize, bool multithread)
int get_dark_channel_downsized(const array2D<float> &R, const array2D<float> &G, const array2D<float> &B, array2D<float> &dst, int patchsize, bool multithread)
{
const int W = R.width();
const int H = R.height();
const int W = R.getWidth();
const int H = R.getHeight();
#ifdef _OPENMP
#pragma omp parallel for if (multithread)
@ -195,8 +195,8 @@ int get_dark_channel_downsized(const array2D<float> &R, const array2D<float> &G,
float estimate_ambient_light(const array2D<float> &R, const array2D<float> &G, const array2D<float> &B, const array2D<float> &dark, int patchsize, int npatches, float ambient[3])
{
const int W = R.width();
const int H = R.height();
const int W = R.getWidth();
const int H = R.getHeight();
float darklim = RT_INFINITY_F;
{

View File

@ -1840,8 +1840,8 @@ void tone_eq(array2D<float> &R, array2D<float> &G, array2D<float> &B, const stru
{
BENCHFUN
const int W = R.width();
const int H = R.height();
const int W = R.getWidth();
const int H = R.getHeight();
array2D<float> Y(W, H);
const auto log2 =

View File

@ -323,14 +323,14 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
cp.CHSLmet = 1;
cp.EDmet = 1;
cp.EDmet = 2;
/*
if (params->wavelet.EDmethod == "SL") {
cp.EDmet = 1;
} else if (params->wavelet.EDmethod == "CU") {
cp.EDmet = 2;
}
*/
cp.cbena = params->wavelet.cbenab;
cp.blhigh = (float)params->wavelet.bluehigh;
cp.grhigh = (float)params->wavelet.greenhigh;
@ -1579,10 +1579,16 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (numtiles > 1) {
float factor = Vmask[i1] * Hmask[j1];
if(L <= 0.f) {
L= 1.f;
}
dsttmp->L[i][j] += factor * L;
dsttmp->a[i][j] += factor * a;
dsttmp->b[i][j] += factor * b;
} else {
if(L <= 0.f) {
L= 1.f;
}
dsttmp->L[i][j] = L;
dsttmp->a[i][j] = a;
dsttmp->b[i][j] = b;
@ -2073,7 +2079,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
ContrastResid(WavCoeffs_L0, cp, W_L, H_L, maxp);
}
if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
// if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
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
const std::unique_ptr<LabImage> temp(new LabImage(W_L, H_L));
#ifdef _OPENMP
#pragma omp parallel for num_threads(wavNestedLevels) if (wavNestedLevels>1)
@ -2098,7 +2105,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
}
if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
// if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step
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
#ifdef _OPENMP
#pragma omp parallel for
#endif
@ -2208,9 +2216,9 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
for (int lvl = 0; lvl < 4; lvl++) {
for (int dir = 1; dir < 4; dir++) {
const float* const* WavCoeffs_LL = WaveletCoeffs_L.level_coeffs(lvl);
float tempkoeli;
float tempkoeli = 0.f;
calckoe (WavCoeffs_LL, gradw, tloww, koeLi, lvl , dir, W_L, H_L, edd, tempkoeli, tmC);
maxkoeLi[lvl * 3 + dir - 1] = tempkoeli;
maxkoeLi[lvl * 3 + dir - 1] = tempkoeli ;
// return convolution KoeLi and maxkoeLi of level 0 1 2 3 and Dir Horiz, Vert, Diag
}
}
@ -2766,7 +2774,6 @@ void ImProcFunctions::calckoe (const float* const* WavCoeffs_LL, float gradw, fl
if (koeLi[level * 3 + dir - 1][i * W_L + j] > maxkoeLi) {
maxkoeLi = koeLi[level * 3 + dir - 1][i * W_L + j];
}
float diff = maxkoeLi - koeLi[level * 3 + dir - 1][i * W_L + j];
diff *= diffFactor;
koeLi[level * 3 + dir - 1][i * W_L + j] = maxkoeLi - diff;
@ -2781,13 +2788,13 @@ void ImProcFunctions::finalContAllL(float* const* WavCoeffs_L, float * WavCoeffs
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] + cp.sigmafin * 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] * cp.sigmafin);
float bsig = 0.5f - asig * mean[level];
float amean = 0.5f / 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)
@ -3058,7 +3065,6 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz,
koe[i * W_L + j] = rtengine::min(thr2, std::fabs(tmC[i][j] / temp));
maxkoe = rtengine::max(maxkoe, koe[i * W_L + j]);
float diff = maxkoe - koe[i * W_L + j];
diff *= (cp.eddet / 100.f);
float interm = maxkoe - diff;
@ -3089,10 +3095,13 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz,
float atten01234 = 0.80f;
value *= (atten01234 * scaleskip[1]); //for zoom < 100% reduce strength...I choose level 1...but!!
}
float edghig = settings->edghi;//increase or reduce "reinforce"
float edglow = settings->edglo;//increase or reduce "reduce"
float limrad = settings->limrad;//threshold action in function radius (rad)
printf("edghi=%f edglo=%f limrad=%f\n", edghig, edglow, limrad);
// 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 lim0 = limrad; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi
float lev = float (level);
float repart = (float)cp.til;
@ -3100,15 +3109,14 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz,
if (cp.reinforce != 2) {
const float brepart =
cp.reinforce == 1
? 3.f
: 0.5f;
? edghig
: edglow;
const float arepart = -(brepart - 1.f) / (lim0 / 60.f);
if (rad < lim0 / 60.f) {
if (rad < (lim0 / 60.f)) {
repart *= (arepart * rad + brepart); //linear repartition of repart
}
}
float al0 = 1.f + (repart) / 50.f;
float al10 = 1.0f; //arbitrary value ==> less = take into account high levels
// float ak =-(al0-al10)/10.f;//10 = maximum levels
@ -3116,15 +3124,16 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz,
float bk = al0;
float koef = ak * level + bk; //modulate for levels : more levels high, more koef low ==> concentrated action on low levels, without or near for high levels
float expkoef = -std::pow(std::fabs(rad - lev), koef); //reduce effect for high levels
printf("repart=%f\n", repart);
if (cp.reinforce == 3) {
if (rad < lim0 / 60.f && level == 0) {
if (rad < (lim0 / 60.f) && level == 0) {
expkoef *= abs(repart); //reduce effect for low values of rad and level=0==> quasi only level 1 is effective
}
}
if (cp.reinforce == 1) {
if (rad < lim0 / 60.f && level == 1) {
if (rad < (lim0 / 60.f) && level == 1) {
expkoef /= repart; //increase effect for low values of rad and level=1==> quasi only level 0 is effective
}
}
@ -3158,13 +3167,13 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz,
// 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
float rapX = (mean[level] + 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]);
float bsig = 0.5f - asig * mean[level];
float amean = 0.5f / mean[level];
float amean = 0.5f / (mean[level]);
float absciss = 0.f;
float kinterm;
float kmul;

View File

@ -459,6 +459,7 @@ RetinexParams::RetinexParams() :
shadows(0),
stonalwidth(80),
radius(40),
complexmethod("normal"),
retinexMethod("high"),
retinexcolorspace("Lab"),
gammaretinex("none"),
@ -496,6 +497,7 @@ bool RetinexParams::operator ==(const RetinexParams& other) const
&& shadows == other.shadows
&& stonalwidth == other.stonalwidth
&& radius == other.radius
&& complexmethod == other.complexmethod
&& retinexMethod == other.retinexMethod
&& retinexcolorspace == other.retinexcolorspace
&& gammaretinex == other.gammaretinex
@ -2395,6 +2397,7 @@ WaveletParams::WaveletParams() :
CLmethod("all"),
Backmethod("grey"),
Tilesmethod("full"),
complexmethod("normal"),
daubcoeffmethod("4_"),
CHmethod("without"),
Medgreinf("less"),
@ -2527,6 +2530,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& CLmethod == other.CLmethod
&& Backmethod == other.Backmethod
&& Tilesmethod == other.Tilesmethod
&& complexmethod == other.complexmethod
&& daubcoeffmethod == other.daubcoeffmethod
&& CHmethod == other.CHmethod
&& Medgreinf == other.Medgreinf
@ -5025,6 +5029,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->retinex.limd, "Retinex", "Limd", retinex.limd, keyFile);
saveToKeyfile(!pedited || pedited->retinex.highl, "Retinex", "highl", retinex.highl, keyFile);
saveToKeyfile(!pedited || pedited->retinex.skal, "Retinex", "skal", retinex.skal, keyFile);
saveToKeyfile(!pedited || pedited->retinex.complexmethod, "Retinex", "complexMethod", retinex.complexmethod, keyFile);
saveToKeyfile(!pedited || pedited->retinex.retinexMethod, "Retinex", "RetinexMethod", retinex.retinexMethod, keyFile);
saveToKeyfile(!pedited || pedited->retinex.mapMethod, "Retinex", "mapMethod", retinex.mapMethod, keyFile);
saveToKeyfile(!pedited || pedited->retinex.viewMethod, "Retinex", "viewMethod", retinex.viewMethod, keyFile);
@ -5988,6 +5993,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
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);
saveToKeyfile(!pedited || pedited->wavelet.complexmethod, "Wavelet", "complexMethod", wavelet.complexmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.daubcoeffmethod, "Wavelet", "DaubMethod", wavelet.daubcoeffmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.CLmethod, "Wavelet", "ChoiceLevMethod", wavelet.CLmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.Backmethod, "Wavelet", "BackMethod", wavelet.Backmethod, keyFile);
@ -6494,6 +6500,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
if (keyFile.has_group("Retinex")) {
assignFromKeyfile(keyFile, "Retinex", "Median", pedited, retinex.medianmap, pedited->retinex.medianmap);
assignFromKeyfile(keyFile, "Retinex", "complexMethod", pedited, retinex.complexmethod, pedited->retinex.complexmethod);
assignFromKeyfile(keyFile, "Retinex", "RetinexMethod", pedited, retinex.retinexMethod, pedited->retinex.retinexMethod);
assignFromKeyfile(keyFile, "Retinex", "mapMethod", pedited, retinex.mapMethod, pedited->retinex.mapMethod);
assignFromKeyfile(keyFile, "Retinex", "viewMethod", pedited, retinex.viewMethod, pedited->retinex.viewMethod);
@ -7858,6 +7865,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "ChoiceLevMethod", pedited, wavelet.CLmethod, pedited->wavelet.CLmethod);
assignFromKeyfile(keyFile, "Wavelet", "BackMethod", pedited, wavelet.Backmethod, pedited->wavelet.Backmethod);
assignFromKeyfile(keyFile, "Wavelet", "TilesMethod", pedited, wavelet.Tilesmethod, pedited->wavelet.Tilesmethod);
assignFromKeyfile(keyFile, "Wavelet", "complexMethod", pedited, wavelet.complexmethod, pedited->wavelet.complexmethod);
assignFromKeyfile(keyFile, "Wavelet", "DaubMethod", pedited, wavelet.daubcoeffmethod, pedited->wavelet.daubcoeffmethod);
assignFromKeyfile(keyFile, "Wavelet", "CHromaMethod", pedited, wavelet.CHmethod, pedited->wavelet.CHmethod);
assignFromKeyfile(keyFile, "Wavelet", "Medgreinf", pedited, wavelet.Medgreinf, pedited->wavelet.Medgreinf);

View File

@ -336,6 +336,7 @@ struct RetinexParams {
int stonalwidth;
int radius;
Glib::ustring complexmethod;
Glib::ustring retinexMethod;
Glib::ustring retinexcolorspace;
Glib::ustring gammaretinex;
@ -1790,6 +1791,7 @@ struct WaveletParams {
Glib::ustring CLmethod;
Glib::ustring Backmethod;
Glib::ustring Tilesmethod;
Glib::ustring complexmethod;
Glib::ustring daubcoeffmethod;
Glib::ustring CHmethod;
Glib::ustring Medgreinf;

View File

@ -247,7 +247,7 @@ protected:
double cared,
double cablue,
bool avoidColourshift,
const array2D<float> &rawData,
array2D<float> &rawData,
double* fitParamsTransfer,
bool fitParamsIn,
bool fitParamsOut,

View File

@ -31,8 +31,8 @@ namespace rtengine
inline float getBilinearValue(const array2D<float> &src, float x, float y)
{
const int W = src.width();
const int H = src.height();
const int W = src.getWidth();
const int H = src.getHeight();
// Get integer and fractional parts of numbers
int xi = x;
@ -57,10 +57,10 @@ inline float getBilinearValue(const array2D<float> &src, float x, float y)
inline void rescaleBilinear(const array2D<float> &src, array2D<float> &dst, bool multithread)
{
const int Ws = src.width();
const int Hs = src.height();
const int Wd = dst.width();
const int Hd = dst.height();
const int Ws = src.getWidth();
const int Hs = src.getHeight();
const int Wd = dst.getWidth();
const int Hd = dst.getHeight();
float col_scale = float (Ws) / float (Wd);
float row_scale = float (Hs) / float (Hd);
@ -81,10 +81,10 @@ inline void rescaleBilinear(const array2D<float> &src, array2D<float> &dst, bool
inline void rescaleNearest(const array2D<float> &src, array2D<float> &dst, bool multithread)
{
const int width = src.width();
const int height = src.height();
const int nw = dst.width();
const int nh = dst.height();
const int width = src.getWidth();
const int height = src.getHeight();
const int nw = dst.getWidth();
const int nh = dst.getHeight();
#ifdef _OPENMP
#pragma omp parallel for if (multithread)

View File

@ -99,6 +99,10 @@ public:
int itcwb_delta;
bool itcwb_stdobserver10;
int itcwb_precis;
//wavelet levels
double edghi;
double edglo;
double limrad;
enum class ThumbnailInspectorMode {

View File

@ -123,12 +123,12 @@ public:
int getRows() const
{
return const_cast<Array2Df &>(*this).height();
return const_cast<Array2Df &>(*this).getHeight();
}
int getCols() const
{
return const_cast<Array2Df &>(*this).width();
return const_cast<Array2Df &>(*this).getWidth();
}
float *data()

View File

@ -42,6 +42,7 @@
#include "pathutils.h"
#include "thumbnail.h"
#include "toolbar.h"
#include "inspector.h"
using namespace std;
@ -2508,6 +2509,15 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event)
}
}
if (!ctrl && !alt) {
switch (event->keyval) {
case GDK_KEY_f:
case GDK_KEY_F:
fileBrowser->getInspector()->showWindow(!shift);
return true;
}
}
return fileBrowser->keyPressed(event);
}

View File

@ -115,9 +115,9 @@ FilePanel::FilePanel () : parent(nullptr), error(0)
Gtk::Label* devLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_DEVELOP")) );
devLab->set_name ("LabelRightNotebook");
devLab->set_angle (90);
Gtk::Label* inspectLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_INSPECT")) );
inspectLab->set_name ("LabelRightNotebook");
inspectLab->set_angle (90);
//Gtk::Label* inspectLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_INSPECT")) );
//inspectLab->set_name ("LabelRightNotebook");
//inspectLab->set_angle (90);
Gtk::Label* filtLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_FILTER")) );
filtLab->set_name ("LabelRightNotebook");
filtLab->set_angle (90);
@ -132,7 +132,7 @@ FilePanel::FilePanel () : parent(nullptr), error(0)
tpcPaned->pack2 (*history, true, false);
rightNotebook->append_page (*sFilterPanel, *filtLab);
rightNotebook->append_page (*inspectorPanel, *inspectLab);
//rightNotebook->append_page (*inspectorPanel, *inspectLab);
rightNotebook->append_page (*tpcPaned, *devLab);
//rightNotebook->append_page (*taggingBox, *tagLab); commented out: currently the tab is empty ...
rightNotebook->append_page (*sExportPanel, *exportLab);

View File

@ -82,9 +82,25 @@ InspectorBuffer::~InspectorBuffer() {
// return deg;
//}
Inspector::Inspector () : currImage(nullptr), zoom(0.0), active(false)
Inspector::Inspector () : currImage(nullptr), scaled(false), scale(1.0), zoomScale(1.0), zoomScaleBegin(1.0), active(false), pinned(false), dirty(false)
{
set_name("Inspector");
window.set_visible(false);
window.set_title("RawTherapee Inspector");
window.add_events(Gdk::KEY_PRESS_MASK);
window.signal_key_release_event().connect(sigc::mem_fun(*this, &Inspector::on_key_release));
window.signal_key_press_event().connect(sigc::mem_fun(*this, &Inspector::on_key_press));
add_events(Gdk::BUTTON_PRESS_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
gestureZoom = Gtk::GestureZoom::create(*this);
gestureZoom->signal_begin().connect(sigc::mem_fun(*this, &Inspector::on_zoom_begin));
gestureZoom->signal_scale_changed().connect(sigc::mem_fun(*this, &Inspector::on_zoom_scale_changed));
window.add(*this);
window.show_all();
window.set_visible(false);
active = true; // always track inspected thumbnails
}
Inspector::~Inspector()
@ -92,8 +108,184 @@ Inspector::~Inspector()
deleteBuffers();
}
void Inspector::showWindow(bool scaled)
{
this->scaled = scaled;
window.fullscreen();
window.set_visible(true);
pinned = false;
}
bool Inspector::on_key_release(GdkEventKey *event)
{
if (!pinned) {
switch (event->keyval) {
case GDK_KEY_f:
case GDK_KEY_F:
zoomScale = 1.0;
window.set_visible(false);
return true;
}
}
return false;
}
bool Inspector::on_key_press(GdkEventKey *event)
{
switch (event->keyval) {
case GDK_KEY_z:
case GDK_KEY_F:
if (pinned || scaled)
zoomScale = 1.0; // reset if not key hold
scaled = false;
queue_draw();
return true;
case GDK_KEY_f:
if (pinned || !scaled)
zoomScale = 1.0; // reset if not key hold
scaled = true;
queue_draw();
return true;
case GDK_KEY_Escape:
zoomScale = 1.0;
window.set_visible(false);
return true;
}
return false;
}
bool Inspector::on_button_press_event(GdkEventButton *event)
{
if (event->type == GDK_BUTTON_PRESS) {
if (!pinned)
// pin window with mouse click
pinned = true;
return true;
}
return false;
}
bool Inspector::on_scroll_event(GdkEventScroll *event)
{
if (!currImage)
return false;
bool alt = event->state & GDK_MOD1_MASK;
int deviceScale = get_scale_factor();
int imW = currImage->imgBuffer.getWidth();
int imH = currImage->imgBuffer.getHeight();
#ifdef GDK_WINDOWING_QUARTZ
// event reports speed of scroll wheel
double step_x = -event->delta_x;
double step_y = event->delta_y;
#else
// assume fixed step of 5%
double step_x = 5;
double step_y = 5;
#endif
int delta_x = 0;
int delta_y = 0;
switch (event->direction) {
case GDK_SCROLL_SMOOTH:
#ifdef GDK_WINDOWING_QUARTZ
// no additional step for smooth scrolling
delta_x = event->delta_x * deviceScale;
delta_y = event->delta_y * deviceScale;
#else
// apply step to smooth scrolling as well
delta_x = event->delta_x * deviceScale * step_x * imW / 100;
delta_y = event->delta_y * deviceScale * step_y * imH / 100;
#endif
break;
case GDK_SCROLL_DOWN:
delta_y = step_y * deviceScale * imH / 100;
break;
case GDK_SCROLL_UP:
delta_y = -step_y * deviceScale * imH / 100;
break;
case GDK_SCROLL_LEFT:
delta_x = step_x * deviceScale * imW / 100;
break;
case GDK_SCROLL_RIGHT:
delta_x = -step_x * deviceScale * imW / 100;
break;
}
if (alt) {
// zoom
beginZoom(event->x, event->y);
if (std::fabs(delta_y) > std::fabs(delta_x))
on_zoom_scale_changed(1.0 - (double)delta_y / imH / deviceScale);
else
on_zoom_scale_changed(1.0 - (double)delta_x / imW / deviceScale);
return true;
}
// scroll
moveCenter(delta_x, delta_y, imW, imH, deviceScale);
if (!dirty) {
dirty = true;
queue_draw();
}
return true;
}
void Inspector::moveCenter(int delta_x, int delta_y, int imW, int imH, int deviceScale)
{
rtengine::Coord margin; // limit to image size
margin.x = rtengine::min<int>(window.get_width() * deviceScale / scale, imW) / 2;
margin.y = rtengine::min<int>(window.get_height() * deviceScale / scale, imH) / 2;
center.set(rtengine::LIM<int>(center.x + delta_x, margin.x, imW - margin.x),
rtengine::LIM<int>(center.y + delta_y, margin.y, imH - margin.y));
}
void Inspector::beginZoom(double x, double y)
{
int deviceScale = get_scale_factor();
int imW = currImage->imgBuffer.getWidth();
int imH = currImage->imgBuffer.getHeight();
// limit center to image size
moveCenter(0, 0, imW, imH, deviceScale);
// store center and current position for zooming
dcenterBegin.x = (x - window.get_width()/2) / scale * deviceScale;
dcenterBegin.y = (y - window.get_height()/2) / scale * deviceScale;
centerBegin = center;
zoomScaleBegin = zoomScale;
}
void Inspector::on_zoom_begin(GdkEventSequence *s)
{
double x, y;
if (gestureZoom->get_point(s, x, y))
beginZoom(x, y);
}
void Inspector::on_zoom_scale_changed(double zscale)
{
if (!currImage)
return;
zoomScale = rtengine::LIM<double>(zoomScaleBegin * zscale, 0.01, 16.0);
double dcenterRatio = 1.0 - zoomScaleBegin / zoomScale;
center.x = centerBegin.x + dcenterBegin.x * dcenterRatio;
center.y = centerBegin.y + dcenterBegin.y * dcenterRatio;
if (!dirty) {
dirty = true;
queue_draw();
}
}
bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
{
dirty = false;
Glib::RefPtr<Gdk::Window> win = get_window();
@ -116,10 +308,24 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
rtengine::Coord availableSize;
rtengine::Coord topLeft;
rtengine::Coord dest(0, 0);
availableSize.x = win->get_width();
availableSize.y = win->get_height();
int imW = currImage->imgBuffer.getWidth();
int imH = currImage->imgBuffer.getHeight();
int deviceScale = get_scale_factor();
availableSize.x = win->get_width() * deviceScale;
availableSize.y = win->get_height() * deviceScale;
int imW = rtengine::max<int>(currImage->imgBuffer.getWidth(), 1);
int imH = rtengine::max<int>(currImage->imgBuffer.getHeight(), 1);
scale = rtengine::min<double>((double)availableSize.x / imW, (double)availableSize.y / imH);
if (scaled) {
// reduce size of image to fit into window, no further zoom down
zoomScale = rtengine::max<double>(zoomScale, 1.0);
scale *= zoomScale;
}
else {
// limit zoom to fill at least complete window or 1:1
zoomScale = rtengine::max<double>(zoomScale, rtengine::min<double>(1.0, scale));
scale = zoomScale;
}
availableSize.x /= scale;
availableSize.y /= scale;
if (imW < availableSize.x) {
// center the image in the available space along X
@ -146,7 +352,6 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
topLeft.y -= availableSize.y;
topLeft.y = rtengine::max<int>(topLeft.y, 0);
}
//printf("center: %d, %d (img: %d, %d) (availableSize: %d, %d) (topLeft: %d, %d)\n", center.x, center.y, imW, imH, availableSize.x, availableSize.y, topLeft.x, topLeft.y);
// define the destination area
@ -163,24 +368,50 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
Glib::RefPtr<Gtk::StyleContext> style = get_style_context();
// draw the background
style->render_background(cr, 0, 0, get_width(), get_height());
//style->render_background(cr, 0, 0, get_width(), get_height());
/* --- old method
///* --- old method (the new method does not seem to work)
c = style->get_background_color (Gtk::STATE_FLAG_NORMAL);
cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue());
cr->set_line_width (0);
cr->rectangle (0, 0, availableSize.x, availableSize.y);
cr->fill ();
*/
//*/
currImage->imgBuffer.copySurface(win);
bool scaledImage = scale != 1.0;
if (deviceScale == 1 && !scaledImage) {
// standard drawing
currImage->imgBuffer.copySurface(win);
}
else {
// consider device scale and image scale
if (deviceScale > 1) {
// use full device resolution and let it scale the image (macOS)
cairo_surface_set_device_scale(cr->get_target()->cobj(), scale, scale);
scaledImage = false;
}
int viewW = rtengine::min<int>(imW, availableSize.x);
int viewH = rtengine::min<int>(imH, availableSize.y);
Glib::RefPtr<Gdk::Pixbuf> crop = Gdk::Pixbuf::create(currImage->imgBuffer.getSurface(), topLeft.x, topLeft.y, viewW, viewH);
if (!scaledImage) {
Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x, dest.y);
}
else {
// scale crop as the device does not seem to support it (Linux)
crop = crop->scale_simple(viewW*scale, viewH*scale, Gdk::INTERP_BILINEAR);
Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x*scale, dest.y*scale);
}
cr->paint();
}
/* --- not for separate window
// draw the frame
c = style->get_border_color (Gtk::STATE_FLAG_NORMAL);
cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue());
cr->set_line_width (1);
cr->rectangle (0.5, 0.5, availableSize.x - 1, availableSize.y - 1);
cr->stroke ();
*/
}
return true;
@ -309,7 +540,7 @@ void Inspector::setActive(bool state)
flushBuffers();
}
active = state;
//active = state;
}

View File

@ -47,12 +47,30 @@ private:
rtengine::Coord center;
std::vector<InspectorBuffer*> images;
InspectorBuffer* currImage;
double zoom;
bool scaled; // fit image into window
double scale; // current scale
double zoomScale, zoomScaleBegin; // scale during zoom
rtengine::Coord centerBegin, dcenterBegin; // center during zoom
bool active;
bool pinned;
bool dirty;
sigc::connection delayconn;
Glib::ustring next_image_path;
Gtk::Window window;
bool on_key_release(GdkEventKey *event);
bool on_key_press(GdkEventKey *event);
bool on_button_press_event(GdkEventButton *event) override;
bool on_scroll_event(GdkEventScroll *event) override;
void moveCenter(int delta_x, int delta_y, int imW, int imH, int deviceScale);
Glib::RefPtr<Gtk::GestureZoom> gestureZoom;
void beginZoom(double x, double y);
void on_zoom_begin(GdkEventSequence *);
void on_zoom_scale_changed(double zscale);
bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override;
void deleteBuffers();
@ -62,6 +80,11 @@ public:
Inspector();
~Inspector() override;
/** @brief Show or hide window
* @param scaled fit image into window
*/
void showWindow(bool scaled);
/** @brief Mouse movement to a new position
* @param pos Location of the mouse, in percentage (i.e. [0;1] range) relative to the full size image ; -1,-1 == out of the image
* @param transform H/V flip and coarse rotation transformation

View File

@ -663,6 +663,8 @@ void LCurve::updateCurveBackgroundHistogram(
{
lshape->updateBackgroundHistogram (histLCurve);
ccshape->updateBackgroundHistogram (histCCurve);
lcshape->updateBackgroundHistogram (histCCurve);
clshape->updateBackgroundHistogram (histLCurve);
}
void LCurve::setAdjusterBehavior (bool bradd, bool contradd, bool satadd)

View File

@ -618,6 +618,12 @@ void Options::setDefaults()
rtSettings.itcwb_precis = 5;//3 or 5 or 9
// end locallab
//wavelet
rtSettings.edghi = 3.0;//1.1 and 5.
rtSettings.edglo = 0.5;//0.1 and 0.95
rtSettings.limrad = 20.;//1 and 60
rtSettings.protectred = 60;
rtSettings.protectredh = 0.3;
rtSettings.CRI_color = 0;
@ -1709,6 +1715,22 @@ void Options::readFromFile(Glib::ustring fname)
}
if (keyFile.has_group("Wavelet")) {
if (keyFile.has_key("Wavelet", "Edghi")) {
rtSettings.edghi = keyFile.get_double("Wavelet", "Edghi");
}
if (keyFile.has_key("Wavelet", "Edglo")) {
rtSettings.edglo = keyFile.get_double("Wavelet", "Edglo");
}
if (keyFile.has_key("Wavelet", "Limrad")) {
rtSettings.limrad = keyFile.get_double("Wavelet", "Limrad");
}
}
if (keyFile.has_group("ICC Profile Creator")) {
if (keyFile.has_key("ICC Profile Creator", "PimariesPreset")) {
ICCPC_primariesPreset = keyFile.get_string("ICC Profile Creator", "PimariesPreset");
@ -2308,6 +2330,11 @@ void Options::saveToFile(Glib::ustring fname)
keyFile.set_integer("Color Management", "Previewselection", rtSettings.previewselection);
keyFile.set_double("Color Management", "Cbdlsensi", rtSettings.cbdlsensi);
keyFile.set_double("Wavelet", "Edghi", rtSettings.edghi);
keyFile.set_double("Wavelet", "Edglo", rtSettings.edglo);
keyFile.set_double("Wavelet", "Limrad", rtSettings.limrad);
keyFile.set_string("ICC Profile Creator", "PimariesPreset", ICCPC_primariesPreset);
keyFile.set_double("ICC Profile Creator", "RedPrimaryX", ICCPC_redPrimaryX);
keyFile.set_double("ICC Profile Creator", "RedPrimaryY", ICCPC_redPrimaryY);

View File

@ -60,6 +60,7 @@ void ParamsEdited::set(bool v)
retinex.mapcurve = v;
retinex.cdHcurve = v;
retinex.lhcurve = v;
retinex.complexmethod = v;
retinex.retinexMethod = v;
retinex.mapMethod = v;
retinex.viewMethod = v;
@ -531,6 +532,7 @@ void ParamsEdited::set(bool v)
wavelet.CLmethod = v;
wavelet.Backmethod = v;
wavelet.Tilesmethod = v;
wavelet.complexmethod = v;
wavelet.daubcoeffmethod = v;
wavelet.CHmethod = v;
wavelet.CHSLmethod = v;
@ -710,6 +712,7 @@ void ParamsEdited::initFrom(const std::vector<rtengine::procparams::ProcParams>&
retinex.lhcurve = retinex.lhcurve && p.retinex.lhcurve == other.retinex.lhcurve;
retinex.transmissionCurve = retinex.transmissionCurve && p.retinex.transmissionCurve == other.retinex.transmissionCurve;
retinex.gaintransmissionCurve = retinex.gaintransmissionCurve && p.retinex.gaintransmissionCurve == other.retinex.gaintransmissionCurve;
retinex.complexmethod = retinex.complexmethod && p.retinex.complexmethod == other.retinex.complexmethod;
retinex.retinexMethod = retinex.retinexMethod && p.retinex.retinexMethod == other.retinex.retinexMethod;
retinex.mapMethod = retinex.mapMethod && p.retinex.mapMethod == other.retinex.mapMethod;
retinex.viewMethod = retinex.viewMethod && p.retinex.viewMethod == other.retinex.viewMethod;
@ -1679,6 +1682,7 @@ void ParamsEdited::initFrom(const std::vector<rtengine::procparams::ProcParams>&
wavelet.CLmethod = wavelet.CLmethod && p.wavelet.CLmethod == other.wavelet.CLmethod;
wavelet.Backmethod = wavelet.Backmethod && p.wavelet.Backmethod == other.wavelet.Backmethod;
wavelet.Tilesmethod = wavelet.Tilesmethod && p.wavelet.Tilesmethod == other.wavelet.Tilesmethod;
wavelet.complexmethod = wavelet.complexmethod && p.wavelet.complexmethod == other.wavelet.complexmethod;
wavelet.daubcoeffmethod = wavelet.daubcoeffmethod && p.wavelet.daubcoeffmethod == other.wavelet.daubcoeffmethod;
wavelet.CHmethod = wavelet.CHmethod && p.wavelet.CHmethod == other.wavelet.CHmethod;
wavelet.CHSLmethod = wavelet.CHSLmethod && p.wavelet.CHSLmethod == other.wavelet.CHSLmethod;
@ -1915,6 +1919,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.retinex.gaintransmissionCurve = mods.retinex.gaintransmissionCurve;
}
if (retinex.complexmethod) {
toEdit.retinex.complexmethod = mods.retinex.complexmethod;
}
if (retinex.retinexMethod) {
toEdit.retinex.retinexMethod = mods.retinex.retinexMethod;
}
@ -5574,6 +5582,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod;
}
if (wavelet.complexmethod) {
toEdit.wavelet.complexmethod = mods.wavelet.complexmethod;
}
if (wavelet.daubcoeffmethod) {
toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod;
}

View File

@ -73,6 +73,7 @@ struct RetinexParamsEdited {
bool slope;
bool neigh;
bool offs;
bool complexmethod;
bool retinexMethod;
bool mapMethod;
bool viewMethod;
@ -1039,6 +1040,7 @@ struct WaveletParamsEdited {
bool CLmethod;
bool Backmethod;
bool Tilesmethod;
bool complexmethod;
bool daubcoeffmethod;
bool Dirmethod;
bool sigma;

View File

@ -9,6 +9,7 @@
#include "rtimage.h"
#include "options.h"
#include "../rtengine/color.h"
#include "eventmapper.h"
using namespace rtengine;
using namespace rtengine::procparams;
@ -25,13 +26,26 @@ Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL")
nextsigma = 0.;
nextminT = 0.;
nextmaxT = 0.;
auto m = ProcEventMapper::getInstance();
EvReticomplex = m->newEvent(DEMOSAIC, "HISTORY_MSG_COMPLEXRETI");
const RetinexParams default_params;
// MAIN Expander ==================================================================
complexmethod = Gtk::manage (new MyComboBoxText ());
complexmethod->append(M("TP_WAVELET_COMPNORMAL"));
complexmethod->append(M("TP_WAVELET_COMPEXPERT"));
complexmethodconn = complexmethod->signal_changed().connect(sigc::mem_fun(*this, &Retinex::complexmethodChanged));
complexmethod->set_tooltip_text(M("TP_WAVELET_COMPLEX_TOOLTIP"));
Gtk::HBox* const complexHBox = Gtk::manage(new Gtk::HBox());
Gtk::Label* const complexLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_COMPLEXLAB") + ":"));
complexHBox->pack_start(*complexLabel, Gtk::PACK_SHRINK, 4);
complexHBox->pack_start(*complexmethod);
pack_start(*complexHBox);
Gtk::Grid *retinexGrid = Gtk::manage ( new Gtk::Grid());
@ -116,7 +130,8 @@ Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL")
// MAP (MASK) Frame ---------------------------------------------------------------
Gtk::Frame *maskFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_LABEL_MASK")) );
// Gtk::Frame *maskFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_LABEL_MASK")) );
maskFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_LABEL_MASK")) );
setExpandAlignProperties (maskFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
Gtk::Grid *maskGrid = Gtk::manage ( new Gtk::Grid());
@ -384,7 +399,6 @@ Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL")
Gtk::Grid *tranGrid = Gtk::manage (new Gtk::Grid());
setExpandAlignProperties (tranGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
const RetinexParams default_params;
// Transmission map curve
transmissionCurveEditorG = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_TRANSMISSION"));
@ -628,12 +642,14 @@ void Retinex::neutral_pressed ()
limd->resetValue (false);
highl->resetValue (false);
gam->resetValue (false);
skal->resetValue (false);
slope->resetValue (false);
highlights->resetValue (false);
h_tonalwidth->resetValue (false);
shadows->resetValue (false);
s_tonalwidth->resetValue (false);
radius->resetValue (false);
medianmap->set_active (false);
mapMethod->set_active (0);
viewMethod->set_active (0);
retinexMethod->set_active (2);
@ -742,7 +758,53 @@ void Retinex::updateTrans ()
}
}
void Retinex::convertParamToNormal()
{
const RetinexParams def_params;
disableListener();
iter->setValue(def_params.iter);
viewMethod->set_active(0);
mapMethod->set_active(0);
cdshape->reset();
cdshapeH->reset();
lhshape->reset();
transmissionShape->reset();
medianmap->set_active(def_params.medianmap);
enableListener();
}
void Retinex::updateGUIToMode(int mode)
{
if(mode ==0) {
iterFrame->hide();
maskFrame->hide();
equalFrame->hide();
viewMethod->hide();
mapMethod->hide();
transmissionCurveEditorG->hide();
medianmap->hide();
} else {
iterFrame->show();
maskFrame->show();
equalFrame->show();
viewMethod->show();
transmissionCurveEditorG->show();
medianmap->show();
mapMethod->show();
if (iter->getIntValue() > 1) {
grad->set_sensitive (true);
scal->set_sensitive (true);
grads->set_sensitive (true);
} else {
grad->set_sensitive (false);
scal->set_sensitive (false);
grads->set_sensitive (false);
}
}
}
void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
{
@ -752,6 +814,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
gammaretinexConn.block (true);
mapMethodConn.block (true);
viewMethodConn.block (true);
complexmethodconn.block (true);
if (pedited) {
@ -775,6 +838,9 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
shadows->setEditedState (pedited->retinex.shadows ? Edited : UnEdited);
s_tonalwidth->setEditedState (pedited->retinex.stonalwidth ? Edited : UnEdited);
if (!pedited->retinex.complexmethod) {
complexmethod->set_active_text (M ("GENERAL_UNCHANGED"));
}
if (!pedited->retinex.retinexMethod) {
retinexMethod->set_active_text (M ("GENERAL_UNCHANGED"));
@ -844,6 +910,13 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
medianmapConn.block (false);
lastmedianmap = pp->retinex.medianmap;
if (pp->retinex.complexmethod == "normal") {
complexmethod->set_active(0);
} else if (pp->retinex.complexmethod == "expert") {
complexmethod->set_active(1);
}
if (pp->retinex.retinexMethod == "low") {
retinexMethod->set_active (0);
} else if (pp->retinex.retinexMethod == "uni") {
@ -906,6 +979,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
mapMethodChanged ();
viewMethodChanged ();
medianmapConn.block (true);
medianmapChanged ();
medianmapConn.block (false);
@ -914,7 +988,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
cdshapeH->setCurve (pp->retinex.cdHcurve);
lhshape->setCurve (pp->retinex.lhcurve);
mapshape->setCurve (pp->retinex.mapcurve);
retinexMethodConn.block (false);
retinexColorSpaceConn.block (false);
gammaretinexConn.block (false);
@ -923,8 +997,18 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited)
transmissionShape->setCurve (pp->retinex.transmissionCurve);
gaintransmissionShape->setCurve (pp->retinex.gaintransmissionCurve);
complexmethodconn.block (false);
enableListener ();
if (complexmethod->get_active_row_number() == 0) {
updateGUIToMode(0);
// convertParamToNormal();
} else {
updateGUIToMode(1);
}
}
@ -961,6 +1045,7 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited)
pp->retinex.stonalwidth = (int)s_tonalwidth->getValue ();
if (pedited) {
pedited->retinex.complexmethod = complexmethod->get_active_text() != M ("GENERAL_UNCHANGED");
pedited->retinex.retinexMethod = retinexMethod->get_active_text() != M ("GENERAL_UNCHANGED");
pedited->retinex.retinexcolorspace = retinexcolorspace->get_active_text() != M ("GENERAL_UNCHANGED");
pedited->retinex.gammaretinex = gammaretinex->get_active_text() != M ("GENERAL_UNCHANGED");
@ -998,6 +1083,12 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited)
}
if (complexmethod->get_active_row_number() == 0) {
pp->retinex.complexmethod = "normal";
} else if (complexmethod->get_active_row_number() == 1) {
pp->retinex.complexmethod = "expert";
}
if (retinexMethod->get_active_row_number() == 0) {
pp->retinex.retinexMethod = "low";
} else if (retinexMethod->get_active_row_number() == 1) {
@ -1056,6 +1147,27 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited)
}
void Retinex::complexmethodChanged()
{
if (!batchMode) {
if (complexmethod->get_active_row_number() == 0) {
updateGUIToMode(0);
convertParamToNormal();
} else {
updateGUIToMode(1);
}
}
if (listener) {
listener->panelChanged(EvReticomplex, complexmethod->get_active_text());
}
}
void Retinex::retinexMethodChanged()
{
@ -1138,8 +1250,11 @@ void Retinex::viewMethodChanged()
limd->show();
transmissionCurveEditorG->show();
medianmap->show();
iterFrame->show();
if (complexmethod->get_active_row_number() == 0) {
iterFrame->hide();
} else {
iterFrame->show();
}
/*
iter->show();
scal->show();
@ -1522,6 +1637,7 @@ void Retinex::setBatchMode (bool batchMode)
h_tonalwidth->showEditedCB ();
shadows->showEditedCB ();
s_tonalwidth->showEditedCB ();
// complexmethod->append(M("GENERAL_UNCHANGED"));
skal->showEditedCB ();
curveEditorGD->setBatchMode (batchMode);

View File

@ -28,6 +28,7 @@ class Retinex final :
{
private:
IdleRegister idle_register;
rtengine::ProcEvent EvReticomplex;
protected:
CurveEditorGroup* curveEditorGD;
@ -72,6 +73,9 @@ protected:
MyComboBoxText* mapMethod;
MyComboBoxText* viewMethod;
Gtk::CheckButton* medianmap;
MyComboBoxText* complexmethod;
sigc::connection complexmethodconn;
double nextmin;
double nextmax;
double nextminiT;
@ -87,6 +91,7 @@ protected:
Gtk::Frame *gainFrame;
Gtk::Frame *tranFrame;
Gtk::Frame *iterFrame;
Gtk::Frame *maskFrame;
Gtk::Frame *equalFrame;
DiagonalCurveEditor* cdshape;
@ -148,4 +153,7 @@ public:
private:
void foldAllButMe(GdkEventButton* event, MyExpander *expander);
void convertParamToNormal();
void updateGUIToMode(int mode);
void complexmethodChanged();
};

View File

@ -158,6 +158,7 @@ Wavelet::Wavelet() :
HSmethod(Gtk::manage(new MyComboBoxText())),
CLmethod(Gtk::manage(new MyComboBoxText())),
Backmethod(Gtk::manage(new MyComboBoxText())),
complexmethod(Gtk::manage(new MyComboBoxText())),
Tilesmethod(Gtk::manage(new MyComboBoxText())),
daubcoeffmethod(Gtk::manage(new MyComboBoxText())),
Dirmethod(Gtk::manage(new MyComboBoxText())),
@ -190,7 +191,10 @@ Wavelet::Wavelet() :
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()))
usharpHBox(Gtk::manage(new Gtk::HBox())),
ctboxch(Gtk::manage(new Gtk::HBox())),
ctboxBA(Gtk::manage(new Gtk::VBox()))
{
CurveListener::setMulti(true);
auto m = ProcEventMapper::getInstance();
@ -227,6 +231,7 @@ Wavelet::Wavelet() :
EvWavrangeab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_RANGEAB");
EvWavprotab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_PROTAB");
EvWavlevelshc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_LEVELSHC");
EvWavcomplexmet = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_COMPLEX");
labgrid = Gtk::manage(new LabGrid(EvWavLabGridValue, M("TP_WAVELET_LABGRID_VALUES")));
@ -269,6 +274,16 @@ Wavelet::Wavelet() :
thres->set_tooltip_text(M("TP_WAVELET_LEVELS_TOOLTIP"));
thres->setAdjusterListener(this);
complexmethod->append(M("TP_WAVELET_COMPNORMAL"));
complexmethod->append(M("TP_WAVELET_COMPEXPERT"));
complexmethodconn = complexmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::complexmethodChanged));
complexmethod->set_tooltip_text(M("TP_WAVELET_COMPLEX_TOOLTIP"));
Gtk::HBox* const complexHBox = Gtk::manage(new Gtk::HBox());
Gtk::Label* const complexLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_COMPLEXLAB") + ":"));
complexHBox->pack_start(*complexLabel, Gtk::PACK_SHRINK, 4);
complexHBox->pack_start(*complexmethod);
Tilesmethod->append(M("TP_WAVELET_TILESFULL"));
Tilesmethod->append(M("TP_WAVELET_TILESBIG"));
// Tilesmethod->append(M("TP_WAVELET_TILESLIT"));
@ -335,6 +350,7 @@ Wavelet::Wavelet() :
levdirSubHBox->pack_start(*Lmethod);
levdirSubHBox->pack_start(*Dirmethod, Gtk::PACK_EXPAND_WIDGET, 2); // same, but 2 not 4?
settingsBox->pack_start(*complexHBox);
settingsBox->pack_start(*strength);
settingsBox->pack_start(*thres);
settingsBox->pack_start(*tilesizeHBox);
@ -452,7 +468,7 @@ Wavelet::Wavelet() :
ToolParamBlock* const chBox = Gtk::manage(new ToolParamBlock());
Gtk::Label* const labmch = Gtk::manage(new Gtk::Label(M("TP_WAVELET_CHTYPE") + ":"));
Gtk::HBox* const ctboxch = Gtk::manage(new Gtk::HBox());
// Gtk::HBox* const ctboxch = Gtk::manage(new Gtk::HBox());
ctboxch->pack_start(*labmch, Gtk::PACK_SHRINK, 1);
CHmethod->append(M("TP_WAVELET_CH1"));
@ -674,7 +690,7 @@ Wavelet::Wavelet() :
EDmethod->append(M("TP_WAVELET_EDCU"));
EDmethodconn = EDmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::EDmethodChanged));
ctboxED->pack_start(*EDmethod);
edgBox->pack_start(*ctboxED);
// edgBox->pack_start(*ctboxED);
edgcont->setAdjusterListener(this);
edgcont->setBgGradient(milestones2);
@ -838,7 +854,7 @@ Wavelet::Wavelet() :
thrH->setAdjusterListener(this);
radius->setAdjusterListener(this);
radius->hide();
// radius->hide();
shFrame->set_label_align(0.025, 0.5);
ToolParamBlock* const shBox = Gtk::manage(new ToolParamBlock());
@ -1007,7 +1023,7 @@ Wavelet::Wavelet() :
resBox->pack_start(*neutrHBox);
// Final Touchup
Gtk::VBox* const ctboxBA = Gtk::manage(new Gtk::VBox());
// Gtk::VBox* const ctboxBA = Gtk::manage(new Gtk::VBox());
ctboxBA->set_spacing(2);
@ -1236,6 +1252,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
CLmethodconn.block(true);
Backmethodconn.block(true);
Tilesmethodconn.block(true);
complexmethodconn.block(true);
daubcoeffmethodconn.block(true);
Dirmethodconn.block(true);
CHmethodconn.block(true);
@ -1357,6 +1374,12 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
} else if (pp->wavelet.CLmethod == "all") {
CLmethod->set_active(3);
}
if (pp->wavelet.complexmethod == "normal") {
complexmethod->set_active(0);
} else if (pp->wavelet.complexmethod == "expert") {
complexmethod->set_active(1);
}
//Tilesmethod->set_active (2);
if (pp->wavelet.Tilesmethod == "full") {
@ -1558,6 +1581,11 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
Backmethod->set_active_text(M("GENERAL_UNCHANGED"));
}
if (!pedited->wavelet.complexmethod) {
complexmethod->set_active_text(M("GENERAL_UNCHANGED"));
}
if (!pedited->wavelet.Tilesmethod) {
Tilesmethod->set_active_text(M("GENERAL_UNCHANGED"));
}
@ -1774,6 +1802,15 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
} else {
sup->hide();
}
if (complexmethod->get_active_row_number() == 0) {
updateGUIToMode(0);
convertParamToNormal();
} else {
updateGUIToMode(1);
}
}
/*****************************************************************************************************
@ -1786,6 +1823,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited)
CLmethodconn.block(false);
Backmethodconn.block(false);
Tilesmethodconn.block(false);
complexmethodconn.block(false);
daubcoeffmethodconn.block(false);
CHmethodconn.block(false);
CHSLmethodconn.block(false);
@ -1965,6 +2003,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
pedited->wavelet.CLmethod = CLmethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->wavelet.Backmethod = Backmethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->wavelet.Tilesmethod = Tilesmethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->wavelet.complexmethod = complexmethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->wavelet.daubcoeffmethod = daubcoeffmethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->wavelet.CHmethod = CHmethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->wavelet.CHSLmethod = CHSLmethod->get_active_text() != M("GENERAL_UNCHANGED");
@ -2168,6 +2207,12 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited)
// pp->wavelet.Tilesmethod = "lit";
}
if (complexmethod->get_active_row_number() == 0) {
pp->wavelet.complexmethod = "normal";
} else if (complexmethod->get_active_row_number() == 1) {
pp->wavelet.complexmethod = "expert";
}
if (daubcoeffmethod->get_active_row_number() == 0) {
pp->wavelet.daubcoeffmethod = "2_";
} else if (daubcoeffmethod->get_active_row_number() == 1) {
@ -2835,6 +2880,110 @@ void Wavelet::ushamethodChanged()
}
void Wavelet::convertParamToNormal()
{
const WaveletParams def_params;
disableListener();
//contrast
offset->setValue(def_params.offset);
sigma->setValue(def_params.sigma);
lowthr->setValue(def_params.lowthr);
//chroma
expchroma->setEnabled(def_params.expchroma);
sigmacol->setValue(def_params.sigmacol);
CHmethod->set_active(2);
//denoise
chromfi->setValue(def_params.chromfi);
chromco->setValue(def_params.chromco);
//toning
exptoning->setEnabled(def_params.exptoning);
//gamut
median->set_active(def_params.median);
avoid->set_active(def_params.avoid);
hueskin->setValue(def_params.hueskin);
skinprotect->setValue(def_params.skinprotect);
//blur
expbl->setEnabled(def_params.expbl);
//edge sharpness
lipst->set_active(def_params.lipst);
lipstUpdateUI();
edgesensi->setValue(def_params.edgesensi);
edgeampli->setValue(def_params.edgeampli);
NPmethod->set_active(0);
//resid
// oldsh->set_active(true);
radius->setValue(def_params.radius);
resblur->setValue(def_params.resblur);
resblurc->setValue(def_params.resblurc);
cbenab->set_active(false);
//final touchup
BAmethod->set_active(0);
sigmafin->setValue(def_params.sigmafin);
enableListener();
// Update GUI based on converted widget parameters:
}
void Wavelet::updateGUIToMode(int mode)
{
if(mode ==0) {
offset->hide();
sigma->hide();
lowthr->hide();
ctboxch->hide();
sigmacol->hide();
expgamut->hide();
exptoning->hide();
chroFrame->hide();
expbl->hide();
lipst->hide();
dirFrame->hide();
oldsh->hide();
radius->hide();
blurFrame->hide();
cbenab->hide();
sigmafin->hide();
} else {
offset->show();
sigma->show();
lowthr->show();
ctboxch->show();
sigmacol->show();
expgamut->show();
exptoning->show();
chroFrame->show();
expbl->show();
lipst->show();
dirFrame->show();
oldsh->hide();
radius->show();
blurFrame->show();
cbenab->show();
sigmafin->show();
}
}
void Wavelet::complexmethodChanged()
{
if (complexmethod->get_active_row_number() == 0) {
updateGUIToMode(0);
convertParamToNormal();
} else {
updateGUIToMode(1);
}
if (listener && (multiImage || getEnabled())) {
listener->panelChanged(EvWavcomplexmet, complexmethod->get_active_text());
}
}
void Wavelet::TilesmethodChanged()
{
//TilesmethodUpdateUI();
@ -2916,6 +3065,7 @@ void Wavelet::setBatchMode(bool batchMode)
CLmethod->append(M("GENERAL_UNCHANGED"));
Backmethod->append(M("GENERAL_UNCHANGED"));
Tilesmethod->append(M("GENERAL_UNCHANGED"));
complexmethod->append(M("GENERAL_UNCHANGED"));
daubcoeffmethod->append(M("GENERAL_UNCHANGED"));
CHmethod->append(M("GENERAL_UNCHANGED"));
Medgreinf->append(M("GENERAL_UNCHANGED"));

View File

@ -47,7 +47,6 @@ class Wavelet final :
public:
Wavelet();
~Wavelet() override;
bool wavComputed_();
void adjusterChanged(Adjuster* a, double newval) override;
void autoOpenCurve() override;
@ -102,6 +101,7 @@ private:
rtengine::ProcEvent EvWavrangeab;
rtengine::ProcEvent EvWavprotab;
rtengine::ProcEvent EvWavlevelshc;
rtengine::ProcEvent EvWavcomplexmet;
LabGrid *labgrid;
@ -121,6 +121,7 @@ private:
void LmethodChanged();
void MedgreinfChanged();
void TMmethodChanged();
void complexmethodChanged();
void TilesmethodChanged();
void avoidToggled();
void showmaskToggled ();
@ -143,7 +144,8 @@ private:
void ushamethodChanged();
void updateGUI();
void updateGUImaxlev();
void convertParamToNormal();
void updateGUIToMode(int mode);
void HSmethodUpdateUI();
void CHmethodUpdateUI();
// void CHSLmethodChangedUI();
@ -297,6 +299,8 @@ private:
sigc::connection CLmethodconn;
MyComboBoxText* const Backmethod;
sigc::connection Backmethodconn;
MyComboBoxText* const complexmethod;
sigc::connection complexmethodconn;
MyComboBoxText* const Tilesmethod;
sigc::connection Tilesmethodconn;
MyComboBoxText* const daubcoeffmethod;
@ -338,6 +342,8 @@ private:
Gtk::HBox* const neutrHBox;
Gtk::HBox* const usharpHBox;
Gtk::HBox* const ctboxch;
Gtk::VBox* const ctboxBA;// = Gtk::manage(new Gtk::VBox());
sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enabletmConn, enableFinalConn, enableclariConn;
sigc::connection enableNoiseConn, enableResidConn, enableToningConn;