diff --git a/AUTHORS.txt b/AUTHORS.txt
index b2d1333d2..9d1309026 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b7cf35099..d673f8e8f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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")
@@ -637,14 +637,8 @@ else()
endif()
# Get compiler name and version.
- get_filename_component(COMPILER_INFO ${CMAKE_C_COMPILER} NAME_WE)
- set(COMPILER_INFO "${COMPILER_INFO} ${CMAKE_C_COMPILER_VERSION}")
-if(NOT APPLE)
- execute_process(
- COMMAND gcc -dumpversion
- OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
- set(COMPILER_INFO "gcc ${GCC_VERSION}")
-endif()
+get_filename_component(COMPILER_INFO ${CMAKE_C_COMPILER} NAME_WE)
+set(COMPILER_INFO "${COMPILER_INFO} ${CMAKE_C_COMPILER_VERSION}")
# Get C++ and linker flags for rtengine (the GUI's C++ flags may have fewer
# flags):
diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais
index 10dabb4a4..1483d7cc5 100644
--- a/rtdata/languages/Francais
+++ b/rtdata/languages/Francais
@@ -1761,7 +1761,7 @@ TP_LOCALLAB_ARTIF_TOOLTIP;Le seuil deltaE étendue accroit la plage of étendue-
TP_LOCALLAB_AUTOGRAY;Automatique
TP_LOCALLAB_AVOID;Evite les dérives de couleurs
TP_LOCALLAB_BALAN;Balance ΔE ab-L
-TP_LOCALLAB_BALANEXP;ΔØ EPD balance
+TP_LOCALLAB_BALANEXP;Balance Laplacien
TP_LOCALLAB_BALANH;Balance ΔE C-H
TP_LOCALLAB_BALAN_TOOLTIP;Change l'algorithme des paramètres ΔE.\nPlus ou moins ab-L, plus ou moins C-H.\nPas pour le Debruitage
TP_LOCALLAB_BASELOG;Base Logarithme
@@ -1908,6 +1908,8 @@ TP_LOCALLAB_EXPCHROMA;Chroma compensation
TP_LOCALLAB_EXPCHROMA_TOOLTIP;Seulement en association avec compensation d'exposition et PDE Ipol.\nEvite la desaturation des couleurs
//TP_LOCALLAB_EXPCOLOR_TOOLTIP;Dans le cas de petits défauts.\n\nYeux-rouges : sélecteur centré sur la partie rouge, délimiteurs du spot près de l'oeil, adaptez Etendue, "luminosité" -100, "chrominance" -100.\n\nSpotIR :sélection Circulaire centrée sur le défaut, délimiteurs du spot proches du default - reduire "chrominance", possibilté d'agir sur Etendue pour réduire la zone de l'action.\n\nPoussières - graisse (petit) :Sélection circulaire centrée sur le défaut (adapter la taille du spot), délimiteurs du spot pas trop près du défaut pour permettre une transition quasi invisible. a) "Transition" (faibles valeurs) and "Transition affaiblissement" (hautes valeurs); b) agir sur "luminosité" et aussi sur "chrominance" ou sur "Grille de correction couleur - direct" de telle manière que le rendu de la zone polluée soit proche de celui de la zone saine; c) agir modérement sur "Etendue" pour moduler l'action.\n\nVous pouvez aussi compléter avec Flouter Gaussien (Adoucir Flouter et bruit)
TP_LOCALLAB_EXPCOLOR_TOOLTIP;Ajuste les couleurs, la luminosité, le contrast et corrige les petits défauts tels que teux-rouges, poussières sur le capteur, etc.
+TP_LOCALLAB_EXPCOMP;Compensation d'exposition ƒ
+TP_LOCALLAB_EXPCOMPINV;Compensation d'exposition
TP_LOCALLAB_EXPCOMP_TOOLTIP;Pour les portraits et les images à faible gradient, vous pouvez changer "Détection de forme" dans "Réglages":\n\nAugmentez 'Seuil ΔE Etendue'\nRéduire 'ΔE affaiblissement'\nAugmenter 'Balance ΔE ab-L'
TP_LOCALLAB_EXPCONTRASTPYR_TOOLTIP;Voir la documentation de ondelettes niveaux.\nCependant il y a des différences: plus d'outils et plus proches des détails .\nEx: Tone mapping pour ondelettes.
TP_LOCALLAB_EXPCONTRAST_TOOLTIP;Evitez les spots trop petits(< 32x32 pixels).\nUtilisez de faibles valeurs de transition et de hautes valeurs de transition affaiblissement et d'Etendue pour simuler un petit RT-spot et s'adapter aux défauts.\nUtimiser si nécessaire le module 'Clarté & Maqsue netteté' et 'Fusion d'images' en ajustant 'Rayon adoucir' pour réduire les artéfacts.
@@ -1927,7 +1929,7 @@ TP_LOCALLAB_EXPRETITOOLS;Outils Retinex avancés
TP_LOCALLAB_EXPSHARP_TOOLTIP;RT-Spot minimum 39*39.\nUtiliser de basses valeurs de transition et de hautes valeurs de transition affaiblissement et Etendue pour simuler un petit RT-spot.
TP_LOCALLAB_EXPTOOL;Outils exposition
TP_LOCALLAB_EXPTRC;Courbe de réponse Tonale - TRC
-TP_LOCALLAB_EXP_TOOLNAME;Atténuation contraste -Compression Dynamique & Exposition- 10
+TP_LOCALLAB_EXP_TOOLNAME;Atténuation Contraste -Compression Dynamique & Exposition- 10
TP_LOCALLAB_FATAMOUNT;Quantité
TP_LOCALLAB_FATANCHOR;Ancre
TP_LOCALLAB_FATANCHORA;Décalage
@@ -1985,10 +1987,10 @@ TP_LOCALLAB_LABGRIDMERG;Arrière plan
TP_LOCALLAB_LABGRID_VALUES;Haut(a)=%1 Haut(b)=%2\nBas(a)=%3 Bas(b)=%4
TP_LOCALLAB_LABSTRUM;Masque Structure
TP_LOCALLAB_LAPLACC;ΔØ Masque Laplacien résoud PDE
-TP_LOCALLAB_LAPLACE;Δ - Laplacien seuil ΔE
-TP_LOCALLAB_LAPLACEXP;∆ - Laplacian seuil
-TP_LOCALLAB_LAPMASKCOL;∆ - Laplacian seuil masque
-TP_LOCALLAB_LAPRAD_TOOLTIP;Eviter d'utiliser Radius and Laplace Seuil en même temps.\nLaplacien seuil reduit le contraste, artéfacts, adoucit le résultat (si PDE réglages activé).
+TP_LOCALLAB_LAPLACE;Laplacien seuil ΔE
+TP_LOCALLAB_LAPLACEXP;Laplacien seuil
+TP_LOCALLAB_LAPMASKCOL;Laplacien seuil masque
+TP_LOCALLAB_LAPRAD_TOOLTIP;Eviter d'utiliser Radius and Laplace Seuil en même temps.\nLaplacien seuil reduit le contraste, artéfacts, adoucit le résultat.
TP_LOCALLAB_LAP_MASK_TOOLTIP;Résoud PDE (Equation aux dérivées partielles) pour tous les masques Laplacien.\nSi activé Laplacien masque seuil reduit les artéfacts et adoucit les résultats.\nSi désactivé réponse linaire.
TP_LOCALLAB_LC_FFTW_TOOLTIP;FFT améliore la qualité et autorise de grands rayons, mais accroît les temps de traitement.\nCe temps dépends de la surface devant être traitée.\nA utiliser de préférences pour de grands rayons.\n\nLes Dimensions peuvent être réduites de quelques pixels pour optimiser FFTW.\nCette optimisation peut réduire le temps de traitement d'un facteur de 1.5 à 10.\n
TP_LOCALLAB_LC_TOOLNAME;Constrast Local & Ondelettes (Défauts) - 7
@@ -2002,7 +2004,7 @@ TP_LOCALLAB_LIGHTN_TOOLTIP;En mode inverse: selection = -100 force la luminance
TP_LOCALLAB_LIGHTRETI;Luminosité
TP_LOCALLAB_LINEAR;Linéarité
TP_LOCALLAB_LIST_NAME;Ajoute un outil au spot courant...
-TP_LOCALLAB_LIST_TOOLTIP;Choisir un outil et ensuite son niveau de complexité "Normal" ou "Expert".\nLe nombre traduit la place de l'outil dans le processus de chaque RT-Spot
+TP_LOCALLAB_LIST_TOOLTIP;Vous pouvez choisir 3 niveaux de complexité pour chaque outil: Basic, Normal & Avancé.\nLe réglage par défaut est Basic mais il peut être changé dans Préférences.\nVous pouvez aussi changer ce niveau pour chaque outil en cours.
TP_LOCALLAB_LMASK_LEVEL_TOOLTIP;Donne priorité à l'action sur les tons moyens et hautes lumières en choisissant les niveaux concernés d'ondelettes
TP_LOCALLAB_LMASK_LL_TOOLTIP;Give priority to action on midtones and high lights
TP_LOCALLAB_LOCCONT;Masque Flou
@@ -2081,8 +2083,8 @@ TP_LOCALLAB_MERTWO;Soustrait
TP_LOCALLAB_METHOD_TOOLTIP;'Enhanced + chroma denoise' significantly increases processing times.\nBut reduce artifacts.
TP_LOCALLAB_MLABEL;Récupère les données Min=%1 Max=%2 (Clip - décalage)
TP_LOCALLAB_MLABEL_TOOLTIP;'Doit être' près de min=0 max=32768 (log mode) mais d'autres valeurs sont possibles.\nVous pouvez agir sur les données récupérées (CLIP) et décalage pour normaliser.\n\nRécupère les données image sans mélange.
-TP_LOCALLAB_MODE_EXPERT;Expert
-TP_LOCALLAB_MODE_NORMAL;Normal
+TP_LOCALLAB_MODE_EXPERT;Avancé
+TP_LOCALLAB_MODE_NORMAL;Standard
TP_LOCALLAB_MRFIV;Arrière plan
TP_LOCALLAB_MRFOU;Spot précédent
TP_LOCALLAB_MRONE;Rien
@@ -2110,8 +2112,8 @@ TP_LOCALLAB_ORIGLC;Fusion seulement avec image originale
TP_LOCALLAB_ORRETILAP_TOOLTIP;Agit sur un deuxième seuil Laplacien, pour prendre en compte ΔE pour différencier l'action nottament avec l'arrière plan (différent de Etendue)
TP_LOCALLAB_ORRETISTREN_TOOLTIP;Aagit sur un seuil Laplacien, plus grande est l'action, plus les différences de contraste seront réduites
TP_LOCALLAB_PASTELS2;Vibrance
-TP_LOCALLAB_PDE;ΔØ Laplacian PDE - Compression dynamique + Standard
-TP_LOCALLAB_PDEFRA;Contrast atténuation ƒ
+TP_LOCALLAB_PDE;Atténuation de Contraste - Compression dynamique
+TP_LOCALLAB_PDEFRA;Contraste atténuation ƒ
TP_LOCALLAB_PDEFRAME_TOOLTIP;PDE IPOL - algorithme personnel adapté de IPOL à Rawtherapee: conduit à des résultats très variés et a besoin de différents réglages que Standard (Noir négatif, gamma < 1,...)\nPeut être utils pour des iamges sous-exposées ou avec une étendue dynamique importante.\n
TP_LOCALLAB_PREVIEW;Prévisualisation ΔE
TP_LOCALLAB_PREVHIDE;Cacher tous les réglages
@@ -2217,8 +2219,8 @@ TP_LOCALLAB_SHOWPOISSON;Poisson (pde ƒ)
TP_LOCALLAB_SHOWR;Masque et modifications
TP_LOCALLAB_SHOWREF;Prévisualisation ΔE
TP_LOCALLAB_SHOWS;Masque et modifications
-TP_LOCALLAB_SHOWSTRUC;Montrer Spot structure (expert)
-TP_LOCALLAB_SHOWSTRUCEX;Montrer Spot structure (expert)
+TP_LOCALLAB_SHOWSTRUC;Montrer Spot structure (avancé)
+TP_LOCALLAB_SHOWSTRUCEX;Montrer Spot structure (avancé)
TP_LOCALLAB_SHOWT;Masque et modifications
TP_LOCALLAB_SHOWVI;Masque et modifications
TP_LOCALLAB_SHRESFRA;Ombres/Lumières
@@ -2253,7 +2255,7 @@ TP_LOCALLAB_STRRETI_TOOLTIP;Si force Retinex < 0.2 seul Dehaze est activé.\nSi
TP_LOCALLAB_STRUC;Structure
TP_LOCALLAB_STRUCCOL;Structure
TP_LOCALLAB_STRUCCOL1;Spot Structure
-TP_LOCALLAB_STRUCT_TOOLTIP;Utilise l'algorithme de Sobel pour prendre en compte la structure dans la détection de forme.\nvous pouvez prévisualiser avec "masque et modifications - Montrer structure spot".\n\nPeut être utilisé avec masques (expert) structure, flouter, ondelettes pour améliorer la détection de bords.\n\nA besoin de réglages sans-masque pour êtrre activé (luminosité, exposition...)
+TP_LOCALLAB_STRUCT_TOOLTIP;Utilise l'algorithme de Sobel pour prendre en compte la structure dans la détection de forme.\nvous pouvez prévisualiser avec "masque et modifications - Montrer structure spot".\n\nPeut être utilisé avec masques (avancé) structure, flouter, ondelettes pour améliorer la détection de bords.\n\nA besoin de réglages sans-masque pour êtrre activé (luminosité, exposition...)
TP_LOCALLAB_STRUMASKCOL;Structure masque force
TP_LOCALLAB_STRUMASK_TOOLTIP;Génère un masque structure qui va différencier les aplats et reliefs.\nSi structure masque comme outil est activé, ce masque est untilisé en plus des autres outils (gamma, slope, courbe contraste ...)
TP_LOCALLAB_STYPE;Forme méthode
@@ -2651,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: l’application dispose du nécessaire pour assurer les opérations courantes, l’interface 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.
diff --git a/rtdata/languages/default b/rtdata/languages/default
index 672eaa764..5026a80f7 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -568,10 +568,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
@@ -635,14 +635,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
@@ -1086,7 +1086,7 @@ HISTORY_MSG_841;Local - LC curve
HISTORY_MSG_842;Local - Contrast Threshold Mask blur
HISTORY_MSG_843;Local - Radius Mask blur
HISTORY_MSG_844;Local - Color Mask fftw
-HISTORY_MSG_845;Local - Encoding log
+HISTORY_MSG_845;Local - log encoding
HISTORY_MSG_846;Local - Encoding auto
HISTORY_MSG_847;Local - Source Gray
HISTORY_MSG_848;Local - Source Gray auto
@@ -1132,8 +1132,8 @@ HISTORY_MSG_888;Local - Contrast Wavelet Balance Threshold
HISTORY_MSG_889;Local - Contrast Wavelet Graduated Strength
HISTORY_MSG_890;Local - Contrast Wavelet Graduated angle
HISTORY_MSG_891;Local - Contrast Wavelet Graduated
-HISTORY_MSG_892;Local - Encoding log Graduated Strength
-HISTORY_MSG_893;Local - Encoding log Graduated angle
+HISTORY_MSG_892;Local - Log Encoding Graduated Strength
+HISTORY_MSG_893;Local - Log Encoding Graduated angle
HISTORY_MSG_894;Local - Color Preview dE
HISTORY_MSG_897;Local - Contrast Wavelet ES strength
HISTORY_MSG_898;Local - Contrast Wavelet ES radius
@@ -1194,10 +1194,12 @@ HISTORY_MSG_952;Local - Mask Common soft radius
HISTORY_MSG_953;Local - Mask Common blend chroma
HISTORY_MSG_954;Local - Show-hide tools
HISTORY_MSG_955;Local - Enable Spot
+HISTORY_MSG_956;Local - CH Curve
+HISTORY_MSG_957;Local - Tool complexity mode
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
@@ -1214,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
@@ -1221,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
@@ -1268,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
@@ -1290,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
@@ -1600,8 +1604,9 @@ PREFERENCES_CLUTSCACHE_LABEL;Maximum number of cached CLUTs
PREFERENCES_CLUTSDIR;HaldCLUT directory
PREFERENCES_CMMBPC;Black point compensation
PREFERENCES_COMPLEXITYLOC;Default complexity for Local Adjustments
-PREFERENCES_COMPLEXITY_EXP;Expert
-PREFERENCES_COMPLEXITY_NORM;Normal
+PREFERENCES_COMPLEXITY_EXP;Advanced
+PREFERENCES_COMPLEXITY_NORM;Standard
+PREFERENCES_COMPLEXITY_SIMP;Basic
PREFERENCES_CROP;Crop Editing
PREFERENCES_CROP_AUTO_FIT;Automatically zoom to fit the crop
PREFERENCES_CROP_GUIDES;Guides shown when not editing the crop
@@ -2339,7 +2344,7 @@ TP_LOCALLAB_ARTIF_TOOLTIP;Threshold deltaE-scope increase the range of scope-del
TP_LOCALLAB_AUTOGRAY;Automatic
TP_LOCALLAB_AVOID;Avoid color shift
TP_LOCALLAB_BALAN;Balance ΔE ab-L
-TP_LOCALLAB_BALANEXP;ΔØ PDE balance
+TP_LOCALLAB_BALANEXP;Laplacian balance
TP_LOCALLAB_BALANH;Balance ΔE C-H
TP_LOCALLAB_BALAN_TOOLTIP;Change algorithm ΔE parameter.\nMore or less ab-L, more or less C - H.\nNot for Denoise
TP_LOCALLAB_BASELOG;Logarithm base
@@ -2360,7 +2365,7 @@ TP_LOCALLAB_BLMETHOD_TOOLTIP;Normal - direct blur and noise with all settings.\n
TP_LOCALLAB_BLNOI_EXP;Blur & Noise
TP_LOCALLAB_BLNORM;Normal
TP_LOCALLAB_BLSYM;Symmetric
-TP_LOCALLAB_BLUFR;Smooth - Blur - Grain - Denoise
+TP_LOCALLAB_BLUFR;Blur - Grain & Denoise
TP_LOCALLAB_BLUMETHOD_TOOLTIP;To blur the background and isolate the foreground:\n*Blur the background by a RT-spot fully covering the image (high values for scope and transition) - normal or inverse.\n*Isolate the foreground by one or more excluding RT-spot with the tools you want (increse scope).\n\nThis module can be used in additional noise reduction,including "median" and "Guided filter"
TP_LOCALLAB_BLUR;Gaussian Blur - Noise - Grain
TP_LOCALLAB_BLURCBDL;Blur levels 0-1-2-3-4
@@ -2370,7 +2375,7 @@ TP_LOCALLAB_BLURLC;Luminance Only
TP_LOCALLAB_BLURLEVELFRA;Blur Levels
TP_LOCALLAB_BLURMASK_TOOLTIP;Generate a blur mask, take into account the structure with the contrast threshold Mask Blur slider.
TP_LOCALLAB_BLURRESIDFRA;Blur Residual
-TP_LOCALLAB_BLUR_TOOLNAME;Smooth Blur Gain & Denoise - 1
+TP_LOCALLAB_BLUR_TOOLNAME;Blur Grain & Denoise - 1
TP_LOCALLAB_BLWH;All changes forced in Black and White
TP_LOCALLAB_BLWH_TOOLTIP;Force color change composante "a" and "b" to zero.\nUsefull when the user chooses black and white processes, or film.
TP_LOCALLAB_BUTTON_ADD;Add
@@ -2382,7 +2387,7 @@ TP_LOCALLAB_CBDL;Contrast by detail levels
TP_LOCALLAB_CBDLCLARI_TOOLTIP;Takes the midtones and enhance them.
TP_LOCALLAB_CBDL_ADJ_TOOLTIP;Acts as a wavelet tools.\nThe first level (0) acts on 2x2 details.\nThe last level (5) acts on 64x64 details.
TP_LOCALLAB_CBDL_THRES_TOOLTIP;Prevent the sharpening of noise
-TP_LOCALLAB_CBDL_TOOLNAME;CBDL (Defects) - 2
+TP_LOCALLAB_CBDL_TOOLNAME;CBDL - 2
TP_LOCALLAB_CENTER_X;Center X
TP_LOCALLAB_CENTER_Y;Center Y
TP_LOCALLAB_CH;Curves CL - LC
@@ -2411,7 +2416,7 @@ TP_LOCALLAB_COLORDEPREV_TOOLTIP;Button Preview ΔE needs that only one tool is e
TP_LOCALLAB_COLORDE_TOOLTIP;Show preview selection ΔE in blue if negative and in green if positive.\n\nMask and modifications (show modifications without mask): show real modifications if positive, show enhanced modifications (only luminance) with blue and yellow if negative.
TP_LOCALLAB_COLORSCOPE;Scope Color Tools
TP_LOCALLAB_COLORSCOPE_TOOLTIP;Use a common Scope for Color and light, Shadows highlight, Vibrance.\nOthers tools have their specific scope.
-TP_LOCALLAB_COLOR_TOOLNAME;Color&Light (Defects) - 11
+TP_LOCALLAB_COLOR_TOOLNAME;Color & Light - 11
TP_LOCALLAB_COL_NAME;Name
TP_LOCALLAB_COL_VIS;Status
TP_LOCALLAB_COMPFRA;Levels Directional Contrast
@@ -2486,6 +2491,8 @@ TP_LOCALLAB_EXPCHROMA;Chroma compensation
TP_LOCALLAB_EXPCHROMA_TOOLTIP;Only in association with exposure compensation and PDE Ipol.\nAvoids desaturation of colors
//TP_LOCALLAB_EXPCOLOR_TOOLTIP;In the case of small defects.\n\nRed-eyes : red-centered circular selector, spot delimiters close to the eye, weak scope, "lightness" -100, "chrominance" -100.\n\nSpotIR :Circular selector centered on the defect, spot delimiters close to the default - reduce "chrominance", possibly act on "scope" to reduce the extent of the action.\n\nDust - grease (small) :Circular selector centered on the defect (adapt the size of the spot), spot delimiters not too close to the defect to allow an inconspicuous transition. a) "Transition" (low values) and "Transition weak" (high values); b) act on "lightness" and possibly on "chrominance" or "Color correction grid - direct" to approach the rendering of the polluted zone to that of the healthy zone; c) act moderately on "scope" to modulate the desired action.\n\nYou can also complete with Gaussian blur (Smooth Blur and noise)
TP_LOCALLAB_EXPCOLOR_TOOLTIP;Adjust color, lightness, contrast and correct small defects such as red-eye, sensor dust etc.
+TP_LOCALLAB_EXPCOMP;Exposure compensation ƒ
+TP_LOCALLAB_EXPCOMPINV;Exposure compensation
TP_LOCALLAB_EXPCOMP_TOOLTIP;For portrait or images with low color gradient, you can change "Shape detection" in "settings":\n\nIncrease 'Threshold ΔE scope'\nReduce 'ΔE decay'\nIncrease 'Balance ΔE ab-L'
TP_LOCALLAB_EXPCONTRASTPYR_TOOLTIP;See the documentation of wavelet levels.\nHowever there are some differences: more tools and closer to the details.\nEx: Tone mapping for wavelet levels.
TP_LOCALLAB_EXPCONTRAST_TOOLTIP;Avoid spots that are too small(< 32x32 pixels).\nUse low transition values and high decay transition values and scope to simulate small RT-spot and deal wth defects.\nUse if necessary the module 'Clarity & Sharp mask and Blend images' by adjusting 'Soft radius' to reduce artifacts.
@@ -2499,13 +2506,13 @@ TP_LOCALLAB_EXPMERGEFILE_TOOLTIP;Allows various possibilities to blend image (as
TP_LOCALLAB_EXPMETHOD_TOOLTIP;Standard : use an algorithm similar as main Exposure but in L*a*b* and taking account of deltaE.\n\nContrast attenuator : use another algorithm also with deltaE and with Poisson equation to solve Laplacian in Fourier space.\nContrast attenuator, Dynamic range compression and Standard can be combined.\nFFTW Fourier Transform is optimized in size to reduce processing time.\nReduce artifacts and noise.
TP_LOCALLAB_EXPNOISEMETHOD_TOOLTIP;Apply a median before Laplace transform to prevent artifacts (noise).\nYou can also use "Denoise" tool.
TP_LOCALLAB_EXPOSE;Dynamic Range Compr. & Exposure
-//TP_LOCALLAB_EXPOSURE_TOOLTIP;In some cases (strong shadows ..) you can use others modules "Shadows Highlights", "Tone equalizer", "TRC", "Encoding Log"...
+//TP_LOCALLAB_EXPOSURE_TOOLTIP;In some cases (strong shadows ..) you can use others modules "Shadows Highlights", "Tone equalizer", "TRC", "Log Encoding"...
TP_LOCALLAB_EXPOSURE_TOOLTIP;Modify exposure in L*a*b space using Laplacian PDE algorithms to take into account dE and minimize artifacts.
TP_LOCALLAB_EXPRETITOOLS;Advanced Retinex Tools
TP_LOCALLAB_EXPSHARP_TOOLTIP;RT-Spot minimum 39*39.\nUse low transition values and high decay transition values and scope to simulate small RT-spot.
TP_LOCALLAB_EXPTOOL;Tools exposure
TP_LOCALLAB_EXPTRC;Tone Response Curve - TRC
-TP_LOCALLAB_EXP_TOOLNAME;Contrast attenuator -Dynamic Range Compression & Exposure- 10
+TP_LOCALLAB_EXP_TOOLNAME;Contrast Attenuator -Dynamic Range Compression & Exposure- 10
TP_LOCALLAB_FATAMOUNT;Amount
TP_LOCALLAB_FATANCHOR;Anchor
TP_LOCALLAB_FATANCHORA;Offset
@@ -2530,7 +2537,7 @@ TP_LOCALLAB_GAMSH;Gamma
TP_LOCALLAB_GRADANG;Gradient angle
TP_LOCALLAB_GRADANG_TOOLTIP;Rotation angle in degrees : -180 0 +180
TP_LOCALLAB_GRADFRA;Graduated Filter Mask
-TP_LOCALLAB_GRADGEN_TOOLTIP;Graduated filter is supplied with Color and Light & merge file, Exposure & mask, Shadows Highlight, Vibrance, Encoding log.\n\nVibrance, Color and Light & merge file, are provided with GF luminance, chrominance, Hue.\nFeather is located in settings.
+TP_LOCALLAB_GRADGEN_TOOLTIP;Graduated filter is supplied with Color and Light & merge file, Exposure & mask, Shadows Highlight, Vibrance, Log Encoding.\n\nVibrance, Color and Light & merge file, are provided with GF luminance, chrominance, Hue.\nFeather is located in settings.
TP_LOCALLAB_GRADLOGFRA;Graduated Filter Luminance
TP_LOCALLAB_GRADSTR;Gradient strength
TP_LOCALLAB_GRADSTRAB_TOOLTIP;Filter chroma strength
@@ -2563,13 +2570,13 @@ TP_LOCALLAB_LABGRIDMERG;Background
TP_LOCALLAB_LABGRID_VALUES;High(a)=%1 High(b)=%2\nLow(a)=%3 Low(b)=%4
TP_LOCALLAB_LABSTRUM;Mask Structure
TP_LOCALLAB_LAPLACC;ΔØ Mask Laplacian solve PDE
-TP_LOCALLAB_LAPLACE;Δ - Laplacian threshold ΔE
-TP_LOCALLAB_LAPLACEXP;∆ - Laplacian threshold
-TP_LOCALLAB_LAPMASKCOL;∆ - Laplacian threshold mask
-TP_LOCALLAB_LAPRAD_TOOLTIP;Avoid using Radius and Laplace Threshold (expert) simultaneously.\nLaplacian threshold reduce contrast, artifacts, smooth result.
+TP_LOCALLAB_LAPLACE;Laplacian threshold ΔE
+TP_LOCALLAB_LAPLACEXP;Laplacian threshold
+TP_LOCALLAB_LAPMASKCOL;Laplacian threshold mask
+TP_LOCALLAB_LAPRAD_TOOLTIP;Avoid using Radius and Laplace Threshold (advanced) simultaneously.\nLaplacian threshold reduce contrast, artifacts, smooth result.
TP_LOCALLAB_LAP_MASK_TOOLTIP;Solve PDE for all Laplacian masks.\nIf enabled Laplacian threshold mask reduce artifacts and smooth result.\nIf disabled linear response.
TP_LOCALLAB_LC_FFTW_TOOLTIP;FFT improve quality and allow big radius, but increases the treatment time.\nThe treatment time depends on the surface to be treated.\nTo be used preferably for large radius.\n\nDimensions can be reduced by a few pixels to optimize FFTW.\nThis optimization can reduce the treatment time by a factor of 1.5 to 10.\n
-TP_LOCALLAB_LC_TOOLNAME;Local Constrast & Wavelet (Defects) - 7
+TP_LOCALLAB_LC_TOOLNAME;Local Contrast & Wavelets - 7
TP_LOCALLAB_LEVELBLUR;Maximum Blur levels
TP_LOCALLAB_LEVELLOCCONTRAST_TOOLTIP;On the abscissa local contrast (near concept luminance). On the ordinate, amplification or reduction local contrast.
TP_LOCALLAB_LEVELWAV;Ψ Wavelets Levels
@@ -2580,17 +2587,17 @@ TP_LOCALLAB_LIGHTN_TOOLTIP;In inverse mode: selection = -100 force luminance to
TP_LOCALLAB_LIGHTRETI;Lightness
TP_LOCALLAB_LINEAR;Linearity
TP_LOCALLAB_LIST_NAME;Add tool to current spot...
-TP_LOCALLAB_LIST_TOOLTIP;Choose a tool and then its level of complexity "Normal" or "Expert".\nThe number reflects the place of the tool in the process of each RT-Spot
+TP_LOCALLAB_LIST_TOOLTIP;You can select 3 levels of complexity for each tool: Basic, Standard & Advanced.\nThe default setting for all tools is Basic but this can be changed in the Preferences window.\nYou can also change the level of complexity on a per-tool basis while you are editing
TP_LOCALLAB_LMASK_LEVEL_TOOLTIP;Give priority to action on midtones and high lights and by choosing the concerned wavelet levels
TP_LOCALLAB_LMASK_LL_TOOLTIP;Give priority to action on midtones and high lights
TP_LOCALLAB_LOCCONT;Unsharp Mask
-TP_LOCALLAB_LOC_CONTRAST;Local contrast -Wavelet-defects
+TP_LOCALLAB_LOC_CONTRAST;Local contrast & Wavelets
TP_LOCALLAB_LOC_CONTRASTPYR;Ψ Pyramid 1:
TP_LOCALLAB_LOC_CONTRASTPYR2;Ψ Pyramid 2:
TP_LOCALLAB_LOC_CONTRASTPYR2LAB;Contrast by Levels- Tone Mapping - Dir.Contrast
TP_LOCALLAB_LOC_CONTRASTPYRLAB;Graduated Filter - Edge Sharpness - Blur
-TP_LOCALLAB_LOC_RESIDPYR;Residual Image Main
-TP_LOCALLAB_LOG;Encoding log
+TP_LOCALLAB_LOC_RESIDPYR;Residual Image (Main)
+TP_LOCALLAB_LOG;Log Encoding
TP_LOCALLAB_LOGAUTO;Automatic
TP_LOCALLAB_LOGAUTO_TOOLTIP;Pressing this button will bring an evaluation of dynamic range and Source Gray point (if "Automatic" Source gray enabled).\nTo be able to touch up the automatic values, press the button again
TP_LOCALLAB_LOGBASE_TOOLTIP;Default = 2.\nValues less than 2 reduce the action of the algorithm, the shadows are darker, the highlights are brighter.\nValues greater than 2 change the action of the algorithm, the shadows are grayer the highlights are more washed out
@@ -2602,7 +2609,7 @@ TP_LOCALLAB_LOGLIN;Logarithm mode
TP_LOCALLAB_LOGPFRA;Relative Exposure Levels
TP_LOCALLAB_LOGSRCGREY_TOOLTIP;Estimated gray point value of the image, early in the process
TP_LOCALLAB_LOGTARGGREY_TOOLTIP;You can change this value to adapt it to your taste.
-TP_LOCALLAB_LOG_TOOLNAME;Encoding log - 0
+TP_LOCALLAB_LOG_TOOLNAME;Log Encoding - 0
TP_LOCALLAB_LUM;Curves LL - CC
TP_LOCALLAB_LUMADARKEST;Darkest
TP_LOCALLAB_LUMASK;Luminance Background Mask
@@ -2611,7 +2618,8 @@ TP_LOCALLAB_LUMAWHITESEST;Whiteest
TP_LOCALLAB_LUMFRA;L*a*b* standard
TP_LOCALLAB_LUMONLY;Luminance only
TP_LOCALLAB_MASKCOM;Common Color Mask
-TP_LOCALLAB_MASKCOM_TOOLTIP;These masks works as all tools, they take into account scope color.\nThey are different from others masks which complete a tool (Color and Light, Exposure...)
+TP_LOCALLAB_MASKCOM_TOOLTIP;A tool in its own right.\nCan be used to adjust the image appearance (chrominance, luminance, contrast) and texture as a function of Scope.
+//These masks works as all tools, they take into account scope color.\nThey are different from others masks which complete a tool (Color and Light, Exposure...)
TP_LOCALLAB_MASFRAME;Mask and Merge
TP_LOCALLAB_MASFRAME_TOOLTIP;For all masks.\nTake into account deltaE image to avoid retouching the selection area when sliders gamma mask, slope mask, chroma mask and curves contrast , levels contrasts, and mask blur, structure(if enabled tool) are used.\nDisabled in Inverse
TP_LOCALLAB_MASK;Mask
@@ -2660,8 +2668,9 @@ TP_LOCALLAB_MERTWO;Substract
TP_LOCALLAB_METHOD_TOOLTIP;'Enhanced + chroma denoise' significantly increases processing times.\nBut reduce artifacts.
TP_LOCALLAB_MLABEL;Restored datas Min=%1 Max=%2 (Clip - Offset)
TP_LOCALLAB_MLABEL_TOOLTIP;'Should be' near min=0 max=32768 (log mode) but others values are possible.\nYou can act on Clip Restored datas and Offset to normalize.\n\nRestored image with no mixture.
-TP_LOCALLAB_MODE_EXPERT;Expert
-TP_LOCALLAB_MODE_NORMAL;Normal
+TP_LOCALLAB_MODE_EXPERT;Advanced
+TP_LOCALLAB_MODE_NORMAL;Standard
+TP_LOCALLAB_MODE_SIMPLE;Basic
TP_LOCALLAB_MRFIV;Background
TP_LOCALLAB_MRFOU;Previous Spot
TP_LOCALLAB_MRONE;None
@@ -2689,12 +2698,12 @@ TP_LOCALLAB_ORIGLC;Merge only with original image
TP_LOCALLAB_ORRETILAP_TOOLTIP;Acts on a second Laplacian threshold, to take into account ΔE to differentiate the action especially with the background (different from Scope)
TP_LOCALLAB_ORRETISTREN_TOOLTIP;Acts on the Laplacian threshold, the greater the action, the more the differences in contrast will be reduced
TP_LOCALLAB_PASTELS2;Vibrance
-TP_LOCALLAB_PDE;Contrast attenuator - Dynamic Range compression
-TP_LOCALLAB_PDEFRA;Contrast attenuator ƒ
+TP_LOCALLAB_PDE;Contrast Attenuator - Dynamic Range compression
+TP_LOCALLAB_PDEFRA;Contrast Attenuator ƒ
TP_LOCALLAB_PDEFRAME_TOOLTIP;PDE IPOL - personal algorithm adapted from IPOL to Rawtherapee: lead to very different results and needs differents settings that Standard (negative black, gamma < 1,...)\nMay be usefull for low exposure or high dynamic range.\n
TP_LOCALLAB_PREVIEW;Preview ΔE
-TP_LOCALLAB_PREVHIDE;Hide all settings
-TP_LOCALLAB_PREVSHOW;Show all settings
+TP_LOCALLAB_PREVHIDE;Hide additional settings
+TP_LOCALLAB_PREVSHOW;Show additional settings
TP_LOCALLAB_PROXI;ΔE decay
TP_LOCALLAB_QUALCURV_METHOD;Curves type
TP_LOCALLAB_QUAL_METHOD;Global quality
@@ -2717,7 +2726,7 @@ TP_LOCALLAB_RESIDHI;Highlights
TP_LOCALLAB_RESIDHITHR;Highlights threshold
TP_LOCALLAB_RESIDSHA;Shadows
TP_LOCALLAB_RESIDSHATHR;Shadows threshold
-TP_LOCALLAB_RETI;Dehaze - Retinex Strong contrast
+TP_LOCALLAB_RETI;Dehaze - Retinex
TP_LOCALLAB_RETIFRA;Retinex
TP_LOCALLAB_RETIM;Original Retinex
TP_LOCALLAB_RETITOOLFRA;Retinex Tools
@@ -2757,8 +2766,9 @@ TP_LOCALLAB_SH1;Shadows Highlights
TP_LOCALLAB_SH2;Equalizer
TP_LOCALLAB_SHADEX;Shadows
TP_LOCALLAB_SHADEXCOMP;Shadows compression & tonal width
-TP_LOCALLAB_SHADHIGH;ShadowsHighlight - Tone equalizer
-TP_LOCALLAB_SHADOWHIGHLIGHT_TOOLTIP;Can be used instead - or in complement - of exposure module in difficult cases.\nThe use of Denoise may be necessary : lightening the shadows.\n\nCan be used as graduated filter (increase Scope)
+TP_LOCALLAB_SHADHIGH;Shadows/Highlights-Tone equalizer
+TP_LOCALLAB_SHADOWHIGHLIGHT_TOOLTIP;Adjust shadows & highlights either with shadows & highlights sliders or with a tone equalizer.\nCan be used instead of, or in conjunction with the Exposure module.\nCan also be used as a graduated filter.
+//Can be used instead - or in complement - of exposure module in difficult cases.\nThe use of Denoise may be necessary : lightening the shadows.\n\nCan be used as graduated filter (increase Scope)
TP_LOCALLAB_SHAMASKCOL;Shadows mask
TP_LOCALLAB_SHAPETYPE;Shape RT-spot area
TP_LOCALLAB_SHAPE_TOOLTIP;Elipse is normal mode.\nRectangle can be used in some cases, for example to work in full image in conjonction with delimiters outside preview, transition = 100.\n\nPolygone - Beziers are waiting for GUI...
@@ -2796,13 +2806,13 @@ TP_LOCALLAB_SHOWPOISSON;Poisson (pde ƒ)
TP_LOCALLAB_SHOWR;Mask and modifications
TP_LOCALLAB_SHOWREF;Preview ΔE
TP_LOCALLAB_SHOWS;Mask and modifications
-TP_LOCALLAB_SHOWSTRUC;Show structure Spot(expert)
-TP_LOCALLAB_SHOWSTRUCEX;Show structure Spot(expert)
+TP_LOCALLAB_SHOWSTRUC;Show structure Spot(advanced)
+TP_LOCALLAB_SHOWSTRUCEX;Show structure Spot(advanced)
TP_LOCALLAB_SHOWT;Mask and modifications
TP_LOCALLAB_SHOWVI;Mask and modifications
TP_LOCALLAB_SHRESFRA;Shadows/Highlights
TP_LOCALLAB_SHTRC_TOOLTIP;Modifies the tones of the image by acting on a TRC (Tone Response Curve).\nGamma acts mainly on light tones.\nSlope acts mainly on dark tones
-TP_LOCALLAB_SH_TOOLNAME;Shadows Highlight & Tone Equalizer - 5
+TP_LOCALLAB_SH_TOOLNAME;Shadows Highlights & Tone Equalizer - 5
TP_LOCALLAB_SIGMAWAV;Attenuation Response
TP_LOCALLAB_SIM;Simple
TP_LOCALLAB_SLOMASKCOL;Slope mask
@@ -2816,7 +2826,7 @@ TP_LOCALLAB_SOFTRETI;Reduce artifact ΔE
TP_LOCALLAB_SOFTRETI_TOOLTIP;Take into account deltaE to improve Transmission map
TP_LOCALLAB_SOFT_TOOLNAME;Soft Light & Original Retinex - 6
TP_LOCALLAB_SOURCE_GRAY;Value
-TP_LOCALLAB_SPECCASE; Specific cases
+TP_LOCALLAB_SPECCASE;Specific cases
TP_LOCALLAB_SPECIAL;Special use of RGB curves
TP_LOCALLAB_SPECIAL_TOOLTIP;Only for this RGB curve, disabled (or reduce effects) of Scope, mask...for example, if you want to have a negative effect.
TP_LOCALLAB_SPOTNAME;New Spot
@@ -2832,7 +2842,7 @@ TP_LOCALLAB_STRRETI_TOOLTIP;if Strength Retinex < 0.2 only Dehaze is enabled.\ni
TP_LOCALLAB_STRUC;Structure
TP_LOCALLAB_STRUCCOL;Structure
TP_LOCALLAB_STRUCCOL1;Structure Spot
-TP_LOCALLAB_STRUCT_TOOLTIP;Use Sobel algorithm to take into account structure in shape detection.\nyou can have a preview by activating "mask and modifications - Show structure spot".\n\nCan be used in conjunction with masks (expert) structure, blur, wavelet to improve edge detection.\n\nNeeds maskless adjustments to be activated (lightness, exposure...)
+TP_LOCALLAB_STRUCT_TOOLTIP;Use Sobel algorithm to take into account structure in shape detection.\nyou can have a preview by activating "mask and modifications - Show structure spot".\n\nCan be used in conjunction with masks (advanced) structure, blur, wavelet to improve edge detection.\n\nNeeds maskless adjustments to be activated (lightness, exposure...)
TP_LOCALLAB_STRUMASKCOL;Structure mask strength
TP_LOCALLAB_STRUMASK_TOOLTIP;Generate a structure mask with difference between surface areas and reliefs.\nIf structure mask as tool is enabled, this mask is used in addition to the other tools (gamma, slope, contrast curve ...)
TP_LOCALLAB_STYPE;Shape method
@@ -2852,7 +2862,8 @@ TP_LOCALLAB_TM_MASK;Use transmission map
TP_LOCALLAB_TONEMAPESTOP_TOOLTIP;This parameter affects sensitivity to edges.\n The greater it is the more likely an illumination change is to be considered an "edge".\n If set to zero tone mapping will have an effect similar to unsharp masking.
TP_LOCALLAB_TONEMAPGAM_TOOLTIP;Gamma moves the action of tone-mapping to shadows or highlights.
TP_LOCALLAB_TONEMAPREWEI_TOOLTIP;In some cases tone mapping may result in a cartoonish appearance, and in some rare cases soft but wide halos may appear.\n Increasing the number of reweighting iterates will help fight some of these problems.
-TP_LOCALLAB_TONEMAP_TOOLTIP;Tone Mapping - main menu must be disabled
+TP_LOCALLAB_TONEMAP_TOOLTIP;Same as the tone mapping tool in the main menu.\nThe main menu tool must be de-activated if this tool is used.
+//Tone Mapping - main menu must be disabled
TP_LOCALLAB_TONEMASCALE_TOOLTIP;This control gives meaning to the difference between "local" and "global" contrast.\nThe greater it is the larger a detail needs to be in order to be boosted
TP_LOCALLAB_TONE_TOOLNAME;Tone Mapping - 4
TP_LOCALLAB_TOOLCOL;Structure mask as tool
@@ -2870,15 +2881,16 @@ TP_LOCALLAB_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscis
TP_LOCALLAB_USEMASK;Use mask
TP_LOCALLAB_VART;Variance (contrast)
TP_LOCALLAB_VIBRANCE;Vibrance - Warm & Cool
+TP_LOCALLAB_VIBRA_TOOLTIP;Adjust vibrance (essentially the same as the global adjustment).\nCarry out the equivalent of a white-balance adjustment using a CIECAM algorithm.
TP_LOCALLAB_VIB_TOOLNAME;Vibrance - Warm & Cool - 3
TP_LOCALLAB_SOFT_TOOLNAME;Soft Light & Original Retinex - 6
-TP_LOCALLAB_BLUR_TOOLNAME;Smooth Blur Gain & Denoise - 1
+TP_LOCALLAB_BLUR_TOOLNAME;Smooth Blur Grain & Denoise - 1
TP_LOCALLAB_TONE_TOOLNAME;Tone Mapping - 4
TP_LOCALLAB_RET_TOOLNAME;Dehaze & Retinex - 9
TP_LOCALLAB_SHARP_TOOLNAME;Sharpening - 8
-TP_LOCALLAB_LC_TOOLNAME;Local Constrast & Wavelet (Defects) - 7
-TP_LOCALLAB_CBDL_TOOLNAME;CBDL (Defects) - 2
-TP_LOCALLAB_LOG_TOOLNAME;Encoding log - 0
+TP_LOCALLAB_LC_TOOLNAME;Local Contrast & Wavelet - 7
+TP_LOCALLAB_CBDL_TOOLNAME;CBDL - 2
+TP_LOCALLAB_LOG_TOOLNAME;Log Encoding - 0
TP_LOCALLAB_MASKCOM_TOOLNAME;Common Color Mask - 13
TP_LOCALLAB_VIS_TOOLTIP;Click to show/hide selected Control Spot.\nCtrl+click to show/hide all Control Spot.
TP_LOCALLAB_WAMASKCOL;Ψ Mask Wavelet level
@@ -3236,18 +3248,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
@@ -3255,9 +3267,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
@@ -3265,7 +3277,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
@@ -3276,10 +3288,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
@@ -3288,16 +3304,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
@@ -3306,34 +3322,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
@@ -3341,7 +3357,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 white balance is incorrect.
-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 white balance is incorrect.
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.
@@ -3349,18 +3365,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
@@ -3368,7 +3384,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
@@ -3379,24 +3395,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
@@ -3405,15 +3421,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
@@ -3421,7 +3437,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
@@ -3434,11 +3450,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
diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc
index fa9788af0..c17826623 100644
--- a/rtengine/CA_correct_RT.cc
+++ b/rtengine/CA_correct_RT.cc
@@ -123,7 +123,7 @@ float* RawImageSource::CA_correct_RT(
double cared,
double cablue,
bool avoidColourshift,
- const array2D &rawData,
+ array2D &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* nonGreen = colour == 0 ? redFactor : blueFactor;
+ array2D* 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* nonGreen = colour == 0 ? redFactor : blueFactor;
+ array2D* 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];
}
diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc
index fca26987f..a2929acbb 100644
--- a/rtengine/FTblockDN.cc
+++ b/rtengine/FTblockDN.cc
@@ -2108,17 +2108,17 @@ float ImProcFunctions::Mad(const float * DataList, const int datalen)
}
//find median of histogram
- int median = 0, count = 0;
+ int lmedian = 0, count = 0;
while (count < datalen / 2) {
- count += histo[median];
- ++median;
+ count += histo[lmedian];
+ ++lmedian;
}
- int count_ = count - histo[median - 1];
+ int count_ = count - histo[lmedian - 1];
// interpolate
- return (((median - 1) + (datalen / 2 - count_) / (static_cast(count - count_))) / 0.6745f);
+ return ((lmedian - 1) + (datalen / 2 - count_) / (static_cast(count - count_))) / 0.6745f;
}
float ImProcFunctions::MadRgb(const float * DataList, const int datalen)
@@ -2141,18 +2141,18 @@ float ImProcFunctions::MadRgb(const float * DataList, const int datalen)
}
//find median of histogram
- int median = 0, count = 0;
+ int lmedian = 0, count = 0;
while (count < datalen / 2) {
- count += histo[median];
- ++median;
+ count += histo[lmedian];
+ ++lmedian;
}
- int count_ = count - histo[median - 1];
+ int count_ = count - histo[lmedian - 1];
// interpolate
delete[] histo;
- return (((median - 1) + (datalen / 2 - count_) / (static_cast(count - count_))) / 0.6745f);
+ return ((lmedian - 1) + (datalen / 2 - count_) / (static_cast(count - count_))) / 0.6745f;
}
diff --git a/rtengine/array2D.h b/rtengine/array2D.h
index de6381aeb..512f7bcc1 100644
--- a/rtengine/array2D.h
+++ b/rtengine/array2D.h
@@ -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 my_array (10,10); // creates 10x10 array of floats
* value = my_array[3][5];
@@ -48,25 +48,20 @@
* array2D 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 // for raise()
#include
+#include
+#include
+#include
+#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
-#include
-
-#include "noncopyable.h"
template
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 rows;
+ std::vector 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(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
-class multi_array2D
+class multi_array2D : public rtengine::NonCopyable
{
private:
array2D 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 & operator[](int index)
{
assert(static_cast(index) < num);
diff --git a/rtengine/ashift_lsd.c b/rtengine/ashift_lsd.c
index a884da437..3a0ec5aba 100644
--- a/rtengine/ashift_lsd.c
+++ b/rtengine/ashift_lsd.c
@@ -1770,10 +1770,10 @@ static void region_grow( int x, int y, image_double angles, struct point * reg,
int xx,yy,i;
/* check parameters */
- if( x < 0 || y < 0 || x >= (int) angles->xsize || y >= (int) angles->ysize )
- error("region_grow: (x,y) out of the image.");
if( angles == NULL || angles->data == NULL )
error("region_grow: invalid image 'angles'.");
+ if( x < 0 || y < 0 || x >= (int) angles->xsize || y >= (int) angles->ysize )
+ error("region_grow: (x,y) out of the image.");
if( reg == NULL ) error("region_grow: invalid 'reg'.");
if( reg_size == NULL ) error("region_grow: invalid pointer 'reg_size'.");
if( reg_angle == NULL ) error("region_grow: invalid pointer 'reg_angle'.");
diff --git a/rtengine/camconst.json b/rtengine/camconst.json
index 19e25264c..578ff1811 100644
--- a/rtengine/camconst.json
+++ b/rtengine/camconst.json
@@ -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]
},
@@ -1556,10 +1564,14 @@ Camera constants:
}
},
- { // Quality B
+ { // Quality A, samples provided by dimonoid (#5842)
"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": 4087 }
+ "ranges": {
+ "black": 200,
+ "white": [ 4000, 4050, 3950 ] // Typical values without LENR: 4009, 4093, 3963
+ } // No significant influence of ISO
+ // No aperture scaling reported
},
{ // Quality B, no LENR samples
@@ -1717,6 +1729,55 @@ Camera constants:
"pdaf_offset" : 32
},
+ { // Quality A, white levels and PDAF lines measured by Yann Leprince #5851
+ "make_model" : "Nikon Z 50",
+ "dcraw_matrix" : [11640, -4829, -1079, -5107, 13006, 2325, -972, 1711, 7380], // Adobe DNG Converter 12.2.1 ColorMatrix2 (D65)
+ "ranges": {
+ "white": [
+ // White level was consistently measured at 16383 for non-LENR images. These values are computed using
+ // 16383 - 6 * read_noise (where read_noise values are extracted from
+ // https://www.photonstophotos.net/Charts/RN_ADU.htm#Nikon%20Z%2050_14 for iso < 1600, fitted in the
+ // 1600-10183 range, and extrapolated from that fit into the 12800-204800 range, where the read noise
+ // provided by photonstophotos is underestimated due to in-body noise reduction. These values were
+ // verified to be below the 1st percentile of the distribution, on LENR white frames taken with a 2 s
+ // shutter in a variety of conditions (apertures from 1.8 to 6.3).
+ {"iso": 100, "levels": 16374},
+ {"iso": 126, "levels": 16371},
+ {"iso": 159, "levels": 16367},
+ {"iso": 200, "levels": 16367},
+ {"iso": 251, "levels": 16364},
+ {"iso": 318, "levels": 16360},
+ {"iso": 400, "levels": 16366},
+ {"iso": 503, "levels": 16364},
+ {"iso": 636, "levels": 16362},
+ {"iso": 800, "levels": 16358},
+ {"iso": 1006, "levels": 16349},
+ {"iso": 1273, "levels": 16345},
+ {"iso": 1600, "levels": 16337},
+ {"iso": 2011, "levels": 16327},
+ {"iso": 2546, "levels": 16313},
+ {"iso": 3200, "levels": 16298},
+ {"iso": 4022, "levels": 16278},
+ {"iso": 5091, "levels": 16253},
+ {"iso": 6400, "levels": 16223},
+ {"iso": 8045, "levels": 16186},
+ {"iso": 10183, "levels": 16139},
+ {"iso": 12800, "levels": 16082},
+ {"iso": 16090, "levels": 16013},
+ {"iso": 20366, "levels": 15924},
+ {"iso": 25600, "levels": 15818},
+ {"iso": 32180, "levels": 15687},
+ {"iso": 40731, "levels": 15521},
+ {"iso": 51200, "levels": 15321},
+ {"iso": 102400, "levels": 14388},
+ {"iso": 204800, "levels": 12633}
+ ]
+ },
+ "pdaf_offset": 0,
+ // Every 12th line from 285 to 3441. These lines (specifically, the blue subpixels) have a lower standard deviation on a black frame.
+ "pdaf_pattern": [285, 297, 309, 321, 333, 345, 357, 369, 381, 393, 405, 417, 429, 441, 453, 465, 477, 489, 501, 513, 525, 537, 549, 561, 573, 585, 597, 609, 621, 633, 645, 657, 669, 681, 693, 705, 717, 729, 741, 753, 765, 777, 789, 801, 813, 825, 837, 849, 861, 873, 885, 897, 909, 921, 933, 945, 957, 969, 981, 993, 1005, 1017, 1029, 1041, 1053, 1065, 1077, 1089, 1101, 1113, 1125, 1137, 1149, 1161, 1173, 1185, 1197, 1209, 1221, 1233, 1245, 1257, 1269, 1281, 1293, 1305, 1317, 1329, 1341, 1353, 1365, 1377, 1389, 1401, 1413, 1425, 1437, 1449, 1461, 1473, 1485, 1497, 1509, 1521, 1533, 1545, 1557, 1569, 1581, 1593, 1605, 1617, 1629, 1641, 1653, 1665, 1677, 1689, 1701, 1713, 1725, 1737, 1749, 1761, 1773, 1785, 1797, 1809, 1821, 1833, 1845, 1857, 1869, 1881, 1893, 1905, 1917, 1929, 1941, 1953, 1965, 1977, 1989, 2001, 2013, 2025, 2037, 2049, 2061, 2073, 2085, 2097, 2109, 2121, 2133, 2145, 2157, 2169, 2181, 2193, 2205, 2217, 2229, 2241, 2253, 2265, 2277, 2289, 2301, 2313, 2325, 2337, 2349, 2361, 2373, 2385, 2397, 2409, 2421, 2433, 2445, 2457, 2469, 2481, 2493, 2505, 2517, 2529, 2541, 2553, 2565, 2577, 2589, 2601, 2613, 2625, 2637, 2649, 2661, 2673, 2685, 2697, 2709, 2721, 2733, 2745, 2757, 2769, 2781, 2793, 2805, 2817, 2829, 2841, 2853, 2865, 2877, 2889, 2901, 2913, 2925, 2937, 2949, 2961, 2973, 2985, 2997, 3009, 3021, 3033, 3045, 3057, 3069, 3081, 3093, 3105, 3117, 3129, 3141, 3153, 3165, 3177, 3189, 3201, 3213, 3225, 3237, 3249, 3261, 3273, 3285, 3297, 3309, 3321, 3333, 3345, 3357, 3369, 3381, 3393, 3405, 3417, 3429, 3441]
+ },
+
{ // Quality B, 16Mp and 64Mp raw frames
"make_model": "OLYMPUS E-M5MarkII",
"dcraw_matrix": [ 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 ], // DNG_v8.8 D65
@@ -2694,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
diff --git a/rtengine/color.cc b/rtengine/color.cc
index 11668451e..5761733f0 100644
--- a/rtengine/color.cc
+++ b/rtengine/color.cc
@@ -1189,48 +1189,26 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u
float koymcp = 0.f;
if(setting == "ROYGCBPM-Abs" || setting == "ROYGCBPM-Rel") {
- float obM = 0.f;
- float ogM = 0.f;
- float orM = 0.f;
-
- float ybM = 0.f;
- float yrM = 0.f;
- float ygM = 0.f;
-
- float mgM = 0.f;
- float mrM = 0.f;
- float mbM = 0.f;
-
- float pgM = 0.f;
- float prM = 0.f;
- float pbM = 0.f;
-
- float crM = 0.f;
- float cgM = 0.f;
- float cbM = 0.f;
- //printf("mixred=%f\n",mixerRed);
-
float fcompl = 1.f;
- if(complement && algo == "SP") {
+ if (complement && algo == "SP") {
fcompl = 3.f; //special
- } else if(complement && algo == "LI") {
+ } else if (complement && algo == "LI") {
fcompl = 1.5f; //linear
}
// ponderate filters: report to R=G=B=33
// I ponder RGB channel, not only orange or yellow or cyan, etc...it's my choice !
- if(mixerOrange != 33) {
- if (algo == "SP") { //special
- if (mixerOrange >= 33) {
- orM = fcompl * (mixerOrange * 0.67f - 22.11f) / 100.f;
- } else {
- orM = fcompl * (-0.3f * mixerOrange + 9.9f) / 100.f;
- }
+ if (mixerOrange != 33.f) {
+ float ogM = 0.f;
+ float orM = 0.f;
- if (mixerOrange >= 33) {
+ if (algo == "SP") { //special
+ if (mixerOrange > 33.f) {
+ orM = fcompl * (mixerOrange * 0.67f - 22.11f) / 100.f;
ogM = fcompl * (-0.164f * mixerOrange + 5.412f) / 100.f;
} else {
+ orM = fcompl * (-0.3f * mixerOrange + 9.9f) / 100.f;
ogM = fcompl * (0.4f * mixerOrange - 13.2f) / 100.f;
}
} else if (algo == "LI") { //linear
@@ -1238,30 +1216,24 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u
ogM = fcompl * (0.5f * mixerOrange - 16.5f) / 100.f;
}
- if(complement) {
- obM = (-0.492f * mixerOrange + 16.236f) / 100.f;
- }
+ const float obM = complement ? (-0.492f * mixerOrange + 16.236f) / 100.f : 0.f;
- mixerRed += orM;
+ mixerRed += orM;
mixerGreen += ogM;
- mixerBlue += obM;
+ mixerBlue += obM;
koymcp += (orM + ogM + obM);
- // printf("mixred+ORange=%f\n",mixerRed);
-
}
- if(mixerYellow != 33) {
+ if (mixerYellow != 33.f) {
+ float yrM = 0.f;
if (algo == "SP") {
yrM = fcompl * (-0.134f * mixerYellow + 4.422f) / 100.f; //22.4
} else if (algo == "LI") {
yrM = fcompl * (0.5f * mixerYellow - 16.5f) / 100.f; //22.4
}
- ygM = fcompl * (0.5f * mixerYellow - 16.5f ) / 100.f;
-
- if(complement) {
- ybM = (-0.492f * mixerYellow + 16.236f) / 100.f;
- }
+ const float ygM = fcompl * (0.5f * mixerYellow - 16.5f ) / 100.f;
+ const float ybM = complement ? (-0.492f * mixerYellow + 16.236f) / 100.f : 0.f;
mixerRed += yrM;
mixerGreen += ygM;
@@ -1269,17 +1241,15 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u
koymcp += (yrM + ygM + ybM);
}
- if(mixerMagenta != 33) {
+ if (mixerMagenta != 33.f) {
+ float mrM = 0.f;
+ float mbM = 0.f;
if (algo == "SP") {
- if(mixerMagenta >= 33) {
+ if (mixerMagenta > 33.f) {
mrM = fcompl * ( 0.67f * mixerMagenta - 22.11f) / 100.f;
- } else {
- mrM = fcompl * (-0.3f * mixerMagenta + 9.9f) / 100.f;
- }
-
- if(mixerMagenta >= 33) {
mbM = fcompl * (-0.164f * mixerMagenta + 5.412f) / 100.f;
} else {
+ mrM = fcompl * (-0.3f * mixerMagenta + 9.9f) / 100.f;
mbM = fcompl * ( 0.4f * mixerMagenta - 13.2f) / 100.f;
}
} else if (algo == "LI") {
@@ -1287,9 +1257,7 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u
mbM = fcompl * (0.5f * mixerMagenta - 16.5f) / 100.f;
}
- if(complement) {
- mgM = (-0.492f * mixerMagenta + 16.236f) / 100.f;
- }
+ const float mgM = complement ? (-0.492f * mixerMagenta + 16.236f) / 100.f : 0.f;
mixerRed += mrM;
mixerGreen += mgM;
@@ -1297,18 +1265,16 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u
koymcp += (mrM + mgM + mbM);
}
- if(mixerPurple != 33) {
+ if (mixerPurple != 33.f) {
+ float prM = 0.f;
if (algo == "SP") {
prM = fcompl * (-0.134f * mixerPurple + 4.422f) / 100.f;
} else if (algo == "LI") {
prM = fcompl * (0.5f * mixerPurple - 16.5f) / 100.f;
}
- pbM = fcompl * (0.5f * mixerPurple - 16.5f) / 100.f;
-
- if(complement) {
- pgM = (-0.492f * mixerPurple + 16.236f) / 100.f;
- }
+ const float pbM = fcompl * (0.5f * mixerPurple - 16.5f) / 100.f;
+ const float pgM = complement ? (-0.492f * mixerPurple + 16.236f) / 100.f : 0.f;
mixerRed += prM;
mixerGreen += pgM;
@@ -1316,18 +1282,16 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u
koymcp += (prM + pgM + pbM);
}
- if(mixerCyan != 33) {
+ if (mixerCyan != 33.f) {
+ float cgM = 0.f;
if (algo == "SP") {
cgM = fcompl * (-0.134f * mixerCyan + 4.422f) / 100.f;
} else if (algo == "LI") {
cgM = fcompl * (0.5f * mixerCyan - 16.5f) / 100.f;
}
- cbM = fcompl * (0.5f * mixerCyan - 16.5f) / 100.f;
-
- if(complement) {
- crM = (-0.492f * mixerCyan + 16.236f) / 100.f;
- }
+ const float cbM = fcompl * (0.5f * mixerCyan - 16.5f) / 100.f;
+ const float crM = complement ? (-0.492f * mixerCyan + 16.236f) / 100.f : 0.f;
mixerRed += crM;
mixerGreen += cgM;
@@ -1347,7 +1311,7 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u
filblue = 1.f;
filcor = 1.f;
- if (filter == "None") {
+ if (filter == "None") {
filred = 1.f;
filgreen = 1.f;
filblue = 1.f;
@@ -1496,101 +1460,79 @@ void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int alg
const float xl, const float yl, const float zl, const float x2, const float y2, const float z2,
const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo)
{
- float X1, Y1, Z1, X2, Y2, Z2, X, Y, Z, XL, YL, ZL;
- float L1 = 0.f, L2, LL, a_1 = 0.f, b_1 = 0.f, a_2 = 0.f, b_2 = 0.f, a_L, b_L;
+ float L1 = 0.f, a_1 = 0.f, b_1 = 0.f, a_2 = 0.f, b_2 = 0.f, a_L = 0.f, b_L = 0.f;
- // converting color 1 to Lab (image)
- Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb);
-
- if(algm == 1) {//use H interpolate
+ if (algm == 1) {//use H interpolate
+ // converting color 1 to Lab (image)
+ float X1, Y1, Z1;
+ Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb);
Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1);
- //Color::Lab2Lch(a_1, b_1, c_1, h_1) ;
}
// converting color l lab(low) first color
- if(twoc == 0) { // 2 colours
- //Color::rgbxyz(rl, gl, bl, XL, YL, ZL, xyz_rgb);
- XL = xl;
- YL = yl;
- ZL = zl;
-
- if(algm <= 1) {//use H interpolate
- Color::XYZ2Lab(XL, YL, ZL, LL, a_L, b_L);
+ if (twoc == 0) { // 2 colours
+ if (algm == 1) {//use H interpolate
+ float unused;
+ Color::XYZ2Lab(xl, yl, zl, unused, a_L, b_L);
}
}
// converting color 2 to lab (universal or high)
- X2 = x2;
- Y2 = y2;
- Z2 = z2;
-
- if(algm == 1 ) {
- Color::XYZ2Lab(X2, Y2, Z2, L2, a_2, b_2);
- //Color::Lab2Lch(a_2, b_2, c_2, h_2) ;
+ if (algm == 1) {
+ float unused;
+ Color::XYZ2Lab(x2, y2, z2, unused, a_2, b_2);
}
- float cal, calH, calm;
- cal = calH = calm = 1.f - chromat;
- float med = 1.f;
- float medH = 0.f;
-
- float calan;
- calan = chromat;
-
- float calby;
- calby = luma;
-
- if(twoc == 0) { // 2 colours
- calan = chromat;
+ float cal, calH;
+ cal = calH = 1.f - chromat;
+ if (twoc == 0) { // 2 colours
//calculate new balance chroma
- if (realL > iplow && realL <= med) {
- cal = realL * calan / (iplow - med) - med * calan / (iplow - med);
+ constexpr float med = 1.f;
+ if (realL > iplow && realL <= med) {
+ cal = realL * chromat / (iplow - med) - chromat / (iplow - med);
} else if (realL <= iplow) {
- cal = realL * calan / iplow;
+ cal = realL * chromat / iplow;
}
- if (realL > medH && realL <= iphigh) {
- calH = realL * calan / (iphigh - medH) - medH * calan / (iphigh - medH);
+ if (realL > 0.f && realL <= iphigh) {
+ calH = realL * chromat / iphigh;
} else if (realL > iphigh) {
- calH = realL * calan; //*(iphigh-1.f) - calan*(iphigh-1.f);//it is better without transition in highlight
+ calH = realL * chromat; //*(iphigh-1.f) - chromat*(iphigh-1.f);//it is better without transition in highlight
}
}
- float aaH, bbH;
-
- if(algm <= 1) {
- if(twoc == 0 && metchrom == 3) { // 2 colours only with special "ab"
- if(algm == 1) {
- aaH = a_1 + (a_2 - a_1) * calH;
- bbH = b_1 + (b_2 - b_1) * calH; //pass to line after
+ if (algm <= 1) {
+ if (twoc == 0 && metchrom == 3) { // 2 colours only with special "ab"
+ if (algm == 1) {
+ const float aaH = a_1 + (a_2 - a_1) * calH;
+ const float bbH = b_1 + (b_2 - b_1) * calH; //pass to line after
a_1 = aaH + (a_L - aaH) * cal * balance;
b_1 = bbH + (b_L - bbH) * cal * balance;
}
- } else if(twoc == 1) {
- if(metchrom == 0) {
+ } else if (twoc == 1) {
+ if (metchrom == 0) {
a_1 = a_1 + (a_2 - a_1) * balance;
b_1 = b_1 + (b_2 - b_1) * balance;
- } else if(metchrom == 1) {
- a_1 = a_1 + (a_2 - a_1) * calan * balance;
- b_1 = b_1 + (b_2 - b_1) * calan * balance;
- } else if(metchrom == 2) {
- a_1 = a_1 + (a_2 - a_1) * calan * balance;
- b_1 = b_1 + (b_2 - b_1) * calby * balance;
+ } else if (metchrom == 1) {
+ a_1 = a_1 + (a_2 - a_1) * chromat * balance;
+ b_1 = b_1 + (b_2 - b_1) * chromat * balance;
+ } else if (metchrom == 2) {
+ a_1 = a_1 + (a_2 - a_1) * chromat * balance;
+ b_1 = b_1 + (b_2 - b_1) * luma * balance;
}
}
}
+ float X, Y, Z;
Color::Lab2XYZ(L1, a_1, b_1, X, Y, Z);
-
Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz);// ro go bo in gamut
}
-void Color::calcGamma (double pwr, double ts, int mode, GammaValues &gamma)
+void Color::calcGamma (double pwr, double ts, GammaValues &gamma)
{
//from Dcraw (D.Coffin)
- int i;
- double g[6], bnd[2] = {0., 0.};
+ double g[6], bnd[2] = {};
g[0] = pwr;
g[1] = ts;
@@ -1598,7 +1540,7 @@ void Color::calcGamma (double pwr, double ts, int mode, GammaValues &gamma)
bnd[g[1] >= 1.] = 1.;
if (g[1] && (g[1] - 1.) * (g[0] - 1.) <= 0.) {
- for (i = 0; i < 99; i++) {
+ for (int i = 0; i < 99; i++) {
g[2] = (bnd[0] + bnd[1]) / 2.;
if (g[0]) {
@@ -1621,16 +1563,13 @@ void Color::calcGamma (double pwr, double ts, int mode, GammaValues &gamma)
g[5] = 1. / (g[1] * SQR(g[3]) / 2. + 1. - g[2] - g[3] - g[2] * g[3] * (log(g[3]) - 1.)) - 1.;
}
- if (!mode--) {
- gamma[0] = g[0];
- gamma[1] = g[1];
- gamma[2] = g[2];
- gamma[3] = g[3];
- gamma[4] = g[4];
- gamma[5] = g[5];
- gamma[6] = 0.;
- return;
- }
+ gamma[0] = g[0];
+ gamma[1] = g[1];
+ gamma[2] = g[2];
+ gamma[3] = g[3];
+ gamma[4] = g[4];
+ gamma[5] = g[5];
+ gamma[6] = 0.;
}
void Color::gammaf2lut (LUTf &gammacurve, float gamma, float start, float slope, float divisor, float factor)
{
@@ -1833,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__
@@ -2039,7 +1978,7 @@ void Color::Lch2Luv(float c, float h, float &u, float &v)
* columns of the matrix p=xyz_rgb are RGB tristimulus primaries in XYZ
* c is the color fixed on the boundary; and m=0 for c=0, m=1 for c=255
*/
-void Color::gamutmap(float &X, float &Y, float &Z, const double p[3][3])
+void Color::gamutmap(float &X, float Y, float &Z, const double p[3][3])
{
float u = 4 * X / (X + 15 * Y + 3 * Z) - u0;
float v = 9 * Y / (X + 15 * Y + 3 * Z) - v0;
@@ -2076,96 +2015,33 @@ void Color::gamutmap(float &X, float &Y, float &Z, const double p[3][3])
Z = (12 - 3 * u - 20 * v) * Y / (4 * v);
}
-void Color::skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s)
-{
- float factorskin, factorsat, factor, factorskinext, interm;
- float scale = 100.0f / 100.1f; //reduction in normal zone
- float scaleext = 1.0f; //reduction in transition zone
- float deltaHH = 0.3f; //HH value transition : I have choice 0.3 radians
- float HH;
- bool doskin = false;
-
- //rough correspondence between h (JC) and H (lab) that has relatively little importance because transitions that blur the correspondence is not linear
- if ((float)h > 8.6f && (float)h <= 74.f ) {
- HH = (1.15f / 65.4f) * (float)h - 0.0012f; //H > 0.15 H<1.3
- doskin = true;
- } else if((float)h > 0.f && (float)h <= 8.6f ) {
- HH = (0.19f / 8.6f ) * (float)h - 0.04f; //H>-0.04 H < 0.15
- doskin = true;
- } else if((float)h > 355.f && (float)h <= 360.f) {
- HH = (0.11f / 5.0f ) * (float)h - 7.96f; //H>-0.15 <-0.04
- doskin = true;
- } else if((float)h > 74.f && (float)h < 95.f ) {
- HH = (0.30f / 21.0f) * (float)h + 0.24285f; //H>1.3 H<1.6
- doskin = true;
- }
-
- if(doskin) {
- float chromapro = sres / Sp;
-
- if(sk == 1) { //in C mode to adapt dred to J
- if (J < 16.0) {
- dred = 40.0f;
- } else if(J < 22.0) {
- dred = 2.5f * (float)J;
- } else if(J < 60.0) {
- dred = 55.0f;
- } else if(J < 70.0) {
- dred = -1.5f * (float)J + 145.0f;
- } else {
- dred = 40.0f;
- }
- }
-
- if(chromapro > 0.0) {
- Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext); //Scale factor
- }
-
- if(chromapro > 1.0) {
- interm = (chromapro - 1.0f) * 100.0f;
- factorskin = 1.0f + (interm * scale) / 100.0f;
- factorskinext = 1.0f + (interm * scaleext) / 100.0f;
- } else {
- factorskin = chromapro ;
- factorskinext = chromapro ;
- }
-
- factorsat = chromapro;
- factor = factorsat;
- Color::transitred ( HH, s, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition
- s *= factor;
- } else {
- s = ko * sres;
- }
-
-}
void Color::skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s)
{
float HH;
bool doskin = false;
//rough correspondence between h (JC) and H (lab) that has relatively little importance because transitions that blur the correspondence is not linear
- if ((float)h > 8.6f && (float)h <= 74.f ) {
- HH = (1.15f / 65.4f) * (float)h - 0.0012f; //H > 0.15 H<1.3
+ if (h > 8.6f && h <= 74.f) {
+ HH = (1.15f / 65.4f) * h - 0.0012f; //H > 0.15 H<1.3
doskin = true;
- } else if((float)h > 0.f && (float)h <= 8.6f ) {
- HH = (0.19f / 8.6f ) * (float)h - 0.04f; //H>-0.04 H < 0.15
+ } else if(h > 0.f && h <= 8.6f) {
+ HH = (0.19f / 8.6f) * h - 0.04f; //H>-0.04 H < 0.15
doskin = true;
- } else if((float)h > 355.f && (float)h <= 360.f) {
- HH = (0.11f / 5.0f ) * (float)h - 7.96f; //H>-0.15 <-0.04
+ } else if(h > 355.f && h <= 360.f) {
+ HH = (0.11f / 5.0f) * h - 7.96f; //H>-0.15 <-0.04
doskin = true;
- } else if((float)h > 74.f && (float)h < 95.f ) {
- HH = (0.30f / 21.0f) * (float)h + 0.24285f; //H>1.3 H<1.6
+ } else if(h > 74.f && h < 95.f ) {
+ HH = (0.30f / 21.0f) * h + 0.24285f; //H>1.3 H<1.6
doskin = true;
}
if(doskin) {
- float factorskin, factorsat, factor, factorskinext;
+ float factorskin, factor, factorskinext;
float deltaHH = 0.3f; //HH value transition : I have choice 0.3 radians
float chromapro = sres / Sp;
if(sk == 1) { //in C mode to adapt dred to J
- if (J < 16.f) {
+ if (J < 16.f) {
dred = 40.f;
} else if(J < 22.f) {
dred = 2.5f * J;
@@ -2182,7 +2058,7 @@ void Color::skinredfloat ( float J, float h, float sres, float Sp, float dred, f
float scale = 0.999000999f; // 100.0f/100.1f; reduction in normal zone
float scaleext = 1.0f; //reduction in transition zone
Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//Scale factor
- float interm = (chromapro - 1.0f);
+ const float interm = chromapro - 1.0f;
factorskin = 1.0f + (interm * scale);
factorskinext = 1.0f + (interm * scaleext);
} else {
@@ -2190,21 +2066,14 @@ void Color::skinredfloat ( float J, float h, float sres, float Sp, float dred, f
factorskinext = chromapro ;
}
- factorsat = chromapro;
- factor = factorsat;
- Color::transitred ( HH, s, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition
+ factor = chromapro;
+ Color::transitred ( HH, s, dred, factorskin, protect_red, factorskinext, deltaHH, chromapro, factor); //transition
s *= factor;
} else {
s = ko * sres;
}
-
}
-
-
-
-
-
void Color::scalered ( const float rstprotection, const float param, const float limit, const float HH, const float deltaHH, float &scale, float &scaleext)
{
if(rstprotection < 99.9999f) {
@@ -2262,32 +2131,21 @@ void Color::transitred (const float HH, float const Chprov1, const float dred, c
void Color::AllMunsellLch(bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHuechroma, float &correctlum)
{
- bool contin1, contin2;
- float correctionHue = 0.0, correctionHueLum = 0.0;
- bool correctL;
+ if (CC >= 6.f && CC < 140.f) { //if C > 140 we say C=140 (only in Prophoto ...with very large saturation)
+ constexpr float huelimit[8] = { -2.48f, -0.55f, 0.44f, 1.52f, 1.87f, 3.09f, -0.27f, 0.44f}; //limits hue of blue-purple, red-yellow, green-yellow, red-purple
- if(CC >= 6.0 && CC < 140) { //if C > 140 we say C=140 (only in Prophoto ...with very large saturation)
- static const float huelimit[8] = { -2.48, -0.55, 0.44, 1.52, 1.87, 3.09, -0.27, 0.44}; //limits hue of blue-purple, red-yellow, green-yellow, red-purple
+ Chprov1 = rtengine::LIM(Chprov1, 6.f, 140.f);
- if (Chprov1 > 140.f) {
- Chprov1 = 139.f; //limits of LUTf
- }
-
- if (Chprov1 < 6.f) {
- Chprov1 = 6.f;
- }
-
- for(int zo = 1; zo <= 4; zo++) {
- if(HH > huelimit[2 * zo - 2] && HH < huelimit[2 * zo - 1]) {
- //zone=zo;
- contin1 = contin2 = false;
- correctL = false;
+ for (int zo = 1; zo <= 4; ++zo) {
+ if (HH > huelimit[2 * zo - 2] && HH < huelimit[2 * zo - 1]) {
+ bool correctL = false;
+ float correctionHue = 0.f, correctionHueLum = 0.f;
MunsellLch (Lprov1, HH, Chprov1, CC, correctionHue, zo, correctionHueLum, correctL); //munsell chroma correction
correctionHuechroma = correctionHue; //preserve
if(lumaMuns) {
+ bool contin1 = false;
float correctlumprov = 0.f;
- float correctlumprov2 = 0.f;
if(correctL) {
//for Munsell luminance correction
@@ -2296,26 +2154,19 @@ void Color::AllMunsellLch(bool lumaMuns, float Lprov1, float Loldd, float HH, fl
correctL = false;
}
- correctionHueLum = 0.0;
- correctionHue = 0.0;
-
- if(fabs(Lprov1 - Loldd) > 6.0) {
+ if (std::fabs(Lprov1 - Loldd) > 6.f) {
+ correctionHueLum = 0.f;
+ correctionHue = 0.f;
// correction if delta L significative..Munsell luminance
MunsellLch (Loldd, HH, Chprov1, Chprov1, correctionHue, zo, correctionHueLum, correctL);
-
if(correctL) {
- correctlumprov2 = correctionHueLum;
- contin2 = true;
- correctL = false;
- }
-
- correctionHueLum = 0.0;
-
- if(contin1 && contin2) {
- correctlum = correctlumprov2 - correctlumprov;
+ if(contin1) {
+ correctlum = correctionHueLum - correctlumprov;
+ }
}
}
}
+ break;
}
}
}
@@ -2337,9 +2188,6 @@ void Color::AllMunsellLch(bool lumaMuns, float Lprov1, float Loldd, float HH, fl
void Color::AllMunsellLch(float Lprov1, float HH, float Chprov1, float CC, float &correctionHuechroma)
{
- float correctionHue = 0.f, correctionHueLum = 0.f;
- bool correctL;
-
if(CC >= 6.f && CC < 140.f) { //if C > 140 we say C=140 (only in Prophoto ...with very large saturation)
static const float huelimit[8] = { -2.48f, -0.55f, 0.44f, 1.52f, 1.87f, 3.09f, -0.27f, 0.44f}; //limits hue of blue-purple, red-yellow, green-yellow, red-purple
@@ -2352,7 +2200,8 @@ void Color::AllMunsellLch(float Lprov1, float HH, float Chprov1, float CC, float
for(int zo = 1; zo <= 4; zo++) {
if(HH > huelimit[2 * zo - 2] && HH < huelimit[2 * zo - 1]) {
//zone=zo;
- correctL = false;
+ float correctionHue = 0.f, correctionHueLum = 0.f;
+ bool correctL = false;
MunsellLch (Lprov1, HH, Chprov1, CC, correctionHue, zo, correctionHueLum, correctL); //munsell chroma correction
correctionHuechroma = correctionHue; //preserve
break;
@@ -2761,8 +2610,6 @@ void Color::gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const
*/
void Color::LabGamutMunsell(float *labL, float *laba, float *labb, const int N, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const double wip[3][3])
{
- float correctlum = 0.f;
- float correctionHuechroma = 0.f;
#ifdef __SSE2__
// precalculate H and C using SSE
float HHBuffer[N];
@@ -2815,8 +2662,8 @@ void Color::LabGamutMunsell(float *labL, float *laba, float *labb, const int N,
}
labL[j] = Lprov1 * 327.68f;
- correctionHuechroma = 0.f;
- correctlum = 0.f;
+ float correctionHuechroma = 0.f;
+ float correctlum = 0.f;
if(corMunsell)
AllMunsellLch(lumaMuns, Lprov1, Loldd, HH, Chprov1, Coldd, correctionHuechroma, correctlum);
diff --git a/rtengine/color.h b/rtengine/color.h
index 55ef52e36..704871d39 100644
--- a/rtengine/color.h
+++ b/rtengine/color.h
@@ -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
@@ -1006,8 +1006,6 @@ public:
* @brief Get the gamma curves' parameters used by LCMS2
* @param pwr gamma value [>1]
* @param ts slope [0 ; 20]
- * @param mode [always 0]
- * @imax imax [always 0]
* @param gamma a pointer to an array of 6 double gamma values:
* gamma0 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value)
* gamma1 used in ip2Lab2rgb [0 ; 20], can be superior to 20, but it's quite unusual(return value)
@@ -1016,7 +1014,7 @@ public:
* gamma4 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value)
* gamma5 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value)
*/
- static void calcGamma (double pwr, double ts, int mode, GammaValues &gamma);
+ static void calcGamma (double pwr, double ts, GammaValues &gamma);
/**
@@ -1468,9 +1466,7 @@ public:
static void scalered ( float rstprotection, float param, float limit, float HH, float deltaHH, float &scale, float &scaleext);
static void transitred (float HH, float Chprov1, float dred, float factorskin, float protect_red, float factorskinext, float deltaHH, float factorsat, float &factor);
- static void skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s);
static void skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s);
-// static void scaleredcdbl ( float skinprot, float param, float limit, float HH, float deltaHH, float &scale,float &scaleext);
static inline void pregamutlab(float lum, float hue, float &chr) //big approximation to limit gamut (Prophoto) before good gamut procedure for locallab chroma, to avoid crash
{
@@ -1801,11 +1797,11 @@ public:
/**
* @brief Gamut correction in the XYZ color space
* @param X X channel input value and corrected output value [0 ; 65535]
- * @param Y Y channel input value and corrected output value [0 ; 65535]
+ * @param Y Y channel input value[0 ; 65535]
* @param Z Z channel input value and corrected output value [0 ; 65535]
* @param p working profile
*/
- static void gamutmap(float &X, float &Y, float &Z, const double p[3][3]);
+ static void gamutmap(float &X, float Y, float &Z, const double p[3][3]);
/**
@@ -1839,7 +1835,6 @@ public:
} else if (HH >= -0.1f && HH < 0.f ) {
hr = 0.1 * double(HH) + 0.93; //hr 0.92 0.93 red
}
-
// in case of !
if (hr < 0.0) {
hr += 1.0;
diff --git a/rtengine/curves.cc b/rtengine/curves.cc
index 017f7755e..640074075 100644
--- a/rtengine/curves.cc
+++ b/rtengine/curves.cc
@@ -37,6 +37,33 @@
using namespace std;
+namespace {
+void fillCurveArray(const rtengine::DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed)
+{
+ if (needed) {
+ for (int i = 0; i <= 0xffff; i += i < 0xffff - skip ? skip : 1) {
+ // change to [0,1] range
+ // apply custom/parametric/NURBS curve, if any
+ outCurve[i] = diagCurve->getVal(i / 65535.f);
+ }
+
+ // if skip > 1, let apply linear interpolation in the skipped points of the curve
+ if (skip > 1) {
+ const float skipmul = 1.f / skip;
+
+ for (int i = 0; i <= 0x10000 - skip; i += skip) {
+ for (int j = 1; j < skip; j++) {
+ outCurve[i + j] = (outCurve[i] * (skip - j) + outCurve[i + skip] * j) * skipmul;
+ }
+ }
+ }
+
+ outCurve *= 65535.f;
+ } else {
+ outCurve.makeIdentity();
+ }
+}
+}
namespace rtengine
{
bool sanitizeCurve(std::vector& curve)
@@ -200,35 +227,6 @@ void Curve::getControlPoint(int cpNum, double &x, double &y) const
const double CurveFactory::sRGBGamma = 2.2;
const double CurveFactory::sRGBGammaCurve = 2.4;
-void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed)
-{
- if (needed) {
- for (int i = 0; i <= 0xffff; i += i < 0xffff - skip ? skip : 1) {
- // change to [0,1] range
- float val = (float)i / 65535.f;
- // apply custom/parametric/NURBS curve, if any
- val = diagCurve->getVal(val);
- // store result in a temporary array
- outCurve[i] = val;
- }
-
- // if skip>1, let apply linear interpolation in the skipped points of the curve
- if (skip > 1) {
- float skipmul = 1.f / (float) skip;
-
- for (int i = 0; i <= 0x10000 - skip; i += skip) {
- for (int j = 1; j < skip; j++) {
- outCurve[i + j] = (outCurve[i] * (skip - j) + outCurve[i + skip] * j) * skipmul;
- }
- }
- }
-
- outCurve *= 65535.f;
- } else {
- outCurve.makeIdentity();
- }
-}
-
void CurveFactory::curveLightBrightColor(const std::vector& curvePoints1, const std::vector& curvePoints2, const std::vector& curvePoints3,
const LUTu & histogram, LUTu & outBeforeCCurveHistogram,//for Luminance
const LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma
@@ -334,113 +332,34 @@ void CurveFactory::curveBW(const std::vector& curvePointsbw, const std::
}
}
-// add curve Lab : C=f(L)
-void CurveFactory::curveCL(bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, int skip)
-{
- clcutili = false;
- std::unique_ptr dCurve;
-
- if (!clcurvePoints.empty() && clcurvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(clcurvePoints, CURVES_MIN_POLY_POINTS / skip));
-
- if (dCurve && !dCurve->isIdentity()) {
- clcutili = true;
- }
- }
-
- fillCurveArray(dCurve.get(), clCurve, skip, clcutili);
-}
-
-void CurveFactory::mapcurve(bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram)
+bool CurveFactory::diagonalCurve2Lut(const std::vector& curvePoints, LUTf & curve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram)
{
bool needed = false;
std::unique_ptr dCurve;
outBeforeCurveHistogram.clear();
bool histNeeded = false;
- if (!mapcurvePoints.empty() && mapcurvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(mapcurvePoints, CURVES_MIN_POLY_POINTS / skip));
-
- if (outBeforeCurveHistogram) {
- histNeeded = true;
- }
-
- if (dCurve && !dCurve->isIdentity()) {
- needed = true;
- mapcontlutili = true;
- }
- }
-
- if (histNeeded) {
- histogram.compressTo(outBeforeCurveHistogram, 32768);
- }
-
- fillCurveArray(dCurve.get(), mapcurve, skip, needed);
-}
-
-void CurveFactory::curveDehaContL(bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram)
-{
- bool needed = false;
- std::unique_ptr dCurve;
- outBeforeCurveHistogram.clear();
- bool histNeeded = false;
-
- if (!dehaclcurvePoints.empty() && dehaclcurvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(dehaclcurvePoints, CURVES_MIN_POLY_POINTS / skip));
-
- if (outBeforeCurveHistogram) {
- histNeeded = true;
- }
-
- if (dCurve && !dCurve->isIdentity()) {
- needed = true;
- dehacontlutili = true;
- }
- }
-
- if (histNeeded) {
- histogram.compressTo(outBeforeCurveHistogram, 32768);
- }
-
- fillCurveArray(dCurve.get(), dehaclCurve, skip, needed);
-}
-
-// add curve Lab wavelet : Cont=f(L)
-void CurveFactory::curveWavContL(bool & wavcontlutili, const std::vector& wavclcurvePoints, LUTf & wavclCurve, /*LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip)
-{
- bool needed = false;
- std::unique_ptr dCurve;
-
- if (!wavclcurvePoints.empty() && wavclcurvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(wavclcurvePoints, CURVES_MIN_POLY_POINTS / skip));
-
- if (dCurve && !dCurve->isIdentity()) {
- needed = true;
- wavcontlutili = true;
- }
- }
-
- fillCurveArray(dCurve.get(), wavclCurve, skip, needed);
-}
-
-// add curve Colortoning : C=f(L) and CLf(L)
-void CurveFactory::curveToning(const std::vector& curvePoints, LUTf & ToningCurve, int skip)
-{
- bool needed = false;
- std::unique_ptr dCurve;
-
if (!curvePoints.empty() && curvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve.reset(new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
+
+ if (outBeforeCurveHistogram) {
+ histNeeded = true;
+ }
if (dCurve && !dCurve->isIdentity()) {
needed = true;
}
}
- fillCurveArray(dCurve.get(), ToningCurve, skip, needed);
+ if (histNeeded) {
+ histogram.compressTo(outBeforeCurveHistogram, 32768);
+ }
+
+ fillCurveArray(dCurve.get(), curve, skip, needed);
+ return needed;
}
-bool CurveFactory::curveLocal(const std::vector& curvePoints, LUTf& LocalCurve, int skip)
+bool CurveFactory::diagonalCurve2Lut(const std::vector& curvePoints, LUTf& curve, int skip)
{
bool needed = false;
std::unique_ptr dCurve;
@@ -453,217 +372,11 @@ bool CurveFactory::curveLocal(const std::vector& curvePoints, LUTf& Loca
}
}
- fillCurveArray(dCurve.get(), LocalCurve, skip, needed);
+ fillCurveArray(dCurve.get(), curve, skip, needed);
return needed;
}
-void CurveFactory::curveskLocal(bool & localskutili, const std::vector& curvePoints, LUTf & LocalskCurve, int skip)
-{
- bool needed = false;
- std::unique_ptr dCurve;
-
-// if (localskutili && !curvePoints.empty() && curvePoints[0] != 0) {
- if (!curvePoints.empty() && curvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
-
- if (dCurve && !dCurve->isIdentity()) {
- needed = true;
- localskutili = true;
- }
- }
-
- fillCurveArray(dCurve.get(), LocalskCurve, skip, needed);
-
-}
-
-void CurveFactory::localLCurve(double br, double contr, /*const std::vector& curvePoints,*/
- LUTu & histogram, LUTf & outCurve,
- int skip, bool & utili)
-{
-
- // curve without contrast
- LUTf dcurve(65536, 0);
-
- // clear array that stores histogram valid before applying the custom curve
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- // tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- // check if brightness curve is needed
- if (br > 0.00001 || br < -0.00001) {
- utili = true;
-
- std::vector brightcurvePoints;
- brightcurvePoints.resize(9);
- brightcurvePoints.at(0) = double (DCT_NURBS);
-
- brightcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
- brightcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
-
- if (br > 0) {
- brightcurvePoints.at(3) = 0.1; // toe point
- brightcurvePoints.at(4) = 0.1 + br / 150.0; //value at toe point
-
- brightcurvePoints.at(5) = 0.7; // shoulder point
- brightcurvePoints.at(6) = min(1.0, 0.7 + br / 300.0); //value at shoulder point
- } else {
- brightcurvePoints.at(3) = 0.1 - br / 150.0; // toe point
- brightcurvePoints.at(4) = 0.1; // value at toe point
-
- brightcurvePoints.at(5) = min(1.0, 0.7 - br / 300.0); // shoulder point
- brightcurvePoints.at(6) = 0.7; // value at shoulder point
- }
-
- brightcurvePoints.at(7) = 1.; // white point
- brightcurvePoints.at(8) = 1.; // value at white point
-
- DiagonalCurve* brightcurve = new DiagonalCurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- // Applying brightness curve
- for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
-
- // change to [0,1] range
- float val = (float)i / 32767.0;
-
- // apply brightness curve
- val = brightcurve->getVal(val);
-
- // store result in a temporary array
- dcurve[i] = val;
- }
-
- delete brightcurve;
- } else {
- for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
- // set the identity curve in the temporary array
- dcurve[i] = (float)i / 32767.0;
- }
- }
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- // check if contrast curve is needed
- if (contr > 0.00001 || contr < -0.00001) {
- utili = true;
-
- DiagonalCurve* contrastcurve = NULL;
-
- // compute mean luminance of the image with the curve applied
- int sum = 0;
- float avg = 0;
-
- //float sqavg = 0;
- for (int i = 0; i < 32768; i++) {
- avg += dcurve[i] * histogram[i];
- //sqavg += dcurve[i]*dcurve[i] * histogram[i];
- sum += histogram[i];
- }
-
- if (sum) {
- avg /= sum;
- //sqavg /= sum;
- //float stddev = sqrt(sqavg-avg*avg);
- // printf("avg=%f\n",avg);
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- std::vector contrastcurvePoints;
- contrastcurvePoints.resize(9);
- contrastcurvePoints.at(0) = double (DCT_NURBS);
-
- contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
-
- contrastcurvePoints.at(3) = avg - avg * (0.6 - contr / 250.0); // toe point
- contrastcurvePoints.at(4) = avg - avg * (0.6 + contr / 250.0); // value at toe point
-
- contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - contr / 250.0); // shoulder point
- contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + contr / 250.0); // value at shoulder point
-
- contrastcurvePoints.at(7) = 1.; // white point
- contrastcurvePoints.at(8) = 1.; // value at white point
-
- contrastcurve = new DiagonalCurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- } else {
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- // sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image
- std::vector contrastcurvePoints;
- contrastcurvePoints.resize(5);
- contrastcurvePoints.at(0) = double (DCT_NURBS);
-
- contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(2) = 1.; // black point. Value in [0 ; 1] range
-
- contrastcurvePoints.at(3) = 1.; // white point
- contrastcurvePoints.at(4) = 1.; // value at white point
-
- contrastcurve = new DiagonalCurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- }
-
- // apply contrast enhancement
- for (int i = 0; i < 32768; i++) {
- dcurve[i] = contrastcurve->getVal(dcurve[i]);
- }
-
- delete contrastcurve;
- }
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- // create a curve if needed
- /* DiagonalCurve* tcurve = NULL;
- bool histNeeded = false;
- if (!curvePoints.empty() && curvePoints[0]!=0) {
- tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS/skip);
- }
- if (tcurve && tcurve->isIdentity()) {
- delete tcurve;
- tcurve = NULL;
- }
-
- if (tcurve) {
- utili=true;//if active
-
- // L values go up to 32767, last stop is for highlight overflow
- for (int i=0; i<32768; i++) {
- float val;
- // apply custom/parametric/NURBS curve, if any
- val = tcurve->getVal (dcurve[i]);
-
- outCurve[i] = (32767.0 * val);
- }
- }
- else
- */
- {
- // Skip the slow getval method if no curve is used (or an identity curve)
- // L values go up to 32767, last stop is for highlight overflow
- for (int i = 0; i < 32768; i++) {
- outCurve[i] = 32767.0 * dcurve[i];
- }
- }
-
- for (int i = 32768; i < 65536; i++) {
- outCurve[i] = (float)i;
- }
-
- // if (tcurve)
- // delete tcurve;
-
-}
-
-
-
-
-
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void CurveFactory::complexsgnCurve(bool & autili, bool & butili, bool & ccutili, bool & cclutili,
const std::vector& acurvePoints, const std::vector& bcurvePoints, const std::vector& cccurvePoints,
const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve,
@@ -675,7 +388,7 @@ void CurveFactory::complexsgnCurve(bool & autili, bool & butili, bool & ccutili
// create a curve if needed
if (!acurvePoints.empty() && acurvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(acurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve.reset(new DiagonalCurve(acurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
autili = true;
@@ -684,12 +397,12 @@ void CurveFactory::complexsgnCurve(bool & autili, bool & butili, bool & ccutili
fillCurveArray(dCurve.get(), aoutCurve, skip, autili);
- dCurve = nullptr;
+ dCurve.reset();
//-----------------------------------------------------
if (!bcurvePoints.empty() && bcurvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(bcurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve.reset(new DiagonalCurve(bcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
butili = true;
@@ -698,12 +411,12 @@ void CurveFactory::complexsgnCurve(bool & autili, bool & butili, bool & ccutili
fillCurveArray(dCurve.get(), boutCurve, skip, butili);
- dCurve = nullptr;
+ dCurve.reset();
//-----------------------------------------------
if (!cccurvePoints.empty() && cccurvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(cccurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve.reset(new DiagonalCurve(cccurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
ccutili = true;
@@ -712,12 +425,12 @@ void CurveFactory::complexsgnCurve(bool & autili, bool & butili, bool & ccutili
fillCurveArray(dCurve.get(), satCurve, skip, ccutili);
- dCurve = nullptr;
+ dCurve.reset();
//----------------------------
if (!lccurvePoints.empty() && lccurvePoints[0] != 0) {
- dCurve = std::unique_ptr (new DiagonalCurve(lccurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ dCurve.reset(new DiagonalCurve(lccurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
cclutili = true;
@@ -755,9 +468,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
// clear array that stores histogram valid before applying the custom curve
outBeforeCCurveHistogram.clear();
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
std::unique_ptr brightcurve;
@@ -787,11 +498,9 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
brightcurvePoints[7] = 1.; // white point
brightcurvePoints[8] = 1.; // value at white point
- brightcurve = std::unique_ptr (new DiagonalCurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip));
+ brightcurve.reset(new DiagonalCurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip));
}
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
hlCurve.setClip(LUT_CLIP_BELOW); // used LUT_CLIP_BELOW, because we want to have a baseline of 2^expcomp in this curve. If we don't clip the lut we get wrong values, see Issue 2621 #14 for details
float exp_scale = a;
float scale = 65536.0;
@@ -849,7 +558,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
// curve without contrast
LUTf dcurve(0x10000);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%
// change to [0,1] range
shCurve.setClip(LUT_CLIP_ABOVE); // used LUT_CLIP_ABOVE, because the curve converges to 1.0 at the upper end and we don't want to exceed this value.
if (black == 0.0) {
@@ -889,11 +597,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
dcurve[i] = val;
}
- brightcurve = nullptr;
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ brightcurve.reset();
// check if contrast curve is needed
if (contr > 0.00001 || contr < -0.00001) {
@@ -910,7 +614,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
avg /= sum;
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
std::vector contrastcurvePoints(9);
contrastcurvePoints[0] = DCT_NURBS;
@@ -928,15 +631,12 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
const DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// apply contrast enhancement
for (int i = 0; i <= 0xffff; i++) {
dcurve[i] = contrastcurve.getVal(dcurve[i]);
}
}
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
// create second curve if needed
bool histNeeded = false;
customToneCurve2.Reset();
@@ -953,10 +653,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
}
}
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
// create first curve if needed
customToneCurve1.Reset();
@@ -972,8 +668,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
}
}
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
#ifdef __SSE2__
vfloat gamma_v = F2V(gamma_);
vfloat startv = F2V(start);
@@ -1076,8 +770,6 @@ void CurveFactory::Curvelocalhl(double ecomp, double hlcompr, double hlcomprthre
}
}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr, double hlcomprthresh,
double shcompr, double br, double cont, double lumare,
LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, LUTf & lightCurveloc, float avg,
@@ -1091,8 +783,6 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
const float add = 0.0954f;
float maxran = 65536.f; //65536
-// ecomp /= 100.;
-
// check if brightness curve is needed
if (br > 0.00001 || br < -0.00001) {
// utili = true;
@@ -1124,7 +814,6 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
brightcurvePoints.at(8) = 1.; // value at white point
DiagonalCurve brightcurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Applying brightness curve
for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
@@ -1138,9 +827,6 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
// store result in a temporary array
lightCurveloc[i] = val;
}
-
-
-
} else {
lightCurveloc.makeIdentity(32767.f);
}
@@ -1151,42 +837,21 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
int k = avg * 32768;
avg = lightCurveloc[k];
- // printf("avg=%f lumaref=%f\n", avg, lumare/100.f);
std::vector contrastcurvePoints;
- bool lumm = true;
+ contrastcurvePoints.resize(9);
+ contrastcurvePoints.at(0) = double (DCT_NURBS);
- if (lumm) {
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- contrastcurvePoints.resize(9);
- contrastcurvePoints.at(0) = double (DCT_NURBS);
+ contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
+ contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
+ contrastcurvePoints.at(3) = avg - avg * (0.6 - cont / 250.0); // toe point
+ contrastcurvePoints.at(4) = avg - avg * (0.6 + cont / 250.0); // value at toe point
- contrastcurvePoints.at(3) = avg - avg * (0.6 - cont / 250.0); // toe point
- contrastcurvePoints.at(4) = avg - avg * (0.6 + cont / 250.0); // value at toe point
+ contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - cont / 250.0); // shoulder point
+ contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + cont / 250.0); // value at shoulder point
- contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - cont / 250.0); // shoulder point
- contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + cont / 250.0); // value at shoulder point
-
- contrastcurvePoints.at(7) = 1.; // white point
- contrastcurvePoints.at(8) = 1.; // value at white point
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- } else {
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- // sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image
- contrastcurvePoints.resize(5);
- contrastcurvePoints.at(0) = double (DCT_NURBS);
-
- contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
- contrastcurvePoints.at(2) = 1.; // black point. Value in [0 ; 1] range
-
- contrastcurvePoints.at(3) = 1.; // white point
- contrastcurvePoints.at(4) = 1.; // value at white point
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- }
+ contrastcurvePoints.at(7) = 1.; // white point
+ contrastcurvePoints.at(8) = 1.; // value at white point
DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
@@ -1203,19 +868,12 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
lightCurveloc[i] = (float)i;
}
-
// a: slope of the curve, black: starting point at the x axis
const float a = powf(2.0f, ecomp);
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
hlCurve.setClip(LUT_CLIP_BELOW); // used LUT_CLIP_BELOW, because we want to have a baseline of 2^expcomp in this curve. If we don't clip the lut we get wrong values, see Issue 2621 #14 for details
float exp_scale = a;
-// float scale = 65536.0;
float scale = maxran;
float comp = (max(0.0, ecomp) + 1.0) * hlcompr / 100.0;
float shoulder = ((scale / max(1.0f, exp_scale)) * (hlcomprthresh / 200.0)) + 0.1;
@@ -1269,11 +927,9 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
}
-
// curve without contrast
LUTf dcurve(maxran);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%
// change to [0,1] range
shCurve.setClip(LUT_CLIP_ABOVE); // used LUT_CLIP_ABOVE, because the curve converges to 1.0 at the upper end and we don't want to exceed this value.
if (black == 0.0) {
@@ -1282,32 +938,22 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
const float val = 1.f / (maxran - 1.f);
shCurve[0] = simplebasecurve(val, black, 0.015 * shcompr) / val;
}
-
-
-
- // gamma correction
+ // gamma correction
float val = Color::gammatab_bt709[0] / maxran;
// store result in a temporary array
dcurve[0] = LIM01(val);
for (int i = 1; i < maxran; i++) {
- float val = i / (maxran - 1.f);
-
-// float val2 = simplebasecurve(val, black, 0.015 * shcompr);
-// shCurve[i] = val2 / val;
if (black != 0.0) {
- const float val = i / 65535.f;
- shCurve[i] = simplebasecurve(val, black, 0.015 * shcompr) / val;
+ const float bval = i / 65535.f;
+ shCurve[i] = simplebasecurve(bval, black, 0.015 * shcompr) / bval;
}
// gamma correction
- val = Color::gammatab_bt709[i] / maxran;
- // store result in a temporary array
- dcurve[i] = val;
+ dcurve[i] = Color::gammatab_bt709[i] / maxran;
}
-
#ifdef __SSE2__
vfloat gamma_v = F2V(gamma_);
vfloat startv = F2V(start);
@@ -1322,23 +968,13 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
valv = igamma(valv, gamma_v, startv, slopev, mulv, addv);
STVFU(outCurve[i], c65535v * valv);
}
-
#else
-
for (int i = 0; i <= (maxran - 1.f); i++) {
- float val = dcurve[i];
- val = igamma(val, gamma_, start, slope, mul, add);
- outCurve[i] = ((maxran - 1.) * val);
+ outCurve[i] = (maxran - 1.f) * igamma(dcurve[i], gamma_, start, slope, mul, add);
}
-
#endif
-
}
-
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
void CurveFactory::complexLCurve(double br, double contr, const std::vector& curvePoints,
const LUTu & histogram, LUTf & outCurve,
LUTu & outBeforeCCurveHistogram, int skip, bool & utili)
@@ -1351,9 +987,7 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector1), hr,sr: highlight,shadow recovery
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// check if brightness curve is needed
if (br > 0.00001 || br < -0.00001) {
@@ -1384,7 +1018,6 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector 0.00001 || contr < -0.00001) {
utili = true;
@@ -1425,7 +1054,6 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector tcurve;
bool histNeeded = false;
if (!curvePoints.empty() && curvePoints[0] != 0) {
- tcurve = std::unique_ptr (new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
+ tcurve.reset(new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
if (outBeforeCCurveHistogram) {
histNeeded = true;
}
}
- if (tcurve && tcurve->isIdentity()) {
- tcurve = nullptr;
- }
-
- if (tcurve) {
+ if (tcurve && !tcurve->isIdentity()) {
utili = true; //if active
// L values go up to 32767, last stop is for highlight overflow
@@ -1500,7 +1117,7 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vectorgetVal(outCurve[i]);
- outCurve[i] = (32767.f * val);
+ outCurve[i] = 32767.f * val;
}
} else {
@@ -1515,15 +1132,11 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector& curvePoints, LUTf & outCurve, int skip)
{
@@ -1531,14 +1144,10 @@ void CurveFactory::RGBCurve(const std::vector& curvePoints, LUTf & outCu
std::unique_ptr tcurve;
if (!curvePoints.empty() && curvePoints[0] != 0) {
- tcurve = std::unique_ptr (new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
+ tcurve.reset(new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
}
- if (tcurve && tcurve->isIdentity()) {
- tcurve = nullptr;
- }
-
- if (tcurve) {
+ if (tcurve && !tcurve->isIdentity()) {
if (!outCurve) {
outCurve(65536, 0);
}
@@ -1555,7 +1164,6 @@ void CurveFactory::RGBCurve(const std::vector& curvePoints, LUTf & outCu
}
}
-
LocretigainCurverab::LocretigainCurverab() : sum(0.f) {};
void LocretigainCurverab::Reset()
@@ -2698,6 +2306,56 @@ bool LocLHCurve::Set(const std::vector &curvePoints)
}
}
+LocCHCurve::LocCHCurve() : sum(0.f) {};
+
+void LocCHCurve::Reset()
+{
+ lutLocCHCurve.reset();
+ sum = 0.f;
+}
+void LocCHCurve::Set(const Curve &pCurve)
+{
+ if (pCurve.isIdentity()) {
+ Reset(); // raise this value if the quality suffers from this number of samples
+ return;
+ }
+
+ lutLocCHCurve(501); // raise this value if the quality suffers from this number of samples
+ sum = 0.f;
+
+ for (int i = 0; i < 501; i++) {
+ lutLocCHCurve[i] = pCurve.getVal(double (i) / 500.);
+
+ if (lutLocCHCurve[i] < 0.02f) {
+ lutLocCHCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value
+ }
+
+ sum += lutLocCHCurve[i];
+ }
+
+ //lutLocHHCurve.dump("wav");
+}
+
+
+
+bool LocCHCurve::Set(const std::vector &curvePoints)
+{
+ // if (HHutili && !curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
+ if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
+ FlatCurve ttcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2);
+ ttcurve.setIdentityValue(0.);
+ Set(ttcurve);
+ return true;
+ } else {
+ Reset();
+ return false;
+ }
+}
+
+
+
+
+
LocwavCurve::LocwavCurve() : sum(0.f) {};
void LocwavCurve::Reset()
@@ -2976,18 +2634,13 @@ void OpacityCurve::Set(const std::vector &curvePoints, bool &opautili)
std::unique_ptr tcurve;
if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
- tcurve = std::unique_ptr (new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
+ tcurve.reset(new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
tcurve->setIdentityValue(0.);
- }
-
- if (tcurve) {
Set(tcurve.get());
opautili = true;
- tcurve = nullptr;
}
}
-
WavCurve::WavCurve() : sum(0.f) {}
void WavCurve::Reset()
@@ -3414,10 +3067,7 @@ void ColorGradientCurve::SetXYZ(const std::vector &curvePoints, const do
std::unique_ptr tcurve;
if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
- tcurve = std::unique_ptr (new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
- }
-
- if (tcurve) {
+ tcurve.reset(new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
SetXYZ(tcurve.get(), xyz_rgb, satur, lumin);
}
}
@@ -3505,10 +3155,7 @@ void ColorGradientCurve::SetRGB(const std::vector &curvePoints)
std::unique_ptr tcurve;
if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) {
- tcurve = std::unique_ptr (new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
- }
-
- if (tcurve) {
+ tcurve.reset(new FlatCurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2));
SetRGB(tcurve.get());
}
}
diff --git a/rtengine/curves.h b/rtengine/curves.h
index 5769cada1..8800e54db 100644
--- a/rtengine/curves.h
+++ b/rtengine/curves.h
@@ -367,23 +367,13 @@ public:
static void curveBW(const std::vector& curvePointsbw, const std::vector& curvePointsbw2, const LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw,
ToneCurve & customToneCurvebw1, ToneCurve & customToneCurvebw2, int skip);
- static void curveCL(bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, int skip);
-
- static void curveWavContL(bool & wavcontlutili, const std::vector& wavclcurvePoints, LUTf & wavclCurve,/* LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip);
- static void curveDehaContL(bool & dehacontlutili, const std::vector& dehaclcurvePoints, LUTf & dehaclCurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram);
- static void mapcurve(bool & mapcontlutili, const std::vector& mapcurvePoints, LUTf & mapcurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram);
-
- static void curveToning(const std::vector& curvePoints, LUTf & ToningCurve, int skip);
-
- static bool curveLocal(const std::vector& curvePoints, LUTf& LocalCurve, int skip);
- static void curveskLocal(bool & localskutili, const std::vector& curvePoints, LUTf & LocalskCurve, int skip);
+ static bool diagonalCurve2Lut(const std::vector& curvePoints, LUTf& curve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram);
+ static bool diagonalCurve2Lut(const std::vector& curvePoints, LUTf& curve, int skip);
static void complexsgnCurve(bool & autili, bool & butili, bool & ccutili, bool & clcutili, const std::vector& acurvePoints,
const std::vector& bcurvePoints, const std::vector& cccurvePoints, const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve,
int skip = 1);
- static void localLCurve(double br, double contr,/* const std::vector& curvePoints,*/ LUTu & histogram, LUTf & outCurve, int skip, bool & utili);
-
static void updatechroma(
const std::vector& cccurvePoints,
LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma
@@ -1283,6 +1273,35 @@ public:
}
};
+
+class LocCHCurve
+{
+private:
+ LUTf lutLocCHCurve; // 0xffff range
+ void Set(const Curve &pCurve);
+
+public:
+ float sum;
+
+ virtual ~LocCHCurve() {};
+ LocCHCurve();
+ void Reset();
+ bool Set(const std::vector &curvePoints);
+ float getSum() const
+ {
+ return sum;
+ }
+
+ float operator[](float index) const
+ {
+ return lutLocCHCurve[index];
+ }
+ operator bool (void) const
+ {
+ return lutLocCHCurve;
+ }
+};
+
class LocretigainCurve
{
private:
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index ce7714e21..c89d2bdb0 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -881,6 +881,7 @@ void Crop::update(int todo)
auto& locRETtransCurve = parent->locRETtransCurve;
auto& loclhCurve = parent->loclhCurve;
auto& lochhCurve = parent->lochhCurve;
+ auto& locchCurve = parent->locchCurve;
auto& locccmasCurve = parent->locccmasCurve;
auto& locllmasCurve = parent->locllmasCurve;
auto& lochhmasCurve = parent->lochhmasCurve;
@@ -930,6 +931,7 @@ void Crop::update(int todo)
locRETtransCurve.Set(params.locallab.spots.at(sp).localTtranscurve);
const bool LHutili = loclhCurve.Set(params.locallab.spots.at(sp).LHcurve);
const bool HHutili = lochhCurve.Set(params.locallab.spots.at(sp).HHcurve);
+ const bool CHutili = locchCurve.Set(params.locallab.spots.at(sp).CHcurve);
const bool lcmasutili = locccmasCurve.Set(params.locallab.spots.at(sp).CCmaskcurve);
const bool llmasutili = locllmasCurve.Set(params.locallab.spots.at(sp).LLmaskcurve);
const bool lhmasutili = lochhmasCurve.Set(params.locallab.spots.at(sp).HHmaskcurve);
@@ -972,22 +974,22 @@ void Crop::update(int todo)
const bool loccompwavutili = loccompwavCurve.Set(params.locallab.spots.at(sp).loccompwavcurve);
const bool loccomprewavutili = loccomprewavCurve.Set(params.locallab.spots.at(sp).loccomprewavcurve);
const bool locedgwavutili = locedgwavCurve.Set(params.locallab.spots.at(sp).locedgwavcurve);
- const bool locallutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).llcurve, lllocalcurve2, skip);
- const bool localclutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).clcurve, cllocalcurve2, skip);
- const bool locallcutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).lccurve, lclocalcurve2, skip);
- const bool localrgbutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).rgbcurve, rgblocalcurve2, skip);
- const bool localcutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).cccurve, cclocalcurve2, skip);
- const bool localexutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).excurve, exlocalcurve2, skip);
- const bool localmaskutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve2, skip);
- const bool localmaskexputili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve2, skip);
- const bool localmaskSHutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve2, skip);
- const bool localmaskvibutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve2, skip);
- const bool localmasktmutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve2, skip);
- const bool localmaskretiutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve2, skip);
- const bool localmaskcbutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve2, skip);
- const bool localmasklcutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve2, skip);
- const bool localmaskblutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve2, skip);
- const bool localmask_utili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmask_curve, lmasklocal_curve2, skip);
+ const bool locallutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).llcurve, lllocalcurve2, skip);
+ const bool localclutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).clcurve, cllocalcurve2, skip);
+ const bool locallcutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).lccurve, lclocalcurve2, skip);
+ const bool localrgbutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).rgbcurve, rgblocalcurve2, skip);
+ const bool localcutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).cccurve, cclocalcurve2, skip);
+ const bool localexutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).excurve, exlocalcurve2, skip);
+ const bool localmaskutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve2, skip);
+ const bool localmaskexputili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve2, skip);
+ const bool localmaskSHutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve2, skip);
+ const bool localmaskvibutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve2, skip);
+ const bool localmasktmutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve2, skip);
+ const bool localmaskretiutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve2, skip);
+ const bool localmaskcbutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve2, skip);
+ const bool localmasklcutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve2, skip);
+ const bool localmaskblutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve2, skip);
+ const bool localmask_utili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmask_curve, lmasklocal_curve2, skip);
double ecomp = params.locallab.spots.at(sp).expcomp;
double black = params.locallab.spots.at(sp).black;
@@ -1028,7 +1030,7 @@ void Crop::update(int todo)
lllocalcurve2,locallutili,
cllocalcurve2, localclutili,
lclocalcurve2, locallcutili,
- loclhCurve, lochhCurve,
+ loclhCurve, lochhCurve, locchCurve,
lmasklocalcurve2, localmaskutili,
lmaskexplocalcurve2, localmaskexputili,
lmaskSHlocalcurve2, localmaskSHutili,
@@ -1060,7 +1062,7 @@ void Crop::update(int todo)
locwavCurveden, locwavdenutili,
locedgwavCurve, locedgwavutili,
loclmasCurve_wav,lmasutili_wav,
- LHutili, HHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
+ LHutili, HHutili, CHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav,
parent->previewDeltaE, parent->locallColorMask, parent->locallColorMaskinv, parent->locallExpMask, parent->locallExpMaskinv, parent->locallSHMask, parent->locallSHMaskinv, parent->locallvibMask, parent->localllcMask, parent->locallsharMask, parent->locallcbMask, parent->locallretiMask, parent->locallsoftMask, parent->localltmMask, parent->locallblMask,
parent->locall_Mask, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
@@ -1069,7 +1071,7 @@ void Crop::update(int todo)
lllocalcurve2,locallutili,
cllocalcurve2, localclutili,
lclocalcurve2, locallcutili,
- loclhCurve, lochhCurve,
+ loclhCurve, lochhCurve, locchCurve,
lmasklocalcurve2, localmaskutili,
lmaskexplocalcurve2, localmaskexputili,
lmaskSHlocalcurve2, localmaskSHutili,
@@ -1102,7 +1104,7 @@ void Crop::update(int todo)
locwavCurveden, locwavdenutili,
locedgwavCurve, locedgwavutili,
loclmasCurve_wav,lmasutili_wav,
- LHutili, HHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
+ LHutili, HHutili, CHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
}
@@ -1278,7 +1280,7 @@ void Crop::update(int todo)
WaveParams.expnoise = false;
}
- parent->ipf.softLight(labnCrop, params.softlight);
+
// parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
@@ -1407,6 +1409,8 @@ void Crop::update(int todo)
}
+
+ parent->ipf.softLight(labnCrop, params.softlight);
if (params.colorappearance.enabled) {
float fnum = parent->imgsrc->getMetaData()->getFNumber(); // F number
diff --git a/rtengine/dirpyr_equalizer.cc b/rtengine/dirpyr_equalizer.cc
index 871c21ac4..92a5ae7ee 100644
--- a/rtengine/dirpyr_equalizer.cc
+++ b/rtengine/dirpyr_equalizer.cc
@@ -29,7 +29,6 @@
#include "improcfun.h"
#include "LUT.h"
#include "opthelper.h"
-#include "boxblur.h"
#include "rt_math.h"
#include "settings.h"
@@ -247,46 +246,20 @@ void fillLut(LUTf &irangefn, int level, double dirpyrThreshold, float mult, floa
}
}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void idirpyr_eq_channel_loc(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult, const float blurcb, const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev, bool multiThread)
+void idirpyr_eq_channel_loc(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult, const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev, bool multiThread)
{
LUTf irangefn(0x20000);
fillLut(irangefn, level, dirpyrThreshold, mult, skinprot);
#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16)
+ #pragma omp parallel for schedule(dynamic,16)
#endif
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++) {
-
- float hipass = (data_fine[i][j] - data_coarse[i][j]);
- buffer[i][j] += irangefn[hipass + 0x10000] * hipass;
-
- }
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ const float hipass = data_fine[i][j] - data_coarse[i][j];
+ buffer[i][j] += irangefn[hipass + 0x10000] * hipass;
}
-
- if(blurcb > 0.f && choice == 0 && level != 5) {
- float multbis;
- if (level == 4 && mult > 1.f) {
- multbis = 1.f + 0.65f * (mult - 1.f);
- } else if (level == 5 && mult > 1.f) {
- multbis = 1.f + 0.45f * (mult - 1.f);
- } else {
- multbis = mult; //multbis to reduce artifacts for high values mult
- }
- AlignedBuffer blurbufcbdl(width * height);
- float rad = 0.05f * blurcb * fabs((level + 1) * (multbis - 1.f)) / scaleprev;
- // printf("rad=%f level=%i\n", rad, level);
-
-#ifdef _OPENMP
- #pragma omp parallel if (multiThread)
-#endif
-// rtengine::boxblur(buffer, buffer, blurbufcbdl.data, rad, rad, width, height);
- rtengine::boxblur(buffer, buffer, rad, width, height, false);
- blurbufcbdl.resize(0);
- }
-
- irangefn.clear();
+ }
}
void idirpyr_eq_channel(const float * const * data_coarse, const float * const * data_fine, float ** buffer, int width, int height, int level, float mult, const double dirpyrThreshold, const float * const * hue, const float * const * chrom, const double skinprot, float b_l, float t_l, float t_r)
@@ -552,7 +525,7 @@ void ImProcFunctions::dirpyr_equalizercam(const CieImage *ncie, float ** src, fl
}
}
-void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwidth, int srcheight, const float * mult, float kchro, const double dirpyrThreshold, const float mergeL, const float contres, const float blurcb, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev, bool multiThread)
+void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwidth, int srcheight, const float * mult, float kchro, const double dirpyrThreshold, const float mergeL, const float contres, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev, bool multiThread)
{
constexpr int maxlevelloc = 6;
constexpr int scalesloc[maxlevelloc] = {1, 2, 4, 8, 16, 32};
@@ -663,13 +636,12 @@ void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwid
for (int level = lastlevel - 1; level > 0; level--) {
- idirpyr_eq_channel_loc(dirpyrlo[level], dirpyrlo[level - 1], residbuff, srcwidth, srcheight, level, multi[level], blurcb, dirpyrThreshold, nullptr, nullptr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice, scaleprev, multiThread);
+ idirpyr_eq_channel_loc(dirpyrlo[level], dirpyrlo[level - 1], residbuff, srcwidth, srcheight, level, multi[level], dirpyrThreshold, nullptr, nullptr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice, scaleprev, multiThread);
}
scale = scalesloc[0];
- idirpyr_eq_channel_loc(dirpyrlo[0], src, residbuff, srcwidth, srcheight, 0, multi[0], blurcb, dirpyrThreshold, nullptr, nullptr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice, scaleprev, multiThread);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ idirpyr_eq_channel_loc(dirpyrlo[0], src, residbuff, srcwidth, srcheight, 0, multi[0], dirpyrThreshold, nullptr, nullptr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice, scaleprev, multiThread);
array2D loct(srcwidth, srcheight);
#ifdef _OPENMP
diff --git a/rtengine/fast_demo.cc b/rtengine/fast_demo.cc
index 772096b87..ca8fb4cc4 100644
--- a/rtengine/fast_demo.cc
+++ b/rtengine/fast_demo.cc
@@ -281,7 +281,6 @@ void RawImageSource::fast_demosaic()
int right = min(left + TS, W - bord + 2);
#ifdef __SSE2__
- int j, cc;
__m128 wtuv, wtdv, wtlv, wtrv;
__m128 greenv, tempv, absv, abs2v;
__m128 c16v = _mm_set1_ps( 16.0f );
@@ -302,7 +301,7 @@ void RawImageSource::fast_demosaic()
float wtu, wtd, wtl, wtr;
#ifdef __SSE2__
selmask = (vmask)_mm_andnot_ps( (__m128)selmask, (__m128)andmask);
-
+ int j, cc;
for (j = left, cc = 0; j < right - 3; j += 4, cc += 4) {
tempv = LVFU(rawData[i][j]);
absv = vabsf(LVFU(rawData[i - 1][j]) - LVFU(rawData[i + 1][j]));
@@ -421,16 +420,12 @@ void RawImageSource::fast_demosaic()
temp1v = LVFU(redtile[rr * TS + cc]);
temp2v = greenv - zd25v * (greensumv - LVFU(redtile[(rr - 1) * TS + cc]) - LVFU(redtile[(rr + 1) * TS + cc]) - LVFU(redtile[rr * TS + cc - 1]) - LVFU(redtile[rr * TS + cc + 1]));
-// temp2v = greenv - zd25v*((LVFU(greentile[(rr-1)*TS+cc])-LVFU(redtile[(rr-1)*TS+cc]))+(LVFU(greentile[(rr+1)*TS+cc])-LVFU(redtile[(rr+1)*TS+cc]))+
-// (LVFU(greentile[rr*TS+cc-1])-LVFU(redtile[rr*TS+cc-1]))+(LVFU(greentile[rr*TS+cc+1])-LVFU(redtile[rr*TS+cc+1])));
_mm_storeu_ps( &redtile[rr * TS + cc], vself(selmask, temp1v, temp2v));
temp1v = LVFU(bluetile[rr * TS + cc]);
temp2v = greenv - zd25v * (greensumv - LVFU(bluetile[(rr - 1) * TS + cc]) - LVFU(bluetile[(rr + 1) * TS + cc]) - LVFU(bluetile[rr * TS + cc - 1]) - LVFU(bluetile[rr * TS + cc + 1]));
-// temp2v = greenv - zd25v*((LVFU(greentile[(rr-1)*TS+cc])-LVFU(bluetile[(rr-1)*TS+cc]))+(LVFU(greentile[(rr+1)*TS+cc])-LVFU(bluetile[(rr+1)*TS+cc]))+
-// (LVFU(greentile[rr*TS+cc-1])-LVFU(bluetile[rr*TS+cc-1]))+(LVFU(greentile[rr*TS+cc+1])-LVFU(bluetile[rr*TS+cc+1])));
_mm_storeu_ps( &bluetile[rr * TS + cc], vself(selmask, temp1v, temp2v));
}
@@ -450,7 +445,7 @@ void RawImageSource::fast_demosaic()
for (int i = top + 2, rr = 2; i < bottom - 2; i++, rr++) {
#ifdef __SSE2__
-
+ int j, cc;
for (j = left + 2, cc = 2; j < right - 5; j += 4, cc += 4) {
_mm_storeu_ps(&red[i][j], vmaxf(LVFU(redtile[rr * TS + cc]), ZEROV));
_mm_storeu_ps(&green[i][j], vmaxf(LVFU(greentile[rr * TS + cc]), ZEROV));
diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc
index b3f843bc1..3f5e00e05 100644
--- a/rtengine/guidedfilter.cc
+++ b/rtengine/guidedfilter.cc
@@ -82,8 +82,8 @@ int calculate_subsampling(int w, int h, int r)
void guidedFilter(const array2D &guide, const array2D &src, array2D &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 &guide, const array2D &src, array2
const auto apply =
[=](Op op, array2D &res, const array2D &a, const array2D &b, const array2D &c=array2D()) -> 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 &guide, const array2D &src, array2
const auto f_subsample =
[=](array2D &d, const array2D &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 &guide, const array2D &src, array2
const auto f_mean =
[multithread](array2D &d, array2D &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(s), static_cast(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(s), static_cast(d), rad, s.getWidth(), s.getHeight(), multithread);
};
array2D I1(w, h);
@@ -225,10 +225,10 @@ void guidedFilter(const array2D &guide, const array2D &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 &guide, float base, array2D &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 &guide, float base, array2D &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);
}
}
diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc
index 6b2be1713..f53ddc893 100644
--- a/rtengine/iccstore.cc
+++ b/rtengine/iccstore.cc
@@ -351,7 +351,7 @@ cmsHPROFILE rtengine::ProfileContent::toProfile() const
double slope = slopetag == 0 ? eps : slopetag;
GammaValues g_b; //gamma parameters
- Color::calcGamma(pwr, ts, 0, g_b); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
+ Color::calcGamma(pwr, ts, g_b); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
cmsFloat64Number gammaParams[7]; //gamma parameters
gammaParams[4] = g_b[3] * ts;
gammaParams[0] = gammatag;
diff --git a/rtengine/iimage.h b/rtengine/iimage.h
index cd8aa9a9e..663795238 100644
--- a/rtengine/iimage.h
+++ b/rtengine/iimage.h
@@ -1809,9 +1809,6 @@ public:
* @return The mutex */
virtual MyMutex& getMutex () = 0;
virtual cmsHPROFILE getProfile () const = 0;
- /** @brief Returns the bits per pixel of the image.
- * @return The bits per pixel of the image */
- virtual int getBitsPerPixel () const = 0;
/** @brief Saves the image to file. It autodetects the format (jpg, tif, png are supported).
* @param fname is the name of the file
@return the error code, 0 if none */
@@ -1836,8 +1833,6 @@ public:
/** @brief Sets the progress listener if you want to follow the progress of the image saving operations (optional).
* @param pl is the pointer to the class implementing the ProgressListener interface */
virtual void setSaveProgressListener (ProgressListener* pl) = 0;
- /** @brief Free the image */
- virtual void free () = 0;
};
/** @brief This class represents an image having a float pixel planar representation.
diff --git a/rtengine/image16.cc b/rtengine/image16.cc
index 07fc66fad..1a9130b5d 100644
--- a/rtengine/image16.cc
+++ b/rtengine/image16.cc
@@ -258,10 +258,10 @@ void Image16::getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, P
lineB[dst_x] = CLIP(bm * btot);
} else {
// computing a special factor for this incomplete sub-region
- float area = src_sub_width * src_sub_height;
- lineR[dst_x] = CLIP(rm2 * rtot / area);
- lineG[dst_x] = CLIP(gm2 * gtot / area);
- lineB[dst_x] = CLIP(bm2 * btot / area);
+ float larea = src_sub_width * src_sub_height;
+ lineR[dst_x] = CLIP(rm2 * rtot / larea);
+ lineG[dst_x] = CLIP(gm2 * gtot / larea);
+ lineB[dst_x] = CLIP(bm2 * btot / larea);
}
}
}
@@ -295,21 +295,6 @@ void Image16::getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, P
#undef GCLIP
}
-Image8* Image16::to8() const
-{
- Image8* img8 = new Image8(width, height);
-
- for (int h = 0; h < height; ++h) {
- for (int w = 0; w < width; ++w) {
- img8->r(h, w) = uint16ToUint8Rounded(r(h, w));
- img8->g(h, w) = uint16ToUint8Rounded(g(h, w));
- img8->b(h, w) = uint16ToUint8Rounded(b(h, w));
- }
- }
-
- return img8;
-}
-
// Parallelized transformation; create transform with cmsFLAGS_NOCACHE!
void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform)
{
diff --git a/rtengine/image16.h b/rtengine/image16.h
index de9288f2d..de9718708 100644
--- a/rtengine/image16.h
+++ b/rtengine/image16.h
@@ -40,8 +40,6 @@ public:
Image16* copy() const;
- Image8* to8() const;
-
void getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const override;
const char* getType() const override
@@ -67,11 +65,6 @@ public:
return getEmbeddedProfile();
}
- int getBitsPerPixel() const override
- {
- return 8 * sizeof(unsigned short);
- }
-
int saveToFile(const Glib::ustring &fname) const override
{
return save(fname);
@@ -97,10 +90,6 @@ public:
setProgressListener(pl);
}
- void free() override
- {
- delete this;
- }
void ExecCMSTransform(cmsHTRANSFORM hTransform);
/* void ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy); */
diff --git a/rtengine/image8.h b/rtengine/image8.h
index c11d9d7fc..dd3be5d9b 100644
--- a/rtengine/image8.h
+++ b/rtengine/image8.h
@@ -64,11 +64,6 @@ public:
return getEmbeddedProfile ();
}
- int getBitsPerPixel () const override
- {
- return 8 * sizeof(unsigned char);
- }
-
int saveToFile (const Glib::ustring &fname) const override
{
return save (fname);
@@ -94,11 +89,6 @@ public:
setProgressListener (pl);
}
- void free () override
- {
- delete this;
- }
-
};
}
diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc
index f905134a0..d9ac841eb 100644
--- a/rtengine/imagefloat.cc
+++ b/rtengine/imagefloat.cc
@@ -288,10 +288,10 @@ void Imagefloat::getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* imag
lineB[dst_x] = CLIP0(bm * btot);
} else {
// computing a special factor for this incomplete sub-region
- float area = src_sub_width * src_sub_height;
- lineR[dst_x] = CLIP0(rm2 * rtot / area);
- lineG[dst_x] = CLIP0(gm2 * gtot / area);
- lineB[dst_x] = CLIP0(bm2 * btot / area);
+ float larea = src_sub_width * src_sub_height;
+ lineR[dst_x] = CLIP0(rm2 * rtot / larea);
+ lineG[dst_x] = CLIP0(gm2 * gtot / larea);
+ lineB[dst_x] = CLIP0(bm2 * btot / larea);
}
}
}
@@ -327,53 +327,15 @@ void Imagefloat::getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* imag
#endif
}
-Image8*
-Imagefloat::to8() const
-{
- Image8* img8 = new Image8(width, height);
-#ifdef _OPENMP
- #pragma omp parallel for schedule(static)
-#endif
-
- for (int h = 0; h < height; ++h) {
- for (int w = 0; w < width; ++w) {
- img8->r(h, w) = uint16ToUint8Rounded(CLIP(r(h, w)));
- img8->g(h, w) = uint16ToUint8Rounded(CLIP(g(h, w)));
- img8->b(h, w) = uint16ToUint8Rounded(CLIP(b(h, w)));
- }
- }
-
- return img8;
-}
-
-Image16*
-Imagefloat::to16() const
-{
- Image16* img16 = new Image16(width, height);
-#ifdef _OPENMP
- #pragma omp parallel for schedule(static)
-#endif
-
- for (int h = 0; h < height; ++h) {
- for (int w = 0; w < width; ++w) {
- img16->r(h, w) = CLIP(r(h, w));
- img16->g(h, w) = CLIP(g(h, w));
- img16->b(h, w) = CLIP(b(h, w));
- }
- }
-
- return img16;
-}
-
void Imagefloat::normalizeFloat(float srcMinVal, float srcMaxVal)
{
- float scale = MAXVALF / (srcMaxVal - srcMinVal);
- int w = width;
- int h = height;
+ const float scale = MAXVALF / (srcMaxVal - srcMinVal);
+ const int w = width;
+ const int h = height;
#ifdef _OPENMP
- #pragma omp parallel for firstprivate(w, h, srcMinVal, scale) schedule(dynamic, 5)
+ #pragma omp parallel for schedule(dynamic, 5)
#endif
for (int y = 0; y < h; y++) {
@@ -389,11 +351,11 @@ void Imagefloat::normalizeFloat(float srcMinVal, float srcMaxVal)
void Imagefloat::normalizeFloatTo1()
{
- int w = width;
- int h = height;
+ const int w = width;
+ const int h = height;
#ifdef _OPENMP
- #pragma omp parallel for firstprivate(w, h) schedule(dynamic, 5)
+ #pragma omp parallel for schedule(dynamic, 5)
#endif
for (int y = 0; y < h; y++) {
@@ -409,11 +371,11 @@ void Imagefloat::normalizeFloatTo1()
void Imagefloat::normalizeFloatTo65535()
{
- int w = width;
- int h = height;
+ const int w = width;
+ const int h = height;
#ifdef _OPENMP
- #pragma omp parallel for firstprivate(w, h) schedule(dynamic, 5)
+ #pragma omp parallel for schedule(dynamic, 5)
#endif
for (int y = 0; y < h; y++) {
@@ -425,59 +387,6 @@ void Imagefloat::normalizeFloatTo65535()
}
}
-void Imagefloat::calcCroppedHistogram(const ProcParams ¶ms, float scale, LUTu & hist)
-{
-
- hist.clear();
-
- // Set up factors to calc the lightness
- TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.workingProfile);
-
- float facRed = wprof[1][0];
- float facGreen = wprof[1][1];
- float facBlue = wprof[1][2];
-
-
- // calc pixel size
- int x1, x2, y1, y2;
- params.crop.mapToResized(width, height, scale, x1, x2, y1, y2);
-
-#ifdef _OPENMP
- #pragma omp parallel
-#endif
- {
- LUTu histThr(65536);
- histThr.clear();
-#ifdef _OPENMP
- #pragma omp for nowait
-#endif
-
- for (int y = y1; y < y2; y++) {
- for (int x = x1; x < x2; x++) {
- int i = (int)(facRed * r(y, x) + facGreen * g(y, x) + facBlue * b(y, x));
-
- if (i < 0) {
- i = 0;
- } else if (i > 65535) {
- i = 65535;
- }
-
- histThr[i]++;
- }
- }
-
-#ifdef _OPENMP
- #pragma omp critical
-#endif
- {
- for(int i = 0; i <= 0xffff; i++) {
- hist[i] += histThr[i];
- }
- }
- }
-
-}
-
// Parallelized transformation; create transform with cmsFLAGS_NOCACHE!
void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform)
{
diff --git a/rtengine/imagefloat.h b/rtengine/imagefloat.h
index cd08daf70..3362afcda 100644
--- a/rtengine/imagefloat.h
+++ b/rtengine/imagefloat.h
@@ -45,9 +45,6 @@ public:
Imagefloat* copy () const;
- Image8* to8() const;
- Image16* to16() const;
-
void getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const override;
const char* getType () const override
@@ -72,10 +69,6 @@ public:
{
return getEmbeddedProfile ();
}
- int getBitsPerPixel () const override
- {
- return 8 * sizeof(float);
- }
int saveToFile (const Glib::ustring &fname) const override
{
return save (fname);
@@ -96,10 +89,6 @@ public:
{
setProgressListener (pl);
}
- void free () override
- {
- delete this;
- }
inline uint16_t DNG_FloatToHalf(float f) const
{
@@ -109,35 +98,35 @@ public:
} tmp;
tmp.f = f;
- int32_t sign = (tmp.i >> 16) & 0x00008000;
+ const int32_t lsign = (tmp.i >> 16) & 0x00008000;
int32_t exponent = ((tmp.i >> 23) & 0x000000ff) - (127 - 15);
- int32_t mantissa = tmp.i & 0x007fffff;
+ int32_t mantissa = tmp.i & 0x007fffff;
if (exponent <= 0) {
if (exponent < -10) {
- return (uint16_t)sign;
+ return (uint16_t)lsign;
}
mantissa = (mantissa | 0x00800000) >> (1 - exponent);
if (mantissa & 0x00001000)
mantissa += 0x00002000;
- return (uint16_t)(sign | (mantissa >> 13));
+ return (uint16_t)(lsign | (mantissa >> 13));
} else if (exponent == 0xff - (127 - 15)) {
if (mantissa == 0) {
- return (uint16_t)(sign | 0x7c00);
+ return (uint16_t)(lsign | 0x7c00);
} else {
- return (uint16_t)(sign | 0x7c00 | (mantissa >> 13));
+ return (uint16_t)(lsign | 0x7c00 | (mantissa >> 13));
}
}
if (mantissa & 0x00001000) {
mantissa += 0x00002000;
if (mantissa & 0x00800000) {
- mantissa = 0; // overflow in significand,
+ mantissa = 0; // overflow in significand,
exponent += 1; // adjust exponent
}
}
if (exponent > 30) {
- return (uint16_t)(sign | 0x7c00); // infinity with the same sign as f.
+ return (uint16_t)(lsign | 0x7c00); // infinity with the same sign as f.
}
- return (uint16_t)(sign | (exponent << 10) | (mantissa >> 13));
+ return (uint16_t)(lsign | (exponent << 10) | (mantissa >> 13));
}
// From DNG SDK dng_utils.h
@@ -148,13 +137,13 @@ public:
uint32_t i;
} tmp;
- int32_t sign = (halfValue >> 15) & 0x00000001;
+ const int32_t lsign = (halfValue >> 15) & 0x00000001;
int32_t exponent = (halfValue >> 10) & 0x0000001f;
- int32_t mantissa = halfValue & 0x000003ff;
+ int32_t mantissa = halfValue & 0x000003ff;
if (exponent == 0) {
if (mantissa == 0) {
// Plus or minus zero
- tmp.i = (uint32_t) (sign << 31);
+ tmp.i = (uint32_t) (lsign << 31);
return tmp.f;
} else {
// Denormalized number -- renormalize it
@@ -168,7 +157,7 @@ public:
} else if (exponent == 31) {
if (mantissa == 0) {
// Positive or negative infinity, convert to maximum (16 bit) values.
- tmp.i = (uint32_t)((sign << 31) | ((0x1eL + 127 - 15) << 23) | (0x3ffL << 13));
+ tmp.i = (uint32_t)((lsign << 31) | ((0x1eL + 127 - 15) << 23) | (0x3ffL << 13));
return tmp.f;
} else {
// Nan -- Just set to zero.
@@ -179,32 +168,32 @@ public:
exponent += (127 - 15);
mantissa <<= 13;
// Assemble sign, exponent and mantissa.
- tmp.i = (uint32_t) ((sign << 31) | (exponent << 23) | mantissa);
+ tmp.i = (uint32_t) ((lsign << 31) | (exponent << 23) | mantissa);
return tmp.f;
}
inline uint32_t DNG_FP24ToFloat(const uint8_t * input)
{
- int32_t sign = (input [0] >> 7) & 0x01;
- int32_t exponent = (input [0] ) & 0x7F;
- int32_t mantissa = (((int32_t) input [1]) << 8) | input[2];
+ const int32_t lsign = (input[0] >> 7) & 0x01;
+ int32_t exponent = input[0] & 0x7F;
+ int32_t mantissa = (((int32_t) input[1]) << 8) | input[2];
if (exponent == 0) {
if (mantissa == 0) {
// Plus or minus zero
- return (uint32_t) (sign << 31);
+ return (uint32_t) (lsign << 31);
} else {
// Denormalized number -- renormalize it
while (!(mantissa & 0x00010000)) {
- mantissa <<= 1;
- exponent -= 1;
- }
- exponent += 1;
- mantissa &= ~0x00010000;
+ mantissa <<= 1;
+ exponent -= 1;
+ }
+ exponent += 1;
+ mantissa &= ~0x00010000;
}
} else if (exponent == 127) {
if (mantissa == 0) {
// Positive or negative infinity, convert to maximum (24 bit) values.
- return (uint32_t) ((sign << 31) | ((0x7eL + 128 - 64) << 23) | (0xffffL << 7));
+ return (uint32_t) ((lsign << 31) | ((0x7eL + 128 - 64) << 23) | (0xffffL << 7));
} else {
// Nan -- Just set to zero.
return 0;
@@ -214,13 +203,12 @@ public:
exponent += (128 - 64);
mantissa <<= 7;
// Assemble sign, exponent and mantissa.
- return (uint32_t) ((sign << 31) | (exponent << 23) | mantissa);
+ return (uint32_t) ((lsign << 31) | (exponent << 23) | mantissa);
}
void normalizeFloat(float srcMinVal, float srcMaxVal) override;
void normalizeFloatTo1();
void normalizeFloatTo65535();
- void calcCroppedHistogram(const ProcParams ¶ms, float scale, LUTu & hist);
void ExecCMSTransform(cmsHTRANSFORM hTransform);
void ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy);
};
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 7a20513f0..fc9d215b7 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -852,8 +852,6 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if ((todo & M_RGBCURVE) || (todo & M_CROP)) {
- // if (hListener) oprevi->calcCroppedHistogram(params, scale, histCropped);
-
//complexCurve also calculated pre-curves histogram depending on crop
CurveFactory::complexCurve(params->toneCurve.expcomp, params->toneCurve.black / 65535.0,
params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh,
@@ -876,8 +874,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
{wprof[2][0], wprof[2][1], wprof[2][2]}
};
params->colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, opautili);
- CurveFactory::curveToning(params->colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16);
- CurveFactory::curveToning(params->colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16);
+ CurveFactory::diagonalCurve2Lut(params->colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16);
+ CurveFactory::diagonalCurve2Lut(params->colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16);
}
if (params->blackwhite.enabled) {
@@ -1005,7 +1003,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if (todo & M_LUMACURVE) {
- CurveFactory::curveCL(clcutili, params->labCurve.clcurve, clcurve, scale == 1 ? 1 : 16);
+ clcutili = CurveFactory::diagonalCurve2Lut(params->labCurve.clcurve, clcurve, scale == 1 ? 1 : 16);
CurveFactory::complexsgnCurve(autili, butili, ccutili, cclutili, params->labCurve.acurve, params->labCurve.bcurve, params->labCurve.cccurve,
params->labCurve.lccurve, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, scale == 1 ? 1 : 16);
@@ -1065,6 +1063,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
locRETtransCurve.Set(params->locallab.spots.at(sp).localTtranscurve);
const bool LHutili = loclhCurve.Set(params->locallab.spots.at(sp).LHcurve);
const bool HHutili = lochhCurve.Set(params->locallab.spots.at(sp).HHcurve);
+ const bool CHutili = locchCurve.Set(params->locallab.spots.at(sp).CHcurve);
const bool lcmasutili = locccmasCurve.Set(params->locallab.spots.at(sp).CCmaskcurve);
const bool llmasutili = locllmasCurve.Set(params->locallab.spots.at(sp).LLmaskcurve);
const bool lhmasutili = lochhmasCurve.Set(params->locallab.spots.at(sp).HHmaskcurve);
@@ -1107,22 +1106,22 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
const bool locwavdenutili = locwavCurveden.Set(params->locallab.spots.at(sp).locwavcurveden);
const bool locedgwavutili = locedgwavCurve.Set(params->locallab.spots.at(sp).locedgwavcurve);
const bool lmasutili_wav = loclmasCurve_wav.Set(params->locallab.spots.at(sp).LLmask_curvewav);
- const bool locallutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).llcurve, lllocalcurve, sca);
- const bool localclutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).clcurve, cllocalcurve, sca);
- const bool locallcutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).lccurve, lclocalcurve, sca);
- const bool localcutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).cccurve, cclocalcurve, sca);
- const bool localrgbutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).rgbcurve, rgblocalcurve, sca);
- const bool localexutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).excurve, exlocalcurve, sca);
- const bool localmaskutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve, sca);
- const bool localmaskexputili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve, sca);
- const bool localmaskSHutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve, sca);
- const bool localmaskvibutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve, sca);
- const bool localmasktmutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve, sca);
- const bool localmaskretiutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve, sca);
- const bool localmaskcbutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve, sca);
- const bool localmaskblutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve, sca);
- const bool localmasklcutili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve, sca);
- const bool localmask_utili = CurveFactory::curveLocal(params->locallab.spots.at(sp).Lmask_curve, lmasklocal_curve, sca);
+ const bool locallutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).llcurve, lllocalcurve, sca);
+ const bool localclutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).clcurve, cllocalcurve, sca);
+ const bool locallcutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).lccurve, lclocalcurve, sca);
+ const bool localcutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).cccurve, cclocalcurve, sca);
+ const bool localrgbutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).rgbcurve, rgblocalcurve, sca);
+ const bool localexutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).excurve, exlocalcurve, sca);
+ const bool localmaskutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve, sca);
+ const bool localmaskexputili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve, sca);
+ const bool localmaskSHutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve, sca);
+ const bool localmaskvibutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve, sca);
+ const bool localmasktmutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve, sca);
+ const bool localmaskretiutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve, sca);
+ const bool localmaskcbutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve, sca);
+ const bool localmaskblutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve, sca);
+ const bool localmasklcutili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve, sca);
+ const bool localmask_utili = CurveFactory::diagonalCurve2Lut(params->locallab.spots.at(sp).Lmask_curve, lmasklocal_curve, sca);
double ecomp = params->locallab.spots.at(sp).expcomp;
double black = params->locallab.spots.at(sp).black;
double hlcompr = params->locallab.spots.at(sp).hlcompr;
@@ -1179,7 +1178,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
lllocalcurve, locallutili,
cllocalcurve, localclutili,
lclocalcurve, locallcutili,
- loclhCurve, lochhCurve,
+ loclhCurve, lochhCurve, locchCurve,
lmasklocalcurve, localmaskutili,
lmaskexplocalcurve, localmaskexputili,
lmaskSHlocalcurve, localmaskSHutili,
@@ -1211,7 +1210,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
locwavCurveden, locwavdenutili,
locedgwavCurve, locedgwavutili,
loclmasCurve_wav, lmasutili_wav,
- LHutili, HHutili, cclocalcurve, localcutili, rgblocalcurve, localrgbutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc,
+ LHutili, HHutili, CHutili, cclocalcurve, localcutili, rgblocalcurve, localrgbutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc,
huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, lastsav, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
@@ -1274,9 +1273,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
}
-
- wavcontlutili = false;
- CurveFactory::curveWavContL(wavcontlutili, params->wavelet.wavclCurve, wavclCurve, scale == 1 ? 1 : 16);
+ wavcontlutili = CurveFactory::diagonalCurve2Lut(params->wavelet.wavclCurve, wavclCurve, scale == 1 ? 1 : 16);
if ((params->wavelet.enabled)) {
WaveletParams WaveParams = params->wavelet;
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index c04387b5d..ab57a4419 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -261,6 +261,7 @@ protected:
LocretigainCurverab locRETgainCurverab;
LocLHCurve loclhCurve;
LocHHCurve lochhCurve;
+ LocCHCurve locchCurve;
LocCCmaskCurve locccmasCurve;
LocLLmaskCurve locllmasCurve;
LocHHmaskCurve lochhmasCurve;
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index 66ad4dc57..d9618ba9f 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -254,9 +254,9 @@ public:
void fftw_tile_blur(int GW, int GH, int tilssize , int max_numblox_W, int min_numblox_W, float **tmp1, int numThreads, double radius);
void maskforretinex(int sp, int before, float ** luminance, float ** out, int W_L, int H_L, int skip,
- const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili,
+ const LocCCmaskCurve & locccmasretiCurve, bool lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool lhmasretiutili,
int llretiMask, bool retiMasktmap, bool retiMask, float rad, float lap, bool pde, float gamm, float slop, float chro, float blend,
- LUTf & lmaskretilocalcurve, bool & localmaskretiutili,
+ const LUTf & lmaskretilocalcurve, bool localmaskretiutili,
LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, bool multiThread,
bool delt, const float hueref, const float chromaref, const float lumaref,
float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask);
@@ -269,8 +269,8 @@ public:
void MSRLocal(int call, int sp, bool fftw, int lum, float** reducDE, LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, float** luminance, const float* const *originalLuminance,
const int width, const int height, int bfwr, int bfhr, const procparams::LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const LocretitransCurve &locRETtransCcurve,
const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax,
- const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili, int llretiMask,
- LUTf & lmaskretilocalcurve, bool & localmaskretiutili,
+ const LocCCmaskCurve & locccmasretiCurve, bool lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool lhmasretiutili, int llretiMask,
+ const LUTf & lmaskretilocalcurve, bool localmaskretiutili,
LabImage * transformed, bool retiMasktmap, bool retiMask,
bool delt, const float hueref, const float chromaref, const float lumaref,
float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask);
@@ -283,7 +283,7 @@ public:
const LUTf& lllocalcurve, bool locallutili,
const LUTf& cllocalcurve, bool localclutili,
const LUTf& lclocalcurve, bool locallcutili,
- const LocLHCurve& loclhCurve, const LocHHCurve& lochhCurve,
+ const LocLHCurve& loclhCurve, const LocHHCurve& lochhCurve, const LocCHCurve& locchCurve,
const LUTf& lmasklocalcurve, bool localmaskutili,
const LUTf& lmaskexplocalcurve, bool localmaskexputili,
const LUTf& lmaskSHlocalcurve, bool localmaskSHutili,
@@ -317,7 +317,7 @@ public:
const LocwavCurve& locwavCurveden, bool locwavdenutili,
const LocwavCurve& locedgwavCurve, bool locedgwavutili,
const LocwavCurve& loclmasCurve_wav, bool lmasutili_wav,
- bool LHutili, bool HHutili, const LUTf& cclocalcurve, bool localcutili, const LUTf& rgblocalcurve, bool localrgbutili, bool localexutili, const LUTf& exlocalcurve, const LUTf& hltonecurveloc, const LUTf& shtonecurveloc, const LUTf& tonecurveloc, const LUTf& lightCurveloc,
+ bool LHutili, bool HHutili, bool CHutili, const LUTf& cclocalcurve, bool localcutili, const LUTf& rgblocalcurve, bool localrgbutili, bool localexutili, const LUTf& exlocalcurve, const LUTf& hltonecurveloc, const LUTf& shtonecurveloc, const LUTf& tonecurveloc, const LUTf& lightCurveloc,
double& huerefblur, double &chromarefblur, double& lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, int &lastsav,
bool prevDeltaE, int llColorMask, int llColorMaskinv, int llExpMask, int llExpMaskinv, int llSHMask, int llSHMaskinv, int llvibMask, int lllcMask, int llsharMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask, int llblMask, int ll_Mask,
float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax);
@@ -387,10 +387,10 @@ public:
void Eval2(const float* const* WavCoeffs_L, int level, int W_L, int H_L, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, int numThreads);
void calceffect(int level, float *mean, float *sigma, float *mea, float effect, float offs);
-
+ std::unique_ptr buildMeaLut(const float inVals[11], const float mea[10], float& lutFactor);
void Aver(const float* HH_Coeffs, int datalen, float &averagePlus, float &averageNeg, float &max, float &min, int numThreads);
void Sigma(const float* HH_Coeffs, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg, int numThreads);
- void calckoe(const float* const* WavCoeffs_LL, float gradw, float tloww, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float &maxkoeLi, float **tmC = nullptr);
+ void calckoe(const float* WavCoeffs_LL, float gradw, float tloww, float *koeLi, int level, int W_L, int H_L, float edd, float &maxkoeLi, float **tmC, bool multiThread = false);
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);
@@ -424,7 +424,7 @@ public:
float MadRgb(const float * DataList, int datalen);
// pyramid wavelet
- void cbdl_local_temp(float ** src, float ** loctemp, int srcwidth, int srcheight, const float * mult, float kchro, const double dirpyrThreshold, const float mergeL, const float contres, const float blurcb, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale, bool multiThread);
+ void cbdl_local_temp(float ** src, float ** loctemp, int srcwidth, int srcheight, const float * mult, float kchro, const double dirpyrThreshold, const float mergeL, const float contres, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale, bool multiThread);
void dirpyr_equalizer(const float * const * src, float ** dst, int srcwidth, int srcheight, const float * const * l_a, const float * const * l_b, const double * mult, double dirpyrThreshold, double skinprot, float b_l, float t_l, float t_r, int scale); //Emil's directional pyramid wavelet
void dirpyr_equalizercam(const CieImage* ncie, float ** src, float ** dst, int srcwidth, int srcheight, const float * const * h_p, const float * const * C_p, const double * mult, const double dirpyrThreshold, const double skinprot, float b_l, float t_l, float t_r, int scale); //Emil's directional pyramid wavelet
void defringe(LabImage* lab);
diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc
index 7d715a9b0..6526d0d1e 100644
--- a/rtengine/ipdehaze.cc
+++ b/rtengine/ipdehaze.cc
@@ -103,10 +103,10 @@ void restore(Imagefloat *rgb, float maxval, bool multithread)
}
}
-int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, const array2D &dst, int patchsize, const float ambient[3], bool clip, bool multithread, float strength)
+int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &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 &R, const array2D &G, const arr
return (W / patchsize + ((W % patchsize) > 0)) * (H / patchsize + ((H % patchsize) > 0));
}
-int get_dark_channel_downsized(const array2D &R, const array2D &G, const array2D &B, const array2D &dst, int patchsize, bool multithread)
+int get_dark_channel_downsized(const array2D &R, const array2D &G, const array2D &B, array2D &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 &R, const array2D &G,
float estimate_ambient_light(const array2D &R, const array2D &G, const array2D &B, const array2D &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;
{
diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc
index 0d3955e91..0549995dd 100644
--- a/rtengine/iplab2rgb.cc
+++ b/rtengine/iplab2rgb.cc
@@ -485,8 +485,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
}
GammaValues g_a; //gamma parameters
- constexpr int mode = 0;
- Color::calcGamma(pwr, ts, mode, g_a); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
+ Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
cmsFloat64Number gammaParams[7];
diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc
index b9d070e14..cfd4a271e 100644
--- a/rtengine/iplocallab.cc
+++ b/rtengine/iplocallab.cc
@@ -69,42 +69,6 @@ constexpr int TS = 64; // Tile size
constexpr float epsilonw = 0.001f / (TS * TS); //tolerance
constexpr int offset = 25; // shift between tiles
-std::unique_ptr buildMeaLut(const float inVals[11], const float mea[10], float& lutFactor)
-{
- constexpr int lutSize = 100;
-
- const float lutMax = std::ceil(mea[9]);
- const float lutDiff = lutMax / lutSize;
-
- std::vector lutVals(lutSize);
- int jStart = 1;
- for (int i = 0; i < lutSize; ++i) {
- const float val = i * lutDiff;
- if (val < mea[0]) {
- // still < first value => no interpolation
- lutVals[i] = inVals[0];
- } else {
- for (int j = jStart; j < 10; ++j) {
- if (val == mea[j]) {
- // exact match => no interpolation
- lutVals[i] = inVals[j];
- ++jStart;
- break;
- }
- if (val < mea[j]) {
- // interpolate
- const float dist = (val - mea[j - 1]) / (mea[j] - mea[j - 1]);
- lutVals[i] = rtengine::intp(dist, inVals[j], inVals[j - 1]);
- break;
- }
- lutVals[i] = inVals[10];
- }
- }
- }
- lutFactor = 1.f / lutDiff;
- return std::unique_ptr(new LUTf(lutVals));
-}
-
constexpr float clipLoc(float x)
{
return rtengine::LIM(x, 0.f, 32767.f);
@@ -197,7 +161,7 @@ void calcGammaLut(double gamma, double ts, LUTf &gammaLut)
std::swap(pwr, gamm);
}
- rtengine::Color::calcGamma(pwr, ts, 0, g_a); // call to calcGamma with selected gamma and slope
+ rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
const double start = gamm2 < 1. ? g_a[2] : g_a[3];
const double add = g_a[4];
@@ -428,7 +392,6 @@ struct local_params {
int chro, cont, sens, sensh, senscb, sensbn, senstm, sensex, sensexclu, sensden, senslc, senssf, senshs, senscolor;
float clarityml;
float contresid;
- float blurcbdl;
bool deltaem;
float struco;
float strengrid;
@@ -1024,7 +987,6 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
int local_sensicb = locallab.spots.at(sp).sensicb;
float local_clarityml = (float) locallab.spots.at(sp).clarityml;
float local_contresid = (float) locallab.spots.at(sp).contresid;
- int local_blurcbdl = 0; //(float) locallab.spots.at(sp).blurcbdl;
int local_contrast = locallab.spots.at(sp).contrast;
float local_lightness = (float) locallab.spots.at(sp).lightness;
float labgridALowloc = locallab.spots.at(sp).labgridALow;
@@ -1274,7 +1236,6 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
lp.senscb = local_sensicb;
lp.clarityml = local_clarityml;
lp.contresid = local_contresid;
- lp.blurcbdl = local_blurcbdl;
lp.cont = local_contrast;
lp.ligh = local_lightness;
lp.lowA = labgridALowloc;
@@ -1879,8 +1840,8 @@ void tone_eq(array2D &R, array2D &G, array2D &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 Y(W, H);
const auto log2 =
@@ -2453,62 +2414,71 @@ void ImProcFunctions::exlabLocal(local_params& lp, int bfh, int bfw, int bfhr, i
constexpr float maxran = 65536.f;
const float linear = lp.linear;
+ int bw = bfw;
+ int bh = bfh;
if (linear > 0.f && lp.expcomp == 0.f) {
lp.expcomp = 0.001f;
}
- const bool exec = (lp.expmet == 1 && linear > 0.f && lp.laplacexp > 0.1f && !lp.invex);
+ const bool exec = (lp.expmet == 1 && linear > 0.f && lp.laplacexp > 0.1f);
- if(!exec) {
- //Laplacian PDE before exposure to smooth L, algorithm exposure leads to increase L differences
- const std::unique_ptr datain(new float[bfwr * bfhr]);
- const std::unique_ptr dataout(new float[bfwr * bfhr]);
- const std::unique_ptr dE(new float[bfwr * bfhr]);
+ if(!exec) {//for standard exposure
const float cexp_scale = std::pow(2.f, lp.expcomp);
const float ccomp = (rtengine::max(0.f, lp.expcomp) + 1.f) * lp.hlcomp / 100.f;
const float cshoulder = ((maxran / rtengine::max(1.0f, cexp_scale)) * (lp.hlcompthr / 200.f)) + 0.1f;
const float chlrange = maxran - cshoulder;
const float diffde = 100.f - lp.sensex;//the more scope, the less take into account dE for Laplace
+ if(!lp.invex) {// Laplacian not in inverse
+ bw = bfwr;
+ bh = bfhr;
- deltaEforLaplace(dE.get(), diffde, bfwr, bfhr, bufexporig, hueref, chromaref, lumaref);
+ //Laplacian PDE before exposure to smooth L, algorithm exposure leads to increase L differences
+ const std::unique_ptr datain(new float[bfwr * bfhr]);
+ const std::unique_ptr dataout(new float[bfwr * bfhr]);
+ const std::unique_ptr dE(new float[bfwr * bfhr]);
- constexpr float alap = 600.f;
- constexpr float blap = 100.f;
- constexpr float aa = (alap - blap) / 50.f;
- constexpr float bb = 100.f - 30.f * aa;
+ deltaEforLaplace(dE.get(), diffde, bfwr, bfhr, bufexporig, hueref, chromaref, lumaref);
- float lap;
- if (diffde > 80.f) {
- lap = alap;
- } else if (diffde < 30.f) {
- lap = blap;
- } else {
- lap = aa * diffde + bb;
- }
+ constexpr float alap = 600.f;
+ constexpr float blap = 100.f;
+ constexpr float aa = (alap - blap) / 50.f;
+ constexpr float bb = 100.f - 30.f * aa;
+
+ float lap;
+ if (diffde > 80.f) {
+ lap = alap;
+ } else if (diffde < 30.f) {
+ lap = blap;
+ } else {
+ lap = aa * diffde + bb;
+ }
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
- for (int y = 0; y < bfhr; y++) {
- for (int x = 0; x < bfwr; x++) {
- datain[y * bfwr + x] = bufexporig->L[y][x];
+ for (int y = 0; y < bfhr; y++) {
+ for (int x = 0; x < bfwr; x++) {
+ datain[y * bfwr + x] = bufexporig->L[y][x];
+ }
}
- }
- MyMutex::MyLock lock(*fftwMutex);
- ImProcFunctions::retinex_pde(datain.get(), dataout.get(), bfwr, bfhr, lap, 1.f, dE.get(), 0, 1, 1);//350 arbitrary value about 45% strength Laplacian
+ MyMutex::MyLock lock(*fftwMutex);
+ ImProcFunctions::retinex_pde(datain.get(), dataout.get(), bfwr, bfhr, lap, 1.f, dE.get(), 0, 1, 1);//350 arbitrary value about 45% strength Laplacian
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
- for (int y = 0; y < bfhr; y++) {
- for (int x = 0; x < bfwr; x++) {
- bufexporig->L[y][x] = dataout[y * bfwr + x];
+ for (int y = 0; y < bfhr; y++) {
+ for (int x = 0; x < bfwr; x++) {
+ bufexporig->L[y][x] = dataout[y * bfwr + x];
+ }
}
+
}
+
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
- for (int ir = 0; ir < bfhr; ir++) {
- for (int jr = 0; jr < bfwr; jr++) {
+ for (int ir = 0; ir < bh; ir++) {//for standard with Laplacian in normal and without in inverse
+ for (int jr = 0; jr < bw; jr++) {
float L = bufexporig->L[ir][jr];
//highlight
const float hlfactor = (2 * L < MAXVALF ? hltonecurve[2 * L] : CurveFactory::hlcurve(cexp_scale, ccomp, chlrange, 2 * L));
@@ -2519,7 +2489,7 @@ void ImProcFunctions::exlabLocal(local_params& lp, int bfh, int bfw, int bfhr, i
lab->L[ir][jr] = 0.5f * tonecurve[2 * L];
}
}
- } else {
+ } else if(!lp.invex) {//for PDE algorithms
constexpr float kl = 1.f;
const float hlcompthr = lp.hlcompthr / 200.f;
const float hlcomp = lp.hlcomp / 100.f;
@@ -3754,6 +3724,13 @@ void ImProcFunctions::retinex_pde(const float * datain, float * dataout, int bfw
fftwf_free(data_fft04);
fftwf_free(data_tmp04);
}
+ if (show == 2) {
+ for (int y = 0; y < bfh ; y++) {
+ for (int x = 0; x < bfw; x++) {
+ datashow[y * bfw + x] = data_fft[y * bfw + x];
+ }
+ }
+ }
/* solve the Poisson PDE in Fourier space */
/* 1. / (float) (bfw * bfh)) is the DCT normalisation term, see libfftw */
@@ -7432,7 +7409,7 @@ BENCHFUN
CompressDR(wav_L0, W_L, H_L, Compression, DetailBoost);
}
- if ((lp.residsha != 0.f || lp.residhi != 0.f)) {
+ if ((lp.residsha < 0.f || lp.residhi < 0.f)) {
float tran = 5.f;//transition shadow
if (lp.residshathr > (100.f - tran)) {
@@ -7469,6 +7446,31 @@ BENCHFUN
}
}
+ if ((lp.residsha > 0.f || lp.residhi > 0.f)) {
+ const std::unique_ptr temp(new LabImage(W_L, H_L));
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ temp->L[i][j] = wav_L0[i * W_L + j];
+ }
+ }
+
+ ImProcFunctions::shadowsHighlights(temp.get(), true, 1, lp.residhi, lp.residsha , 40, sk, lp.residhithr, lp.residshathr);
+
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ wav_L0[i * W_L + j] = temp->L[i][j];
+ }
+ }
+ }
+
if (contrast != 0.) {
double avedbl = 0.0; // use double precision for large summations
@@ -7545,9 +7547,9 @@ BENCHFUN
float eddlipampl = 1.f + lp.basew / 50.f;
int W_L = wdspot->level_W(0);//provisory W_L H_L
int H_L = wdspot->level_H(0);
+
float *koeLi[12];
float maxkoeLi[12] = {0.f};
- float *beta = new float[W_L * H_L];
float *koeLibuffer = new float[12 * H_L * W_L]; //12
@@ -7555,65 +7557,21 @@ BENCHFUN
koeLi[i] = &koeLibuffer[i * W_L * H_L];
}
- for (int j = 0; j < 12; j++) {
- for (int i = 0; i < W_L * H_L; i++) {
- koeLi[j][i] = 0.f;
- }
- }
-
array2D tmC(W_L, H_L);
float gradw = lp.gradw;
float tloww = lp.tloww;
-//StopWatch Stop1("test");
for (int lvl = 0; lvl < 4; lvl++) {
for (int dir = 1; dir < 4; dir++) {
const int W_L = wdspot->level_W(lvl);
const int H_L = wdspot->level_H(lvl);
float* const* wav_L = wdspot->level_coeffs(lvl);
- if (lvl == 3 && dir == 3) {
- const float effect = lp.sigmaed;
- constexpr float offset = 1.f;
- float mea[10];
- calceffect(lvl, mean, sigma, mea, effect, offset);
-
-#ifdef _OPENMP
- #pragma omp parallel for if(multiThread)
-#endif
- for (int co = 0; co < H_L * W_L; co++) {
- const float WavCL = std::fabs(wav_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.5f;
- } else if (WavCL < mea[7]) {
- beta[co] = 0.3f;
- } else if (WavCL < mea[8]) {
- beta[co] = 0.2f; // + 2 sigma
- } else if (WavCL < mea[9]) {
- beta[co] = 0.1f;
- } else {
- beta[co] = 0.05f;
- }
- }
- }
- calckoe(wav_L, gradw, tloww, koeLi, lvl, dir, W_L, H_L, edd, maxkoeLi[lvl * 3 + dir - 1], tmC);
+ calckoe(wav_L[dir], gradw, tloww, koeLi[lvl * 3 + dir - 1], lvl, W_L, H_L, edd, maxkoeLi[lvl * 3 + dir - 1], tmC, true);
// return convolution KoeLi and maxkoeLi of level 0 1 2 3 and Dir Horiz, Vert, Diag
}
}
+
tmC.free();
-//Stop1.stop();
float aamp = 1.f + lp.thigw / 100.f;
const float alipinfl = (eddlipampl - 1.f) / (1.f - eddlipinfl);
@@ -7773,6 +7731,14 @@ BENCHFUN
constexpr float da_abssd = (maxampd - abssd) / 0.333f;
constexpr float db_abssd = maxampd - da_abssd;
constexpr float am = (abssd - bbssd) / 0.666f;
+ const float effect = lp.sigmaed;
+ constexpr float offset = 1.f;
+ float mea[10];
+ calceffect(lvl, mean, sigma, mea, effect, offset);
+ float lutFactor;
+ const float inVals[] = {0.05f, 0.2f, 0.7f, 1.f, 1.f, 0.8f, 0.5f, 0.3f, 0.2f, 0.1f, 0.05f};
+ const auto meaLut = buildMeaLut(inVals, mea, lutFactor);
+
for (int dir = 1; dir < 4; dir++) {
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16) if(multiThread)
@@ -7830,7 +7796,7 @@ BENCHFUN
}
edge = std::max(edge * kinterm, 1.f);
- wav_L[dir][k] *= 1.f + (edge - 1.f) * beta[k];
+ wav_L[dir][k] *= 1.f + (edge - 1.f) * (*meaLut)[std::fabs(wav_L[dir][k]) * lutFactor];
}
}
}
@@ -7840,8 +7806,6 @@ BENCHFUN
if (koeLibuffer) {
delete [] koeLibuffer;
}
-
- delete[] beta;
}
//edge sharpness end
@@ -9512,7 +9476,7 @@ void ImProcFunctions::Lab_Local(
const LUTf& lllocalcurve, bool locallutili,
const LUTf& cllocalcurve, bool localclutili,
const LUTf& lclocalcurve, bool locallcutili,
- const LocLHCurve& loclhCurve, const LocHHCurve& lochhCurve,
+ const LocLHCurve& loclhCurve, const LocHHCurve& lochhCurve, const LocCHCurve& locchCurve,
const LUTf& lmasklocalcurve, bool localmaskutili,
const LUTf& lmaskexplocalcurve, bool localmaskexputili,
const LUTf& lmaskSHlocalcurve, bool localmaskSHutili,
@@ -9546,7 +9510,7 @@ void ImProcFunctions::Lab_Local(
const LocwavCurve& locedgwavCurve, bool locedgwavutili,
const LocwavCurve& loclmasCurve_wav, bool lmasutili_wav,
- bool LHutili, bool HHutili, const LUTf& cclocalcurve, bool localcutili, const LUTf& rgblocalcurve, bool localrgbutili, bool localexutili, const LUTf& exlocalcurve, const LUTf& hltonecurveloc, const LUTf& shtonecurveloc, const LUTf& tonecurveloc, const LUTf& lightCurveloc,
+ bool LHutili, bool HHutili, bool CHutili, const LUTf& cclocalcurve, bool localcutili, const LUTf& rgblocalcurve, bool localrgbutili, bool localexutili, const LUTf& exlocalcurve, const LUTf& hltonecurveloc, const LUTf& shtonecurveloc, const LUTf& tonecurveloc, const LUTf& lightCurveloc,
double& huerefblur, double& chromarefblur, double& lumarefblur, double& hueref, double& chromaref, double& lumaref, double& sobelref, int &lastsav,
bool prevDeltaE, int llColorMask, int llColorMaskinv, int llExpMask, int llExpMaskinv, int llSHMask, int llSHMaskinv, int llvibMask, int lllcMask, int llsharMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask, int llblMask, int ll_Mask,
float& minCD, float& maxCD, float& mini, float& maxi, float& Tmean, float& Tsigma, float& Tmin, float& Tmax
@@ -10807,7 +10771,7 @@ void ImProcFunctions::Lab_Local(
lp.mulloc[5] = 1.001f;
}
- ImProcFunctions::cbdl_local_temp(bufsh, loctemp->L, bfw, bfh, lp.mulloc, 1.f, lp.threshol, lp.clarityml, lp.contresid, lp.blurcbdl, skinprot, false, b_l, t_l, t_r, b_r, choice, sk, multiThread);
+ ImProcFunctions::cbdl_local_temp(bufsh, loctemp->L, bfw, bfh, lp.mulloc, 1.f, lp.threshol, lp.clarityml, lp.contresid, skinprot, false, b_l, t_l, t_r, b_r, choice, sk, multiThread);
if (lp.softradiuscb > 0.f) {
softproc(origcbdl.get(), loctemp.get(), lp.softradiuscb, bfh, bfw, 0.001, 0.00001, 0.5f, sk, multiThread, 1);
@@ -10846,7 +10810,7 @@ void ImProcFunctions::Lab_Local(
}
choice = 1;
- ImProcFunctions::cbdl_local_temp(bufsh, loctemp->L, bfw, bfh, multc, rtengine::max(lp.chromacb, 1.f), lp.threshol, clarich, 0.f, lp.blurcbdl, skinprot, false, b_l, t_l, t_r, b_r, choice, sk, multiThread);
+ ImProcFunctions::cbdl_local_temp(bufsh, loctemp->L, bfw, bfh, multc, rtengine::max(lp.chromacb, 1.f), lp.threshol, clarich, 0.f, skinprot, false, b_l, t_l, t_r, b_r, choice, sk, multiThread);
float minC = loctemp->L[0][0] - std::sqrt(SQR(loctemp->a[0][0]) + SQR(loctemp->b[0][0]));
@@ -13754,6 +13718,15 @@ void ImProcFunctions::Lab_Local(
}
+
+ if (locchCurve && CHutili && lp.qualcurvemet != 0) {//C=f(H) curve
+ const float rhue = xatan2f(bufcolcalcb, bufcolcalca);
+ const float valparam = locchCurve[500.f * Color::huelab_to_huehsv2(rhue)] - 0.5f; //get valp=f(H)
+ float chromaChfactor = 1.0f + valparam;
+ bufcolcalca *= chromaChfactor;//apply C=f(H)
+ bufcolcalcb *= chromaChfactor;
+ }
+
if (ctoning) {//color toning and direct change color
if (lp.gridmet == 0) {
bufcolcalca += kd * bufcolcalcL * a_scale + a_base;
diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc
index ec812c270..d65bf1cad 100644
--- a/rtengine/ipretinex.cc
+++ b/rtengine/ipretinex.cc
@@ -74,7 +74,7 @@ void calcGammaLut(double gamma, double ts, LUTf &gammaLut)
std::swap(pwr, gamm);
}
- rtengine::Color::calcGamma(pwr, ts, 0, g_a); // call to calcGamma with selected gamma and slope
+ rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
const double start = gamm2 < 1. ? g_a[2] : g_a[3];
const double add = g_a[4];
@@ -779,9 +779,9 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
void ImProcFunctions::maskforretinex(int sp, int before, float ** luminance, float ** out, int W_L, int H_L, int skip,
- const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili,
+ const LocCCmaskCurve & locccmasretiCurve, bool lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool lhmasretiutili,
int llretiMask, bool retiMasktmap, bool retiMask, float rad, float lap, bool pde, float gamm, float slop, float chro, float blend,
- LUTf & lmaskretilocalcurve, bool & localmaskretiutili,
+ const LUTf & lmaskretilocalcurve, bool localmaskretiutili,
LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, bool multiThread,
bool delt, const float hueref, const float chromaref, const float lumaref,
float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask)
@@ -1127,534 +1127,504 @@ void ImProcFunctions::maskforretinex(int sp, int before, float ** luminance, flo
void ImProcFunctions::MSRLocal(int call, int sp, bool fftw, int lum, float** reducDE, LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, float** luminance, const float* const *originalLuminance,
const int width, const int height, int bfwr, int bfhr, const procparams::LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const LocretitransCurve &locRETtransCcurve,
const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax,
- const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili, int llretiMask,
- LUTf & lmaskretilocalcurve, bool & localmaskretiutili,
+ const LocCCmaskCurve & locccmasretiCurve, bool lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool lhmasretiutili, int llretiMask,
+ const LUTf & lmaskretilocalcurve, bool localmaskretiutili,
LabImage * transformed, bool retiMasktmap, bool retiMask,
bool delt, const float hueref, const float chromaref, const float lumaref,
float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask)
{
BENCHFUN
- bool py = true;
- if (py) {//enabled
- float mean, stddv, maxtr, mintr;
- mean = 0.f;
- stddv = 0.f;
- maxtr = 0.f;
- mintr = 0.f;
- float delta;
- constexpr float eps = 2.f;
- bool useHslLin = false;
- const float offse = loc.spots.at(sp).offs;
- const float chrT = (float)(loc.spots.at(sp).chrrt) / 100.f;
- const int scal = (loc.spots.at(sp).scalereti);
- float vart = loc.spots.at(sp).vart / 100.f;//variance
- const float strength = loc.spots.at(sp).str / 100.f; // Blend with original L channel data
- const float dar = loc.spots.at(sp).darkness;
- const float lig = loc.spots.at(sp).lightnessreti;
- float value = pow(strength, 0.4f);
- float value_1 = pow(strength, 0.3f);
- bool logli = loc.spots.at(sp).loglin;
- float limD = loc.spots.at(sp).limd;//10.f
- limD = pow(limD, 1.7f); //about 2500 enough
- float ilimD = 1.f / limD;
- float threslum = loc.spots.at(sp).limd;
- const float elogt = 2.71828f;
+ float mean, stddv, maxtr, mintr;
+ mean = 0.f;
+ stddv = 0.f;
+ maxtr = 0.f;
+ mintr = 0.f;
+ constexpr float eps = 2.f;
+ bool useHslLin = false;
+ const float offse = loc.spots.at(sp).offs;
+ const float chrT = (float)(loc.spots.at(sp).chrrt) / 100.f;
+ const int scal = (loc.spots.at(sp).scalereti);
+ float vart = loc.spots.at(sp).vart / 100.f;//variance
+ const float strength = loc.spots.at(sp).str / 100.f; // Blend with original L channel data
+ const float dar = loc.spots.at(sp).darkness;
+ const float lig = loc.spots.at(sp).lightnessreti;
+ float value = pow(strength, 0.4f);
+ float value_1 = pow(strength, 0.3f);
+ bool logli = loc.spots.at(sp).loglin;
+ float limD = loc.spots.at(sp).limd;//10.f
+ limD = pow(limD, 1.7f); //about 2500 enough
+ float ilimD = 1.f / limD;
+ float threslum = loc.spots.at(sp).limd;
+ const float elogt = 2.71828f;
- if (!logli) {
- useHslLin = true;
+ if (!logli) {
+ useHslLin = true;
+ }
+
+ //empirical skip evaluation : very difficult because quasi all parameters interfere
+ //to test on several images
+ int nei = (int)(krad * loc.spots.at(sp).neigh);
+ // printf("neigh=%i\n", nei);
+ //several test to find good values ???!!!
+ //very difficult to do because 4 factor are correlate with skip and cannot been solved easily
+ // size of spots
+ // radius - neigh
+ // scal
+ // variance vart
+ //not too bad proposition
+ float divsca = 1.f;
+
+ if (scal >= 3) {
+ divsca = sqrt(scal / 3.f);
+ }
+
+ if (skip >= 4) {
+ //nei = (int)(0.1f * nei + 2.f); //not too bad
+ nei = (int)(nei / (1.5f * skip)) / divsca;
+ vart *= sqrt(skip);
+ } else if (skip > 1) {
+ //nei = (int)(0.3f * nei + 2.f);
+ nei = (int)(nei / skip) / divsca;
+ vart *= sqrt(skip);
+ }
+
+ int moderetinex = 0;
+
+ if (loc.spots.at(sp).retinexMethod == "uni") {
+ moderetinex = 0;
+ } else if (loc.spots.at(sp).retinexMethod == "low") {
+ moderetinex = 1;
+ } else if (loc.spots.at(sp).retinexMethod == "high") {
+ moderetinex = 2;
+ }
+
+ const float high = 0.f; // Dummy to pass to retinex_scales(...)
+
+ constexpr auto maxRetinexScales = 10;
+ float RetinexScales[maxRetinexScales];
+
+ retinex_scales(RetinexScales, scal, moderetinex, nei, high);
+
+
+ const int H_L = height;
+ const int W_L = width;
+ std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L));
+ float** src = *(srcBuffer.get());
+
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int i = 0; i < H_L; i++)
+ for (int j = 0; j < W_L; j++) {
+ src[i][j] = luminance[i][j] + eps;
+ luminance[i][j] = 0.f;
}
- //empirical skip evaluation : very difficult because quasi all parameters interfere
- //to test on several images
- int nei = (int)(krad * loc.spots.at(sp).neigh);
- // printf("neigh=%i\n", nei);
- //several test to find good values ???!!!
- //very difficult to do because 4 factor are correlate with skip and cannot been solved easily
- // size of spots
- // radius - neigh
- // scal
- // variance vart
- //not too bad proposition
- float divsca = 1.f;
+ JaggedArray out(W_L, H_L);
- if (scal >= 3) {
- divsca = sqrt(scal / 3.f);
+ float clipt = loc.spots.at(sp).cliptm;
+
+ const float logBetaGain = xlogf(16384.f);
+ float pond = logBetaGain / (float) scal;
+
+ if (!useHslLin) {
+ pond /= log(elogt);
+ }
+
+ float kr;//on FFTW
+ float kg = 1.f;//on Gaussianblur
+
+ for (int scale = scal - 1; scale >= 0; --scale) {
+ // printf("retscale=%f scale=%i \n", mulradiusfftw * RetinexScales[scale], scale);
+ //emprical adjustment between FFTW radius and Gaussainblur
+ //under 50 ==> 10.f
+ // 400 ==> 1.f
+ float sigm = 1.f;
+
+ if (settings->fftwsigma == false) { //empirical formula
+ sigm = RetinexScales[scale];
+ float ak = -9.f / 350.f;
+ float bk = 10.f - 50.f * ak;
+ kr = ak * sigm + bk;
+
+ if (sigm < 50.f) {
+ kr = 10.f;
+ }
+
+ //above 400 at 5000 ==> 20.f
+ if (sigm > 400.f) { //increase ==> 5000
+ float ka = 19.f / 4600.f;
+ float kb = 1.f - 400 * ka;
+ kr = ka * sigm + kb;
+ float kga = -0.14f / 4600.f;//decrease
+ float kgb = 1.f - 400.f * kga;
+ kg = kga * sigm + kgb;
+
+ if (sigm > 5000.f) {
+ kr = ka * 5000.f + kb;
+ kg = kga * 5000.f + kgb;
+ }
+
+ }
+ } else {//sigma *= sigma
+ kg = 1.f;
+ kr = sigm;
}
- if (skip >= 4) {
- //nei = (int)(0.1f * nei + 2.f); //not too bad
- nei = (int)(nei / (1.5f * skip)) / divsca;
- vart *= sqrt(skip);
- } else if (skip > 1 && skip < 4) {
- //nei = (int)(0.3f * nei + 2.f);
- nei = (int)(nei / skip) / divsca;
- vart *= sqrt(skip);
+ if (!fftw) { // || (fftw && call != 2)) {
+ if (scale == scal - 1) {
+ gaussianBlur(src, out, W_L, H_L, kg * RetinexScales[scale], true);
+ } else { // reuse result of last iteration
+ // out was modified in last iteration => restore it
+ gaussianBlur(out, out, W_L, H_L, sqrtf(SQR(kg * RetinexScales[scale]) - SQR(kg * RetinexScales[scale + 1])), true);
+ }
+ } else {
+ if (scale == scal - 1) {
+ if (settings->fftwsigma == false) { //empirical formula
+ ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (kr * RetinexScales[scale]), 0, 0);
+ } else {
+ ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (SQR(RetinexScales[scale])), 0, 0);
+ }
+ } else { // reuse result of last iteration
+ // out was modified in last iteration => restore it
+ if (settings->fftwsigma == false) { //empirical formula
+ ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, sqrtf(SQR(kr * RetinexScales[scale]) - SQR(kr * RetinexScales[scale + 1])), 0, 0);
+ } else {
+ ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, (SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), 0, 0);
+ }
+ }
}
- int moderetinex = 0;
+ if (scale == 1) { //equalize last scale with darkness and lightness of course acts on TM!
+ if (dar != 1.f || lig != 1.f) {
- if (loc.spots.at(sp).retinexMethod == "uni") {
- moderetinex = 0;
- } else if (loc.spots.at(sp).retinexMethod == "low") {
- moderetinex = 1;
- } else if (loc.spots.at(sp).retinexMethod == "high") {
- moderetinex = 2;
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int y = 0; y < H_L; ++y) {
+ for (int x = 0; x < W_L; ++x) {
+ float buf = (src[y][x] - out[y][x]) * value;
+ buf *= (buf > 0.f) ? lig : dar;
+ out[y][x] = LIM(out[y][x] + buf, -100000.f, 100000.f);
+ }
+ }
+ }
}
- const float high = 0.f; // Dummy to pass to retinex_scales(...)
-
- constexpr auto maxRetinexScales = 10;
- float RetinexScales[maxRetinexScales];
-
- retinex_scales(RetinexScales, scal, moderetinex, nei, high);
-
-
- const int H_L = height;
- const int W_L = width;
- std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L));
- float** src = *(srcBuffer.get());
-
-
#ifdef _OPENMP
#pragma omp parallel for
#endif
- for (int i = 0; i < H_L; i++)
- for (int j = 0; j < W_L; j++) {
- src[i][j] = luminance[i][j] + eps;
- luminance[i][j] = 0.f;
- }
-
- JaggedArray out(W_L, H_L);
-
- float clipt = loc.spots.at(sp).cliptm;
-
- const float logBetaGain = xlogf(16384.f);
- float pond = logBetaGain / (float) scal;
-
- if (!useHslLin) {
- pond /= log(elogt);
- }
-
- float kr = 1.f;//on FFTW
- float kg = 1.f;//on Gaussianblur
- std::unique_ptr buffer;
- buffer.reset(new float[W_L * H_L]);
-
- for (int scale = scal - 1; scale >= 0; --scale) {
- // printf("retscale=%f scale=%i \n", mulradiusfftw * RetinexScales[scale], scale);
- //emprical adjustment between FFTW radius and Gaussainblur
- //under 50 ==> 10.f
- // 400 ==> 1.f
- float sigm = 1.f;
-
- if (settings->fftwsigma == false) { //empirical formula
- sigm = RetinexScales[scale];
- float ak = -9.f / 350.f;
- float bk = 10.f - 50.f * ak;
- kr = ak * sigm + bk;
-
- if (sigm < 50.f) {
- kr = 10.f;
- }
-
- //above 400 at 5000 ==> 20.f
- if (sigm > 400.f) { //increase ==> 5000
- float ka = 19.f / 4600.f;
- float kb = 1.f - 400 * ka;
- kr = ka * sigm + kb;
- float kga = -0.14f / 4600.f;//decrease
- float kgb = 1.f - 400.f * kga;
- kg = kga * sigm + kgb;
-
- if (sigm > 5000.f) {
- kr = ka * 5000.f + kb;
- kg = kga * 5000.f + kgb;
- }
-
- }
- } else {//sigma *= sigma
- kg = 1.f;
- kr = sigm;
- }
- printf("call=%i\n", call);
- if (!fftw) { // || (fftw && call != 2)) {
- if (scale == scal - 1) {
- gaussianBlur(src, out, W_L, H_L, kg * RetinexScales[scale], true);
- } else { // reuse result of last iteration
- // out was modified in last iteration => restore it
- gaussianBlur(out, out, W_L, H_L, sqrtf(SQR(kg * RetinexScales[scale]) - SQR(kg * RetinexScales[scale + 1])), true);
- }
- } else {
- if (scale == scal - 1) {
- if (settings->fftwsigma == false) { //empirical formula
- ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (kr * RetinexScales[scale]), 0, 0);
- } else {
- ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (SQR(RetinexScales[scale])), 0, 0);
- }
- } else { // reuse result of last iteration
- // out was modified in last iteration => restore it
- if (settings->fftwsigma == false) { //empirical formula
- ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, sqrtf(SQR(kr * RetinexScales[scale]) - SQR(kr * RetinexScales[scale + 1])), 0, 0);
- } else {
- ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, (SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), 0, 0);
- }
- }
- }
-
- if (scale == 1) { //equalize last scale with darkness and lightness of course acts on TM!
- if (dar != 1.f || lig != 1.f) {
-
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int y = 0; y < H_L; ++y) {
- for (int x = 0; x < W_L; ++x) {
- float buf = (src[y][x] - out[y][x]) * value;
- buf *= (buf > 0.f) ? lig : dar;
- out[y][x] = LIM(out[y][x] + buf, -100000.f, 100000.f);
- }
- }
- }
-
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int i = 0; i < H_L; i++) {
- int j = 0;
+ for (int i = 0; i < H_L; i++) {
+ int j = 0;
#ifdef __SSE2__
- const vfloat pondv = F2V(pond);
- const vfloat limMinv = F2V(ilimD);
- const vfloat limMaxv = F2V(limD);
+ const vfloat pondv = F2V(pond);
+ const vfloat limMinv = F2V(ilimD);
+ const vfloat limMaxv = F2V(limD);
- if (useHslLin) {
- for (; j < W_L - 3; j += 4) {
- STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv));
- }
- } else {
- for (; j < W_L - 3; j += 4) {
- STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv)));
- }
+ if (useHslLin) {
+ for (; j < W_L - 3; j += 4) {
+ STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv));
}
-
-#endif
-
- if (useHslLin) {
- for (; j < W_L; j++) {
- luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimD, limD));
- }
- } else {
- for (; j < W_L; j++) {
- luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimD, limD));
- }
+ } else {
+ for (; j < W_L - 3; j += 4) {
+ STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv)));
}
}
+#endif
+
+ if (useHslLin) {
+ for (; j < W_L; j++) {
+ luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimD, limD));
+ }
+ } else {
+ for (; j < W_L; j++) {
+ luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimD, limD));
+ }
+ }
}
-// srcBuffer.reset();
+ }
+ if (scal == 1) {//only if user select scal = 1
+ const float threslow = threslum * 163.f;
- if (scal == 1) {//only if user select scal = 1
-
- float kval = 1.f;
#ifdef _OPENMP
- #pragma omp parallel for
+ #pragma omp parallel for
#endif
- for (int y = 0; y < H_L; ++y) {
- for (int x = 0; x < W_L; ++x) {
- float threslow = threslum * 163.f;
-
- if (src[y][x] < threslow) {
- kval = src[y][x] / threslow;
- }
- }
+ for (int y = 0; y < H_L; ++y) {
+ for (int x = 0; x < W_L; ++x) {
+ const float srcVal = src[y][x];
+ const float kval = rtengine::min(srcVal / threslow, 1.f);
+ float buf = (srcVal - out[y][x]) * value_1;
+ buf *= (buf > 0.f) ? lig : dar;
+ luminance[y][x] = LIM(srcVal + (1.f + kval) * buf, -32768.f, 32768.f);
}
-
-
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int y = 0; y < H_L; ++y) {
- for (int x = 0; x < W_L; ++x) {
- float buf = (src[y][x] - out[y][x]) * value_1;
- buf *= (buf > 0.f) ? lig : dar;
- luminance[y][x] = LIM(src[y][x] + (1.f + kval) * buf, -32768.f, 32768.f);
- }
- }
-
- double avg = 0.f;
- int ng = 0;
-
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int i = 0; i < H_L; i++) {
- for (int j = 0; j < W_L; j++) {
- avg += luminance[i][j];
- ng++;
- }
- }
-
- avg /= ng;
- avg /= 32768.f;
- avg = LIM01(avg);
- float contreal = 0.5f * vart;
- DiagonalCurve reti_contrast({
- DCT_NURBS,
- 0, 0,
- avg - avg * (0.6 - contreal / 250.0), avg - avg * (0.6 + contreal / 250.0),
- avg + (1 - avg) * (0.6 - contreal / 250.0), avg + (1 - avg) * (0.6 + contreal / 250.0),
- 1, 1
- });
-
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int i = 0; i < H_L; i++)
- for (int j = 0; j < W_L; j++) {
- float buf = LIM01(luminance[i][j] / 32768.f);
- buf = reti_contrast.getVal(buf);
- buf *= 32768.f;
- luminance[i][j] = buf;
- }
-
}
- srcBuffer.reset();
-
- float str = strength * (chrome == 0 ? 1.f : 0.8f * (chrT - 0.4f));
- const float maxclip = (chrome == 0 ? 32768.f : 50000.f);
-
- if (scal != 1) {
- mean = 0.f;
- stddv = 0.f;
-
- mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);
- // printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr);
-
- if (locRETtransCcurve && mean != 0.f && stddv != 0.f) { //if curve
- float asig = 0.166666f / stddv;
- float bsig = 0.5f - asig * mean;
- float amax = 0.333333f / (maxtr - mean - stddv);
- float bmax = 1.f - amax * maxtr;
- float amin = 0.333333f / (mean - stddv - mintr);
- float bmin = -amin * mintr;
-
- asig *= 500.f;
- bsig *= 500.f;
- amax *= 500.f;
- bmax *= 500.f;
- amin *= 500.f;
- bmin *= 500.f;
+ double avg = 0.f;
#ifdef _OPENMP
- #pragma omp parallel
+ #pragma omp parallel for reduction(+:avg)
#endif
- {
- float absciss;
+
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ avg += luminance[i][j];
+ }
+ }
+
+ avg /= H_L * W_L;
+ avg /= 32768.f;
+ avg = LIM01(avg);
+ float contreal = 0.5f * vart;
+ DiagonalCurve reti_contrast({
+ DCT_NURBS,
+ 0, 0,
+ avg - avg * (0.6 - contreal / 250.0), avg - avg * (0.6 + contreal / 250.0),
+ avg + (1 - avg) * (0.6 - contreal / 250.0), avg + (1 - avg) * (0.6 + contreal / 250.0),
+ 1, 1
+ });
+
#ifdef _OPENMP
- #pragma omp for schedule(dynamic,16)
+ #pragma omp parallel for
#endif
- for (int i = 0; i < H_L; i++)
- for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission
- if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
- absciss = asig * luminance[i][j] + bsig;
- } else if (luminance[i][j] >= mean) {
- absciss = amax * luminance[i][j] + bmax;
- } else { /*if(luminance[i][j] <= mean - stddv)*/
- absciss = amin * luminance[i][j] + bmin;
- }
-
- //TODO : move multiplication by 4.f and subtraction of 1.f inside the curve
- luminance[i][j] *= (-1.f + 4.f * locRETtransCcurve[absciss]); //new transmission
-
- }
- }
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ float buf = LIM01(luminance[i][j] / 32768.f);
+ buf = reti_contrast.getVal(buf);
+ buf *= 32768.f;
+ luminance[i][j] = buf;
}
+ }
+ }
- mean = 0.f;
- stddv = 0.f;
- mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);//new calculation of mean...
+ srcBuffer.reset();
- float epsil = 0.1f;
+ float str = strength * (chrome == 0 ? 1.f : 0.8f * (chrT - 0.4f));
+ const float maxclip = (chrome == 0 ? 32768.f : 50000.f);
- mini = mean - vart * stddv;
+ if (scal != 1) {
+ mean = 0.f;
+ stddv = 0.f;
- if (mini < mintr) {
- mini = mintr + epsil;
- }
+ mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);
- maxi = mean + vart * stddv;
-
- if (maxi > maxtr) {
- maxi = maxtr - epsil;
- }
-
- delta = maxi - mini;
- // printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr);
-
- if (!delta) {
- delta = 1.0f;
- }
-
-
- float *copylum[H_L] ALIGNED16;
- float *copylumBuffer = new float[H_L * W_L];
-
- for (int i = 0; i < H_L; i++) {
- copylum[i] = ©lumBuffer[i * W_L];
- }
-
- float cdfactor = (clipt * 32768.f) / delta;
- maxCD = -9999999.f;
- minCD = 9999999.f;
- //prepare work for curve gain
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int i = 0; i < H_L; i++) {
- for (int j = 0; j < W_L; j++) {
- luminance[i][j] = luminance[i][j] - mini;
- }
- }
-
- mean = 0.f;
- stddv = 0.f;
-
- mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);
-// printf("meanun=%f stdun=%f maxtr=%f mintr=%f\n", mean, stddv, maxtr, mintr);
-
- float asig = 0.f, bsig = 0.f, amax = 0.f, bmax = 0.f, amin = 0.f, bmin = 0.f;
- const bool hasRetGainCurve = locRETgainCcurve && mean != 0.f && stddv != 0.f;
-
- if (hasRetGainCurve) { //if curve
- asig = 0.166666f / stddv;
- bsig = 0.5f - asig * mean;
- amax = 0.333333f / (maxtr - mean - stddv);
- bmax = 1.f - amax * maxtr;
- amin = 0.333333f / (mean - stddv - mintr);
- bmin = -amin * mintr;
-
- asig *= 500.f;
- bsig *= 500.f;
- amax *= 500.f;
- bmax *= 500.f;
- amin *= 500.f;
- bmin *= 500.f;
- cdfactor *= 2.f;
- }
+ if (locRETtransCcurve && mean != 0.f && stddv != 0.f) { //if curve
+ float asig = 0.166666f / stddv;
+ float bsig = 0.5f - asig * mean;
+ float amax = 0.333333f / (maxtr - mean - stddv);
+ float bmax = 1.f - amax * maxtr;
+ float amin = 0.333333f / (mean - stddv - mintr);
+ float bmin = -amin * mintr;
+ asig *= 500.f;
+ bsig *= 500.f;
+ amax *= 500.f;
+ bmax *= 500.f;
+ amin *= 500.f;
+ bmin *= 500.f;
#ifdef _OPENMP
#pragma omp parallel
#endif
{
- // float absciss;
- float cdmax = -999999.f, cdmin = 999999.f;
- float gan = 0.5f;
-
+ float absciss;
#ifdef _OPENMP
#pragma omp for schedule(dynamic,16)
#endif
- for (int i = 0; i < H_L; i ++)
- for (int j = 0; j < W_L; j++) {
-
- if (hasRetGainCurve) {
- float absciss;
-
- if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
- absciss = asig * luminance[i][j] + bsig;
- } else if (luminance[i][j] >= mean) {
- absciss = amax * luminance[i][j] + bmax;
- } else {
- absciss = amin * luminance[i][j] + bmin;
- }
-
- gan = locRETgainCcurve[absciss]; //new gain function transmission
+ for (int i = 0; i < H_L; i++)
+ for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission
+ if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
+ absciss = asig * luminance[i][j] + bsig;
+ } else if (luminance[i][j] >= mean) {
+ absciss = amax * luminance[i][j] + bmax;
+ } else { /*if(luminance[i][j] <= mean - stddv)*/
+ absciss = amin * luminance[i][j] + bmin;
}
- //but we don't update mean stddv for display only...
- copylum[i][j] = gan * luminance[i][j];//update data for display
- float cd = gan * cdfactor * luminance[i][j] + offse;
+ //TODO : move multiplication by 4.f and subtraction of 1.f inside the curve
+ luminance[i][j] *= (-1.f + 4.f * locRETtransCcurve[absciss]); //new transmission
- cdmax = cd > cdmax ? cd : cdmax;
- cdmin = cd < cdmin ? cd : cdmin;
- luminance[i][j] = intp(str * reducDE[i][j], clipretinex(cd, 0.f, maxclip), originalLuminance[i][j]);
}
+ }
+ }
+ mean = 0.f;
+ stddv = 0.f;
+ mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);//new calculation of mean...
+
+ float epsil = 0.1f;
+
+ mini = mean - vart * stddv;
+
+ if (mini < mintr) {
+ mini = mintr + epsil;
+ }
+
+ maxi = mean + vart * stddv;
+
+ if (maxi > maxtr) {
+ maxi = maxtr - epsil;
+ }
+
+ float delta = maxi - mini;
+ if (!delta) {
+ delta = 1.0f;
+ }
+
+
+ float *copylum[H_L] ALIGNED16;
+ float *copylumBuffer = new float[H_L * W_L];
+
+ for (int i = 0; i < H_L; i++) {
+ copylum[i] = ©lumBuffer[i * W_L];
+ }
+
+ float cdfactor = (clipt * 32768.f) / delta;
+ maxCD = -9999999.f;
+ minCD = 9999999.f;
+ //prepare work for curve gain
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ luminance[i][j] = luminance[i][j] - mini;
+ }
+ }
+
+ mean = 0.f;
+ stddv = 0.f;
+
+ mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+// printf("meanun=%f stdun=%f maxtr=%f mintr=%f\n", mean, stddv, maxtr, mintr);
+
+ float asig = 0.f, bsig = 0.f, amax = 0.f, bmax = 0.f, amin = 0.f, bmin = 0.f;
+ const bool hasRetGainCurve = locRETgainCcurve && mean != 0.f && stddv != 0.f;
+
+ if (hasRetGainCurve) { //if curve
+ asig = 0.166666f / stddv;
+ bsig = 0.5f - asig * mean;
+ amax = 0.333333f / (maxtr - mean - stddv);
+ bmax = 1.f - amax * maxtr;
+ amin = 0.333333f / (mean - stddv - mintr);
+ bmin = -amin * mintr;
+
+ asig *= 500.f;
+ bsig *= 500.f;
+ amax *= 500.f;
+ bmax *= 500.f;
+ amin *= 500.f;
+ bmin *= 500.f;
+ cdfactor *= 2.f;
+ }
#ifdef _OPENMP
- #pragma omp critical
+ #pragma omp parallel
#endif
- {
- maxCD = maxCD > cdmax ? maxCD : cdmax;
- minCD = minCD < cdmin ? minCD : cdmin;
- }
- }
- mean = 0.f;
- stddv = 0.f;
+ {
+ // float absciss;
+ float cdmax = -999999.f, cdmin = 999999.f;
+ float gan = 0.5f;
- mean_stddv2(copylum, mean, stddv, W_L, H_L, maxtr, mintr);
- delete [] copylumBuffer;
- copylumBuffer = nullptr;
-
-// printf("mean=%f std=%f maxtr=%f mintr=%f\n", mean, stddv, maxtr, mintr);
-
- } else {
#ifdef _OPENMP
#pragma omp for schedule(dynamic,16)
#endif
for (int i = 0; i < H_L; i ++)
for (int j = 0; j < W_L; j++) {
- luminance[i][j] = LIM(luminance[i][j], 0.f, maxclip) * str + (1.f - str) * originalLuminance[i][j];
+ if (hasRetGainCurve) {
+ float absciss;
+
+ if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
+ absciss = asig * luminance[i][j] + bsig;
+ } else if (luminance[i][j] >= mean) {
+ absciss = amax * luminance[i][j] + bmax;
+ } else {
+ absciss = amin * luminance[i][j] + bmin;
+ }
+
+ gan = locRETgainCcurve[absciss]; //new gain function transmission
+ }
+
+ //but we don't update mean stddv for display only...
+ copylum[i][j] = gan * luminance[i][j];//update data for display
+ float cd = gan * cdfactor * luminance[i][j] + offse;
+
+ cdmax = cd > cdmax ? cd : cdmax;
+ cdmin = cd < cdmin ? cd : cdmin;
+ luminance[i][j] = intp(str * reducDE[i][j], clipretinex(cd, 0.f, maxclip), originalLuminance[i][j]);
}
+
+
+#ifdef _OPENMP
+ #pragma omp critical
+#endif
+ {
+ maxCD = maxCD > cdmax ? maxCD : cdmax;
+ minCD = minCD < cdmin ? minCD : cdmin;
+ }
}
+ mean = 0.f;
+ stddv = 0.f;
- float rad = loc.spots.at(sp).radmaskreti;
- float slop = loc.spots.at(sp).slomaskreti;
- float gamm = loc.spots.at(sp).gammaskreti;
- float blend = loc.spots.at(sp).blendmaskreti;
- float chro = loc.spots.at(sp).chromaskreti;
- float lap = loc.spots.at(sp).lapmaskreti;
- bool pde = params->locallab.spots.at(sp).laplac;
+ mean_stddv2(copylum, mean, stddv, W_L, H_L, maxtr, mintr);
+ delete [] copylumBuffer;
+ copylumBuffer = nullptr;
- if (lum == 1 && (llretiMask == 3 || llretiMask == 0 || llretiMask == 2 || llretiMask == 4)) { //only mask with luminance on last scale
- int before = 1;
- maskforretinex(sp, before, luminance, nullptr, W_L, H_L, skip,
- locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask, retiMasktmap, retiMask,
- rad, lap, pde, gamm, slop, chro, blend,
- lmaskretilocalcurve, localmaskretiutili,
- bufreti, bufmask, buforig, buforigmas, multiThread,
- delt, hueref, chromaref, lumaref,
- maxdE, mindE, maxdElim, mindElim, iterat, limscope, scope, balance, balanceh, lumask
- );
- }
+ } else {
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
- //mask does not interfered with data displayed
+ for (int i = 0; i < H_L; i ++)
+ for (int j = 0; j < W_L; j++) {
+ luminance[i][j] = LIM(luminance[i][j], 0.f, maxclip) * str + (1.f - str) * originalLuminance[i][j];
+
+ }
- Tmean = mean;
- Tsigma = stddv;
- Tmin = mintr;
- Tmax = maxtr;
}
+
+ float rad = loc.spots.at(sp).radmaskreti;
+ float slop = loc.spots.at(sp).slomaskreti;
+ float gamm = loc.spots.at(sp).gammaskreti;
+ float blend = loc.spots.at(sp).blendmaskreti;
+ float chro = loc.spots.at(sp).chromaskreti;
+ float lap = loc.spots.at(sp).lapmaskreti;
+ bool pde = params->locallab.spots.at(sp).laplac;
+
+ if (lum == 1 && (llretiMask == 3 || llretiMask == 0 || llretiMask == 2 || llretiMask == 4)) { //only mask with luminance on last scale
+ int before = 1;
+ maskforretinex(sp, before, luminance, nullptr, W_L, H_L, skip,
+ locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask, retiMasktmap, retiMask,
+ rad, lap, pde, gamm, slop, chro, blend,
+ lmaskretilocalcurve, localmaskretiutili,
+ bufreti, bufmask, buforig, buforigmas, multiThread,
+ delt, hueref, chromaref, lumaref,
+ maxdE, mindE, maxdElim, mindElim, iterat, limscope, scope, balance, balanceh, lumask
+ );
+ }
+
+ //mask does not interfered with data displayed
+
+ Tmean = mean;
+ Tsigma = stddv;
+ Tmin = mintr;
+ Tmax = maxtr;
}
}
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index 949dbafbd..21fffb76c 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -50,6 +50,8 @@
#endif
#include "cplx_wavelet_dec.h"
+#define BENCHMARK
+#include "StopWatch.h"
namespace rtengine
{
@@ -162,6 +164,41 @@ struct cont_params {
int wavNestedLevels = 1;
+std::unique_ptr ImProcFunctions::buildMeaLut(const float inVals[11], const float mea[10], float& lutFactor)
+{
+ constexpr int lutSize = 100;
+
+ const float lutMax = std::ceil(mea[9]);
+ const float lutDiff = lutMax / lutSize;
+
+ std::vector lutVals(lutSize);
+ int jStart = 1;
+ for (int i = 0; i < lutSize; ++i) {
+ const float val = i * lutDiff;
+ if (val < mea[0]) {
+ // still < first value => no interpolation
+ lutVals[i] = inVals[0];
+ } else {
+ for (int j = jStart; j < 10; ++j) {
+ if (val == mea[j]) {
+ // exact match => no interpolation
+ lutVals[i] = inVals[j];
+ ++jStart;
+ break;
+ }
+ if (val < mea[j]) {
+ // interpolate
+ const float dist = (val - mea[j - 1]) / (mea[j] - mea[j - 1]);
+ lutVals[i] = rtengine::intp(dist, inVals[j], inVals[j - 1]);
+ break;
+ }
+ lutVals[i] = inVals[10];
+ }
+ }
+ }
+ lutFactor = 1.f / lutDiff;
+ return std::unique_ptr(new LUTf(lutVals));
+}
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)
@@ -286,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;
@@ -1542,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;
@@ -1974,6 +2017,7 @@ void ImProcFunctions::WaveletcontAllLfinal(wavelet_decomposition& WaveletCoeffs_
void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float **varchrom, 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)
{
+ BENCHFUN
const int maxlvl = WaveletCoeffs_L.maxlevel();
const int W_L = WaveletCoeffs_L.level_W(0);
const int H_L = WaveletCoeffs_L.level_H(0);
@@ -2035,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 temp(new LabImage(W_L, H_L));
#ifdef _OPENMP
#pragma omp parallel for num_threads(wavNestedLevels) if (wavNestedLevels>1)
@@ -2060,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
@@ -2129,10 +2175,6 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
}
}
-//
- 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;
-
float *koeLi[12];
const std::unique_ptr koeLibuffer(new float[12 * H_L * W_L]());
@@ -2174,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;
- calckoe (WavCoeffs_LL, gradw, tloww, koeLi, lvl , dir, W_L, H_L, edd, tempkoeli, tmC);
- maxkoeLi[lvl * 3 + dir - 1] = tempkoeli;
+ float tempkoeli = 0.f;
+ calckoe (WavCoeffs_LL[dir], gradw, tloww, koeLi[lvl * 3 + dir - 1], lvl, W_L, H_L, edd, tempkoeli, tmC);
+ maxkoeLi[lvl * 3 + dir - 1] = tempkoeli ;
// return convolution KoeLi and maxkoeLi of level 0 1 2 3 and Dir Horiz, Vert, Diag
}
}
@@ -2281,13 +2323,14 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
for (int i = 0; i < 500; i++) {
if (wavblcurve[i] != 0.) {
wavcurvecomp = true;
+ break;
}
}
}
+ std::unique_ptr aft;
#ifdef _OPENMP
- // #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)
+ #pragma omp for schedule(dynamic) collapse(2)
#endif
for (int dir = 1; dir < 4; dir++) {
@@ -2299,85 +2342,37 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float *
float* const* WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl);
ContAllL(koeLi, maxkoeLi[lvl * 3 + dir - 1], true, maxlvl, labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L, skip, mean, sigma, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, waOpacityCurveSH, ChCurve, Chutili);
- int minWL = min(Wlvl_L, Hlvl_L);
- if(minWL > 180) {
+ if (std::min(Wlvl_L, Hlvl_L) > 180) {
if (wavblcurve && wavcurvecomp && cp.blena) {
// printf("Blur level L\n");
float mea[10];
const float effect = cp.bluwav;
constexpr float offs = 1.f;
- float * beta = new float[Wlvl_L * Hlvl_L];
-
calceffect(lvl, mean, sigma, mea, effect, offs);
-
- 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++;
- }
-
-
+ float lutFactor;
+ const float inVals[] = {0.05f, 0.2f, 0.7f, 1.f, 1.f, 0.8f, 0.6f, 0.4f, 0.2f, 0.1f, 0.01f};
+ const auto meaLut = buildMeaLut(inVals, mea, lutFactor);
+ if (!aft.get()) {
+ aft.reset(new float[Wlvl_L * Hlvl_L]);
}
- 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);
+ //blur level
+ const float klev = wavblcurve[lvl * 55.5f] * 80.f / skip;
+ auto WavL = WavCoeffs_L[dir];
+ boxblur(WavL, aft.get(), klev, Wlvl_L, Hlvl_L, false);
+
+ int co = 0;
+#ifdef __SSE2__
+ const vfloat lutFactorv = F2V(lutFactor);
+ for (; co < Hlvl_L * Wlvl_L - 3; co += 4) {
+ const vfloat valv = LVFU(WavL[co]);
+ STVFU(WavL[co], intp((*meaLut)[vabsf(valv) * lutFactorv], LVFU(aft[co]), valv));
}
-
- float klev = (wavblcurve[lvl * 55.5f]);
-
- //blur level
- klev *= 80.f / skip;
- boxblur(bef, aft, klev, Wlvl_L, Hlvl_L, false);
-
- for (int co = 0; co < Hlvl_L * Wlvl_L; co++) {
- aft[co] = bef[co] * (1.f - beta[co]) + aft[co] * beta[co];
- WavCoeffs_L[dir][co] = aft[co];
+#endif
+ for (; co < Hlvl_L * Wlvl_L; co++) {
+ WavL[co] = intp((*meaLut)[std::fabs(WavL[co]) * lutFactor], aft[co], WavL[co]);
}
-
- delete[] bef;
- delete[] aft;
- delete[] beta;
}
}
}
@@ -2454,7 +2449,7 @@ void ImProcFunctions::WaveletAandBAllAB(wavelet_decomposition& WaveletCoeffs_a,
void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float **varchrom, wavelet_decomposition& WaveletCoeffs_ab, const Wavblcurve & wavblcurve, const WavOpacityCurveW & waOpacityCurveW,
struct cont_params &cp, const bool useChannelA, int skip, float *meanab, float *sigmaab)
{
-
+BENCHFUN
int maxlvl = WaveletCoeffs_ab.maxlevel();
int W_L = WaveletCoeffs_ab.level_W(0);
int H_L = WaveletCoeffs_ab.level_H(0);
@@ -2594,10 +2589,12 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float
for (int i = 0; i < 500; i++) {
if (wavblcurve[i] != 0.) {
wavcurvecomp = true;
+ break;
}
}
}
+ std::unique_ptr aft;
#ifdef _OPENMP
#pragma omp for schedule(dynamic) collapse(2)
#endif
@@ -2610,92 +2607,49 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float
float* const* 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, meanab, sigmaab);
- int minWL = min(Wlvl_ab, Hlvl_ab);
- if(minWL > 180) {
+ if(std::min(Wlvl_ab, Hlvl_ab) > 180) {
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;
- }
-
+ const float effect = cp.bluwav;
+ constexpr float offs = 1.f;
calceffect(lvl, meanab, sigmaab, mea, effect, offs);
+ float lutFactor;
+ const float inVals[] = {0.05f, 0.2f, 0.7f, 1.f, 1.f, 0.8f, 0.6f, 0.4f, 0.2f, 0.1f, 0.00f};
+ const auto meaLut = buildMeaLut(inVals, mea, lutFactor);
- 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;
- }
-
-
+ if (!aft.get()) {
+ aft.reset(new float[Wlvl_ab * Hlvl_ab]);
}
- klev = (wavblcurve[lvl * 55.5f]);
+ //blur level
+ const float klev = wavblcurve[lvl * 55.5f] * 80.f / skip;
+ boxblur(WavCoeffs_ab[dir], aft.get(), klev, Wlvl_ab, Hlvl_ab, false);
- klev *= cp.chrwav * 80.f / skip;
-
- boxblur(bef, aft, klev, Wlvl_ab, Hlvl_ab, false);
-
- for (int co = 0; co < Hlvl_ab * Wlvl_ab; co++) {
- aft[co] = bef[co] * (1.f - beta[co]) + aft[co] * beta[co];
- WavCoeffs_ab[dir][co] = aft[co];
+ auto WavAb = WavCoeffs_ab[dir];
+ int co = 0;
+#ifdef __SSE2__
+ const vfloat lutFactorv = F2V(lutFactor);
+ for (; co < Hlvl_ab * Wlvl_ab - 3; co += 4) {
+ const vfloat valv = LVFU(WavAb[co]);
+ STVFU(WavAb[co], intp((*meaLut)[vabsf(valv) * lutFactorv], LVFU(aft[co]), valv));
+ }
+#endif
+ for (; co < Hlvl_ab * Wlvl_ab; co++) {
+ WavAb[co] = intp((*meaLut)[std::fabs(WavAb[co]) * lutFactor], aft[co], WavAb[co]);
}
-
- delete[] bef;
- delete[] aft;
- delete[] beta;
}
}
-
}
}
-
-
}
}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-//void ImProcFunctions::calckoe(float ** WavCoeffs_LL, const cont_params& cp, float *koeLi[12], int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC)
-void ImProcFunctions::calckoe (const float* const* WavCoeffs_LL, float gradw, float tloww, float *koeLi[12], int level, int dir, int W_L, int H_L, float edd, float &maxkoeLi, float **tmC)
+void ImProcFunctions::calckoe (const float* WavCoeffs, float gradw, float tloww, float *koeLi, int level, int W_L, int H_L, float edd, float &maxkoeLi, float **tmC, bool multiThread)
{
- int borderL = 2;
-
- if (tloww < 30.f) {
- borderL = 1;
+ const int borderL = tloww < 75.f ? 1 : 2;
+ if (tloww < 75.f) {
// I calculate coefficients with r size matrix 3x3 r=1 ; 5x5 r=2; 7x7 r=3
/*
float k[2*r][2*r];
@@ -2707,124 +2661,144 @@ void ImProcFunctions::calckoe (const float* const* WavCoeffs_LL, float gradw, fl
//I could also use Gauss.h for 3x3
// If necessary I can put a 7x7 matrix
*/
- for (int i = 1; i < H_L - 1; i++) { //sigma=0.55
- for (int j = 1; j < W_L - 1; j++) {
- tmC[i][j] = (8.94f * WavCoeffs_LL[dir][i * W_L + j] + 1.71f * (WavCoeffs_LL[dir][(i - 1) * W_L + j] + 1.71f * WavCoeffs_LL[dir][(i + 1) * W_L + j]
- + 1.71f * WavCoeffs_LL[dir][i * W_L + j + 1] + 1.71f * WavCoeffs_LL[dir][i * W_L + j - 1]) + 0.33f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1]
- + 0.33f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 0.33f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 0.33f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1]) * 0.0584795f;
- // apply to each direction Wavelet level : horizontal / vertiacle / diagonal
-
-
- }
+ float c0, c1, c2, mult;
+ if (tloww < 30.f) { //sigma=0.55
+ c0 = 8.94f;
+ c1 = 1.71f;
+ c2 = 0.33f;
+ mult = 0.0584795f;
+ } else if (tloww < 50.f) { //sigma=0.85
+ c0 = 4.0091f;
+ c1 = 2.0068f;
+ c2 = 1.0045f;
+ mult = 0.062288f;
+ } else { //sigma=1.1
+ c0 = 3.025f;
+ c1 = 2.001f;
+ c2 = 1.323f;
+ mult = 0.06127f;
}
- } else if (tloww < 50.f) {
- borderL = 1;
-
- for (int i = 1; i < H_L - 1; i++) { //sigma=0.85
- for (int j = 1; j < W_L - 1; j++) {
- tmC[i][j] = (4.0091f * WavCoeffs_LL[dir][i * W_L + j] + 2.0068f * (WavCoeffs_LL[dir][(i - 1) * W_L + j] + 2.0068f * WavCoeffs_LL[dir][(i + 1) * W_L + j]
- + 2.0068f * WavCoeffs_LL[dir][i * W_L + j + 1] + 2.0068f * WavCoeffs_LL[dir][i * W_L + j - 1]) + 1.0045f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1]
- + 1.0045f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 1.0045f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 1.0045f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1]) * 0.062288f;
- // apply to each direction Wavelet level : horizontal / vertiacle / diagonal
-
-
- }
- }
- }
-
-
- else if (tloww < 75.f) {
- borderL = 1;
-
+ c0 *= mult;
+ c1 *= mult;
+ c2 *= mult;
+#ifdef _OPENMP
+ #pragma omp parallel for if(multiThread)
+#endif
for (int i = 1; i < H_L - 1; i++) {
- for (int j = 1; j < W_L - 1; j++) { //sigma=1.1
- tmC[i][j] = (3.025f * WavCoeffs_LL[dir][i * W_L + j] + 2.001f * (WavCoeffs_LL[dir][(i - 1) * W_L + j] + 2.001f * WavCoeffs_LL[dir][(i + 1) * W_L + j]
- + 2.001f * WavCoeffs_LL[dir][i * W_L + j + 1] + 2.001f * WavCoeffs_LL[dir][i * W_L + j - 1]) + 1.323f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1]
- + 1.323f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 1.323f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 1.323f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1]) * 0.06127f;
+ for (int j = 1; j < W_L - 1; j++) {
+ tmC[i][j] = c0 * WavCoeffs[i * W_L + j] +
+ c1 * ((WavCoeffs[(i - 1) * W_L + j] + WavCoeffs[(i + 1) * W_L + j]) + (WavCoeffs[i * W_L + j + 1] + WavCoeffs[i * W_L + j - 1])) +
+ c2 * ((WavCoeffs[(i - 1) * W_L + j - 1] + WavCoeffs[(i - 1) * W_L + j + 1]) + (WavCoeffs[(i + 1) * W_L + j - 1] + WavCoeffs[(i + 1) * W_L + j + 1]));
}
}
- }
-
- else if (tloww >= 75.f) {
- borderL = 2;
-
+ } else {
if (level > 1) { // do not activate 5x5 if level 0 or 1
+ // Gaussian 1.1
+ // 0.5 2 3 2 0.5
+ // 2 7 10 7 2
+ // 3 10 15 10 3
+ // 2 7 10 7 2
+ // 0.5 2 3 2 0.5
+ // divi 113
+ //Gaussian 1.4
+ // 2 4 5 4 2
+ // 4 9 12 9 4
+ // 5 12 15 12 5
+ // 4 9 12 9 4
+ // 2 4 5 4 2
+ // divi 159
+ float c0, c1, c2, c3, c4, c5, mult;
+ if (tloww < 85.f) { //sigma=1.1
+ c0 = 15.f;
+ c1 = 10.f;
+ c2 = 7.f;
+ c3 = 3.f;
+ c4 = 2.f;
+ c5 = 0.5f;
+ mult = 0.0088495f;
+ } else { //sigma=1.4
+ c0 = 15.f;
+ c1 = 12.f;
+ c2 = 9.f;
+ c3 = 5.f;
+ c4 = 4.f;
+ c5 = 2.f;
+ mult = 0.0062893f;
+ }
+ c0 *= mult;
+ c1 *= mult;
+ c2 *= mult;
+ c3 *= mult;
+ c4 *= mult;
+ c5 *= mult;
+#ifdef _OPENMP
+ #pragma omp parallel for if(multiThread)
+#endif
for (int i = 2; i < H_L - 2; i++) {
for (int j = 2; j < W_L - 2; j++) {
- // Gaussian 1.1
- // 0.5 2 3 2 0.5
- // 2 7 10 7 2
- // 3 10 15 10 3
- // 2 7 10 7 2
- // 0.5 2 3 2 0.5
- // divi 113
- //Gaussian 1.4
- // 2 4 5 4 2
- // 4 9 12 9 4
- // 5 12 15 12 5
- // 4 9 12 9 4
- // 2 4 5 4 2
- // divi 159
- if (tloww < 85.f) { //sigma=1.1
- tmC[i][j] = (15.f * WavCoeffs_LL[dir][i * W_L + j] + 10.f * WavCoeffs_LL[dir][(i - 1) * W_L + j] + 10.f * WavCoeffs_LL[dir][(i + 1) * W_L + j]
- + 10.f * WavCoeffs_LL[dir][i * W_L + j + 1] + 10.f * WavCoeffs_LL[dir][i * W_L + j - 1] + 7.f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1]
- + 7.f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 7.f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 7.f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1]
- + 3.f * WavCoeffs_LL[dir][(i - 2) * W_L + j] + 3.f * WavCoeffs_LL[dir][(i + 2) * W_L + j] + 3.f * WavCoeffs_LL[dir][i * W_L + j - 2] + 3.f * WavCoeffs_LL[dir][i * W_L + j + 2]
- + 2.f * WavCoeffs_LL[dir][(i - 2) * W_L + j - 1] + 2.f * WavCoeffs_LL[dir][(i - 2) * W_L + j + 1] + 2.f * WavCoeffs_LL[dir][(i + 2) * W_L + j + 1] + 2.f * WavCoeffs_LL[dir][(i + 2) * W_L + j - 1]
- + 2.f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 2] + 2.f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 2] + 2.f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 2] + 2.f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 2]
- + 0.5f * WavCoeffs_LL[dir][(i - 2) * W_L + j - 2] + 0.5f * WavCoeffs_LL[dir][(i - 2) * W_L + j + 2] + 0.5f * WavCoeffs_LL[dir][(i + 2) * W_L + j - 2] + 0.5f * WavCoeffs_LL[dir][(i + 2) * W_L + j + 2]
- ) * 0.0088495f;
-
- }
-
- else {//sigma=1.4
- tmC[i][j] = (15.f * WavCoeffs_LL[dir][i * W_L + j] + 12.f * WavCoeffs_LL[dir][(i - 1) * W_L + j] + 12.f * WavCoeffs_LL[dir][(i + 1) * W_L + j]
- + 12.f * WavCoeffs_LL[dir][i * W_L + j + 1] + 12.f * WavCoeffs_LL[dir][i * W_L + j - 1] + 9.f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1]
- + 9.f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 9.f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 9.f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1]
- + 5.f * WavCoeffs_LL[dir][(i - 2) * W_L + j] + 5.f * WavCoeffs_LL[dir][(i + 2) * W_L + j] + 5.f * WavCoeffs_LL[dir][i * W_L + j - 2] + 5.f * WavCoeffs_LL[dir][i * W_L + j + 2]
- + 4.f * WavCoeffs_LL[dir][(i - 2) * W_L + j - 1] + 4.f * WavCoeffs_LL[dir][(i - 2) * W_L + j + 1] + 4.f * WavCoeffs_LL[dir][(i + 2) * W_L + j + 1] + 4.f * WavCoeffs_LL[dir][(i + 2) * W_L + j - 1]
- + 4.f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 2] + 4.f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 2] + 4.f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 2] + 4.f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 2]
- + 2.f * WavCoeffs_LL[dir][(i - 2) * W_L + j - 2] + 2.f * WavCoeffs_LL[dir][(i - 2) * W_L + j + 2] + 2.f * WavCoeffs_LL[dir][(i + 2) * W_L + j - 2] + 2.f * WavCoeffs_LL[dir][(i + 2) * W_L + j + 2]
- ) * 0.0062893f;
- }
-
-
- // apply to each direction Wavelet level : horizontal / vertiacle / diagonal
+ tmC[i][j] = c0 * WavCoeffs[i * W_L + j] +
+ c1 * ((WavCoeffs[(i - 1) * W_L + j] + WavCoeffs[(i + 1) * W_L + j]) + (WavCoeffs[i * W_L + j + 1] + WavCoeffs[i * W_L + j - 1])) +
+ c2 * ((WavCoeffs[(i - 1) * W_L + j - 1] + WavCoeffs[(i - 1) * W_L + j + 1]) + (WavCoeffs[(i + 1) * W_L + j - 1] + WavCoeffs[(i + 1) * W_L + j + 1])) +
+ c3 * ((WavCoeffs[(i - 2) * W_L + j] + WavCoeffs[(i + 2) * W_L + j]) + (WavCoeffs[i * W_L + j - 2] + WavCoeffs[i * W_L + j + 2])) +
+ c4 * ((WavCoeffs[(i - 2) * W_L + j - 1] + WavCoeffs[(i - 2) * W_L + j + 1]) + (WavCoeffs[(i + 2) * W_L + j + 1] + WavCoeffs[(i + 2) * W_L + j - 1]) +
+ (WavCoeffs[(i - 1) * W_L + j - 2] + WavCoeffs[(i - 1) * W_L + j + 2]) + (WavCoeffs[(i + 1) * W_L + j + 2] + WavCoeffs[(i + 1) * W_L + j - 2])) +
+ c5 * ((WavCoeffs[(i - 2) * W_L + j - 2] + WavCoeffs[(i - 2) * W_L + j + 2]) + (WavCoeffs[(i + 2) * W_L + j - 2] + WavCoeffs[(i + 2) * W_L + j + 2]));
}
}
+ } else {
+#ifdef _OPENMP
+ #pragma omp parallel for if(multiThread)
+#endif
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ koeLi[i * W_L + j] = 0.f;
+ }
+ }
+ return;
}
-
}
- float thr = 40.f; //avoid artifact eg. noise...to test
- float thr2 = 1.5f * edd; //edd can be modified in option ed_detect
- thr2 += gradw / 30.f; //to test
- float diffFactor = (gradw / 100.f);
-
- for (int i = 0; i < H_L; i++) {
+ // fill borders with 1.f
+ int ii = 0;
+ for (; ii < borderL; ii++) {
for (int j = 0; j < W_L; j++) {
- koeLi[level * 3 + dir - 1][i * W_L + j] = 1.f;
+ koeLi[ii * W_L + j] = 1.f;
}
}
+ for (; ii < H_L - borderL; ii++) {
+ for (int j = 0; j < borderL; j++) {
+ koeLi[ii * W_L + j] = 1.f;
+ }
+ for (int j = W_L - borderL; j < W_L; j++) {
+ koeLi[ii * W_L + j] = 1.f;
+ }
+ }
+ for (; ii < H_L; ii++) {
+ for (int j = 0; j < W_L; j++) {
+ koeLi[ii * W_L + j] = 1.f;
+ }
+ }
+
+ constexpr float thr = 40.f; //avoid artifact eg. noise...to test
+ const float thr2 = 1.5f * edd + gradw / 30.f; //edd can be modified in option ed_detect
+ const float diffFactor = gradw / 100.f;
for (int i = borderL; i < H_L - borderL; i++) {
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 = 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
+ float temp = rtengine::max(std::fabs(WavCoeffs[i * W_L + j]), thr);
+ koeLi[i * W_L + j] = rtengine::min(thr2, std::fabs(tmC[i][j] / temp)); // limit maxi
//it will be more complicated to calculate both Wh and Wv, but we have also Wd==> pseudo Lipschitz
- if (koeLi[level * 3 + dir - 1][i * W_L + j] > maxkoeLi) {
- maxkoeLi = koeLi[level * 3 + dir - 1][i * W_L + j];
+ if (koeLi[i * W_L + j] > maxkoeLi) {
+ maxkoeLi = koeLi[i * W_L + j];
}
-
- float diff = maxkoeLi - koeLi[level * 3 + dir - 1][i * W_L + j];
+ float diff = maxkoeLi - koeLi[i * W_L + j];
diff *= diffFactor;
- koeLi[level * 3 + dir - 1][i * W_L + j] = maxkoeLi - diff;
+ koeLi[i * W_L + j] = maxkoeLi - diff;
}
}
-
}
void ImProcFunctions::finalContAllL(float* const* WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, const cont_params &cp,
@@ -2833,13 +2807,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)
@@ -3110,7 +3084,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;
@@ -3141,10 +3114,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;
@@ -3152,15 +3128,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
@@ -3168,15 +3143,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
}
}
@@ -3210,13 +3186,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;
@@ -3432,32 +3408,26 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz,
}
}
-
if (!cp.link && cp.noiseena) { //used both with denoise 1 2 3
float refine = 0.f;
+ if (level == 0) {
+ refine = cp.lev0s / 40.f;
+ } else if (level == 1) {
+ refine = cp.lev1s / 40.f;
+ } else if (level == 2) {
+ refine = cp.lev2s / 40.f;
+ } else if (level == 3) {
+ refine = cp.lev3s / 40.f;
+ }
- for (int i = 0; i < W_L * H_L; i++) {
- if (level == 0) {
- refine = cp.lev0s / 40.f;
+ if (refine != 0.f) {
+ refine += 1.f;
+ for (int i = 0; i < W_L * H_L; i++) {
+ WavCoeffs_L[dir][i] *= refine;
}
-
- if (level == 1) {
- refine = cp.lev1s / 40.f;
- }
-
- if (level == 2) {
- refine = cp.lev2s / 40.f;
- }
-
- if (level == 3) {
- refine = cp.lev3s / 40.f;
- }
-
- WavCoeffs_L[dir][i] *= (1.f + refine);
}
}
-
float cpMul = cp.mul[level];
if (cpMul != 0.f && cp.contena) { // cpMul == 0.f means all will be multiplied by 1.f, so we can skip this
diff --git a/rtengine/lmmse_demosaic.cc b/rtengine/lmmse_demosaic.cc
index 5c4ddffed..c2d5bffbf 100644
--- a/rtengine/lmmse_demosaic.cc
+++ b/rtengine/lmmse_demosaic.cc
@@ -41,6 +41,18 @@ namespace rtengine
// TODO Tiles to reduce memory consumption
void RawImageSource::lmmse_interpolate_omp(int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations)
{
+ // Test for RGB cfa
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ if (FC(i, j) == 3) {
+ // avoid crash
+ std::cout << "lmmse_interpolate_omp supports only RGB Colour filter arrays. Falling back to igv_interpolate" << std::endl;
+ igv_interpolate(winw, winh);
+ return;
+ }
+ }
+ }
+
const int width = winw, height = winh;
const int ba = 10;
const int rr1 = height + 2 * ba;
diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc
index 2e98b7b22..ff7be3e40 100644
--- a/rtengine/pixelshift.cc
+++ b/rtengine/pixelshift.cc
@@ -283,20 +283,20 @@ void calcFrameBrightnessFactor(unsigned int frame, uint32_t datalen, LUTu *histo
{
float medians[4];
- for(int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; ++i) {
//find median of histogram
- uint32_t median = 0, count = 0;
+ uint32_t lmedian = 0, count = 0;
- while(count < datalen / 2) {
- count += (*histo[i])[median];
- ++median;
+ while (count < datalen / 2) {
+ count += (*histo[i])[lmedian];
+ ++lmedian;
}
- const float weight = (count - datalen / 2.f) / (*histo[i])[median - 1];
- medians[i] = rtengine::intp(weight, (float)(median - 2), (float)(median - 1));
+ const float weight = (count - datalen / 2.f) / (*histo[i])[lmedian - 1];
+ medians[i] = rtengine::intp(weight, (float)(lmedian - 2), (float)(lmedian - 1));
}
- for(int i = 0; i < 4; ++i) {
+ for (int i = 0; i < 4; ++i) {
brightnessFactor[i] = medians[frame] / medians[i];
}
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index efe793696..b64748d22 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -686,7 +686,7 @@ enum ProcEventCode {
EvLocallabcontresid = 660,
Evlocallabnoiselumf0 = 661,
Evlocallabnoiselumf2 = 662,
- EvLocallabblurcbdl = 663,
+ //EvLocallabblurcbdl = 663,
Evlocallabblendmaskcb = 664,
Evlocallabradmaskcb = 665,
Evlocallabchromaskcb = 666,
@@ -946,7 +946,7 @@ enum ProcEventCode {
Evlocallabsigmalc2 = 920,
Evlocallabblwh = 921,
EvlocallabcomplexityWithRefresh = 922,
- EvlocallabcomplexityWithoutRefresh = 923,
+ // EvlocallabcomplexityWithoutRefresh = 923,
EvLocallabSpotcolorscope = 924,
EvlocallabshowmasktypMethod = 925,
Evlocallabshadmaskblsha = 926,
@@ -978,7 +978,7 @@ enum ProcEventCode {
Evlocallabblendmaskab = 952,
EvLocallabSpotprevMethod = 953,
Evlocallabactiv = 954,
-
+ EvlocallabCHshape = 955,
NUMOFEVENTS
};
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index b7396b165..d7ead7513 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -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
@@ -2652,7 +2656,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
// Color & Light
visicolor(false),
expcolor(false),
- complexcolor(0),
+ complexcolor(2),
curvactiv(false),
lightness(0),
contrast(0),
@@ -2777,6 +2781,33 @@ LocallabParams::LocallabSpot::LocallabSpot() :
0.35,
0.35
},
+ CHcurve{
+ static_cast(FCT_MinMaxCPoints),
+ 0.0,
+ 0.50,
+ 0.35,
+ 0.35,
+ 0.166,
+ 0.50,
+ 0.35,
+ 0.35,
+ 0.333,
+ 0.50,
+ 0.35,
+ 0.35,
+ 0.50,
+ 0.50,
+ 0.35,
+ 0.35,
+ 0.666,
+ 0.50,
+ 0.35,
+ 0.35,
+ 0.833,
+ 0.50,
+ 0.35,
+ 0.35
+ },
invers(false),
special(false),
toolcol(true),
@@ -3262,7 +3293,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
scaltm(1.0),
rewei(0),
satur(0.),
- sensitm(30),
+ sensitm(60),
softradiustm(0.0),
amount(95.),
equiltm(true),
@@ -3659,7 +3690,6 @@ LocallabParams::LocallabSpot::LocallabSpot() :
sensicb(60),
clarityml(0.1),
contresid(0),
- blurcbdl(0.),
softradiuscb(0.0),
enacbMask(false),
CCmaskcbcurve{
@@ -3926,6 +3956,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& rgbcurve == other.rgbcurve
&& LHcurve == other.LHcurve
&& HHcurve == other.HHcurve
+ && CHcurve == other.CHcurve
&& invers == other.invers
&& special == other.special
&& toolcol == other.toolcol
@@ -4281,7 +4312,6 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& sensicb == other.sensicb
&& clarityml == other.clarityml
&& contresid == other.contresid
- && blurcbdl == other.blurcbdl
&& softradiuscb == other.softradiuscb
&& enacbMask == other.enacbMask
&& CCmaskcbcurve == other.CCmaskcbcurve
@@ -5002,6 +5032,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);
@@ -5451,6 +5482,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->rgbcurve, "Locallab", "RGBCurve_" + index_str, spot.rgbcurve, keyFile);
saveToKeyfile(!pedited || spot_edited->LHcurve, "Locallab", "LHCurve_" + index_str, spot.LHcurve, keyFile);
saveToKeyfile(!pedited || spot_edited->HHcurve, "Locallab", "HHCurve_" + index_str, spot.HHcurve, keyFile);
+ saveToKeyfile(!pedited || spot_edited->CHcurve, "Locallab", "CHCurve_" + index_str, spot.CHcurve, keyFile);
saveToKeyfile(!pedited || spot_edited->invers, "Locallab", "Invers_" + index_str, spot.invers, keyFile);
saveToKeyfile(!pedited || spot_edited->special, "Locallab", "Special_" + index_str, spot.special, keyFile);
saveToKeyfile(!pedited || spot_edited->toolcol, "Locallab", "Toolcol_" + index_str, spot.toolcol, keyFile);
@@ -5807,7 +5839,6 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->sensicb, "Locallab", "Sensicb_" + index_str, spot.sensicb, keyFile);
saveToKeyfile(!pedited || spot_edited->clarityml, "Locallab", "Clarityml_" + index_str, spot.clarityml, keyFile);
saveToKeyfile(!pedited || spot_edited->contresid, "Locallab", "Contresid_" + index_str, spot.contresid, keyFile);
- saveToKeyfile(!pedited || spot_edited->blurcbdl, "Locallab", "Blurcbdl_" + index_str, spot.blurcbdl, keyFile);
saveToKeyfile(!pedited || spot_edited->softradiuscb, "Locallab", "Softradiuscb_" + index_str, spot.softradiuscb, keyFile);
saveToKeyfile(!pedited || spot_edited->enacbMask, "Locallab", "EnacbMask_" + index_str, spot.enacbMask, keyFile);
saveToKeyfile(!pedited || spot_edited->CCmaskcbcurve, "Locallab", "CCmaskcbCurve_" + index_str, spot.CCmaskcbcurve, keyFile);
@@ -5965,6 +5996,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);
@@ -6471,6 +6503,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);
@@ -7122,6 +7155,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "RGBCurve_" + index_str, pedited, spot.rgbcurve, spotEdited.rgbcurve);
assignFromKeyfile(keyFile, "Locallab", "LHCurve_" + index_str, pedited, spot.LHcurve, spotEdited.LHcurve);
assignFromKeyfile(keyFile, "Locallab", "HHCurve_" + index_str, pedited, spot.HHcurve, spotEdited.HHcurve);
+ assignFromKeyfile(keyFile, "Locallab", "CHCurve_" + index_str, pedited, spot.CHcurve, spotEdited.CHcurve);
assignFromKeyfile(keyFile, "Locallab", "Invers_" + index_str, pedited, spot.invers, spotEdited.invers);
assignFromKeyfile(keyFile, "Locallab", "Special_" + index_str, pedited, spot.special, spotEdited.special);
assignFromKeyfile(keyFile, "Locallab", "Toolcol_" + index_str, pedited, spot.toolcol, spotEdited.toolcol);
@@ -7550,7 +7584,6 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Sensicb_" + index_str, pedited, spot.sensicb, spotEdited.sensicb);
assignFromKeyfile(keyFile, "Locallab", "Clarityml_" + index_str, pedited, spot.clarityml, spotEdited.clarityml);
assignFromKeyfile(keyFile, "Locallab", "Contresid_" + index_str, pedited, spot.contresid, spotEdited.contresid);
- assignFromKeyfile(keyFile, "Locallab", "Blurcbdl_" + index_str, pedited, spot.blurcbdl, spotEdited.blurcbdl);
assignFromKeyfile(keyFile, "Locallab", "Softradiuscb_" + index_str, pedited, spot.softradiuscb, spotEdited.softradiuscb);
assignFromKeyfile(keyFile, "Locallab", "EnacbMask_" + index_str, pedited, spot.enacbMask, spotEdited.enacbMask);
assignFromKeyfile(keyFile, "Locallab", "CCmaskcbCurve_" + index_str, pedited, spot.CCmaskcbcurve, spotEdited.CCmaskcbcurve);
@@ -7835,6 +7868,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);
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 42873e8e8..0e70e8821 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -50,6 +50,7 @@ class LocretigainCurve;
class LocretigainCurverab;
class LocLHCurve;
class LocHHCurve;
+class LocCHCurve;
class LocLLmaskCurve;
class LocCCmaskCurve;
class LocHHmaskCurve;
@@ -335,6 +336,7 @@ struct RetinexParams {
int stonalwidth;
int radius;
+ Glib::ustring complexmethod;
Glib::ustring retinexMethod;
Glib::ustring retinexcolorspace;
Glib::ustring gammaretinex;
@@ -1056,6 +1058,7 @@ struct LocallabParams {
std::vector rgbcurve;
std::vector LHcurve;
std::vector HHcurve;
+ std::vector CHcurve;
bool invers;
bool special;
bool toolcol;
@@ -1395,7 +1398,6 @@ struct LocallabParams {
int sensicb;
double clarityml;
int contresid;
- double blurcbdl;
double softradiuscb;
bool enacbMask;
std::vector CCmaskcbcurve;
@@ -1789,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;
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index 2c7ddd36a..8bfcaa5ab 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1720,10 +1720,8 @@ void RawImageSource::retinexPrepareBuffers(const ColorManagementParams& cmp, con
std::swap(pwr, gamm);
}
- int mode = 0;
- Color::calcGamma(pwr, ts, mode, g_a); // call to calcGamma with selected gamma and slope
+ Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
- // printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4);
double start;
double add;
@@ -1951,12 +1949,12 @@ void RawImageSource::retinexPrepareCurves(const RetinexParams &retinexParams, LU
useHsl = (retinexParams.retinexcolorspace == "HSLLOG" || retinexParams.retinexcolorspace == "HSLLIN");
if (useHsl) {
- CurveFactory::curveDehaContL (retinexcontlutili, retinexParams.cdHcurve, cdcurve, 1, lhist16RETI, histLRETI);
+ retinexcontlutili = CurveFactory::diagonalCurve2Lut(retinexParams.cdHcurve, cdcurve, 1, lhist16RETI, histLRETI);
} else {
- CurveFactory::curveDehaContL (retinexcontlutili, retinexParams.cdcurve, cdcurve, 1, lhist16RETI, histLRETI);
+ retinexcontlutili = CurveFactory::diagonalCurve2Lut(retinexParams.cdcurve, cdcurve, 1, lhist16RETI, histLRETI);
}
- CurveFactory::mapcurve(mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI);
+ mapcontlutili = CurveFactory::diagonalCurve2Lut(retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI);
mapcurve *= 0.5f;
retinexParams.getCurves(retinextransmissionCurve, retinexgaintransmissionCurve);
}
@@ -1987,13 +1985,12 @@ void RawImageSource::retinex(const ColorManagementParams& cmp, const RetinexPara
double gamm = deh.gam;
double gamm2 = gamm;
double ts = deh.slope;
- int mode = 0;
if (gamm2 < 1.) {
std::swap(pwr, gamm);
}
- Color::calcGamma(pwr, ts, mode, g_a); // call to calcGamma with selected gamma and slope
+ Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
double mul = 1. + g_a[4];
double add;
diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h
index 79e52e7a7..7b1b4197c 100644
--- a/rtengine/rawimagesource.h
+++ b/rtengine/rawimagesource.h
@@ -247,7 +247,7 @@ protected:
double cared,
double cablue,
bool avoidColourshift,
- const array2D &rawData,
+ array2D &rawData,
double* fitParamsTransfer,
bool fitParamsIn,
bool fitParamsOut,
diff --git a/rtengine/rcd_demosaic.cc b/rtengine/rcd_demosaic.cc
index 5a86aec40..6587d3930 100644
--- a/rtengine/rcd_demosaic.cc
+++ b/rtengine/rcd_demosaic.cc
@@ -48,6 +48,18 @@ namespace rtengine
// Tiled version by Ingo Weyrich (heckflosse67@gmx.de)
void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
{
+ // Test for RGB cfa
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ if (FC(i, j) == 3) {
+ // avoid crash
+ std::cout << "rcd_demosaic supports only RGB Colour filter arrays. Falling back to igv_interpolate" << std::endl;
+ igv_interpolate(W, H);
+ return;
+ }
+ }
+ }
+
std::unique_ptr stop;
if (measure) {
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index b7e70fda3..1be81a7de 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -690,7 +690,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvLocallabcontresid
LUMINANCECURVE, // Evlocallabnoiselumf0
LUMINANCECURVE, // Evlocallabnoiselumf2
- LUMINANCECURVE, // Evlocallabblurcbdl
+ 0, // Evlocallabblurcbdl
LUMINANCECURVE, // Evlocallabblendmaskcb
LUMINANCECURVE, // Evlocallabradmaskcb
LUMINANCECURVE, // Evlocallabchromaskcb
@@ -950,7 +950,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // Evlocallabsigmalc2
LUMINANCECURVE, // Evlocallabblwh
LUMINANCECURVE, // EvlocallabcomplexityWithRefresh
- M_VOID, // EvlocallabcomplexityWithoutRefresh
+ 0, // can be reused
LUMINANCECURVE, // EvLocallabSpotcolorscope
LUMINANCECURVE, // EvlocallabshowmasktypMethod
LUMINANCECURVE, // Evlocallabshadmaskblsha
@@ -981,8 +981,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // Evlocallabsoftradiusmask
LUMINANCECURVE, // Evlocallabblendmaskab
LUMINANCECURVE, // EvLocallabSpotprevMethod
- LUMINANCECURVE // Evlocallabactiv
-
+ LUMINANCECURVE, // Evlocallabactiv
+ LUMINANCECURVE, // EvlocallabCHshape
};
diff --git a/rtengine/rescale.h b/rtengine/rescale.h
index 2138cd8e8..3126a7c58 100644
--- a/rtengine/rescale.h
+++ b/rtengine/rescale.h
@@ -31,8 +31,8 @@ namespace rtengine
inline float getBilinearValue(const array2D &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 &src, float x, float y)
inline void rescaleBilinear(const array2D &src, array2D &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 &src, array2D &dst, bool
inline void rescaleNearest(const array2D &src, array2D &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)
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 4ebb95842..357ad3a69 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -1327,10 +1327,10 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
params.colorToning.getCurves (ctColorCurve, ctOpacityCurve, wp, opautili);
clToningcurve (65536);
- CurveFactory::curveToning (params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16);
+ CurveFactory::diagonalCurve2Lut (params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16);
cl2Toningcurve (65536);
- CurveFactory::curveToning (params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16);
+ CurveFactory::diagonalCurve2Lut (params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16);
}
if (params.blackwhite.enabled) {
@@ -1406,8 +1406,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve,
hist16, lumacurve, dummy, 16, utili);
- bool clcutili;
- CurveFactory::curveCL (clcutili, params.labCurve.clcurve, clcurve, 16);
+ const bool clcutili = CurveFactory::diagonalCurve2Lut(params.labCurve.clcurve, clcurve, 16);
bool autili, butili, ccutili, cclutili;
CurveFactory::complexsgnCurve (autili, butili, ccutili, cclutili, params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve,
diff --git a/rtengine/settings.h b/rtengine/settings.h
index fde6fa132..0fb4996df 100644
--- a/rtengine/settings.h
+++ b/rtengine/settings.h
@@ -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 {
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 8eae9daba..7b8575635 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -965,9 +965,9 @@ private:
};
params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, opautili);
clToningcurve(65536, 0);
- CurveFactory::curveToning(params.colorToning.clcurve, clToningcurve, 1);
+ CurveFactory::diagonalCurve2Lut(params.colorToning.clcurve, clToningcurve, 1);
cl2Toningcurve(65536, 0);
- CurveFactory::curveToning(params.colorToning.cl2curve, cl2Toningcurve, 1);
+ CurveFactory::diagonalCurve2Lut(params.colorToning.cl2curve, cl2Toningcurve, 1);
}
labView = new LabImage(fw, fh);
@@ -1070,8 +1070,7 @@ private:
bool utili;
CurveFactory::complexLCurve(params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, hist16, lumacurve, dummy, 1, utili);
- bool clcutili;
- CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, 1);
+ const bool clcutili = CurveFactory::diagonalCurve2Lut(params.labCurve.clcurve, clcurve, 1);
bool ccutili, cclutili;
CurveFactory::complexsgnCurve(autili, butili, ccutili, cclutili, params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve,
@@ -1087,6 +1086,7 @@ private:
LocretitransCurve locRETtransCurve;
LocLHCurve loclhCurve;
LocHHCurve lochhCurve;
+ LocCHCurve locchCurve;
LocCCmaskCurve locccmasCurve;
LocLLmaskCurve locllmasCurve;
LocHHmaskCurve lochhmasCurve;
@@ -1165,6 +1165,7 @@ private:
locRETtransCurve.Set(params.locallab.spots.at(sp).localTtranscurve);
const bool LHutili = loclhCurve.Set(params.locallab.spots.at(sp).LHcurve);
const bool HHutili = lochhCurve.Set(params.locallab.spots.at(sp).HHcurve);
+ const bool CHutili = locchCurve.Set(params.locallab.spots.at(sp).CHcurve);
const bool lcmasutili = locccmasCurve.Set(params.locallab.spots.at(sp).CCmaskcurve);
const bool llmasutili = locllmasCurve.Set(params.locallab.spots.at(sp).LLmaskcurve);
const bool lhmasutili = lochhmasCurve.Set(params.locallab.spots.at(sp).HHmaskcurve);
@@ -1207,22 +1208,22 @@ private:
const bool loccompwavutili = loccompwavCurve.Set(params.locallab.spots.at(sp).loccompwavcurve);
const bool loccomprewavutili = loccomprewavCurve.Set(params.locallab.spots.at(sp).loccomprewavcurve);
const bool locedgwavutili = locedgwavCurve.Set(params.locallab.spots.at(sp).locedgwavcurve);
- const bool locallutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).llcurve, lllocalcurve, 1);
- const bool localclutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).clcurve, cllocalcurve, 1);
- const bool locallcutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).lccurve, lclocalcurve, 1);
- const bool localcutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).cccurve, cclocalcurve, 1);
- const bool localrgbutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).rgbcurve, rgblocalcurve, 1);
- const bool localexutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).excurve, exlocalcurve, 1);
- const bool localmaskutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve, 1);
- const bool localmaskexputili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve, 1);
- const bool localmaskSHutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve, 1);
- const bool localmaskvibutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve, 1);
- const bool localmasktmutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve, 1);
- const bool localmaskretiutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve, 1);
- const bool localmaskcbutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve, 1);
- const bool localmaskblutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve, 1);
- const bool localmasklcutili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve, 1);
- const bool localmask_utili = CurveFactory::curveLocal(params.locallab.spots.at(sp).Lmask_curve, lmasklocal_curve, 1);
+ const bool locallutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).llcurve, lllocalcurve, 1);
+ const bool localclutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).clcurve, cllocalcurve, 1);
+ const bool locallcutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).lccurve, lclocalcurve, 1);
+ const bool localcutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).cccurve, cclocalcurve, 1);
+ const bool localrgbutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).rgbcurve, rgblocalcurve, 1);
+ const bool localexutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).excurve, exlocalcurve, 1);
+ const bool localmaskutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve, 1);
+ const bool localmaskexputili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve, 1);
+ const bool localmaskSHutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve, 1);
+ const bool localmaskvibutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve, 1);
+ const bool localmasktmutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve, 1);
+ const bool localmaskretiutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve, 1);
+ const bool localmaskcbutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve, 1);
+ const bool localmaskblutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve, 1);
+ const bool localmasklcutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve, 1);
+ const bool localmask_utili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmask_curve, lmasklocal_curve, 1);
//provisory
double ecomp = params.locallab.spots.at(sp).expcomp;
@@ -1262,7 +1263,7 @@ private:
lllocalcurve, locallutili,
cllocalcurve, localclutili,
lclocalcurve, locallcutili,
- loclhCurve, lochhCurve,
+ loclhCurve, lochhCurve, locchCurve,
lmasklocalcurve, localmaskutili,
lmaskexplocalcurve, localmaskexputili,
lmaskSHlocalcurve, localmaskSHutili,
@@ -1294,7 +1295,7 @@ private:
locwavCurveden, locwavdenutili,
locedgwavCurve, locedgwavutili,
loclmasCurve_wav,lmasutili_wav,
- LHutili, HHutili, cclocalcurve, localcutili, rgblocalcurve, localrgbutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc,
+ LHutili, HHutili, CHutili, cclocalcurve, localcutili, rgblocalcurve, localrgbutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax);
@@ -1361,9 +1362,6 @@ private:
if ((params.wavelet.enabled)) {
LabImage *unshar = nullptr;
- Glib::ustring provis;
-
- bool wavcontlutili = false;
WaveletParams WaveParams = params.wavelet;
WavCurve wavCLVCurve;
Wavblcurve wavblcurve;
@@ -1392,10 +1390,10 @@ private:
params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
- CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1);
+ CurveFactory::diagonalCurve2Lut(params.wavelet.wavclCurve, wavclCurve, 1);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
- provis = params.wavelet.CLmethod;
+ const Glib::ustring provis = params.wavelet.CLmethod;
params.wavelet.CLmethod = "all";
ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
unshar = new LabImage(*labView, true);
diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc
index 60fbc7b4c..f49fe9c53 100644
--- a/rtengine/tmo_fattal02.cc
+++ b/rtengine/tmo_fattal02.cc
@@ -123,12 +123,12 @@ public:
int getRows() const
{
- return const_cast(*this).height();
+ return const_cast(*this).getHeight();
}
int getCols() const
{
- return const_cast(*this).width();
+ return const_cast(*this).getWidth();
}
float *data()
@@ -1180,7 +1180,6 @@ void ImProcFunctions::ToneMapFattal02(Imagefloat *rgb, const FattalToneMappingPa
scale = (oldMedian == 0.f || newMedian == 0.f) ? 65535.f : (oldMedian / newMedian); // avoid Nan
} else {
- scale = 65535.f;
{
float ratio = 0.f;
int ww, hh;
diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc
index ef456af3a..34cab71d1 100644
--- a/rtengine/vng4_demosaic_RT.cc
+++ b/rtengine/vng4_demosaic_RT.cc
@@ -63,6 +63,18 @@ namespace rtengine
void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &red, array2D &green, array2D &blue)
{
+ // Test for RGB cfa
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ if (FC(i, j) == 3) {
+ // avoid crash
+ std::cout << "vng4_demosaic supports only RGB Colour filter arrays. Falling back to igv_interpolate" << std::endl;
+ igv_interpolate(W, H);
+ return;
+ }
+ }
+ }
+
BENCHFUN
const signed short int *cp, terms[] = {
-2, -2, +0, -1, 0, 0x01, -2, -2, +0, +0, 1, 0x01, -2, -1, -1, +0, 0, 0x01,
diff --git a/rtexif/canonattribs.cc b/rtexif/canonattribs.cc
index a91b7266c..529b2314d 100644
--- a/rtexif/canonattribs.cc
+++ b/rtexif/canonattribs.cc
@@ -917,10 +917,11 @@ public:
{253, "Canon EF 70-200mm f/2.8L IS II USM + 2x"},
{253, "Canon EF 70-200mm f/2.8L IS III USM + 2x"},
{254, "Canon EF 100mm f/2.8L Macro IS USM"},
- {255, "Sigma 24-105mm f/4 DG OS HSM | A or Other Sigma Lens"},
+ {255, "Sigma 24-105mm f/4 DG OS HSM | A or Other Lens"},
{255, "Sigma 180mm f/2.8 EX DG OS HSM APO Macro"},
+ {255, "Tamron SP 70-200mm f/2.8 Di VC USD"},
{368, "Sigma 14-24mm f/2.8 DG HSM | A or other Sigma Lens"},
- {368, "Sigma 20mm f/1.4 DG HSM | A"},
+ {368, "Sigma 35mm f/1.4 DG HSM | A"},
{368, "Sigma 50mm f/1.4 DG HSM | A"},
{368, "Sigma 40mm f/1.4 DG HSM | A"},
{368, "Sigma 60-600mm f/4.5-6.3 DG OS HSM | S"},
@@ -966,13 +967,14 @@ public:
{749, "Tamron 100-400mm f/4.5-6.3 Di VC USD A035E + 2x"},
{750, "Canon EF 35mm f/1.4L II USM or Tamron Lens"},
{750, "Tamron SP 85mm f/1.8 Di VC USD (F016)"},
+ {750, "Tamron SP 45mm f/1.8 Di VC USD (F013)"},
{751, "Canon EF 16-35mm f/2.8L III USM"},
{752, "Canon EF 24-105mm f/4L IS II USM"},
{753, "Canon EF 85mm f/1.4L IS USM"},
{754, "Canon EF 70-200mm f/4L IS II USM"},
{757, "Canon EF 400mm f/2.8L IS III USM"},
{758, "Canon EF 600mm f/4L IS III USM"},
- {1136, "Sigma 24-70mm f/2.8 DG OS HSM | Art 017"},
+ {1136, "Sigma 24-70mm f/2.8 DG OS HSM | A"},
{4142, "Canon EF-S 18-135mm f/3.5-5.6 IS STM"},
{4143, "Canon EF-M 18-55mm f/3.5-5.6 IS STM or Tamron Lens"},
{4143, "Tamron 18-200mm f/3.5-6.3 Di III VC"},
@@ -1901,6 +1903,7 @@ public:
choices[2147484712] = "EOS-1D X Mark III";
choices[2147484722] = "EOS Rebel T7 / 2000D / 1500D / Kiss X90";
choices[2147484723] = "EOS RP";
+ choices[2147484725] = "EOS Rebel T8i / 850D / X10i";
choices[2147484726] = "EOS SL3 / 250D / Kiss X10";
choices[2147484727] = "EOS 90D";
choices[2147484960] = "EOS D2000C";
diff --git a/rtexif/nikonattribs.cc b/rtexif/nikonattribs.cc
index 0bc9ce730..70213e8b0 100644
--- a/rtexif/nikonattribs.cc
+++ b/rtexif/nikonattribs.cc
@@ -563,6 +563,7 @@ const std::map NALensDataInterpreter::lenses = {
{"00 47 44 44 24 24 00 06", "Tokina AT-X M35 PRO DX (AF 35mm f/2.8 Macro)"},
{"00 47 53 80 30 3C 00 06", "Tamron AF 55-200mm f/4-5.6 Di II LD (A15)"},
{"00 48 1C 29 24 24 00 06", "Tokina AT-X 116 PRO DX (AF 11-16mm f/2.8)"},
+ {"00 48 27 27 24 24 00 00", "Carl Zeiss Distagon T* 2.8/15 ZF.2"},
{"00 48 29 3C 24 24 00 06", "Tokina AT-X 16-28 AF PRO FX (AF 16-28mm f/2.8)"},
{"00 48 29 50 24 24 00 06", "Tokina AT-X 165 PRO DX (AF 16-50mm f/2.8)"},
{"00 48 32 32 24 24 00 00", "Carl Zeiss Distagon T* 2.8/21 ZF.2"},
@@ -819,6 +820,7 @@ const std::map NALensDataInterpreter::lenses = {
{"4A 4C 24 24 1E 6C 4D 06", "Samyang 14mm f/2.4 Premium"},
{"4A 54 29 29 18 0C 4D 02", "Samyang 16mm f/2.0 ED AS UMC CS"},
{"4A 54 62 62 0C 0C 4D 02", "AF Nikkor 85mm f/1.4D IF"},
+ {"4A 58 30 30 14 0C 4D 02", "Rokinon 20mm f/1.8 ED AS UMC"},
{"4A 60 36 36 0C 0C 4D 02", "Samyang 24mm f/1.4 ED AS UMC"},
{"4A 60 44 44 0C 0C 4D 02", "Samyang 35mm f/1.4 AS UMC"},
{"4A 60 62 62 0C 0C 4D 02", "Samyang AE 85mm f/1.4 AS IF UMC"},
@@ -900,6 +902,7 @@ const std::map NALensDataInterpreter::lenses = {
{"7A 48 5C 80 24 24 4B 06", "Sigma 70-200mm f/2.8 EX APO DG Macro HSM II"},
{"7A 54 6E 8E 24 24 4B 02", "Sigma APO 120-300mm f/2.8 EX DG HSM"},
{"7B 48 80 98 30 30 80 0E", "AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED"},
+ {"7C 54 2B 50 24 24 00 06", "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16)"},
{"7D 48 2B 53 24 24 82 06", "AF-S DX Zoom-Nikkor 17-55mm f/2.8G IF-ED"},
{"7F 40 2D 5C 2C 34 84 06", "AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED"},
{"7F 48 2B 5C 24 34 1C 06", "Sigma 17-70mm f/2.8-4.5 DC Macro Asp. IF"},
@@ -965,6 +968,7 @@ const std::map NALensDataInterpreter::lenses = {
{"A0 54 50 50 0C 0C A2 06", "AF-S Nikkor 50mm f/1.4G"},
{"A1 40 18 37 2C 34 A3 06", "AF-S DX Nikkor 10-24mm f/3.5-4.5G ED"},
{"A1 41 19 31 2C 2C 4B 06", "Sigma 10-20mm f/3.5 EX DC HSM"},
+ {"A1 48 6E 8E 24 24 DB 4E", "AF-S Nikkor 120-300mm f/2.8E FL ED SR VR"},
{"A1 54 55 55 0C 0C BC 06", "AF-S Nikkor 58mm f/1.4G"},
{"A2 38 5C 8E 34 40 CD 86", "AF-P DX Nikkor 70-300mm f/4.5-6.3G VR"},
{"A2 40 2D 53 2C 3C BD 0E", "AF-S DX Nikkor 18-55mm f/3.5-5.6G VR II"},
@@ -1041,9 +1045,11 @@ const std::map NALensDataInterpreter::lenses = {
{"C1 48 24 37 24 24 4B 46", "Sigma 14-24mm f/2.8 DG HSM | A"},
{"C2 4C 24 24 14 14 4B 06", "Sigma 14mm f/1.8 DG HSM | A"},
{"C3 34 68 98 38 40 4B 4E", "Sigma 100-400mm f/5-6.3 DG OS HSM | C"},
+ {"C4 4C 73 73 14 14 4B 46", "Sigma 135mm f/1.8 DG HSM | A"},
{"C8 54 44 44 0D 0D DF 46", "Tamron SP 35mm f/1.4 Di USD (F045)"},
{"C8 54 62 62 0C 0C 4B 06", "Sigma 85mm f/1.4 DG HSM | A"},
{"C8 54 62 62 0C 0C 4B 46", "Sigma 85mm f/1.4 DG HSM | A"},
+ {"C9 3C 44 76 25 31 DF 4E", "Tamron 35-150mm f/2.8-4 Di VC OSD (A043)"},
{"C9 48 37 5C 24 24 4B 4E", "Sigma 24-70mm f/2.8 DG OS HSM | A"},
{"CA 48 27 3E 24 24 DF 4E", "Tamron SP 15-30mm f/2.8 Di VC USD G2 (A041)"},
{"CB 3C 2B 44 24 31 DF 46", "Tamron 17-35mm f/2.8-4 Di OSD (A037)"},
@@ -1053,6 +1059,7 @@ const std::map NALensDataInterpreter::lenses = {
{"CE 47 37 5C 25 25 DF 4E", "Tamron SP 24-70mm f/2.8 Di VC USD G2 (A032)"},
{"CF 38 6E 98 34 3C 4B 0E", "Sigma APO 120-400mm f/4.5-5.6 DG OS HSM"},
{"CF 47 5C 8E 31 3D DF 0E", "Tamron SP 70-300mm f/4-5.6 Di VC USD (A030)"},
+ {"D2 3C 8E B0 3C 3C 4B 02", "Sigma APO 300-800mm f/5.6 EX DG HSM"},
{"DC 48 19 19 24 24 4B 06", "Sigma 10mm f/2.8 EX DC HSM Fisheye"},
{"DE 54 50 50 0C 0C 4B 06", "Sigma 50mm f/1.4 EX DG HSM"},
{"E0 3C 5C 8E 30 3C 4B 06", "Sigma 70-300mm f/4-5.6 APO DG Macro HSM"},
diff --git a/rtexif/olympusattribs.cc b/rtexif/olympusattribs.cc
index 52fbec55d..d0b3bdeda 100644
--- a/rtexif/olympusattribs.cc
+++ b/rtexif/olympusattribs.cc
@@ -192,7 +192,10 @@ public:
lenses["02 28 10"] = "Lumix G Vario 12-60mm f/3.5-5.6 Asph. Power OIS";
lenses["02 29 10"] = "Leica DG Summilux 12mm f/1.4 Asph.";
lenses["02 30 10"] = "Leica DG Vario-Elmarit 12-60mm f/2.8-4 Asph. Power OIS";
+ lenses["02 31 10"] = "Lumix G Vario 45-200mm f/4.0-5.6 II";
+ lenses["02 32 10"] = "Lumix G Vario 100-300mm f/4.0-5.6 II";
lenses["02 33 10"] = "Lumix G X Vario 12-35mm f/2.8 II Asph. Power OIS";
+ lenses["02 34 10"] = "Lumix G Vario 35-100mm f/2.8 II";
lenses["02 35 10"] = "Leica DG Vario-Elmarit 8-18mm f/2.8-4 Asph.";
lenses["02 36 10"] = "Leica DG Elmarit 200mm f/2.8 Power OIS";
lenses["02 37 10"] = "Leica DG Vario-Elmarit 50-200mm f/2.8-4 Asph. Power OIS";
@@ -200,6 +203,7 @@ public:
lenses["03 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph.";
lenses["03 02 00"] = "Leica D Summilux 25mm f/1.4 Asph.";
lenses["05 01 10"] = "Tamron 14-150mm f/3.5-5.8 Di III";
+ lenses["024 01 10"] = "Venus Optics Laowa 50mm f/2.8 2x Macro";
}
std::string toString (const Tag* t) const override
{
diff --git a/rtexif/sonyminoltaattribs.cc b/rtexif/sonyminoltaattribs.cc
index 4c901b8c0..5eb5c9ec1 100644
--- a/rtexif/sonyminoltaattribs.cc
+++ b/rtexif/sonyminoltaattribs.cc
@@ -1098,6 +1098,7 @@ public:
choices.insert (p_t (32853, "Sony E 16-55mm f/2.8 G"));
choices.insert (p_t (32854, "Sony E 70-350mm f/4.5-6.3 G OSS"));
choices.insert (p_t (32858, "Sony FE 35mm f/1.8"));
+ choices.insert (p_t (32859, "Sony FE 20mm f/1.8 G"));
choices.insert (p_t (33072, "Sony FE 70-200mm f/2.8 GM OSS + 1.4X Teleconverter"));
choices.insert (p_t (33073, "Sony FE 70-200mm f/2.8 GM OSS + 2X Teleconverter"));
choices.insert (p_t (33076, "Sony FE 100mm f/2.8 STF GM OSS (macro mode)"));
@@ -1127,6 +1128,8 @@ public:
choices.insert (p_t (49459, "Tamron 35mm f/2.8 Di III OSD M1:2"));
choices.insert (p_t (49460, "Tamron 24mm f/2.8 Di III OSD M1:2"));
choices.insert (p_t (49461, "Tamron 20mm f/2.8 Di III OSD M1:2"));
+ choices.insert (p_t (49462, "Tamron 70-180mm f/2.8 Di III VXD"));
+ choices.insert (p_t (49463, "Tamron 28-200mm f/2.8-5.6 Di III RXD"));
choices.insert (p_t (49712, "Tokina FiRIN 20mm f/2 FE AF"));
choices.insert (p_t (49713, "Tokina FiRIN 100mm f/2.8 FE MACRO"));
choices.insert (p_t (50480, "Sigma 30mm f/1.4 DC DN | C"));
@@ -1154,6 +1157,7 @@ public:
choices.insert (p_t (50515, "Sigma 35mm f/1.2 DG DN | A"));
choices.insert (p_t (50516, "Sigma 14-24mm f/2.8 DG DN | A"));
choices.insert (p_t (50517, "Sigma 24-70mm f/2.8 DG DN | A"));
+ choices.insert (p_t (50518, "Sigma 100-400mm f/5-6.3 DG DN OS"));
choices.insert (p_t (50992, "Voigtlander SUPER WIDE-HELIAR 15mm f/4.5 III"));
choices.insert (p_t (50993, "Voigtlander HELIAR-HYPER WIDE 10mm f/5.6"));
choices.insert (p_t (50994, "Voigtlander ULTRA WIDE-HELIAR 12mm f/5.6 III"));
@@ -1165,12 +1169,14 @@ public:
choices.insert (p_t (51000, "Voigtlander NOKTON 50mm f/1.2 Aspherical"));
choices.insert (p_t (51001, "Voigtlander NOKTON 21mm f/1.4 Aspherical"));
choices.insert (p_t (51002, "Voigtlander APO-LANTHAR 50mm f/2 Aspherical"));
+ choices.insert (p_t (51003, "Voigtlander NOKTON 35mm f/1.2 Aspherical SE"));
choices.insert (p_t (51504, "Samyang AF 50mm f/1.4"));
choices.insert (p_t (51505, "Samyang AF 14mm f/2.8 or Samyang AF 35mm f/2.8"));
choices.insert (p_t (51505, "Samyang AF 35mm f/2.8"));
choices.insert (p_t (51507, "Samyang AF 35mm f/1.4"));
choices.insert (p_t (51508, "Samyang AF 45mm f/1.8"));
choices.insert (p_t (51510, "Samyang AF 18mm f/2.8"));
+ choices.insert (p_t (51512, "Samyang AF 75mm f/1.8"));
}
std::string toString (const Tag* t) const override
diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc
index 8b4583877..3b6bb73ed 100644
--- a/rtgui/batchqueue.cc
+++ b/rtgui/batchqueue.cc
@@ -699,7 +699,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img)
err = img->saveAsJPEG (fname, saveFormat.jpegQuality, saveFormat.jpegSubSamp);
}
- img->free ();
+ delete img;
if (err) {
throw Glib::FileError(Glib::FileError::FAILED, M("MAIN_MSG_CANNOTSAVE") + "\n" + fname);
diff --git a/rtgui/bqentryupdater.cc b/rtgui/bqentryupdater.cc
index 61683e158..7115447c2 100644
--- a/rtgui/bqentryupdater.cc
+++ b/rtgui/bqentryupdater.cc
@@ -146,7 +146,7 @@ void BatchQueueEntryUpdater::processThread ()
}
memcpy(current.oimg, img->getData(), prevw * prevh * 3);
- img->free();
+ delete img;
}
}
diff --git a/rtgui/controlspotpanel.cc b/rtgui/controlspotpanel.cc
index 5aa501476..0b66eb986 100644
--- a/rtgui/controlspotpanel.cc
+++ b/rtgui/controlspotpanel.cc
@@ -95,6 +95,7 @@ ControlSpotPanel::ControlSpotPanel():
preview_(Gtk::manage(new Gtk::ToggleButton(M("TP_LOCALLAB_PREVIEW")))),
ctboxshape(Gtk::manage(new Gtk::HBox())),
+ ctboxshapemethod(Gtk::manage(new Gtk::HBox())),
controlPanelListener(nullptr),
lastObject_(-1),
@@ -250,7 +251,7 @@ ControlSpotPanel::ControlSpotPanel():
pack_start(*excluFrame);
- Gtk::HBox* const ctboxshapemethod = Gtk::manage(new Gtk::HBox());
+// Gtk::HBox* const ctboxshapemethod = Gtk::manage(new Gtk::HBox());
Gtk::Label* const labelshapemethod = Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_STYPE") + ":"));
ctboxshapemethod->pack_start(*labelshapemethod, Gtk::PACK_SHRINK, 4);
@@ -309,7 +310,6 @@ ControlSpotPanel::ControlSpotPanel():
sigc::mem_fun(
*this, &ControlSpotPanel::qualityMethodChanged));
ctboxqualitymethod->pack_start(*qualityMethod_);
-// pack_start(*ctboxqualitymethod);
if (showtooltip) {
expTransGrad_->set_tooltip_text(M("TP_LOCALLAB_TRANSIT_TOOLTIP"));
@@ -319,21 +319,9 @@ ControlSpotPanel::ControlSpotPanel():
if (showtooltip) {
transit_->set_tooltip_text(M("TP_LOCALLAB_TRANSIT_TOOLTIP"));
- }
-
- if (showtooltip) {
transitweak_->set_tooltip_text(M("TP_LOCALLAB_TRANSITWEAK_TOOLTIP"));
- }
-
- if (showtooltip) {
feather_->set_tooltip_text(M("TP_LOCALLAB_FEATH_TOOLTIP"));
- }
-
- if (showtooltip) {
transitgrad_->set_tooltip_text(M("TP_LOCALLAB_TRANSITGRAD_TOOLTIP"));
- }
-
- if (showtooltip) {
scopemask_->set_tooltip_text(M("TP_LOCALLAB_SCOPEMASK_TOOLTIP"));
}
@@ -927,6 +915,7 @@ void ControlSpotPanel::prevMethodChanged()
expMaskMerge_->hide();
circrad_->hide();
ctboxshape->hide();
+ shapeMethod_->set_active(0);
} else { // Excluding case
expTransGrad_->show();
@@ -1743,6 +1732,25 @@ void ControlSpotPanel::setParamEditable(bool cond)
savrest_->set_sensitive(cond);
complexMethod_->set_sensitive(cond);
wavMethod_->set_sensitive(cond);
+ preview_->set_sensitive(cond);
+
+ if (!cond) {
+ // Reset complex parameters visibility to default state
+ expTransGrad_->hide();
+ expShapeDetect_->hide();
+ expSpecCases_->hide();
+ expMaskMerge_->hide();
+ circrad_->hide();
+ ctboxshape->hide();
+ excluFrame->hide();
+// ctboxshapemethod->hide();
+ locX_->hide();
+ locXL_->hide();
+ locY_->hide();
+ locYT_->hide();
+ centerX_->hide();
+ centerY_->hide();
+ }
}
void ControlSpotPanel::setDefaultExpanderVisibility()
diff --git a/rtgui/controlspotpanel.h b/rtgui/controlspotpanel.h
index 81a79fb61..720bdf0c1 100644
--- a/rtgui/controlspotpanel.h
+++ b/rtgui/controlspotpanel.h
@@ -419,6 +419,7 @@ private:
sigc::connection previewConn_;
Gtk::HBox* const ctboxshape;
+ Gtk::HBox* const ctboxshapemethod;
// Internal variables
ControlPanelListener* controlPanelListener;
diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc
index 079a083ea..f4fc8449e 100644
--- a/rtgui/diagonalcurveeditorsubgroup.cc
+++ b/rtgui/diagonalcurveeditorsubgroup.cc
@@ -399,6 +399,25 @@ DiagonalCurveEditor* DiagonalCurveEditorSubGroup::addCurve(Glib::ustring curveLa
return newCE;
}
+
+void DiagonalCurveEditorSubGroup::updateLocallabBackground(CurveEditor* ce)
+{
+ if (ce == parent->displayedCurve) {
+ paramCurve->updateLocallabBackground(ce->locallabRef);
+ customCurve->updateLocallabBackground(ce->locallabRef);
+ NURBSCurve->updateLocallabBackground(ce->locallabRef);
+ }
+}
+
+void DiagonalCurveEditorSubGroup::restoreLocallabBackground()
+{
+ if (parent->displayedCurve) {
+ paramCurve->updateLocallabBackground(parent->displayedCurve->locallabRef);
+ customCurve->updateLocallabBackground(parent->displayedCurve->locallabRef);
+ NURBSCurve->updateLocallabBackground(parent->displayedCurve->locallabRef);
+ }
+}
+
/*
* Switch off the edit button
*/
diff --git a/rtgui/diagonalcurveeditorsubgroup.h b/rtgui/diagonalcurveeditorsubgroup.h
index 9b1f67462..08e0828f5 100644
--- a/rtgui/diagonalcurveeditorsubgroup.h
+++ b/rtgui/diagonalcurveeditorsubgroup.h
@@ -95,6 +95,7 @@ public:
void pipetteDrag(EditDataProvider *provider, int modifierKey) override;
void showCoordinateAdjuster(CoordinateProvider *provider) override;
void stopNumericalAdjustment() override;
+ void updateLocallabBackground(CurveEditor* ce) override;
bool curveReset (CurveEditor *ce) override;
@@ -102,6 +103,7 @@ protected:
void storeCurveValues (CurveEditor* ce, const std::vector& p) override;
void storeDisplayedCurve () override;
void restoreDisplayedHistogram () override;
+ void restoreLocallabBackground() override;
void savePressed ();
void loadPressed ();
void copyPressed ();
diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc
index 669dd491a..9d6860e0f 100644
--- a/rtgui/editorpanel.cc
+++ b/rtgui/editorpanel.cc
@@ -1795,7 +1795,7 @@ bool EditorPanel::idle_saveImage (ProgressConnector *pc,
bool EditorPanel::idle_imageSaved (ProgressConnector *pc, rtengine::IImagefloat* img, Glib::ustring fname, SaveFormat sf, rtengine::procparams::ProcParams &pparams)
{
- img->free ();
+ delete img;
if (! pc->returnValue() ) {
openThm->imageDeveloped ();
@@ -1995,7 +1995,7 @@ bool EditorPanel::saveImmediately (const Glib::ustring &filename, const SaveForm
err = 1;
}
- img->free();
+ delete img;
return !err;
}
@@ -2057,7 +2057,7 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *p
}
if (tries == 1000) {
- img->free ();
+ delete img;
return false;
}
@@ -2078,7 +2078,7 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *p
bool EditorPanel::idle_sentToGimp (ProgressConnector *pc, rtengine::IImagefloat* img, Glib::ustring filename)
{
- img->free ();
+ delete img;
int errore = pc->returnValue();
setProgressState(false);
delete pc;
diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc
index 3129e93e2..cbe31726d 100644
--- a/rtgui/filebrowserentry.cc
+++ b/rtgui/filebrowserentry.cc
@@ -230,7 +230,7 @@ void FileBrowserEntry::updateImage(rtengine::IImage8* img, double scale, const r
--feih->pending;
}
- img->free();
+ delete img;
return false;
}
@@ -276,7 +276,7 @@ void FileBrowserEntry::_updateImage(rtengine::IImage8* img, double s, const rten
landscape = newLandscape;
- img->free();
+ delete img;
if (parent) {
if (rotated) {
diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc
index 42a2263e2..34d6c8aa3 100644
--- a/rtgui/filecatalog.cc
+++ b/rtgui/filecatalog.cc
@@ -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);
}
diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc
index 1a66aed7c..983a0840c 100644
--- a/rtgui/filepanel.cc
+++ b/rtgui/filepanel.cc
@@ -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);
diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc
index b8338e4e8..b1c0b62df 100644
--- a/rtgui/histogrampanel.cc
+++ b/rtgui/histogrampanel.cc
@@ -471,16 +471,17 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin
cc->set_line_width (1.0 * s);
if ( r != -1 && g != -1 && b != -1 ) {
+ double xpos;
if (needRed) {
// Red
cc->set_source_rgb(1.0, 0.0, 0.0);
if (options.histogramDrawMode < 2) {
- cc->move_to(r * (winw - 1.) / 255.0 + 0.5*s, 0); // Rescaling seems needed to fit between boundaries of draw area
- cc->line_to(r * (winw - 1.) / 255.0 + 0.5*s, winh - 0);
+ xpos = padding + r * (winw - padding * 2.0) / 255.0 + 0.5*s;
} else {
- cc->move_to(HistogramScaling::log (255, r) * (winw - 1.*s) / 255.0 + 0.5*s, 0);
- cc->line_to(HistogramScaling::log (255, r) * (winw - 1.*s) / 255.0 + 0.5*s, winh - 0);
+ xpos = padding + HistogramScaling::log (255, r) * (winw - padding * 2.0) / 255.0 + 0.5*s;
}
+ cc->move_to(xpos, 0.0);
+ cc->line_to(xpos, winh - 0.0);
cc->stroke();
}
@@ -488,12 +489,12 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin
// Green
cc->set_source_rgb(0.0, 1.0, 0.0);
if (options.histogramDrawMode < 2) {
- cc->move_to(g * (winw - 1.) / 255.0 + 0.5*s, 0);
- cc->line_to(g * (winw - 1.) / 255.0 + 0.5*s, winh - 0);
+ xpos = padding + g * (winw - padding * 2.0) / 255.0 + 0.5*s;
} else {
- cc->move_to(HistogramScaling::log (255, g) * (winw - 1.) / 255.0 + 0.5*s, 0);
- cc->line_to(HistogramScaling::log (255, g) * (winw - 1.) / 255.0 + 0.5*s, winh - 0);
+ xpos = padding + HistogramScaling::log (255, g) * (winw - padding * 2.0) / 255.0 + 0.5*s;
}
+ cc->move_to(xpos, 0.0);
+ cc->line_to(xpos, winh - 0.0);
cc->stroke();
}
@@ -501,12 +502,12 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin
// Blue
cc->set_source_rgb(0.0, 0.4, 1.0);
if (options.histogramDrawMode < 2) {
- cc->move_to(b * (winw - 1.) / 255.0 + 0.5*s, 0);
- cc->line_to(b * (winw - 1.) / 255.0 + 0.5*s, winh - 0);
+ xpos = padding + b * (winw - padding * 2.0) / 255.0 + 0.5*s;
} else {
- cc->move_to(HistogramScaling::log (255, b) * (winw - 1.) / 255.0 + 0.5*s, 0);
- cc->line_to(HistogramScaling::log (255, b) * (winw - 1.) / 255.0 + 0.5*s, winh - 0);
+ xpos = padding + HistogramScaling::log (255, b) * (winw - padding * 2.0) / 255.0 + 0.5*s;
}
+ cc->move_to(xpos, 0.0);
+ cc->line_to(xpos, winh - 0.0);
cc->stroke();
}
@@ -518,27 +519,26 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin
// Luma
cc->set_source_rgb(1.0, 1.0, 1.0);
if (options.histogramDrawMode < 2) {
- cc->move_to(static_cast(Lab_L) * (winw - 3. * s) / 100.0 + 0.5 * s, 0);
- cc->line_to(static_cast(Lab_L) * (winw - 3. * s) / 100.0 + 0.5 * s, winh - 0);
+ xpos = padding + static_cast(Lab_L) * (winw - padding * 2.0) / 100.0 + 0.5*s;
} else {
- cc->move_to(HistogramScaling::log(100, Lab_L) * (winw - 1.) / 100.0 + 0.5 * s, 0);
- cc->line_to(HistogramScaling::log(100, Lab_L) * (winw - 1.) / 100.0 + 0.5 * s, winh - 0);
+ xpos = padding + HistogramScaling::log(100, Lab_L) * (winw - padding * 2.0) / 100.0 + 0.5*s;
}
+ cc->move_to(xpos, 0.0);
+ cc->line_to(xpos, winh - 0.0);
cc->stroke();
}
if (needChroma) {
// Chroma
double chromaval = sqrt(Lab_a * Lab_a + Lab_b * Lab_b) / 1.8;
- // float chromaval = sqrt(Lab_a*Lab_a + Lab_b*Lab_b);
cc->set_source_rgb(0.9, 0.9, 0.0);
if (options.histogramDrawMode < 2) {
- cc->move_to(chromaval * (winw - 1.) / 100.0 + 0.5 * s, 0);
- cc->line_to(chromaval * (winw - 1.) / 100.0 + 0.5 * s, winh - 0);
+ xpos = padding + chromaval * (winw - padding * 2.0) / 100.0 + 0.5*s;
} else {
- cc->move_to(HistogramScaling::log(100, chromaval) * (winw - 1.) / 100.0 + 0.5 * s, 0);
- cc->line_to(HistogramScaling::log(100, chromaval) * (winw - 1.) / 100.0 + 0.5 * s, winh - 0);
+ xpos = padding + HistogramScaling::log(100, chromaval) * (winw - padding * 2.0) / 100.0 + 0.5*s;
}
+ cc->move_to(xpos, 0.0);
+ cc->line_to(xpos, winh - 0.0);
cc->stroke();
}
}
@@ -826,31 +826,29 @@ void HistogramArea::updateBackBuffer ()
int nrOfVGridPartitions = 8; // always show 8 stops (lines at 1,3,7,15,31,63,127)
// draw vertical gridlines
- if (options.histogramDrawMode < 2) {
- for (int i = 1; i < nrOfVGridPartitions; i++) {
- cr->move_to ((pow(2.0,i) - 1) / 255.0 * w + 0.5, 0.);
- cr->line_to ((pow(2.0,i) - 1) / 255.0 * w + 0.5, h);
- cr->stroke ();
- }
- } else {
- for (int i = 1; i < nrOfVGridPartitions; i++) {
- cr->move_to (HistogramScaling::log (255, pow(2.0,i) - 1) / 255.0 * w + 0.5, 0.);
- cr->line_to (HistogramScaling::log (255, pow(2.0,i) - 1) / 255.0 * w + 0.5, h);
- cr->stroke ();
+ for (int i = 0; i <= nrOfVGridPartitions; i++) {
+ double xpos = padding + 0.5;
+ if (options.histogramDrawMode < 2) {
+ xpos += (pow(2.0,i) - 1) * (w - padding * 2.0) / 255.0;
+ } else {
+ xpos += HistogramScaling::log (255, pow(2.0,i) - 1) * (w - padding * 2.0) / 255.0;
}
+ cr->move_to (xpos, 0.);
+ cr->line_to (xpos, h);
+ cr->stroke ();
}
// draw horizontal gridlines
if (options.histogramDrawMode == 0) {
- for (int i = 1; i < nrOfHGridPartitions; i++) {
- cr->move_to (0., i * (double)h / nrOfHGridPartitions + 0.5);
- cr->line_to (w, i * (double)h / nrOfHGridPartitions + 0.5);
+ for (int i = 1; i < nrOfHGridPartitions; i++) {
+ cr->move_to (padding, i * (double)h / nrOfHGridPartitions + 0.5);
+ cr->line_to (w - padding, i * (double)h / nrOfHGridPartitions + 0.5);
cr->stroke ();
}
} else {
for (int i = 1; i < nrOfHGridPartitions; i++) {
- cr->move_to (0., h - HistogramScaling::log (h, i * (double)h / nrOfHGridPartitions) + 0.5*s);
- cr->line_to (w, h - HistogramScaling::log (h, i * (double)h / nrOfHGridPartitions) + 0.5*s);
+ cr->move_to (padding, h - HistogramScaling::log (h, i * (double)h / nrOfHGridPartitions) + 0.5);
+ cr->line_to (w - padding, h - HistogramScaling::log (h, i * (double)h / nrOfHGridPartitions) + 0.5);
cr->stroke ();
}
}
@@ -988,7 +986,7 @@ void HistogramArea::drawCurve(Cairo::RefPtr &cr,
double s = RTScalable::getScale();
cr->set_line_width(s);
- cr->move_to (0, vsize - 1);
+ cr->move_to (padding, vsize - 1);
scale = scale <= 0.0 ? 0.001 : scale; // avoid division by zero and negative values
for (int i = 0; i < 256; i++) {
@@ -1003,13 +1001,13 @@ void HistogramArea::drawCurve(Cairo::RefPtr &cr,
iscaled = HistogramScaling::log (255.0, (double)i);
}
- double posX = (iscaled / 255.0) * (hsize - 1);
+ double posX = padding + iscaled * (hsize - padding * 2.0) / 255.0;
double posY = vsize - 2 + val * (4 - vsize) / vsize;
cr->line_to (posX, posY);
}
- cr->line_to (hsize - 1, vsize - 1);
+ cr->line_to (hsize - padding, vsize - 1);
}
void HistogramArea::drawMarks(Cairo::RefPtr &cr,
@@ -1018,11 +1016,11 @@ void HistogramArea::drawMarks(Cairo::RefPtr &cr,
int s = 8 * RTScalable::getScale();
if(data[0] > scale) {
- cr->rectangle(0, (ui++)*s, s, s);
+ cr->rectangle(padding, (ui++)*s, s, s);
}
if(data[255] > scale) {
- cr->rectangle(hsize - s, (oi++)*s, s, s);
+ cr->rectangle(hsize - s - padding, (oi++)*s, s, s);
}
cr->fill();
diff --git a/rtgui/histogrampanel.h b/rtgui/histogrampanel.h
index cec44ed03..2a29ded9a 100644
--- a/rtgui/histogrampanel.h
+++ b/rtgui/histogrampanel.h
@@ -78,6 +78,8 @@ protected:
bool barDisplayed;
Gtk::Grid* parent;
+
+ double padding = 5.0;
HistogramRGBAreaIdleHelper* harih;
@@ -138,6 +140,8 @@ protected:
bool rawMode;
bool isPressed;
double movingPosition;
+
+ double padding = 5.0;
HistogramAreaIdleHelper* haih;
diff --git a/rtgui/iccprofilecreator.cc b/rtgui/iccprofilecreator.cc
index a8f9be007..c9639f70b 100644
--- a/rtgui/iccprofilecreator.cc
+++ b/rtgui/iccprofilecreator.cc
@@ -881,8 +881,7 @@ void ICCProfileCreator::savePressed()
double ts = slope;
double slope2 = slope == 0 ? eps : slope;
- int mode = 0;
- rtengine::Color::calcGamma(pwr, ts, mode, g_a); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
+ rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
ga[4] = g_a[3] * ts;
//printf("g_a.gamma0=%f g_a.gamma1=%f g_a.gamma2=%f g_a.gamma3=%f g_a.gamma4=%f\n", g_a.gamma0,g_a.gamma1,g_a.gamma2,g_a.gamma3,g_a.gamma4);
ga[0] = gamma;
diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc
index 9002cc389..7d5d44e44 100644
--- a/rtgui/inspector.cc
+++ b/rtgui/inspector.cc
@@ -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(window.get_width() * deviceScale / scale, imW) / 2;
+ margin.y = rtengine::min(window.get_height() * deviceScale / scale, imH) / 2;
+ center.set(rtengine::LIM(center.x + delta_x, margin.x, imW - margin.x),
+ rtengine::LIM(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(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 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(currImage->imgBuffer.getWidth(), 1);
+ int imH = rtengine::max(currImage->imgBuffer.getHeight(), 1);
+ scale = rtengine::min