diff --git a/AUTHORS.txt b/AUTHORS.txt
index 9d1309026..ec40f75e1 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -60,6 +60,7 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati
Oscar de Lama
Lebarhon
Karl Loncarek
+ Patrick Lopatto
Jie Luo
Paul Matthijsse
Wim ter Meer
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6de75e748..edbff34c1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -493,7 +493,11 @@ endif()
# Check for libcanberra-gtk3 (sound events on Linux):
if(UNIX AND (NOT APPLE))
- pkg_check_modules(CANBERRA-GTK REQUIRED libcanberra-gtk3)
+ option(USE_LIBCANBERRA "Build with libcanberra" ON)
+ if(USE_LIBCANBERRA)
+ pkg_check_modules(CANBERRA-GTK REQUIRED libcanberra-gtk3)
+ add_definitions(-DUSE_CANBERRA)
+ endif()
endif()
if(WITH_MYFILE_MMAP)
@@ -637,14 +641,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/dcpprofiles/CANON EOS 5D MARK IV.dcp b/rtdata/dcpprofiles/Canon EOS 5D Mark IV.dcp
similarity index 100%
rename from rtdata/dcpprofiles/CANON EOS 5D MARK IV.dcp
rename to rtdata/dcpprofiles/Canon EOS 5D Mark IV.dcp
diff --git a/rtdata/dcpprofiles/Canon EOS 90D.dcp b/rtdata/dcpprofiles/Canon EOS 90D.dcp
index b65a8e7ac..e50e677b1 100644
Binary files a/rtdata/dcpprofiles/Canon EOS 90D.dcp and b/rtdata/dcpprofiles/Canon EOS 90D.dcp differ
diff --git a/rtdata/dcpprofiles/CANON EOS M6 MARK II.dcp b/rtdata/dcpprofiles/Canon EOS M6 Mark II.dcp
similarity index 100%
rename from rtdata/dcpprofiles/CANON EOS M6 MARK II.dcp
rename to rtdata/dcpprofiles/Canon EOS M6 Mark II.dcp
diff --git a/rtdata/dcpprofiles/CANON EOS R.dcp b/rtdata/dcpprofiles/Canon EOS R.dcp
similarity index 100%
rename from rtdata/dcpprofiles/CANON EOS R.dcp
rename to rtdata/dcpprofiles/Canon EOS R.dcp
diff --git a/rtdata/dcpprofiles/Canon EOS R5.dcp b/rtdata/dcpprofiles/Canon EOS R5.dcp
new file mode 100644
index 000000000..88f94620d
Binary files /dev/null and b/rtdata/dcpprofiles/Canon EOS R5.dcp differ
diff --git a/rtdata/dcpprofiles/Canon EOS R6.dcp b/rtdata/dcpprofiles/Canon EOS R6.dcp
new file mode 100644
index 000000000..7aaa04ab2
Binary files /dev/null and b/rtdata/dcpprofiles/Canon EOS R6.dcp differ
diff --git a/rtdata/dcpprofiles/CANON POWERSHOT G1 X MARK II.dcp b/rtdata/dcpprofiles/Canon PowerShot G1 X Mark II.dcp
similarity index 100%
rename from rtdata/dcpprofiles/CANON POWERSHOT G1 X MARK II.dcp
rename to rtdata/dcpprofiles/Canon PowerShot G1 X Mark II.dcp
diff --git a/rtdata/dcpprofiles/FUJIFILM X-PRO3.dcp b/rtdata/dcpprofiles/FUJIFILM X-Pro3.dcp
similarity index 100%
rename from rtdata/dcpprofiles/FUJIFILM X-PRO3.dcp
rename to rtdata/dcpprofiles/FUJIFILM X-Pro3.dcp
diff --git a/rtdata/dcpprofiles/OLYMPUS E-M5MARKII.dcp b/rtdata/dcpprofiles/OLYMPUS E-M5MarkII.dcp
similarity index 100%
rename from rtdata/dcpprofiles/OLYMPUS E-M5MARKII.dcp
rename to rtdata/dcpprofiles/OLYMPUS E-M5MarkII.dcp
diff --git a/rtdata/iccprofiles/output/RTv2_Medium.icc b/rtdata/iccprofiles/output/RTv2_Medium.icc
index ebaf4d133..930f38a71 100644
Binary files a/rtdata/iccprofiles/output/RTv2_Medium.icc and b/rtdata/iccprofiles/output/RTv2_Medium.icc differ
diff --git a/rtdata/images/svg/bidirectional-arrow-horizontal-hicontrast.svg b/rtdata/images/svg/bidirectional-arrow-horizontal-hicontrast.svg
new file mode 100644
index 000000000..f2712cee9
--- /dev/null
+++ b/rtdata/images/svg/bidirectional-arrow-horizontal-hicontrast.svg
@@ -0,0 +1,127 @@
+
+
diff --git a/rtdata/images/svg/bidirectional-arrow-horizontal-prelight.svg b/rtdata/images/svg/bidirectional-arrow-horizontal-prelight.svg
new file mode 100644
index 000000000..6382cc546
--- /dev/null
+++ b/rtdata/images/svg/bidirectional-arrow-horizontal-prelight.svg
@@ -0,0 +1,127 @@
+
+
diff --git a/rtdata/images/svg/bidirectional-arrow-vertical-hicontrast.svg b/rtdata/images/svg/bidirectional-arrow-vertical-hicontrast.svg
new file mode 100644
index 000000000..93cb21a43
--- /dev/null
+++ b/rtdata/images/svg/bidirectional-arrow-vertical-hicontrast.svg
@@ -0,0 +1,127 @@
+
+
diff --git a/rtdata/images/svg/bidirectional-arrow-vertical-prelight.svg b/rtdata/images/svg/bidirectional-arrow-vertical-prelight.svg
new file mode 100644
index 000000000..76f4312cb
--- /dev/null
+++ b/rtdata/images/svg/bidirectional-arrow-vertical-prelight.svg
@@ -0,0 +1,127 @@
+
+
diff --git a/rtdata/images/svg/draw.svg b/rtdata/images/svg/draw.svg
new file mode 100644
index 000000000..30ea04ea4
--- /dev/null
+++ b/rtdata/images/svg/draw.svg
@@ -0,0 +1,108 @@
+
+
diff --git a/rtdata/images/svg/histogram-ellipsis-small.svg b/rtdata/images/svg/histogram-ellipsis-small.svg
new file mode 100644
index 000000000..4fdb17907
--- /dev/null
+++ b/rtdata/images/svg/histogram-ellipsis-small.svg
@@ -0,0 +1,135 @@
+
+
diff --git a/rtdata/images/svg/histogram-bayer-on-small.svg b/rtdata/images/svg/histogram-type-histogram-raw-small.svg
similarity index 100%
rename from rtdata/images/svg/histogram-bayer-on-small.svg
rename to rtdata/images/svg/histogram-type-histogram-raw-small.svg
diff --git a/rtdata/images/svg/histogram-bayer-off-small.svg b/rtdata/images/svg/histogram-type-histogram-small.svg
similarity index 59%
rename from rtdata/images/svg/histogram-bayer-off-small.svg
rename to rtdata/images/svg/histogram-type-histogram-small.svg
index 5d6c439fb..1d2f6547e 100644
--- a/rtdata/images/svg/histogram-bayer-off-small.svg
+++ b/rtdata/images/svg/histogram-type-histogram-small.svg
@@ -1,6 +1,4 @@
-
-
diff --git a/rtdata/images/svg/histogram-type-parade-small.svg b/rtdata/images/svg/histogram-type-parade-small.svg
new file mode 100644
index 000000000..f299f8ab2
--- /dev/null
+++ b/rtdata/images/svg/histogram-type-parade-small.svg
@@ -0,0 +1,132 @@
+
+
diff --git a/rtdata/images/svg/histogram-type-vectorscope-hc-small.svg b/rtdata/images/svg/histogram-type-vectorscope-hc-small.svg
new file mode 100644
index 000000000..ef2e8b51f
--- /dev/null
+++ b/rtdata/images/svg/histogram-type-vectorscope-hc-small.svg
@@ -0,0 +1,131 @@
+
+
diff --git a/rtdata/images/svg/histogram-type-vectorscope-hs-small.svg b/rtdata/images/svg/histogram-type-vectorscope-hs-small.svg
new file mode 100644
index 000000000..62bbf9586
--- /dev/null
+++ b/rtdata/images/svg/histogram-type-vectorscope-hs-small.svg
@@ -0,0 +1,135 @@
+
+
diff --git a/rtdata/images/svg/histogram-type-waveform-small.svg b/rtdata/images/svg/histogram-type-waveform-small.svg
new file mode 100644
index 000000000..5147ab2fc
--- /dev/null
+++ b/rtdata/images/svg/histogram-type-waveform-small.svg
@@ -0,0 +1,122 @@
+
+
diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais
index 1483d7cc5..ae2d78b2f 100644
--- a/rtdata/languages/Francais
+++ b/rtdata/languages/Francais
@@ -1782,17 +1782,19 @@ TP_LOCALLAB_BLMETHOD_TOOLTIP;Normal - direct floute et bruite avec tous les rég
TP_LOCALLAB_BLNOI_EXP;Flouter & Bruit
TP_LOCALLAB_BLNORM;Normal
TP_LOCALLAB_BLSYM;Symétrique
-TP_LOCALLAB_BLUFR;Adoucir - Flouter - Grain - Debruiter
+TP_LOCALLAB_BLURCOLDE_TOOLTIP;L'image pour calculer dE est légèrement floutéeafin d'éviter de prendre en compte des pixels isolés.
+TP_LOCALLAB_BLUFR;Flouter - Grain - Debruiter
TP_LOCALLAB_BLUMETHOD_TOOLTIP;Pour flouter l'arrère plan et isoler le premier plan:\n*Flouter l'arrière plan avec un RT-spot couvrant totalement l'image (valeurs élevées Etendue et transition) - normal ou inverse.\n*Isoler le premier plan avec un ou plusieurs RT-spot Exclusion avec l'outils que vous voulez (accroître Etendue).\n\nCe module peut être utilisé en réduction de bruit additionnelle,incluant un "median" et un "Filtre Guidé"
TP_LOCALLAB_BLUR;Flou Gaussien - Bruit - Grain
TP_LOCALLAB_BLURCBDL;Flouter niveaux 0-1-2-3-4
-TP_LOCALLAB_BLURCOL;Rayon floutage masque
+TP_LOCALLAB_BLURCOL;Rayon floutage
TP_LOCALLAB_BLURDE;Flouter la détection de forme
TP_LOCALLAB_BLURLC;Luminance seulement
TP_LOCALLAB_BLURLEVELFRA;Flouter niveaux
TP_LOCALLAB_BLURMASK_TOOLTIP;Génère un masque flou, prend en compte la structure avec le curseur de seuil de contraste du Masque flou.
+TP_LOCALLAB_BLURRMASK_TOOLTIP;Vous permet de faire varier "rayon" du flou Gaussien (0 to 1000)
TP_LOCALLAB_BLURRESIDFRA;Flouter image Résiduelle
-TP_LOCALLAB_BLUR_TOOLNAME;Adoucir Flouter Grain & Réduction du Bruit - 1
+TP_LOCALLAB_BLUR_TOOLNAME;Flouter/Grain & Réduction du Bruit - 1
TP_LOCALLAB_BLWH;Tous les changements forcés en noir et blanc
TP_LOCALLAB_BLWH_TOOLTIP;Force le changement de la composante "a" et "b" à zéro.\nUtile quand l'utilisateur choisit un processus noir et blanc, ou un film.
TP_LOCALLAB_BUTTON_ADD;Ajouter
@@ -1800,11 +1802,11 @@ TP_LOCALLAB_BUTTON_DEL;Effacer
TP_LOCALLAB_BUTTON_DUPL;Dupliquer
TP_LOCALLAB_BUTTON_REN;Renommer
TP_LOCALLAB_BUTTON_VIS;Montrer/Cacher
-TP_LOCALLAB_CBDL;Contraste niveaux détail
+TP_LOCALLAB_CBDL;Contraste par niveaux de détail
TP_LOCALLAB_CBDLCLARI_TOOLTIP;Ajuste les tons moyens et les réhausse.
TP_LOCALLAB_CBDL_ADJ_TOOLTIP;Agit comme un outil ondelettes.\nLe premier niveau (0) agit sur des détails de 2x2.\nLe dernier niveau (5) agit sur des détails de 64x64.
TP_LOCALLAB_CBDL_THRES_TOOLTIP;Empêche d'augmenter le bruit
-TP_LOCALLAB_CBDL_TOOLNAME;Contraste par niveaux de détails(Défauts) - 2
+TP_LOCALLAB_CBDL_TOOLNAME;Contraste par niveaux de détail - 2
TP_LOCALLAB_CENTER_X;Centre X
TP_LOCALLAB_CENTER_Y;Centre Y
TP_LOCALLAB_CH;Courbes CL - LC
@@ -1814,7 +1816,7 @@ TP_LOCALLAB_CHROMABLU_TOOLTIP;Agit comme un amplificateur-reducteur d'action en
TP_LOCALLAB_CHROMACBDL;Chroma
TP_LOCALLAB_CHROMACB_TOOLTIP;Agit comme un amplificateur-reducteur d'action en comparant aux curseurs de luminance.\nEn dessous de 100 reduit, au dessus de 100 amplifie
TP_LOCALLAB_CHROMALEV;Niveaux de Chroma
-TP_LOCALLAB_CHROMASKCOL;Masque Chroma
+TP_LOCALLAB_CHROMASKCOL;Chroma
TP_LOCALLAB_CHROMASK_TOOLTIP;Vous pouvez utiliser ce curseur pour désaturer l'arrière plan (inverse masque - courbe proche de 0).\nEgalement pour atténier ou accroître l'action du masque sur la chroma
TP_LOCALLAB_CHRRT;Chroma
TP_LOCALLAB_CIRCRADIUS;Taille Spot
@@ -1833,7 +1835,7 @@ TP_LOCALLAB_COLORDEPREV_TOOLTIP;Bouton Prévisualisation ΔE a besoin qu'un seul
TP_LOCALLAB_COLORDE_TOOLTIP;Affiche la prévisualisation ΔE en bleu si négatif et en vert si positif.\n\nMasque et modifications (montre modifications sans masque): montre les modifications réelles si positf, montre les modifications améliorées (luminance seule) en bleu et jaune si négatif.
TP_LOCALLAB_COLORSCOPE;Etendue Outils Couleur
TP_LOCALLAB_COLORSCOPE_TOOLTIP;Utilise une étendue commune pour Couleur et lumière, Ombres Lumières, Vibrance.\nLes autres outils ont leur étendue spécifique.
-TP_LOCALLAB_COLOR_TOOLNAME;Couleur&Lumière (Défauts) - 11
+TP_LOCALLAB_COLOR_TOOLNAME;Couleur & Lumière - 11
TP_LOCALLAB_COL_NAME;Nom
TP_LOCALLAB_COL_VIS;Statut
TP_LOCALLAB_COMPFRA;Niveaux Contraste directionnel
@@ -1847,6 +1849,7 @@ TP_LOCALLAB_CONTFRA;Contraste par niveau
TP_LOCALLAB_CONTRAST;Contraste
TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP;Contrôle de contraste du masque.
TP_LOCALLAB_CONTRESID;Contraste
+TP_LOCALLAB_CONTTHMASK_TOOLTIP;Vous permet de déterminer quelles parties de l'image seront concernées par la texture.
TP_LOCALLAB_CONTTHR;Seuil contraste
TP_LOCALLAB_CONTWFRA;Contrast Local
TP_LOCALLAB_CSTHRESHOLD;Ψ Ondelettes niveaux
@@ -1866,13 +1869,23 @@ TP_LOCALLAB_CURVENSOB2;Combined HueChroma + Contrast threshold (experimental)
TP_LOCALLAB_CURVNONE;Désactive courbes
TP_LOCALLAB_DARKRETI;Obscuirité
TP_LOCALLAB_DEHAFRA;Elimination de la brume
+TP_LOCALLAB_DEHAZFRAME_TOOLTIP;Élimine la brume atmosphérique. Augmente généralement la saturation et les détails. \ N Peut supprimer les dominantes de couleur, mais peut également introduire une dominante bleue qui peut être corrigée à l'aide d'autres outils.
TP_LOCALLAB_DEHAZ;Force
TP_LOCALLAB_DEHAZ_TOOLTIP;Valeurs Négatives ajoute de la brume
TP_LOCALLAB_DELTAD;Delta balance
TP_LOCALLAB_DELTAEC;Masque ΔE Image
TP_LOCALLAB_DENOIS;Ψ Réduction du bruit
TP_LOCALLAB_DENOI_EXP;Réduction du bruit
+TP_LOCALLAB_DENOIQUA_TOOLTIP;Conservatif préserve les fréquences basses, alors que agressif tend à les effacer
+TP_LOCALLAB_DENOIEQUAL_TOOLTIP;Equilibre l'action de denoise luminance entre les ombres et les lumières
TP_LOCALLAB_DENOI_TOOLTIP;Ce module peut être utilisé seul (à la fin du processus), ou en complément de Réduction du bruit (au début).\nEtendue(deltaE)permet de différencier l'action.\nVous pouvez compléter avec "median" ou "Filtre guidé" (Adoucir Flou...).\nVous pouvez compléter l'action avec "Flou niveaux" "Ondelette pyramide"
+TP_LOCALLAB_DENOILUMDETAIL_TOOLTIP;Permet de récupérer les détails de luminance par mise en oeuvre progressive de la transformée de Fourier (DCT)
+TP_LOCALLAB_DENOICHROF_TOOLTIP;Agit sur les fins détails du bruit de chrominance
+TP_LOCALLAB_DENOICHROC_TOOLTIP;Agit sur les paquets et amas de bruit de chrominance
+TP_LOCALLAB_DENOICHRODET_TOOLTIP;Permet de récupérer les détails de chrominance par mise en oeuvre progressive de la transformée de Fourier (DCT)
+TP_LOCALLAB_DENOITHR_TOOLTIP;Règle l'effet de bord pour privilégier l'action sur les aplats
+TP_LOCALLAB_DENOIEQUALCHRO_TOOLTIP;Equilibre l'action de denoise chrominance entre les bleus-jaunes et les rouges-verts
+TP_LOCALLAB_DENOIBILAT_TOOLTIP;Traite le bruit d'impulsion (poivre et sel)
TP_LOCALLAB_DEPTH;Profondeur
TP_LOCALLAB_DETAIL;Contrast local
TP_LOCALLAB_DETAILSH;Details
@@ -1902,11 +1915,9 @@ TP_LOCALLAB_EXCLUTYPE;Spot méthode
TP_LOCALLAB_EXCLUTYPE_TOOLTIP;Spot Normal utilise les données récursives.\n\nSpot exclusion réinitialise les données d'origine.\nPeut être utilsé pour annuler totalement ou partiellement une action précédente ou pour réaliser un mode inverse
TP_LOCALLAB_EXECLU;Spot Exclusion
TP_LOCALLAB_EXNORM;Spot Normal
-//TP_LOCALLAB_EXPCBDL_TOOLTIP;Dans le cas d'un capteur contaminé ("graisse"), et qaund la surface est importante ou pourune série de petits défauts.\n\na) Mettre la sélection du spot sur un défaut prononcé (adapter la taille si nécessaire), utilise run spot suffisament grand qui autorise les ondelettes; b) choisir une aire suffisament grande pour couvrir largement la zone affectée par les défauts; c) Choisir une valeur de transition (basse) et une transition affaiblissement (haute); d) agir sur les niveaux 2, 3, 4 or 5 ou^plus bas en réduisant le the contrast (valeurs en dessous de 100) agir sur le curseur chroma si nécessaire. e)possibilité d'agir sur "Etendue" pour réduire la zone d'action.\n\nVous pouvez aussi compléter avec "Flou niveaux" et Flouu Gaussien (Adoucir Flou et bruit)
TP_LOCALLAB_EXPCBDL_TOOLTIP;Peut être utilisé pour retirer les marques sur le capteur ou la lentille.
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
@@ -1915,6 +1926,7 @@ TP_LOCALLAB_EXPCONTRASTPYR_TOOLTIP;Voir la documentation de ondelettes niveaux.\
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.
TP_LOCALLAB_EXPCURV;Courbes
TP_LOCALLAB_EXPGRAD;Filtre gradué
+TP_LOCALLAB_EXPGRADCOL_TOOLTIP;Un filtre gardué est disponible dans Couleur et lumière (luminance, chrominance & teinte gradients, et "Fusion fichier") Exposure (luminance grad.), Exposition Masque(luminance grad.), Ombres/lumières (luminance grad.), Vibrance (luminance, chrominance & teinte gradients), Local contrast & ondelettes pyramide (local contrast grad.).\nAdoucissement de gradient est dans "Réglages".
TP_LOCALLAB_EXPLAPBAL_TOOLTIP;Balance l'action entre l'iamge originale image et la transformée de Laplace.
TP_LOCALLAB_EXPLAPGAMM_TOOLTIP;Applique un gamma avant et après la transformée de Laplace
TP_LOCALLAB_EXPLAPLIN_TOOLTIP;Ajoute une exposition linéaire avant l'application de la transformée de Laplace
@@ -1922,14 +1934,13 @@ TP_LOCALLAB_EXPLAP_TOOLTIP;Plus vous agissez sur ce curseur de seuil, plus grand
TP_LOCALLAB_EXPMERGEFILE_TOOLTIP;Autorise de nombreuses possibilités de fusionner les images (comme les calques dans Photosshop) : difference, multiply, soft light, overlay...avec opacité...\nOriginale Image : fusionne le RT-spot en cours avec Originale.\nSpot Précédent : fusionne le RT-spot en cours avec le précédent - si il n'y a qu'un spot précédent = original.\nArrière plan : fusionne le RT-spot en cours avec la couleur et la luminance de l'arrière plan (moins de possibilités)
TP_LOCALLAB_EXPMETHOD_TOOLTIP;Standard : utilise un algorithme similaire à Exposure principal mais en L*a*b* et en prenant en compte le deltaE.\n\nCompression dynamique et atténuateur de contraste : utilise un autre algorithme aussi avec deltaE et avec l'équation de Poisson pour résoudre le Laplacien dans l'espace de Fourier.\nAtténuateur, Compression dynamqiue et Standard peuvent être combinés.\nFFTW La transformée de Fourier est optimisée en taille pour réduire les temps de traitement.\nRéduit les artéfacts et le bruit.
TP_LOCALLAB_EXPNOISEMETHOD_TOOLTIP;Applique un median avant la transformée de Laplace pour éviter les artéfacts (bruit).\nVous pouvez aussi utiliser l'outil "Réduction du bruit".
-TP_LOCALLAB_EXPOSE;Compression dynamique - Exposition
-//TP_LOCALLAB_EXPOSURE_TOOLTIP;Dans certains cases (fortes ombres ..) vous pouvez utiliser le module "Shadows Highlights", "Tone equalizer", "TRC", "Encoding Log"...
+TP_LOCALLAB_EXPOSE;Compression dynamique & Exposition
TP_LOCALLAB_EXPOSURE_TOOLTIP;Modifie l'exposition dans l'espace L*a*b* en utilisant un Laplacien et les algorithmes PDE en prenant en compte dE, minimise les artéfacts.
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;Compression Dynamique & Exposition- 10
TP_LOCALLAB_FATAMOUNT;Quantité
TP_LOCALLAB_FATANCHOR;Ancre
TP_LOCALLAB_FATANCHORA;Décalage
@@ -1942,14 +1953,17 @@ TP_LOCALLAB_FATSHFRA;Compression Dynamique Masque ƒ
TP_LOCALLAB_FEATH_TOOLTIP;Largeur du Gradient en porcentage de la diagonale du Spot\nUtilisé par tous les Filtres Gradués dans tous les outils.\nPas d'action si les filtres gradués ne sont pas utilisés.
TP_LOCALLAB_FEATVALUE;Adoucissement gradient (Filtres Gradués)
TP_LOCALLAB_FFTCOL_MASK;FFTW ƒ
+TP_LOCALLAB_FFTMASK_TOOLTIP;Utilise une transformée de Fourier pour une meilleure qualité (accroit le temps de traitement et le besoin en mémoire)
TP_LOCALLAB_FFTW;ƒ - Utilise Fast Fourier Transform
TP_LOCALLAB_FFTW2;ƒ - Utilise Fast Fourier Transform (TIF, JPG,..)
TP_LOCALLAB_FFTWBLUR;ƒ - Utilise toujours Fast Fourier Transform
TP_LOCALLAB_FULLIMAGE;Calcule les valeurs Noir Ev - Blanc Ev - sur l'image entière
+TP_LOCALLAB_FULLIMAGELOG_TOOLTIP;Calcule les valeurs Ev sur l'image entière.
TP_LOCALLAB_GAM;Gamma
TP_LOCALLAB_GAMFRA;Courbe Réponse Tonale (TRC)
TP_LOCALLAB_GAMM;Gamma
-TP_LOCALLAB_GAMMASKCOL;Gamma masque
+TP_LOCALLAB_GAMMASKCOL;Gamma
+TP_LOCALLAB_GAMMASK_TOOLTIP;Gamma et Pente (Slope) autorise une transformation du masque en douceur et sans artefacts en modifiant progressivement "L" pour éviter les discontinuité.
TP_LOCALLAB_GAMSH;Gamma
TP_LOCALLAB_GRADANG;Angle du Gradient
TP_LOCALLAB_GRADANG_TOOLTIP;Angle de Rotation en degrés : -180 0 +180
@@ -1965,13 +1979,18 @@ TP_LOCALLAB_GRADSTRHUE_TOOLTIP;Filttre Teinte force
TP_LOCALLAB_GRADSTRLUM;Force Gradient Luminance
TP_LOCALLAB_GRADSTR_TOOLTIP;Force Filtre en Ev
TP_LOCALLAB_GRAINFRA;Film Grain 1:1
+TP_LOCALLAB_GRAIN_TOOLTIP;Ajoute du grain pour simuler un film
TP_LOCALLAB_GRALWFRA;Filtre Gradué Local contraste
TP_LOCALLAB_GRIDFRAME_TOOLTIP;Vous pouvez utiliser cet outil comme une brosse. Utiliser un petit Spot et adaptez transition et transition affaiblissement\nSeulement en mode NORMAL et éventuellement Teinte, Saturation, Couleur, Luminosité sont concernés par Fusion arrire plan (ΔE)
TP_LOCALLAB_GRIDONE;Virage partiel
TP_LOCALLAB_GRIDTWO;Direct
+TP_LOCALLAB_GRIDMETH_TOOLTIP;Virage partiel: la luminance est prise en compte quand varie la chroma -Equivalent de H=f(H) si le "point blanc" sur la grille the grid est à zéro et vous faites varier le "point noir" -Equivalent de "Virage partiel" si vous faites varier les 2 points.\n\nDirect: agit directement sur la chroma
TP_LOCALLAB_GUIDBL;Rayon adoucir
TP_LOCALLAB_GUIDFILTER;Rayon Filtre Guidé
TP_LOCALLAB_GUIDFILTER_TOOLTIP;Adapter cette valeur en fonction des images - peut réduire ou accroître les artéfacts.
+TP_LOCALLAB_GUIDBL_TOOLTIP;Applique un filtre guidé avec un rayon donné, pour réduire les artefacts ou flouter l'image
+TP_LOCALLAB_GUIDSTRBL_TOOLTIP;Force du filtre guidé
+TP_LOCALLAB_GUIDEPSBL_TOOLTIP;Détail - agit sur la répartition du filtre guidé, les valeurs négatives simulent un flou gaussien
TP_LOCALLAB_HHMASK_TOOLTIP;Ajustements fin de la teinte par exemple pour la peau.
TP_LOCALLAB_HIGHMASKCOL;Hautes lumières masque
TP_LOCALLAB_HLH;Courbes H
@@ -1979,6 +1998,7 @@ TP_LOCALLAB_IND;Independant (souris)
TP_LOCALLAB_INDSL;Independant (souris + curseurs)
TP_LOCALLAB_INVERS;Inverse
TP_LOCALLAB_INVERS_TOOLTIP;Si sélectionné (inverse) moins de possibilités.\n\nAlternative\nPremier Spot:\n image entière - delimiteurs en dehors de la prévisualisation\n RT-spot forme sélection : rectangle. Transition 100\n\nDeuxième spot : Spot Exclusion
+TP_LOCALLAB_INVBL_TOOLTIP;Alternative\nPremier Spot:\n image entière - delimiteurs en dehors de la prévisualisation\n RT-spot forme sélection : rectangle. Transition 100\n\nDeuxième spot : Spot Exclusion
TP_LOCALLAB_ISOGR;Plus gros (ISO)
TP_LOCALLAB_LABBLURM;Masque Flouter
TP_LOCALLAB_LABEL;Ajustements Locaux
@@ -1989,11 +2009,12 @@ TP_LOCALLAB_LABSTRUM;Masque Structure
TP_LOCALLAB_LAPLACC;ΔØ Masque Laplacien résoud PDE
TP_LOCALLAB_LAPLACE;Laplacien seuil ΔE
TP_LOCALLAB_LAPLACEXP;Laplacien seuil
-TP_LOCALLAB_LAPMASKCOL;Laplacien seuil masque
+TP_LOCALLAB_LAPMASKCOL;Laplacien seuil
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_LAPRAD1_TOOLTIP;Eviter d'utiliser Radius and Laplace Seuil en même temps.\nTransforme le masque pour éliminer les valeurs inférieures au seuil.\nReduit les artefacts et le bruit, et permet une modification du contraste local.
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
+TP_LOCALLAB_LC_TOOLNAME;Constraste Local & Ondelettes - 7
TP_LOCALLAB_LEVELBLUR;Maximum Flouter
TP_LOCALLAB_LEVELLOCCONTRAST_TOOLTIP;En abscisse le contraste local (proche du concept de luminance). En ordonnée, amplification ou reduction du contraste local.
TP_LOCALLAB_LEVELWAV;Ψ Ondelettes Niveaux
@@ -2006,9 +2027,9 @@ TP_LOCALLAB_LINEAR;Linéarité
TP_LOCALLAB_LIST_NAME;Ajoute un outil au spot courant...
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_LMASK_LL_TOOLTIP;Vous permet de modifier librement le contraste du masque. Peut amener de artefacts.
TP_LOCALLAB_LOCCONT;Masque Flou
-TP_LOCALLAB_LOC_CONTRAST;Contraste Local-Ondelettes-déf.
+TP_LOCALLAB_LOC_CONTRAST;Contraste Local & Ondelettes
TP_LOCALLAB_LOC_CONTRASTPYR;Ψ Pyramide 1:
TP_LOCALLAB_LOC_CONTRASTPYR2;Ψ Pyramide 2:
TP_LOCALLAB_LOC_CONTRASTPYR2LAB; Contr. par niveaux- Tone Mapping - Cont.Dir.
@@ -2031,19 +2052,22 @@ TP_LOCALLAB_LUM;Courbes LL - CC
TP_LOCALLAB_LUMADARKEST;Plus Sombre
TP_LOCALLAB_LUMASK;Maqsue Luminance arrière plan
TP_LOCALLAB_LUMASK_TOOLTIP;Ajuste le gris de l'arrière plan du masque dans Montrer Masque (Masque et modifications)
-TP_LOCALLAB_LUMAWHITESEST;Plus blanc
-TP_LOCALLAB_LUMONLY;Luminance seulemnt
+TP_LOCALLAB_LUMAWHITESEST;Plus clair
+TP_LOCALLAB_LUMONLY;Luminance seulement
TP_LOCALLAB_MASKCOM;Masque couleur Commun
TP_LOCALLAB_MASKCOM_TOOLTIP;Ces masques travaillent comme les autres outils, ils prennet en compte Etendue.\nIls sont différents des autres masques qui complètent un outil (Couleur et Lumière, Exposition...)
TP_LOCALLAB_MASFRAME;Masque et Fusion
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;Masque
-TP_LOCALLAB_MASK2;Courbe de Contraste masque
+TP_LOCALLAB_MASK2;Courbe de Contraste
TP_LOCALLAB_MASKCOL;Masque Courbes
-TP_LOCALLAB_MASKH;Courbe teinte masque
+TP_LOCALLAB_MASKCURVE_TOOLTIP;Si la courbe est au sommet, le masque est compétement noir aucune transformation n'est réalisée par le masque sur l'image.\nQuand vous descendez la courbe, progressivement le masque va se colorer et s'éclaicir, l'image change de plus en plus.\n\nIl est recommendé (pas obligatoire) de positionner le sommet des courbes curves sur la ligne de transition grise qui représnte les références (chroma, luma, couleur).
+TP_LOCALLAB_MASKH;Courbe teinte
TP_LOCALLAB_MASK_TOOLTIP;Vous pouvez activer plusieurs masques pour un simple outil, ceci nécessite d'activer un autre outil (mais sans utilser l'outil : curseurs à 0,...)où est le masque que vous souhaitez activer.\n\nVous pouvez aussi dupliquer le RT-spot et le placer juste à côté de l'autre,les variations de références autorisent un travail fin sur les images.
TP_LOCALLAB_MED;Medium
TP_LOCALLAB_MEDIAN;Median Bas
+TP_LOCALLAB_MEDIAN_TOOLTIP;Choisir un median 3x3 à 9x9: plus les valeurs sont élévées, plus la réduction du bruit ou le flou seront marqués
+TP_LOCALLAB_MEDIANITER_TOOLTIP;Nombre d'applications successives du median
TP_LOCALLAB_MEDNONE;Rien
TP_LOCALLAB_MERCOL;Couleur
TP_LOCALLAB_MERDCOL;Fusion arrière plan (ΔE)
@@ -2053,6 +2077,7 @@ TP_LOCALLAB_MERFOR;Couleur esquiver
TP_LOCALLAB_MERFOU;Multiplier
TP_LOCALLAB_MERGE1COLFRA;Fusion avec Original ou Précédent ou arrière plan
TP_LOCALLAB_MERGECOLFRA;Masque: LCH & Structure
+TP_LOCALLAB_MERGECOLFRMASK_TOOLTIP;Vous permet de créer des masques basés sur les 3 courbes LCH et/ou un algorithm de détection de structure
TP_LOCALLAB_MERGEFIV;Previous Spot(Mask 7) + Mask LCH
TP_LOCALLAB_MERGEFOU;Previous Spot(Mask 7)
TP_LOCALLAB_MERGEMER_TOOLTIP;Prend en compte ΔE pour fusionner les fichiers (équivalent de Etendue pour cet usage)
@@ -2070,7 +2095,7 @@ TP_LOCALLAB_MERLUM;Luminosité
TP_LOCALLAB_MERNIN;Ecran
TP_LOCALLAB_MERONE;Normal
TP_LOCALLAB_MERSAT;Saturation
-TP_LOCALLAB_MERSEV;Soft Light Photshop
+TP_LOCALLAB_MERSEV;Soft Light (legacy)
TP_LOCALLAB_MERSEV0;Soft Light Illusion
TP_LOCALLAB_MERSEV1;Soft Light W3C
TP_LOCALLAB_MERSEV2;Lumière dure
@@ -2092,6 +2117,7 @@ TP_LOCALLAB_MRTHR;Image Originale
TP_LOCALLAB_MRTWO;Short Curves 'L' Mask
TP_LOCALLAB_MULTIPL_TOOLTIP;Autorise la retouche des tons sur une large plage : -18EV +4EV. Le remier curseur agit sur -18EV and -6EV. Le dernier curseur agit sur les tons au-dessus de 4EV
TP_LOCALLAB_NEIGH;Rayon
+TP_LOCALLAB_NOISE_TOOLTIP;Ajoute du bruit de luminance
TP_LOCALLAB_NOISECHROCOARSE;Chroma gros (Ond)
TP_LOCALLAB_NOISECHROC_TOOLTIP;Si supérieur à zéro, algorithme haute qualité est activé.\nGros est sélectionné si curseur >=0.2
TP_LOCALLAB_NOISECHRODETAIL;Récupération des détails Chroma (DCT ƒ)
@@ -2123,7 +2149,7 @@ TP_LOCALLAB_QUALCURV_METHOD;Types de Courbes
TP_LOCALLAB_QUAL_METHOD;Qualité globale
TP_LOCALLAB_RADIUS;Rayon
TP_LOCALLAB_RADIUS_TOOLTIP;Above Radius 30 Use Fast Fourier Transform
-TP_LOCALLAB_RADMASKCOL;Rayon adoucir Masque
+TP_LOCALLAB_RADMASKCOL;Rayon adoucir
TP_LOCALLAB_RECT;Rectangle
TP_LOCALLAB_RECURS;Réferences Récursives
TP_LOCALLAB_RECURS_TOOLTIP;Recalcule les références pour teinte, luma, chroma après chaque module et après chaque RT-spot.\nAussi utile pour le travail avec les masques.
@@ -2144,6 +2170,7 @@ TP_LOCALLAB_RETI;De-brume - Retinex Fort contraste
TP_LOCALLAB_RETIFRA;Retinex
TP_LOCALLAB_RETIM;Original Retinex
TP_LOCALLAB_RETITOOLFRA;Retinex Outils
+TP_LOCALLAB_RETIFRAME_TOOLTIP; L'utilisation de Retinex peut être bénéfique pour le traitement des images: \ nqui sont floues, brumeuses ou ayant un voile de brouillard (en complément de Dehaz). \ Navec d'importants écarts de luminance. \ N où l'utilisateur recherche des effets spéciaux (cartographie des tons…)
TP_LOCALLAB_RETI_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 traitée\nLe temps de traitements dépend de "scale" (échelle) (soyez prudent avec les hautes valeurs ).\nA utiliser de préférence avec de grand 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.\nOptimisation pas utilsée en prévisualisation
TP_LOCALLAB_RETI_LIGHTDARK_TOOLTIP;Have no effect when the value "Lightness = 1" or "Darkness =2" is chosen.\nIn other cases, the last step of "Multiple scale Retinex" is applied an algorithm close to "local contrast", these 2 cursors, associated with "Strength" will allow to play upstream on the local contrast.
TP_LOCALLAB_RETI_LIMDOFFS_TOOLTIP;Play on internal parameters to optimize response.\nLook at the "restored datas" indicators "near" min=0 and max=32768 (log mode), but others values are possible.
@@ -2172,8 +2199,7 @@ TP_LOCALLAB_SENSIH;Etendue
TP_LOCALLAB_SENSIH_TOOLTIP;Ajuste Etendue de l'action:\nLes petites valeurs limitent l'action aux couleurs très similaires à celles sous le centre du spot.\nHautes valeurs laissent l'outil agir sur une large plage de couleurs.
TP_LOCALLAB_SENSILOG;Etendue
TP_LOCALLAB_SENSIS;Etendue
-TP_LOCALLAB_SENSIS_TOOLTIP;Ajuste Etendue de l'action:\nLes petites valeurs limitent l'action aux couleurs très similaires à celles sous le centre du spot.\nHautes valeurs laissent l'outil agir sur une large plage de couleurs.\nValeurs inférieures à 20 conduisent à un meilleur algorithme.
-TP_LOCALLAB_SENSI_TOOLTIP;Ajuste Etendue de l'action:\nLes petites valeurs limitent l'action aux couleurs très similaires à celles sous le centre du spot.\nHautes valeurs laissent l'outil agir sur une large plage de couleurs.\nValeurs inférieures à 20 conduisent à un meilleur algorithme.
+TP_LOCALLAB_SENSI_TOOLTIP;Ajuste Etendue de l'action:\nLes petites valeurs limitent l'action aux couleurs très similaires à celles sous le centre du spot.\nHautes valeurs laissent l'outil agir sur une large plage de couleurs.
TP_LOCALLAB_SENSIMASK_TOOLTIP;Ajuste Etendue pour ce masque commun.\nAgit sur l'écart entre l'image originale et le masque.\nLes références (luma, chroma, teinte) sont celles du centre du RT-spot\n\nVous pouvez aussi agir sur le deltaE interne au masque avec 'Etendue Masque deltaE image' dans 'Réglages'
TP_LOCALLAB_SETTINGS;Réglages
TP_LOCALLAB_SH1;Ombres Lumières
@@ -2182,7 +2208,9 @@ TP_LOCALLAB_SHADEX;Ombres
TP_LOCALLAB_SHADEXCOMP;Compression ombres & profondeur tonale
TP_LOCALLAB_SHADHIGH;Ombres/Lumières - Egaliseur tonal
TP_LOCALLAB_SHADOWHIGHLIGHT_TOOLTIP;Peut être utilisé - ou en complement - du module Exposition dans les cas difficiles.\nUtiliser réduction du bruit Denoise peut être nécessaire : éclaicir les ombres.\n\nPeut être utilisé comme un filtre gradué (augmenter Etendue)
-TP_LOCALLAB_SHAMASKCOL;masque ombres
+TP_LOCALLAB_SHAMASKCOL;Ombres
+TP_LOCALLAB_SHADMASK_TOOLTIP;Relève les ombres du masque de la même manière que l'algorithme "ombres/lumières"
+TP_LOCALLAB_SHADHMASK_TOOLTIP;Abaisse les hautes lumières du masque de la même manière que l'algorithme "ombres/lumières"
TP_LOCALLAB_SHAPETYPE;Forme aire RT-spot
TP_LOCALLAB_SHAPE_TOOLTIP;Ellipse est le mode normal.\nRectangle peut être utilé dans certains cas, par exemple pour travailler en image complète en conjonction avec les délimiteurs en dehors de la prévisualisation, transition = 100.\n\nPolygone - Beziers sont en attente de GUI...
TP_LOCALLAB_SHARAMOUNT;Quantité
@@ -2210,7 +2238,7 @@ TP_LOCALLAB_SHOWMASKTYP1;Flouter & Bruit
TP_LOCALLAB_SHOWMASKTYP2;Réduction du bruit
TP_LOCALLAB_SHOWMASKTYP3;Flouter & Bruit + De-bruite
TP_LOCALLAB_SHOWMASKTYP_TOOLTIP;Masque et modifications peuvent être choisis.\nFlouter et bruit: dans ce cas il n'est pas utilisé pour 'Réduction du bruit'.\nRéduction du bruit : dans ce cas il n'est pas utilisé pour 'flouter et bruit'.\n\nFlouter et bruit + Réduction du bruit : le masque est partagé, faire attention à 'montrer modifications' et 'Etendue'
-TP_LOCALLAB_SHOWMNONE;Rien
+TP_LOCALLAB_SHOWMNONE;Montrer image modifiée
TP_LOCALLAB_SHOWMODIF;Montrer modifications sans masque
TP_LOCALLAB_SHOWMODIFMASK;Montrer modifications avec masque
TP_LOCALLAB_SHOWNORMAL;Normalise luminance (non)
@@ -2225,16 +2253,17 @@ TP_LOCALLAB_SHOWT;Masque et modifications
TP_LOCALLAB_SHOWVI;Masque et modifications
TP_LOCALLAB_SHRESFRA;Ombres/Lumières
TP_LOCALLAB_SHTRC_TOOLTIP;Modifie les tons de l'image en agissant sur la TRC (Tone Response Curve).\nGamma agit principalement sur les tons lumineux.\nSlope (pente) agit principalement sur les tons sombres.
-TP_LOCALLAB_SH_TOOLNAME;Ombres-lumières & Egaliser tonal - 5
+TP_LOCALLAB_SH_TOOLNAME;Ombres/lumières & Egaliseur tonal - 5
TP_LOCALLAB_SIGMAWAV;Atténuation Réponse
TP_LOCALLAB_SIM;Simple
-TP_LOCALLAB_SLOMASKCOL;Pente (slope) masque
+TP_LOCALLAB_SLOMASKCOL;Pente (slope)
+TP_LOCALLAB_SLOMASK_TOOLTIP;Gamma et Pente (Slope) autorise une transformation du masque en douceur et sans artefacts en modifiant progressivement "L" pour éviter les discontinuité.
TP_LOCALLAB_SLOSH;Pente
TP_LOCALLAB_SOFT;Lumière douce - Original Retinex
TP_LOCALLAB_SOFTM;Lumière douce (soft light)
-//TP_LOCALLAB_SOFTMETHOD_TOOLTIP;Original Retinex est très différent des autres méthodes Retinex.\nIl agit sur les gris et équilibre la luminance.\nC'est une émulation de "Dodge" and "Burn"
TP_LOCALLAB_SOFTMETHOD_TOOLTIP;Applique un mélange Lumière douce. Effectue une émulation de "dodge and burn" en utilisant l'algorithme original de retinex.
TP_LOCALLAB_SOFTRADIUSCOL;Rayon adoucir
+TP_LOCALLAB_SOFTRADIUSCOL_TOOLTIP;Applique un filtre guidé à l'image de sortie pour réduire les éventuels artefacts.
TP_LOCALLAB_SOFTRETI;Reduire artefact ΔE
TP_LOCALLAB_SOFTRETI_TOOLTIP;Prend en compte ΔE pour améliorer Transmission map
TP_LOCALLAB_SOFT_TOOLNAME;Lumière douce & Original Retinex - 6
@@ -2248,16 +2277,18 @@ TP_LOCALLAB_STR;Force
TP_LOCALLAB_STRBL;Force
TP_LOCALLAB_STREN;Compression Force
TP_LOCALLAB_STRENG;Force
+TP_LOCALLAB_STRENGRID_TOOLTIP;Vous pouvez ajuster l'effet désiré avec "force", mais vous pouvez aussi utiliser la fonction "Etendue" qui permet de délimiter l'action (par exemple, pour isoler une couleur particulière).
TP_LOCALLAB_STRENGR;Force
TP_LOCALLAB_STRENGTH;Bruit
TP_LOCALLAB_STRGRID;Force
TP_LOCALLAB_STRRETI_TOOLTIP;Si force Retinex < 0.2 seul Dehaze est activé.\nSi force Retinex >= 0.1 Dehaze est en mode luminance.
TP_LOCALLAB_STRUC;Structure
TP_LOCALLAB_STRUCCOL;Structure
-TP_LOCALLAB_STRUCCOL1;Spot 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 (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_STRUMASKCOL;Structure 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_STRUSTRMASK_TOOLTIP;Un usage modéré de ce curseur est recommandé!
TP_LOCALLAB_STYPE;Forme méthode
TP_LOCALLAB_STYPE_TOOLTIP;Vous pouvez choisir entre:\nSymétrique - gauche et droite sont liés, haut et bas sont liés.\nIndépendent - toutes les saisies sont indépendantes.
TP_LOCALLAB_SYM;Symétrique (souris)
@@ -2279,7 +2310,9 @@ TP_LOCALLAB_TONEMAP_TOOLTIP;Compression tonal - menu principal doit être désac
TP_LOCALLAB_TONEMASCALE_TOOLTIP;Ce contrôle donne le pouvoir de différencier le contraste "local" et "global".\nPlus il est important, plus un détail sera accentué.
TP_LOCALLAB_TONE_TOOLNAME;Compression tonale - 4
TP_LOCALLAB_TOOLCOL;Masque Structure comme outil
-TP_LOCALLAB_TOOLMASK;Outils
+TP_LOCALLAB_TOOLCOLFRMASK_TOOLTIP;Autorise de modifier le masque s'il a été créé
+TP_LOCALLAB_TOOLMASK;Outils du masque
+TP_LOCALLAB_TOOLMASK_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_TRANSIT;Transition - Gradient
TP_LOCALLAB_TRANSITGRAD;Transition différentiation XY
TP_LOCALLAB_TRANSITGRAD_TOOLTIP;Change la transition des abscisses vers les ordonnées
@@ -2293,25 +2326,51 @@ TP_LOCALLAB_TRANSMISSION_TOOLTIP;Transmission en accord à transmission.\nAbsci
TP_LOCALLAB_USEMASK;Utiliser masque
TP_LOCALLAB_VART;Variance (contraste)
TP_LOCALLAB_VIBRANCE;Vibrance - Chaud & Froid
+TP_LOCALLAB_VIBRA_TOOLTIP;Ajuste vibrance (Globalement identique à Couleur ajustement).\nAmène l'équivalent d'une balance des blancs en utilisant l'algorithme CIECAM.
TP_LOCALLAB_VIB_TOOLNAME;Vibrance - Chaud & Froid - 3
TP_LOCALLAB_SOFT_TOOLNAME;Lumière douce & Original Retinex - 6
-TP_LOCALLAB_BLUR_TOOLNAME;Adoucir Flouter Grain & De-bruite - 1
+TP_LOCALLAB_BLUR_TOOLNAME;Flouter/Grain & Réduction du bruit - 1
TP_LOCALLAB_TONE_TOOLNAME;Compression tonale - 4
TP_LOCALLAB_RET_TOOLNAME;De-brume & Retinex - 9
TP_LOCALLAB_SHARP_TOOLNAME;Netteté - 8
TP_LOCALLAB_LC_TOOLNAME;Constraste local & Ondelettes (Défauts) - 7
-TP_LOCALLAB_CBDL_TOOLNAME;Contraste par Niveau détail (Défauts) - 2
+TP_LOCALLAB_CBDL_TOOLNAME;Contraste par Niveau détail - 2
TP_LOCALLAB_LOG_TOOLNAME;Codage log - 0
TP_LOCALLAB_MASKCOM_TOOLNAME;Masque Commun Couleur - 13
TP_LOCALLAB_VIS_TOOLTIP;Click pour montrer/cacher le Spot sélectionné.\nCtrl+click pour montrer/cacher tous les Spot.
-TP_LOCALLAB_WAMASKCOL;Ψ Masque Niveau Ondelettes
+TP_LOCALLAB_WAMASKCOL;Ψ Niveau Ondelettes
TP_LOCALLAB_WARM;Chaud - Froid & Artefacts de couleur
TP_LOCALLAB_WARM_TOOLTIP;Ce curseur utilise l'algorithme Ciecam et agit comme une Balance des blancs, il prut réchauffer ou refroidir cool la zone concernée.\nIl peut aussi dans certains réduire les artefacts colorés.
TP_LOCALLAB_WASDEN_TOOLTIP;De-bruite luminance pour les 3 premiers niveaux (fin).\nLa limite droite de la courbe correspond à gros : niveau 3 et au delà.
+TP_LOCALLAB_WAT_WAVSHAPE_TOOLTIP;Contraste faible à élevé de gauche à droite en abscisse\nAugmente ou réduit le contraste en ordonnée.
+TP_LOCALLAB_WAT_LEVELLOCCONTRAST_TOOLTIP;Contraste faible à élevé de gauche à droite en abscisse\nAugmente ou réduit le contraste en ordonnée.
+TP_LOCALLAB_WAT_SIGMALC_TOOLTIP;L'effet sur le contraste local est maximum pour les valeurs moyennes, et affaibli pour les valeurs faibles ou élevées.\n Le curseur contrôle comment s'effectue les changements pour ces valeurs extêmse.\n Plus la valeur du curseur est élevée, plus grande sera l'étendue qui recevra le maximum d'ajustements, ainsi que le risque de voir apparaître des artefacts.\n .Plus faible sera cette valeur, plus les différences de contraste seront atténuées
+TP_LOCALLAB_WAT_BLURLC_TOOLTIP;Par défaut les 3 dimensions de L*a*b* luminance et couleur sont concernées par le floutage.\nCase cochée - luminance seulement
+TP_LOCALLAB_WAT_THRESHOLDWAV_TOOLTIP;Etendue des niveaux d’ondelettes utilisée dans l’ensemble du module “wavelets”
+TP_LOCALLAB_WAT_EXPRESID_TOOLTIP;Image résiduelle, a le même comportement que l'image principale
+TP_LOCALLAB_WAT_CLARIL_TOOLTIP;"Fusion luma" est utilisée pour selectionner l'intensité de l'effet désiré sur la luminance.
+TP_LOCALLAB_WAT_CLARIC_TOOLTIP;"Fusion chroma" est utilisée pour selectionner l'intensité de l'effet désiré sur la luminance.
+TP_LOCALLAB_WAT_ORIGLC_TOOLTIP;"Fusion seulement avec image originale", empêche les actions "Wavelet Pyramid" d'interférer avec "Claté" and "Masque netteté"
+TP_LOCALLAB_WAT_STRWAV_TOOLTIP;Permet au contraste local de varier en fonction d'un gradient et d'un angle. La variation du signal de la luminance signal est prise en compte et non pas la luminance.
+TP_LOCALLAB_WAT_CONTOFFSET_TOOLTIP;Décalage modifie la balance entre faible contraste et contraste élévé.\nLes hautes valeurs amplifient les changements de contraste pour les détails à contraste élévé, alors que les faibles valeurs vont amplifier les détails à contraste faible .\nEn selectionant des valeurs faibles vous pouvez ainsi sélectionner les zones de contrastes qui seront accentuées.
+TP_LOCALLAB_WAT_CONTCHROMALEV_TOOLTIP;"Niveaux de Chroma": ajuste les valeurs "a" et "b" des composantes L*a*b* comme une proportion de la luminance.
+TP_LOCALLAB_WAT_WAVCBDL_TOOLTIP;Similaira à Contraste par niveaux de détail. Des détails fins au gros details de gauche à droite en abscisse.
+TP_LOCALLAB_WAT_STRENGTHW_TOOLTIP;Intensité de la détection d'effet de bord
+TP_LOCALLAB_WAT_LOCCONTRASTEDG_TOOLTIP;Vous pouvez agir sur la répartition du contraste local selon l'intensité initiale du contraste par niveaux d'ondelettes.\nCeci aura comme conséquences de modifier l'effet de perspective et de relief de l'image, et/ou réduire les contrastes pour les très faibles niveaux de contraste initial
+TP_LOCALLAB_WAT_GRADW_TOOLTIP;Plus vous déplacez le curseur à droite, plus l'algorithme de détection sera efficace, moins les effets du contraste local seront sensibles
+TP_LOCALLAB_WAT_WAVESHOW_TOOLTIP;Montre l'ensemble des outils "Netteté bords".\nLa lecture de la documentation wavelet est recommandée
+TP_LOCALLAB_WAT_WAVLEVELBLUR_TOOLTIP;Permet d'ajuster l'effet maximum de floutage des niveaux
+TP_LOCALLAB_WAT_WAVBLURCURV_TOOLTIP;Vous permet de flouter chaque niveau de décomposition.\nEn abscisse de gauche à droite, les niveaux de décomposition du plus fin au plus gros
+TP_LOCALLAB_WAT_RESIDBLUR_TOOLTIP;Floute l'image résiduelle, indépendamment des niveaux
+TP_LOCALLAB_WAT_WAVTM_TOOLTIP;La partie inférieure (négative) compresse chaque niveau de décomposition créant un effet tone mapping.\nLa partie supérieure (positive) atténue le contraste par niveau.\nEn abscisse de gauche à droite, les niveaux de décomposition du plus fin au plus gros
+TP_LOCALLAB_WAT_BALTHRES_TOOLTIP;Equilibre l'action à l'intérieur de chaque niveau
+TP_LOCALLAB_WAT_RESIDCOMP_TOOLTIP;Commpresse l'image résiduelle afin d'accentuer ou réduire les contrastes
+TP_LOCALLAB_WAT_DELTABAL_TOOLTIP;En déplaçant le curseur à gauche, les bas niveaux sont accentués, et vers la droite ce sont les bas niveaux qui sont réduits et les hauts niveaux accentués
+TP_LOCALLAB_WAT_WAVDELTABAL_TOOLTIP;Agit sur la balance des trois directions horizontale - verticale - diagonale - en fonction de la luminance de l'image.\nPar défaut les parties sombres ou hautes lumières sont réduites afin d'éviter les artefacts
TP_LOCALLAB_WAV;Contrast local niveau
TP_LOCALLAB_WAVBLUR_TOOLTIP;Réalise un flou pour chaque niveau de décomposition, également pour l'image résiduelle.
TP_LOCALLAB_WAVCOMP;Compression par niveau
-TP_LOCALLAB_WAVCOMPRE;(de)Compression par niveau
+TP_LOCALLAB_WAVCOMPRE;Compression par niveau
TP_LOCALLAB_WAVCOMPRE_TOOLTIP;Réalise un 'Tone-mapping' ou une réduction du contraste local par niveau.\nEn abscisse: niveaux
TP_LOCALLAB_WAVCOMP_TOOLTIP;Réalise un contrast local en fonction de la direction de la décomposition en ondelettes : horizontal, vertical, diagonal
TP_LOCALLAB_WAVCON;Contraste par niveau
@@ -2324,7 +2383,8 @@ TP_LOCALLAB_WAVGRAD_TOOLTIP;Filtre gradué pour Contraste local "luminance"
TP_LOCALLAB_WAVHIGH;Ψ Ondelette haut
TP_LOCALLAB_WAVLEV;Flouter par niveau
TP_LOCALLAB_WAVLOW;Ψ Ondelette bas
-TP_LOCALLAB_WAVMASK;Ψ Masque Niveau contraste local
+TP_LOCALLAB_WAVMASK;Ψ Niveau contraste local
+TP_LOCALLAB_WAVEMASK_LEVEL_TOOLTIP;Amplitude des niveaux d'ondelettes utilisés par “Local contrast”
TP_LOCALLAB_WAVMASK_TOOLTIP;Autorise un travail fin sur les masques niveaux de contraste (structure)
TP_LOCALLAB_WAVMED;Ψ Ondelette normal
TP_LOCALLAB_WEDIANHI;Median Haut
diff --git a/rtdata/languages/default b/rtdata/languages/default
index 041bb29f7..e17054528 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -222,8 +222,10 @@ GENERAL_BEFORE;Before
GENERAL_CANCEL;Cancel
GENERAL_CLOSE;Close
GENERAL_CURRENT;Current
+GENERAL_DELETE_ALL;Delete all
GENERAL_DISABLE;Disable
GENERAL_DISABLED;Disabled
+GENERAL_EDIT;Edit
GENERAL_ENABLE;Enable
GENERAL_ENABLED;Enabled
GENERAL_FILE;File
@@ -245,11 +247,20 @@ GIMP_PLUGIN_INFO;Welcome to the RawTherapee GIMP plugin!\nOnce you are done edit
HISTOGRAM_TOOLTIP_B;Show/Hide blue histogram.
HISTOGRAM_TOOLTIP_BAR;Show/Hide RGB indicator bar.
HISTOGRAM_TOOLTIP_CHRO;Show/Hide chromaticity histogram.
+HISTOGRAM_TOOLTIP_CROSSHAIR;Show/Hide indicator crosshair.
HISTOGRAM_TOOLTIP_G;Show/Hide green histogram.
HISTOGRAM_TOOLTIP_L;Show/Hide CIELab luminance histogram.
HISTOGRAM_TOOLTIP_MODE;Toggle between linear, log-linear and log-log scaling of the histogram.
HISTOGRAM_TOOLTIP_R;Show/Hide red histogram.
HISTOGRAM_TOOLTIP_RAW;Show/Hide raw histogram.
+HISTOGRAM_TOOLTIP_SHOW_OPTIONS;Toggle visibility of the scope option buttons.
+HISTOGRAM_TOOLTIP_TRACE_BRIGHTNESS;Adjust scope brightness.
+HISTOGRAM_TOOLTIP_TYPE_HISTOGRAM;Histogram
+HISTOGRAM_TOOLTIP_TYPE_HISTOGRAM_RAW;Raw Histogram
+HISTOGRAM_TOOLTIP_TYPE_PARADE;RGB Parade
+HISTOGRAM_TOOLTIP_TYPE_WAVEFORM;Waveform
+HISTOGRAM_TOOLTIP_TYPE_VECTORSCOPE_HC;Hue-Chroma Vectorscope
+HISTOGRAM_TOOLTIP_TYPE_VECTORSCOPE_HS;Hue-Saturation Vectorscope
HISTORY_CHANGED;Changed
HISTORY_CUSTOMCURVE;Custom curve
HISTORY_FROMCLIPBOARD;From clipboard
@@ -834,11 +845,11 @@ HISTORY_MSG_580;Local - Denoise
HISTORY_MSG_581;Local - deNoise lum f 1
HISTORY_MSG_582;Local - deNoise lum c
HISTORY_MSG_583;Local - deNoise lum detail
-HISTORY_MSG_584;Local - deNoise Equalizer white-black
+HISTORY_MSG_584;Local - deNoise equalizer White-Black
HISTORY_MSG_585;Local - deNoise chro f
HISTORY_MSG_586;Local - deNoise chro c
HISTORY_MSG_587;Local - deNoise chro detail
-HISTORY_MSG_588;Local - deNoise Equalizer blue-red
+HISTORY_MSG_588;Local - deNoise equalizer Blue-Red
HISTORY_MSG_589;Local - deNoise bilateral
HISTORY_MSG_590;Local - deNoise Scope
HISTORY_MSG_591;Local - Avoid color shift
@@ -1084,51 +1095,47 @@ HISTORY_MSG_838;Local - Vib gradient strength H
HISTORY_MSG_839;Local - Software complexity
HISTORY_MSG_840;Local - CL Curve
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 - log encoding
-HISTORY_MSG_846;Local - Encoding auto
-HISTORY_MSG_847;Local - Source Gray
-HISTORY_MSG_848;Local - Source Gray auto
-HISTORY_MSG_849;Local - Auto Grayon
-HISTORY_MSG_850;Local - Black Ev
-HISTORY_MSG_851;Local - White Ev
-HISTORY_MSG_852;Local - Target Gray
-HISTORY_MSG_853;Local - Local contrast
-HISTORY_MSG_854;Local - Scope encoding log
-HISTORY_MSG_855;Local - Entire image
-HISTORY_MSG_856;Local - Base log
-HISTORY_MSG_857;Local - Contrast Blur Residual
-HISTORY_MSG_858;Local - Contrast Luminance only
-HISTORY_MSG_859;Local - Contrast Maximum Blur levels
-HISTORY_MSG_860;Local - Contrast Curve Blur levels
-HISTORY_MSG_861;Local - Contrast Curve Contrast levels
-HISTORY_MSG_862;Local - Contrast Sigma luminance
-HISTORY_MSG_863;Local - Contrast Merge Original
-HISTORY_MSG_864;Local - Directional sigma
-HISTORY_MSG_865;Local - Directional delta
-HISTORY_MSG_866;Local - Contrast Curve Compression
-HISTORY_MSG_867;Local - Contrast Amount residual
-HISTORY_MSG_868;Local - balance ΔE C-H
-HISTORY_MSG_869;Local - denoise curve luminance
-HISTORY_MSG_870;Local - LC mask curve LC(H)
-HISTORY_MSG_871;Local - LC mask curve C(C)
-HISTORY_MSG_872;Local - LC mask curve L(L)
-HISTORY_MSG_873;Local - LC mask enable
-HISTORY_MSG_875;Local - LC mask blend
-HISTORY_MSG_876;Local - LC mask radius
-HISTORY_MSG_877;Local - LC mask chroma
-HISTORY_MSG_878;Local - LC mask curve contrast
-HISTORY_MSG_879;Local - LC Chroma levels
-HISTORY_MSG_880;Local - LC Chroma blur levels
-HISTORY_MSG_881;Local - Contrast Offset Luminance
-HISTORY_MSG_882;Local - Contrast Blur
-HISTORY_MSG_883;Local - Contrast By Levels
-HISTORY_MSG_884;Local - Contrast Dynamic Range Laplacian
-HISTORY_MSG_885;Local - Contrast Dynamic Range Wavelet
-HISTORY_MSG_886;Local - Contrast Wavelet Curve Compression
-HISTORY_MSG_887;Local - Contrast Wavelet Compression Residual
+HISTORY_MSG_842;Local - Contrast Threshold
+HISTORY_MSG_843;Local - Radius
+HISTORY_MSG_845;Local - Log encoding
+HISTORY_MSG_846;Local - Log encoding auto
+HISTORY_MSG_847;Local - Log encoding Source
+HISTORY_MSG_849;Local - Log encoding Source auto
+HISTORY_MSG_850;Local - Log encoding B_Ev
+HISTORY_MSG_851;Local - Log encoding W_Ev
+HISTORY_MSG_852;Local - Log encoding Target
+HISTORY_MSG_853;Local - Log encodind loc contrast
+HISTORY_MSG_854;Local - Log encodind Scope
+HISTORY_MSG_855;Local - Log encoding Entire image
+HISTORY_MSG_856;Local - Log encoding Shadows range
+HISTORY_MSG_857;Local - Wavelet blur residual
+HISTORY_MSG_858;Local - Wavelet blur luminance only
+HISTORY_MSG_859;Local - Wavelet max blur
+HISTORY_MSG_860;Local - Wavelet blur levels
+HISTORY_MSG_861;Local - Wavelet contrast levels
+HISTORY_MSG_862;Local - Wavelet contrast attenuation
+HISTORY_MSG_863;Local - Wavelet merge original image
+HISTORY_MSG_864;Local - Wavelet dir contrast attenuation
+HISTORY_MSG_865;Local - Wavelet dir contrast delta
+HISTORY_MSG_866;Local - Wavelet dir compression
+HISTORY_MSG_869;Local - Denoise by level
+HISTORY_MSG_870;Local - Wavelet mask curve H
+HISTORY_MSG_871;Local - Wavelet mask curve C
+HISTORY_MSG_872;Local - Wavelet mask curve L
+HISTORY_MSG_873;Local - Wavelet mask
+HISTORY_MSG_875;Local - Wavelet mask blend
+HISTORY_MSG_876;Local - Wavelet mask smooth
+HISTORY_MSG_877;Local - Wavelet mask chroma
+HISTORY_MSG_878;Local - Wavelet mask contrast curve
+HISTORY_MSG_879;Local - Wavelet contrast chroma
+HISTORY_MSG_880;Local - Wavelet blur chroma
+HISTORY_MSG_881;Local - Wavelet contrast offset
+HISTORY_MSG_882;Local - Wavelet blur
+HISTORY_MSG_883;Local - Wavelet contrast by level
+HISTORY_MSG_884;Local - Wavelet dir contrast
+HISTORY_MSG_885;Local - Wavelet tone mapping
+HISTORY_MSG_886;Local - Wavelet tone mapping compress
+HISTORY_MSG_887;Local - Wavelet tone mapping compress residual
HISTORY_MSG_888;Local - Contrast Wavelet Balance Threshold
HISTORY_MSG_889;Local - Contrast Wavelet Graduated Strength
HISTORY_MSG_890;Local - Contrast Wavelet Graduated angle
@@ -1166,7 +1173,7 @@ HISTORY_MSG_923;Local - Tool complexity mode
HISTORY_MSG_924;Local - Tool complexity mode
HISTORY_MSG_925;Local - Scope color tools
HISTORY_MSG_926;Local - Show mask type
-HISTORY_MSG_927;Local - Shadow mask
+HISTORY_MSG_927;Local - Shadow
HISTORY_MSG_928;Local - Common color mask
HISTORY_MSG_929;Local - Mask common scope
HISTORY_MSG_930;Local - Mask Common blend luma
@@ -1196,7 +1203,16 @@ 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_957;Local - Denoise mode
+HISTORY_MSG_959;Local - Inverse blur
+HISTORY_MSG_958;Local - Show/hide settings
+HISTORY_MSG_960;Local - Log encoding - cat02
+HISTORY_MSG_961;Local - Log encoding Ciecam
+HISTORY_MSG_962;Local - Log encoding Absolute luminance source
+HISTORY_MSG_963;Local - Log encoding Absolute luminance target
+HISTORY_MSG_964;Local - Log encoding Surround
+HISTORY_MSG_965;Local - Log encoding Saturation s
+HISTORY_MSG_966;Local - Log encoding Contrast J
HISTORY_MSG_BLSHAPE;Blur by level
HISTORY_MSG_BLURCWAV;Blur chroma
HISTORY_MSG_BLURWAV;Blur luminance
@@ -1217,6 +1233,7 @@ 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_CATCOMPLEX;Ciecam complexity
HISTORY_MSG_COMPLEX;Wavelet complexity
HISTORY_MSG_COMPLEXRETI;Retinex complexity
HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth
@@ -1255,6 +1272,7 @@ HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - Corner radius boost
HISTORY_MSG_PERSP_CAM_ANGLE;Perspective - Camera
HISTORY_MSG_PERSP_CAM_FL;Perspective - Camera
HISTORY_MSG_PERSP_CAM_SHIFT;Perspective - Camera
+HISTORY_MSG_PERSP_CTRL_LINE;Perspective - Control lines
HISTORY_MSG_PERSP_METHOD;Perspective - Method
HISTORY_MSG_PERSP_PROJ_ANGLE;Perspective - Recovery
HISTORY_MSG_PERSP_PROJ_ROTATE;Perspective - PCA rotation
@@ -1289,18 +1307,35 @@ HISTORY_MSG_WAVBL;Blur levels
HISTORY_MSG_WAVCHROMCO;Chroma coarse
HISTORY_MSG_WAVCHROMFI;Chroma fine
HISTORY_MSG_WAVCLARI;Clarity
+HISTORY_MSG_WAVDENLH;Level 5
+HISTORY_MSG_WAVDENOISE;Local contrast
+HISTORY_MSG_WAVDENOISEH;High levels Local contrast
+HISTORY_MSG_WAVDENMET;Local equalizer
+HISTORY_MSG_WAVDETEND;Details soft
HISTORY_MSG_WAVEDGS;Edge stopping
+HISTORY_MSG_WAVGUIDH;Local contrast-Hue equalizer
+HISTORY_MSG_WAVHUE;Equalizer hue
+HISTORY_MSG_WAVLEVDEN;High level local contrast
+HISTORY_MSG_WAVLEVSIGM;Radius
+HISTORY_MSG_WAVLIMDEN;Interaction 56 14
HISTORY_MSG_WAVLOWTHR;Threshold low contrast
HISTORY_MSG_WAVMERGEC;Merge C
HISTORY_MSG_WAVMERGEL;Merge L
+HISTORY_MSG_WAVMIXMET;Reference local contrast
HISTORY_MSG_WAVOFFSET;Offset
HISTORY_MSG_WAVOLDSH;Old algorithm
+HISTORY_MSG_WAVQUAMET;Denoise mode
HISTORY_MSG_WAVRADIUS;Radius shadows-highlights
HISTORY_MSG_WAVSCALE;Scale
HISTORY_MSG_WAVSHOWMASK;Show wavelet mask
HISTORY_MSG_WAVSIGMA;Attenuation response
+HISTORY_MSG_WAVSIGM;Sigma
HISTORY_MSG_WAVSOFTRAD;Soft radius clarity
HISTORY_MSG_WAVSOFTRADEND;Soft radius final
+HISTORY_MSG_WAVSLIMET;Method
+HISTORY_MSG_WAVTHRDEN;Threshold local contrast
+HISTORY_MSG_WAVTHREND;Threshold local contrast
+HISTORY_MSG_WAVSTREND;Strength soft
HISTORY_MSG_WAVUSHAMET;Clarity method
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
@@ -1323,7 +1358,7 @@ ICCPROFCREATOR_ILL_65;D65
ICCPROFCREATOR_ILL_80;D80
ICCPROFCREATOR_ILL_DEF;Default
ICCPROFCREATOR_ILL_INC;StdA 2856K
-ICCPROFCREATOR_ILL_TOOLTIP;You can only set the illuminant for ICC v4 profiles.
+ICCPROFCREATOR_ILL_TOOLTIP;You can set the illuminant for ICC v4 profiles and also for ICC v2 profiles.
ICCPROFCREATOR_PRIMARIES;Primaries:
ICCPROFCREATOR_PRIM_ACESP0;ACES AP0
ICCPROFCREATOR_PRIM_ACESP1;ACES AP1
@@ -1340,7 +1375,7 @@ ICCPROFCREATOR_PRIM_REC2020;Rec2020
ICCPROFCREATOR_PRIM_REDX;Red X
ICCPROFCREATOR_PRIM_REDY;Red Y
ICCPROFCREATOR_PRIM_SRGB;sRGB
-ICCPROFCREATOR_PRIM_TOOLTIP;You can only set custom primaries for ICC v4 profiles.
+ICCPROFCREATOR_PRIM_TOOLTIP;You can set custom primaries for ICC v4 profiles and also for ICC v2 profiles.
ICCPROFCREATOR_PRIM_WIDEG;Widegamut
ICCPROFCREATOR_PROF_V2;ICC v2
ICCPROFCREATOR_PROF_V4;ICC v4
@@ -1841,6 +1876,7 @@ THRESHOLDSELECTOR_TR;Top-right
TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen the tool is active:\n- Add a picker: left-click.\n- Drag a picker: left-click and drag.\n- Delete a picker: right-click.\n- Delete all pickers: Ctrl+Shift+right-click.\n- Revert to hand tool: right-click outside any picker.
TOOLBAR_TOOLTIP_CROP;Crop selection.\nShortcut: c\nMove the crop using Shift+mouse drag.
TOOLBAR_TOOLTIP_HAND;Hand tool.\nShortcut: h
+TOOLBAR_TOOLTIP_PERSPECTIVE;Perspective Correction\n\nEdit control lines to correct perspective distortion. Click this button again to apply correction.
TOOLBAR_TOOLTIP_STRAIGHTEN;Straighten / fine rotation.\nShortcut: s\n\nIndicate the vertical or horizontal by drawing a guide line over the image preview. Angle of rotation will be shown next to the guide line. Center of rotation is the geometrical center of the image.
TOOLBAR_TOOLTIP_WB;Spot white balance.\nShortcut: w
TP_BWMIX_ALGO;Algorithm OYCPM
@@ -1917,6 +1953,7 @@ TP_COARSETRAF_TOOLTIP_ROTLEFT;Rotate left.\n\nShortcuts:\n[ - Multiple Ed
TP_COARSETRAF_TOOLTIP_ROTRIGHT;Rotate right.\n\nShortcuts:\n] - Multiple Editor Tabs Mode,\nAlt-] - Single Editor Tab Mode.
TP_COARSETRAF_TOOLTIP_VFLIP;Flip vertically.
TP_COLORAPP_ABSOLUTELUMINANCE;Absolute luminance
+TP_COLORAPP_ADAPSCEN_TOOLTIP;It corresponds to the luminance at the time of the shooting in candelas per m2, calculated automatically from the exif data.
TP_COLORAPP_ALGO;Algorithm
TP_COLORAPP_ALGO_ALL;All
TP_COLORAPP_ALGO_JC;Lightness + Chroma (JC)
@@ -1926,33 +1963,37 @@ TP_COLORAPP_ALGO_TOOLTIP;Lets you choose between parameter subsets or all parame
TP_COLORAPP_BADPIXSL;Hot/bad pixel filter
TP_COLORAPP_BADPIXSL_TOOLTIP;Suppression of hot/bad (brightly colored) pixels.\n0 = No effect\n1 = Median\n2 = Gaussian.\nAlternatively, adjust the image to avoid very dark shadows.\n\nThese artifacts are due to limitations of CIECAM02.
TP_COLORAPP_BRIGHT;Brightness (Q)
-TP_COLORAPP_BRIGHT_TOOLTIP;Brightness in CIECAM02 takes into account the white's luminosity and differs from L*a*b* and RGB brightness.
+TP_COLORAPP_BRIGHT_TOOLTIP;Brightness in CIECAM02 is the amount of perceived light emanating from a stimulus and differs from L*a*b* and RGB brightness.
TP_COLORAPP_CAT02ADAPTATION_TOOLTIP;When setting manually, values above 65 are recommended.
TP_COLORAPP_CHROMA;Chroma (C)
TP_COLORAPP_CHROMA_M;Colorfulness (M)
-TP_COLORAPP_CHROMA_M_TOOLTIP;Colorfulness in CIECAM02 differs from L*a*b* and RGB colorfulness.
+TP_COLORAPP_CHROMA_M_TOOLTIP;Colorfulness in CIECAM02 is the perceived amount of hue in relation to gray, an indicator that a stimulus appears to be more or less colored.
TP_COLORAPP_CHROMA_S;Saturation (S)
-TP_COLORAPP_CHROMA_S_TOOLTIP;Saturation in CIECAM02 differs from L*a*b* and RGB saturation.
-TP_COLORAPP_CHROMA_TOOLTIP;Chroma in CIECAM02 differs from L*a*b* and RGB chroma.
+TP_COLORAPP_CHROMA_S_TOOLTIP;Saturation in CIECAM02 corresponds to the color of a stimulus in relation to its own brightness, differs from L*a*b* and RGB saturation.
+TP_COLORAPP_CHROMA_TOOLTIP;Chroma in CIECAM02 corresponds to the color of a stimulus relative to the clarity of a stimulus that appears white under identical conditions, differs from L*a*b* and RGB chroma.
TP_COLORAPP_CIECAT_DEGREE;CAT02 adaptation
-TP_COLORAPP_CONTRAST;Contrast (J)
+TP_COLORAPP_CONTRAST;Contrast (J),
TP_COLORAPP_CONTRAST_Q;Contrast (Q)
-TP_COLORAPP_CONTRAST_Q_TOOLTIP;Differs from L*a*b* and RGB contrast.
-TP_COLORAPP_CONTRAST_TOOLTIP;Differs from L*a*b* and RGB contrast.
+TP_COLORAPP_CONTRAST_Q_TOOLTIP;Contrast (Q) based on brightness, differs from L*a*b* and RGB contrast.
+TP_COLORAPP_CONTRAST_TOOLTIP;Contrast (J) based on lightness, differs from L*a*b* and RGB contrast.
TP_COLORAPP_CURVEEDITOR1;Tone curve 1
-TP_COLORAPP_CURVEEDITOR1_TOOLTIP;Shows the histogram of L* (L*a*b*) before CIECAM02.\nIf the "Show CIECAM02 output histograms in curves" checkbox is enabled, shows the histogram of J or Q after CIECAM02.\n\nJ and Q are not shown in the main histogram panel.\n\nFor final output refer to the main histogram panel.
+TP_COLORAPP_CURVEEDITOR1_TOOLTIP;Shows the histogram of L* (L*a*b*) before CIECAM02.\nIf the "CIECAM02 output histograms in curves" checkbox is enabled, shows the histogram of J or Q after CIECAM02.\n\nJ and Q are not shown in the main histogram panel.\n\nFor final output refer to the main histogram panel.
TP_COLORAPP_CURVEEDITOR2;Tone curve 2
TP_COLORAPP_CURVEEDITOR2_TOOLTIP;Same usage as with the second exposure tone curve.
TP_COLORAPP_CURVEEDITOR3;Color curve
-TP_COLORAPP_CURVEEDITOR3_TOOLTIP;Adjust either chroma, saturation or colorfulness.\n\nShows the histogram of chromaticity (L*a*b*) before CIECAM02.\nIf the "Show CIECAM02 output histograms in curves" checkbox is enabled, shows the histogram of C, s or M after CIECAM02.\n\nC, s and M are not shown in the main histogram panel.\nFor final output refer to the main histogram panel.
+TP_COLORAPP_CURVEEDITOR3_TOOLTIP;Adjust either chroma, saturation or colorfulness.\n\nShows the histogram of chromaticity (L*a*b*) before CIECAM02.\nIf the "CIECAM02 output histograms in curves" checkbox is enabled, shows the histogram of C, S or M after CIECAM02.\n\nC, S and M are not shown in the main histogram panel.\nFor final output refer to the main histogram panel.
TP_COLORAPP_DATACIE;CIECAM02 output histograms in curves
TP_COLORAPP_DATACIE_TOOLTIP;When enabled, histograms in CIECAM02 curves show approximate values/ranges for J or Q, and C, s or M after the CIECAM02 adjustments.\nThis selection does not impact the main histogram panel.\n\nWhen disabled, histograms in CIECAM02 curves show L*a*b* values before CIECAM02 adjustments.
+TP_COLORAPP_DEGREE_TOOLTIP;CAT02 is a chromatic adaptation, it converts the values of an image whose white point is that of a given illuminant (for example D65), into new values whose white point is that of the new illuminant - see WP Model (for example D50 or D55).
+TP_COLORAPP_DEGREOUT_TOOLTIP;CAT02 is a chromatic adaptation, it converts the values of an image whose white point is that of a given illuminant (for example D50), into new values whose white point is that of the new illuminant - see WP model (for example D75).
TP_COLORAPP_FREE;Free temp+green + CAT02 + [output]
TP_COLORAPP_GAMUT;Gamut control (L*a*b*)
TP_COLORAPP_GAMUT_TOOLTIP;Allow gamut control in L*a*b* mode.
+TP_COLORAPP_GEN;Settings - Preset
+TP_COLORAPP_GEN_TOOLTIP;This module is based on the CIECAM02 color appearance model, which was designed to better simulate how human vision perceives colors under different lighting conditions, e.g., against different backgrounds.\nIt takes into account the environment of each color and modifies its appearance to get as close as possible to human perception.\nIt also adapts the output to the intended viewing conditions (monitor, TV, projector, printer, etc.) so that the chromatic appearance is preserved across the scene and display environments.
TP_COLORAPP_HUE;Hue (h)
-TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0° and 360°.
TP_COLORAPP_IL41;D41
+TP_COLORAPP_HUE_TOOLTIP;Hue (h) is the degree to which a stimulus can be described as similar to a color described as red, green, blue and yellow.
TP_COLORAPP_IL50;D50
TP_COLORAPP_IL55;D55
TP_COLORAPP_IL60;D60
@@ -1962,26 +2003,29 @@ TP_COLORAPP_ILA;Incandescent StdA 2856K
TP_COLORAPP_ILFREE;Free
TP_COLORAPP_ILLUM;Illuminant
TP_COLORAPP_ILLUM_TOOLTIP;Select the illuminant closest to the shooting conditions.\nIn general D50, but it can change depending on the time and lattitude.
-TP_COLORAPP_LABEL;CIE Color Appearance Model 2002
+TP_COLORAPP_LABEL;Color Appearance & Lighting (CIECAM02)
TP_COLORAPP_LABEL_CAM02;Image Adjustments
TP_COLORAPP_LABEL_SCENE;Scene Conditions
TP_COLORAPP_LABEL_VIEWING;Viewing Conditions
TP_COLORAPP_LIGHT;Lightness (J)
-TP_COLORAPP_LIGHT_TOOLTIP;Lightness in CIECAM02 differs from L*a*b* and RGB lightness.
+TP_COLORAPP_LIGHT_TOOLTIP;Lightness in CIECAM02 is the clarity of a stimulus relative to the clarity of a stimulus that appears white under similar viewing conditions, differs from L*a*b* and RGB lightness.
TP_COLORAPP_MEANLUMINANCE;Mean luminance (Yb%)
TP_COLORAPP_MODEL;WP Model
TP_COLORAPP_MODEL_TOOLTIP;White-Point Model.\n\nWB [RT] + [output]: RT's white balance is used for the scene, CIECAM02 is set to D50, and the output device's white balance is set in Viewing Conditions.\n\nWB [RT+CAT02] + [output]: RT's white balance settings are used by CAT02 and the output device's white balance is set in Viewing Conditions.\n\nFree temp+green + CAT02 + [output]: temp and green are selected by the user, the output device's white balance is set in Viewing Conditions.
TP_COLORAPP_NEUTRAL;Reset
TP_COLORAPP_NEUTRAL_TIP;Reset all sliders checkbox and curves to their default values
TP_COLORAPP_PRESETCAT02;Preset cat02 automatic
-TP_COLORAPP_PRESETCAT02_TIP;Set combobox, sliders, temp, green so that Cat02 automatic is preset.\nYou can change illuminant shooting conditions.\nYou must change Cat02 adaptation Viewing conditions if need.\nYou can change Temperature and Tint Viewing conditions if need, and other settings if need.
+TP_COLORAPP_PRESETCAT02_TIP;Set combobox, sliders, temp, green so that Cat02 automatic is preset.\nYou can change illuminant shooting conditions.\nYou must change Cat02 adaptation Viewing conditions if needed.\nYou can change Temperature and Tint Viewing conditions if needed, and other settings if needed.
TP_COLORAPP_RSTPRO;Red & skin-tones protection
TP_COLORAPP_RSTPRO_TOOLTIP;Red & skin-tones protection affects both sliders and curves.
+TP_COLORAPP_SOURCEF_TOOLTIP;Corresponds to the shooting conditions and how to bring the conditions and data back to a "normal" area. Normal" means average or standard conditions and data, i.e. without taking into account CIECAM corrections.
TP_COLORAPP_SURROUND;Surround
TP_COLORAPP_SURROUND_AVER;Average
TP_COLORAPP_SURROUND_DARK;Dark
TP_COLORAPP_SURROUND_DIM;Dim
TP_COLORAPP_SURROUND_EXDARK;Extremly Dark (Cutsheet)
+TP_COLORAPP_SURROUNDSRC;Surround - Scene Lighting
+TP_COLORAPP_SURSOURCE_TOOLTIP;Changes tones and colors to take into account the Scene conditions.\n\nAverage: Average light environment (standard). The image will not change.\n\nDim: Dim environment. The image will become slightly bright.\n\nDark: Dark environment. The image will become more bright.\n\nExtremly Dark: Extremly dark environment. The image will become very bright.
TP_COLORAPP_SURROUND_TOOLTIP;Changes tones and colors to take into account the viewing conditions of the output device.\n\nAverage: Average light environment (standard). The image will not change.\n\nDim: Dim environment (TV). The image will become slightly dark.\n\nDark: Dark environment (projector). The image will become more dark.\n\nExtremly Dark: Extremly dark environment (cutsheet). The image will become very dark.
TP_COLORAPP_TCMODE_BRIGHTNESS;Brightness
TP_COLORAPP_TCMODE_CHROMA;Chroma
@@ -1997,8 +2041,11 @@ TP_COLORAPP_TEMP_TOOLTIP;To select an illuminant, always set Tint=1.\n\nA temp=2
TP_COLORAPP_TONECIE;Tone mapping using CIECAM02
TP_COLORAPP_TONECIE_TOOLTIP;If this option is disabled, tone mapping is done in L*a*b* space.\nIf this option is enabled, tone mapping is done using CIECAM02.\nThe Tone Mapping tool must be enabled for this setting to take effect.
TP_COLORAPP_VIEWING_ABSOLUTELUMINANCE_TOOLTIP;Absolute luminance of the viewing environment\n(usually 16 cd/m²).
+TP_COLORAPP_VIEWINGF_TOOLTIP;Takes into account the support on which the final image will be viewed (monitor, TV, projector, printer, ...), as well as its environment. This process will take the data coming from process "Image Adjustments" and "bring" it to the support in such a way that the viewing conditions and its environment are taken into account.
TP_COLORAPP_WBCAM;WB [RT+CAT02] + [output]
TP_COLORAPP_WBRT;WB [RT] + [output]
+TP_COLORAPP_YBOUT_TOOLTIP;Yb is the relative luminance of the background, expressed in % of gray. A gray at 18% corresponds to a background luminance expressed in CIE L of 50%.\nThis data must take into account the average luminance of the image
+TP_COLORAPP_YBSCEN_TOOLTIP;Yb is the relative luminance of the background, expressed in % of gray. A gray at 18% corresponds to a background luminance expressed in CIE L of 50%.\nThis data is calculated from the average luminance of the image
TP_COLORTONING_AB;o C/L
TP_COLORTONING_AUTOSAT;Automatic
TP_COLORTONING_BALANCE;Balance
@@ -2339,24 +2386,24 @@ TP_LOCALCONTRAST_LIGHTNESS;Lightness level
TP_LOCALCONTRAST_RADIUS;Radius
TP_LOCALLAB_ACTIV;Luminance only
TP_LOCALLAB_ACTIVSPOT;Enable Spot
-TP_LOCALLAB_ADJ;Equalizer Blue-yellow Red-green
+TP_LOCALLAB_ADJ;Equalizer Blue-Yellow/Red-Green
TP_LOCALLAB_ALL;All rubrics
TP_LOCALLAB_AMOUNT;Amount
TP_LOCALLAB_ARTIF;Shape detection
-TP_LOCALLAB_ARTIF_TOOLTIP;Threshold deltaE-scope increase the range of scope-deltaE - high values are for very wide gamut images.\nIncrease deltaE decay improve shape detection, but can reduce the scope of detection.
+TP_LOCALLAB_ARTIF_TOOLTIP;ΔE scope threshold increases the range of deltaE scope. High values are for very wide gamut images.\nIncreasing deltaE decay can improve shape detection, but can also reduce the scope.
TP_LOCALLAB_AUTOGRAY;Automatic
TP_LOCALLAB_AVOID;Avoid color shift
-TP_LOCALLAB_BALAN;Balance ΔE ab-L
+TP_LOCALLAB_BALAN;ab-L balance (ΔE)
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
+TP_LOCALLAB_BALANH;C-H balance (ΔE)
+TP_LOCALLAB_BALAN_TOOLTIP;Changes the ΔE algorithm parameters.\nTakes into account more or less a*b* or L*, or more or less C or H.\nNot for Denoise
+TP_LOCALLAB_BASELOG;Shadows range (logarithm base)
TP_LOCALLAB_BILATERAL;Bilateral filter
TP_LOCALLAB_BLACK_EV;Black Ev
TP_LOCALLAB_BLCO;Chrominance only
TP_LOCALLAB_BLENDMASKCOL;Blend
-TP_LOCALLAB_BLENDMASKMASK;Add / substract mask Luminance
-TP_LOCALLAB_BLENDMASKMASKAB;Add / substract mask Chrominance
+TP_LOCALLAB_BLENDMASKMASK;Add/subtract luminance mask
+TP_LOCALLAB_BLENDMASKMASKAB;Add/subtract chrominance mask
TP_LOCALLAB_BLENDMASK_TOOLTIP;If blend = 0 only shape detection is improved.\nIf blend > 0 the mask is added to the image. If blend < 0 the mask is subtracted from the image
TP_LOCALLAB_BLENDMASKMASK_TOOLTIP;If this slider = 0 no action.\nAdd or subtract the mask from the original image
TP_LOCALLAB_BLGUID;Guided Filter
@@ -2368,83 +2415,92 @@ 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;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_BLUFR;Blur/Grain & Denoise
+TP_LOCALLAB_BLUMETHOD_TOOLTIP;To blur the background and isolate the foreground:\n-blur the background by completely covering the image with an an RT-spot (high values for scope and transition and ‘Normal’ or ‘Inverse’ in checkbox).\n-Isolate the foreground by using one or more ‘Excluding’ RT-spot(s) and increase the scope.\n\nThis module (including the "median" and "Guided filter") can be used in addition to the main-menu noise reduction.
TP_LOCALLAB_BLUR;Gaussian Blur - Noise - Grain
TP_LOCALLAB_BLURCBDL;Blur levels 0-1-2-3-4
-TP_LOCALLAB_BLURCOL;Radius Mask Blur
-TP_LOCALLAB_BLURDE;Blur Shape detection
-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_BLURCOL;Radius
+TP_LOCALLAB_BLURCOLDE_TOOLTIP;The image used to calculate dE is blurred slightly to avoid taking isolated pixels into account.
+TP_LOCALLAB_BLURDE;Blur shape detection
+TP_LOCALLAB_BLURLC;Luminance only
+TP_LOCALLAB_BLURLEVELFRA;Blur levels
+TP_LOCALLAB_BLURMASK_TOOLTIP;Uses a large-radius blur to create a mask that allows you to vary the contrast of the image and/or darken/lighten parts of it.
+TP_LOCALLAB_BLURRMASK_TOOLTIP;Allows you to vary the "radius" of the Gaussian blur (0 to 1000)
TP_LOCALLAB_BLURRESIDFRA;Blur Residual
-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_BLUR_TOOLNAME;Blur/Grain & Denoise - 1
+TP_LOCALLAB_BLWH;All changes forced in Black-and-White
+TP_LOCALLAB_BLWH_TOOLTIP;Force color components "a" and "b" to zero.\nUseful for black and white processing, or film simulation.
TP_LOCALLAB_BUTTON_ADD;Add
TP_LOCALLAB_BUTTON_DEL;Delete
TP_LOCALLAB_BUTTON_DUPL;Duplicate
TP_LOCALLAB_BUTTON_REN;Rename
TP_LOCALLAB_BUTTON_VIS;Show/Hide
-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_CATAD;Chromatic adaptation - Cat02
+TP_LOCALLAB_CBDL;Contrast by Detail Levels
+TP_LOCALLAB_CBDLCLARI_TOOLTIP;Enhances local contrast of the midtones.
+TP_LOCALLAB_CBDL_ADJ_TOOLTIP;Same as wavelets.\nThe first level (0) acts on 2x2 pixel details.\nThe last level (5) acts on 64x64 pixel details.
+TP_LOCALLAB_CBDL_THRES_TOOLTIP;Prevents the sharpening of noise
TP_LOCALLAB_CBDL_TOOLNAME;CBDL - 2
TP_LOCALLAB_CENTER_X;Center X
TP_LOCALLAB_CENTER_Y;Center Y
TP_LOCALLAB_CH;Curves CL - LC
TP_LOCALLAB_CHROMA;Chrominance
TP_LOCALLAB_CHROMABLU;Chroma levels
-TP_LOCALLAB_CHROMABLU_TOOLTIP;Acts as an amplifier-reducer action compare to settings of luma.\nUnder 1 reduce, above 1 amplifie
+TP_LOCALLAB_CHROMABLU_TOOLTIP;Increases or reduces the effect depending on the luma settings.\nValues under 1 reduce the effect. Values greater than 1 increase the effect.
TP_LOCALLAB_CHROMACBDL;Chroma
-TP_LOCALLAB_CHROMACB_TOOLTIP;Acts as an amplifier-reducer action compare to sliders of luminance.\nUnder 100 reduce, above 100 amplifie
+TP_LOCALLAB_CHROMACB_TOOLTIP;Increases or reduces the effect depending on the luma settings.\nValues under 1 reduce the effect. Values greater than 1 increase the effect.
TP_LOCALLAB_CHROMALEV;Chroma levels
-TP_LOCALLAB_CHROMASKCOL;Chroma mask
+TP_LOCALLAB_CHROMASKCOL;Chroma
+TP_LOCALLAB_CHROMASK_TOOLTIP;Changes the chroma of the mask if one exists (i.e. C(C) or LC(H) is activated).
TP_LOCALLAB_CHROMASK_TOOLTIP;You can use this slider to desaturated background (inverse mask - curve near 0).\nAlso to attenuate or enhance the action of a mask on the chroma
TP_LOCALLAB_CHRRT;Chroma
+TP_LOCALLAB_CIEC;Use Ciecam environment parameters
+//TP_LOCALLAB_CIECAMLOG_TOOLTIP;This module is based on the CIECAM02 color appearance model which was designed to better simulate how human vision perceives colors under different lighting conditions.\nOnly the third Ciecam process (Viewing conditions - Target) is taken into account, as well as part of the second (contrast J, saturation s) , as well as some data from the first process (Scene conditions - Source) which is used for the Log encoding.\nIt also adapts the output to the intended viewing conditions (monitor, TV, projector, printer, etc.) so that the chromatic and contrast appearance is preserved across the display environment.
+TP_LOCALLAB_CIECAMLOG_TOOLTIP;This module is based on the CIECAM02 color appearance model which was designed to better simulate how human vision perceives colors under different lighting conditions.\nThe first Ciecam process 'Scene conditions' is carried out by Log encoding, it also uses 'Absolute luminance' at the time of the shooting.\nThe second Ciecam process 'Image adjustments' is simplified and uses only 3 variables (local contrast, contrast J, saturation s).\nThe third Ciecam process 'Viewing conditions' adapts the output to the intended viewing conditions (monitor, TV, projector, printer, etc.) so that the chromatic and contrast appearance is preserved across the display environment.
TP_LOCALLAB_CIRCRADIUS;Spot size
-TP_LOCALLAB_CIRCRAD_TOOLTIP;Contains the references of RT-spot, useful for shape detection (hue, luma, chroma, Sobel).\nLow values may be useful for treating foliage.\nHigh values may be useful for treating skin
-TP_LOCALLAB_CLARICRES;Merge Chroma
-TP_LOCALLAB_CLARIFRA;Clarity & Sharp mask - Blend & Soft images
-TP_LOCALLAB_CLARILRES;Merge Luma
+TP_LOCALLAB_CIRCRAD_TOOLTIP;Contains the references of the RT-spot, useful for shape detection (hue, luma, chroma, Sobel).\nLow values may be useful for treating foliage.\nHigh values may be useful for treating skin
+TP_LOCALLAB_CLARICRES;Merge chroma
+TP_LOCALLAB_CLARIFRA;Clarity & Sharp mask - Blend & Soften Images
+TP_LOCALLAB_CLARILRES;Merge luma
TP_LOCALLAB_CLARISOFT;Soft radius
-TP_LOCALLAB_CLARISOFT_TOOLTIP;Enabled for Clarity and Sharp mask if Merge Luma different from zero.\n\nEnabled for all wavelets pyramid modules.\nDisabled if Soft radius = 0
+TP_LOCALLAB_CLARISOFT_TOOLTIP;The "Soft radius" slider (guided filter algorithm) reduces halos and irregularities for both Clarity and Sharp Mask and for all pyramid wavelet processes. To deactivate, set slider to zero.
TP_LOCALLAB_CLARITYML;Clarity
-TP_LOCALLAB_CLARI_TOOLTIP;Under or equal level wavelet 4, 'Sharp mask' is enabled.\nAbove level wavelet 5 'Clarity' is enabled.\nUsefull if you use 'Level dynamic Range Compression'
-TP_LOCALLAB_CLIPTM;Clip Restored datas (gain)
+TP_LOCALLAB_CLARI_TOOLTIP;Levels 0 to 4 (included): ‘Sharp mask’ is enabled\nLevels 5 and above: 'Clarity' is enabled.\nUseful if you use 'Wavelet level tone mapping'
+TP_LOCALLAB_CLIPTM;Clip restored data (gain)
TP_LOCALLAB_COFR;Color & Light
-TP_LOCALLAB_COLORDE;Color preview selection ΔE - Intensity
-TP_LOCALLAB_COLORDEPREV_TOOLTIP;Button Preview ΔE needs that only one tool is enabled (expander).\nTo be able to have an Preview ΔE with several enable tools use Mask and modifications - Preview Δ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_COLORDE;ΔE preview color - intensity
+TP_LOCALLAB_COLORDE_TOOLTIP;Show a blue color-preview for ΔE selection if negative and green if positive.\n\nMask and modifications (show modified areas without mask): show actual modifications if positive, show enhanced modifications (luminance only) with blue and yellow if negative.
+TP_LOCALLAB_COLORDEPREV_TOOLTIP;Preview ΔE button will only work if you have activated one (and only one) of the tools in "Add tool to current spot" menu.\nTo be able to preview ΔE with several tools enabled, use Mask and modifications - Preview ΔE
+TP_LOCALLAB_COLORSCOPE;Scope (color tools)
+TP_LOCALLAB_COLORSCOPE_TOOLTIP;Common Scope slider for Color and Light, Shadows/Highlights, Vibrance.\nOther tools have their own scope controls.
TP_LOCALLAB_COLOR_TOOLNAME;Color & Light - 11
TP_LOCALLAB_COL_NAME;Name
TP_LOCALLAB_COL_VIS;Status
-TP_LOCALLAB_COMPFRA;Levels Directional Contrast
-TP_LOCALLAB_COMPFRAME_TOOLTIP;Allows special effects. You can reduce artifacts with 'Clarity & Sharp mask - Blend & Soft Images".\nUses a lot of resources
+TP_LOCALLAB_COMPFRA;Directional contrast
+TP_LOCALLAB_COMPFRAME_TOOLTIP;Allows special effects. You can reduce artifacts with 'Clarity & Sharp mask - Blend & Soften Images".\nUses a lot of resources
TP_LOCALLAB_COMPLEX_METHOD;Software Complexity
TP_LOCALLAB_COMPLEX_TOOLTIP; Allow user to select Local adjustments rubrics.
-TP_LOCALLAB_COMPREFRA;Levels Dynamic Wavelet Range (un)Compression
-TP_LOCALLAB_COMPRESS_TOOLTIP;Use if necessary the module 'Clarity & Sharp mask and Blend & Soft Images' by adjusting 'Soft radius' to reduce artifacts.
-TP_LOCALLAB_CONTCOL;Contrast threshold Mask Blur
-TP_LOCALLAB_CONTFRA;Contrast by Level
+TP_LOCALLAB_COMPREFRA;Wavelet level tone mapping
+TP_LOCALLAB_COMPRESS_TOOLTIP;Use if necessary the module 'Clarity & Sharp mask and Blend & Soften Images' by adjusting 'Soft radius' to reduce artifacts.
+TP_LOCALLAB_CONTCOL;Contrast threshold
+TP_LOCALLAB_CONTFRA;Contrast by level
+TP_LOCALLAB_CONTL;Contrast (J)
+TP_LOCALLAB_CONTTHMASK_TOOLTIP;Allows you to determine which parts of the image will be impacted based on the texture.
TP_LOCALLAB_CONTRAST;Contrast
-TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP;Main mask contrast control.
+TP_LOCALLAB_CONTRASTCURVMASK1_TOOLTIP;Allows you to freely modify the contrast of the mask (gamma & slope), instead of using a continuous & progressive curve. However it can create artifacts that have to be dealt with using the “Smooth radius” or “Laplacian threshold sliders”.
TP_LOCALLAB_CONTRESID;Contrast
TP_LOCALLAB_CONTTHR;Contrast Threshold
TP_LOCALLAB_CONTWFRA;Local contrast
-TP_LOCALLAB_CSTHRESHOLD;Ψ Wavelets Levels
-TP_LOCALLAB_CSTHRESHOLDBLUR;Ψ Mask Wavelet level
+TP_LOCALLAB_CSTHRESHOLD;Ψ Wavelet levels
+TP_LOCALLAB_CSTHRESHOLDBLUR;Ψ Wavelet level selection
TP_LOCALLAB_CURV;Lightness - Contrast - Chrominance "Super"
TP_LOCALLAB_CURVCURR;Normal
-TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP;If curves at the top, mask is completely black no transformation is made by the mask on the image.\nAs you go down the curve, the mask gradually more colorful and brilliant, the image is changing more and more.\n\nIt is recommended (not required) to position the top of the curves on the gray transition line which represents the references (chroma, luma, hue).
+TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP;If curves are at the top, the mask is completely black and no changes are made to the image.\nAs you lower the curve, the mask gradually becomes more colorful and bright, progressively changing the image.\n\nIt is recommended (but not mandatory) to position the top of the curves on the gray boundary line which represents the reference values of chroma, luma, hue for the RT-spot.
TP_LOCALLAB_CURVEEDITORM_CC_TOOLTIP;If curves at the top, mask is completely black no transformation is made by the mask on the image.\nAs you go down the curve, the mask gradually more colorful and brilliant, the image is changing more and more.\n\nThe gray transition line which represents the references (chroma, luma, hue).\nYou can choose or not to position the top of the curves on this transition.
-TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP;To be active, you must enable combobox 'Curves type'
+TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP;To activate the curves, set the ‘Curve type’ combobox to ‘Normal’
TP_LOCALLAB_CURVEEDITOR_TONES_LABEL;Tone curve
TP_LOCALLAB_CURVEEDITOR_TONES_TOOLTIP;L=f(L), can be used with L(H) in Color and Light
-TP_LOCALLAB_CURVEMETHOD_TOOLTIP;'Normal', the curve L=f(L) has the same algorithm than slider lightness.\n'Super' the curve L=f(L) has an new improved algorithm, which can leeds in some cases to artifacts.
+TP_LOCALLAB_CURVEMETHOD_TOOLTIP;'Normal', the curve L=f(L) uses the same algorithm as the lightness slider.
TP_LOCALLAB_CURVENCONTRAST;Super+Contrast threshold (experimental)
TP_LOCALLAB_CURVENH;Super
TP_LOCALLAB_CURVENHSU;Combined HueChroma (experimental)
@@ -2453,20 +2509,30 @@ TP_LOCALLAB_CURVNONE;Disable curves
TP_LOCALLAB_DARKRETI;Darkness
TP_LOCALLAB_DEHAFRA;Dehaze
TP_LOCALLAB_DEHAZ;Strength
-TP_LOCALLAB_DEHAZ_TOOLTIP;Negative values adds haze
+TP_LOCALLAB_DEHAZ_TOOLTIP;Negative values add haze
+TP_LOCALLAB_DEHAZFRAME_TOOLTIP;Removes atmospheric haze. Increases overall saturation and detail.\nCan remove color casts, but may also introduce a blue cast which can be corrected with other tools.
TP_LOCALLAB_DELTAD;Delta balance
-TP_LOCALLAB_DELTAEC;Mask ΔE Image
+TP_LOCALLAB_DELTAEC;ΔE Image mask
TP_LOCALLAB_DENOIS;Ψ Denoise
TP_LOCALLAB_DENOI_EXP;Denoise
-TP_LOCALLAB_DENOI_TOOLTIP;This module can be used alone (at the end of process), or in complement of main denoise (at the beginning).\nScope allows to differentiate the action according to the color (deltaE).\nYou can complete the action with "median" or "Guided Filter" (Smooth Blur...).\nYou can complete the action with "Blur levels" "Wavelet pyramid"
+TP_LOCALLAB_DENOIQUA_TOOLTIP;Conservative mode preserves low frequency detail. “Aggressive” mode removes low frequency detail.
+TP_LOCALLAB_DENOIEQUAL_TOOLTIP;Allows you to carry out more or less noise reduction in either the shadows or the highlights.
+TP_LOCALLAB_DENOI_TOOLTIP;This module can be used for noise reduction either on its own (at the end of the processing pipeline) or in addition to the Noise Reduction module in the Detail tab (which works at the beginning of the pipeline).\n Scope allows you to differentiate the action based on color (deltaE).\n\n You can refine the result with a "Median filter" or a "Guided Filter" (Soft radius).
+TP_LOCALLAB_DENOILUMDETAIL_TOOLTIP;Allows you to recover luminance detail by progressively applying a Fourier transform (DCT).
+TP_LOCALLAB_DENOICHROF_TOOLTIP;Allows you to adjust fine-detail chrominance noise
+TP_LOCALLAB_DENOICHROC_TOOLTIP;Allows you to deal with blotches and packets of noise.
+TP_LOCALLAB_DENOICHRODET_TOOLTIP;Allows you to recover chrominance detail by progressively applying a Fourier transform (DCT).
+TP_LOCALLAB_DENOITHR_TOOLTIP;Adjusts edge detection to help reduce noise in uniform, low-contrast areas.
+TP_LOCALLAB_DENOIEQUALCHRO_TOOLTIP;Allows you to direct the chroma noise reduction towards either the blue-yellow or red-green colors.
+TP_LOCALLAB_DENOIBILAT_TOOLTIP;Allows you to reduce impulse or ‘salt & pepper’ noise.
TP_LOCALLAB_DEPTH;Depth
TP_LOCALLAB_DETAIL;Local contrast
TP_LOCALLAB_DETAILSH;Details
-TP_LOCALLAB_DETAILTHR;Detail threshold Luminance Chroma (DCT ƒ)
+TP_LOCALLAB_DETAILTHR;Luminance & chroma detail threshold (DCT ƒ)
TP_LOCALLAB_DUPLSPOTNAME;Copy
-TP_LOCALLAB_EDGFRA;Edge Sharpness
-TP_LOCALLAB_EDGSHOW;Show all tolls
-TP_LOCALLAB_ELI;Elipse
+TP_LOCALLAB_EDGFRA;Edge sharpness
+TP_LOCALLAB_EDGSHOW;Show all tools
+TP_LOCALLAB_ELI;Ellipse
TP_LOCALLAB_ENABLE_AFTER_MASK;Use Tone Mapping
TP_LOCALLAB_ENABLE_MASK;Enable mask
TP_LOCALLAB_ENABLE_MASKAFT;Use all algorithms Exposure
@@ -2474,8 +2540,8 @@ TP_LOCALLAB_ENARETIMASKTMAP_TOOLTIP;If enabled Mask uses Restored Datas after Tr
TP_LOCALLAB_ENH;Enhanced
TP_LOCALLAB_ENHDEN;Enhanced + chroma denoise
TP_LOCALLAB_EPSBL;Detail
-TP_LOCALLAB_EQUIL;Normalize Luminance
-TP_LOCALLAB_EQUILTM_TOOLTIP;Reconstruct luminance in such a way that the mean and the variance of the output image is identical to that of the original.
+TP_LOCALLAB_EQUIL;Normalize luminance
+TP_LOCALLAB_EQUILTM_TOOLTIP;Reconstruct luminance so that the mean and variance of the output image are identical to those of the original.
TP_LOCALLAB_ESTOP;Edge stopping
TP_LOCALLAB_EV_DUPL;Copy of
TP_LOCALLAB_EV_NVIS;Hide
@@ -2483,155 +2549,174 @@ TP_LOCALLAB_EV_NVIS_ALL;Hide all
TP_LOCALLAB_EV_VIS;Show
TP_LOCALLAB_EV_VIS_ALL;Show all
TP_LOCALLAB_EXCLUF;Excluding
-TP_LOCALLAB_EXCLUF_TOOLTIP;Can be used to exclude this part of datas - move Scope to extend color.\n You can apply all settings to this RT-spot.
+TP_LOCALLAB_EXCLUF_TOOLTIP;‘Excluding’ mode prevents adjacent spots from influencing certain parts of the image. Adjusting ‘Scope’ will extend the range of colors.\n You can also add tools to an Excluding spot and use them in the same way as for a normal spot.
TP_LOCALLAB_EXCLUTYPE;Spot method
-TP_LOCALLAB_EXCLUTYPE_TOOLTIP;Normal spot use recursive data.\n\nExcluding spot reinitialize data to origin.\nCan be used to totally or partially cancel a previous action or to perform a inverse mode
+TP_LOCALLAB_EXCLUTYPE_TOOLTIP;Normal spot uses recursive data.\n\nExcluding spot reinitializes all local adjustment data.\nCan be used to totally or partially cancel a previous action or to carry out operations in Inverse mode
TP_LOCALLAB_EXECLU;Excluding spot
TP_LOCALLAB_EXNORM;Normal spot
-//TP_LOCALLAB_EXPCBDL_TOOLTIP;In the case of contaminated sensor (type "grease"), and when the area is important or for a series of small defects.\n\na) Put the selection spot on a pronounced default (adapting its size if necessary), use a large spot enough to allow wavelet; b) choose a wide selection area to cover most of the area affected by the defects; c) Select a transition value (low) and transition decay (high value); d) act on levels 2, 3, 4 or 5 or lower by reducing the contrast (values below 100) and by acting on the chroma slider if necessary. e)possibly act on "scope" to reduce the extent of the action.\n\nYou can also complete with Blur levels and Gaussian blur (Smooth Blur and noise)
-TP_LOCALLAB_EXPCBDL_TOOLTIP;Can be used to remove marks on the sensor or lens.
+TP_LOCALLAB_EXPCBDL_TOOLTIP;Can be used to remove marks on the sensor or lens by reducing the contrast on the appropriate detail level(s).
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_EXPCHROMA_TOOLTIP;Use in association with ‘Exposure compensation f’ and ‘Contrast Attenuator f’ to avoid desaturating colors.
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.
+TP_LOCALLAB_EXPCOMP_TOOLTIP;For portraits or images with a low color gradient. You can change "Shape detection" in "Settings":\n\nIncrease 'ΔE scope threshold'\nReduce 'ΔE decay'\nIncrease 'ab-L balance (ΔE)’
+TP_LOCALLAB_EXPCONTRASTPYR_TOOLTIP;See the documentation for Wavelet Levels.\nThere are some differences in the Locallab version: more tools and more possibilities for working on individual detail levels.\ne.g. Wavelet-level tone mapping.
+TP_LOCALLAB_EXPCONTRAST_TOOLTIP;Avoid spots that are too small ( < 32x32 pixels).\nUse low ‘Transition value’ and high ‘Transition decay’ and ‘Scope’ to simulate small RT-spots and deal wth defects.\nUse 'Clarity & Sharp mask and Blend & Soften Images' if necessary by adjusting 'Soft radius' to reduce artifacts.
TP_LOCALLAB_EXPCURV;Curves
TP_LOCALLAB_EXPGRAD;Graduated Filter
-TP_LOCALLAB_EXPLAPBAL_TOOLTIP;Balances the action between the original image and the Laplace transform.
-TP_LOCALLAB_EXPLAPGAMM_TOOLTIP;Apply a gamma before and after Laplace transform
-TP_LOCALLAB_EXPLAPLIN_TOOLTIP;Add linear exposure component before application Laplace transform
-TP_LOCALLAB_EXPLAP_TOOLTIP;The more you act on this threshold slider, the greater the action of reducing contrast.
-TP_LOCALLAB_EXPMERGEFILE_TOOLTIP;Allows various possibilities to blend image (as layers in Photosshop) : difference, multiply, soft light, overlay...with opacity...\nOriginal Image : merge current RT-spot with Original.\nPrevious spot : merge current Rt-spot with previous - if there is only one spot previous = original.\nBackground : merge current RT-spot with a color and luminance background (less possibilties)
+TP_LOCALLAB_EXPGRADCOL_TOOLTIP;A graduated filter is available in Color and Light (luminance, chrominance & hue gradients, and "Merge file") Exposure (luminance grad.), Exposure Mask (luminance grad.), Shadows/Highlights (luminance grad.), Vibrance (luminance, chrominance & hue gradients), Local contrast & wavelet pyramid (local contrast grad.).\nFeather is located in Settings.
+TP_LOCALLAB_EXPLAPBAL_TOOLTIP;Changes the transformed/original image blend
+TP_LOCALLAB_EXPLAPGAMM_TOOLTIP;Changes the behaviour for images with too much or too little contrast by adding a gamma curve before and after the Laplace transform
+TP_LOCALLAB_EXPLAPLIN_TOOLTIP;Changes the behaviour for underexposed images by adding a linear component prior to applying the Laplace transform
+TP_LOCALLAB_EXPLAP_TOOLTIP;Moving the slider to the right progressively reduces the contrast.
+TP_LOCALLAB_EXPMERGEFILE_TOOLTIP;Allows you to use GIMP or Photoshop (c) layer blend modes i.e. Difference, Multiply, Soft Light, Overlay etc., with opacity control.\nOriginal Image : merge current RT-spot with Original.\nPrevious spot : merge current Rt-spot with previous - if there is only one spot previous = original.\nBackground : merge current RT-spot with a color and luminance background (fewer possibilties)
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", "Log Encoding"...
+TP_LOCALLAB_EXPNOISEMETHOD_TOOLTIP;Applies a median filter before the Laplace transform to prevent artifacts (noise).\nYou can also use the "Denoise" tool.
+TP_LOCALLAB_EXPOSE;Dynamic Range & Exposure
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_EXPSHARP_TOOLTIP;RT-Spot minimum 39*39.\nUse low transition values and high ‘Transition decay’ and ‘Scope’ values to simulate smaller RT-spots.
+TP_LOCALLAB_EXPTOOL;Exposure Tools
TP_LOCALLAB_EXPTRC;Tone Response Curve - TRC
-TP_LOCALLAB_EXP_TOOLNAME;Contrast Attenuator -Dynamic Range Compression & Exposure- 10
+TP_LOCALLAB_EXP_TOOLNAME;Dynamic Range & Exposure - 10
TP_LOCALLAB_FATAMOUNT;Amount
TP_LOCALLAB_FATANCHOR;Anchor
TP_LOCALLAB_FATANCHORA;Offset
TP_LOCALLAB_FATDETAIL;Detail
TP_LOCALLAB_FATFRA;Dynamic Range Compression ƒ
-TP_LOCALLAB_FATFRAME_TOOLTIP;PDE Fattal - use Fattal Tone mapping algorithm.
+TP_LOCALLAB_FATFRAME_TOOLTIP;PDE Fattal – uses the Fattal Tone-mapping algorithm.
TP_LOCALLAB_FATLEVEL;Sigma
TP_LOCALLAB_FATRES;Amount Residual Image
TP_LOCALLAB_FATSHFRA;Dynamic Range Compression Mask ƒ
-TP_LOCALLAB_FEATH_TOOLTIP;Gradient width in percent of the Spot diagonal\nUsed by all Graduated filter in all tools.\nNo action if Graduated Filter are not used.
+TP_LOCALLAB_FEATH_TOOLTIP;Gradient width as a percentage of the Spot diagonal\nUsed by all graduated filters in all tools.\nNo action if a graduated filter hasn’t been activated.
TP_LOCALLAB_FEATVALUE;Feather gradient (Graduated Filters)
TP_LOCALLAB_FFTCOL_MASK;FFTW ƒ
TP_LOCALLAB_FFTW;ƒ - Use Fast Fourier Transform
TP_LOCALLAB_FFTW2;ƒ - Use Fast Fourier Transform (TIF, JPG,..)
+TP_LOCALLAB_FFTMASK_TOOLTIP;Use a Fourier transform for better quality (increased processing time and memory requirements)
TP_LOCALLAB_FFTWBLUR;ƒ - Always Use Fast Fourier Transform
-TP_LOCALLAB_FULLIMAGE;Calculate DarkEv - WhiteEv - Value on the entire image
+TP_LOCALLAB_FULLIMAGE;Dark-Ev & white-Ev for the entire image
+TP_LOCALLAB_FULLIMAGELOG_TOOLTIP;Calculates the Ev levels for the entire image.
TP_LOCALLAB_GAM;Gamma
TP_LOCALLAB_GAMFRA;Tone response curve (TRC)
TP_LOCALLAB_GAMM;Gamma
-TP_LOCALLAB_GAMMASKCOL;Gamma mask
+TP_LOCALLAB_GAMMASKCOL;Gamma
+TP_LOCALLAB_GAMMASK_TOOLTIP;Gamma and Slope allow a soft and artifact-free transformation of the mask by progressively modifying “L” to avoid any discontinuities.
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, 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_GRADGEN_TOOLTIP;Adjusts luminance gradient strength
+TP_LOCALLAB_GRADLOGFRA;Graduated Filter Luminance
TP_LOCALLAB_GRADSTR;Gradient strength
-TP_LOCALLAB_GRADSTRAB_TOOLTIP;Filter chroma strength
-TP_LOCALLAB_GRADSTRCHRO;Gradient strength Chrominance
-TP_LOCALLAB_GRADSTRHUE;Gradient strength Hue
-TP_LOCALLAB_GRADSTRHUE2;Gradient strength Hue
-TP_LOCALLAB_GRADSTRHUE_TOOLTIP;Filter Hue strength
-TP_LOCALLAB_GRADSTRLUM;Gradient strength Luminance
+TP_LOCALLAB_GRADSTRAB_TOOLTIP;Adjusts chroma gradient strength
+TP_LOCALLAB_GRADSTRCHRO;Chrominance gradient strength
+TP_LOCALLAB_GRADSTRHUE;Hue gradient strength
+TP_LOCALLAB_GRADSTRHUE2;Hue gradient strength
+TP_LOCALLAB_GRADSTRHUE_TOOLTIP;Adjusts hue gradient strength
+TP_LOCALLAB_GRADSTRLUM;Luminance gradient strength
TP_LOCALLAB_GRADSTR_TOOLTIP;Filter strength in stops
+TP_LOCALLAB_GRAIN_TOOLTIP;Adds film-like grain to the image
TP_LOCALLAB_GRAINFRA;Film Grain 1:1
-TP_LOCALLAB_GRALWFRA;Graduated Filter Local contrast
+TP_LOCALLAB_GRALWFRA;Graduated filter (local contrast)
TP_LOCALLAB_GRIDFRAME_TOOLTIP;You can use this tool as a brush. Use small spot and adapt transition and transition decay\nOnly mode NORMAL and eventually Hue, Saturation, Color, Luminosity are concerned by Merge background (ΔE)
TP_LOCALLAB_GRIDONE;Color Toning
TP_LOCALLAB_GRIDTWO;Direct
+TP_LOCALLAB_GRIDMETH_TOOLTIP;Color toning: the luminance is taken into account when varying chroma. Equivalent to H=f(H) if the "white dot" on the grid remains at zero and you only vary the "black dot". Equivalent to "Color toning" if you vary the 2 dots.\n\nDirect: acts directly on the chroma
TP_LOCALLAB_GUIDBL;Soft radius
+TP_LOCALLAB_GUIDBL_TOOLTIP;Applies a guided filter with adjustable radius. Allows you to reduce artifacts or blur the image.
+TP_LOCALLAB_GUIDEPSBL_TOOLTIP;Changes the distribution function of the guided filter. Negative values simulate a Gaussian blur.
TP_LOCALLAB_GUIDFILTER;Guided filter radius
-TP_LOCALLAB_GUIDFILTER_TOOLTIP;Adapt this values according to images - can reduce or increase artifacts.
+TP_LOCALLAB_GUIDFILTER_TOOLTIP;Can reduce or increase artifacts.
+TP_LOCALLAB_GUIDSTRBL_TOOLTIP;Intensity of the guided filter
TP_LOCALLAB_HHMASK_TOOLTIP;Fine hue adjustments for example for the skin.
-TP_LOCALLAB_HIGHMASKCOL;Highlights mask
+TP_LOCALLAB_HIGHMASKCOL;Highlights
TP_LOCALLAB_HLH;Curves H
TP_LOCALLAB_IND;Independent (mouse)
TP_LOCALLAB_INDSL;Independent (mouse + sliders)
TP_LOCALLAB_INVERS;Inverse
-TP_LOCALLAB_INVERS_TOOLTIP;If selected (inverse) less possibilities.\n\nAlternative\nFirst Spot:\n full image - delimiter outside preview\n Shape RT-spot area : rectangle. Transition 100\n\nSecond spot : Excluding spot
+TP_LOCALLAB_INVBL;Inverse
+TP_LOCALLAB_INVERS_TOOLTIP;Fewer possibilities if selected (Inverse).\n\nAlternative: use two spots\nFirst Spot:\n full image - delimiter outside preview\n RT-spot shape: rectangle. Transition 100\n\nSecond spot: Excluding spot
+TP_LOCALLAB_INVBL_TOOLTIP;Alternative to ‘Inverse’ mode: use two spots\nFirst Spot:\n full image - delimiter outside preview\n RT-spot shape: rectangle. Transition 100\n\nSecond spot : Excluding spot
TP_LOCALLAB_ISOGR;Coarseness (ISO)
-TP_LOCALLAB_LABBLURM;Mask Blur
+TP_LOCALLAB_LABBLURM;Blur Mask
TP_LOCALLAB_LABEL;Local Adjustments
TP_LOCALLAB_LABGRID;Color correction grid
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_LABSTRUM;Structure Mask
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 (advanced) simultaneously.\nLaplacian threshold reduce contrast, artifacts, smooth result.
+TP_LOCALLAB_LAPMASKCOL;Laplacian threshold
+TP_LOCALLAB_LAPRAD_TOOLTIP;Avoid using “Smooth radius” and “Laplacian threshold” (advanced) together.\nSmooth radius uses a guided filter to decrease artifacts and smooth out the transition
+TP_LOCALLAB_LAPRAD1_TOOLTIP;Avoid using “Smooth radius” and “Laplacian threshold” (advanced) together.\nTransforms the mask to eliminate values lower than the threshold.\nReduces artifacts and noise, and allows local contrast to be modified.
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_FFTW_TOOLTIP;FFT improves quality and allows the use of large radii, but increases processing time (depends on the area to be processed). Preferable to use only for large radii. The size of the area can be reduced by a few pixels to optimize the FFTW. This can reduce the processing time by a factor of 1.5 to 10.
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
+TP_LOCALLAB_LEVELBLUR;Maximum blur levels
+TP_LOCALLAB_LEVELWAV;Ψ Wavelet levels
TP_LOCALLAB_LEVELWAV_TOOLTIP;The Level is automatically adapted to the size of the spot and the preview.\nFrom level 9 size max 512 to level 1 size max = 4
TP_LOCALLAB_LEVFRA;Levels
TP_LOCALLAB_LIGHTNESS;Lightness
-TP_LOCALLAB_LIGHTN_TOOLTIP;In inverse mode: selection = -100 force luminance to zero
+TP_LOCALLAB_LIGHTN_TOOLTIP;In inverse mode: selection = -100 forces luminance to zero
TP_LOCALLAB_LIGHTRETI;Lightness
TP_LOCALLAB_LINEAR;Linearity
TP_LOCALLAB_LIST_NAME;Add tool to current 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_LMASK_LL_TOOLTIP;Allows you to freely change the contrast of the mask. May create artifacts.
TP_LOCALLAB_LOCCONT;Unsharp Mask
-TP_LOCALLAB_LOC_CONTRAST;Local contrast & Wavelets
+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_LOC_CONTRASTPYR2LAB; Contrast by level- Tone Mapping - Dir.Contrast
+TP_LOCALLAB_LOC_CONTRASTPYRLAB; Graduated Filter - Edge Sharpness - Blur
+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
-TP_LOCALLAB_LOGBLACKWHEV_TOOLTIP;Estimated values of Dynamic Range - Black Ev and White Ev
-TP_LOCALLAB_LOGENCOD_TOOLTIP;Allows Tone Mapping with Logarithm encoding (ACES).\nUsefull for underexposed pictures, or with high dynamic range.\n\nTwo steps in the process : 1) Calculate Dynamic Range 2) User adaptation
-TP_LOCALLAB_LOGFRA;Source Gray Point
-TP_LOCALLAB_LOGFRAME_TOOLTIP;Calculate or use Exposure levels of the image early in the process:\n Black Ev, White Ev and Source Gray point.\n Take into account main exposure compensation.
+TP_LOCALLAB_LOGAUTO_TOOLTIP;Pressing this button will calculate the dynamic range and Source Gray Point (if "Automatic Source Gray Point” enabled).\nPress the button again to adjust the automatically calculated values.
+TP_LOCALLAB_LOGBASE_TOOLTIP;Default = 2.\nValues less than 2 reduce the action of the algorithm making the shadows darker and the highlights brighter.\nWith values greater than 2, the shadows are grayer and the highlights become more washed out.
+TP_LOCALLAB_LOGBLACKWHEV_TOOLTIP;Estimated values of Dynamic Range i.e. Black Ev and White Ev
+TP_LOCALLAB_LOGCONTL_TOOLTIP;Contrast (J) in CIECAM02 takes into account the increase in perceived coloration with luminance.
+TP_LOCALLAB_LOGDETAIL_TOOLTIP;Acts mainly on high frequencies.
+TP_LOCALLAB_LOGCATAD_TOOLTIP;The chromatic adaptation allows us to interpret a color according to its spatio-temporal environment.\nUseful when the white balance is far from reference D50.\nAdapts colors to the illuminant of the output device.
+TP_LOCALLAB_LOGENCOD_TOOLTIP;Tone Mapping with Logarithmic encoding (ACES).\nUseful for underexposed images or images with high dynamic range.\n\nTwo-step process : 1) Dynamic Range calculation 2) Manual adjustment
+TP_LOCALLAB_LOGFRA;Scene Conditions
+TP_LOCALLAB_LOG1FRA;Image Adjustments
+TP_LOCALLAB_LOG2FRA;Viewing Conditions
+TP_LOCALLAB_LOGFRAME_TOOLTIP;Allows you to calculate and adjust the Ev levels and the Source Gray Point for the spot area. The resulting values will be used by all Lab operations and most RGB operations in the pipeline.\nTakes into account exposure compensation in the main-menu Exposure tab.\nAlso calculates the absolute luminance at the time of the shooting.
+TP_LOCALLAB_LOGIMAGE_TOOLTIP;Takes into account corresponding Ciecam variables (mainly Contrast 'J' and Saturation 's').
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_LOGSATURL_TOOLTIP;Saturation (s) in CIECAM02 corresponds to the color of a stimulus in relation to its own brightness.\nActs mainly on medium and highlights tones
+TP_LOCALLAB_LOGSCENE_TOOLTIP;Corresponds to the shooting conditions.
+TP_LOCALLAB_LOGSRCGREY_TOOLTIP;Estimated gray point value of the image.
+TP_LOCALLAB_LOGTARGGREY_TOOLTIP;You can adjust this value to suit.
TP_LOCALLAB_LOG_TOOLNAME;Log Encoding - 0
+TP_LOCALLAB_LOGVIEWING_TOOLTIP;Corresponds to the medium on which the final image will be viewed (monitor, TV, projector, printer,..), as well as its environment.
TP_LOCALLAB_LUM;Curves LL - CC
TP_LOCALLAB_LUMADARKEST;Darkest
-TP_LOCALLAB_LUMASK;Luminance Background Mask
-TP_LOCALLAB_LUMASK_TOOLTIP;Adjust the gray of the mask background in Show Mask (Mask and modifications)
-TP_LOCALLAB_LUMAWHITESEST;Whiteest
+TP_LOCALLAB_LUMASK;Background color for luminance and color masks
+TP_LOCALLAB_LUMASK_TOOLTIP;Adjusts the shade of gray or color of the mask background in Show Mask (Mask and modifications)
+TP_LOCALLAB_LUMAWHITESEST;Lightest
TP_LOCALLAB_LUMFRA;L*a*b* standard
TP_LOCALLAB_LUMONLY;Luminance only
TP_LOCALLAB_MASKCOM;Common Color Mask
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_MASFRAME_TOOLTIP;For all masks.\nTakes into account the deltaE image to avoid modifying the selection area when the following Mask Tools are used: Gamma , Slope , Chroma, Contrast curve , Local contrast (by wavelet level), Blur Mask and Structure Mask (if enabled ) .\nDisabled when Inverse mode is used
TP_LOCALLAB_MASK;Mask
-TP_LOCALLAB_MASK2;Contrast curve mask
+TP_LOCALLAB_MASK2;Contrast curve
TP_LOCALLAB_MASKCOL;Mask Curves
-TP_LOCALLAB_MASKH;Hue curve mask
-TP_LOCALLAB_MASK_TOOLTIP;You can enable multiple masks for a single tool, this requires activating another tool (but without using the tool : sliders to 0,...) where is the mask you want to activate.\n\nYou can also duplicate the RT-spot and place it right next to each other,variations of references allow fine work on images.
+TP_LOCALLAB_MASKCURVE_TOOLTIP;The 3 curves are set to 1 (maximum) by default:\nC=f(C) the chroma varies according to the chrominance. You can decrease the chroma to improve the selection. By setting this curve close to zero (with a low value of C to activate the curve) you can desaturate the background in Inverse mode.\nL=f(L) the luminance varies according to the luminance, so you can decrease the brightness to improve the selection.\nL and C = f(H) luminance and chroma vary with hue, so you can decrease luminance and chroma to improve selection
+TP_LOCALLAB_MASKH;Hue curve
+TP_LOCALLAB_MASK_TOOLTIP;You can enable multiple masks for a tool by activating another tool and using only the mask (set the tool sliders to 0 ).\n\nYou can also duplicate the RT-spot and place it close to the first spot. The small variations in the spot references allows you to make fine adjustments.
TP_LOCALLAB_MED;Medium
TP_LOCALLAB_MEDIAN;Median Low
+TP_LOCALLAB_MEDIAN_TOOLTIP;You can choose a median value in the range 3x3 to 9x9 pixels. Higher values increase noise reduction and blur.
+TP_LOCALLAB_MEDIANITER_TOOLTIP;The number of successive iterations carried out by the median filter.
TP_LOCALLAB_MEDNONE;None
TP_LOCALLAB_MERCOL;Color
TP_LOCALLAB_MERDCOL;Merge background (ΔE)
@@ -2641,12 +2726,13 @@ TP_LOCALLAB_MERFOR;Color Dodge
TP_LOCALLAB_MERFOU;Multiply
TP_LOCALLAB_MERGE1COLFRA;Merge with Original or Previous or Background
TP_LOCALLAB_MERGECOLFRA;Mask: LCH & Structure
+TP_LOCALLAB_MERGECOLFRMASK_TOOLTIP;Allows you to create masks based on the 3 LCH curves and/or a structure-detection algorithm
TP_LOCALLAB_MERGEFIV;Previous Spot(Mask 7) + Mask LCH
TP_LOCALLAB_MERGEFOU;Previous Spot(Mask 7)
-TP_LOCALLAB_MERGEMER_TOOLTIP;Take into account ΔE to merge files (equivalent of scope for this use)
+TP_LOCALLAB_MERGEMER_TOOLTIP;Takes ΔE into account when merging files (equivalent of scope in this case)
TP_LOCALLAB_MERGENONE;None
TP_LOCALLAB_MERGEONE;Short Curves 'L' Mask
-TP_LOCALLAB_MERGEOPA_TOOLTIP;Opacity merge % current Spot with original or previous Spot.\nContrast threshold : adjust result in function of Original contrast
+TP_LOCALLAB_MERGEOPA_TOOLTIP;Opacity = % of current spot to be merged with original or previous Spot.\nContrast threshold : adjusts result as a function of contrast in original image.
TP_LOCALLAB_MERGETHR;Original(Mask 7) + Mask LCH
TP_LOCALLAB_MERGETWO;Original(Mask 7)
TP_LOCALLAB_MERGETYPE;Merge image and mask
@@ -2658,7 +2744,7 @@ TP_LOCALLAB_MERLUM;Luminosity
TP_LOCALLAB_MERNIN;Screen
TP_LOCALLAB_MERONE;Normal
TP_LOCALLAB_MERSAT;Saturation
-TP_LOCALLAB_MERSEV;Soft Light Photshop
+TP_LOCALLAB_MERSEV;Soft Light (legacy)
TP_LOCALLAB_MERSEV0;Soft Light Illusion
TP_LOCALLAB_MERSEV1;Soft Light W3C
TP_LOCALLAB_MERSEV2;Hard Light
@@ -2667,10 +2753,10 @@ TP_LOCALLAB_MERTEN;Darken only
TP_LOCALLAB_MERTHI;Color Burn
TP_LOCALLAB_MERTHR;Difference
TP_LOCALLAB_MERTWE;Exclusion
-TP_LOCALLAB_MERTWO;Substract
+TP_LOCALLAB_MERTWO;Subtract
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_MLABEL;Restored data Min=%1 Max=%2 (Clip - Offset)
+TP_LOCALLAB_MLABEL_TOOLTIP;The values should be close to Min=0 Max=32768 (log mode) but other values are possible.You can adjust ‘Clip restored data (gain)’ and ‘Offset’ to normalize.\nRecovers image data without blending.
TP_LOCALLAB_MODE_EXPERT;Advanced
TP_LOCALLAB_MODE_NORMAL;Standard
TP_LOCALLAB_MODE_SIMPLE;Basic
@@ -2679,12 +2765,13 @@ TP_LOCALLAB_MRFOU;Previous Spot
TP_LOCALLAB_MRONE;None
TP_LOCALLAB_MRTHR;Original Image
TP_LOCALLAB_MRTWO;Short Curves 'L' Mask
-TP_LOCALLAB_MULTIPL_TOOLTIP;Allows the retouching of tones over a very wide range : -18EV +4EV. The first slider acts on very dark tones between -18EV and -6EV. The last slider acts light tones up to 4EV
+TP_LOCALLAB_MULTIPL_TOOLTIP;Wide-range tone adjustment: -18EV to +4EV. The first slider acts on very dark tones between -18EV and -6EV. The last slider acts on light tones up to 4EV
TP_LOCALLAB_NEIGH;Radius
-TP_LOCALLAB_NOISECHROCOARSE;Chroma coarse (Wav)
+TP_LOCALLAB_NOISE_TOOLTIP;Adds luminance noise
+TP_LOCALLAB_NOISECHROCOARSE;Coarse chroma (Wav)
TP_LOCALLAB_NOISECHROC_TOOLTIP;If superior to zero, high quality algorithm is enabled.\nCoarse is for slider >=0.02
TP_LOCALLAB_NOISECHRODETAIL;Chroma detail recovery (DCT ƒ)
-TP_LOCALLAB_NOISECHROFINE;Chroma fine (Wav)
+TP_LOCALLAB_NOISECHROFINE;Fine chroma (Wav)
TP_LOCALLAB_NOISEDETAIL_TOOLTIP;Disabled if slider = 100
TP_LOCALLAB_NOISELEQUAL;Equalizer white-black
TP_LOCALLAB_NOISELUMCOARSE;Luminance coarse (Wav)
@@ -2694,87 +2781,84 @@ TP_LOCALLAB_NOISELUMFINETWO;Luminance fine 2 (Wav)
TP_LOCALLAB_NOISELUMFINEZERO;Luminance fine 0 (Wav)
TP_LOCALLAB_NOISEMETH;Denoise
TP_LOCALLAB_NONENOISE;None
+TP_LOCALLAB_NUL_TOOLTIP;.
TP_LOCALLAB_OFFS;Offset
TP_LOCALLAB_OFFSETWAV;Offset
TP_LOCALLAB_OPACOL;Opacity
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_ORRETILAP_TOOLTIP;Modifies ΔE prior to any changes made by ‘Scope’. This allows you to differentiate the action for different parts of the image (with respect to the background for example).
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_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_PDEFRAME_TOOLTIP;PDE IPOL algorithm adapted for Rawtherapee : gives different results and requires different settings compared to main-menu ‘Exposure’.\nMay be useful for under-exposed or high dynamic range images.
TP_LOCALLAB_PREVIEW;Preview ΔE
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_QUALCURV_METHOD;Curve type
TP_LOCALLAB_QUAL_METHOD;Global quality
TP_LOCALLAB_RADIUS;Radius
-TP_LOCALLAB_RADIUS_TOOLTIP;Above Radius 30 Use Fast Fourier Transform
-TP_LOCALLAB_RADMASKCOL;Smooth Radius Mask
+TP_LOCALLAB_RADIUS_TOOLTIP;Uses a Fast Fourier Transform for radius > 30
+TP_LOCALLAB_RADMASKCOL;Smooth radius
TP_LOCALLAB_RECT;Rectangle
TP_LOCALLAB_RECURS;Recursive references
-TP_LOCALLAB_RECURS_TOOLTIP;Recalculate references for hue, luma, chroma after each module and after each RT-spot.\nAlso useful for working with masks.
+TP_LOCALLAB_RECURS_TOOLTIP;Forces the algorithm to recalculate the references after each tool is applied.\nAlso useful for working with masks.
TP_LOCALLAB_REFLABEL;Ref. (0..1) Chroma=%1 Luma=%2 Hue=%3
TP_LOCALLAB_REN_DIALOG_LAB;Enter the new Control Spot name
TP_LOCALLAB_REN_DIALOG_NAME;Renaming Control Spot
TP_LOCALLAB_RESETSHOW;Reset All Show Modifications
TP_LOCALLAB_RESID;Residual Image
-TP_LOCALLAB_RESIDBLUR;Blur Residual Image
+TP_LOCALLAB_RESIDBLUR;Blur residual image
TP_LOCALLAB_RESIDCHRO;Residual image Chroma
-TP_LOCALLAB_RESIDCOMP;Compress Residual image
+TP_LOCALLAB_RESIDCOMP;Compress residual image
TP_LOCALLAB_RESIDCONT;Residual image Contrast
TP_LOCALLAB_RESIDHI;Highlights
TP_LOCALLAB_RESIDHITHR;Highlights threshold
TP_LOCALLAB_RESIDSHA;Shadows
TP_LOCALLAB_RESIDSHATHR;Shadows threshold
-TP_LOCALLAB_RETI;Dehaze - Retinex
+TP_LOCALLAB_RETI;Dehaze & Retinex
TP_LOCALLAB_RETIFRA;Retinex
+TP_LOCALLAB_RETIFRAME_TOOLTIP;Retinex can be useful for processing images: \nthat are blurred, foggy or hazy (in addition to Dehaze).\nthat contain large differences in luminance.\nIt can also be used for special effects (tone mapping).
TP_LOCALLAB_RETIM;Original Retinex
TP_LOCALLAB_RETITOOLFRA;Retinex Tools
TP_LOCALLAB_RETI_FFTW_TOOLTIP;FFT improve quality and allow big radius, but increases the treatment time.\nThe treatment time depends on the surface to be treated\nThe treatment time depends on the value of scale (be carefull to high values).\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.\nOptimization not used in Preview
-TP_LOCALLAB_RETI_LIGHTDARK_TOOLTIP;Have no effect when the value "Lightness = 1" or "Darkness =2" is chosen.\nIn other cases, the last step of "Multiple scale Retinex" is applied an algorithm close to "local contrast", these 2 cursors, associated with "Strength" will allow to play upstream on the local contrast.
-TP_LOCALLAB_RETI_LIMDOFFS_TOOLTIP;Play on internal parameters to optimize response.\nLook at the "restored datas" indicators "near" min=0 and max=32768 (log mode), but others values are possible.
-TP_LOCALLAB_RETI_LOGLIN_TOOLTIP;Logarithm allows differenciation for haze or normal.\nLogarithm brings more contrast but will generate more halo.
-TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP;Adapt these values according to images - if misty images and depending on whether you want to act on the front or the background
-TP_LOCALLAB_RETI_SCALE_TOOLTIP;If scale=1, retinex behaves like local contrast with many more possibilities.\nThe greater the scale, the more intense the recursive action, the longer the calculation times
+TP_LOCALLAB_RETI_LIGHTDARK_TOOLTIP;Has no effect when the value of "Lightness = 1" or "Darkness =2".\nFor other values, the last step of a "Multiple scale Retinex" algorithm (similar to "local contrast") is applied. These 2 cursors, associated with "Strength" allow you to make adjustments upstream of local contrast
+TP_LOCALLAB_RETI_LIMDOFFS_TOOLTIP;Adjusts the internal parameters to optimize the response.\nPreferable to keep the "Restored data" values close to Min=0 and Max=32768 (log mode), but other values are possible.
+TP_LOCALLAB_RETI_LOGLIN_TOOLTIP;Logarithm mode introduces more contrast but will also generate more halos.
+TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP;The radius and variance sliders allow you adjust haze and target either the foreground or the background.
+TP_LOCALLAB_RETI_SCALE_TOOLTIP;If Scale=1, Retinex behaves like local contrast with additional possibilities.\nIncreasing the value of Scale increases the intensity of the recursive action at the expense of processing time.
TP_LOCALLAB_RET_TOOLNAME;Dehaze & Retinex - 9
TP_LOCALLAB_REWEI;Reweighting iterates
TP_LOCALLAB_RGB;RGB Tone Curve
+TP_LOCALLAB_RGBCURVE_TOOLTIP;In RGB mode you have 4 choices : Standard, Weighted standard, Luminance & Film-like.
TP_LOCALLAB_ROW_NVIS;Not visible
TP_LOCALLAB_ROW_VIS;Visible
TP_LOCALLAB_SATUR;Saturation
+TP_LOCALLAB_SATURV;Saturation (s)
TP_LOCALLAB_SAVREST;Save - Restore Current Image
TP_LOCALLAB_SCALEGR;Scale
TP_LOCALLAB_SCALERETI;Scale
TP_LOCALLAB_SCALTM;Scale
-TP_LOCALLAB_SCOPEMASK;Scope Mask ΔE Image
-TP_LOCALLAB_SCOPEMASK_TOOLTIP;Enabled if Mask DeltaE Image is enabled.\nLow values avoid retouching selected area
+TP_LOCALLAB_SCOPEMASK;Scope (ΔE image mask)
+TP_LOCALLAB_SCOPEMASK_TOOLTIP;Enabled if DeltaE Image Mask is enabled.\nLow values avoid retouching selected area
TP_LOCALLAB_SENSI;Scope
-TP_LOCALLAB_SENSIBN;Scope
-TP_LOCALLAB_SENSICB;Scope
-TP_LOCALLAB_SENSIDEN;Scope
TP_LOCALLAB_SENSIEXCLU;Scope
-TP_LOCALLAB_SENSIEXCLU_TOOLTIP;Adjust color to include in exclusion!
-TP_LOCALLAB_SENSIH;Scope
-TP_LOCALLAB_SENSIH_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.
-TP_LOCALLAB_SENSILOG;Scope
-TP_LOCALLAB_SENSIS;Scope
-TP_LOCALLAB_SENSIS_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm.
-TP_LOCALLAB_SENSI_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm.
-TP_LOCALLAB_SENSIMASK_TOOLTIP;Adjust scope of action for this common mask tool.\nActs on the gap between the original image and the mask.\nThe references (luma, chroma, hue) are those of the center of the RT-spot\n\nYou can also act on deltaE internal to the mask with 'Scope Mask deltaE image' in 'Settings'
+TP_LOCALLAB_SENSIEXCLU_TOOLTIP;Adjust the colors to be excluded
+TP_LOCALLAB_SENSI_TOOLTIP;Adjusts the scope of the action:\nSmall values limit the action to colors similar to those in the center of the spot.\nHigh values let the tool act on a wider range of colors
+TP_LOCALLAB_SENSIMASK_TOOLTIP;Scope adjustment specific to common mask tool.\nActs on the difference between the original image and the mask.\nUses the luma, chroma & hue references from the center of the RT-spot\n\nYou can also adjust the deltaE of the mask itself by using 'Scope (deltaE image mask)' in 'Settings' > ‘Mask & Merge’
TP_LOCALLAB_SETTINGS;Settings
TP_LOCALLAB_SH1;Shadows Highlights
TP_LOCALLAB_SH2;Equalizer
TP_LOCALLAB_SHADEX;Shadows
-TP_LOCALLAB_SHADEXCOMP;Shadows compression & tonal width
-TP_LOCALLAB_SHADHIGH;Shadows/Highlights-Tone equalizer
+TP_LOCALLAB_SHADEXCOMP;Shadow compression & tonal width
+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...
+TP_LOCALLAB_SHAMASKCOL;Shadows
+TP_LOCALLAB_SHADMASK_TOOLTIP;Lifts the shadows of the mask in the same way as the shadows/highlights algorithm
+TP_LOCALLAB_SHADHMASK_TOOLTIP;Lowers the highlights of the mask in the same way as the shadows/highlights algorithm
+TP_LOCALLAB_SHAPETYPE;RT-spot shape
+TP_LOCALLAB_SHAPE_TOOLTIP;”Ellipse” is the normal mode.\n “Rectangle” can be used in certain cases, for example to work in full-image mode by placing the delimiters outside the preview area. In this case, set transition = 100.\n\nFuture developments will include polygon shapes and Bezier curves.
TP_LOCALLAB_SHARAMOUNT;Amount
TP_LOCALLAB_SHARBLUR;Blur radius
TP_LOCALLAB_SHARDAMPING;Damping
@@ -2788,136 +2872,167 @@ TP_LOCALLAB_SHORTCMASK_TOOLTIP;Short circuit the 2 curves L(L) and L(H).\nAllows
TP_LOCALLAB_SHOWC;Mask and modifications
TP_LOCALLAB_SHOWC1;Merge file
TP_LOCALLAB_SHOWCB;Mask and modifications
-TP_LOCALLAB_SHOWDCT;Show process Fourier ƒ
+TP_LOCALLAB_SHOWDCT;Show Fourier (ƒ) process
TP_LOCALLAB_SHOWE;Mask and modifications
TP_LOCALLAB_SHOWFOURIER;Fourier ƒ(dct)
TP_LOCALLAB_SHOWLAPLACE;∆ Laplacian (first)
TP_LOCALLAB_SHOWLC;Mask and modifications
TP_LOCALLAB_SHOWMASK;Show mask
-TP_LOCALLAB_SHOWMASKCOL_TOOLTIP;Display mask modifications.\nBeware, you can only view one tool mask at the same time.\n\nNote: Use Mask is before algorihtm shape detection.
-TP_LOCALLAB_SHOWMASKSOFT_TOOLTIP;Show process Fourier:\nShows the different stages of the process.\nLaplace - builds the second derivative according to the threshold (first step).\nFourier -shows the transformed Laplacian with DCT.\nPoisson - show solution of Poisson DCE.\nNormalize - show result without normalization luminance.
+TP_LOCALLAB_SHOWMASKCOL_TOOLTIP;Displays masks and modifications.\nBeware, you can only view one tool mask at a time.\nShow modified image: shows the modified image including the effect of any adjustments and masks.\nShow modified areas without mask: shows the modifications before any masks are applied.\nShow modified areas with mask: shows the modifications after a mask has been applied.\nShow mask: shows the aspect of the mask including the effect of any curves and filters.\nShow spot structure: allows you to see the structure-detection mask when the "Spot structure" cursor is activated (when available).\nNote: The mask is applied before the shape detection algorithm.
+TP_LOCALLAB_SHOWMASKSOFT_TOOLTIP;Allows you to visualize the different stages of the Fourier process.\n Laplace - calculates the second derivative of the Laplace transform as a function of the threshold.\nFourier - shows the Laplacian transform with DCT.\nPoisson - shows the solution of the Poisson DCE.\nNo luminance normalization - shows result without any luminance normalization.
TP_LOCALLAB_SHOWMASKTYP1;Blur & Noise
TP_LOCALLAB_SHOWMASKTYP2;Denoise
TP_LOCALLAB_SHOWMASKTYP3;Blur & Noise + Denoise
TP_LOCALLAB_SHOWMASKTYP_TOOLTIP;Mask and modifications can be chosen.\nBlur and noise : in this case it is not used for 'denoise'.\nDenoise : in this case it is not used for 'blur and noise'.\n\nBlur and noise + denoise : mask is shared, be carefull to 'show modifications' and 'scope'
-TP_LOCALLAB_SHOWMNONE;None
-TP_LOCALLAB_SHOWMODIF;Show modifications without mask
-TP_LOCALLAB_SHOWMODIFMASK;Show modifications with mask
-TP_LOCALLAB_SHOWNORMAL;Normalize luminance (no)
-TP_LOCALLAB_SHOWPLUS;Mask and modifications - Smooth-Blur & Denoise
+TP_LOCALLAB_SHOWMNONE;Show modified image
+TP_LOCALLAB_SHOWMODIF;Show modified areas without mask
+TP_LOCALLAB_SHOWMODIFMASK;Show modified areas with mask
+TP_LOCALLAB_SHOWNORMAL;No luminance normalization
+TP_LOCALLAB_SHOWPLUS;Mask and modifications (Blur & Denoise)
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(advanced)
-TP_LOCALLAB_SHOWSTRUCEX;Show structure Spot(advanced)
+TP_LOCALLAB_SHOWSTRUC;Show spot structure(advanced)
+TP_LOCALLAB_SHOWSTRUCEX;Show spot structure(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 Highlights & Tone Equalizer - 5
-TP_LOCALLAB_SIGMAWAV;Attenuation Response
+TP_LOCALLAB_SHTRC_TOOLTIP;Based on 'working profile' (only those provided), 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.\nIt is recommended that the TRC of both devices (monitor and output profile) be sRGB (default).
+TP_LOCALLAB_SH_TOOLNAME;Shadows/Highlights & Tone Equalizer - 5
+TP_LOCALLAB_SIGMAWAV;Attenuation response
TP_LOCALLAB_SIM;Simple
-TP_LOCALLAB_SLOMASKCOL;Slope mask
+TP_LOCALLAB_SLOMASKCOL;Slope
+TP_LOCALLAB_SLOMASK_TOOLTIP;Gamma and Slope allow a soft and artifact-free transformation of the mask by progressively modifying “L” to avoid any discontinuities.
TP_LOCALLAB_SLOSH;Slope
-TP_LOCALLAB_SOFT;Soft Light - Original Retinex
+TP_LOCALLAB_SOFT;Soft Light & Original Retinex
TP_LOCALLAB_SOFTM;Soft Light
-//TP_LOCALLAB_SOFTMETHOD_TOOLTIP;Original Retinex is very different from others Retinex method.\nIts acts on grey and balance luminance.\nIt is an emulation of "Dodge" and "Burn"
TP_LOCALLAB_SOFTMETHOD_TOOLTIP;Apply a Soft-light blend (identical to the global adjustment). Carry out dodge and burn using the original Retinex algorithm.
TP_LOCALLAB_SOFTRADIUSCOL;Soft radius
-TP_LOCALLAB_SOFTRETI;Reduce artifact ΔE
+TP_LOCALLAB_SOFTRADIUSCOL_TOOLTIP;Applies a guided filter to the output image to reduce possible artifacts.
+TP_LOCALLAB_SOFTRETI;Reduce ΔE artifacts
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_SOURCE_ABS;Absolute luminance
+TP_LOCALLAB_SOURCE_GRAY;Mean luminance (Yb%)
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_SPECIAL_TOOLTIP;The checkbox allows you to remove all other actions i.e. “Scope”, masks, sliders etc., (except for transitions) and use just the effect of the RGB tone-curve.
TP_LOCALLAB_SPOTNAME;New Spot
TP_LOCALLAB_STD;Standard
TP_LOCALLAB_STR;Strength
TP_LOCALLAB_STRBL;Strength
-TP_LOCALLAB_STREN;Compression Strength
+TP_LOCALLAB_STREN;Compression strength
TP_LOCALLAB_STRENG;Strength
TP_LOCALLAB_STRENGR;Strength
TP_LOCALLAB_STRENGTH;Noise
+TP_LOCALLAB_STRENGRID_TOOLTIP;You can adjust the desired effect with "strength", but you can also use the "scope" function which allows you to delimit the action (e.g. to isolate a particular color).
TP_LOCALLAB_STRGRID;Strength
TP_LOCALLAB_STRRETI_TOOLTIP;if Strength Retinex < 0.2 only Dehaze is enabled.\nif Strength Retinex >= 0.1 Dehaze is in luminance mode.
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 (advanced) structure, blur, wavelet to improve edge detection.\n\nNeeds maskless adjustments to be activated (lightness, exposure...)
+TP_LOCALLAB_STRUCCOL;Spot structure
+TP_LOCALLAB_STRUCCOL1;Spot structure
+TP_LOCALLAB_STRUCT_TOOLTIP;Uses the Sobel algorithm to take into account structure for shape detection.\nActivate "Mask and modifications” > “Show spot structure" (advanced mode) to see a preview of the mask (without modifications).\n\nCan be used in conjunction with the Structure Mask, Blur Mask and “Local contrast (by wavelet level)” to improve edge detection.\n\nEffects of adjustments using Lightness, Contrast, Chrominance, Exposure or other non-mask-related tools visible using either ‘Show modified image” or “Show modified areas with mask ”.
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_STRUMASK_TOOLTIP;Structure mask (slider) with the checkbox "Structure mask as tool" unchecked: In this case a mask showing the structure will be generated even if none of the 3 curves is activated. Structure masks are available for mask 1 (Blur and denoise") and mask 7 (Color & Light).
+TP_LOCALLAB_STRUSTRMASK_TOOLTIP;Moderate use of this slider is recommended!
TP_LOCALLAB_STYPE;Shape method
TP_LOCALLAB_STYPE_TOOLTIP;You can choose between:\nSymmetrical - left handle linked to right, top handle linked to bottom.\nIndependent - all handles are independent.
TP_LOCALLAB_SYM;Symmetrical (mouse)
TP_LOCALLAB_SYMSL;Symmetrical (mouse + sliders)
-TP_LOCALLAB_TARGET_GRAY;Target Gray Point
+TP_LOCALLAB_TARGET_GRAY;Mean luminance (Yb%)
TP_LOCALLAB_THRES;Threshold structure
-TP_LOCALLAB_THRESDELTAE;Threshold ΔE-scope
+TP_LOCALLAB_THRESDELTAE;ΔE scope threshold
TP_LOCALLAB_THRESRETI;Threshold
-TP_LOCALLAB_THRESWAV;Balance Threshold
-TP_LOCALLAB_TLABEL;TM Datas Min=%1 Max=%2 Mean=%3 Sigma=%4 (Threshold)
+TP_LOCALLAB_THRESWAV;Balance threshold
+TP_LOCALLAB_TLABEL;TM Data Min=%1 Max=%2 Mean=%3 Sigma=%4 (Threshold)
TP_LOCALLAB_TLABEL2;TM Effective Tm=%1 TM=%2
-TP_LOCALLAB_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Variance.\nTm=Min TM=Max of Transmission Map.\nYou can act on Threshold to normalize
-TP_LOCALLAB_TM;Tone Mapping - Texture
+TP_LOCALLAB_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Variance.\nTm=Min TM=Max of Transmission Map.\nYou can normalize the results with the threshold slider.
+TP_LOCALLAB_TM;Tone Mapping
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_TOOLMASK_TOOLTIP;Structure mask (slider) with the checkbox "Structure mask as tool" checked: in this case a mask showing the structure will be generated after one or more of the 2 curves L(L) or LC(H) has been modified.\n Here, the "Structure mask" behaves like the other Mask tools : Gamma, Slope, etc.\n It allows you to vary the action on the mask according to the structure of the image.
+TP_LOCALLAB_TONEMAPESTOP_TOOLTIP;This slider affects edge sensitivity.\n The greater the value, the more likely a change in contrast will be interpreted as an "edge".\n If set to zero the tone mapping will have an effect similar to unsharp masking.
+TP_LOCALLAB_TONEMAPGAM_TOOLTIP;The Gamma slider shifts the tone-mapping effect towards either the shadows or the 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;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_TONEMAP_TOOLTIP;Same as the tone mapping tool in the main menu.\nThe main-menu tool must be deactivated if this tool is used.
+TP_LOCALLAB_TONEMASCALE_TOOLTIP;This slider allows you to adjust the transition between "local" and "global" contrast.\nThe greater the value, the larger a detail needs to be for it to be boosted
TP_LOCALLAB_TONE_TOOLNAME;Tone Mapping - 4
TP_LOCALLAB_TOOLCOL;Structure mask as tool
-TP_LOCALLAB_TOOLMASK;Tools
+TP_LOCALLAB_TOOLCOLFRMASK_TOOLTIP;Allows you to modify the mask, if one exists
TP_LOCALLAB_TRANSIT;Transition Gradient
+TP_LOCALLAB_TOOLMASK;Mask Tools
TP_LOCALLAB_TRANSITGRAD;Transition differentiation XY
-TP_LOCALLAB_TRANSITGRAD_TOOLTIP;Changes the transition of the abscissa to that of the ordinate
+TP_LOCALLAB_TRANSITGRAD_TOOLTIP;Allows you to vary the y-axis transition
TP_LOCALLAB_TRANSITVALUE;Transition value
TP_LOCALLAB_TRANSITWEAK;Transition decay (linear-log)
-TP_LOCALLAB_TRANSITWEAK_TOOLTIP;Adjust transition decay : change smoothness process - 1 linear - 2 parabolic - 3 cubic - ^25.\nCan be used in conjunction with very low transition values to reduce defects (CBDL, Wavelet, Color & Light)
-TP_LOCALLAB_TRANSIT_TOOLTIP;Adjust smoothness of transition between affected and unaffected areas, as a percentage of the "radius"
+TP_LOCALLAB_TRANSITWEAK_TOOLTIP;Adjust transition decay function: 1 linear , 2 parabolic, 3 cubic up to ^25.\nCan be used in conjunction with very low transition values to reduce defects (CBDL, Wavelets, Color & Light)
+TP_LOCALLAB_TRANSIT_TOOLTIP;Adjust smoothness of transition between affected and unaffected areas as a percentage of the "radius"
TP_LOCALLAB_TRANSMISSIONGAIN;Transmission gain
TP_LOCALLAB_TRANSMISSIONMAP;Transmission map
-TP_LOCALLAB_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscissa: transmission from negative values (min), mean, and positives values (max).\nOrdinate: amplification or reduction.\nYou can act on this curve to change Transmission and reduce the artifacts
+TP_LOCALLAB_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscissa: transmission from negative values (min), mean, and positive values (max).\nOrdinate: amplification or reduction.\nYou can adjust this curve to change the Transmission and reduce artifacts
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_VIBRANCE;Vibrance & Warm/Cool
+TP_LOCALLAB_VIBRA_TOOLTIP;Adjusts vibrance (essentially the same as the global adjustment).\nCarries 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 Grain & Denoise - 1
+TP_LOCALLAB_BLUR_TOOLNAME;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 Contrast & Wavelet - 7
+TP_LOCALLAB_LC_TOOLNAME;Local Contrast & Wavelets - 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
-TP_LOCALLAB_WARM;Warm - Cool & Color artifacts
-TP_LOCALLAB_WARM_TOOLTIP;This slider use Ciecam algorithm and acts as White Balance, it can warm or cool the area selected.\nIt can also in some cases reduce color artifacts.
-TP_LOCALLAB_WASDEN_TOOLTIP;Denoise luminance for the 3 first levels (fine).\nThe right limit of the curve correspond to coarse : level 3 and beyond
-TP_LOCALLAB_WAV;Levels local contrast
-TP_LOCALLAB_WAVBLUR_TOOLTIP;Performs a blur for each level of decomposition, as well as the residual image.
-TP_LOCALLAB_WAVCOMP;Compression by Level
-TP_LOCALLAB_WAVCOMPRE;(un)Compression by Level
-TP_LOCALLAB_WAVCOMPRE_TOOLTIP;Achieve a Tone-mapping or reduction local contrast by levels.\nOn abscissa levels
-TP_LOCALLAB_WAVCOMP_TOOLTIP;Achive local contrast in function of the direction wavelet decomposition : horizontal, vertical, diagonal
-TP_LOCALLAB_WAVCON;Contrast by Level
-TP_LOCALLAB_WAVCONTF_TOOLTIP;Similar to Contrast By Detail Levels : on abscissa levels.
-TP_LOCALLAB_WAVDEN;Luminance denoise by level (0 1 2 +3 and more)
-TP_LOCALLAB_WAVE;Ψ Wavelet
+TP_LOCALLAB_WARM;Warm/Cool & Color artifacts
+TP_LOCALLAB_WARM_TOOLTIP;This slider uses the CIECAM algorithm and acts as a White Balance control to make the color temperature of the selected area warmer or cooler.\nIt can also reduce color artifacts in some cases.
+TP_LOCALLAB_WASDEN_TOOLTIP;Luminance noise reduction: the left-hand side of the curve corresponds to the first 3 levels 0,1 &2 (fine detail). The right hand side of the curve corresponds to the coarser details (level 3 and beyond).
+TP_LOCALLAB_WAT_WAVSHAPE_TOOLTIP;Low to high local contrast from left to right on the x-axis\nIncrease or decrease local contrast on the y-axis.
+TP_LOCALLAB_WAT_LEVELLOCCONTRAST_TOOLTIP;Low to high local contrast from left to right on the x-axis.\nIncrease or decrease local contrast on the y-axis.
+TP_LOCALLAB_WAT_SIGMALC_TOOLTIP;The effect of the local contrast adjustment is stronger for medium-contrast details, and weaker for high and low-contrast details.\n This slider controls how quickly the effect dampens towards the extreme contrasts.\nThe higher the value of the slider, the wider the range of contrasts that will receive the full effect of the local contrast adjustment, and the higher the risk of generating artifacts.\nThe lower the value, the more the effect will be pinpointed towards a narrow range of contrast values.
+TP_LOCALLAB_WAT_BLURLC_TOOLTIP;The default blur setting affects all 3 L*a* b* components (luminance and colour).\nWhen checked, only luminance is blurred.
+TP_LOCALLAB_WAT_THRESHOLDWAV_TOOLTIP;Range of wavelet levels used throughout the "Wavelets" module.
+TP_LOCALLAB_WAT_EXPRESID_TOOLTIP;The residual image behaves in the same way as the main image when making adjustments to contrast, chroma etc.
+TP_LOCALLAB_WAT_CLARIL_TOOLTIP;“Merge luma” is used to select the intensity of the desired effect on luminance.
+TP_LOCALLAB_WAT_CLARIC_TOOLTIP;“Merge chroma” is used to select the intensity of the desired effect on chrominance.
+TP_LOCALLAB_WAT_ORIGLC_TOOLTIP;“Merge only with original image”, prevents the “Wavelet Pyramid” settings from interfering with “Clarity” and “Sharp mask”.
+TP_LOCALLAB_WAT_STRWAV_TOOLTIP;Allows the local contrast to be varied according to a chosen gradient and angle. The variation of the luminance signal is taken into account and not the luminance.
+TP_LOCALLAB_WAT_CONTOFFSET_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_LOCALLAB_WAT_CONTCHROMALEV_TOOLTIP;“Chroma levels”: adjusts the “a” and “b” components of Lab* as a proportion of the luminance value.
+TP_LOCALLAB_WAT_WAVCBDL_TOOLTIP;Similar to Contrast By Detail Levels. Fine to coarse detail levels from left to right on the x-axis.
+TP_LOCALLAB_WAT_STRENGTHW_TOOLTIP;Intensity of edge-effect detection.
+TP_LOCALLAB_WAT_LOCCONTRASTEDG_TOOLTIP;You can adjust the distribution of local contrast by wavelet level based on the initial intensity of the contrast. This will modify the effects of perspective and relief in the image, and/or reduce the contrast values for very low initial contrast levels.
+TP_LOCALLAB_WAT_GRADW_TOOLTIP;The more you move the slider to the right, the more effective the detection algorithm will be and the less noticeable the effects of local contrast.
+TP_LOCALLAB_WAT_WAVESHOW_TOOLTIP;Shows all of the "Edge sharpness" tools. It is advisable to read the Wavelet Levels documentation.
+TP_LOCALLAB_WAT_WAVLEVELBLUR_TOOLTIP;Allows you to adjust the maximum effect of blurring on the levels.
+TP_LOCALLAB_WAT_WAVBLURCURV_TOOLTIP;Allows you to blur each level of decomposition.\nThe finest to coarsest levels of decomposition are from left to right.
+TP_LOCALLAB_WAT_RESIDBLUR_TOOLTIP;Blurs the residual image, independent of the levels.
+TP_LOCALLAB_WAT_WAVTM_TOOLTIP;The lower (negative) part compresses each level of decomposition creating a tone mapping effect.\nThe upper (positive) part attenuates the contrast by level.\nThe finest to coarsest levels of decomposition are from left to right on the x-axis.
+TP_LOCALLAB_WAT_BALTHRES_TOOLTIP;Balances the action within each level.
+TP_LOCALLAB_WAT_RESIDCOMP_TOOLTIP;Compresses the residual image to increase or reduce contrast.
+TP_LOCALLAB_WAT_DELTABAL_TOOLTIP;By moving the slider to the left, the lower levels are accentuated. To the right, the lower levels are reduced and the higher levels accentuated.
+TP_LOCALLAB_WAT_WAVDELTABAL_TOOLTIP;Acts on the balance of the three directions (horizontal, vertical and diagonal) based on the luminance of the image.\nBy default the shadows or highlights are reduced to avoid artifacts.
+TP_LOCALLAB_WAV;Local contrast
+TP_LOCALLAB_WAVBLUR_TOOLTIP;Allows you to blur each level of the decomposition, as well as the residual image.
+TP_LOCALLAB_WAVCOMP;Compression by level
+TP_LOCALLAB_WAVCOMPRE;Compression by level
+TP_LOCALLAB_WAVCOMPRE_TOOLTIP;Allows you to apply tone mapping or reduce local contrast on individual levels.\nFine to coarse detail levels from left to right on the x-axis.
+TP_LOCALLAB_WAVCOMP_TOOLTIP;Allows you to apply local contrast based on the direction of the wavelet decomposition : horizontal, vertical, diagonal
+TP_LOCALLAB_WAVCON;Contrast by level
+TP_LOCALLAB_WAVCONTF_TOOLTIP;Similar to Contrast By Detail Levels. Fine to coarse detail levels from left to right on the x-axis.
+TP_LOCALLAB_WAVDEN;Luminance denoise by level
+TP_LOCALLAB_WAVE;Ψ Wavelets
TP_LOCALLAB_WAVEDG;Local contrast
-TP_LOCALLAB_WAVEEDG_TOOLTIP;Achieves a sharpness taking into account the notion of edges wavelet.\nRequires that at least the first 4 levels are usable
-TP_LOCALLAB_WAVGRAD_TOOLTIP;Graduated filter for Local contrast "luminance"
+TP_LOCALLAB_WAVEEDG_TOOLTIP;Improves sharpness by targeting the action of local contrast on the edges. It has the same functions as the corresponding module in Wavelet Levels and uses the same settings.
+TP_LOCALLAB_WAVGRAD_TOOLTIP;Allows the local contrast to be varied according to a chosen gradient and angle. The variation of the luminance signal is taken into account and not the luminance.
TP_LOCALLAB_WAVHIGH;Ψ Wavelet high
-TP_LOCALLAB_WAVLEV;Blur by Level
+TP_LOCALLAB_WAVLEV;Blur by level
TP_LOCALLAB_WAVLOW;Ψ Wavelet low
-TP_LOCALLAB_WAVMASK;Ψ Mask Levels local contrast
-TP_LOCALLAB_WAVMASK_TOOLTIP;Allows fine work on mask levels contrasts (structure)
+TP_LOCALLAB_WAVMASK;Ψ Local contrast (by wavelet level)
+TP_LOCALLAB_WAVMASK_TOOLTIP;Uses wavelets to modify the local contrast of the mask and reinforce or reduce the structure (skin, buildings...)
+TP_LOCALLAB_WAVEMASK_LEVEL_TOOLTIP;Range of wavelet levels used in “Local contrast (by wavelet level)”
TP_LOCALLAB_WAVMED;Ψ Wavelet normal
TP_LOCALLAB_WEDIANHI;Median Hi
TP_LOCALLAB_WHITE_EV;White Ev
@@ -2925,7 +3040,7 @@ TP_LOCAL_HEIGHT;Bottom
TP_LOCAL_HEIGHT_T;Top
TP_LOCAL_WIDTH;Right
TP_LOCAL_WIDTH_L;Left
-TP_LOCRETI_METHOD_TOOLTIP;Low = Reinforce low light.\nUniform = Equalize action.\nHigh = Reinforce high light.\n
+TP_LOCRETI_METHOD_TOOLTIP;Low = Reinforce low light.\nUniform = Evenly distributed.\nHigh = Reinforce strong light.\n
TP_METADATA_EDIT;Apply modifications
TP_METADATA_MODE;Metadata copy mode
TP_METADATA_STRIP;Strip all metadata
@@ -2948,6 +3063,8 @@ TP_PERSPECTIVE_CAMERA_ROLL;Rotation
TP_PERSPECTIVE_CAMERA_SHIFT_HORIZONTAL;Horizontal shift
TP_PERSPECTIVE_CAMERA_SHIFT_VERTICAL;Vertical shift
TP_PERSPECTIVE_CAMERA_YAW;Horizontal
+TP_PERSPECTIVE_CONTROL_LINES;Control lines
+TP_PERSPECTIVE_CONTROL_LINES_TOOLTIP;Ctrl+drag: Draw new line\nRight-click: Delete line
TP_PERSPECTIVE_HORIZONTAL;Horizontal
TP_PERSPECTIVE_LABEL;Perspective
TP_PERSPECTIVE_METHOD;Method
@@ -3006,11 +3123,13 @@ TP_RAW_3PASSBEST;3-pass (Markesteijn)
TP_RAW_4PASS;3-pass+fast
TP_RAW_AHD;AHD
TP_RAW_AMAZE;AMaZE
+TP_RAW_AMAZEBILINEAR;AMaZE+Bilinear
TP_RAW_AMAZEVNG4;AMaZE+VNG4
TP_RAW_BORDER;Border
TP_RAW_DCB;DCB
TP_RAW_DCBENHANCE;DCB enhancement
TP_RAW_DCBITERATIONS;Number of DCB iterations
+TP_RAW_DCBBILINEAR;DCB+Bilinear
TP_RAW_DCBVNG4;DCB+VNG4
TP_RAW_DMETHOD;Method
TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing...
@@ -3063,6 +3182,7 @@ TP_RAW_PIXELSHIFTSIGMA_TOOLTIP;The default radius of 1.0 usually fits well for b
TP_RAW_PIXELSHIFTSMOOTH;Smooth transitions
TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP;Smooth transitions between areas with motion and areas without.\nSet to 0 to disable transition smoothing.\nSet to 1 to either get the AMaZE/LMMSE result of the selected frame (depending on whether "Use LMMSE" is selected), or the median of all four frames if "Use median" is selected.
TP_RAW_RCD;RCD
+TP_RAW_RCDBILINEAR;RCD+Bilinear
TP_RAW_RCDVNG4;RCD+VNG4
TP_RAW_SENSOR_BAYER_LABEL;Sensor with Bayer Matrix
TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP;3-pass gives best results (recommended for low ISO images).\n1-pass is almost undistinguishable from 3-pass for high ISO images and is faster.\n+fast gives less artifacts in flat areas
@@ -3100,7 +3220,7 @@ TP_RETINEX_FREEGAMMA;Free gamma
TP_RETINEX_GAIN;Gain
TP_RETINEX_GAINOFFS;Gain and Offset (brightness)
TP_RETINEX_GAINTRANSMISSION;Gain transmission
-TP_RETINEX_GAINTRANSMISSION_TOOLTIP;Amplify or reduce the transmission map to achieve the desired luminance.\nThe x-axis is the transmission.\nThe y-axis is the gain.
+TP_RETINEX_GAINTRANSMISSION_TOOLTIP;Increase or reduce the transmission map to achieve the desired luminance. The x-axis is the transmission. The y-axis is the gain.
TP_RETINEX_GAMMA;Gamma
TP_RETINEX_GAMMA_FREE;Free
TP_RETINEX_GAMMA_HIGH;High
@@ -3135,7 +3255,7 @@ TP_RETINEX_MEDIAN;Transmission median filter
TP_RETINEX_METHOD;Method
TP_RETINEX_METHOD_TOOLTIP;Low = Reinforce low light.\nUniform = Equalize action.\nHigh = Reinforce high light.\nHighlights = Remove magenta in highlights.
TP_RETINEX_MLABEL;Restored data Min=%1 Max=%2
-TP_RETINEX_MLABEL_TOOLTIP;'Should be' near min=0 max=32768 (log mode) but others values are possible\nRestored image with no mixture.
+TP_RETINEX_MLABEL_TOOLTIP;The values should be close to Min=0 Max=32768 (log mode) but other values are possible.You can adjust ‘Clip restored data (gain)’ and ‘Offset’ to normalize.\nRecovers image data without blending
TP_RETINEX_NEIGHBOR;Radius
TP_RETINEX_NEUTRAL;Reset
TP_RETINEX_NEUTRAL_TIP;Reset all sliders and curves to their default values.
@@ -3150,7 +3270,7 @@ TP_RETINEX_THRESHOLD;Threshold
TP_RETINEX_THRESHOLD_TOOLTIP;Limits in/out.\nIn = image source,\nOut = image gauss.
TP_RETINEX_TLABEL;TM Datas Min=%1 Max=%2 Mean=%3 Sigma=%4
TP_RETINEX_TLABEL2;TM Effective Tm=%1 TM=%2
-TP_RETINEX_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Variance.\nTm=Min TM=Max of Transmission Map.
+TP_RETINEX_TLABEL_TOOLTIP;ransmission map result.\nMin and Max are used by Variance.\nTm=Min TM=Max of Transmission Map.\nYou can normalize the results with the threshold slider.
TP_RETINEX_TRANF;Transmission
TP_RETINEX_TRANSMISSION;Transmission map
TP_RETINEX_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscissa: transmission from negative values (min), mean, and positives values (max).\nOrdinate: amplification or reduction.
@@ -3224,7 +3344,7 @@ TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE3;Red/Yellow
TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE4;Yellow
TP_VIBRANCE_CURVEEDITOR_SKINTONES_TOOLTIP;Hue according to hue H=f(H)
TP_VIBRANCE_LABEL;Vibrance
-TP_VIBRANCE_PASTELS;Pastel Tones
+TP_VIBRANCE_PASTELS;Pastel tones
TP_VIBRANCE_PASTSATTOG;Link pastel and saturated tones
TP_VIBRANCE_PROTECTSKINS;Protect skin-tones
TP_VIBRANCE_PSTHRESHOLD;Pastel/saturated tones threshold
@@ -3258,9 +3378,10 @@ 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_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;Chroma 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_BALCHROM;Denoise equalizer Blue-Yellow/Red-Green
+TP_WAVELET_BALLUM;Denoise equalizer White-Black
TP_WAVELET_BANONE;None
TP_WAVELET_BASLI;Slider
TP_WAVELET_BATYPE;Contrast balance method
@@ -3323,6 +3444,33 @@ 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 first levels. However the quality is not strictly related to this coefficient and can vary depending on image and use.
+TP_WAVELET_DENOISE;Guide curve based on Local contrast
+TP_WAVELET_DENOISEGUID;Guided threshold based on hue
+TP_WAVELET_DENOISEH;High levels Curve Local contrast
+TP_WAVELET_DENOISEHUE;Denoise equalizer Hue
+TP_WAVELET_DENCONTRAST;Local contrast Equalizer
+TP_WAVELET_DENEQUAL;1 2 3 4 Equal
+TP_WAVELET_DEN14PLUS;1 4 High
+TP_WAVELET_DEN14LOW;1 4 Low
+TP_WAVELET_DEN12PLUS;1 2 High
+TP_WAVELET_DEN12LOW;1 2 Low
+TP_WAVELET_DEN5THR;Guided threshold
+//TP_WAVELET_DENH;Low levels (1234)- Finest details
+//TP_WAVELET_DENLH;Guided threshold by detail levels 1-4
+//TP_WAVELET_DENL;High levels - Coarsest details
+TP_WAVELET_DENH;Threshold
+TP_WAVELET_DENLH;Guided threshold by detail levels 1-4
+TP_WAVELET_DENL;Correction structure
+TP_WAVELET_DENLOCAL_TOOLTIP;Use a curve in order to guide the denoising according to the local contrast.\nThe areas are denoised, the structures are maintained
+TP_WAVELET_DENMIX_TOOLTIP;Balances the action of the guide taking into account the original image and the denoised image
+TP_WAVELET_DENQUA;Mode
+TP_WAVELET_DENSLILAB;Method
+TP_WAVELET_DENSLI;Slider
+TP_WAVELET_DENCURV;Curve
+TP_WAVELET_DENSIGMA_TOOLTIP;Adapts the shape of the guide
+TP_WAVELET_DENWAVHUE_TOOLTIP;Amplify or reduce denoising depending on the color
+TP_WAVELET_DENWAVGUID_TOOLTIP;Uses hue to reduce or increase the action of the guided filter
+TP_WAVELET_DETEND;Details
TP_WAVELET_DIRFRAME;Directional contrast
TP_WAVELET_DONE;Vertical
TP_WAVELET_DTHR;Diagonal
@@ -3332,7 +3480,7 @@ 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+std. dev. and maxima.
-TP_WAVELET_EDGE;Edge Sharpness
+TP_WAVELET_EDGE;Edge sharpness
TP_WAVELET_EDGEAMPLI;Base amplification
TP_WAVELET_EDGEDETECT;Gradient sensitivity
TP_WAVELET_EDGEDETECTTHR;Threshold low (noise)
@@ -3352,6 +3500,8 @@ TP_WAVELET_FINAL;Final Touchup
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_FINTHR_TOOLTIP;Uses local contrast to reduce or increase the action of the guided filter
+TP_WAVELET_GUIDFRAME;Final smoothing (guided filter)
TP_WAVELET_HIGHLIGHT;Finer levels luminance range
TP_WAVELET_HS1;Whole luminance range
TP_WAVELET_HS2;Selective luminance range
@@ -3361,21 +3511,27 @@ 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.
-TP_WAVELET_LABEL;Wavelet Levels
+TP_WAVELET_LABEL;Wavelet levels
TP_WAVELET_LARGEST;Coarsest
TP_WAVELET_LEVCH;Chroma
+TP_WAVELET_LEVDEN;Level 5-6 denoise
TP_WAVELET_LEVDIR_ALL;All levels, in all directions
TP_WAVELET_LEVDIR_INF;Finer detail levels, including selected level
TP_WAVELET_LEVDIR_ONE;One level
TP_WAVELET_LEVDIR_SUP;Coarser detail levels, excluding selected level
TP_WAVELET_LEVELS;Wavelet levels
+TP_WAVELET_LEVELLOW;Radius 1-4
+TP_WAVELET_LEVELHIGH;Radius 5-6
+TP_WAVELET_LEVELSIGM;Radius
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_LEVFOUR;Level 5-6 denoise and guided threshold
TP_WAVELET_LEVONE;Level 2
TP_WAVELET_LEVTHRE;Level 4
TP_WAVELET_LEVTWO;Level 3
TP_WAVELET_LEVZERO;Level 1
+TP_WAVELET_LIMDEN;Interaction levels 56 on levels 14
TP_WAVELET_LINKEDG;Link to Edge Sharpness Strength
TP_WAVELET_LIPST;Enhanced algoritm
TP_WAVELET_LOWLIGHT;Coarser levels luminance range
@@ -3385,11 +3541,16 @@ 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_MERGEL;Merge Luma
+TP_WAVELET_MERGEL;Merge luma
TP_WAVELET_NEUTRAL;Neutral
+TP_WAVELET_MIXCONTRAST;Reference local contrast
+TP_WAVELET_MIXDENOISE;Denoise
+TP_WAVELET_MIXNOISE;Noise
+TP_WAVELET_MIXMIX;Mixed 50% noise - 50% denoise
+TP_WAVELET_MIXMIX70;Mixed 30% noise - 70% denoise
TP_WAVELET_NOIS;Denoise
TP_WAVELET_NOISE;Denoise and Refine
-TP_WAVELET_NOISE_TOOLTIP;If level 4 luminance denoise superior to 20, mode Agressive is used.\nIf chrominance coarse superior to 20, mode Agressive is used.
+TP_WAVELET_NOISE_TOOLTIP;If level 4 luminance denoise superior to 50, mode Agressive is used.\nIf chrominance coarse superior to 20, mode Agressive is used.
TP_WAVELET_NPHIGH;High
TP_WAVELET_NPLOW;Low
TP_WAVELET_NPNONE;None
@@ -3404,6 +3565,8 @@ TP_WAVELET_OPACITYWL_TOOLTIP;Modify the final local contrast at the end of the w
TP_WAVELET_PASTEL;Pastel chroma
TP_WAVELET_PROC;Process
TP_WAVELET_PROTAB;Protection
+TP_WAVELET_QUAAGRES;Agressive
+TP_WAVELET_QUACONSER;Conservative
TP_WAVELET_RADIUS;Radius shadows - highlight
TP_WAVELET_RANGEAB;Range a and b %
TP_WAVELET_RE1;Reinforced
@@ -3422,6 +3585,7 @@ TP_WAVELET_SHA;Sharp mask
TP_WAVELET_SHFRAME;Shadows/Highlights
TP_WAVELET_SHOWMASK;Show wavelet 'mask'
TP_WAVELET_SIGMA;Attenuation response
+TP_WAVELET_SIGM;Radius
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
@@ -3430,9 +3594,13 @@ 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_STREND;Strength
TP_WAVELET_STRENGTH;Strength
TP_WAVELET_SUPE;Extra
TP_WAVELET_THR;Shadows threshold
+TP_WAVELET_THREND;Local contrast threshold
+TP_WAVELET_THRDEN_TOOLTIP;Generates a stepped curve in order to guide the denoising according to the local contrast.\nThe areas are denoised, the structures are maintained
+TP_WAVELET_THRDEN_TOOLTIP;Generates a stepped denoise curve based on local contrast.\nReduces noise in uniform areas and preserves image structure
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.
diff --git a/rtdata/themes/RawTherapee-GTK3-20_.css b/rtdata/themes/RawTherapee-GTK3-20_.css
index 76f0004ee..f4f9ddb7f 100644
--- a/rtdata/themes/RawTherapee-GTK3-20_.css
+++ b/rtdata/themes/RawTherapee-GTK3-20_.css
@@ -720,6 +720,36 @@ flowboxchild:selected {
margin: 0;
}
+/* Vertical version of slider. */
+#histScale {
+ min-height: 4em;
+ min-width: 0.4166666666666666em;
+ margin: 0.5833333333333333em 0 0 0;
+}
+#histScale trough {
+ padding: 0.583333333333333333em 0;
+}
+#histScale trough highlight {
+ margin: -0.583333333333333333em 0;
+ padding: 0.1em 0 0 0.1em;
+}
+#histScale.fine-tune trough highlight {
+ padding: 0.5em 0 0 0.5em;
+}
+
+/* Copied from button.flat style. */
+button.radio#histButton {
+ background-image: none;
+}
+
+button.radio#histButton:checked {
+ background-image: linear-gradient(#343434, #2E2E2E, #292929);
+}
+
+button.radio#histButton:hover {
+ background-image: linear-gradient(shade(#343434,1.3), shade(#2E2E2E,1.3), shade(#292929,1.3));
+}
+
/*** end ***************************************************************************************/
#MyExpander {
diff --git a/rtdata/themes/TooWaBlue-GTK3-20_.css b/rtdata/themes/TooWaBlue-GTK3-20_.css
index ce4bb8d28..c4300413e 100644
--- a/rtdata/themes/TooWaBlue-GTK3-20_.css
+++ b/rtdata/themes/TooWaBlue-GTK3-20_.css
@@ -454,6 +454,47 @@ filechooser placessidebar list row:selected {
margin: 0;
}
+/* Vertical version of slider. */
+#histScale {
+ min-height: 4em;
+ min-width: 1.833333333333333333em;
+ margin: -0.333333333333333333em 0;
+}
+#histScale trough {
+ padding: 0.583333333333333333em 0;
+}
+#histScale highlight {
+ background-image: linear-gradient(to right, shade (@accent-color2,1.22), shade(@accent-color2,.88));
+ margin: -0.583333333333333333em 0;
+ padding: 0.333333333333333333em 0 0 0.333333333333333333em;
+}
+#histScale slider {
+}
+#histScale.fine-tune highlight {
+ padding: 0.5em 0 0 0.5em;
+}
+
+/* Copied from button.flat style. */
+button.radio#histButton {
+ border: 0.083333333333333333em solid transparent;
+ box-shadow: none;
+ background-image: none;
+ background-color: transparent;
+}
+button.radio#histButton:hover {
+ border-color: @bg-button-border;
+ box-shadow: inset 0 0.083333333333333333em rgba(242, 242, 242, 0.1);
+ background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3));
+ background-color: @bg-button-hover;
+}
+button.radio#histButton:active,
+button.radio#histButton:checked {
+ border-color: @bg-button-border;
+ box-shadow: inset 0 0.1em rgba(242, 242, 242, 0.08);
+ background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3));
+ background-color: @bg-button-active;
+}
+
/*** end ***************************************************************************************/
/*** Separator *********************************************************************************/
diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index d3634f3d0..543cd4841 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -63,6 +63,7 @@ set(RTENGINESOURCEFILES
ahd_demosaic_RT.cc
amaze_demosaic_RT.cc
badpixels.cc
+ bayer_bilinear_demosaic.cc
boxblur.cc
canon_cr3_decoder.cc
CA_correct_RT.cc
diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc
index a2929acbb..66f12b668 100644
--- a/rtengine/FTblockDN.cc
+++ b/rtengine/FTblockDN.cc
@@ -2099,12 +2099,12 @@ float ImProcFunctions::Mad(const float * DataList, const int datalen)
}
//computes Median Absolute Deviation
- //DataList values should mostly have abs val < 256 because we are in Lab mode
- int histo[256] ALIGNED64 = {0};
+ //DataList values should mostly have abs val < 256 because we are in Lab mode (32768)
+ int histo[32768] ALIGNED64 = {0};
//calculate histogram of absolute values of wavelet coeffs
for (int i = 0; i < datalen; ++i) {
- histo[static_cast(rtengine::min(255.f, fabsf(DataList[i])))]++;
+ histo[static_cast(rtengine::min(32768.f, fabsf(DataList[i])))]++;
}
//find median of histogram
@@ -2196,6 +2196,10 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition& Wavelet
maxlvl = 4; //for refine denoise edge wavelet
}
+ if (edge == 6) {
+ maxlvl = 6; //for wavelet denoise
+ }
+
if (edge == 2) {
maxlvl = 7; //for locallab denoise
}
@@ -2264,7 +2268,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition& Wavelet
for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
nvl[i] = 0.f;
}
- if ((edge == 1 || edge == 2 || edge == 3 || edge == 5) && vari) {
+ if ((edge == 1 || edge == 2 || edge == 3 || edge == 5 || edge == 6) && vari) {
// nvl = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer
if ((edge == 1 || edge == 3)) {
for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
@@ -2272,7 +2276,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition& Wavelet
}
}
- if (edge == 2 || edge == 4 || edge == 5) {
+ if (edge == 2 || edge == 4 || edge == 5 || edge == 6) {
for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) {
nvl[i] = vari[lvl] * SQR(noisevarlum[i]);
}
@@ -2373,6 +2377,12 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition& Wavelet
bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition& WaveletCoeffs_L, wavelet_decomposition& WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels)
{
int maxlvl = WaveletCoeffs_L.maxlevel();
+ printf("Ftblockdn ab bishrink\n");
+
+ if (local == 1) {
+ maxlvl = 6; //for local denoise
+ }
+
if (local == 2) {
maxlvl = 7; //for local denoise
@@ -2449,6 +2459,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition& Wavele
float* const* WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl);
if (lvl == maxlvl - 1) {
+ //printf("Shrink ab bis\n");
ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], nullptr, 0, madab[lvl], true);
} else {
//simple wavelet shrinkage
@@ -2550,6 +2561,10 @@ bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition& WaveletCoeffs_L,
maxlvl = 4; //for refine denoise edge wavelet
}
+ if (edge == 6) {
+ maxlvl = 6; //for wavelet denoise
+ }
+
if (edge == 2) {
maxlvl = 7; //for locallab denoise
}
@@ -2565,7 +2580,6 @@ bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition& WaveletCoeffs_L,
maxHL = WaveletCoeffs_L.level_H(lvl);
}
}
-
bool memoryAllocationFailed = false;
#ifdef _OPENMP
#pragma omp parallel num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1)
@@ -2605,9 +2619,13 @@ bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition& WaveletCoeffs_L
float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels)//mod JD
{
-
int maxlvl = WaveletCoeffs_L.maxlevel();
+ if (local == 1) {
+ maxlvl = 6; //for local denoise
+ }
+
+
if (local == 2) {
maxlvl = 7; //for local denoise
}
@@ -2690,15 +2708,15 @@ void ImProcFunctions::ShrinkAllL(wavelet_decomposition& WaveletCoeffs_L, float *
nvl[i] = 0.f;
}
- if ((edge == 1 || edge == 2 || edge == 3 || edge == 5) && vari) {
+ if ((edge == 1 || edge == 2 || edge == 3 || edge == 5 || edge == 6) && vari) {
// nvl = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer
if ((edge == 1 || edge == 3)) {
for (int i = 0; i < W_L * H_L; ++i) {
nvl[i] = vari[level]; //* SQR(1.f + 4.f * noisevarchrom[p]);
}
- }
+ }
- if (edge == 2 || edge == 4 || edge == 5) {
+ if (edge == 2 || edge == 4 || edge == 5 || edge == 6) {
for (int i = 0; i < W_L * H_L; ++i) {
nvl[i] = vari[level] * SQR(noisevarlum[i]);
}
diff --git a/rtengine/array2D.h b/rtengine/array2D.h
index 512f7bcc1..ca4db3d06 100644
--- a/rtengine/array2D.h
+++ b/rtengine/array2D.h
@@ -64,8 +64,7 @@ constexpr unsigned int ARRAY2D_BYREFERENCE = 2;
template
-class array2D :
- public rtengine::NonCopyable
+class array2D
{
private:
@@ -125,6 +124,25 @@ public:
}
}
+ array2D(const array2D& other) :
+ width(other.width),
+ buffer(other.buffer)
+ {
+ initRows(other.rows.size());
+ }
+
+ array2D& operator =(const array2D& other)
+ {
+ if (this != &other) {
+ free();
+ width = other.width;
+ buffer = other.buffer;
+ initRows(other.rows.size());
+ }
+
+ return *this;
+ }
+
void fill(const T val, bool multiThread = false)
{
const ssize_t height = rows.size();
@@ -140,6 +158,7 @@ public:
{
buffer.clear();
rows.clear();
+ width = 0;
}
// use with indices
@@ -192,6 +211,24 @@ public:
}
}
+ array2D& operator+=(const array2D& rhs)
+ {
+ if (rhs.getWidth() == this->getWidth() && rhs.getHeight() == this->getHeight()) {
+ for (int i = 0; i < getHeight(); ++i) {
+#ifdef _OPENMP
+ #pragma omp simd
+#endif
+
+ for (int j = 0; j < getWidth(); ++j) {
+ rows[i][j] += rhs[i][j];
+ }
+ }
+ }
+
+ return *this;
+ }
+
+
int getWidth() const
{
return width;
diff --git a/rtengine/ashift_dt.c b/rtengine/ashift_dt.c
index 3894a1c1b..ce19b6808 100644
--- a/rtengine/ashift_dt.c
+++ b/rtengine/ashift_dt.c
@@ -2111,7 +2111,7 @@ static double model_fitness(double *params, void *data)
}
// setup all data structures for fitting and call NM simplex
-static dt_iop_ashift_nmsresult_t nmsfit(dt_iop_module_t *module, dt_iop_ashift_params_t *p, dt_iop_ashift_fitaxis_t dir)
+static dt_iop_ashift_nmsresult_t nmsfit(dt_iop_module_t *module, dt_iop_ashift_params_t *p, dt_iop_ashift_fitaxis_t dir, int min_line_count)
{
dt_iop_ashift_gui_data_t *g = (dt_iop_ashift_gui_data_t *)module->gui_data;
@@ -2227,7 +2227,7 @@ static dt_iop_ashift_nmsresult_t nmsfit(dt_iop_module_t *module, dt_iop_ashift_p
// we use vertical lines for fitting
fit.linetype |= ASHIFT_LINE_DIRVERT;
fit.weight += g->vertical_weight;
- enough_lines = enough_lines && (g->vertical_count >= MINIMUM_FITLINES);
+ enough_lines = enough_lines && (g->vertical_count >= min_line_count);
}
if(mdir & ASHIFT_FIT_LINES_HOR)
@@ -2235,7 +2235,7 @@ static dt_iop_ashift_nmsresult_t nmsfit(dt_iop_module_t *module, dt_iop_ashift_p
// we use horizontal lines for fitting
fit.linetype |= 0;
fit.weight += g->horizontal_weight;
- enough_lines = enough_lines && (g->horizontal_count >= MINIMUM_FITLINES);
+ enough_lines = enough_lines && (g->horizontal_count >= min_line_count);
}
// this needs to come after ASHIFT_FIT_LINES_VERT and ASHIFT_FIT_LINES_HOR
@@ -2905,7 +2905,7 @@ static int do_clean_structure(dt_iop_module_t *module, dt_iop_ashift_params_t *p
//-----------------------------------------------------------------------------
// helper function to start parameter fit and report about errors
-static int do_fit(dt_iop_module_t *module, dt_iop_ashift_params_t *p, dt_iop_ashift_fitaxis_t dir)
+static int do_fit(dt_iop_module_t *module, dt_iop_ashift_params_t *p, dt_iop_ashift_fitaxis_t dir, int min_line_count = MINIMUM_FITLINES)
{
dt_iop_ashift_gui_data_t *g = (dt_iop_ashift_gui_data_t *)module->gui_data;
dt_iop_ashift_nmsresult_t res;
@@ -2918,7 +2918,7 @@ static int do_fit(dt_iop_module_t *module, dt_iop_ashift_params_t *p, dt_iop_ash
g->fitting = 1;
- res = nmsfit(module, p, dir);
+ res = nmsfit(module, p, dir, min_line_count);
switch(res)
{
@@ -3815,8 +3815,10 @@ void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, i
cairo_restore(cr);
}
+#endif // if 0
+//-----------------------------------------------------------------------------
-update the number of selected vertical and horizontal lines
+// update the number of selected vertical and horizontal lines
static void update_lines_count(const dt_iop_ashift_line_t *lines, const int lines_count,
int *vertical_count, int *horizontal_count)
{
@@ -3835,6 +3837,9 @@ static void update_lines_count(const dt_iop_ashift_line_t *lines, const int line
*horizontal_count = hlines;
}
+//-----------------------------------------------------------------------------
+// RT: BEGIN COMMENT
+#if 0
int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
{
dt_iop_ashift_gui_data_t *g = (dt_iop_ashift_gui_data_t *)self->gui_data;
diff --git a/rtengine/bayer_bilinear_demosaic.cc b/rtengine/bayer_bilinear_demosaic.cc
new file mode 100644
index 000000000..5b3835ce9
--- /dev/null
+++ b/rtengine/bayer_bilinear_demosaic.cc
@@ -0,0 +1,56 @@
+////////////////////////////////////////////////////////////////
+//
+// Bilinear bayer demosaic, optimized for speed, intended use is for flat regions of dual-demosaic
+//
+// copyright (c) 2020 Ingo Weyrich
+//
+//
+// code dated: May 09, 2020
+//
+// bayer_bilinear_demosaic.cc is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+////////////////////////////////////////////////////////////////
+
+#include "rawimagesource.h"
+#include "rt_math.h"
+
+using namespace rtengine;
+
+void RawImageSource::bayer_bilinear_demosaic(const float* const * blend, const array2D &rawData, array2D &red, array2D &green, array2D &blue)
+{
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+ for (int i = 1; i < H - 1; ++i) {
+ float **nonGreen1 = red;
+ float **nonGreen2 = blue;
+ if (FC(i, 0) == 2 || FC(i, 1) == 2) { // blue row => swap pointers
+ std::swap(nonGreen1, nonGreen2);
+ }
+#if defined(__clang__)
+ #pragma clang loop vectorize(assume_safety)
+#elif defined(__GNUC__)
+ #pragma GCC ivdep
+#endif
+ for (int j = 2 - (FC(i, 1) & 1); j < W - 2; j += 2) { // always begin with a green pixel
+ green[i][j] = intp(blend[i][j], green[i][j], rawData[i][j]);
+ nonGreen1[i][j] = intp(blend[i][j], nonGreen1[i][j], (rawData[i][j - 1] + rawData[i][j + 1]) * 0.5f);
+ nonGreen2[i][j] = intp(blend[i][j], nonGreen2[i][j], (rawData[i - 1][j] + rawData[i + 1][j]) * 0.5f);
+ green[i][j + 1] = intp(blend[i][j + 1], green[i][j + 1], ((rawData[i - 1][j + 1] + rawData[i][j]) + (rawData[i][j + 2] + rawData[i + 1][j + 1])) * 0.25f);
+ nonGreen1[i][j + 1] = intp(blend[i][j + 1], nonGreen1[i][j + 1], rawData[i][j + 1]);
+ nonGreen2[i][j + 1] = intp(blend[i][j + 1], nonGreen2[i][j + 1], ((rawData[i - 1][j] + rawData[i - 1][j + 2]) + (rawData[i + 1][j] + rawData[i + 1][j + 2])) * 0.25f);
+ }
+ }
+}
diff --git a/rtengine/camconst.json b/rtengine/camconst.json
index 578ff1811..22270bfe2 100644
--- a/rtengine/camconst.json
+++ b/rtengine/camconst.json
@@ -1144,11 +1144,30 @@ Camera constants:
"raw_crop": [ 144, 72, 6984, 4660 ]
},
- { // Quality C, only raw crop
+ { // Quality B, samples by jonathanBieler (#5922). No dual-pixel information.
"make_model": [ "Canon EOS R" ],
- "raw_crop": [ 144, 46, 6744, 4500 ]
+ "dcraw_matrix" : [ 8293, -1789, -1094, -5025, 12925, 2327, -1199, 2769, 6108 ], // DNG v2 style
+ "raw_crop": [ 144, 46, 6744, 4500 ],
+ "masked_areas": [ 50, 40, 4540, 140 ], // Taken from ART
+ "ranges" : { "white" : 16367 } // Typically 16383 without LENR, with LENR safest value is 15800 for ISO 25600
},
+ { // Quality C
+ "make_model": "Canon EOS R5",
+ "dcraw_matrix" : [9766, -2953, -1254, -4276, 12116, 2433, -437, 1336, 5131],
+ "raw_crop" : [ 124, 92, 8220, 5486 ],
+ "masked_areas" : [ 94, 20, 5578, 122 ],
+ "ranges" : { "white" : 16382 }
+ },
+
+ { // Quality C
+ "make_model": "Canon EOS R6",
+ "dcraw_matrix" : [8293, -1611, -1132, -4759, 12710, 2275, -1013, 2415, 5508],
+ "raw_crop": [ 72, 38, 5496, 3670 ],
+ "masked_areas" : [ 40, 10, 5534, 70 ],
+ "ranges" : { "white" : 16382 }
+ },
+
// Canon Powershot
{ // Quality C, CHDK DNGs, raw frame correction
"make_model": "Canon PowerShot A3100 IS",
@@ -1260,15 +1279,18 @@ Camera constants:
{ // Quality C
"make_model": [ "DJI FC2103" ],
- "ranges": {
- "black": 4080
- }
+ "ranges": { "black": 4080 }
},
{ // Quality C
"make_model": "DJI FC6310",
"ranges": { "white": 64886 }
},
+
+ { // Quality C
+ "make_model": "DJI FC3170",
+ "ranges": { "white": 65472 }
+ },
{ // Quality C
"make_model": "FUJIFILM GFX 100",
@@ -1729,6 +1751,11 @@ Camera constants:
"pdaf_offset" : 32
},
+ { // Quality C, only dcraw looted from ART commit ad88c7d97
+ "make_model" : "NIKON Z 5",
+ "dcraw_matrix" : [8695, -2558, -648, -5015, 12711, 2575, -1279, 2215, 7514]
+ },
+
{ // 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)
diff --git a/rtengine/canon_cr3_decoder.cc b/rtengine/canon_cr3_decoder.cc
index f9850189c..e3097ad2e 100644
--- a/rtengine/canon_cr3_decoder.cc
+++ b/rtengine/canon_cr3_decoder.cc
@@ -602,7 +602,9 @@ int DCraw::parseCR3(
relpos_inBox += lTag;
}
}
-
+ if (!szItem) {
+ goto fin;
+ }
relpos_inDir += szItem;
}
@@ -3130,7 +3132,8 @@ void DCraw::crxLoadRaw()
hdr.tileHeight >>= 1;
}
-// /*imgdata.color.*/maximum = (1 << hdr.nBits) - 1;
+ // /*imgdata.color.*/maximum = (1 << hdr.nBits) - 1;
+ tiff_bps = hdr.nBits;
std::uint8_t* const hdrBuf = static_cast(malloc(hdr.mdatHdrSize));
diff --git a/rtengine/capturesharpening.cc b/rtengine/capturesharpening.cc
index 4dcdd0734..83c44aa18 100644
--- a/rtengine/capturesharpening.cc
+++ b/rtengine/capturesharpening.cc
@@ -127,12 +127,8 @@ void compute3x3kernel(float sigma, float kernel[3][3]) {
float sum = 0.f;
for (int i = -1; i <= 1; ++i) {
for (int j = -1; j <= 1; ++j) {
- if((rtengine::SQR(i) + rtengine::SQR(j)) <= rtengine::SQR(3.0 * 0.84)) {
- kernel[i + 1][j + 1] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp);
- sum += kernel[i + 1][j + 1];
- } else {
- kernel[i + 1][j + 1] = 0.f;
- }
+ kernel[i + 1][j + 1] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp);
+ sum += kernel[i + 1][j + 1];
}
}
@@ -647,7 +643,7 @@ float calcRadiusBayer(const float * const *rawData, int W, int H, float lowerLim
}
}
}
- return std::sqrt((1.f / (std::log(1.f / maxRatio) / 2.f)) / -2.f);
+ return std::sqrt(1.f / std::log(maxRatio));
}
float calcRadiusXtrans(const float * const *rawData, int W, int H, float lowerLimit, float upperLimit, unsigned int starty, unsigned int startx)
@@ -738,7 +734,7 @@ float calcRadiusXtrans(const float * const *rawData, int W, int H, float lowerLi
}
}
}
- return std::sqrt((1.f / (std::log(1.f / maxRatio) / 2.f)) / -2.f);
+ return std::sqrt(1.f / std::log(maxRatio));
}
bool checkForStop(float** tmpIThr, float** iterCheck, int fullTileSize, int border)
@@ -1116,23 +1112,23 @@ BENCHFUN
return;
}
- array2D* Lbuffer = nullptr;
+ std::unique_ptr> Lbuffer;
if (!redCache) {
- Lbuffer = new array2D(W, H);
+ Lbuffer.reset(new array2D(W, H));
}
- array2D* YOldbuffer = nullptr;
+ std::unique_ptr> YOldbuffer;
if (!greenCache) {
- YOldbuffer = new array2D(W, H);
+ YOldbuffer.reset(new array2D(W, H));
}
- array2D* YNewbuffer = nullptr;
+ std::unique_ptr> YNewbuffer;
if (!blueCache) {
- YNewbuffer = new array2D(W, H);
+ YNewbuffer.reset(new array2D(W, H));
}
- array2D& L = Lbuffer ? *Lbuffer : red;
- array2D& YOld = YOldbuffer ? * YOldbuffer : green;
- array2D& YNew = YNewbuffer ? * YNewbuffer : blue;
+ array2D& L = Lbuffer.get() ? *Lbuffer.get() : red;
+ array2D& YOld = YOldbuffer.get() ? *YOldbuffer.get() : green;
+ array2D& YNew = YNewbuffer.get() ? *YNewbuffer.get() : blue;
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16)
@@ -1160,17 +1156,12 @@ BENCHFUN
#pragma omp parallel for schedule(dynamic, 16)
#endif
for (int i = 0; i < H; ++i) {
- int j = 0;
-#ifdef __SSE2__
- for (; j < W - 3; j += 4) {
- const vfloat factor = LVFU(YNew[i][j]) / vmaxf(LVFU(YOld[i][j]), F2V(0.00001f));
- STVFU(red[i][j], LVFU(redVals[i][j]) * factor);
- STVFU(green[i][j], LVFU(greenVals[i][j]) * factor);
- STVFU(blue[i][j], LVFU(blueVals[i][j]) * factor);
- }
-
+#if defined(__clang__)
+ #pragma clang loop vectorize(assume_safety)
+#elif defined(__GNUC__)
+ #pragma GCC ivdep
#endif
- for (; j < W; ++j) {
+ for (int j = 0; j < W; ++j) {
const float factor = YNew[i][j] / std::max(YOld[i][j], 0.00001f);
red[i][j] = redVals[i][j] * factor;
green[i][j] = greenVals[i][j] * factor;
@@ -1178,9 +1169,6 @@ BENCHFUN
}
}
- delete Lbuffer;
- delete YOldbuffer;
- delete YNewbuffer;
if (plistener) {
plistener->setProgress(1.0);
}
diff --git a/rtengine/color.cc b/rtengine/color.cc
index 5761733f0..11a94d1dc 100644
--- a/rtengine/color.cc
+++ b/rtengine/color.cc
@@ -1015,23 +1015,6 @@ void Color::xyz2r (float x, float y, float z, float &r, const double rgb_xyz[3][
r = ((rgb_xyz[0][0] * x + rgb_xyz[0][1] * y + rgb_xyz[0][2] * z)) ;
}
-// same for float
-void Color::xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const float rgb_xyz[3][3])
-{
- r = ((rgb_xyz[0][0] * x + rgb_xyz[0][1] * y + rgb_xyz[0][2] * z)) ;
- g = ((rgb_xyz[1][0] * x + rgb_xyz[1][1] * y + rgb_xyz[1][2] * z)) ;
- b = ((rgb_xyz[2][0] * x + rgb_xyz[2][1] * y + rgb_xyz[2][2] * z)) ;
-}
-
-#ifdef __SSE2__
-void Color::xyz2rgb (vfloat x, vfloat y, vfloat z, vfloat &r, vfloat &g, vfloat &b, const vfloat rgb_xyz[3][3])
-{
- r = ((rgb_xyz[0][0] * x + rgb_xyz[0][1] * y + rgb_xyz[0][2] * z)) ;
- g = ((rgb_xyz[1][0] * x + rgb_xyz[1][1] * y + rgb_xyz[1][2] * z)) ;
- b = ((rgb_xyz[2][0] * x + rgb_xyz[2][1] * y + rgb_xyz[2][2] * z)) ;
-}
-#endif // __SSE2__
-
#ifdef __SSE2__
void Color::trcGammaBW (float &r, float &g, float &b, float gammabwr, float gammabwg, float gammabwb)
{
@@ -1570,6 +1553,9 @@ void Color::calcGamma (double pwr, double ts, GammaValues &gamma)
gamma[4] = g[4];
gamma[5] = g[5];
gamma[6] = 0.;
+ // if (rtengine::settings->verbose) {
+ // printf("g0=%f g1=%f g2=%f g3=%f g4=%f g5=%f\n", g[0], g[1], g[2], g[3], g[4], g[5]);
+ // }
}
void Color::gammaf2lut (LUTf &gammacurve, float gamma, float start, float slope, float divisor, float factor)
{
@@ -1646,19 +1632,6 @@ void Color::gammanf2lut (LUTf &gammacurve, float gamma, float divisor, float fac
#endif
}
-void Color::Lab2XYZ(float L, float a, float b, float &x, float &y, float &z)
-{
- float LL = L / 327.68f;
- float aa = a / 327.68f;
- float bb = b / 327.68f;
- float fy = (c1By116 * LL) + c16By116; // (L+16)/116
- float fx = (0.002f * aa) + fy;
- float fz = fy - (0.005f * bb);
- x = 65535.0f * f2xyz(fx) * D50x;
- z = 65535.0f * f2xyz(fz) * D50z;
- y = (LL > epskap) ? 65535.0f * fy * fy * fy : 65535.0f * LL / kappa;
-}
-
float Color::L2Y(float L)
{
const float LL = L / 327.68f;
@@ -1676,27 +1649,6 @@ void Color::L2XYZ(float L, float &x, float &y, float &z) // for black & white
y = (LL > epskap) ? 65535.0f * fy * fy * fy : 65535.0f * LL / kappa;
}
-
-#ifdef __SSE2__
-void Color::Lab2XYZ(vfloat L, vfloat a, vfloat b, vfloat &x, vfloat &y, vfloat &z)
-{
- vfloat c327d68 = F2V(327.68f);
- L /= c327d68;
- a /= c327d68;
- b /= c327d68;
- vfloat fy = F2V(c1By116) * L + F2V(c16By116);
- vfloat fx = F2V(0.002f) * a + fy;
- vfloat fz = fy - (F2V(0.005f) * b);
- vfloat c65535 = F2V(65535.f);
- x = c65535 * f2xyz(fx) * F2V(D50x);
- z = c65535 * f2xyz(fz) * F2V(D50z);
- vfloat res1 = fy * fy * fy;
- vfloat res2 = L / F2V(kappa);
- y = vself(vmaskf_gt(L, F2V(epskap)), res1, res2);
- y *= c65535;
-}
-#endif // __SSE2__
-
inline float Color::computeXYZ2Lab(float f)
{
if (f < 0.f) {
diff --git a/rtengine/color.h b/rtengine/color.h
index 704871d39..b6bf60818 100644
--- a/rtengine/color.h
+++ b/rtengine/color.h
@@ -570,9 +570,20 @@ public:
*/
static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const double rgb_xyz[3][3]);
static void xyz2r (float x, float y, float z, float &r, const double rgb_xyz[3][3]);
- static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const float rgb_xyz[3][3]);
+ static inline void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const float rgb_xyz[3][3])
+ {
+ r = ((rgb_xyz[0][0] * x + rgb_xyz[0][1] * y + rgb_xyz[0][2] * z)) ;
+ g = ((rgb_xyz[1][0] * x + rgb_xyz[1][1] * y + rgb_xyz[1][2] * z)) ;
+ b = ((rgb_xyz[2][0] * x + rgb_xyz[2][1] * y + rgb_xyz[2][2] * z)) ;
+ }
+
#ifdef __SSE2__
- static void xyz2rgb (vfloat x, vfloat y, vfloat z, vfloat &r, vfloat &g, vfloat &b, const vfloat rgb_xyz[3][3]);
+ static inline void xyz2rgb (vfloat x, vfloat y, vfloat z, vfloat &r, vfloat &g, vfloat &b, const vfloat rgb_xyz[3][3])
+ {
+ r = ((rgb_xyz[0][0] * x + rgb_xyz[0][1] * y + rgb_xyz[0][2] * z)) ;
+ g = ((rgb_xyz[1][0] * x + rgb_xyz[1][1] * y + rgb_xyz[1][2] * z)) ;
+ b = ((rgb_xyz[2][0] * x + rgb_xyz[2][1] * y + rgb_xyz[2][2] * z)) ;
+ }
#endif
@@ -603,12 +614,40 @@ public:
* @param y Y coordinate [0 ; 65535] ; can be negative! (return value)
* @param z Z coordinate [0 ; 65535] ; can be negative! (return value)
*/
- static void Lab2XYZ(float L, float a, float b, float &x, float &y, float &z);
+ static inline void Lab2XYZ(float L, float a, float b, float &x, float &y, float &z)
+ {
+ float LL = L / 327.68f;
+ float aa = a / 327.68f;
+ float bb = b / 327.68f;
+ float fy = (c1By116 * LL) + c16By116; // (L+16)/116
+ float fx = (0.002f * aa) + fy;
+ float fz = fy - (0.005f * bb);
+ x = 65535.f * f2xyz(fx) * D50x;
+ z = 65535.f * f2xyz(fz) * D50z;
+ y = (LL > epskapf) ? 65535.f * fy * fy * fy : 65535.f * LL / kappaf;
+ }
+
static void L2XYZ(float L, float &x, float &y, float &z);
static float L2Y(float L);
#ifdef __SSE2__
- static void Lab2XYZ(vfloat L, vfloat a, vfloat b, vfloat &x, vfloat &y, vfloat &z);
+static inline void Lab2XYZ(vfloat L, vfloat a, vfloat b, vfloat &x, vfloat &y, vfloat &z)
+{
+ vfloat c327d68 = F2V(327.68f);
+ L /= c327d68;
+ a /= c327d68;
+ b /= c327d68;
+ vfloat fy = F2V(c1By116) * L + F2V(c16By116);
+ vfloat fx = F2V(0.002f) * a + fy;
+ vfloat fz = fy - (F2V(0.005f) * b);
+ vfloat c65535 = F2V(65535.f);
+ x = c65535 * f2xyz(fx) * F2V(D50x);
+ z = c65535 * f2xyz(fz) * F2V(D50z);
+ vfloat res1 = fy * fy * fy;
+ vfloat res2 = L / F2V(kappa);
+ y = vself(vmaskf_gt(L, F2V(epskap)), res1, res2);
+ y *= c65535;
+}
#endif // __SSE2__
/**
diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc
index a166ecf15..fd9f9211b 100644
--- a/rtengine/dcraw.cc
+++ b/rtengine/dcraw.cc
@@ -273,11 +273,7 @@ void CLASS derror()
if (feof(ifp))
fprintf (stderr,_("Unexpected end of file\n"));
else
-#ifdef WIN32
- fprintf (stderr,_("Corrupt data near 0x%I64x\n"), (INT64) ftello(ifp));
-#else
fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp));
-#endif
}
data_error++;
/*RT Issue 2467 longjmp (failure, 1);*/
@@ -1403,7 +1399,7 @@ void CLASS nikon_load_raw()
void CLASS nikon_yuv_load_raw()
{
- int row, col, yuv[4], rgb[3], b, c;
+ int row, col, yuv[4] = {}, rgb[3], b, c;
UINT64 bitbuf=0;
for (row=0; row < raw_height; row++)
@@ -2050,9 +2046,8 @@ void CLASS phase_one_load_raw_c()
} else if ((col & 7) == 0) {
for (int i = 0; i < 2; i++) {
int j;
- for (j = 0; j < 5 && !ph1_bits(1); j++)
- ;
- if (j--) {
+ for (j = 0; j < 5 && !ph1_bits(1); j++) ;
+ if (j--) {
len[i] = length[j * 2 + ph1_bits(1)];
}
}
@@ -4090,7 +4085,7 @@ void CLASS foveon_interpolate()
FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
#undef LAST
FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
- sprintf (str, "%sRGBNeutral", model2);
+ snprintf(str, sizeof(str), "%sRGBNeutral", model2);
if (foveon_camf_param ("IncludeBlocks", str))
foveon_fixed (div, 3, str);
num = 0;
@@ -5625,7 +5620,7 @@ nf: order = 0x4949;
if (tag == 2 && strstr(make,"NIKON") && !iso_speed)
iso_speed = (get2(),get2());
if ((tag == 0x25 || tag == 0x28) && strstr(make,"NIKON") && !iso_speed) { // Nikon ISOInfo Tags/ISO & ISO2
- uchar iso[1];
+ uchar iso[1] = {};
fread (iso, 1, 1, ifp);
iso_speed = 100 * pow(2,(float)iso[0]/12.0-5);
}
@@ -6207,8 +6202,8 @@ void CLASS parse_exif (int base)
case 36867:
case 36868: get_timestamp(0); break;
case 37377: if ((expo = -getreal(type)) < 128)
- tiff_ifd[tiff_nifds-1].shutter =
- shutter = pow (2, expo); break;
+ tiff_ifd[tiff_nifds-1].shutter = shutter = pow (2, expo);
+ break;
case 37378: aperture = pow (2, getreal(type)/2); break;
case 37386: focal_len = getreal(type); break;
case 37500: parse_makernote (base, 0); break;
@@ -6728,7 +6723,7 @@ int CLASS parse_tiff_ifd (int base)
raw_height = height;
left_margin = top_margin = filters = flip = 0;
}
- sprintf (model, "Ixpress %d-Mp", height*width/1000000);
+ snprintf(model, sizeof(model), "Ixpress %d-Mp", height*width/1000000);
load_raw = &CLASS imacon_full_load_raw;
if (filters) {
if (left_margin & 1) filters = 0x61616161;
@@ -7093,7 +7088,8 @@ void CLASS apply_tiff()
load_flags = 24;
if (!strcmp(make,"SONY") && tiff_bps < 14 &&
tiff_ifd[raw].bytes == raw_width*raw_height*2)
- tiff_bps = 14; if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) {
+ tiff_bps = 14;
+ if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) {
load_flags = 81;
tiff_bps = 12;
} slr:
@@ -7166,7 +7162,8 @@ void CLASS apply_tiff()
// load_raw = &CLASS packed_load_raw;
load_raw = &CLASS nikon_14bit_load_raw;
} else
- load_raw = &CLASS nikon_load_raw; break;
+ load_raw = &CLASS nikon_load_raw;
+ break;
case 65535:
load_raw = &CLASS pentax_load_raw; break;
case 65000:
@@ -7720,7 +7717,7 @@ void CLASS parse_smal (int offset, int fsize)
raw_height = height = get2();
raw_width = width = get2();
strcpy (make, "SMaL");
- sprintf (model, "v%d %dx%d", ver, width, height);
+ snprintf(model, sizeof(model), "v%d %dx%d", ver, width, height);
if (ver == 6) load_raw = &CLASS smal_v6_load_raw;
if (ver == 9) load_raw = &CLASS smal_v9_load_raw;
}
@@ -7748,7 +7745,7 @@ void CLASS parse_cine()
}
fseek (ifp, off_setup+792, SEEK_SET);
strcpy (make, "CINE");
- sprintf (model, "%d", get4());
+ snprintf(model, sizeof(model), "%d", get4());
fseek (ifp, 12, SEEK_CUR);
switch ((i=get4()) & 0xffffff) {
case 3: filters = 0x94949494; break;
@@ -9061,7 +9058,7 @@ void CLASS adobe_coeff (const char *make, const char *model)
char name[130];
int i, j;
- sprintf (name, "%s %s", make, model);
+ snprintf(name, sizeof(name), "%s %s", make, model);
// -- RT --------------------------------------------------------------------
@@ -10525,7 +10522,7 @@ bw: colors = 1;
load_raw = &CLASS rollei_load_raw;
}
if (!model[0])
- sprintf (model, "%dx%d", width, height);
+ snprintf(model, sizeof(model), "%dx%d", width, height);
if (filters == UINT_MAX) filters = 0x94949494;
if (thumb_offset && !thumb_height) {
fseek (ifp, thumb_offset, SEEK_SET);
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index c89d2bdb0..d5596c8ce 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -804,7 +804,7 @@ void Crop::update(int todo)
if (todo & M_RGBCURVE) {
Imagefloat *workingCrop = baseCrop;
-
+/*
if (params.icm.workingTRC == "Custom") { //exec TRC IN free
const Glib::ustring profile = params.icm.workingProfile;
@@ -818,7 +818,7 @@ void Crop::update(int todo)
parent->ipf.workingtrc(workingCrop, workingCrop, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, parent->getCustomTransformOut(), false, true, true);
}
}
-
+*/
double rrm, ggm, bbm;
DCPProfileApplyState as;
DCPProfile *dcpProf = parent->imgsrc->getDCP(params.icm, as);
@@ -1231,6 +1231,8 @@ void Crop::update(int todo)
}
WavCurve wavCLVCurve;
+ WavCurve wavdenoise;
+ WavCurve wavdenoiseh;
Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
WavOpacityCurveSH waOpacityCurveSH;
@@ -1240,7 +1242,7 @@ void Crop::update(int todo)
LUTf wavclCurve;
- params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves(wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
LabImage *unshar = nullptr;
Glib::ustring provis;
LabImage *provradius = nullptr;
@@ -1267,7 +1269,7 @@ void Crop::update(int todo)
provis = params.wavelet.CLmethod;
params.wavelet.CLmethod = "all";
- parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
+ parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
unshar = new LabImage(*labnCrop, true);
params.wavelet.CLmethod = provis;
@@ -1284,7 +1286,7 @@ void Crop::update(int todo)
// parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
- parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
+ parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
WaveParams.expcontrast = procont;
@@ -1406,6 +1408,7 @@ void Crop::update(int todo)
}
+
}
diff --git a/rtengine/dual_demosaic_RT.cc b/rtengine/dual_demosaic_RT.cc
index 253468a76..558d9095b 100644
--- a/rtengine/dual_demosaic_RT.cc
+++ b/rtengine/dual_demosaic_RT.cc
@@ -33,9 +33,6 @@
#include "../rtgui/options.h"
-//#define BENCHMARK
-#include "StopWatch.h"
-
using namespace std;
namespace rtengine
@@ -43,20 +40,22 @@ namespace rtengine
void RawImageSource::dual_demosaic_RT(bool isBayer, const procparams::RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast)
{
- BENCHFUN
if (contrast == 0.0 && !autoContrast) {
// contrast == 0.0 means only first demosaicer will be used
if(isBayer) {
- if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) ) {
+ if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEBILINEAR) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4)) {
amaze_demosaic_RT(0, 0, winw, winh, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure);
- } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4) ) {
+ } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBBILINEAR) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4)) {
dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance);
- } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDVNG4) ) {
+ } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDBILINEAR) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDVNG4)) {
rcd_demosaic(options.chunkSizeRCD, options.measure);
}
} else {
- if (raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FOUR_PASS) ) {
+ if (raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FOUR_PASS)) {
xtrans_interpolate (3, true, options.chunkSizeXT, options.measure);
} else {
xtrans_interpolate (1, false, options.chunkSizeXT, options.measure);
@@ -69,15 +68,19 @@ void RawImageSource::dual_demosaic_RT(bool isBayer, const procparams::RAWParams
array2D L(winw, winh);
if (isBayer) {
- if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) || raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT)) {
+ if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEBILINEAR) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT)) {
amaze_demosaic_RT(0, 0, winw, winh, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure);
- } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4) ) {
+ } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBBILINEAR) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4)) {
dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance);
- } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDVNG4) ) {
+ } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDBILINEAR) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDVNG4)) {
rcd_demosaic(options.chunkSizeRCD, options.measure);
}
} else {
- if (raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FOUR_PASS) ) {
+ if (raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FOUR_PASS)) {
xtrans_interpolate (3, true, options.chunkSizeXT, options.measure);
} else {
xtrans_interpolate (1, false, options.chunkSizeXT, options.measure);
@@ -91,59 +94,47 @@ void RawImageSource::dual_demosaic_RT(bool isBayer, const procparams::RAWParams
};
#ifdef _OPENMP
- #pragma omp parallel
+ #pragma omp parallel for schedule(dynamic,16)
#endif
- {
-#ifdef _OPENMP
- #pragma omp for
-#endif
- for(int i = 0; i < winh; ++i) {
- Color::RGB2L(red[i], green[i], blue[i], L[i], xyz_rgb, winw);
- }
+ for(int i = 0; i < winh; ++i) {
+ Color::RGB2L(red[i], green[i], blue[i], L[i], xyz_rgb, winw);
}
- // calculate contrast based blend factors to use vng4 in regions with low contrast
+
+ // calculate contrast based blend factors to use flat demosaicer in regions with low contrast
JaggedArray blend(winw, winh);
float contrastf = contrast / 100.0;
buildBlendMask(L, blend, winw, winh, contrastf, autoContrast);
contrast = contrastf * 100.f;
- array2D& redTmp = L; // L is not needed anymore => reuse it
- array2D greenTmp(winw, winh);
- array2D blueTmp(winw, winh);
-
if (isBayer) {
- vng4_demosaic(rawData, redTmp, greenTmp, blueTmp);
+ if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEBILINEAR) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDBILINEAR) ||
+ raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBBILINEAR)) {
+ bayer_bilinear_demosaic(blend, rawData, red, green, blue);
+ } else {
+ array2D& redTmp = L; // L is not needed anymore => reuse it
+ array2D greenTmp(winw, winh);
+ array2D blueTmp(winw, winh);
+ vng4_demosaic(rawData, redTmp, greenTmp, blueTmp);
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+ for(int i = 0; i < winh; ++i) {
+ // the following is split into 3 loops intentionally to avoid cache conflicts on CPUs with only 4-way cache
+ for(int j = 0; j < winw; ++j) {
+ red[i][j] = intp(blend[i][j], red[i][j], redTmp[i][j]);
+ }
+ for(int j = 0; j < winw; ++j) {
+ green[i][j] = intp(blend[i][j], green[i][j], greenTmp[i][j]);
+ }
+ for(int j = 0; j < winw; ++j) {
+ blue[i][j] = intp(blend[i][j], blue[i][j], blueTmp[i][j]);
+ }
+ }
+ }
} else {
- fast_xtrans_interpolate(rawData, redTmp, greenTmp, blueTmp);
+ fast_xtrans_interpolate_blend(blend, rawData, red, green, blue);
}
-
-
- // the following is split into 3 loops intentionally to avoid cache conflicts on CPUs with only 4-way cache
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
- for(int i = 0; i < winh; ++i) {
- for(int j = 0; j < winw; ++j) {
- red[i][j] = intp(blend[i][j], red[i][j], redTmp[i][j]);
- }
- }
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
- for(int i = 0; i < winh; ++i) {
- for(int j = 0; j < winw; ++j) {
- green[i][j] = intp(blend[i][j], green[i][j], greenTmp[i][j]);
- }
- }
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
- for(int i = 0; i < winh; ++i) {
- for(int j = 0; j < winw; ++j) {
- blue[i][j] = intp(blend[i][j], blue[i][j], blueTmp[i][j]);
- }
- }
-
}
}
diff --git a/rtengine/histmatching.cc b/rtengine/histmatching.cc
index 0053cb0d4..d3c5d0190 100644
--- a/rtengine/histmatching.cc
+++ b/rtengine/histmatching.cc
@@ -279,7 +279,7 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, st
{
RawMetaDataLocation rml;
eSensorType sensor_type;
- int w, h;
+ int w = 0, h = 0;
std::unique_ptr thumb(Thumbnail::loadQuickFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, true, true));
if (!thumb) {
if (settings->verbose) {
diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc
index f53ddc893..2f443522c 100644
--- a/rtengine/iccstore.cc
+++ b/rtengine/iccstore.cc
@@ -1151,102 +1151,6 @@ std::vector rtengine::ICCStore::getWorkingProfiles()
return implementation->getWorkingProfiles();
}
-// WARNING: the caller must lock lcmsMutex
-cmsHPROFILE rtengine::ICCStore::makeStdGammaProfile(cmsHPROFILE iprof)
-{
- // forgive me for the messy code, quick hack to change gamma of an ICC profile to the RT standard gamma
- if (!iprof) {
- return nullptr;
- }
-
- cmsUInt32Number bytesNeeded = 0;
- cmsSaveProfileToMem(iprof, nullptr, &bytesNeeded);
-
- if (bytesNeeded == 0) {
- return nullptr;
- }
-
- uint8_t *data = new uint8_t[bytesNeeded + 1];
- cmsSaveProfileToMem(iprof, data, &bytesNeeded);
- const uint8_t *p = &data[128]; // skip 128 byte header
- uint32_t tag_count;
- memcpy(&tag_count, p, 4);
- p += 4;
- tag_count = ntohl(tag_count);
-
- struct icctag {
- uint32_t sig;
- uint32_t offset;
- uint32_t size;
- } tags[tag_count];
-
- constexpr uint32_t gamma = 0x239;
- constexpr int gamma_size = 14;
- int data_size = (gamma_size + 3) & ~3;
-
- for (uint32_t i = 0; i < tag_count; i++) {
- memcpy(&tags[i], p, 12);
- tags[i].sig = ntohl(tags[i].sig);
- tags[i].offset = ntohl(tags[i].offset);
- tags[i].size = ntohl(tags[i].size);
- p += 12;
-
- if (tags[i].sig != 0x62545243 && // bTRC
- tags[i].sig != 0x67545243 && // gTRC
- tags[i].sig != 0x72545243 && // rTRC
- tags[i].sig != 0x6B545243) { // kTRC
- data_size += (tags[i].size + 3) & ~3;
- }
- }
-
- uint32_t sz = 128 + 4 + tag_count * 12 + data_size;
- uint8_t *nd = new uint8_t[sz];
- memset(nd, 0, sz);
- memcpy(nd, data, 128 + 4);
- sz = htonl(sz);
- memcpy(nd, &sz, 4);
- uint32_t offset = 128 + 4 + tag_count * 12;
- uint32_t gamma_offset = 0;
-
- for (uint32_t i = 0; i < tag_count; i++) {
- struct icctag tag;
- tag.sig = htonl(tags[i].sig);
-
- if (tags[i].sig == 0x62545243 || // bTRC
- tags[i].sig == 0x67545243 || // gTRC
- tags[i].sig == 0x72545243 || // rTRC
- tags[i].sig == 0x6B545243) { // kTRC
- if (gamma_offset == 0) {
- gamma_offset = offset;
- uint32_t pcurve[] = { htonl(0x63757276), htonl(0), htonl(/*gamma_size == 12 ? 0U : */1U) };
- memcpy(&nd[offset], pcurve, 12);
-
- //if (gamma_size == 14) {
- uint16_t gm = htons(gamma);
- memcpy(&nd[offset + 12], &gm, 2);
- //}
-
- offset += (gamma_size + 3) & ~3;
- }
-
- tag.offset = htonl(gamma_offset);
- tag.size = htonl(gamma_size);
- } else {
- tag.offset = htonl(offset);
- tag.size = htonl(tags[i].size);
- memcpy(&nd[offset], &data[tags[i].offset], tags[i].size);
- offset += (tags[i].size + 3) & ~3;
- }
-
- memcpy(&nd[128 + 4 + i * 12], &tag, 12);
- }
-
- cmsHPROFILE oprof = cmsOpenProfileFromMem(nd, ntohl(sz));
- delete [] nd;
- delete [] data;
- return oprof;
-}
-
cmsHPROFILE rtengine::ICCStore::createFromMatrix(const double matrix[3][3], bool gamma, const Glib::ustring& name)
{
diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h
index 117124122..fb2331263 100644
--- a/rtengine/iccstore.h
+++ b/rtengine/iccstore.h
@@ -96,7 +96,6 @@ public:
/*static*/ std::vector getWorkingProfiles();
- static cmsHPROFILE makeStdGammaProfile(cmsHPROFILE iprof);
static cmsHPROFILE createFromMatrix(const double matrix[3][3], bool gamma = false, const Glib::ustring& name = Glib::ustring());
private:
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/imagedata.cc b/rtengine/imagedata.cc
index 5025b31e5..16b6a4c91 100644
--- a/rtengine/imagedata.cc
+++ b/rtengine/imagedata.cc
@@ -69,6 +69,15 @@ T getFromFrame(
return {};
}
+const std::string& validateUft8(const std::string& str, const std::string& on_error = "???")
+{
+ if (Glib::ustring(str).validate()) {
+ return str;
+ }
+
+ return on_error;
+}
+
}
FramesMetaData* FramesMetaData::fromFile(const Glib::ustring& fname, std::unique_ptr rml, bool firstFrameOnly)
@@ -122,7 +131,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
}
if (tag) {
- make = tag->valueToString();
+ make = validateUft8(tag->valueToString());
// Same dcraw treatment
for (const auto& corp : {
@@ -158,7 +167,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
tag = newFrameRootDir->findTagUpward("Model");
if (tag) {
- model = tag->valueToString();
+ model = validateUft8(tag->valueToString());
}
if (!model.empty()) {
@@ -193,14 +202,14 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
if (model == "Unknown") {
tag = newFrameRootDir->findTag("UniqueCameraModel");
if (tag) {
- model = tag->valueToString();
+ model = validateUft8(tag->valueToString());
}
}
tag = newFrameRootDir->findTagUpward("Orientation");
if (tag) {
- orientation = tag->valueToString();
+ orientation = validateUft8(tag->valueToString());
}
// Look for Rating metadata in the following order:
@@ -310,7 +319,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
}
if (tag) {
- serial = tag->valueToString();
+ serial = validateUft8(tag->valueToString());
}
// guess lens...
@@ -320,7 +329,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
if (!make.compare(0, 8, "FUJIFILM")) {
if (exif->getTag("LensModel")) {
- lens = exif->getTag("LensModel")->valueToString();
+ lens = validateUft8(exif->getTag("LensModel")->valueToString());
}
} else if (!make.compare(0, 4, "SONY")) {
if (iso_speed == 65535 || iso_speed == 0) {
@@ -347,9 +356,9 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
const rtexif::Tag* const lens_make = exif->getTag(0xA433);
const std::string make =
lens_make
- ? lens_make->valueToString()
+ ? validateUft8(lens_make->valueToString())
: std::string();
- const std::string model = lens_model->valueToString();
+ const std::string model = validateUft8(lens_model->valueToString());
if (!model.empty()) {
lens = make;
@@ -382,7 +391,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
bool lensOk = false;
if (mnote->getTag("LensData")) {
- std::string ldata = mnote->getTag("LensData")->valueToString();
+ std::string ldata = validateUft8(mnote->getTag("LensData")->valueToString());
size_t pos;
if (ldata.size() > 10 && (pos = ldata.find("Lens = ")) != Glib::ustring::npos) {
@@ -394,10 +403,10 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
size_t pos = lens.find("$FL$"); // is there a placeholder for focallength?
if (pos != Glib::ustring::npos) { // then fill in focallength
- lens = lens.replace(pos, 4, exif->getTag("FocalLength")->valueToString());
+ lens = lens.replace(pos, 4, validateUft8(exif->getTag("FocalLength")->valueToString()));
if (mnote->getTag("LensType")) {
- std::string ltype = mnote->getTag("LensType")->valueToString();
+ const std::string ltype = validateUft8(mnote->getTag("LensType")->valueToString());
if (ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens, should be always
lens = lens.replace(0, 7, "MF");
@@ -416,7 +425,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
}
if (!lensOk && mnote->getTag("Lens")) {
- std::string ldata = mnote->getTag("Lens")->valueToString();
+ const std::string ldata = validateUft8(mnote->getTag("Lens")->valueToString());
size_t i = 0, j = 0;
double n[4] = {0.0};
@@ -453,7 +462,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
// Look whether it's MF or AF
if (mnote->getTag("LensType")) {
- std::string ltype = mnote->getTag("LensType")->valueToString();
+ const std::string ltype = validateUft8(mnote->getTag("LensType")->valueToString());
if (ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens
lens = lens.replace(0, 7, "MF"); // replace 'Unknwon' with 'MF'
@@ -478,7 +487,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
if (lt) {
if (lt->toInt()) {
- std::string ldata = lt->valueToString ();
+ const std::string ldata = validateUft8(lt->valueToString());
if (ldata.size() > 1) {
found = true;
@@ -499,7 +508,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
lt = mnote->findTag("LensID");
if (lt) {
- std::string ldata = lt->valueToString();
+ const std::string ldata = validateUft8(lt->valueToString());
if (ldata.size() > 1) {
lens = ldata;
@@ -521,7 +530,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
}
if (mnote->getTag("LensType")) {
- lens = mnote->getTag ("LensType")->valueToString();
+ lens = validateUft8(mnote->getTag("LensType")->valueToString());
// If MakeNotes are vague, fall back to Exif LensMake and LensModel if set
// https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Pentax.html#LensType
if (lens == "M-42 or No Lens" || lens == "K or M Lens" || lens == "A Series Lens" || lens == "Sigma") {
@@ -548,7 +557,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
}
} else if (!make.compare (0, 4, "SONY") || !make.compare (0, 6, "KONICA")) {
if (mnote->getTag ("LensID")) {
- lens = mnote->getTag ("LensID")->valueToString ();
+ lens = validateUft8(mnote->getTag("LensID")->valueToString());
if (lens == "Unknown") {
lens_from_make_and_model();
}
@@ -558,7 +567,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
rtexif::TagDirectory* eq = mnote->getTag("Equipment")->getDirectory();
if (eq->getTag("LensType")) {
- lens = eq->getTag("LensType")->valueToString();
+ lens = validateUft8(eq->getTag("LensType")->valueToString());
}
}
if (lens == "Unknown") {
@@ -566,7 +575,7 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
}
} else if (!make.compare (0, 9, "Panasonic")) {
if (mnote->getTag ("LensType")) {
- std::string panalens = mnote->getTag("LensType")->valueToString();
+ const std::string panalens = validateUft8(mnote->getTag("LensType")->valueToString());
if (panalens.find("LUMIX") != Glib::ustring::npos) {
lens = "Panasonic " + panalens;
@@ -576,9 +585,9 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
}
}
} else if (exif->getTag("DNGLensInfo")) {
- lens = exif->getTag("DNGLensInfo")->valueToString();
+ lens = validateUft8(exif->getTag("DNGLensInfo")->valueToString());
} else if (!lens_from_make_and_model() && exif->getTag ("LensInfo")) {
- lens = exif->getTag("LensInfo")->valueToString();
+ lens = validateUft8(exif->getTag("LensInfo")->valueToString());
}
}
}
@@ -1238,7 +1247,7 @@ std::string FramesMetaData::apertureToString(double aperture)
{
char buffer[256];
- sprintf(buffer, "%0.1f", aperture);
+ snprintf(buffer, sizeof(buffer), "%0.1f", aperture);
return buffer;
}
@@ -1248,9 +1257,9 @@ std::string FramesMetaData::shutterToString(double shutter)
char buffer[256];
if (shutter > 0.0 && shutter <= 0.5) {
- sprintf(buffer, "1/%0.0f", 1.0 / shutter);
+ snprintf(buffer, sizeof(buffer), "1/%0.0f", 1.0 / shutter);
} else {
- sprintf(buffer, "%0.1f", shutter);
+ snprintf(buffer, sizeof(buffer), "%0.1f", shutter);
}
return buffer;
@@ -1263,13 +1272,13 @@ std::string FramesMetaData::expcompToString(double expcomp, bool maskZeroexpcomp
if (maskZeroexpcomp) {
if (expcomp != 0.0) {
- sprintf(buffer, "%0.2f", expcomp);
+ snprintf(buffer, sizeof(buffer), "%0.2f", expcomp);
return buffer;
} else {
return "";
}
} else {
- sprintf(buffer, "%0.2f", expcomp);
+ snprintf(buffer, sizeof(buffer), "%0.2f", expcomp);
return buffer;
}
}
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 c7000d4b8..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
{
@@ -220,7 +209,6 @@ public:
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 aa8770504..a564676ef 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -17,16 +17,14 @@
* along with RawTherapee. If not, see .
*/
#include
-#include
-#include
#include
#include "improccoordinator.h"
+#include "array2D.h"
#include "cieimage.h"
#include "color.h"
#include "colortemp.h"
-#include "jaggedarray.h"
#include "curves.h"
#include "dcp.h"
#include "iccstore.h"
@@ -47,6 +45,9 @@
namespace
{
+
+constexpr int VECTORSCOPE_SIZE = 128;
+
using rtengine::Coord2D;
Coord2D translateCoord(const rtengine::ImProcFunctions& ipf, int fw, int fh, int x, int y) {
@@ -129,6 +130,21 @@ ImProcCoordinator::ImProcCoordinator() :
histLRETI(256),
+ hist_lrgb_dirty(false),
+ hist_raw_dirty(false),
+
+ vectorscopeScale(0),
+ vectorscope_hc_dirty(false),
+ vectorscope_hs_dirty(false),
+ vectorscope_hc(VECTORSCOPE_SIZE, VECTORSCOPE_SIZE),
+ vectorscope_hs(VECTORSCOPE_SIZE, VECTORSCOPE_SIZE),
+ waveformScale(0),
+ waveform_dirty(false),
+ waveformRed(0, 0),
+ waveformGreen(0, 0),
+ waveformBlue(0, 0),
+ waveformLuma(0, 0),
+
CAMBrightCurveJ(), CAMBrightCurveQ(),
rCurve(),
@@ -348,6 +364,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
imgsrc->getRAWHistogram(histRedRaw, histGreenRaw, histBlueRaw);
+ hist_raw_dirty = !(hListener && hListener->updateHistogramRaw());
highDetailPreprocessComputed = highDetailNeeded;
@@ -728,6 +745,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
float *sourceg = nullptr;
sourceg = new float[sizespot];
+ float *sourceab = nullptr;
+ sourceab = new float[sizespot];
float *targetg = nullptr;
targetg = new float[sizespot];
bool *log = nullptr;
@@ -760,6 +779,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
blackev[sp] = params->locallab.spots.at(sp).blackEv;
whiteev[sp] = params->locallab.spots.at(sp).whiteEv;
sourceg[sp] = params->locallab.spots.at(sp).sourceGray;
+ sourceab[sp] = params->locallab.spots.at(sp).sourceabs;
Autogr[sp] = params->locallab.spots.at(sp).Autogray;
targetg[sp] = params->locallab.spots.at(sp).targetGray;
locx[sp] = params->locallab.spots.at(sp).loc.at(0) / 2000.0;
@@ -789,14 +809,15 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
xend = 1.f;
}
- ipf.getAutoLogloc(sp, imgsrc, sourceg, blackev, whiteev, Autogr, fw, fh, xsta, xend, ysta, yend, SCALE);
+ ipf.getAutoLogloc(sp, imgsrc, sourceg, blackev, whiteev, Autogr, sourceab, fw, fh, xsta, xend, ysta, yend, SCALE);
params->locallab.spots.at(sp).blackEv = blackev[sp];
params->locallab.spots.at(sp).whiteEv = whiteev[sp];
params->locallab.spots.at(sp).sourceGray = sourceg[sp];
+ params->locallab.spots.at(sp).sourceabs = sourceab[sp];
if (locallListener) {
- locallListener->logencodChanged(blackev[sp], whiteev[sp], sourceg[sp], targetg[sp]);
+ locallListener->logencodChanged(blackev[sp], whiteev[sp], sourceg[sp], sourceab[sp], targetg[sp]);
}
}
}
@@ -812,6 +833,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
delete [] whiteev;
delete [] blackev;
delete [] targetg;
+ delete [] sourceab;
delete [] sourceg;
delete [] log;
delete [] autocomput;
@@ -819,7 +841,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
if (todo & (M_AUTOEXP | M_RGBCURVE)) {
- if (params->icm.workingTRC == "Custom") { //exec TRC IN free
+ /* if (params->icm.workingTRC == "Custom") { //exec TRC IN free
if (oprevi == orig_prev) {
oprevi = new Imagefloat(pW, pH);
orig_prev->copyData(oprevi);
@@ -848,12 +870,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
ipf.workingtrc(oprevi, oprevi, cw, ch, 5, params->icm.workingProfile, params->icm.workingTRCGamma, params->icm.workingTRCSlope, customTransformOut, false, true, true);
}
}
+ */
}
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,
@@ -1279,7 +1300,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if ((params->wavelet.enabled)) {
WaveletParams WaveParams = params->wavelet;
- WaveParams.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ WaveParams.getCurves(wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
int kall = 0;
LabImage *unshar = nullptr;
Glib::ustring provis;
@@ -1303,7 +1324,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
provis = params->wavelet.CLmethod;
params->wavelet.CLmethod = "all";
- ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
+ ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
unshar = new LabImage(*nprevl, true);
params->wavelet.CLmethod = provis;
@@ -1316,7 +1337,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
WaveParams.expnoise = false;
}
- ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
+ ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
@@ -1437,6 +1458,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
delete unshar;
unshar = NULL;
+
+
/*
if (WaveParams.softrad > 0.f) {
array2D ble(pW, pH);
@@ -1637,9 +1660,21 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
imageListener->imageReady(params->crop);
}
+ hist_lrgb_dirty = vectorscope_hc_dirty = vectorscope_hs_dirty = waveform_dirty = true;
if (hListener) {
- updateLRGBHistograms();
- hListener->histogramChanged(histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRedRaw, histGreenRaw, histBlueRaw, histChroma, histLRETI);
+ if (hListener->updateHistogram()) {
+ updateLRGBHistograms();
+ }
+ if (hListener->updateVectorscopeHC()) {
+ updateVectorscopeHC();
+ }
+ if (hListener->updateVectorscopeHS()) {
+ updateVectorscopeHS();
+ }
+ if (hListener->updateWaveform()) {
+ updateWaveforms();
+ }
+ notifyHistogramChanged();
}
}
@@ -1740,8 +1775,42 @@ void ImProcCoordinator::setScale(int prevscale)
}
-void ImProcCoordinator::updateLRGBHistograms()
+void ImProcCoordinator::notifyHistogramChanged()
{
+ if (hListener) {
+ hListener->histogramChanged(
+ histRed,
+ histGreen,
+ histBlue,
+ histLuma,
+ histToneCurve,
+ histLCurve,
+ histCCurve,
+ histLCAM,
+ histCCAM,
+ histRedRaw,
+ histGreenRaw,
+ histBlueRaw,
+ histChroma,
+ histLRETI,
+ vectorscopeScale,
+ vectorscope_hc,
+ vectorscope_hs,
+ waveformScale,
+ waveformRed,
+ waveformGreen,
+ waveformBlue,
+ waveformLuma
+ );
+ }
+}
+
+bool ImProcCoordinator::updateLRGBHistograms()
+{
+
+ if (!hist_lrgb_dirty) {
+ return false;
+ }
int x1, y1, x2, y2;
params->crop.mapToResized(pW, pH, scale, x1, x2, y1, y2);
@@ -1799,6 +1868,159 @@ void ImProcCoordinator::updateLRGBHistograms()
}
}
+ hist_lrgb_dirty = false;
+ return true;
+
+}
+
+bool ImProcCoordinator::updateVectorscopeHC()
+{
+ if (!workimg || !vectorscope_hc_dirty) {
+ return false;
+ }
+
+ int x1, y1, x2, y2;
+ params->crop.mapToResized(pW, pH, scale, x1, x2, y1, y2);
+
+ constexpr int size = VECTORSCOPE_SIZE;
+ constexpr float norm_factor = size / (128.f * 655.36f);
+ vectorscope_hc.fill(0);
+
+ vectorscopeScale = (x2 - x1) * (y2 - y1);
+
+ const std::unique_ptr a(new float[vectorscopeScale]);
+ const std::unique_ptr b(new float[vectorscopeScale]);
+ const std::unique_ptr L(new float[vectorscopeScale]);
+ ipf.rgb2lab(*workimg, x1, y1, x2 - x1, y2 - y1, L.get(), a.get(), b.get(), params->icm);
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ array2D vectorscopeThr(size, size, ARRAY2D_CLEAR_DATA);
+#ifdef _OPENMP
+ #pragma omp for nowait
+#endif
+ for (int i = y1; i < y2; ++i) {
+ for (int j = x1, ofs_lab = (i - y1) * (x2 - x1); j < x2; ++j, ++ofs_lab) {
+ const int col = norm_factor * a[ofs_lab] + size / 2 + 0.5f;
+ const int row = norm_factor * b[ofs_lab] + size / 2 + 0.5f;
+ if (col >= 0 && col < size && row >= 0 && row < size) {
+ vectorscopeThr[row][col]++;
+ }
+ }
+ }
+#ifdef _OPENMP
+ #pragma omp critical
+#endif
+ {
+ vectorscope_hc += vectorscopeThr;
+ }
+ }
+
+ vectorscope_hc_dirty = false;
+ return true;
+}
+
+bool ImProcCoordinator::updateVectorscopeHS()
+{
+ if (!workimg || !vectorscope_hs_dirty) {
+ return false;
+ }
+
+ int x1, y1, x2, y2;
+ params->crop.mapToResized(pW, pH, scale, x1, x2, y1, y2);
+
+ constexpr int size = VECTORSCOPE_SIZE;
+ vectorscope_hs.fill(0);
+
+ vectorscopeScale = (x2 - x1) * (y2 - y1);
+
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ array2D vectorscopeThr(size, size, ARRAY2D_CLEAR_DATA);
+#ifdef _OPENMP
+ #pragma omp for nowait
+#endif
+ for (int i = y1; i < y2; ++i) {
+ int ofs = (i * pW + x1) * 3;
+ for (int j = x1; j < x2; ++j) {
+ const float red = 257.f * workimg->data[ofs++];
+ const float green = 257.f * workimg->data[ofs++];
+ const float blue = 257.f * workimg->data[ofs++];
+ float h, s, l;
+ Color::rgb2hslfloat(red, green, blue, h, s, l);
+ const auto sincosval = xsincosf(2.f * RT_PI_F * h);
+ const int col = s * sincosval.y * (size / 2) + size / 2;
+ const int row = s * sincosval.x * (size / 2) + size / 2;
+ if (col >= 0 && col < size && row >= 0 && row < size) {
+ vectorscopeThr[row][col]++;
+ }
+ }
+ }
+#ifdef _OPENMP
+ #pragma omp critical
+#endif
+ {
+ vectorscope_hs += vectorscopeThr;
+ }
+ }
+
+ vectorscope_hs_dirty = false;
+ return true;
+}
+
+bool ImProcCoordinator::updateWaveforms()
+{
+ if (!workimg) {
+ // free memory
+ waveformRed.free();
+ waveformGreen.free();
+ waveformBlue.free();
+ waveformLuma.free();
+ return true;
+ }
+
+ if (!waveform_dirty) {
+ return false;
+ }
+
+ int x1, y1, x2, y2;
+ params->crop.mapToResized(pW, pH, scale, x1, x2, y1, y2);
+ int waveform_width = waveformRed.getWidth();
+
+ if (waveform_width != x2 - x1) {
+ // Resize waveform arrays.
+ waveform_width = x2 - x1;
+ waveformRed(waveform_width, 256);
+ waveformGreen(waveform_width, 256);
+ waveformBlue(waveform_width, 256);
+ waveformLuma(waveform_width, 256);
+ }
+
+ // Start with zero.
+ waveformRed.fill(0);
+ waveformGreen.fill(0);
+ waveformBlue.fill(0);
+ waveformLuma.fill(0);
+
+ constexpr float luma_factor = 255.f / 32768.f;
+ for (int i = y1; i < y2; i++) {
+ int ofs = (i * pW + x1) * 3;
+ float* L_row = nprevl->L[i] + x1;
+
+ for (int j = 0; j < waveform_width; j++) {
+ waveformRed[workimg->data[ofs++]][j]++;
+ waveformGreen[workimg->data[ofs++]][j]++;
+ waveformBlue[workimg->data[ofs++]][j]++;
+ waveformLuma[LIM(L_row[j] * luma_factor, 0, 255)][j]++;
+ }
+ }
+
+ waveformScale = y2 - y1;
+ waveform_dirty = false;
+ return true;
}
bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, double tempBias)
@@ -2243,4 +2465,61 @@ void ImProcCoordinator::setHighQualComputed()
highQualityComputed = true;
}
+void ImProcCoordinator::requestUpdateWaveform()
+{
+ if (!hListener) {
+ return;
+ }
+ bool updated = updateWaveforms();
+ if (updated) {
+ notifyHistogramChanged();
+ }
+}
+
+void ImProcCoordinator::requestUpdateHistogram()
+{
+ if (!hListener) {
+ return;
+ }
+ bool updated = updateLRGBHistograms();
+ if (updated) {
+ notifyHistogramChanged();
+ }
+}
+
+void ImProcCoordinator::requestUpdateHistogramRaw()
+{
+ if (!hListener) {
+ return;
+ }
+ // Don't need to actually update histogram because it is always
+ // up-to-date.
+ if (hist_raw_dirty) {
+ hist_raw_dirty = false;
+ notifyHistogramChanged();
+ }
+}
+
+void ImProcCoordinator::requestUpdateVectorscopeHC()
+{
+ if (!hListener) {
+ return;
+ }
+ bool updated = updateVectorscopeHC();
+ if (updated) {
+ notifyHistogramChanged();
+ }
+}
+
+void ImProcCoordinator::requestUpdateVectorscopeHS()
+{
+ if (!hListener) {
+ return;
+ }
+ bool updated = updateVectorscopeHS();
+ if (updated) {
+ notifyHistogramChanged();
+ }
+}
+
}
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index ab57a4419..83bee6955 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -54,7 +54,7 @@ class Crop;
* but using this class' LUT and other precomputed parameters. The main preview area is displaying a non framed Crop object,
* while detail windows are framed Crop objects.
*/
-class ImProcCoordinator final : public StagedImageProcessor
+class ImProcCoordinator final : public StagedImageProcessor, public HistogramObservable
{
friend class Crop;
@@ -126,6 +126,16 @@ protected:
LUTu histBlue, histBlueRaw;
LUTu histLuma, histToneCurve, histToneCurveBW, histLCurve, histCCurve;
LUTu histLLCurve, histLCAM, histCCAM, histClad, bcabhist, histChroma, histLRETI;
+ bool hist_lrgb_dirty;
+ /// Used to simulate a lazy update of the raw histogram.
+ bool hist_raw_dirty;
+ int vectorscopeScale;
+ bool vectorscope_hc_dirty, vectorscope_hs_dirty;
+ array2D vectorscope_hc, vectorscope_hs;
+ /// Waveform's intensity. Same as height of reference image.
+ int waveformScale;
+ bool waveform_dirty;
+ array2D waveformRed, waveformGreen, waveformBlue, waveformLuma;
LUTf CAMBrightCurveJ, CAMBrightCurveQ;
@@ -139,6 +149,8 @@ protected:
NoiseCurve noiseLCurve;
NoiseCurve noiseCCurve;
WavCurve wavCLVCurve;
+ WavCurve wavdenoise;
+ WavCurve wavdenoiseh;
Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
WavOpacityCurveSH waOpacityCurveSH;
@@ -193,8 +205,16 @@ protected:
MyMutex minit; // to gain mutually exclusive access to ... to what exactly?
+ void notifyHistogramChanged();
void reallocAll();
- void updateLRGBHistograms();
+ /// Updates L, R, G, and B histograms. Returns true unless not updated.
+ bool updateLRGBHistograms();
+ /// Updates the H-C vectorscope. Returns true unless not updated.
+ bool updateVectorscopeHC();
+ /// Updates the H-S vectorscope. Returns true unless not updated.
+ bool updateVectorscopeHS();
+ /// Updates all waveforms. Returns true unless not updated.
+ bool updateWaveforms();
void setScale(int prevscale);
void updatePreviewImage (int todo, bool panningRelatedChange);
@@ -447,7 +467,13 @@ public:
}
void setHistogramListener (HistogramListener *h) override
{
+ if (hListener) {
+ hListener->setObservable(nullptr);
+ }
hListener = h;
+ if (h) {
+ h->setObservable(this);
+ }
}
void setAutoCamListener (AutoCamListener* acl) override
{
@@ -548,6 +574,11 @@ public:
} denoiseInfoStore;
+ void requestUpdateHistogram() override;
+ void requestUpdateHistogramRaw() override;
+ void requestUpdateVectorscopeHC() override;
+ void requestUpdateVectorscopeHS() override;
+ void requestUpdateWaveform() override;
};
}
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index 6051b6b0b..05cc115d9 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -5218,7 +5218,7 @@ void ImProcFunctions::EPDToneMaplocal(int sp, LabImage *lab, LabImage *tmp1, uns
/* Debuggery. Saves L for toying with outside of RT.
char nm[64];
- sprintf(nm, "%ux%ufloat.bin", lab->W, lab->H);
+ snprintf(nm, sizeof(nm), "%ux%ufloat.bin", lab->W, lab->H);
FILE *f = fopen(nm, "wb");
fwrite(L, N, sizeof(float), f);
fclose(f);*/
@@ -5716,6 +5716,116 @@ void ImProcFunctions::rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::
}
}
+void ImProcFunctions::rgb2lab(const Image8 &src, int x, int y, int w, int h, float L[], float a[], float b[], const procparams::ColorManagementParams &icm, bool consider_histogram_settings) const
+{ // Adapted from ImProcFunctions::lab2rgb
+ const int src_width = src.getWidth();
+ const int src_height = src.getHeight();
+
+ if (x < 0) {
+ x = 0;
+ }
+
+ if (y < 0) {
+ y = 0;
+ }
+
+ if (x + w > src_width) {
+ w = src_width - x;
+ }
+
+ if (y + h > src_height) {
+ h = src_height - y;
+ }
+
+ Glib::ustring profile;
+
+ cmsHPROFILE oprof = nullptr;
+
+ if (settings->HistogramWorking && consider_histogram_settings) {
+ profile = icm.workingProfile;
+ } else {
+ profile = icm.outputProfile;
+
+ if (icm.outputProfile.empty() || icm.outputProfile == ColorManagementParams::NoICMString) {
+ profile = "sRGB";
+ }
+ oprof = ICCStore::getInstance()->getProfile(profile);
+ }
+
+ if (oprof) {
+ cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE; // NOCACHE is important for thread safety
+
+ if (icm.outputBPC) {
+ flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
+ }
+
+ lcmsMutex->lock();
+ cmsHPROFILE LabIProf = cmsCreateLab4Profile(nullptr);
+ cmsHTRANSFORM hTransform = cmsCreateTransform (oprof, TYPE_RGB_8, LabIProf, TYPE_Lab_FLT, icm.outputIntent, flags);
+ cmsCloseProfile(LabIProf);
+ lcmsMutex->unlock();
+
+ // cmsDoTransform is relatively expensive
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ AlignedBuffer oBuf(3 * w);
+ float *outbuffer = oBuf.data;
+ int condition = y + h;
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for (int i = y; i < condition; i++) {
+ const int ix = 3 * (x + i * src_width);
+ int iy = 0;
+ float* rL = L + (i - y) * w;
+ float* ra = a + (i - y) * w;
+ float* rb = b + (i - y) * w;
+
+ cmsDoTransform (hTransform, src.data + ix, outbuffer, w);
+
+ for (int j = 0; j < w; j++) {
+ rL[j] = outbuffer[iy++] * 327.68f;
+ ra[j] = outbuffer[iy++] * 327.68f;
+ rb[j] = outbuffer[iy++] * 327.68f;
+ }
+ }
+ } // End of parallelization
+
+ cmsDeleteTransform(hTransform);
+ } else {
+ TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(profile);
+ const float wp[3][3] = {
+ {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])},
+ {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])},
+ {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])}
+ };
+
+ const int x2 = x + w;
+ const int y2 = y + h;
+ constexpr float rgb_factor = 65355.f / 255.f;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+
+ for (int i = y; i < y2; i++) {
+ int offset = (i - y) * w;
+ for (int j = x; j < x2; j++) {
+ float X, Y, Z;
+ // lab2rgb uses gamma2curve, which is gammatab_srgb.
+ const auto& igamma = Color::igammatab_srgb;
+ Color::rgbxyz(igamma[rgb_factor * src.r(i, j)], igamma[rgb_factor * src.g(i, j)], igamma[rgb_factor * src.b(i, j)], X, Y, Z, wp);
+ Color::XYZ2Lab(X, Y, Z, L[offset], a[offset], b[offset]);
+ offset++;
+ }
+ }
+ }
+}
+
void ImProcFunctions::lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace)
{
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix(workingSpace);
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index d9618ba9f..3f0d2c0e4 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -175,7 +175,7 @@ public:
void moyeqt(Imagefloat* working, float &moyS, float &eqty);
void luminanceCurve(LabImage* lold, LabImage* lnew, const LUTf &curve);
- void ciecamloc_02float(int sp, LabImage* lab);
+ void ciecamloc_02float(int sp, LabImage* lab, int call);
void ciecam_02float(CieImage* ncie, float adap, int pW, int pwb, LabImage* lab, const procparams::ProcParams* params,
const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3,
@@ -233,7 +233,7 @@ public:
const LocCCmaskCurve & locccmasCurve, bool lcmasutili,
const LocLLmaskCurve & locllmasCurve, bool llmasutili,
const LocHHmaskCurve & lochhmasCurve, bool lhmasutili, const LocHHmaskCurve & lochhhmasCurve, bool lhhmasutili,
- bool multiThread, bool enaMask, bool showmaske, bool deltaE, bool modmask, bool zero, bool modif, float chrom, float rad, float lap, float gamma, float slope, float blendm, float blendmab, int shado, float amountcd, float anchorcd,
+ bool multiThread, bool enaMask, bool showmaske, bool deltaE, bool modmask, bool zero, bool modif, float chrom, float rad, float lap, float gamma, float slope, float blendm, float blendmab, int shado, int highl, float amountcd, float anchorcd,
const LUTf& lmasklocalcurve, bool localmaskutili,
const LocwavCurve & loclmasCurvecolwav, bool lmasutilicolwav, int level_bl, int level_hl, int level_br, int level_hr,
int shortcu, bool delt, const float hueref, const float chromaref, const float lumaref,
@@ -263,8 +263,8 @@ public:
//3 functions from Alberto Griggio, adapted J.Desmis 2019
void filmGrain(Imagefloat *rgb, int isogr, int strengr, int scalegr, int bfw, int bfh);
- void log_encode(Imagefloat *rgb, const struct local_params & lp, bool multiThread, int bfw, int bfh);
- void getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg, float *blackev, float *whiteev, bool *Autogr, int fw, int fh, float xsta, float xend, float ysta, float yend, int SCALE);
+ void log_encode(Imagefloat *rgb, struct local_params & lp, bool multiThread, int bfw, int bfh);
+ void getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg, float *blackev, float *whiteev, bool *Autogr, float *sourceab, int fw, int fh, float xsta, float xend, float ysta, float yend, int SCALE);
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,
@@ -368,7 +368,7 @@ public:
//Wavelet and denoise
void Tile_calc(int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip);
- void ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const Wavblcurve & wavblcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveSH & waOpacityCurveSH, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, const LUTf &wavclCurve, int skip);
+ void ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavCurve & wavdenoise, WavCurve & wavdenoiseh, const Wavblcurve & wavblcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveSH & waOpacityCurveSH, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, const LUTf &wavclCurve, int skip);
void WaveletcontAllL(LabImage * lab, float **varhue, float **varchrom, 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);
@@ -449,6 +449,7 @@ public:
void labColorCorrectionRegions(LabImage *lab);
Image8* lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true);
+ void rgb2lab(const Image8 &src, int x, int y, int w, int h, float L[], float a[], float b[], const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true) const;
Imagefloat* lab2rgbOut(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm);
// CieImage *ciec;
void workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, const Glib::ustring &profile, double gampos, double slpos, cmsHTRANSFORM &transform, bool normalizeIn = true, bool normalizeOut = true, bool keepTransForm = false) const;
diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc
index 0549995dd..dd89301ae 100644
--- a/rtengine/iplab2rgb.cc
+++ b/rtengine/iplab2rgb.cc
@@ -32,8 +32,6 @@
namespace rtengine
{
-extern void filmlike_clip(float *r, float *g, float *b);
-
namespace {
inline void copyAndClampLine(const float *src, unsigned char *dst, const int W)
@@ -46,9 +44,26 @@ inline void copyAndClampLine(const float *src, unsigned char *dst, const int W)
inline void copyAndClamp(const LabImage *src, unsigned char *dst, const double rgb_xyz[3][3], bool multiThread)
{
- int W = src->W;
- int H = src->H;
+ const int W = src->W;
+ const int H = src->H;
+ float rgb_xyzf[3][3];
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ rgb_xyzf[i][j] = rgb_xyz[i][j];
+ }
+ }
+
+#ifdef __SSE2__
+ vfloat rgb_xyzv[3][3];
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ rgb_xyzv[i][j] = F2V(rgb_xyzf[i][j]);
+ }
+ }
+#endif
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
@@ -58,17 +73,47 @@ inline void copyAndClamp(const LabImage *src, unsigned char *dst, const double r
float* rb = src->b[i];
int ix = i * 3 * W;
- float R, G, B;
- float x_, y_, z_;
-
- for (int j = 0; j < W; ++j) {
+#ifdef __SSE2__
+ float rbuffer[W] ALIGNED16;
+ float gbuffer[W] ALIGNED16;
+ float bbuffer[W] ALIGNED16;
+ int j = 0;
+ for (; j < W - 3; j += 4) {
+ vfloat R, G, B;
+ vfloat x_, y_, z_;
+ Color::Lab2XYZ(LVFU(rL[j]), LVFU(ra[j]), LVFU(rb[j]), x_, y_, z_ );
+ Color::xyz2rgb(x_, y_, z_, R, G, B, rgb_xyzv);
+ STVF(rbuffer[j], Color::gamma2curve[R]);
+ STVF(gbuffer[j], Color::gamma2curve[G]);
+ STVF(bbuffer[j], Color::gamma2curve[B]);
+ }
+ for (; j < W; ++j) {
+ float R, G, B;
+ float x_, y_, z_;
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_ );
- Color::xyz2rgb(x_, y_, z_, R, G, B, rgb_xyz);
+ Color::xyz2rgb(x_, y_, z_, R, G, B, rgb_xyzf);
+ rbuffer[j] = Color::gamma2curve[R];
+ gbuffer[j] = Color::gamma2curve[G];
+ bbuffer[j] = Color::gamma2curve[B];
+ }
+ for (int j = 0; j < W; ++j) {
+ dst[ix++] = uint16ToUint8Rounded(rbuffer[j]);
+ dst[ix++] = uint16ToUint8Rounded(gbuffer[j]);
+ dst[ix++] = uint16ToUint8Rounded(bbuffer[j]);
+ }
+
+#else
+ for (int j = 0; j < W; ++j) {
+ float R, G, B;
+ float x_, y_, z_;
+ Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_ );
+ Color::xyz2rgb(x_, y_, z_, R, G, B, rgb_xyzf);
dst[ix++] = uint16ToUint8Rounded(Color::gamma2curve[R]);
dst[ix++] = uint16ToUint8Rounded(Color::gamma2curve[G]);
dst[ix++] = uint16ToUint8Rounded(Color::gamma2curve[B]);
}
+#endif
}
}
@@ -151,8 +196,6 @@ void ImProcFunctions::lab2monitorRgb(LabImage* lab, Image8* image)
// otherwise divide by 327.68, convert to xyz and apply the RGB transform, before converting with gamma2curve
Image8* ImProcFunctions::lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings)
{
- //gamutmap(lab);
-
if (cx < 0) {
cx = 0;
}
@@ -172,11 +215,10 @@ Image8* ImProcFunctions::lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch,
Image8* image = new Image8(cw, ch);
Glib::ustring profile;
- bool standard_gamma;
+ cmsHPROFILE oprof = nullptr;
if (settings->HistogramWorking && consider_histogram_settings) {
profile = icm.workingProfile;
- standard_gamma = true;
} else {
profile = icm.outputProfile;
@@ -184,27 +226,15 @@ Image8* ImProcFunctions::lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch,
profile = "sRGB";
}
- standard_gamma = false;
+ oprof = ICCStore::getInstance()->getProfile(profile);
}
- cmsHPROFILE oprof = ICCStore::getInstance()->getProfile(profile);
-
if (oprof) {
- cmsHPROFILE oprofG = oprof;
-
- if (standard_gamma) {
- oprofG = ICCStore::makeStdGammaProfile(oprof);
- }
-
- cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
-
- if (icm.outputBPC) {
- flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
- }
+ const cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | (icm.outputBPC ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0); // NOCACHE is important for thread safety
lcmsMutex->lock();
cmsHPROFILE LabIProf = cmsCreateLab4Profile(nullptr);
- cmsHTRANSFORM hTransform = cmsCreateTransform (LabIProf, TYPE_Lab_DBL, oprofG, TYPE_RGB_FLT, icm.outputIntent, flags); // NOCACHE is important for thread safety
+ cmsHTRANSFORM hTransform = cmsCreateTransform (LabIProf, TYPE_Lab_DBL, oprof, TYPE_RGB_FLT, icm.outputIntent, flags);
cmsCloseProfile(LabIProf);
lcmsMutex->unlock();
@@ -245,9 +275,6 @@ Image8* ImProcFunctions::lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch,
cmsDeleteTransform(hTransform);
- if (oprofG != oprof) {
- cmsCloseProfile(oprofG);
- }
} else {
const auto xyz_rgb = ICCStore::getInstance()->workingSpaceInverseMatrix(profile);
copyAndClamp(lab, image->data, xyz_rgb, multiThread);
diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc
index cfd4a271e..a6e46b53a 100644
--- a/rtengine/iplocallab.cc
+++ b/rtengine/iplocallab.cc
@@ -36,7 +36,6 @@
#include "rt_algo.h"
#include "settings.h"
#include "../rtgui/options.h"
-
#include "utils.h"
#ifdef _OPENMP
#include
@@ -539,6 +538,7 @@ struct local_params {
int blmet;
int smasktyp;
int chromet;
+ int quamet;
int shmeth;
int medmet;
int locmet;
@@ -709,12 +709,14 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
} else if (locallab.spots.at(sp).gridMethod == "two") {
lp.gridmet = 1;
}
-
+/*
if (locallab.spots.at(sp).expMethod == "std") {
lp.expmet = 0;
} else if (locallab.spots.at(sp).expMethod == "pde") {
lp.expmet = 1;
}
+*/
+ lp.expmet = 1;
if (locallab.spots.at(sp).localcontMethod == "loc") {
lp.locmet = 0;
@@ -784,6 +786,12 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
lp.chromet = 2;
}
+ if (locallab.spots.at(sp).quamethod == "cons") {
+ lp.quamet = 0;
+ } else if (locallab.spots.at(sp).quamethod == "agre") {
+ lp.quamet = 1;
+ }
+
if (locallab.spots.at(sp).shMethod == "std") {
lp.shmeth = 0;
} else if (locallab.spots.at(sp).shMethod == "tone") {
@@ -802,12 +810,18 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
} else if (locallab.spots.at(sp).medMethod == "99") {
lp.medmet = 3;
}
-
+/*
if (locallab.spots.at(sp).blurMethod == "norm") {
lp.blurmet = 0;
} else if (locallab.spots.at(sp).blurMethod == "inv") {
lp.blurmet = 1;
}
+*/
+ if (locallab.spots.at(sp).invbl == false) {
+ lp.blurmet = 0;
+ } else if (locallab.spots.at(sp).invbl == true) {
+ lp.blurmet = 1;
+ }
if (locallab.spots.at(sp).showmaskblMethodtyp == "blur") {
lp.smasktyp = 0;
@@ -1546,18 +1560,23 @@ float find_gray(float source_gray, float target_gray)
// basic log encoding taken from ACESutil.Lin_to_Log2, from
// https://github.com/ampas/aces-dev
// (as seen on pixls.us)
-void ImProcFunctions::log_encode(Imagefloat *rgb, const struct local_params & lp, bool multiThread, int bfw, int bfh)
+void ImProcFunctions::log_encode(Imagefloat *rgb, struct local_params & lp, bool multiThread, int bfw, int bfh)
{
/* J.Desmis 12 2019
small adaptations to local adjustments
replace log2 by log(lp.baselog) allows diferentiation between low and high lights
*/
- BENCHFUN
+ // BENCHFUN
const float gray = lp.sourcegray / 100.f;
const float shadows_range = lp.blackev;
- const float dynamic_range = lp.whiteev - lp.blackev;
+
+ float dynamic_range = lp.whiteev - lp.blackev;
+ if (dynamic_range < 0.5f) {
+ dynamic_range = 0.5f;
+ }
const float noise = pow_F(2.f, -16.f);
- const float log2 = xlogf(lp.baselog);
+ // const float log2 = xlogf(lp.baselog);
+ const float log2 = xlogf(2.f);
const float base = lp.targetgray > 1 && lp.targetgray < 100 && dynamic_range > 0 ? find_gray(std::abs(lp.blackev) / dynamic_range, lp.targetgray / 100.f) : 0.f;
const float linbase = rtengine::max(base, 0.f);
TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile);
@@ -1633,9 +1652,14 @@ void ImProcFunctions::log_encode(Imagefloat *rgb, const struct local_params & lp
if (m > noise) {
float mm = apply(m);
float f = mm / m;
+ f = min(f, 1000000.f);
+
r *= f;
b *= f;
g *= f;
+ r = CLIP(r);
+ g = CLIP(g);
+ b = CLIP(b);
}
assert(r == r);
@@ -1689,22 +1713,27 @@ void ImProcFunctions::log_encode(Imagefloat *rgb, const struct local_params & lp
// float t2 = norm(r, g, b);
float f2 = apply(t2) / t2;
f = intp(blend, f, f2);
- assert(std::isfinite(f));
+ f = min(f, 1000000.f);
+
+ // assert(std::isfinite(f));
r *= f;
g *= f;
b *= f;
- assert(std::isfinite(r));
- assert(std::isfinite(g));
- assert(std::isfinite(b));
+ r = CLIP(r);
+ g = CLIP(g);
+ b = CLIP(b);
+ // assert(std::isfinite(r));
+ // assert(std::isfinite(g));
+ // assert(std::isfinite(b));
}
}
}
}
}
-void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg, float *blackev, float *whiteev, bool *Autogr, int fw, int fh, float xsta, float xend, float ysta, float yend, int SCALE)
+void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg, float *blackev, float *whiteev, bool *Autogr, float *sourceab, int fw, int fh, float xsta, float xend, float ysta, float yend, int SCALE)
{
- BENCHFUN
+ //BENCHFUN
//adpatation to local adjustments Jacques Desmis 12 2019
const PreviewProps pp(0, 0, fw, fh, SCALE);
@@ -1808,14 +1837,45 @@ void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg,
}
}
}
-
const float gray = sourceg[sp] / 100.f;
whiteev[sp] = xlogf(maxVal / gray) / log2;
blackev[sp] = whiteev[sp] - dynamic_range;
+
+
+ //calculate La - Absolute luminance shooting
+
+ const FramesMetaData* metaData = imgsrc->getMetaData();
+ int imgNum = 0;
+
+ if (imgsrc->isRAW()) {
+ if (imgsrc->getSensorType() == ST_BAYER) {
+ imgNum = rtengine::LIM(params->raw.bayersensor.imageNum, 0, metaData->getFrameCount() - 1);
+ } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) {
+ //imgNum = rtengine::LIM(params->raw.xtranssensor.imageNum, 0, metaData->getFrameCount() - 1);
+ }
+ }
+
+ float fnum = metaData->getFNumber(imgNum); // F number
+ float fiso = metaData->getISOSpeed(imgNum) ; // ISO
+ float fspeed = metaData->getShutterSpeed(imgNum) ; // Speed
+ double fcomp = metaData->getExpComp(imgNum); // Compensation +/-
+ double adap;
+
+ if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
+ adap = 2000.;
+ } else {
+ double E_V = fcomp + std::log2(double ((fnum * fnum) / fspeed / (fiso / 100.f)));
+ E_V += params->toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
+ E_V += std::log2(params->raw.expos); // exposure raw white point ; log2 ==> linear to EV
+ adap = pow(2.0, E_V - 3.0); // cd / m2
+ // end calculation adaptation scene luminosity
+ }
+
+ sourceab[sp] = adap;
}
}
-void tone_eq(array2D &R, array2D &G, array2D &B, const struct local_params & lp, const Glib::ustring &workingProfile, double scale, bool multithread)
+void tone_eq(array2D &R, array2D &G, array2D &B, const struct local_params & lp, const Glib::ustring &workingProfile, double scale, bool multithread)
// adapted from the tone equalizer of darktable
/*
Copyright 2019 Alberto Griggio
@@ -1838,7 +1898,7 @@ void tone_eq(array2D &R, array2D &G, array2D &B, const stru
*/
{
- BENCHFUN
+ // BENCHFUN
const int W = R.getWidth();
const int H = R.getHeight();
@@ -2043,11 +2103,13 @@ void tone_eq(array2D &R, array2D &G, array2D &B, const stru
}
-void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab)
+void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab, int call)
{
- //be careful quasi duplicate with branch cat02wb
- BENCHFUN
-
+ //BENCHFUN
+ bool ciec = false;
+ if (params->locallab.spots.at(sp).ciecam && params->locallab.spots.at(sp).explog && call == 1) {
+ ciec = true;
+ }
int width = lab->W, height = lab->H;
float Yw;
Yw = 1.0f;
@@ -2059,13 +2121,121 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab)
double Xwout, Zwout;
double Xwsc, Zwsc;
- int tempo;
+ LUTu hist16J;
+ //for J light and contrast
+ LUTf CAMBrightCurveJ;
+ CAMBrightCurveJ(32768, LUT_CLIP_ABOVE);
+ CAMBrightCurveJ.dirty = true;
- if (params->locallab.spots.at(sp).warm > 0) {
- tempo = 5000 - 30 * params->locallab.spots.at(sp).warm;
- } else {
- tempo = 5000 - 49 * params->locallab.spots.at(sp).warm;
+ if (CAMBrightCurveJ.dirty) {
+ hist16J(32768);
+ hist16J.clear();
+
+ double sum = 0.0; // use double precision for large summations
+
+#ifdef _OPENMP
+ const int numThreads = min(max(width * height / 65536, 1), omp_get_max_threads());
+ #pragma omp parallel num_threads(numThreads) if(numThreads>1)
+#endif
+ {
+ LUTu hist16Jthr;
+ hist16Jthr(hist16J.getSize());
+ hist16Jthr.clear();
+
+#ifdef _OPENMP
+ #pragma omp for reduction(+:sum)
+#endif
+
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) { //rough correspondence between L and J
+ float currL = lab->L[i][j] / 327.68f;
+ float koef; //rough correspondence between L and J
+
+ if (currL > 50.f) {
+ if (currL > 70.f) {
+ if (currL > 80.f) {
+ if (currL > 85.f) {
+ koef = 0.97f;
+ } else {
+ koef = 0.93f;
+ }
+ } else {
+ koef = 0.87f;
+ }
+ } else {
+ if (currL > 60.f) {
+ koef = 0.85f;
+ } else {
+ koef = 0.8f;
+ }
+ }
+ } else {
+ if (currL > 10.f) {
+ if (currL > 20.f) {
+ if (currL > 40.f) {
+ koef = 0.75f;
+ } else {
+ koef = 0.7f;
+ }
+ } else {
+ koef = 0.9f;
+ }
+ } else {
+ koef = 1.0;
+ }
+ }
+
+ hist16Jthr[(int)((koef * lab->L[i][j]))]++; //evaluate histogram luminance L # J
+ sum += static_cast(koef) * static_cast(lab->L[i][j]); //evaluate mean J to calculate Yb
+ //sum not used, but perhaps...
+ }
+ }
+
+#ifdef _OPENMP
+ #pragma omp critical
+#endif
+ {
+ hist16J += hist16Jthr;
+ }
+ }
+#ifdef _OPENMP
+ static_cast(numThreads); // to silence cppcheck warning
+#endif
+
+ //evaluate lightness, contrast
+ }
+
+
+
+
+
+ float contL = 0.f;
+ if (ciec) {
+ contL = 0.6f *params->locallab.spots.at(sp).contl;//0.6 less effect, no need 1.
+
+ if (CAMBrightCurveJ.dirty) {
+ Ciecam02::curveJfloat(0.f, contL, hist16J, CAMBrightCurveJ); //contrast J
+ CAMBrightCurveJ /= 327.68f;
+ CAMBrightCurveJ.dirty = false;
+ }
}
+ int tempo = 5000;
+ if(params->locallab.spots.at(sp).expvibrance && call == 2) {
+ if (params->locallab.spots.at(sp).warm > 0) {
+ tempo = 5000 - 30 * params->locallab.spots.at(sp).warm;
+ } else if (params->locallab.spots.at(sp).warm < 0){
+ tempo = 5000 - 70 * params->locallab.spots.at(sp).warm;
+ }
+ }
+
+ if(ciec) {
+ if (params->locallab.spots.at(sp).catad > 0) {
+ tempo = 5000 - 30 * params->locallab.spots.at(sp).catad;
+ } else if (params->locallab.spots.at(sp).catad < 0){
+ tempo = 5000 - 70 * params->locallab.spots.at(sp).catad;
+ }
+ }
+
ColorTemp::temp2mulxyz(params->wb.temperature, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB
ColorTemp::temp2mulxyz(tempo, "Custom", Xwout, Zwout);
@@ -2077,8 +2247,25 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab)
nc = 1.00f;
//viewing condition for surround
f2 = 1.0f, c2 = 0.69f, nc2 = 1.0f;
- //with which algorithm
- // alg = 0;
+ if(ciec) {
+ //viewing condition for surround
+ if (params->locallab.spots.at(sp).surround == "Average") {
+ f2 = 1.0f, c2 = 0.69f, nc2 = 1.0f;
+ } else if (params->locallab.spots.at(sp).surround == "Dim") {
+ f2 = 0.9f;
+ c2 = 0.59f;
+ nc2 = 0.9f;
+ } else if (params->locallab.spots.at(sp).surround == "Dark") {
+ f2 = 0.8f;
+ c2 = 0.525f;
+ nc2 = 0.8f;
+ } else if (params->locallab.spots.at(sp).surround == "ExtremelyDark") {
+ f2 = 0.8f;
+ c2 = 0.41f;
+ nc2 = 0.8f;
+ }
+ }
+
xwd = 100.0 * Xwout;
@@ -2090,18 +2277,42 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab)
yws = 100.f;
- yb2 = 18;
//La and la2 = ambiant luminosity scene and viewing
la = 400.f;
- const float la2 = 400.f;
+ float la2 = 400.f;
+ if(ciec) {
+ la = params->locallab.spots.at(sp).sourceabs;
+
+ la2 = params->locallab.spots.at(sp).targabs;
+ }
+
const float pilot = 2.f;
const float pilotout = 2.f;
//algoritm's params
- // const float rstprotection = 100. ;//- params->colorappearance.rstprotection;
- LUTu hist16J;
LUTu hist16Q;
float yb = 18.f;
+ yb2 = 18;
+ if(ciec) {
+ yb = params->locallab.spots.at(sp).targetGray;//target because we are after Log encoding
+
+ yb2 = params->locallab.spots.at(sp).targetGray;
+ }
+
+ float schr = 0.f;
+
+ if (ciec) {
+ schr = params->locallab.spots.at(sp).saturl;
+
+ if (schr > 0.f) {
+ schr = schr / 2.f; //divide sensibility for saturation
+ }
+
+ if (schr == -100.f) {
+ schr = -99.8f;
+ }
+ }
+
float d, dj;
// const int gamu = 0; //(params->colorappearance.gamut) ? 1 : 0;
@@ -2109,7 +2320,11 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab)
yw = 100.f * Yw;
zw = 100.0 * Zw;
float xw1 = xws, yw1 = yws, zw1 = zws, xw2 = xwd, yw2 = ywd, zw2 = zwd;
-
+/*
+ xw1 = 96.46f; //use RT WB; CAT 02 is used for output device (see prefreneces)
+ yw1 = 100.0f;
+ zw1 = 82.445f;
+*/
float cz, wh, pfl;
Ciecam02::initcam1float(yb, pilot, f, la, xw, yw, zw, n, d, nbb, ncb, cz, aw, wh, pfl, fl, c);
// const float chr = 0.f;
@@ -2120,6 +2335,8 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab)
const float reccmcz = 1.f / (c2 * czj);
#endif
const float pow1n = pow_F(1.64f - pow_F(0.29f, nj), 0.73f);
+ const float coe = pow_F(fl, 0.25f);
+ const float QproFactor = (0.4f / c) * (aw + 4.0f) ;
#ifdef __SSE2__
int bufferLength = ((width + 3) / 4) * 4; // bufferLength has to be a multiple of 4
@@ -2231,7 +2448,21 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab)
spro = s;
/*
*/
-
+ if(ciec) {
+ Jpro = CAMBrightCurveJ[Jpro * 327.68f]; //CIECAM02 + contrast
+ float sres;
+ float rstprotection = 50.f;//arbitrary 50% protection skin tones
+ float Sp = spro / 100.0f;
+ float parsat = 1.5f; //parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation)
+ Ciecam02::curvecolorfloat(schr, Sp, sres, parsat);
+ float dred = 100.f; // in C mode
+ float protect_red = 80.0f; // in C mode
+ dred = 100.0f * sqrtf((dred * coe) / Qpro);
+ protect_red = 100.0f * sqrtf((protect_red * coe) / Qpro);
+ Color::skinredfloat(Jpro, hpro, sres, Sp, dred, protect_red, 0, rstprotection, 100.f, spro);
+ Qpro = QproFactor * sqrtf(Jpro);
+ Cpro = (spro * spro * Qpro) / (10000.0f);
+ }
//retrieve values C,J...s
C = Cpro;
@@ -2409,10 +2640,14 @@ void ImProcFunctions::softprocess(const LabImage* bufcolorig, array2D &bu
void ImProcFunctions::exlabLocal(local_params& lp, int bfh, int bfw, int bfhr, int bfwr, LabImage* bufexporig, LabImage* lab, const LUTf& hltonecurve, const LUTf& shtonecurve, const LUTf& tonecurve, const float hueref, const float lumaref, const float chromaref)
{
- BENCHFUN
+ //BENCHFUN
//exposure local
constexpr float maxran = 65536.f;
+ if(lp.laplacexp == 0.f) {
+ lp.linear = 0.f;
+ }
+
const float linear = lp.linear;
int bw = bfw;
int bh = bfh;
@@ -3401,6 +3636,13 @@ void ImProcFunctions::deltaEforMask(float **rdE, int bfw, int bfh, LabImage* buf
static void showmask(int lumask, const local_params& lp, int xstart, int ystart, int cx, int cy, int bfw, int bfh, LabImage* bufexporig, LabImage* transformed, LabImage* bufmaskorigSH, int inv)
{
+ float lum = fabs(lumask * 400.f);
+ float colo = 0.f;
+ if(lumask < 0.f) {
+ lum *= 1.4f;
+ colo = 30000.f + 12.f * lum;
+ }
+
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16)
#endif
@@ -3421,24 +3663,25 @@ static void showmask(int lumask, const local_params& lp, int xstart, int ystart,
if (inv == 0) {
if (zone > 0) {//normal
- transformed->L[y + ystart][x + xstart] = (lumask * 400.f) + clipLoc(bufmaskorigSH->L[y][x]);
+ transformed->L[y + ystart][x + xstart] = (lum) + clipLoc(bufmaskorigSH->L[y][x]);
transformed->a[y + ystart][x + xstart] = bufexporig->a[y][x] * bufmaskorigSH->a[y][x];
- transformed->b[y + ystart][x + xstart] = bufexporig->b[y][x] * bufmaskorigSH->b[y][x];
+ transformed->b[y + ystart][x + xstart] = (colo) + bufexporig->b[y][x] * bufmaskorigSH->b[y][x];
}
} else if (inv == 1) { //inverse
if (zone == 0) {
- transformed->L[y + ystart][x + xstart] = (lumask * 400.f) + clipLoc(bufmaskorigSH->L[y][x]);
+ transformed->L[y + ystart][x + xstart] = (lum) + clipLoc(bufmaskorigSH->L[y][x]);
transformed->a[y + ystart][x + xstart] = bufexporig->a[y][x] * bufmaskorigSH->a[y][x];
- transformed->b[y + ystart][x + xstart] = bufexporig->b[y][x] * bufmaskorigSH->b[y][x];
+ transformed->b[y + ystart][x + xstart] = (colo) + bufexporig->b[y][x] * bufmaskorigSH->b[y][x];
}
}
+
}
}
}
void ImProcFunctions::discrete_laplacian_threshold(float * data_out, const float * data_in, size_t nx, size_t ny, float t)
{
- BENCHFUN
+ // BENCHFUN
if (!data_in || !data_out) {
fprintf(stderr, "a pointer is NULL and should not be so\n");
@@ -3525,7 +3768,7 @@ void ImProcFunctions::rex_poisson_dct(float * data, size_t nx, size_t ny, double
* @author Nicolas Limare
* some adaptations for Rawtherapee
*/
- BENCHFUN
+ // BENCHFUN
/*
* get the cosinus tables
@@ -3639,7 +3882,7 @@ void ImProcFunctions::retinex_pde(const float * datain, float * dataout, int bfw
* adapted for Rawtherapee by Jacques Desmis 6-2019
*/
- BENCHFUN
+ // BENCHFUN
#ifdef RT_FFTW3F_OMP
if (multiThread) {
fftwf_init_threads();
@@ -3789,7 +4032,7 @@ void ImProcFunctions::maskcalccol(bool invmask, bool pde, int bfw, int bfh, int
const LocCCmaskCurve & locccmasCurve, bool lcmasutili,
const LocLLmaskCurve & locllmasCurve, bool llmasutili,
const LocHHmaskCurve & lochhmasCurve, bool lhmasutili, const LocHHmaskCurve & lochhhmasCurve, bool lhhmasutili,
- bool multiThread, bool enaMask, bool showmaske, bool deltaE, bool modmask, bool zero, bool modif, float chrom, float rad, float lap, float gamma, float slope, float blendm, float blendmab, int shado, float amountcd, float anchorcd,
+ bool multiThread, bool enaMask, bool showmaske, bool deltaE, bool modmask, bool zero, bool modif, float chrom, float rad, float lap, float gamma, float slope, float blendm, float blendmab, int shado, int highl, float amountcd, float anchorcd,
const LUTf& lmasklocalcurve, bool localmaskutili,
const LocwavCurve & loclmasCurvecolwav, bool lmasutilicolwav, int level_bl, int level_hl, int level_br, int level_hr,
int shortcu, bool delt, const float hueref, const float chromaref, const float lumaref,
@@ -4086,7 +4329,6 @@ void ImProcFunctions::maskcalccol(bool invmask, bool pde, int bfw, int bfh, int
if (strumask > 0.f && astool) {
-
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
@@ -4111,6 +4353,10 @@ void ImProcFunctions::maskcalccol(bool invmask, bool pde, int bfw, int bfh, int
ImProcFunctions::shadowsHighlights(bufmaskblurcol, true, 1, 0, shado, 40, sk, 0, 60);
}
+ if (highl > 0) {
+ ImProcFunctions::shadowsHighlights(bufmaskblurcol, true, 1, highl, 0, 40, sk, 50, 0);
+ }
+
int wavelet_level = level_br;
int minwin = rtengine::min(bfw, bfh);
@@ -4503,7 +4749,7 @@ void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueref, co
void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, const float hueref, const float chromaref, const float lumaref, local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk)
{
- BENCHFUN
+ //BENCHFUN
const float ach = lp.trans / 100.f;
const float varsens = senstype == 1 ? lp.senslc : lp.senssha;
const bool sharshow = (lp.showmasksharmet == 1);
@@ -4627,7 +4873,8 @@ void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, const
void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromaref, float lumaref, float sobelref, float meansobel, const struct local_params & lp, const LabImage * original, LabImage * transformed, const LabImage * rsv, const LabImage * reserv, int cx, int cy, int sk)
{
- BENCHFUN {
+ // BENCHFUN
+ {
const float ach = lp.trans / 100.f;
const float varsens = lp.sensexclu;
const float mindE = 2.f + MINSCOPE * varsens * lp.thr;
@@ -4766,7 +5013,8 @@ void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromar
void ImProcFunctions::transit_shapedetect_retinex(int call, int senstype, LabImage * bufexporig, LabImage * bufmask, LabImage * buforigmas, float **buflight, float **bufchro, const float hueref, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk)
{
- BENCHFUN {
+ //BENCHFUN
+ {
const int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
const int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
const int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
@@ -4981,7 +5229,7 @@ void ImProcFunctions::transit_shapedetect_retinex(int call, int senstype, LabIma
void ImProcFunctions::transit_shapedetect(int senstype, const LabImage * bufexporig, LabImage * originalmask, float **bufchro, bool HHutili, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk)
{
- BENCHFUN
+ // BENCHFUN
const int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
const int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
const int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
@@ -5888,7 +6136,7 @@ void optfft(int N_fftwsize, int &bfh, int &bfw, int &bfhr, int &bfwr, struct loc
void ImProcFunctions::BlurNoise_Local(LabImage *tmp1, LabImage * originalmask, float **bufchro, const float hueref, const float chromaref, const float lumaref, local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk)
{
//local BLUR
- BENCHFUN
+ //BENCHFUN
const int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
const int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
@@ -6379,7 +6627,7 @@ void ImProcFunctions::exposure_pde(float * dataor, float * datain, float * datao
*/
{
- BENCHFUN
+ //BENCHFUN
#ifdef RT_FFTW3F_OMP
if (multiThread) {
fftwf_init_threads();
@@ -6464,7 +6712,7 @@ void ImProcFunctions::fftw_convol_blur(float * input, float * output, int bfw, i
** you can enabled or disabled this function with rtsettings.fftwsigma in options. By default empirical formula is disabled
** in fact no importance....if it is this function (for sigma) or another... we are not in research :)
*/
- BENCHFUN
+ //BENCHFUN
#ifdef RT_FFTW3F_OMP
if (multiThread) {
@@ -6642,7 +6890,7 @@ void ImProcFunctions::fftw_convol_blur2(float **input2, float **output2, int bfw
void ImProcFunctions::fftw_tile_blur(int GW, int GH, int tilssize, int max_numblox_W, int min_numblox_W, float **tmp1, int numThreads, double radius)
{
- BENCHFUN
+ //BENCHFUN
float epsil = 0.001f / (tilssize * tilssize);
fftwf_plan plan_forward_blox[2];
fftwf_plan plan_backward_blox[2];
@@ -7052,7 +7300,7 @@ void ImProcFunctions::wavcont(const struct local_params& lp, float ** tmp, wavel
const LocwavCurve & loccomprewavCurve, bool loccomprewavutili,
float radlevblur, int process, float chromablu, float thres, float sigmadc, float deltad)
{
- BENCHFUN
+ //BENCHFUN
const int W_L = wdspot.level_W(0);
const int H_L = wdspot.level_H(0);
@@ -7265,7 +7513,7 @@ void ImProcFunctions::wavcontrast4(struct local_params& lp, float ** tmp, float
const LocwavCurve & locedgwavCurve, bool locedgwavutili,
float sigm, float offs, int & maxlvl, float sigmadc, float deltad, float chromalev, float chromablu, bool blurlc, bool blurena, bool levelena, bool comprena, bool compreena, float compress, float thres)
{
-BENCHFUN
+//BENCHFUN
std::unique_ptr wdspot(new wavelet_decomposition(tmp[0], bfw, bfh, maxlvl, 1, sk, numThreads, lp.daubLen));
//first decomposition for compress dynamic range positive values and other process
@@ -7940,7 +8188,7 @@ BENCHFUN
void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_numblox_W, float **tmp1, array2D *Lin, int numThreads, const struct local_params & lp, int chrom)
{
- BENCHFUN
+ // BENCHFUN
fftwf_plan plan_forward_blox[2];
fftwf_plan plan_backward_blox[2];
@@ -8380,7 +8628,7 @@ void ImProcFunctions::DeNoise(int call, int del, float * slidL, float * slida, f
}
}
- if ((lp.noiselc < 0.02f && aut == 0) || (mxsl < 1.f && (aut == 1 || aut == 2))) {
+ if ((lp.quamet == 0 && aut == 0) || (mxsl < 1.f && (aut == 1 || aut == 2))) {
WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads);
} else {
@@ -8670,7 +8918,7 @@ void ImProcFunctions::DeNoise(int call, int del, float * slidL, float * slida, f
float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0);
- if ((lp.noisecc < 2.f && aut == 0) || (maxccoarse < 0.1f && (aut == 1 || aut == 2))) {
+ if ((lp.quamet == 0 && aut == 0) || (maxccoarse < 0.1f && (aut == 1 || aut == 2))) {
WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads);
WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads);
} else {
@@ -8931,7 +9179,7 @@ void ImProcFunctions::DeNoise(int call, int del, float * slidL, float * slida, f
}
- if ((lp.noiselc < 0.02f && aut == 0) || (mxsl < 1.f && (aut == 1 || aut == 2))) {
+ if ((lp.quamet == 0 && aut == 0) || (mxsl < 1.f && (aut == 1 || aut == 2))) {
WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads);
} else {
WaveletDenoiseAll_BiShrinkL(Ldecomp, noisevarlum, madL, vari, edge, numThreads);
@@ -9217,7 +9465,7 @@ void ImProcFunctions::DeNoise(int call, int del, float * slidL, float * slida, f
float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0);
- if ((lp.noisecc < 0.02f && aut == 0) || (maxccoarse < 0.1f && (aut == 1 || aut == 2))) {
+ if ((lp.quamet == 0 && aut == 0) || (maxccoarse < 0.1f && (aut == 1 || aut == 2))) {
WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads);
WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads);
} else {
@@ -9521,7 +9769,7 @@ void ImProcFunctions::Lab_Local(
return;
}
- BENCHFUN
+ //BENCHFUN
constexpr int del = 3; // to avoid crash with [loy - begy] and [lox - begx] and bfh bfw // with gtk2 [loy - begy-1] [lox - begx -1 ] and del = 1
struct local_params lp;
@@ -9640,6 +9888,9 @@ void ImProcFunctions::Lab_Local(
log_encode(tmpImage.get(), lp, multiThread, bfw, bfh);
rgb2lab(*(tmpImage.get()), *bufexpfin, params->icm.workingProfile);
tmpImage.reset();
+ if (params->locallab.spots.at(sp).ciecam) {
+ ImProcFunctions::ciecamloc_02float(sp, bufexpfin.get(), 1);
+ }
//here begin graduated filter
//first solution "easy" but we can do other with log_encode...to see the results
@@ -9676,7 +9927,6 @@ void ImProcFunctions::Lab_Local(
bool blurz = false;
bool delt = params->locallab.spots.at(sp).deltae;
- bool astool = params->locallab.spots.at(sp).toolbl;
if (((radius > 1.5 * GAUSS_SKIP) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 1 || lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) && lp.blurena) {
blurz = true;
@@ -9684,8 +9934,9 @@ void ImProcFunctions::Lab_Local(
const int GW = transformed->W;
const int GH = transformed->H;
+ const std::unique_ptr bufblorig(new LabImage(GW, GH));
- LabImage * originalmaskbl = nullptr;
+ std::unique_ptr originalmaskbl;
std::unique_ptr bufmaskorigbl;
std::unique_ptr bufmaskblurbl;
std::unique_ptr bufgb;
@@ -9693,389 +9944,99 @@ void ImProcFunctions::Lab_Local(
if (denoiz || blurz || lp.denoiena || lp.blurena) {
bufgb.reset(new LabImage(GW, GH));
-
- if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) {
- bufmaskorigbl.reset(new LabImage(GW, GH));
- bufmaskblurbl.reset(new LabImage(GW, GH));
- originalmaskbl = new LabImage(GW, GH);
- }
-
- array2D ble(GW, GH);
- array2D blechro(GW, GH);
- array2D hue(GW, GH);
- array2D guid(GW, GH);
- float meanfab, fab;
- mean_fab(0, 0, GW, GH, bufgb.get(), original, fab, meanfab, lp.chromabl, multiThread);
- float chromult = 1.f - 0.01f * lp.chromabl;
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int y = 0; y < GH; y++) {
- for (int x = 0; x < GW; x++) {
- bufgb->L[y][x] = original->L[y][x];
- bufgb->a[y][x] = original->a[y][x];
- bufgb->b[y][x] = original->b[y][x];
- }
- }
-
- const float strumask = 0.02f * params->locallab.spots.at(sp).strumaskbl;
- JaggedArray blendstru(GW, GH);
-
- if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) {
- if (strumask > 0.f) {
- float delstrumask = 4.1f - strumask;//4.1 = 2 * max slider strumask + 0.1
- buildBlendMask(bufgb->L, blendstru, GW, GH, delstrumask);
- const float radblur = 0.02f * 0.1f * std::fabs(lp.radmabl);
- const float rm = radblur / sk;
-
- if (rm > 0) {
-#ifdef _OPENMP
- #pragma omp parallel if (multiThread)
-#endif
- {
- gaussianBlur(blendstru, blendstru, GW, GH, rm);
- }
- }
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < GH; ir++) {
- for (int jr = 0; jr < GW; jr++) {
- float kmaskLexp = 0.f;
- float kmaskCH = 0.f;
- float kmasstru = 0.f;
-
- if (strumask > 0.f && !astool) {
- kmasstru = bufgb->L[ir][jr] * blendstru[ir][jr];
- }
-
- if (locllmasblCurve && llmasblutili) {
- const float ligh = bufgb->L[ir][jr] / 32768.f;
- kmaskLexp = 32768.f * LIM01(1.f - locllmasblCurve[500.f * ligh]);
- }
-
- if (lp.showmaskblmet != 4) {
- if (locccmasblCurve && lcmasblutili) {
- const float chromask = 0.0001f + std::sqrt(SQR((bufgb->a[ir][jr]) / fab) + SQR((bufgb->b[ir][jr]) / fab));
- kmaskCH = LIM01(1.f - locccmasblCurve[500.f * chromask]);
- }
- }
-
- if (lochhmasblCurve && lhmasblutili) {
- const float huema = xatan2f(bufgb->b[ir][jr], bufgb->a[ir][jr]);
- float h = Color::huelab_to_huehsv2(huema);
- h += 1.f / 6.f;
-
- if (h > 1.f) {
- h -= 1.f;
- }
-
- const float valHH = LIM01(1.f - lochhmasblCurve[500.f * h]);
-
- if (lp.showmaskblmet != 4) {
- kmaskCH += chromult * valHH;
- }
-
- kmaskLexp += 32768.f * valHH;
- }
-
- bufmaskblurbl->L[ir][jr] = clipLoc(kmaskLexp + kmasstru);
- bufmaskblurbl->a[ir][jr] = kmaskCH;
- bufmaskblurbl->b[ir][jr] = kmaskCH;
- ble[ir][jr] = bufmaskblurbl->L[ir][jr] / 32768.f;
- hue[ir][jr] = xatan2f(bufmaskblurbl->b[ir][jr], bufmaskblurbl->a[ir][jr]);
- const float chromah = std::sqrt(SQR(bufmaskblurbl->b[ir][jr]) + SQR(bufmaskblurbl->a[ir][jr]));
- blechro[ir][jr] = chromah / 32768.f;
- guid[ir][jr] = Color::L2Y(bufgb->L[ir][jr]) / 32768.f;
- }
- }
-
- const std::unique_ptr bufprov(new LabImage(GW, GH));
-
- bufprov->CopyFrom(bufmaskblurbl.get(), multiThread);
-
- if (lp.radmabl != 0.f) {
- float blur = lp.radmabl;
- blur = blur < 0.f ? -1.f / blur : 1.f + blur;
- const int r1 = rtengine::max(4 / sk * blur + 0.5f, 1);
- const int r2 = rtengine::max(25 / sk * blur + 0.5f, 1);
-
- constexpr float epsilmax = 0.005f;
- constexpr float epsilmin = 0.00001f;
-
- const float aepsil = (epsilmax - epsilmin) / 100.f;
- const float bepsil = epsilmin; //epsilmax - 100.f * aepsil;
- const float epsil = lp.radmabl < 0.f ? 0.001f : aepsil * lp.radmabl + bepsil;
-
- rtengine::guidedFilter(guid, blechro, blechro, r1, epsil, multiThread);
- rtengine::guidedFilter(guid, ble, ble, r2, 0.2 * epsil, multiThread);
-
- // guidedFilter(guid, ble, ble, lp.radmabl * 10.f / sk, 0.001, multiThread, 4);
- }
-
- LUTf lutTonemaskbl(65536);
- calcGammaLut(lp.gammabl, lp.slomabl, lutTonemaskbl);
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < GH; ir++) {
- for (int jr = 0; jr < GW; jr++) {
- const float2 sincosval = xsincosf(hue[ir][jr]);
- bufmaskblurbl->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f;
- const float L_ = 2.f * bufmaskblurbl->L[ir][jr];
- bufmaskblurbl->L[ir][jr] = lutTonemaskbl[L_];
- bufmaskblurbl->a[ir][jr] = 32768.f * sincosval.y * blechro[ir][jr];
- bufmaskblurbl->b[ir][jr] = 32768.f * sincosval.x * blechro[ir][jr];
- }
- }
- }
-
- if (strumask > 0.f && astool && (lp.enablMask || lp.showmaskblmet == 3)) {
-
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < GH; ir++) {
- for (int jr = 0; jr < GW; jr++) {
- bufmaskblurbl->L[ir][jr] *= (1.f + blendstru[ir][jr]);
- }
- }
- }
-
- if (lmaskbllocalcurve && localmaskblutili && (lp.enablMask || lp.showmaskblmet == 3)) {
-#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < GH; ir++)
- for (int jr = 0; jr < GW; jr++) {
- bufmaskblurbl->L[ir][jr] = 0.5f * lmaskbllocalcurve[2.f * bufmaskblurbl->L[ir][jr]];
- }
- }
-
- const int highli = params->locallab.spots.at(sp).shadmaskbl;
-
- if (highli > 0 && (lp.enablMask || lp.showmaskblmet == 3)) {
- ImProcFunctions::shadowsHighlights(bufmaskblurbl.get(), true, 1, highli, 0, 40, sk, 50, 0);
- }
-
- const int shado = params->locallab.spots.at(sp).shadmaskblsha;
-
- if (shado > 0 && (lp.enablMask || lp.showmaskblmet == 3)) {
- ImProcFunctions::shadowsHighlights(bufmaskblurbl.get(), true, 1, 0, shado, 40, sk, 0, 60);
- }
-
- int wavelet_level = params->locallab.spots.at(sp).shadmaskbl;
- int maxlvl = wavelet_level;
-
- int minwin = rtengine::min(GW, GH);
- int maxlevelspot = 9;
-
- while ((1 << maxlevelspot) >= (minwin * sk) && maxlevelspot > 1) {
- --maxlevelspot ;
- }
-
- wavelet_level = rtengine::min(wavelet_level, maxlevelspot);
- bool wavcurvemask = false;
-
- if (loclmasCurveblwav && lmasutiliblwav && (lp.enablMask || lp.showmaskblmet == 3)) {
- for (int i = 0; i < 500; i++) {
- if (loclmasCurveblwav[i] != 0.5) {
- wavcurvemask = true;
- }
- }
- }
-
- if (wavcurvemask && (lp.enablMask || lp.showmaskblmet == 3)) {
- const int level_bl = params->locallab.spots.at(sp).csthresholdblur.getBottomLeft();
- const int level_hl = params->locallab.spots.at(sp).csthresholdblur.getTopLeft();
- const int level_br = params->locallab.spots.at(sp).csthresholdblur.getBottomRight();
- const int level_hr = params->locallab.spots.at(sp).csthresholdblur.getTopRight();
-
-#ifdef _OPENMP
- const int numThreads = omp_get_max_threads();
-#else
- const int numThreads = 1;
-
-#endif
-
- wavelet_decomposition *wdspotbl = new wavelet_decomposition(bufmaskblurbl->L[0], GW, GH, maxlvl, 1, sk, numThreads, lp.daubLen);
- if (wdspotbl->memory_allocation_failed()) {
- return;
- }
-
-
- float mean[10];
- float meanN[10];
- float sigma[10];
- float sigmaN[10];
- float MaxP[10];
- float MaxN[10];
-
- Evaluate2(*wdspotbl, mean, meanN, sigma, sigmaN, MaxP, MaxN, numThreads);
- float alow = 1.f;
- float blow = 0.f;
- if (level_hl != level_bl) {
- alow = 1.f / (level_hl - level_bl);
- blow = -alow * level_bl;
- }
- float ahigh = 1.f;
- float bhigh = 0.f;
-
- if (level_hr != level_br) {
- ahigh = 1.f / (level_hr - level_br);
- bhigh = -ahigh * level_br;
+ if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) {
+ bufmaskorigbl.reset(new LabImage(GW, GH));
+ bufmaskblurbl.reset(new LabImage(GW, GH, true));
+ originalmaskbl.reset (new LabImage(GW, GH));
}
-
- for (int dir = 1; dir < 4; dir++) {
- for (int level = level_bl; level < maxlvl; ++level) {
- int W_L = wdspotbl->level_W(level);
- int H_L = wdspotbl->level_H(level);
- float* const *wav_L = wdspotbl->level_coeffs(level);
-
- if (MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) {
- 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 inx = log(insigma);
- float iny = log(rapX);
- float rap = inx / iny; //koef
- float asig = 0.166f / (sigma[level]);
- float bsig = 0.5f - asig * mean[level];
- float amean = 0.5f / mean[level];
-
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
- for (int i = 0; i < W_L * H_L; i++) {
- if(loclmasCurveblwav && lmasutiliblwav) {
- float absciss;
- float &val = wav_L[dir][i];
-
- if (fabsf(val) >= (mean[level] + sigma[level])) { //for max
- float valcour = xlogf(fabsf(val));
- float valc = valcour - logmax;
- float vald = valc * rap;
- absciss = xexpf(vald);
- } else if (fabsf(val) >= mean[level]) {
- absciss = asig * fabsf(val) + bsig;
- } else {
- absciss = amean * fabsf(val);
- }
-
- float klev = 1.f;
- if (level >= level_hl && level <= level_hr) {
- klev = 1.f;
- }
- if (level_hl != level_bl) {
- if (level >= level_bl && level < level_hl) {
- klev = alow * level + blow;
- }
- }
-
- if (level_hr != level_br) {
- if (level > level_hr && level <= level_br) {
- klev = ahigh * level + bhigh;
- }
- }
- float kc = klev * (loclmasCurveblwav[absciss * 500.f] - 0.5f);
- float amplieffect = kc <= 0.f ? 1.f : 4.f;
-
- float kinterm = 1.f + amplieffect * kc;
- kinterm = kinterm <= 0.f ? 0.01f : kinterm;
-
- val *= kinterm;
-
- }
- }
- }
-
- }
- }
- wdspotbl->reconstruct(bufmaskblurbl->L[0], 1.f);
- delete wdspotbl;
-
- }
-
-
- // deltae Mask with scope
- int sco = params->locallab.spots.at(sp).scopemask;
- const float mindE = 2.f + MINSCOPE * sco * lp.thr;
- const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
- const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
- const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
-
- if (delt && lp.blurmet == 0 && (lp.enablMask || lp.showmaskblmet == 3)) {
- JaggedArray rdE(GW, GH);
- deltaEforMask(rdE, GW, GH, bufgb.get(), hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, lp.balance, lp.balanceh);
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
-#endif
- for (int ir = 0; ir < GH; ir++) {
- for (int jr = 0; jr < GW; jr++) {
- bufmaskblurbl->L[ir][jr] = bufprov->L[ir][jr] + rdE[ir][jr] * (bufmaskblurbl->L[ir][jr] - bufprov->L[ir][jr]);
- bufmaskblurbl->a[ir][jr] = bufprov->a[ir][jr] + rdE[ir][jr] * (bufmaskblurbl->a[ir][jr] - bufprov->a[ir][jr]);
- bufmaskblurbl->b[ir][jr] = bufprov->b[ir][jr] + rdE[ir][jr] * (bufmaskblurbl->b[ir][jr] - bufprov->b[ir][jr]);
- }
- }
- }
-
- const float lap = params->locallab.spots.at(sp).lapmaskbl;
- const bool pde = params->locallab.spots.at(sp).laplac;
- const float lumask = params->locallab.spots.at(sp).lumask;
-
- if (lap > 0.f && (lp.enablMask || lp.showmaskblmet == 3)) {
- const float *datain = bufmaskblurbl->L[0];
- const std::unique_ptr data_tmp(new float[GH * GW]);
-
- if (!pde) {
- ImProcFunctions::discrete_laplacian_threshold(data_tmp.get(), datain, GW, GH, 200.f * lap);
- } else {
- ImProcFunctions::retinex_pde(datain, data_tmp.get(), GW, GH, 12.f * lap, 1.f, nullptr, 0, 0, 1);
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
#endif
for (int y = 0; y < GH; y++) {
for (int x = 0; x < GW; x++) {
- bufmaskblurbl->L[y][x] = data_tmp[y * GW + x];
+ bufblorig->L[y][x] = original->L[y][x];
}
}
- }
- const float radiusb = 1.f / sk;
+ int inv = 0;
+ bool showmaske = false;
+ bool enaMask = false;
+ bool deltaE = false;
+ bool modmask = false;
+ bool zero = false;
+ bool modif = false;
- if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) {
- const int invers = lp.blurmet == 1 ? 1 : 0;
-
-#ifdef _OPENMP
- #pragma omp parallel if (multiThread)
-#endif
- {
- gaussianBlur(bufmaskblurbl->L, bufmaskorigbl->L, GW, GH, radiusb);
- gaussianBlur(bufmaskblurbl->a, bufmaskorigbl->a, GW, GH, 1.f + (0.005f * lp.radmabl) / sk);
- gaussianBlur(bufmaskblurbl->b, bufmaskorigbl->b, GW, GH, 1.f + (0.005f * lp.radmabl) / sk);
+ if (lp.showmaskblmet == 3) {
+ showmaske = true;
}
- if (lp.showmaskblmet == 0 || lp.showmaskblmet == 1 || lp.showmaskblmet == 2 || lp.showmaskblmet == 4 || lp.enablMask) {
- blendmask(lp, 0, 0, cx, cy, GW, GH, bufgb.get(), original, bufmaskorigbl.get(), originalmaskbl, lp.blendmabl, lp.blendmabl, invers);
- } else if (lp.showmaskblmet == 3) {
- showmask(lumask, lp, 0, 0, cx, cy, GW, GH, bufgb.get(), transformed, bufmaskorigbl.get(), invers);
- return;
+ if (lp.enablMask) {
+ enaMask = true;
+ }
+
+ if (lp.showmaskblmet == 4) {
+ deltaE = true;
+ }
+
+ if (lp.showmaskblmet == 2) {
+ modmask = true;
+ }
+
+ if (lp.showmaskblmet == 1) {
+ modif = true;
+ }
+
+ if (lp.showmaskblmet == 0) {
+ zero = true;
+ }
+
+ float chrom = lp.chromabl;
+ float rad = lp.radmabl;
+ float gamma = lp.gammabl;
+ float slope = lp.slomabl;
+ float blendm = lp.blendmabl;
+ float lap = params->locallab.spots.at(sp).lapmaskbl;
+ bool pde = params->locallab.spots.at(sp).laplac;
+ LocwavCurve dummy;
+ bool delt = params->locallab.spots.at(sp).deltae;
+ int lumask = params->locallab.spots.at(sp).lumask;
+ int sco = params->locallab.spots.at(sp).scopemask;
+ int shortcu = 0;
+
+ const float mindE = 2.f + MINSCOPE * sco * lp.thr;
+ const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr);
+ const float mindElim = 2.f + MINSCOPE * limscope * lp.thr;
+ const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
+ const int shado = params->locallab.spots.at(sp).shadmaskblsha;
+ const int highl = params->locallab.spots.at(sp).shadmaskbl;
+ constexpr float amountcd = 0.f;
+ constexpr float anchorcd = 50.f;
+ LocHHmaskCurve lochhhmasCurve;
+ constexpr bool lhhmasutili = false;
+ const float strumask = 0.02f * params->locallab.spots.at(sp).strumaskbl;
+ bool astool = params->locallab.spots.at(sp).toolbl;
+
+ maskcalccol(false, pde, GW, GH, 0, 0, sk, cx, cy, bufblorig.get(), bufmaskblurbl.get(), originalmaskbl.get(), original, reserved, inv, lp,
+ strumask, astool,
+ locccmasblCurve, lcmasblutili, locllmasblCurve, llmasblutili, lochhmasblCurve, lhmasblutili, lochhhmasCurve, lhhmasutili, multiThread,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmaskbllocalcurve, localmaskblutili, loclmasCurveblwav, lmasutiliblwav, 1, 1, 5, 5,
+ shortcu, delt, hueref, chromaref, lumaref,
+ maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, 0
+ );
+
+ if (lp.showmaskblmet == 3) {
+ showmask(lumask, lp, 0, 0, cx, cy, GW, GH, bufblorig.get(), transformed, bufmaskblurbl.get(), inv);
+ return;
}
- }
-//end mask
}
bool execmaskblur = (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) && lp.smasktyp != 1;
- if (((radius > 1.5 * GAUSS_SKIP && lp.rad > 1.6) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 0 || execmaskblur) && lp.blurena) { // radius < GAUSS_SKIP means no gauss, just copy of original image
+ int strengr = params->locallab.spots.at(sp).strengr;
+
+ if (((radius > 1.5 * GAUSS_SKIP && lp.rad > 1.6) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 0 || strengr > 0 || execmaskblur) && lp.blurena) { // radius < GAUSS_SKIP means no gauss, just copy of original image
// if (((radius > 1.5 * GAUSS_SKIP && lp.rad > 1.6) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 0 || lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) && lp.blurena) { // radius < GAUSS_SKIP means no gauss, just copy of original image
std::unique_ptr tmp1;
std::unique_ptr tmp2;
@@ -10090,8 +10051,7 @@ void ImProcFunctions::Lab_Local(
bool fft = params->locallab.spots.at(sp).fftwbl;
int isogr = params->locallab.spots.at(sp).isogr;
- int strengr = params->locallab.spots.at(sp).strengr;
- int scalegr = params->locallab.spots.at(sp).scalegr;
+ int scalegr = 100;//params->locallab.spots.at(sp).scalegr;
@@ -10544,7 +10504,7 @@ void ImProcFunctions::Lab_Local(
// BlurNoise_Local(tmp1.get(), originalmaskbl, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
if(lp.smasktyp != 1) {
- BlurNoise_Local(tmp1.get(), originalmaskbl, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
+ BlurNoise_Local(tmp1.get(), originalmaskbl.get(), bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
} else {
BlurNoise_Local(tmp1.get(), original, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
}
@@ -10557,7 +10517,7 @@ void ImProcFunctions::Lab_Local(
} else if (lp.blurmet == 1) {
// InverseBlurNoise_Local(originalmaskbl, bufchro, lp, hueref, chromaref, lumaref, original, transformed, tmp1.get(), cx, cy, sk);
if(lp.smasktyp != 1) {
- InverseBlurNoise_Local(originalmaskbl, bufchro, lp, hueref, chromaref, lumaref, original, transformed, tmp1.get(), cx, cy, sk);
+ InverseBlurNoise_Local(originalmaskbl.get(), bufchro, lp, hueref, chromaref, lumaref, original, transformed, tmp1.get(), cx, cy, sk);
} else {
InverseBlurNoise_Local(original, bufchro, lp, hueref, chromaref, lumaref, original, transformed, tmp1.get(), cx, cy, sk);
}
@@ -10612,7 +10572,7 @@ void ImProcFunctions::Lab_Local(
ImProcFunctions::impulse_nr(bufwv.get(), threshold);
}
- DeNoise_Local(call, lp, originalmaskbl, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *(bufwv.get()), cx, cy, sk);
+ DeNoise_Local(call, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *(bufwv.get()), cx, cy, sk);
if (params->locallab.spots.at(sp).recurs) {
original->CopyFrom(transformed, multiThread);
@@ -10628,7 +10588,7 @@ void ImProcFunctions::Lab_Local(
float slida[8] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
float slidb[8] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
constexpr int aut = 0;
- DeNoise(call, del, slidL, slida, slidb, aut, noiscfactiv, lp, originalmaskbl, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, cx, cy, sk);
+ DeNoise(call, del, slidL, slida, slidb, aut, noiscfactiv, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, cx, cy, sk);
if (params->locallab.spots.at(sp).recurs) {
original->CopyFrom(transformed, multiThread);
@@ -10637,9 +10597,6 @@ void ImProcFunctions::Lab_Local(
}
}
- if (denoiz || blurz || lp.denoiena || lp.blurena) {
- delete originalmaskbl;
- }
//begin cbdl
if ((lp.mulloc[0] != 1.f || lp.mulloc[1] != 1.f || lp.mulloc[2] != 1.f || lp.mulloc[3] != 1.f || lp.mulloc[4] != 1.f || lp.mulloc[5] != 1.f || lp.clarityml != 0.f || lp.contresid != 0.f || lp.enacbMask || lp.showmaskcbmet == 2 || lp.showmaskcbmet == 3 || lp.showmaskcbmet == 4 || lp.prevdE) && lp.cbdlena) {
@@ -10729,10 +10686,11 @@ void ImProcFunctions::Lab_Local(
int shortcu = 0; //lp.mergemet; //params->locallab.spots.at(sp).shortc;
LocHHmaskCurve lochhhmasCurve;
bool lhhmasutili = false;
+ const int highl = 0;
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, loctemp.get(), bufmaskorigcb.get(), originalmaskcb.get(), original, reserved, inv, lp,
0.f, false,
locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmaskcblocalcurve, localmaskcbutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmaskcblocalcurve, localmaskcbutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.0f, 0.f, -1
);
@@ -10944,11 +10902,12 @@ void ImProcFunctions::Lab_Local(
bool lhhmasutili = false;
float amountcd = 0.f;
float anchorcd = 50.f;
+ const int highl = 0;
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufexporig.get(), bufmaskorigvib.get(), originalmaskvib.get(), original, reserved, inv, lp,
0.f, false,
locccmasvibCurve, lcmasvibutili, locllmasvibCurve, llmasvibutili, lochhmasvibCurve, lhmasvibutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmaskviblocalcurve, localmaskvibutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmaskviblocalcurve, localmaskvibutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
);
@@ -11055,7 +11014,7 @@ void ImProcFunctions::Lab_Local(
ImProcFunctions::vibrance(bufexpfin.get(), vibranceParams, params->toneCurve.hrenabled, params->icm.workingProfile);
if (params->locallab.spots.at(sp).warm != 0) {
- ImProcFunctions::ciecamloc_02float(sp, bufexpfin.get());
+ ImProcFunctions::ciecamloc_02float(sp, bufexpfin.get(), 2);
}
@@ -11175,11 +11134,12 @@ void ImProcFunctions::Lab_Local(
float anchorcd = 50.f;
LocHHmaskCurve lochhhmasCurve;
bool lhhmasutili = false;
+ const int highl = 0;
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufgbm.get(), bufmaskorigtm.get(), originalmasktm.get(), original, reserved, inv, lp,
0.f, false,
locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
);
@@ -11216,11 +11176,12 @@ void ImProcFunctions::Lab_Local(
float anchorcd = 50.f;
LocHHmaskCurve lochhhmasCurve;
bool lhhmasutili = false;
+ const int highl = 0;
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, tmp1.get(), bufmaskorigtm.get(), originalmasktm.get(), original, reserved, inv, lp,
0.f, false,
locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
);
@@ -11307,12 +11268,14 @@ void ImProcFunctions::Lab_Local(
}
bool tonecurv = false;
+ const Glib::ustring profile = params->icm.workingProfile;
+ bool isworking = (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1");
- if (params->locallab.spots.at(sp).gamSH != 2.4 || params->locallab.spots.at(sp).sloSH != 12.92) {
+ if (isworking && (params->locallab.spots.at(sp).gamSH != 2.4 || params->locallab.spots.at(sp).sloSH != 12.92)) {
tonecurv = true;
}
- if (! lp.invsh && (lp.highlihs > 0.f || lp.shadowhs > 0.f || tonequ || tonecurv || lp.strSH != 0.f || lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3 || lp.showmaskSHmet == 4 || lp.prevdE) && call < 3 && lp.hsena) {
+ if (! lp.invsh && (lp.highlihs > 0.f || lp.shadowhs > 0.f || tonequ || tonecurv || lp.strSH != 0.f || lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3 || lp.showmaskSHmet == 4 || lp.prevdE) && call <= 3 && lp.hsena) {
const int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
const int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
const int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
@@ -11399,11 +11362,12 @@ void ImProcFunctions::Lab_Local(
int lumask = params->locallab.spots.at(sp).lumask;
LocHHmaskCurve lochhhmasCurve;
bool lhhmasutili = false;
+ const int highl = 0;
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufexporig.get(), bufmaskorigSH.get(), originalmaskSH.get(), original, reserved, inv, lp,
0.f, false,
locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmaskSHlocalcurve, localmaskSHutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmaskSHlocalcurve, localmaskSHutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
);
@@ -11550,11 +11514,12 @@ void ImProcFunctions::Lab_Local(
int lumask = params->locallab.spots.at(sp).lumask;
LocHHmaskCurve lochhhmasCurve;
bool lhhmasutili = false;
+ const int highl = 0;
maskcalccol(false, pde, GW, GH, 0, 0, sk, cx, cy, bufcolorig.get(), bufmaskblurcol.get(), originalmaskSH.get(), original, reserved, inv, lp,
0.f, false,
locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmaskSHlocalcurve, localmaskSHutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmaskSHlocalcurve, localmaskSHutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
);
@@ -11577,7 +11542,7 @@ void ImProcFunctions::Lab_Local(
}
// soft light and retinex_pde
- if (lp.strng > 0.f && call <= 3 && lp.sfena) {
+ if (lp.strng > 1.f && call <= 3 && lp.sfena) {
int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
int xstart = rtengine::max(static_cast(lp.xc - lp.lxL) - cx, 0);
@@ -11705,7 +11670,7 @@ void ImProcFunctions::Lab_Local(
}
}
- if ((lp.lcamount > 0.f || wavcurve || lp.showmasklcmet == 2 || lp.enalcMask || lp.showmasklcmet == 3 || lp.showmasklcmet == 4 || lp.prevdE || lp.strwav != 0.f || wavcurvelev || wavcurvecon || wavcurvecomp || wavcurvecompre || lp.edgwena || params->locallab.spots.at(sp).residblur > 0.f || params->locallab.spots.at(sp).levelblur > 0.f || params->locallab.spots.at(sp).residcont != 0.f || params->locallab.spots.at(sp).clarilres != 0.f || params->locallab.spots.at(sp).claricres != 0.f) && call < 3 && lp.lcena) {
+ if ((lp.lcamount > 0.f || wavcurve || lp.showmasklcmet == 2 || lp.enalcMask || lp.showmasklcmet == 3 || lp.showmasklcmet == 4 || lp.prevdE || lp.strwav != 0.f || wavcurvelev || wavcurvecon || wavcurvecomp || wavcurvecompre || lp.edgwena || params->locallab.spots.at(sp).residblur > 0.f || params->locallab.spots.at(sp).levelblur > 0.f || params->locallab.spots.at(sp).residcont != 0.f || params->locallab.spots.at(sp).clarilres != 0.f || params->locallab.spots.at(sp).claricres != 0.f) && call <= 3 && lp.lcena) {
int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
int yend = rtengine::min(static_cast(lp.yc + lp.ly) - cy, original->H);
@@ -11822,10 +11787,11 @@ void ImProcFunctions::Lab_Local(
int lumask = params->locallab.spots.at(sp).lumask;
LocHHmaskCurve lochhhmasCurve;
bool lhhmasutili = false;
+ const int highl = 0;
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufgb.get(), bufmaskoriglc.get(), originalmasklc.get(), original, reserved, inv, lp,
0.f, false,
locccmaslcCurve, lcmaslcutili, locllmaslcCurve, llmaslcutili, lochhmaslcCurve, lhmaslcutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmasklclocalcurve, localmasklcutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasklclocalcurve, localmasklcutili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, -1
);
@@ -12987,11 +12953,12 @@ void ImProcFunctions::Lab_Local(
int lumask = params->locallab.spots.at(sp).lumask;
LocHHmaskCurve lochhhmasCurve;
bool lhhmasutili = false;
+ const int highl = 0;
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufexporig.get(), bufmaskblurexp.get(), originalmaskexp.get(), original, reserved, inv, lp,
0.f, false,
locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmaskexplocalcurve, localmaskexputili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmaskexplocalcurve, localmaskexputili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, 0
);
@@ -13030,15 +12997,16 @@ void ImProcFunctions::Lab_Local(
}
if (lp.expcomp == 0.f) {
- lp.expcomp = 0.001f; // to enabled
+ lp.expcomp = 0.001f;// to enabled
}
ImProcFunctions::exlabLocal(lp, bfh, bfw, bfhr, bfwr, bufexpfin.get(), bufexpfin.get(), hltonecurveloc, shtonecurveloc, tonecurveloc, hueref, lumaref, chromaref);
} else {
-
- ImProcFunctions::exlabLocal(lp, bfh, bfw, bfhr, bfwr, bufexporig.get(), bufexpfin.get(), hltonecurveloc, shtonecurveloc, tonecurveloc, hueref, lumaref, chromaref);
+ if (lp.expcomp != 0.f || lp.laplacexp > 0.1f) {
+ ImProcFunctions::exlabLocal(lp, bfh, bfw, bfhr, bfwr, bufexporig.get(), bufexpfin.get(), hltonecurveloc, shtonecurveloc, tonecurveloc, hueref, lumaref, chromaref);
+ }
}
//gradient
@@ -13262,11 +13230,12 @@ void ImProcFunctions::Lab_Local(
constexpr float anchorcd = 50.f;
LocHHmaskCurve lochhhmasCurve;
constexpr bool lhhmasutili = false;
+ const int highl = 0;
maskcalccol(false, pde, GW, GH, 0, 0, sk, cx, cy, bufexporig.get(), bufmaskblurexp.get(), originalmaskexp.get(), original, reserved, inv, lp,
0.f, false,
locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmaskexplocalcurve, localmaskexputili, dummy, lmasutilicolwav, 1, 1, 5, 5,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmaskexplocalcurve, localmaskexputili, dummy, lmasutilicolwav, 1, 1, 5, 5,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, false, 0.f, 0.f, 0
);
@@ -13462,11 +13431,13 @@ void ImProcFunctions::Lab_Local(
const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
const float amountcd = 0.f;
const float anchorcd = 50.f;
+ const int highl = 0;
+ bool astool = params->locallab.spots.at(sp).toolcol;
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufcolorig.get(), bufmaskblurcol.get(), originalmaskcol.get(), original, reserved, inv, lp,
strumask, astool,
locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmasklocalcurve, localmaskutili, loclmasCurvecolwav, lmasutilicolwav,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasklocalcurve, localmaskutili, loclmasCurvecolwav, lmasutilicolwav,
level_bl, level_hl, level_br, level_hr,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, lp.fftColorMask, lp.blurcolmask, lp.contcolmask, -1
@@ -13687,7 +13658,7 @@ void ImProcFunctions::Lab_Local(
if (lochhCurve && HHcurve && lp.qualcurvemet != 0 && !ctoning) { // H=f(H)
const float chromat = std::sqrt(SQR(bufcolcalca) + SQR(bufcolcalcb));
const float hhforcurv = xatan2f(bufcolcalcb, bufcolcalca);
- const float valparam = float ((lochhCurve[500.f * Color::huelab_to_huehsv2(hhforcurv)] - 0.5f)); //get H=f(H)
+ const float valparam = 2.f * float ((lochhCurve[500.f * Color::huelab_to_huehsv2(hhforcurv)] - 0.5f)) + static_cast(hhforcurv);
float2 sincosval = xsincosf(valparam);
bufcolcalca = chromat * sincosval.y;
bufcolcalcb = chromat * sincosval.x;
@@ -14425,11 +14396,12 @@ void ImProcFunctions::Lab_Local(
const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
constexpr float amountcd = 0.f;
constexpr float anchorcd = 50.f;
+ const int highl = 0;
maskcalccol(false, pde, GW, GH, 0, 0, sk, cx, cy, bufcolorig.get(), bufmaskblurcol.get(), originalmaskcol.get(), original, reserved, inv, lp,
strumask, params->locallab.spots.at(sp).toolcol,
locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, lochhhmasCurve, lhhmasutili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, amountcd, anchorcd, lmasklocalcurve, localmaskutili, loclmasCurvecolwav, lmasutilicolwav,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendm, shado, highl, amountcd, anchorcd, lmasklocalcurve, localmaskutili, loclmasCurvecolwav, lmasutilicolwav,
level_bl, level_hl, level_br, level_hr,
shortcu, false, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, lp.fftColorMask, lp.blurcolmask, lp.contcolmask, -1
@@ -14545,11 +14517,13 @@ void ImProcFunctions::Lab_Local(
const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr);
const float amountcd = 0.f;
const float anchorcd = 50.f;
-
+ const int highl = 0;
+ bool astool = params->locallab.spots.at(sp).toolmask;
+
maskcalccol(false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufcolorig.get(), bufmaskblurcol.get(), originalmaskcol.get(), original, reserved, inv, lp,
strumask, astool,
locccmas_Curve, lcmas_utili, locllmas_Curve, llmas_utili, lochhmas_Curve, lhmas_utili, lochhhmas_Curve, lhhmas_utili, multiThread,
- enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendmab, shado, amountcd, anchorcd, lmasklocal_curve, localmask_utili, loclmasCurve_wav, lmasutili_wav,
+ enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, blendmab, shado, highl, amountcd, anchorcd, lmasklocal_curve, localmask_utili, loclmasCurve_wav, lmasutili_wav,
level_bl, level_hl, level_br, level_hr,
shortcu, delt, hueref, chromaref, lumaref,
maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, lp.fftma, lp.blurma, lp.contma, 12
diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc
index 8a1142c17..a18e616f7 100644
--- a/rtengine/iptransform.cc
+++ b/rtengine/iptransform.cc
@@ -454,7 +454,7 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src,
double cost = cos (params->rotate.degree * rtengine::RT_PI / 180.0);
double sint = sin (params->rotate.degree * rtengine::RT_PI / 180.0);
- double ascale = ascaleDef > 0 ? ascaleDef : (params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0);
+ double ascale = ascaleDef > 0 ? ascaleDef : (params->commonTrans.autofill && params->perspective.render ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0);
// auxiliary variables for perspective correction
// Simple.
@@ -1182,7 +1182,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I
p_projection_rotate, p_projection_shift_horiz,
p_projection_shift_vert, p_projection_scale);
- const double ascale = params->commonTrans.autofill ? getTransformAutoFill(oW, oH, pLCPMap) : 1.0;
+ const double ascale = params->commonTrans.autofill && params->perspective.render ? getTransformAutoFill(oW, oH, pLCPMap) : 1.0;
const bool darkening = (params->vignetting.amount <= 0.0);
const bool useLog = params->commonTrans.method == "log" && highQuality;
@@ -1471,7 +1471,8 @@ bool ImProcFunctions::needsPerspective () const
{
return ( (params->perspective.method == "simple") &&
(params->perspective.horizontal || params->perspective.vertical) )
- || ( (params->perspective.method == "camera_based") && (
+ || ( (params->perspective.method == "camera_based") &&
+ params->perspective.render && (
params->perspective.camera_pitch ||
params->perspective.camera_roll ||
params->perspective.camera_shift_horiz ||
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index 21fffb76c..fe6b7be29 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -80,7 +80,7 @@ struct cont_params {
float b_lsl, t_lsl, b_rsl, t_rsl;
float b_lhl, t_lhl, b_rhl, t_rhl;
float edg_low, edg_mean, edg_sd, edg_max;
- float lev0s, lev0n, lev1s, lev1n, lev2s, lev2n, lev3s, lev3n;
+ float lev0s, lev0n, lev1s, lev1n, lev2s, lev2n, lev3s, lev3n, lev4n, lev4t;
float b_lpast, t_lpast, b_rpast, t_rpast;
float b_lsat, t_lsat, b_rsat, t_rsat;
int rad;
@@ -96,6 +96,8 @@ struct cont_params {
bool opaRG;
bool edgcurv;
bool diagcurv;
+ bool denoicurv;
+ bool denoicurvh;
int CHmet;
int CHSLmet;
int EDmet;
@@ -118,6 +120,10 @@ struct cont_params {
float sigmaton;
float sigmacol;
float sigmadir;
+ int denmet;
+ int mixmet;
+ int quamet;
+ int slimet;
int ite;
int contmet;
bool opaW;
@@ -160,6 +166,13 @@ struct cont_params {
float b_low;
float rangeab;
float protab;
+ float sigmm;
+ float sigmm14;
+ float sigmm56;
+ float levden;
+ float thrden;
+ float limden;
+ int complex;
};
int wavNestedLevels = 1;
@@ -200,7 +213,7 @@ std::unique_ptr ImProcFunctions::buildMeaLut(const float inVals[11], const
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)
+void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavCurve & wavdenoise, WavCurve & wavdenoiseh, const Wavblcurve & wavblcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveSH & waOpacityCurveSH, const WavOpacityCurveBY & waOpacityCurveBY, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, const LUTf &wavclCurve, int skip)
{
@@ -211,11 +224,43 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
{wiprof[2][0], wiprof[2][1], wiprof[2][2]}
};
const int imheight = lab->H, imwidth = lab->W;
+ int levwavL;
+ //Flat curve for H=f(H) in final touchup for guidedfilter
+ FlatCurve* wavguidCurve = new FlatCurve(params->wavelet.wavguidcurve); //curve H=f(H)
+ bool wavguidutili = false;
+
+ if (!wavguidCurve || wavguidCurve->isIdentity()) {
+ if (wavguidCurve) {
+ delete wavguidCurve;
+ wavguidCurve = nullptr;
+ }
+ } else {
+ wavguidutili = true;
+ }
+//flat curve for equalizer H
+ FlatCurve* wavhueCurve = new FlatCurve(params->wavelet.wavhuecurve); //curve H=f(H)
+ bool wavhueutili = false;
+
+ if (!wavhueCurve || wavhueCurve->isIdentity()) {
+ if (wavhueCurve) {
+ delete wavhueCurve;
+ wavhueCurve = nullptr;
+ }
+ } else {
+ wavhueutili = true;
+ }
struct cont_params cp;
cp.avoi = params->wavelet.avoid;
+ if (params->wavelet.complexmethod == "normal") {
+ cp.complex = 0;
+ } else if (params->wavelet.complexmethod == "expert") {
+ cp.complex = 1;
+ }
+
+
if (params->wavelet.Medgreinf == "more") {
cp.reinforce = 1;
} else if (params->wavelet.Medgreinf == "none") {
@@ -244,6 +289,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.sigmaton = params->wavelet.sigmaton;
cp.sigmacol = params->wavelet.sigmacol;
cp.sigmadir = params->wavelet.sigmadir;
+ cp.sigmm = params->wavelet.sigm;
+ cp.levden = params->wavelet.levden;
+ cp.thrden = 0.01f * params->wavelet.thrden;
+ cp.limden = params->wavelet.limden;
if (params->wavelet.TMmethod == "cont") {
cp.contmet = 1;
@@ -251,6 +300,41 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.contmet = 2;
}
+
+ if (params->wavelet.denmethod == "equ") {
+ cp.denmet = 0;
+ } else if (params->wavelet.denmethod == "high") {
+ cp.denmet = 1;
+ } else if (params->wavelet.denmethod == "low") {
+ cp.denmet = 2;
+ } else if (params->wavelet.denmethod == "12high") {
+ cp.denmet = 3;
+ } else if (params->wavelet.denmethod == "12low") {
+ cp.denmet = 4;
+ }
+
+ if (params->wavelet.mixmethod == "nois") {
+ cp.mixmet = 0;
+ } else if (params->wavelet.mixmethod == "mix") {
+ cp.mixmet = 1;
+ } else if (params->wavelet.mixmethod == "mix7") {
+ cp.mixmet = 2;
+ } else if (params->wavelet.mixmethod == "den") {
+ cp.mixmet = 3;
+ }
+
+ if (params->wavelet.quamethod == "cons") {
+ cp.quamet = 0;
+ } else if (params->wavelet.quamethod == "agre") {
+ cp.quamet = 1;
+ }
+
+ if (params->wavelet.slimethod == "sli") {
+ cp.slimet = 0;
+ } else if (params->wavelet.slimethod == "cur") {
+ cp.slimet = 1;
+ }
+
if (params->wavelet.BAmethod != "none") {
cp.bam = true;
@@ -341,6 +425,8 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.curv = false;
cp.edgcurv = false;
cp.diagcurv = false;
+ cp.denoicurv = false;
+ cp.denoicurvh = false;
cp.opaRG = false;
cp.opaBY = false;
cp.opaW = false;
@@ -425,6 +511,28 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.diagcurv = true;
}
+ if (wavdenoise) {
+ for (int i = 0; i < 500; i++) {
+ if (wavdenoise[i] != 1.0) {
+ cp.denoicurv = true;
+ break;
+ }
+ }
+ }
+
+ if(cp.complex == 0) {
+ wavdenoiseh = wavdenoise;
+ }
+
+ if (wavdenoiseh) {
+ for (int i = 0; i < 500; i++) {
+ if (wavdenoiseh[i] != 1.0) {
+ cp.denoicurvh = true;
+ break;
+ }
+ }
+ }
+
for (int m = 0; m < maxmul; m++) {
cp.mul[m] = waparams.c[m];
}
@@ -470,7 +578,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.chromfi = 0.1f * waparams.chromfi;
cp.chromco = 0.1f * waparams.chromco;
cp.ballum = waparams.ballum;
-
cp.conres = waparams.rescon;
cp.conresH = waparams.resconH;
cp.radius = waparams.radius;
@@ -531,6 +638,10 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.lev2n = static_cast(params->wavelet.level2noise.getTop());
cp.lev3s = static_cast(params->wavelet.level3noise.getBottom());
cp.lev3n = static_cast(params->wavelet.level3noise.getTop());
+ cp.lev4n = static_cast(params->wavelet.leveldenoise.getTop());
+ cp.lev4t = 0.01f * static_cast(params->wavelet.leveldenoise.getBottom());
+ cp.sigmm14 = static_cast(params->wavelet.levelsigm.getTop());
+ cp.sigmm56 = static_cast(params->wavelet.levelsigm.getBottom());
cp.detectedge = params->wavelet.medianlev;
int minwin = rtengine::min(imwidth, imheight);
@@ -557,12 +668,18 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
maxlevelcrop = 6;
}
- if (minwin < 64) {
+ if (minwin * skip < 64) {
maxlevelcrop = 5;
}
-
+ if (minwin * skip < 32) {
+ maxlevelcrop = 4;
+ }
+
int levwav = params->wavelet.thres;
+ if(params->wavelet.expnoise) {
+ levwav = 6;
+ }
if (levwav == 9 && cp.mul[9] != 0) {
levwav = 10;
@@ -634,6 +751,14 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
maxlev2 = 6;
}
+ if (minsizetile < 64) {
+ maxlev2 = 5;
+ }
+
+ if (minsizetile < 32) {
+ maxlev2 = 4;
+ }
+
levwav = rtengine::min(maxlev2, levwav);
#ifdef _OPENMP
@@ -714,6 +839,12 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
float sigmaN[10];
float MaxP[10];
float MaxN[10];
+ float meand[10];
+ float meanNd[10];
+ float sigmad[10];
+ float sigmaNd[10];
+ float MaxPd[10];
+ float MaxNd[10];
float meanab[10];
float meanNab[10];
@@ -877,7 +1008,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
int datalen = labco->W * labco->H;
- int levwavL = levwav;
+ levwavL = levwav;
bool ref0 = false;
if ((cp.lev0s > 0.f || cp.lev1s > 0.f || cp.lev2s > 0.f || cp.lev3s > 0.f) && cp.noiseena) {
@@ -901,31 +1032,57 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
cp.mul[0] = 0.01f;//to always enable WaveletcontAllL if no contrast is needed
}
}
-
- if (!exblurL && cp.contrast == 0.f && cp.blurres == 0.f && !cp.tonemap && cp.conres == 0.f && cp.conresH == 0.f && cp.val == 0 && !ref0 && params->wavelet.CLmethod == "all") { // no processing of residual L or edge=> we probably can reduce the number of levels
+
+ if (cp.BAmet != 0) {
+ if (cp.mul[0] == 0.f) {
+ cp.mul[0] = 0.01f;
+ }
+ }
+
+
+ if (!exblurL && cp.contrast == 0.f && cp.blurres == 0.f && !cp.noiseena && !cp.tonemap && !cp.resena && !cp.chromena && !cp.finena && !cp.edgeena && cp.conres == 0.f && cp.conresH == 0.f && cp.val == 0 && !ref0 && params->wavelet.CLmethod == "all") { // no processing of residual L or edge=> we probably can reduce the number of levels
while (levwavL > 0 && cp.mul[levwavL - 1] == 0.f) { // cp.mul[level] == 0.f means no changes to level
levwavL--;
}
}
+ if (levwavL == 6 && cp.noiseena && cp.chromfi == 0.f) {
+ cp.chromfi = 0.01f;
+ }
+
if (cp.chromfi > 0.f || cp.chromco > 0.f) {
if (levwavL < 7) {
levwavL = 7;
}
}
- if (levwavL < 4) {
- levwavL = 4; //to allow edge => I always allocate 3 (4) levels..because if user select wavelet it is to do something !!
+ if (levwavL < 5 && cp.noiseena) {
+ levwavL = 6; //to allow edge and denoise => I always allocate 3 (4) levels..because if user select wavelet it is to do something !!
}
+
+
+/*
+ if(cp.denoicurvh || cp.levdenhigh > 0.01f) {
+ levwavL = levwav;
+ }
+*/
+ float th = 0.01f * (float) waparams.thrend;
+ if(th > 0.f) {
+ levwavL = levwav;
+ }
+
+
+ bool usechrom = cp.chromfi > 0.f || cp.chromco > 0.f;
+ levwavL = rtengine::min(maxlevelcrop, levwavL);
+ levwavL = rtengine::min(maxlev2, levwavL);
if (settings->verbose) {
printf("Level decomp L=%i\n", levwavL);
}
- bool usechrom = cp.chromfi > 0.f || cp.chromco > 0.f;
-
if (levwavL > 0) {
const std::unique_ptr Ldecomp(new wavelet_decomposition(labco->data, labco->W, labco->H, levwavL, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+ // const std::unique_ptr Ldecomp2(new wavelet_decomposition(labco->data, labco->W, labco->H, levwavL, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
if (!Ldecomp->memory_allocation_failed()) {
float madL[10][3];
@@ -945,7 +1102,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
madL[lvl][dir - 1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L * Hlvl_L));
if (settings->verbose) {
- printf("sqrt madL=%f lvl=%i dir=%i\n", sqrt(madL[lvl][dir - 1]), lvl, dir - 1);
+ printf("Luminance noise estimate (sqr) madL=%.0f lvl=%i dir=%i\n", madL[lvl][dir - 1], lvl, dir - 1);
}
}
}
@@ -954,6 +1111,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if ((cp.lev0s > 0.f || cp.lev1s > 0.f || cp.lev2s > 0.f || cp.lev3s > 0.f) && cp.noiseena) {
ref = true;
+
}
bool contr = false;
@@ -964,82 +1122,391 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
- if (cp.val > 0 || ref || contr) { //edge
- Evaluate2(*Ldecomp, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavNestedLevels);
+ // if (cp.val > 0 || ref || contr || cp.denoicurv || cp.denoicurvh || cp.noiseena || cp.levdenlow > 0.f || cp.thrden > 0.f ) { //edge
+ if (cp.val > 0 || ref || contr || cp.denoicurv || cp.denoicurvh || cp.noiseena || cp.thrden > 0.f ) { //edge
+ Evaluate2(*Ldecomp, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavNestedLevels);
}
//init for edge and denoise
- float vari[4];
+ float vari[6];
vari[0] = 0.8f * SQR((cp.lev0n / 125.f) * (1.f + cp.lev0n / 25.f));
vari[1] = 0.8f * SQR((cp.lev1n / 125.f) * (1.f + cp.lev1n / 25.f));
vari[2] = 0.8f * SQR((cp.lev2n / 125.f) * (1.f + cp.lev2n / 25.f));
vari[3] = 0.8f * SQR((cp.lev3n / 125.f) * (1.f + cp.lev3n / 25.f));
+ vari[4] = 0.8f * SQR((cp.lev4n / 125.f) * (1.f + cp.lev4n / 25.f));
+ vari[5] = 0.8f * SQR((cp.lev4n / 125.f) * (1.f + cp.lev4n / 25.f));
float kr3 = 1.f;
if (cp.lev3n < 10.f) {
- kr3 = 0.f;
+ kr3 = 0.3f;
} else if (cp.lev3n < 30.f) {
- kr3 = 0.5f;
+ kr3 = 0.6f;
} else if (cp.lev3n < 70.f) {
- kr3 = 0.7f;
+ kr3 = 0.8f;
} else {
kr3 = 1.f;
}
- if ((cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f) && cp.noiseena) {
- int edge = 5;
+ float kr4 = 1.f;
+
+ if (cp.lev4n < 10.f) {
+ kr4 = 0.6f;
+ } else if (cp.lev4n < 30.f) {
+ kr4 = 0.8f;
+ } else if (cp.lev4n < 70.f) {
+ kr4 = 0.9f;
+ } else {
+ kr4 = 1.f;
+ }
+
+ if ((cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f || cp.lev4n > 0.1f) && cp.noiseena) {
+ int edge = 6;
vari[0] = rtengine::max(0.000001f, vari[0]);
vari[1] = rtengine::max(0.000001f, vari[1]);
vari[2] = rtengine::max(0.000001f, vari[2]);
vari[3] = rtengine::max(0.000001f, kr3 * vari[3]);
-
- if (settings->verbose) {
- printf("LUM var0=%f var1=%f var2=%f var3=%f\n", vari[0], vari[1], vari[2], vari[3]);
- }
+ vari[4] = rtengine::max(0.000001f, kr4 * vari[4]);
+ vari[5] = rtengine::max(0.000001f, kr4 * vari[5]);
+
+ const std::unique_ptr Ldecomp2(new wavelet_decomposition(labco->data, labco->W, labco->H, levwavL, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+ if(!Ldecomp2->memory_allocation_failed()){
+ if (settings->verbose) {
+ printf("LUM var0=%f var1=%f var2=%f var3=%f var4=%f\n", vari[0], vari[1], vari[2], vari[3], vari[4]);
+ }
// float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL
- int GWL = labco->W;
- int GHL = labco->H;
- float* noisevarlum = new float[GHL * GWL];
- int GW2L = (GWL + 1) / 2;
+ int GWL = labco->W;
+ int GHL = labco->H;
+ float* noisevarlum = new float[GHL * GWL];
+ float* noisevarhue = new float[GHL * GWL];
+ int GW2L = (GWL + 1) / 2;
- float nvlh[13] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.7f, 0.5f}; //high value
- float nvll[13] = {0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.7f, 0.8f, 1.f, 1.f, 1.f}; //low value
+ float nvlh[13] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.7f, 0.5f}; //high value
+ float nvll[13] = {0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.7f, 0.8f, 1.f, 1.f, 1.f}; //low value
- float seuillow = 3000.f;//low
- float seuilhigh = 18000.f;//high
- int i = 10 - cp.ballum;
- float ac = (nvlh[i] - nvll[i]) / (seuillow - seuilhigh);
- float bc = nvlh[i] - seuillow * ac;
+ float seuillow = 3000.f;//low
+ float seuilhigh = 18000.f;//high
+ int i = 10 - cp.ballum;
+ float ac = (nvlh[i] - nvll[i]) / (seuillow - seuilhigh);
+ float bc = nvlh[i] - seuillow * ac;
#ifdef _OPENMP
- #pragma omp parallel for
+ #pragma omp parallel for
#endif
- for (int ir = 0; ir < GHL; ir++)
- for (int jr = 0; jr < GWL; jr++) {
- float lN = labco->L[ir][jr];
+ for (int ir = 0; ir < GHL; ir++)
+ for (int jr = 0; jr < GWL; jr++) {
+ float lN = labco->L[ir][jr];
- if (lN < seuillow) {
- noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = nvlh[i];
- } else if (lN < seuilhigh) {
- noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = ac * lN + bc;
- } else {
- noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = nvll[i];
+ if (lN < seuillow) {
+ noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = nvlh[i];
+ } else if (lN < seuilhigh) {
+ noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = ac * lN + bc;
+ } else {
+ noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] = nvll[i];
+ }
}
+
+ if(wavhueutili) {
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+ for (int ir = 0; ir < GHL; ir++)
+ for (int jr = 0; jr < GWL; jr++) {
+ float hueG = xatan2f(labco->b[ir][jr], labco->a[ir][jr]);
+ noisevarhue[(ir >> 1)*GW2L + (jr >> 1)] = 1.f + 2.f * (static_cast(wavhueCurve->getVal(Color::huelab_to_huehsv2(hueG))) - 0.5f);
+ noisevarlum[(ir >> 1)*GW2L + (jr >> 1)] *= noisevarhue[(ir >> 1)*GW2L + (jr >> 1)];
+ }
}
- if (cp.lev3n < 20.f) {
- WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
- } else {
- WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+
- WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+
+ if(cp.quamet == 0) {
+ if (settings->verbose) {
+ printf("denoise standard\n");
+ }
+ WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+ } else {
+ if (settings->verbose) {
+ printf("denoise bishrink\n");
+ }
+ WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+
+ WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge, 1);
+ }
+ delete[] noisevarlum;
+
+ //evaluate after denoise
+ bool exitifzero = true;
+ Evaluate2(*Ldecomp, meand, meanNd, sigmad, sigmaNd, MaxPd, MaxNd, wavNestedLevels);
+ for (int dir = 1; dir < 4; dir++) {
+ for (int level = 0; level < levwavL; level++) {
+ if(mean[level] < 0.1f || meand[level] < 0.1f || sigma[level] < 0.1f || sigmad[level] < 0.1f) {
+ printf("near zero - exit\n");
+ exitifzero = false;
+ }
+ }
+ }
+
+ //for level 0 1 2 3
+ float thr = 0.f;
+ float thrend = cp.thrden; //cp.levdenlow;
+ if(thrend < 0.01f) thr = 0.95f;
+ else if(thrend < 0.02f) thr = 0.9f;
+ else if(thrend < 0.04f) thr = 0.8f;
+ else if(thrend < 0.06f) thr = 0.7f;
+ else if(thrend < 0.08f) thr = 0.6f;
+ else if(thrend < 0.1f) thr = 0.5f;
+ else if(thrend < 0.2f) thr = 0.2f;
+ else thr = 0.f;
+
+ FlatCurve wavlow({
+ FCT_MinMaxCPoints,
+ 0, 1, 0.35, 0.35,thrend, 1.0, 0.35, 0.35, thrend + 0.01f, thr, 0.35, 0.35, 1, thr, 0.35, 0.35
+ });
+ //for level 4
+ float thrhigh = 0.f;
+ float threndhigh = cp.lev4t; //cp.levdenlow;
+ if(threndhigh < 0.01f) thrhigh = 0.95f;
+ else if(threndhigh < 0.02f) thrhigh = 0.9f;
+ else if(threndhigh < 0.04f) thrhigh = 0.8f;
+ else if(threndhigh < 0.06f) thrhigh = 0.7f;
+ else if(threndhigh < 0.08f) thrhigh = 0.6f;
+ else if(threndhigh < 0.1f) thrhigh = 0.5f;
+ else thrhigh = 0.f;
+
+ FlatCurve wavhigh({
+ FCT_MinMaxCPoints,
+ 0, 1, 0.35, 0.35,threndhigh, 1.0, 0.35, 0.35, threndhigh + 0.01f, thrhigh, 0.35, 0.35, 1, thrhigh, 0.35, 0.35
+ });
+
+ float thrmed = 0.f;
+ float threndmed = 1.f - cp.limden;
+ if(threndmed < 0.02f) thrmed = 0.5f;
+ else if(threndmed < 0.05f) thrmed = 0.2f;
+ else thrmed = 0.f;
+
+ FlatCurve wavmed({
+ FCT_MinMaxCPoints,
+ 0, 1, 0.35, 0.35,threndmed, 1.0, 0.35, 0.35, threndmed + 0.01f, thrmed, 0.35, 0.35, 1, thrmed, 0.35, 0.35
+ });
+
+ float siglh[10];
+ float levref = 6;
+ //levref = levwavL-1;
+ if(cp.complex == 1){
+ for (int level = 0; level < levref; level++) {
+ if(level > 3) {
+ siglh[level] = cp.sigmm56;
+ } else {
+ siglh[level] = cp.sigmm14;
+ }
+ }
+ } else {
+ levref = 4;
+ for (int level = 0; level < levref; level++) {
+ siglh[level] = cp.sigmm;
+ }
+ }
+
+// printf("sig0=%f sig1=%f sig2=%f sig3=%f sig4=%f sig5=%f\n", siglh[0], siglh[1],siglh[2],siglh[3],siglh[4],siglh[5]);
+
+
+ bool execut = false;
+
+ if(cp.slimet == 0) {
+ // if(cp.levdenlow > 0.f) {
+ if(cp.thrden > 0.f) {
+ execut = true;
+ }
+ } else {
+ if(cp.denoicurv) {
+ execut = true;
+ }
+ }
+ // }
+ if (execut && exitifzero) {
+ for (int dir = 1; dir < 4; dir++) {
+ for (int level = 0; level < levref; level++) {
+ int Wlvl_L = Ldecomp->level_W(level);
+ int Hlvl_L = Ldecomp->level_H(level);
+ float* const* WavCoeffs_L = Ldecomp->level_coeffs(level);//first decomp denoised
+ float* const* WavCoeffs_L2 = Ldecomp2->level_coeffs(level);//second decomp before denoise
+ int k4 = 3;
+ int k5 = 3;
+ if(cp.complex == 1){
+ k4= 4;
+ k5= 5;
+ }
+ auto WavL0 = Ldecomp->level_coeffs(0)[dir];
+ auto WavL1 = Ldecomp->level_coeffs(1)[dir];
+ auto WavL2 = Ldecomp->level_coeffs(2)[dir];
+ auto WavL3 = Ldecomp->level_coeffs(3)[dir];
+ auto WavL4 = Ldecomp->level_coeffs(k4)[dir];
+ auto WavL5 = Ldecomp->level_coeffs(k5)[dir];
+ //not denoise
+ const auto WavL02 = Ldecomp2->level_coeffs(0)[dir];
+ const auto WavL12 = Ldecomp2->level_coeffs(1)[dir];
+ const auto WavL22 = Ldecomp2->level_coeffs(2)[dir];
+ const auto WavL32 = Ldecomp2->level_coeffs(3)[dir];
+ const auto WavL42 = Ldecomp2->level_coeffs(k4)[dir];
+ const auto WavL52 = Ldecomp2->level_coeffs(k5)[dir];
+ if (settings->verbose) {
+ printf("level=%i mean=%.0f meanden=%.0f sigma=%.0f sigmaden=%.0f Max=%.0f Maxden=%.0f\n", level, mean[level], meand[level], sigma[level], sigmad[level],MaxP[level], MaxPd[level]);
+ }
+
+ //find local contrast
+ float tempmean = 0.f;
+ float tempsig = 0.f;
+ float tempmax = 0.f;
+ if(cp.mixmet == 0){
+ tempmean = mean[level];
+ tempsig = sigma[level];
+ tempmax = MaxP[level];
+ } else if(cp.mixmet == 1){
+ tempmean = 0.5f * mean[level] + 0.5f * meand[level] ;
+ tempsig = 0.5f * sigma[level] + 0.5f * sigmad[level] ;
+ tempmax = 0.5f * MaxP[level] + 0.5f * MaxPd[level] ;
+ } else if(cp.mixmet == 2){
+ tempmean = 0.3f * mean[level] + 0.7f * meand[level] ;
+ tempsig = 0.3f * sigma[level] + 0.7f * sigmad[level] ;
+ tempmax = 0.3f * MaxP[level] + 0.7f * MaxPd[level] ;
+ } else if(cp.mixmet == 3){
+ tempmean = meand[level];
+ tempsig = sigmad[level];
+ tempmax = MaxPd[level];
+ }
+
+ if (MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { //curve
+ float insigma = 0.666f; //SD
+ float logmax = log(tempmax); //log Max
+ //cp.sigmm change the "wider" of sigma
+ float rapX = (tempmean + siglh[level] * tempsig) / (tempmax); //rapport between sD / max
+ float inx = log(insigma);
+ float iny = log(rapX);
+ float rap = inx / iny; //koef
+ float asig = 0.166f / (tempsig * siglh[level]);
+ float bsig = 0.5f - asig * tempmean;
+ float amean = 0.5f / (tempmean);
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic, Wlvl_L * 16) num_threads(wavNestedLevels) if (wavNestedLevels>1)
+#endif
+
+ for (int i = 0; i < Wlvl_L * Hlvl_L; i++) {
+ float absciss;
+ float tempwav = 0.f;
+ if(cp.mixmet == 0){
+ tempwav = WavCoeffs_L2[dir][i];
+ } else if(cp.mixmet == 1){
+ tempwav = 0.5f * WavCoeffs_L[dir][i] + 0.5f * WavCoeffs_L2[dir][i];
+ } else if(cp.mixmet == 2){
+ tempwav = 0.7f * WavCoeffs_L[dir][i] + 0.3f * WavCoeffs_L2[dir][i];
+ } else if(cp.mixmet == 3){
+ tempwav = WavCoeffs_L[dir][i];
+ }
+
+ if (std::fabs(tempwav) >= (tempmean + siglh[level] * tempsig)) { //for max
+ float valcour = xlogf(std::fabs(tempwav));
+ float valc = valcour - logmax;
+ float vald = valc * rap;
+ absciss = xexpf(vald);
+ } else if (std::fabs(tempwav) >= tempmean) {
+ absciss = asig * std::fabs(tempwav) + bsig;
+ } else {
+ absciss = amean * std::fabs(tempwav);
+ float k = siglh[level];
+ if(siglh[level] > 1.f) {
+ k = SQR(siglh[level]);
+ }
+ float abs = pow(2.f * absciss, (1.f / k));
+ absciss = 0.5f * abs;
+ }
+ float kc = 0.f;
+ if(cp.slimet == 0) {
+ kc = wavlow.getVal(absciss) -1.f;
+ } else {
+ kc = wavdenoise[absciss * 500.f] - 1.f;
+ }
+
+ float kchigh = 0.f;
+ kchigh = wavhigh.getVal(absciss) -1.f;
+ kchigh = -SQR(kchigh);
+
+ float kcmed = 0.f;
+ kcmed = wavmed.getVal(absciss) -1.f;
+ kcmed = -SQR(kcmed);
+
+ if(kc < 0) {
+ kc = -SQR(kc);//approximation to simulate sliders denoise
+ }
+ //equalizer for levels 0 1 and 3... 1.33 and 0.75 arbitrary values
+ if(cp.denmet == 1) {
+ if(level == 0 || level == 3) {
+ kc *= 1.7f;
+ }
+ } else if(cp.denmet == 2) {
+ if(level == 0 || level == 3) {
+ kc *= 0.3f;
+ }
+ } else if(cp.denmet == 3) {
+ if(level == 0 || level == 1) {
+ kc *= 1.7f;
+ }
+ } else if(cp.denmet == 4) {
+ if(level == 0 || level == 1) {
+ kc *= 0.3f;
+ }
+ }
+
+ float reduceeffect = kc <= 0.f ? 1.f : 1.2f;//1.2 allows to increase denoise (not used)
+
+ float kinterm = 1.f + reduceeffect * kc;
+ kinterm = kinterm <= 0.f ? 0.01f : kinterm;
+
+ float kintermhigh = 1.f + reduceeffect * kchigh;
+ kintermhigh = kintermhigh <= 0.f ? 0.01f : kintermhigh;
+
+ float kintermed = 1.f + reduceeffect * kcmed;
+ kintermed = kintermed <= 0.f ? 0.01f : kintermed;
+
+ float kintermlow = kinterm;
+ if(level < 4) {
+ WavL0[i] = WavL02[i] + (WavL0[i] - WavL02[i]) * kintermlow;
+ WavL1[i] = WavL12[i] + (WavL1[i] - WavL12[i]) * kintermlow;
+ WavL2[i] = WavL22[i] + (WavL2[i] - WavL22[i]) * kintermlow;
+ WavL3[i] = WavL32[i] + (WavL3[i] - WavL32[i]) * kintermlow;
+ }
+ if(cp.complex == 1){
+ if(cp.limden > 0.f) {
+ WavL0[i] = WavL02[i] + (WavL0[i] - WavL02[i]) * kintermed;
+ WavL1[i] = WavL12[i] + (WavL1[i] - WavL12[i]) * kintermed;
+ WavL2[i] = WavL22[i] + (WavL2[i] - WavL22[i]) * kintermed;
+ WavL3[i] = WavL32[i] + (WavL3[i] - WavL32[i]) * kintermed;
+ }
+ WavL4[i] = WavL42[i] + (WavL4[i] - WavL42[i]) * kintermhigh;
+ WavL5[i] = WavL52[i] + (WavL5[i] - WavL52[i]) * kintermhigh;
+ }
+ }
+ }
+ }
+ }
+ if (settings->verbose) {
+ Evaluate2(*Ldecomp, meand, meanNd, sigmad, sigmaNd, MaxPd, MaxNd, wavNestedLevels);
+ for (int dir = 1; dir < 4; dir++) {
+ for (int level = 0; level < levref; level++) {
+ printf("AFTER LC level=%i mean=%.0f meanden=%.0f sigma=%.0f sigmaden=%.0f Max=%.0f Maxden=%.0f\n", level, mean[level], meand[level], sigma[level], sigmad[level],MaxP[level], MaxPd[level]);
+ }
+ }
+ }
+
+ }
+ delete[] noisevarhue;
}
- }
-
+ }
//Flat curve for Contrast=f(H) in levels
FlatCurve* ChCurve = new FlatCurve(params->wavelet.Chcurve); //curve C=f(H)
bool Chutili = false;
@@ -1106,7 +1573,6 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (noiseccb < 0.f) {
noiseccb = 0.0001f;
}
-
int edge = 2;
variC[0] = SQR(noisecfr);
variC[1] = SQR(noisecfr);
@@ -1302,7 +1768,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (!hhutili) { //always a or b
int levwava = levwav;
- if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
+ if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && !cp.noiseena && !cp.tonemap && !cp.resena && !cp.chromena && !cp.finena && !cp.edgeena&& params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
while (levwava > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwava - 1] == 0.f)) || (cp.CHmet != 2 && (levwava == 10 || (!cp.curv || cp.mulC[levwava - 1] == 0.f))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava - 1] == 0.f)) && ((levwava == 10 || (cp.CHSLmet == 1 && cp.mulC[levwava - 1] == 0.f)))) {
levwava--;
}
@@ -1314,31 +1780,41 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
+ levwava = rtengine::min(maxlevelcrop, levwava);
+ levwava = rtengine::min(maxlev2, levwava);
if (settings->verbose) {
printf("Leval decomp a=%i\n", levwava);
}
if (levwava > 0) {
const std::unique_ptr adecomp(new wavelet_decomposition(labco->data + datalen, labco->W, labco->H, levwava, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
-
if (!adecomp->memory_allocation_failed()) {
- if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f )) {
+ if(levwava == 6) {
+ edge = 1;
+ }
+ if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.quamet == 0 )) {
+
WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
- } else if (cp.chromfi > 0.f && cp.chromco >= 2.f){
+
+ } else if (cp.noiseena && ((cp.chromfi > 0.f && cp.chromco >= 0.f) && cp.quamet == 1 )){
WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
+
}
Evaluate2(*adecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab, wavNestedLevels);
+
WaveletcontAllAB(labco, varhue, varchro, *adecomp, wavblcurve, waOpacityCurveW, cp, true, skip, meanab, sigmaab);
+
adecomp->reconstruct(labco->data + datalen, cp.strength);
+
}
}
int levwavb = levwav;
- if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
+ if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && !cp.noiseena && !cp.tonemap && !cp.resena && !cp.chromena && !cp.finena && !cp.edgeena && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels
while (levwavb > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavb - 1] == 0.f)) || (cp.CHmet != 2 && (levwavb == 10 || (!cp.curv || cp.mulC[levwavb - 1] == 0.f))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb - 1] == 0.f)) && ((levwavb == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavb - 1] == 0.f)))) {
levwavb--;
}
@@ -1350,20 +1826,35 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
}
+
+ levwavb = rtengine::min(maxlevelcrop, levwavb);
+ levwavb = rtengine::min(maxlev2, levwavb);
+
if (settings->verbose) {
printf("Leval decomp b=%i\n", levwavb);
}
-
if (levwavb > 0) {
const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavb, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+ if(levwavb == 6) {
+ edge = 1;
+ }
if (!bdecomp->memory_allocation_failed()) {
- if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f )) {
+ // if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f )) {
+ if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.quamet == 0)) {
WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
- } else if (cp.chromfi > 0.f && cp.chromco >= 2.f){
+ if (settings->verbose) {
+ printf("Denoise ab standard\n");
+ }
+ } else if (cp.noiseena && ((cp.chromfi > 0.f && cp.chromco >= 0.f) && cp.quamet == 1 )){
+
WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
+ if (settings->verbose) {
+ printf("Denoise ab bishrink\n");
+ }
+
}
Evaluate2(*bdecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab, wavNestedLevels);
@@ -1385,7 +1876,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
const std::unique_ptr bdecomp(new wavelet_decomposition(labco->data + 2 * datalen, labco->W, labco->H, levwavab, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
if (!adecomp->memory_allocation_failed() && !bdecomp->memory_allocation_failed()) {
- if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f)) {
+ if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.quamet == 0)) {
WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
} else if (cp.chromfi > 0.f && cp.chromco >= 2.f){
WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, 1);
@@ -1394,7 +1885,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
Evaluate2(*adecomp, meanab, meanNab, sigmaab, sigmaNab, MaxPab, MaxNab, wavNestedLevels);
WaveletcontAllAB(labco, varhue, varchro, *adecomp, wavblcurve, waOpacityCurveW, cp, true, skip, meanab, sigmaab);
- if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.chromco < 2.f)) {
+ if (cp.noiseena && ((cp.chromfi > 0.f || cp.chromco > 0.f) && cp.quamet == 0)) {
WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
} else if (cp.chromfi > 0.f && cp.chromco >= 2.f){
WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, 1);
@@ -1422,6 +1913,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
if (usechrom) {
Ldecomp->reconstruct(labco->data, cp.strength);
}
+
}
}
@@ -1626,8 +2118,30 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
if (waparams.softradend > 0.f && cp.finena) {
- array2D ble(lab->W, lab->H);
- array2D guid(lab->W, lab->H);
+ float guid = waparams.softradend;
+ float strend = waparams.strend;
+ float detend = (float) waparams.detend;
+ float thrend = 0.01f * (float) waparams.thrend;
+ int ww = lab->W;
+ int hh = lab->H;
+ array2D LL(ww, hh);
+ array2D LLbef(ww, hh);
+ array2D LAbef(ww, hh);
+ array2D LBbef(ww, hh);
+ array2D guide(ww, hh);
+ const float blend = LIM01(float(strend) / 100.f);
+ float mean[10];
+ float meanN[10];
+ float sigma[10];
+ float sigmaN[10];
+ float MaxP[10];
+ float MaxN[10];
+ float meang[10];
+ float meanNg[10];
+ float sigmag[10];
+ float sigmaNg[10];
+ float MaxPg[10];
+ float MaxNg[10];
bool multiTh = false;
@@ -1639,31 +2153,141 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
#pragma omp parallel for
#endif
-
- for (int ir = 0; ir < lab->H; ir++) {
- for (int jr = 0; jr < lab->W; jr++) {
- guid[ir][jr] = Color::L2Y(lab->L[ir][jr]) / 32768.f;
- ble[ir][jr] = Color::L2Y(dst->L[ir][jr]) / 32768.f;
+ for (int y = 0; y < hh; y++) {
+ for (int x = 0; x < ww; x++) {
+ LL[y][x] = dst->L[y][x];
+ LLbef[y][x] = dst->L[y][x];
+ LAbef[y][x] = dst->a[y][x];
+ LBbef[y][x] = dst->b[y][x];
+ float ll = LL[y][x] / 32768.f;
+ guide[y][x] = xlin2log(rtengine::max(ll, 0.f), 10.f);
}
}
+ array2D iL(ww, hh, LL, 0);
+ int r = rtengine::max(int(guid / skip), 1);
- constexpr double epsilmax = 0.002;
- constexpr double epsilmin = 0.0005;
- constexpr double aepsil = 0.01f * (epsilmax - epsilmin);
- constexpr double bepsil = epsilmin;
- const double epsil = aepsil * waparams.softradend + bepsil;
-
- const float blur = 10.f / scale * (0.001f + 0.8f * waparams.softradend);
-
- rtengine::guidedFilter(guid, ble, ble, blur, epsil, multiTh);
-
+ const float epsil = 0.001f * std::pow(2, - detend);
+ rtengine::guidedFilterLog(guide, 10.f, LL, r, epsil, multiTh);
+ //take Hue to modulate LL
+ //LL in function of LLbef and Labef Lbbef
+ if(wavguidutili) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
+ for (int y = 0; y < hh ; y++) {
+ for (int x = 0; x < ww; x++) {
+ float hueG = xatan2f(LBbef[y][x], LAbef[y][x]);
+ float valparam = 1.f * (static_cast(wavguidCurve->getVal(Color::huelab_to_huehsv2(hueG))) - 0.5f);
+ LL[y][x] = LLbef[y][x] + (LL[y][x] - LLbef[y][x]) * (1.f + valparam);
+ }
+ }
+ }
+ //end hue
+
+
+ if (thrend > 0.f) {
+ //2 decomposition LL after guidefilter and dst before (perhaps dst no need)
+ const std::unique_ptr LdecompLL(new wavelet_decomposition(LL[0], ww, hh, levwavL, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+ const std::unique_ptr Ldecompdst(new wavelet_decomposition(dst->L[0], ww, hh, levwavL, 1, skip, rtengine::max(1, wavNestedLevels), DaubLen));
+ if (!LdecompLL->memory_allocation_failed() && !Ldecompdst->memory_allocation_failed()) {
- for (int ir = 0; ir < lab->H; ir++) {
- for (int jr = 0; jr < lab->W; jr++) {
- dst->L[ir][jr] = Color::computeXYZ2LabY(32768.f * ble[ir][jr]);
+ Evaluate2(*LdecompLL, meang, meanNg, sigmag, sigmaNg, MaxPg, MaxNg, wavNestedLevels);
+ Evaluate2(*Ldecompdst, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavNestedLevels);
+ float sig = 2.f;
+ float thr = 0.f;
+ if(thrend < 0.02f) thr = 0.5f;
+ else if(thrend < 0.1f) thr = 0.2f;
+ else thr = 0.f;
+
+ FlatCurve wavguid({
+ FCT_MinMaxCPoints,
+ 0, 1, 0.35, 0.35,thrend, 1.0, 0.35, 0.35, thrend + 0.01f, thr, 0.35, 0.35, 1, thr, 0.35, 0.35
+ });
+
+ for (int dir = 1; dir < 4; dir++) {
+ for (int level = 0; level < levwavL-1; level++) {
+ int Wlvl_L = LdecompLL->level_W(level);
+ int Hlvl_L = LdecompLL->level_H(level);
+ float* const* WavCoeffs_L = LdecompLL->level_coeffs(level);//first decomp denoised
+ float* const* WavCoeffs_L2 = Ldecompdst->level_coeffs(level);//second decomp before denoise
+ if (settings->verbose) {
+ printf("level=%i mean=%.0f meanden=%.0f sigma=%.0f sigmaden=%.0f Max=%.0f Maxden=%.0f\n", level, mean[level], meang[level], sigma[level], sigmag[level],MaxP[level], MaxPg[level]);
+ }
+
+ //find local contrast
+ float tempmean = 0.f;
+ float tempsig = 0.f;
+ float tempmax = 0.f;
+ tempmean = 0.3f * mean[level] + 0.7f * meang[level] ;
+ tempsig = 0.3f * sigma[level] + 0.7f * sigmag[level] ;
+ tempmax = 0.3f * MaxP[level] + 0.7f * MaxPg[level] ;
+
+ if (MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { //curve
+ float insigma = 0.666f; //SD
+ float logmax = log(tempmax); //log Max
+ //cp.sigmm change the "wider" of sigma
+ float rapX = (tempmean + sig * tempsig) / (tempmax); //rapport between sD / max
+ float inx = log(insigma);
+ float iny = log(rapX);
+ float rap = inx / iny; //koef
+ float asig = 0.166f / (tempsig * sig);
+ float bsig = 0.5f - asig * tempmean;
+ float amean = 0.5f / (tempmean);
+
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic, Wlvl_L * 16) num_threads(wavNestedLevels) if (wavNestedLevels>1)
+#endif
+
+ for (int i = 0; i < Wlvl_L * Hlvl_L; i++) {
+ float absciss;
+ float tempwav = 0.f;
+ tempwav = 0.7f * WavCoeffs_L[dir][i] + 0.3f * WavCoeffs_L2[dir][i];
+
+ if (std::fabs(tempwav) >= (tempmean + sig * tempsig)) { //for max
+ float valcour = xlogf(std::fabs(tempwav));
+ float valc = valcour - logmax;
+ float vald = valc * rap;
+ absciss = xexpf(vald);
+ } else if (std::fabs(tempwav) >= tempmean) {
+ absciss = asig * std::fabs(tempwav) + bsig;
+ } else {
+ absciss = amean * std::fabs(tempwav);
+ float k = sig;
+ if(sig > 1.f) {
+ k = SQR(sig);
+ }
+ float abs = pow(2.f * absciss, (1.f / k));
+ absciss = 0.5f * abs;
+ }
+ float kc = wavguid.getVal(absciss) -1.f;
+
+ if(kc < 0) {
+ kc = -SQR(kc);//approximation to simulate sliders denoise
+ }
+ float reduceeffect = kc <= 0.f ? 1.f : 1.2f;//1.2 allows to increase denoise (not used)
+
+ float kinterm = 1.f + reduceeffect * kc;
+ kinterm = kinterm <= 0.f ? 0.01f : kinterm;
+ float prov = WavCoeffs_L2[dir][i];//save before denoise
+ WavCoeffs_L[dir][i] = prov + (WavCoeffs_L[dir][i] - prov) * kinterm;//only apply local contrast on difference between denoise and normal
+ }
+ }
+ }
+ }
+ LdecompLL->reconstruct(LL[0], cp.strength);
+ }
+ }
+
+
+ //end local contrast
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+ for (int y = 0; y < hh ; y++) {
+ for (int x = 0; x < ww; x++) {
+ LL[y][x] = intp(blend, LL[y][x] , iL[y][x]);
+ dst->L[y][x] = LL[y][x];
}
}
}
@@ -2017,7 +2641,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
+// 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);
@@ -2449,7 +3073,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
+//BENCHFUN
int maxlvl = WaveletCoeffs_ab.maxlevel();
int W_L = WaveletCoeffs_ab.level_W(0);
int H_L = WaveletCoeffs_ab.level_H(0);
@@ -2967,11 +3591,11 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz,
for (int sc = 0; sc < 10; sc++) {
scaleskip[sc] = scales[sc] / skip;
}
-
+/*
if (settings->verbose) {
printf("level=%i mean=%f sigma=%f maxp=%f\n", level, mean[level], sigma[level], MaxP[level]);
}
-
+*/
constexpr float t_r = 40.f;
constexpr float t_l = 10.f;
constexpr float b_r = 75.f;
@@ -3117,7 +3741,7 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz,
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);
+ // printf("edghi=%f edglo=%f limrad=%f\n", edghig, edglow, limrad);
// value *= beta;
float edge = 1.f;
float lim0 = limrad; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi
@@ -3143,7 +3767,7 @@ 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);
+ // printf("repart=%f\n", repart);
if (cp.reinforce == 3) {
if (rad < (lim0 / 60.f) && level == 0) {
diff --git a/rtengine/jdatasrc.cc b/rtengine/jdatasrc.cc
index e461b60f5..f9256899d 100644
--- a/rtengine/jdatasrc.cc
+++ b/rtengine/jdatasrc.cc
@@ -248,12 +248,18 @@ my_error_exit (j_common_ptr cinfo)
}
-//const char * const jpeg_std_message_table[] = {
-//#include "jerror.h"
-// NULL
-//};
-extern const char * const jpeg_std_message_table[];
+#ifdef WIN32
+#define JVERSION "6b 27-Mar-1998"
+#define JCOPYRIGHT_SHORT "(C) 1998, Thomas G. Lane"
+#define JMESSAGE(code,string) string ,
+const char * const jpeg_std_message_table[] = {
+#include "jerror.h"
+ NULL
+};
+#else
+extern const char * const jpeg_std_message_table[];
+#endif
/*
* Actual output of an error or trace message.
@@ -373,9 +379,9 @@ format_message (j_common_ptr cinfo, char * buffer)
/* Format the message into the passed buffer */
if (isstring) {
- sprintf(buffer, msgtext, err->msg_parm.s);
+ snprintf(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s);
} else
- sprintf(buffer, msgtext,
+ snprintf(buffer, JMSG_LENGTH_MAX, msgtext,
err->msg_parm.i[0], err->msg_parm.i[1],
err->msg_parm.i[2], err->msg_parm.i[3],
err->msg_parm.i[4], err->msg_parm.i[5],
diff --git a/rtengine/klt/trackFeatures.cc b/rtengine/klt/trackFeatures.cc
index a99225543..8c0cd5ba6 100644
--- a/rtengine/klt/trackFeatures.cc
+++ b/rtengine/klt/trackFeatures.cc
@@ -1044,7 +1044,7 @@ static int _am_trackFeatureAffine(
#ifdef DEBUG_AFFINE_MAPPING
aff_diff_win->data = imgdiff;
- sprintf(fname, "./debug/kltimg_trans_diff_win%03d.%03d.pgm", glob_index, counter);
+ snprintf(fname, sizeof(fname), "./debug/kltimg_trans_diff_win%03d.%03d.pgm", glob_index, counter);
printf("%s\n", fname);
_KLTWriteAbsFloatImageToPGM(aff_diff_win, fname,256.0);
printf("iter = %d translation tracker res: %f\n", iteration, _sumAbsFloatWindow(imgdiff, width, height)/(width*height));
@@ -1095,13 +1095,13 @@ static int _am_trackFeatureAffine(
counter++;
_am_computeAffineMappedImage(img1, x1, y1, 1.0, 0.0 , 0.0, 1.0, width, height, imgdiff);
aff_diff_win->data = imgdiff;
- sprintf(fname, "./debug/kltimg_aff_diff_win%03d.%03d_1.pgm", glob_index, counter);
+ snprintf(fname, sizeof(fname), "./debug/kltimg_aff_diff_win%03d.%03d_1.pgm", glob_index, counter);
printf("%s\n", fname);
_KLTWriteAbsFloatImageToPGM(aff_diff_win, fname,256.0);
_am_computeAffineMappedImage(img2, *x2, *y2, *Axx, *Ayx , *Axy, *Ayy, width, height, imgdiff);
aff_diff_win->data = imgdiff;
- sprintf(fname, "./debug/kltimg_aff_diff_win%03d.%03d_2.pgm", glob_index, counter);
+ snprintf(fname, sizeof(fname), "./debug/kltimg_aff_diff_win%03d.%03d_2.pgm", glob_index, counter);
printf("%s\n", fname);
_KLTWriteAbsFloatImageToPGM(aff_diff_win, fname,256.0);
#endif
@@ -1110,7 +1110,7 @@ static int _am_trackFeatureAffine(
width, height, imgdiff);
#ifdef DEBUG_AFFINE_MAPPING
aff_diff_win->data = imgdiff;
- sprintf(fname, "./debug/kltimg_aff_diff_win%03d.%03d_3.pgm", glob_index,counter);
+ snprintf(fname, sizeof(fname), "./debug/kltimg_aff_diff_win%03d.%03d_3.pgm", glob_index,counter);
printf("%s\n", fname);
_KLTWriteAbsFloatImageToPGM(aff_diff_win, fname,256.0);
@@ -1335,17 +1335,17 @@ void KLTTrackFeatures(
if (tc->writeInternalImages) {
char fname[80];
for (i = 0 ; i < tc->nPyramidLevels ; i++) {
- sprintf(fname, "kltimg_tf_i%d.pgm", i);
+ snprintf(fname, sizeof(fname), "kltimg_tf_i%d.pgm", i);
_KLTWriteFloatImageToPGM(pyramid1->img[i], fname);
- sprintf(fname, "kltimg_tf_i%d_gx.pgm", i);
+ snprintf(fname, sizeof(fname), "kltimg_tf_i%d_gx.pgm", i);
_KLTWriteFloatImageToPGM(pyramid1_gradx->img[i], fname);
- sprintf(fname, "kltimg_tf_i%d_gy.pgm", i);
+ snprintf(fname, sizeof(fname), "kltimg_tf_i%d_gy.pgm", i);
_KLTWriteFloatImageToPGM(pyramid1_grady->img[i], fname);
- sprintf(fname, "kltimg_tf_j%d.pgm", i);
+ snprintf(fname, sizeof(fname), "kltimg_tf_j%d.pgm", i);
_KLTWriteFloatImageToPGM(pyramid2->img[i], fname);
- sprintf(fname, "kltimg_tf_j%d_gx.pgm", i);
+ snprintf(fname, sizeof(fname), "kltimg_tf_j%d_gx.pgm", i);
_KLTWriteFloatImageToPGM(pyramid2_gradx->img[i], fname);
- sprintf(fname, "kltimg_tf_j%d_gy.pgm", i);
+ snprintf(fname, sizeof(fname), "kltimg_tf_j%d_gy.pgm", i);
_KLTWriteFloatImageToPGM(pyramid2_grady->img[i], fname);
}
}
diff --git a/rtengine/klt/writeFeatures.cc b/rtengine/klt/writeFeatures.cc
index 1bfe3f20f..d3bf6f3d4 100644
--- a/rtengine/klt/writeFeatures.cc
+++ b/rtengine/klt/writeFeatures.cc
@@ -97,6 +97,7 @@ static FILE* _printSetupTxt(
const char *fname, /* Input: filename, or NULL for stderr */
const char *fmt, /* Input: format (e.g., %5.1f or %3d) */
char *format, /* Output: format (e.g., (%5.1f,%5.1f)=%3d) */
+ std::size_t format_size,
char *type) /* Output: either 'f' or 'd', based on input format */
{
FILE *fp;
@@ -124,7 +125,7 @@ static FILE* _printSetupTxt(
}
/* Construct feature format */
- sprintf(format, "(%s,%s)=%%%dd ", fmt, fmt, val_width);
+ snprintf(format, format_size, "(%s,%s)=%%%dd ", fmt, fmt, val_width);
return fp;
}
@@ -163,7 +164,7 @@ static void _printInteger(
int width)
{
char fmt[80];
- sprintf(fmt, "%%%dd", width);
+ snprintf(fmt, sizeof(fmt), "%%%dd", width);
fprintf(fp, fmt, integer);
}
@@ -358,7 +359,7 @@ void KLTWriteFeatureList(
}
if (fmt != nullptr) { /* text file or stderr */
- fp = _printSetupTxt(fname, fmt, format, &type);
+ fp = _printSetupTxt(fname, fmt, format, sizeof(format), &type);
_printHeader(fp, format, FEATURE_LIST, 0, fl->nFeatures);
for (i = 0 ; i < fl->nFeatures ; i++) {
@@ -396,7 +397,7 @@ void KLTWriteFeatureHistory(
}
if (fmt != nullptr) { /* text file or stderr */
- fp = _printSetupTxt(fname, fmt, format, &type);
+ fp = _printSetupTxt(fname, fmt, format, sizeof(format), &type);
_printHeader(fp, format, FEATURE_HISTORY, fh->nFrames, 0);
for (i = 0 ; i < fh->nFrames ; i++) {
@@ -435,7 +436,7 @@ void KLTWriteFeatureTable(
}
if (fmt != nullptr) { /* text file or stderr */
- fp = _printSetupTxt(fname, fmt, format, &type);
+ fp = _printSetupTxt(fname, fmt, format, sizeof(format), &type);
_printHeader(fp, format, FEATURE_TABLE, ft->nFrames, ft->nFeatures);
for (j = 0 ; j < ft->nFeatures ; j++) {
diff --git a/rtengine/myfile.h b/rtengine/myfile.h
index 423edea9a..34b90c525 100644
--- a/rtengine/myfile.h
+++ b/rtengine/myfile.h
@@ -107,13 +107,13 @@ inline int getc (IMFILE* f)
return fgetc(f);
}
-inline int fread (void* dst, int es, int count, IMFILE* f)
+inline int fread (void* dst, size_t es, size_t count, IMFILE* f)
{
- int s = es * count;
- int avail = f->size - f->pos;
+ size_t s = es * count;
+ size_t avail = static_cast(f->size) - static_cast(f->pos);
- if (s <= avail) {
+ if (static_cast(s) <= static_cast(avail)) {
memcpy (dst, f->data + f->pos, s);
f->pos += s;
diff --git a/rtengine/perspectivecorrection.cc b/rtengine/perspectivecorrection.cc
index 5fa7b32f3..7a56ef5a8 100644
--- a/rtengine/perspectivecorrection.cc
+++ b/rtengine/perspectivecorrection.cc
@@ -225,10 +225,44 @@ void get_view_size(int w, int h, const procparams::PerspectiveParams ¶ms, do
}
*/
+/**
+ * Allocates a new array and populates it with ashift lines corresponding to the
+ * provided control lines.
+ */
+std::unique_ptr toAshiftLines(const std::vector *lines)
+{
+ std::unique_ptr retval(new dt_iop_ashift_line_t[lines->size()]);
+
+ for (size_t i = 0; i < lines->size(); i++) {
+ const float x1 = (*lines)[i].x1;
+ const float y1 = (*lines)[i].y1;
+ const float x2 = (*lines)[i].x2;
+ const float y2 = (*lines)[i].y2;
+ retval[i].p1[0] = x1;
+ retval[i].p1[1] = y1;
+ retval[i].p1[2] = 1.0f;
+ retval[i].p2[0] = x2;
+ retval[i].p2[1] = y2;
+ retval[i].p2[2] = 1.0f;
+ retval[i].length = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+ retval[i].width = 1.0f;
+ retval[i].weight = retval[i].length;
+ if ((*lines)[i].type == ControlLine::HORIZONTAL) {
+ retval[i].type = ASHIFT_LINE_HORIZONTAL_SELECTED;
+ } else if ((*lines)[i].type == ControlLine::VERTICAL) {
+ retval[i].type = ASHIFT_LINE_VERTICAL_SELECTED;
+ } else {
+ retval[i].type = ASHIFT_LINE_IRRELEVANT;
+ }
+ }
+
+ return retval;
+}
+
} // namespace
-PerspectiveCorrection::Params PerspectiveCorrection::autocompute(ImageSource *src, bool corr_pitch, bool corr_yaw, const procparams::ProcParams *pparams, const FramesMetaData *metadata)
+PerspectiveCorrection::Params PerspectiveCorrection::autocompute(ImageSource *src, bool corr_pitch, bool corr_yaw, const procparams::ProcParams *pparams, const FramesMetaData *metadata, const std::vector *control_lines)
{
auto pcp = procparams::PerspectiveParams(pparams->perspective);
procparams::PerspectiveParams dflt;
@@ -252,49 +286,51 @@ PerspectiveCorrection::Params PerspectiveCorrection::autocompute(ImageSource *sr
int tr = getCoarseBitMask(pparams->coarse);
int fw, fh;
src->getFullSize(fw, fh, tr);
- int skip = max(float(max(fw, fh)) / 900.f + 0.5f, 1.f);
- PreviewProps pp(0, 0, fw, fh, skip);
- int w, h;
- src->getSize(pp, w, h);
- std::unique_ptr img(new Imagefloat(w, h));
+ if (control_lines == nullptr) {
+ int skip = max(float(max(fw, fh)) / 900.f + 0.5f, 1.f);
+ PreviewProps pp(0, 0, fw, fh, skip);
+ int w, h;
+ src->getSize(pp, w, h);
+ std::unique_ptr img(new Imagefloat(w, h));
- ProcParams neutral;
- neutral.raw.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::FAST);
- neutral.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST);
- neutral.icm.outputProfile = ColorManagementParams::NoICMString;
- src->getImage(src->getWB(), tr, img.get(), pp, neutral.toneCurve, neutral.raw);
- src->convertColorSpace(img.get(), pparams->icm, src->getWB());
+ ProcParams neutral;
+ neutral.raw.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::FAST);
+ neutral.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST);
+ neutral.icm.outputProfile = ColorManagementParams::NoICMString;
+ src->getImage(src->getWB(), tr, img.get(), pp, neutral.toneCurve, neutral.raw);
+ src->convertColorSpace(img.get(), pparams->icm, src->getWB());
- neutral.commonTrans.autofill = false; // Ensures crop factor is correct.
- // TODO: Ensure image borders of rotated image do not get detected as lines.
- neutral.rotate = pparams->rotate;
- neutral.distortion = pparams->distortion;
- neutral.lensProf = pparams->lensProf;
- ImProcFunctions ipf(&neutral, true);
- if (ipf.needsTransform(w, h, src->getRotateDegree(), src->getMetaData())) {
- Imagefloat *tmp = new Imagefloat(w, h);
- ipf.transform(img.get(), tmp, 0, 0, 0, 0, w, h, w, h,
- src->getMetaData(), src->getRotateDegree(), false);
- img.reset(tmp);
- }
+ neutral.commonTrans.autofill = false; // Ensures crop factor is correct.
+ // TODO: Ensure image borders of rotated image do not get detected as lines.
+ neutral.rotate = pparams->rotate;
+ neutral.distortion = pparams->distortion;
+ neutral.lensProf = pparams->lensProf;
+ ImProcFunctions ipf(&neutral, true);
+ if (ipf.needsTransform(w, h, src->getRotateDegree(), src->getMetaData())) {
+ Imagefloat *tmp = new Imagefloat(w, h);
+ ipf.transform(img.get(), tmp, 0, 0, 0, 0, w, h, w, h,
+ src->getMetaData(), src->getRotateDegree(), false);
+ img.reset(tmp);
+ }
- // allocate the gui buffer
- g.buf = static_cast(malloc(sizeof(float) * w * h * 4));
- g.buf_width = w;
- g.buf_height = h;
+ // allocate the gui buffer
+ g.buf = static_cast(malloc(sizeof(float) * w * h * 4));
+ g.buf_width = w;
+ g.buf_height = h;
+
+ img->normalizeFloatTo1();
- img->normalizeFloatTo1();
-
#ifdef _OPENMP
# pragma omp parallel for
#endif
- for (int y = 0; y < h; ++y) {
- for (int x = 0; x < w; ++x) {
- int i = (y * w + x) * 4;
- g.buf[i] = img->r(y, x);
- g.buf[i+1] = img->g(y, x);
- g.buf[i+2] = img->b(y, x);
- g.buf[i+3] = 1.f;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ int i = (y * w + x) * 4;
+ g.buf[i] = img->r(y, x);
+ g.buf[i+1] = img->g(y, x);
+ g.buf[i+2] = img->b(y, x);
+ g.buf[i+3] = 1.f;
+ }
}
}
@@ -311,7 +347,20 @@ PerspectiveCorrection::Params PerspectiveCorrection::autocompute(ImageSource *sr
// internally!
srand(1);
- auto res = do_get_structure(&module, &p, ASHIFT_ENHANCE_EDGES) && do_fit(&module, &p, fitaxis);
+ bool res;
+ if (control_lines == nullptr) {
+ res = do_get_structure(&module, &p, ASHIFT_ENHANCE_EDGES) && do_fit(&module, &p, fitaxis);
+ } else {
+ std::unique_ptr ashift_lines = toAshiftLines(control_lines);
+ dt_iop_ashift_gui_data_t *g = module.gui_data;
+ g->lines_count = control_lines->size();
+ g->lines = ashift_lines.get();
+ g->lines_in_height = fh;
+ g->lines_in_width = fw;
+ update_lines_count(g->lines, g->lines_count, &(g->vertical_count), &(g->horizontal_count));
+ res = do_fit(&module, &p, fitaxis, 2);
+ g->lines = nullptr;
+ }
Params retval = {
.angle = p.rotation,
.pitch = p.camera_pitch,
@@ -322,7 +371,7 @@ PerspectiveCorrection::Params PerspectiveCorrection::autocompute(ImageSource *sr
if (g.lines) free(g.lines);
if (g.points) free(g.points);
if (g.points_idx) free(g.points_idx);
- free(g.buf);
+ if (g.buf) free(g.buf);
if (!res) {
retval.angle = pparams->perspective.camera_roll;
diff --git a/rtengine/perspectivecorrection.h b/rtengine/perspectivecorrection.h
index bf7cfa08d..f092f2c8c 100644
--- a/rtengine/perspectivecorrection.h
+++ b/rtengine/perspectivecorrection.h
@@ -20,12 +20,32 @@
#pragma once
-#include "coord2d.h"
-#include "procparams.h"
-#include "imagesource.h"
+#include
namespace rtengine {
+namespace procparams
+{
+
+class ProcParams;
+
+}
+
+class ImageSource;
+class FramesMetaData;
+
+class ControlLine
+{
+public:
+ enum Type
+ {
+ HORIZONTAL,
+ VERTICAL
+ };
+ float x1, y1, x2, y2;
+ Type type;
+};
+
class PerspectiveCorrection {
public:
struct Params
@@ -35,7 +55,7 @@ public:
double yaw;
};
- static Params autocompute(ImageSource *src, bool corr_pitch, bool corr_yaw, const procparams::ProcParams *pparams, const FramesMetaData *metadata);
+ static Params autocompute(ImageSource *src, bool corr_pitch, bool corr_yaw, const procparams::ProcParams *pparams, const FramesMetaData *metadata, const std::vector *control_lines = nullptr);
//static void autocrop(int width, int height, bool fixratio, const procparams::PerspectiveParams ¶ms, const FramesMetaData *metadata, int &x, int &y, int &w, int &h);
};
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index b64748d22..22b967ee7 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -979,6 +979,17 @@ enum ProcEventCode {
EvLocallabSpotprevMethod = 953,
Evlocallabactiv = 954,
EvlocallabCHshape = 955,
+ EvlocallabquaMethod = 956,
+ Evlocallabhishow = 957,
+ Evlocallabinvbl = 958,
+ Evlocallabcatad = 959,
+ Evlocallabciecam = 960,
+ Evlocallabsourceabs = 961,
+ Evlocallabtargabs = 962,
+ Evlocallabsurround = 963,
+ Evlocallabsaturl = 964,
+ Evlocallabcontl = 965,
+
NUMOFEVENTS
};
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index acad7d34d..7a56248bf 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -1375,6 +1375,7 @@ ColorAppearanceParams::ColorAppearanceParams() :
curveMode(TcMode::LIGHT),
curveMode2(TcMode::LIGHT),
curveMode3(CtcMode::CHROMA),
+ complexmethod("normal"),
surround("Average"),
surrsrc("Average"),
adapscen(2000.0),
@@ -1423,6 +1424,7 @@ bool ColorAppearanceParams::operator ==(const ColorAppearanceParams& other) cons
&& curveMode == other.curveMode
&& curveMode2 == other.curveMode2
&& curveMode3 == other.curveMode3
+ && complexmethod == other.complexmethod
&& surround == other.surround
&& surrsrc == other.surrsrc
&& adapscen == other.adapscen
@@ -1870,6 +1872,7 @@ LensProfParams::LcMode LensProfParams::getMethodNumber(const Glib::ustring& mode
PerspectiveParams::PerspectiveParams() :
method("simple"),
+ render(true),
horizontal(0.0),
vertical(0.0),
camera_crop_factor(0.0),
@@ -1891,6 +1894,7 @@ bool PerspectiveParams::operator ==(const PerspectiveParams& other) const
{
return
method == other.method
+ && render == other.render
&& horizontal == other.horizontal
&& vertical == other.vertical
&& camera_focal_length == other.camera_focal_length
@@ -1904,7 +1908,12 @@ bool PerspectiveParams::operator ==(const PerspectiveParams& other) const
&& projection_shift_vert == other.projection_shift_vert
&& projection_rotate == other.projection_rotate
&& projection_pitch == other.projection_pitch
- && projection_yaw == other.projection_yaw;
+ && projection_yaw == other.projection_yaw
+ // Lines could still be equivalent if the vectors aren't, but this is
+ // rare and a small issue. Besides, a proper comparison requires lots
+ // more code which introduces clutter.
+ && control_line_values == other.control_line_values
+ && control_line_types == other.control_line_types;
}
bool PerspectiveParams::operator !=(const PerspectiveParams& other) const
@@ -2204,6 +2213,36 @@ WaveletParams::WaveletParams() :
0.35,
0.35
},
+ wavdenoise{
+ static_cast(FCT_MinMaxCPoints),
+ 0.0,
+ 1.0,
+ 0.35,
+ 0.35,
+ 0.50,
+ 1.0,
+ 0.35,
+ 0.35,
+ 1.0,
+ 1.0,
+ 0.35,
+ 0.35
+ },
+ wavdenoiseh{
+ static_cast(FCT_MinMaxCPoints),
+ 0.0,
+ 1.0,
+ 0.35,
+ 0.35,
+ 0.50,
+ 1.0,
+ 0.35,
+ 0.35,
+ 1.0,
+ 1.0,
+ 0.35,
+ 0.35
+ },
blcurve{
static_cast(FCT_MinMaxCPoints),
0.0,
@@ -2339,6 +2378,12 @@ WaveletParams::WaveletParams() :
hhcurve{
FCT_Linear
},
+ wavguidcurve{
+ FCT_Linear
+ },
+ wavhuecurve{
+ FCT_Linear
+ },
Chcurve{
FCT_Linear
},
@@ -2357,6 +2402,10 @@ WaveletParams::WaveletParams() :
greenhigh(0),
bluehigh(0),
ballum(7.),
+ sigm(1.0),
+ levden(0.),
+ thrden(0.),
+ limden(0.),
balchrom(0.),
chromfi(0.),
chromco(0.),
@@ -2364,6 +2413,9 @@ WaveletParams::WaveletParams() :
mergeC(20.),
softrad(0.),
softradend(0.),
+ strend(50.),
+ detend(0),
+ thrend(0),
lipst(false),
avoid(false),
showmask(false),
@@ -2398,6 +2450,10 @@ WaveletParams::WaveletParams() :
Backmethod("grey"),
Tilesmethod("full"),
complexmethod("normal"),
+ denmethod("12low"),
+ mixmethod("mix"),
+ slimethod("sli"),
+ quamethod("cons"),
daubcoeffmethod("4_"),
CHmethod("without"),
Medgreinf("less"),
@@ -2454,7 +2510,9 @@ WaveletParams::WaveletParams() :
level0noise(0, 0, false),
level1noise(0, 0, false),
level2noise(0, 0, false),
- level3noise(0, 0, false)
+ level3noise(0, 0, false),
+ leveldenoise(0, 0, false),
+ levelsigm(1, 1, false)
{
}
@@ -2462,6 +2520,8 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
{
return
ccwcurve == other.ccwcurve
+ && wavdenoise == other.wavdenoise
+ && wavdenoiseh == other.wavdenoiseh
&& blcurve == other.blcurve
&& opacityCurveRG == other.opacityCurveRG
&& opacityCurveSH == other.opacityCurveSH
@@ -2469,6 +2529,8 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& opacityCurveW == other.opacityCurveW
&& opacityCurveWL == other.opacityCurveWL
&& hhcurve == other.hhcurve
+ && wavguidcurve == other.wavguidcurve
+ && wavhuecurve == other.wavhuecurve
&& Chcurve == other.Chcurve
&& wavclCurve == other.wavclCurve
&& enabled == other.enabled
@@ -2483,6 +2545,10 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& greenhigh == other.greenhigh
&& bluehigh == other.bluehigh
&& ballum == other.ballum
+ && sigm == other.sigm
+ && levden == other.levden
+ && thrden == other.thrden
+ && limden == other.limden
&& balchrom == other.balchrom
&& chromfi == other.chromfi
&& chromco == other.chromco
@@ -2490,6 +2556,9 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& mergeC == other.mergeC
&& softrad == other.softrad
&& softradend == other.softradend
+ && strend == other.strend
+ && detend == other.detend
+ && thrend == other.thrend
&& lipst == other.lipst
&& avoid == other.avoid
&& showmask == other.showmask
@@ -2531,6 +2600,10 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& Backmethod == other.Backmethod
&& Tilesmethod == other.Tilesmethod
&& complexmethod == other.complexmethod
+ && denmethod == other.denmethod
+ && mixmethod == other.mixmethod
+ && slimethod == other.slimethod
+ && quamethod == other.quamethod
&& daubcoeffmethod == other.daubcoeffmethod
&& CHmethod == other.CHmethod
&& Medgreinf == other.Medgreinf
@@ -2587,7 +2660,9 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& level0noise == other.level0noise
&& level1noise == other.level1noise
&& level2noise == other.level2noise
- && level3noise == other.level3noise;
+ && level3noise == other.level3noise
+ && leveldenoise == other.leveldenoise
+ && levelsigm == other.levelsigm;
}
bool WaveletParams::operator !=(const WaveletParams& other) const
@@ -2597,6 +2672,8 @@ bool WaveletParams::operator !=(const WaveletParams& other) const
void WaveletParams::getCurves(
WavCurve& cCurve,
+ WavCurve& wavdenoise,
+ WavCurve& wavdenoiseh,
Wavblcurve& tCurve,
WavOpacityCurveRG& opacityCurveLUTRG,
WavOpacityCurveSH& opacityCurveLUTSH,
@@ -2606,6 +2683,8 @@ void WaveletParams::getCurves(
) const
{
cCurve.Set(this->ccwcurve);
+ wavdenoise.Set(this->wavdenoise);
+ wavdenoiseh.Set(this->wavdenoiseh);
tCurve.Set(this->blcurve);
opacityCurveLUTRG.Set(this->opacityCurveRG);
opacityCurveLUTSH.Set(this->opacityCurveSH);
@@ -2643,6 +2722,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
colorscope(30.0),
transitweak(1.0),
transitgrad(0.0),
+ hishow(false),
activ(true),
avoid(false),
blwh(false),
@@ -2810,7 +2890,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
},
invers(false),
special(false),
- toolcol(true),
+ toolcol(false),
enaColorMask(false),
fftColorMask(true),
CCmaskcurve{
@@ -3175,6 +3255,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
epsbl(0),
blMethod("blur"),
chroMethod("lum"),
+ quamethod("cons"),
blurMethod("norm"),
medMethod("33"),
activlum(true),
@@ -3254,6 +3335,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
},
enablMask(false),
fftwbl(false),
+ invbl(false),
toolbl(false),
blendmaskbl(0),
radmaskbl(0.0),
@@ -3755,13 +3837,20 @@ LocallabParams::LocallabSpot::LocallabSpot() :
explog(false),
autocompute(false),
sourceGray(10.),
+ sourceabs(2000.),
+ targabs(16.),
targetGray(18.),
+ catad(0.),
+ saturl(0.),
+ contl(0.),
Autogray(true),
fullimage(true),
+ ciecam(false),
blackEv(-5.0),
whiteEv(10.0),
detail(0.6),
sensilog(60),
+ surround("Average"),
baselog(2.),
strlog(0.0),
anglog(0.0),
@@ -3823,7 +3912,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
0.35
},
strumaskmask(0.),
- toolmask(true),
+ toolmask(false),
radmask(0.0),
lapmask(0.0),
chromask(0.0),
@@ -3900,6 +3989,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& colorscope == other.colorscope
&& transitweak == other.transitweak
&& transitgrad == other.transitgrad
+ && hishow == other.hishow
&& activ == other.activ
&& avoid == other.avoid
&& blwh == other.blwh
@@ -4109,6 +4199,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& epsbl == other.epsbl
&& blMethod == other.blMethod
&& chroMethod == other.chroMethod
+ && quamethod == other.quamethod
&& blurMethod == other.blurMethod
&& medMethod == other.medMethod
&& activlum == other.activlum
@@ -4132,6 +4223,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& HHmaskblcurve == other.HHmaskblcurve
&& enablMask == other.enablMask
&& fftwbl == other.fftwbl
+ && invbl == other.invbl
&& toolbl == other.toolbl
&& blendmaskbl == other.blendmaskbl
&& radmaskbl == other.radmaskbl
@@ -4329,14 +4421,21 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& explog == other.explog
&& autocompute == other.autocompute
&& sourceGray == other.sourceGray
+ && sourceabs == other.sourceabs
+ && targabs == other.targabs
&& targetGray == other.targetGray
+ && catad == other.catad
+ && saturl == other.saturl
+ && contl == other.contl
&& Autogray == other.Autogray
&& fullimage == other.fullimage
+ && ciecam == other.ciecam
&& blackEv == other.blackEv
&& whiteEv == other.whiteEv
&& detail == other.detail
&& sensilog == other.sensilog
&& baselog == other.baselog
+ && surround == other.surround
&& strlog == other.strlog
&& anglog == other.anglog
// mask
@@ -4633,10 +4732,13 @@ const std::vector& RAWParams::BayerSensor::getMethodStrings()
{
static const std::vector method_strings {
"amaze",
+ "amazebilinear",
"amazevng4",
"rcd",
+ "rcdbilinear",
"rcdvng4",
"dcb",
+ "dcbbilinear",
"dcbvng4",
"lmmse",
"igv",
@@ -5196,6 +5298,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->colorappearance.degreeout, "Color appearance", "Degreeout", colorappearance.degreeout, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.autodegreeout, "Color appearance", "AutoDegreeout", colorappearance.autodegreeout, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.surround, "Color appearance", "Surround", colorappearance.surround, keyFile);
+ saveToKeyfile(!pedited || pedited->colorappearance.complexmethod, "Color appearance", "complex", colorappearance.complexmethod, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.surrsrc, "Color appearance", "Surrsrc", colorappearance.surrsrc, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.adaplum, "Color appearance", "AdaptLum", colorappearance.adaplum, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.badpixsl, "Color appearance", "Badpixsl", colorappearance.badpixsl, keyFile);
@@ -5375,6 +5478,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->perspective.projection_shift_horiz, "Perspective", "ProjectionShiftHorizontal", perspective.projection_shift_horiz, keyFile);
saveToKeyfile(!pedited || pedited->perspective.projection_shift_vert, "Perspective", "ProjectionShiftVertical", perspective.projection_shift_vert, keyFile);
saveToKeyfile(!pedited || pedited->perspective.projection_yaw, "Perspective", "ProjectionYaw", perspective.projection_yaw, keyFile);
+ saveToKeyfile(!pedited || pedited->perspective.control_lines, "Perspective", "ControlLineValues", perspective.control_line_values, keyFile);
+ saveToKeyfile(!pedited || pedited->perspective.control_lines, "Perspective", "ControlLineTypes", perspective.control_line_types, keyFile);
// Gradient
saveToKeyfile(!pedited || pedited->gradient.enabled, "Gradient", "Enabled", gradient.enabled, keyFile);
@@ -5423,6 +5528,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->colorscope, "Locallab", "Colorscope_" + index_str, spot.colorscope, keyFile);
saveToKeyfile(!pedited || spot_edited->transitweak, "Locallab", "Transitweak_" + index_str, spot.transitweak, keyFile);
saveToKeyfile(!pedited || spot_edited->transitgrad, "Locallab", "Transitgrad_" + index_str, spot.transitgrad, keyFile);
+ saveToKeyfile(!pedited || spot_edited->hishow, "Locallab", "Hishow_" + index_str, spot.hishow, keyFile);
saveToKeyfile(!pedited || spot_edited->activ, "Locallab", "Activ_" + index_str, spot.activ, keyFile);
saveToKeyfile(!pedited || spot_edited->avoid, "Locallab", "Avoid_" + index_str, spot.avoid, keyFile);
saveToKeyfile(!pedited || spot_edited->blwh, "Locallab", "Blwh_" + index_str, spot.blwh, keyFile);
@@ -5632,6 +5738,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->epsbl, "Locallab", "Epsbl_" + index_str, spot.epsbl, keyFile);
saveToKeyfile(!pedited || spot_edited->blMethod, "Locallab", "BlMethod_" + index_str, spot.blMethod, keyFile);
saveToKeyfile(!pedited || spot_edited->chroMethod, "Locallab", "ChroMethod_" + index_str, spot.chroMethod, keyFile);
+ saveToKeyfile(!pedited || spot_edited->quamethod, "Locallab", "QuaMethod_" + index_str, spot.quamethod, keyFile);
saveToKeyfile(!pedited || spot_edited->blurMethod, "Locallab", "BlurMethod_" + index_str, spot.blurMethod, keyFile);
saveToKeyfile(!pedited || spot_edited->medMethod, "Locallab", "MedMethod_" + index_str, spot.medMethod, keyFile);
saveToKeyfile(!pedited || spot_edited->activlum, "Locallab", "activlum_" + index_str, spot.activlum, keyFile);
@@ -5655,6 +5762,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->HHmaskblcurve, "Locallab", "HHmaskblCurve_" + index_str, spot.HHmaskblcurve, keyFile);
saveToKeyfile(!pedited || spot_edited->enablMask, "Locallab", "EnablMask_" + index_str, spot.enablMask, keyFile);
saveToKeyfile(!pedited || spot_edited->fftwbl, "Locallab", "Fftwbl_" + index_str, spot.fftwbl, keyFile);
+ saveToKeyfile(!pedited || spot_edited->invbl, "Locallab", "Invbl_" + index_str, spot.invbl, keyFile);
saveToKeyfile(!pedited || spot_edited->toolbl, "Locallab", "Toolbl_" + index_str, spot.toolbl, keyFile);
saveToKeyfile(!pedited || spot_edited->blendmaskbl, "Locallab", "Blendmaskbl_" + index_str, spot.blendmaskbl, keyFile);
saveToKeyfile(!pedited || spot_edited->radmaskbl, "Locallab", "Radmaskbl_" + index_str, spot.radmaskbl, keyFile);
@@ -5854,14 +5962,21 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->explog, "Locallab", "Explog_" + index_str, spot.explog, keyFile);
saveToKeyfile(!pedited || spot_edited->autocompute, "Locallab", "Autocompute_" + index_str, spot.autocompute, keyFile);
saveToKeyfile(!pedited || spot_edited->sourceGray, "Locallab", "SourceGray_" + index_str, spot.sourceGray, keyFile);
+ saveToKeyfile(!pedited || spot_edited->sourceabs, "Locallab", "Sourceabs_" + index_str, spot.sourceabs, keyFile);
+ saveToKeyfile(!pedited || spot_edited->targabs, "Locallab", "Targabs_" + index_str, spot.targabs, keyFile);
saveToKeyfile(!pedited || spot_edited->targetGray, "Locallab", "TargetGray_" + index_str, spot.targetGray, keyFile);
+ saveToKeyfile(!pedited || spot_edited->catad, "Locallab", "Catad_" + index_str, spot.catad, keyFile);
+ saveToKeyfile(!pedited || spot_edited->saturl, "Locallab", "Saturl_" + index_str, spot.saturl, keyFile);
+ saveToKeyfile(!pedited || spot_edited->contl, "Locallab", "Contl_" + index_str, spot.contl, keyFile);
saveToKeyfile(!pedited || spot_edited->Autogray, "Locallab", "Autogray_" + index_str, spot.Autogray, keyFile);
saveToKeyfile(!pedited || spot_edited->fullimage, "Locallab", "Fullimage_" + index_str, spot.fullimage, keyFile);
+ saveToKeyfile(!pedited || spot_edited->ciecam, "Locallab", "Ciecam_" + index_str, spot.ciecam, keyFile);
saveToKeyfile(!pedited || spot_edited->blackEv, "Locallab", "BlackEv_" + index_str, spot.blackEv, keyFile);
saveToKeyfile(!pedited || spot_edited->whiteEv, "Locallab", "WhiteEv_" + index_str, spot.whiteEv, keyFile);
saveToKeyfile(!pedited || spot_edited->detail, "Locallab", "Detail_" + index_str, spot.detail, keyFile);
saveToKeyfile(!pedited || spot_edited->sensilog, "Locallab", "Sensilog_" + index_str, spot.sensilog, keyFile);
saveToKeyfile(!pedited || spot_edited->baselog, "Locallab", "Baselog_" + index_str, spot.baselog, keyFile);
+ saveToKeyfile(!pedited || spot_edited->surround, "Locallab", "Surround_" + index_str, spot.surround, keyFile);
saveToKeyfile(!pedited || spot_edited->strlog, "Locallab", "Strlog_" + index_str, spot.strlog, keyFile);
saveToKeyfile(!pedited || spot_edited->anglog, "Locallab", "Anglog_" + index_str, spot.anglog, keyFile);
}
@@ -5994,6 +6109,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
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.denmethod, "Wavelet", "denMethod", wavelet.denmethod, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.mixmethod, "Wavelet", "mixMethod", wavelet.mixmethod, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.slimethod, "Wavelet", "sliMethod", wavelet.slimethod, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.quamethod, "Wavelet", "quaMethod", wavelet.quamethod, 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);
@@ -6006,6 +6125,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.bluemed, "Wavelet", "CBbluemed", wavelet.bluemed, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.bluelow, "Wavelet", "CBbluelow", wavelet.bluelow, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.ballum, "Wavelet", "Ballum", wavelet.ballum, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.sigm, "Wavelet", "Sigm", wavelet.sigm, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.levden, "Wavelet", "Levden", wavelet.levden, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.thrden, "Wavelet", "Thrden", wavelet.thrden, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.limden, "Wavelet", "Limden", wavelet.limden, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.balchrom, "Wavelet", "Balchrom", wavelet.balchrom, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.chromfi, "Wavelet", "Chromfine", wavelet.chromfi, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.chromco, "Wavelet", "Chromcoarse", wavelet.chromco, keyFile);
@@ -6013,6 +6136,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.mergeC, "Wavelet", "MergeC", wavelet.mergeC, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.softrad, "Wavelet", "Softrad", wavelet.softrad, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.softradend, "Wavelet", "Softradend", wavelet.softradend, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.strend, "Wavelet", "Strend", wavelet.strend, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.detend, "Wavelet", "Detend", wavelet.detend, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.thrend, "Wavelet", "Thrend", wavelet.thrend, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expcontrast, "Wavelet", "Expcontrast", wavelet.expcontrast, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expchroma, "Wavelet", "Expchroma", wavelet.expchroma, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.expedge, "Wavelet", "Expedge", wavelet.expedge, keyFile);
@@ -6050,6 +6176,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.level1noise, "Wavelet", "Level1noise", wavelet.level1noise.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.level2noise, "Wavelet", "Level2noise", wavelet.level2noise.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.level3noise, "Wavelet", "Level3noise", wavelet.level3noise.toVector(), keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.leveldenoise, "Wavelet", "Leveldenoise", wavelet.leveldenoise.toVector(), keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.levelsigm, "Wavelet", "Levelsigm", wavelet.levelsigm.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.threshold, "Wavelet", "ThresholdHighlight", wavelet.threshold, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.threshold2, "Wavelet", "ThresholdShadow", wavelet.threshold2, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.edgedetect, "Wavelet", "Edgedetect", wavelet.edgedetect, keyFile);
@@ -6074,9 +6202,13 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveRG, "Wavelet", "OpacityCurveRG", wavelet.opacityCurveRG, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveSH, "Wavelet", "Levalshc", wavelet.opacityCurveSH, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveBY, "Wavelet", "OpacityCurveBY", wavelet.opacityCurveBY, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.wavdenoise, "Wavelet", "wavdenoise", wavelet.wavdenoise, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.wavdenoiseh, "Wavelet", "wavdenoiseh", wavelet.wavdenoiseh, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveW, "Wavelet", "OpacityCurveW", wavelet.opacityCurveW, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveWL, "Wavelet", "OpacityCurveWL", wavelet.opacityCurveWL, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.hhcurve, "Wavelet", "HHcurve", wavelet.hhcurve, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.wavguidcurve, "Wavelet", "Wavguidcurve", wavelet.wavguidcurve, keyFile);
+ saveToKeyfile(!pedited || pedited->wavelet.wavhuecurve, "Wavelet", "Wavhuecurve", wavelet.wavhuecurve, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.Chcurve, "Wavelet", "CHcurve", wavelet.Chcurve, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.wavclCurve, "Wavelet", "WavclCurve", wavelet.wavclCurve, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.median, "Wavelet", "Median", wavelet.median, keyFile);
@@ -6755,6 +6887,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Color appearance", "AutoDegreeout", pedited, colorappearance.autodegreeout, pedited->colorappearance.autodegreeout);
+ assignFromKeyfile(keyFile, "Color appearance", "complex", pedited, colorappearance.complexmethod, pedited->colorappearance.complexmethod);
assignFromKeyfile(keyFile, "Color appearance", "Surround", pedited, colorappearance.surround, pedited->colorappearance.surround);
assignFromKeyfile(keyFile, "Color appearance", "Surrsrc", pedited, colorappearance.surrsrc, pedited->colorappearance.surrsrc);
assignFromKeyfile(keyFile, "Color appearance", "AdaptLum", pedited, colorappearance.adaplum, pedited->colorappearance.adaplum);
@@ -7038,6 +7171,13 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Perspective", "ProjectionShiftHorizontal", pedited, perspective.projection_shift_horiz, pedited->perspective.projection_shift_horiz);
assignFromKeyfile(keyFile, "Perspective", "ProjectionShiftVertical", pedited, perspective.projection_shift_vert, pedited->perspective.projection_shift_vert);
assignFromKeyfile(keyFile, "Perspective", "ProjectionYaw", pedited, perspective.projection_yaw, pedited->perspective.projection_yaw);
+ if (keyFile.has_key("Perspective", "ControlLineValues") && keyFile.has_key("Perspective", "ControlLineTypes")) {
+ perspective.control_line_values = keyFile.get_integer_list("Perspective", "ControlLineValues");
+ perspective.control_line_types = keyFile.get_integer_list("Perspective", "ControlLineTypes");
+ if (pedited) {
+ pedited->perspective.control_lines = true;
+ }
+ }
}
if (keyFile.has_group("Gradient")) {
@@ -7092,6 +7232,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Colorscope_" + index_str, pedited, spot.colorscope, spotEdited.colorscope);
assignFromKeyfile(keyFile, "Locallab", "Transitweak_" + index_str, pedited, spot.transitweak, spotEdited.transitweak);
assignFromKeyfile(keyFile, "Locallab", "Transitgrad_" + index_str, pedited, spot.transitgrad, spotEdited.transitgrad);
+ assignFromKeyfile(keyFile, "Locallab", "Hishow_" + index_str, pedited, spot.hishow, spotEdited.hishow);
assignFromKeyfile(keyFile, "Locallab", "Activ_" + index_str, pedited, spot.activ, spotEdited.activ);
assignFromKeyfile(keyFile, "Locallab", "Avoid_" + index_str, pedited, spot.avoid, spotEdited.avoid);
assignFromKeyfile(keyFile, "Locallab", "Blwh_" + index_str, pedited, spot.blwh, spotEdited.blwh);
@@ -7342,6 +7483,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Epsbl_" + index_str, pedited, spot.epsbl, spotEdited.epsbl);
assignFromKeyfile(keyFile, "Locallab", "BlMethod_" + index_str, pedited, spot.blMethod, spotEdited.blMethod);
assignFromKeyfile(keyFile, "Locallab", "ChroMethod_" + index_str, pedited, spot.chroMethod, spotEdited.chroMethod);
+ assignFromKeyfile(keyFile, "Locallab", "QuaMethod_" + index_str, pedited, spot.quamethod, spotEdited.quamethod);
assignFromKeyfile(keyFile, "Locallab", "BlurMethod_" + index_str, pedited, spot.blurMethod, spotEdited.blurMethod);
assignFromKeyfile(keyFile, "Locallab", "MedMethod_" + index_str, pedited, spot.medMethod, spotEdited.medMethod);
assignFromKeyfile(keyFile, "Locallab", "activlum_" + index_str, pedited, spot.activlum, spotEdited.activlum);
@@ -7365,6 +7507,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "HHmaskblCurve_" + index_str, pedited, spot.HHmaskblcurve, spotEdited.HHmaskblcurve);
assignFromKeyfile(keyFile, "Locallab", "EnablMask_" + index_str, pedited, spot.enablMask, spotEdited.enablMask);
assignFromKeyfile(keyFile, "Locallab", "Fftwbl_" + index_str, pedited, spot.fftwbl, spotEdited.fftwbl);
+ assignFromKeyfile(keyFile, "Locallab", "Invbl_" + index_str, pedited, spot.invbl, spotEdited.invbl);
assignFromKeyfile(keyFile, "Locallab", "Toolbl_" + index_str, pedited, spot.toolbl, spotEdited.toolbl);
assignFromKeyfile(keyFile, "Locallab", "Blendmaskbl_" + index_str, pedited, spot.blendmaskbl, spotEdited.blendmaskbl);
assignFromKeyfile(keyFile, "Locallab", "Radmaskbl_" + index_str, pedited, spot.radmaskbl, spotEdited.radmaskbl);
@@ -7602,14 +7745,21 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Autocompute_" + index_str, pedited, spot.autocompute, spotEdited.autocompute);
assignFromKeyfile(keyFile, "Locallab", "SourceGray_" + index_str, pedited, spot.sourceGray, spotEdited.sourceGray);
+ assignFromKeyfile(keyFile, "Locallab", "Sourceabs_" + index_str, pedited, spot.sourceabs, spotEdited.sourceabs);
+ assignFromKeyfile(keyFile, "Locallab", "Targabs_" + index_str, pedited, spot.targabs, spotEdited.targabs);
assignFromKeyfile(keyFile, "Locallab", "TargetGray_" + index_str, pedited, spot.targetGray, spotEdited.targetGray);
+ assignFromKeyfile(keyFile, "Locallab", "Catad_" + index_str, pedited, spot.catad, spotEdited.catad);
+ assignFromKeyfile(keyFile, "Locallab", "Saturl_" + index_str, pedited, spot.saturl, spotEdited.saturl);
+ assignFromKeyfile(keyFile, "Locallab", "Contl_" + index_str, pedited, spot.contl, spotEdited.contl);
assignFromKeyfile(keyFile, "Locallab", "AutoGray_" + index_str, pedited, spot.Autogray, spotEdited.Autogray);
assignFromKeyfile(keyFile, "Locallab", "Fullimage_" + index_str, pedited, spot.fullimage, spotEdited.fullimage);
+ assignFromKeyfile(keyFile, "Locallab", "Ciecam_" + index_str, pedited, spot.ciecam, spotEdited.ciecam);
assignFromKeyfile(keyFile, "Locallab", "BlackEv_" + index_str, pedited, spot.blackEv, spotEdited.blackEv);
assignFromKeyfile(keyFile, "Locallab", "WhiteEv_" + index_str, pedited, spot.whiteEv, spotEdited.whiteEv);
assignFromKeyfile(keyFile, "Locallab", "Detail_" + index_str, pedited, spot.detail, spotEdited.detail);
assignFromKeyfile(keyFile, "Locallab", "Sensilog_" + index_str, pedited, spot.sensilog, spotEdited.sensilog);
assignFromKeyfile(keyFile, "Locallab", "Baselog_" + index_str, pedited, spot.baselog, spotEdited.baselog);
+ assignFromKeyfile(keyFile, "Locallab", "Surround_" + index_str, pedited, spot.surround, spotEdited.surround);
assignFromKeyfile(keyFile, "Locallab", "Strlog_" + index_str, pedited, spot.strlog, spotEdited.strlog);
assignFromKeyfile(keyFile, "Locallab", "Anglog_" + index_str, pedited, spot.anglog, spotEdited.anglog);
// mask
@@ -7833,6 +7983,10 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "CBbluemed", pedited, wavelet.bluemed, pedited->wavelet.bluemed);
assignFromKeyfile(keyFile, "Wavelet", "CBbluelow", pedited, wavelet.bluelow, pedited->wavelet.bluelow);
assignFromKeyfile(keyFile, "Wavelet", "Ballum", pedited, wavelet.ballum, pedited->wavelet.ballum);
+ assignFromKeyfile(keyFile, "Wavelet", "Sigm", pedited, wavelet.sigm, pedited->wavelet.sigm);
+ assignFromKeyfile(keyFile, "Wavelet", "Levden", pedited, wavelet.levden, pedited->wavelet.levden);
+ assignFromKeyfile(keyFile, "Wavelet", "Thrden", pedited, wavelet.thrden, pedited->wavelet.thrden);
+ assignFromKeyfile(keyFile, "Wavelet", "Limden", pedited, wavelet.limden, pedited->wavelet.limden);
assignFromKeyfile(keyFile, "Wavelet", "Balchrom", pedited, wavelet.balchrom, pedited->wavelet.balchrom);
assignFromKeyfile(keyFile, "Wavelet", "Chromfine", pedited, wavelet.chromfi, pedited->wavelet.chromfi);
assignFromKeyfile(keyFile, "Wavelet", "Chromcoarse", pedited, wavelet.chromco, pedited->wavelet.chromco);
@@ -7840,6 +7994,9 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "MergeC", pedited, wavelet.mergeC, pedited->wavelet.mergeC);
assignFromKeyfile(keyFile, "Wavelet", "Softrad", pedited, wavelet.softrad, pedited->wavelet.softrad);
assignFromKeyfile(keyFile, "Wavelet", "Softradend", pedited, wavelet.softradend, pedited->wavelet.softradend);
+ assignFromKeyfile(keyFile, "Wavelet", "Strend", pedited, wavelet.strend, pedited->wavelet.strend);
+ assignFromKeyfile(keyFile, "Wavelet", "Detend", pedited, wavelet.detend, pedited->wavelet.detend);
+ assignFromKeyfile(keyFile, "Wavelet", "Thrend", pedited, wavelet.thrend, pedited->wavelet.thrend);
assignFromKeyfile(keyFile, "Wavelet", "Lipst", pedited, wavelet.lipst, pedited->wavelet.lipst);
assignFromKeyfile(keyFile, "Wavelet", "AvoidColorShift", pedited, wavelet.avoid, pedited->wavelet.avoid);
assignFromKeyfile(keyFile, "Wavelet", "Showmask", pedited, wavelet.showmask, pedited->wavelet.showmask);
@@ -7866,6 +8023,10 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
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", "denMethod", pedited, wavelet.denmethod, pedited->wavelet.denmethod);
+ assignFromKeyfile(keyFile, "Wavelet", "mixMethod", pedited, wavelet.mixmethod, pedited->wavelet.mixmethod);
+ assignFromKeyfile(keyFile, "Wavelet", "sliMethod", pedited, wavelet.slimethod, pedited->wavelet.slimethod);
+ assignFromKeyfile(keyFile, "Wavelet", "quaMethod", pedited, wavelet.quamethod, pedited->wavelet.quamethod);
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);
@@ -7914,9 +8075,13 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveRG", pedited, wavelet.opacityCurveRG, pedited->wavelet.opacityCurveRG);
assignFromKeyfile(keyFile, "Wavelet", "Levalshc", pedited, wavelet.opacityCurveSH, pedited->wavelet.opacityCurveSH);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveBY", pedited, wavelet.opacityCurveBY, pedited->wavelet.opacityCurveBY);
+ assignFromKeyfile(keyFile, "Wavelet", "wavdenoise", pedited, wavelet.wavdenoise, pedited->wavelet.wavdenoise);
+ assignFromKeyfile(keyFile, "Wavelet", "wavdenoiseh", pedited, wavelet.wavdenoiseh, pedited->wavelet.wavdenoiseh);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveW", pedited, wavelet.opacityCurveW, pedited->wavelet.opacityCurveW);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveWL", pedited, wavelet.opacityCurveWL, pedited->wavelet.opacityCurveWL);
assignFromKeyfile(keyFile, "Wavelet", "HHcurve", pedited, wavelet.hhcurve, pedited->wavelet.hhcurve);
+ assignFromKeyfile(keyFile, "Wavelet", "Wavguidcurve", pedited, wavelet.wavguidcurve, pedited->wavelet.wavguidcurve);
+ assignFromKeyfile(keyFile, "Wavelet", "Wavhuecurve", pedited, wavelet.wavhuecurve, pedited->wavelet.wavhuecurve);
assignFromKeyfile(keyFile, "Wavelet", "CHcurve", pedited, wavelet.Chcurve, pedited->wavelet.Chcurve);
assignFromKeyfile(keyFile, "Wavelet", "WavclCurve", pedited, wavelet.wavclCurve, pedited->wavelet.wavclCurve);
@@ -8028,6 +8193,30 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
}
+ if (keyFile.has_key("Wavelet", "Leveldenoise")) {
+ const std::vector thresh = keyFile.get_double_list("Wavelet", "Leveldenoise");
+
+ if (thresh.size() >= 2) {
+ wavelet.leveldenoise.setValues(thresh[0], thresh[1]);
+ }
+
+ if (pedited) {
+ pedited->wavelet.leveldenoise = true;
+ }
+ }
+
+ if (keyFile.has_key("Wavelet", "Levelsigm")) {
+ const std::vector thresh = keyFile.get_double_list("Wavelet", "Levelsigm");
+
+ if (thresh.size() >= 2) {
+ wavelet.levelsigm.setValues(thresh[0], thresh[1]);
+ }
+
+ if (pedited) {
+ pedited->wavelet.levelsigm = true;
+ }
+ }
+
if (keyFile.has_key("Wavelet", "Pastlev")) {
const std::vector thresh = keyFile.get_integer_list("Wavelet", "Pastlev");
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 0af03eaee..1ba0f5e80 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -672,6 +672,7 @@ struct ColorAppearanceParams {
TcMode curveMode;
TcMode curveMode2;
CtcMode curveMode3;
+ Glib::ustring complexmethod;
Glib::ustring surround;
Glib::ustring surrsrc;
@@ -932,6 +933,7 @@ struct LensProfParams {
*/
struct PerspectiveParams {
Glib::ustring method;
+ bool render;
double horizontal;
double vertical;
double camera_crop_factor;
@@ -946,6 +948,10 @@ struct PerspectiveParams {
double projection_shift_horiz;
double projection_shift_vert;
double projection_yaw;
+ /** A line is stored as 4 integers in this order: x1, y1, x2, y2 */
+ std::vector control_line_values;
+ /** 0 is vertical, 1 is horizontal, undefined otherwise. */
+ std::vector control_line_types;
PerspectiveParams();
@@ -1002,6 +1008,7 @@ struct LocallabParams {
double colorscope;
double transitweak;
double transitgrad;
+ bool hishow;
bool activ;
bool avoid;
bool blwh;
@@ -1203,6 +1210,7 @@ struct LocallabParams {
int epsbl;
Glib::ustring blMethod; // blur, med, guid
Glib::ustring chroMethod; // lum, chr, all
+ Glib::ustring quamethod; // cons agre
Glib::ustring blurMethod; // norm, inv
Glib::ustring medMethod; // none, 33, 55, 77, 99
bool activlum;
@@ -1226,6 +1234,7 @@ struct LocallabParams {
std::vector HHmaskblcurve;
bool enablMask;
bool fftwbl;
+ bool invbl;
bool toolbl;
int blendmaskbl;
double radmaskbl;
@@ -1415,13 +1424,20 @@ struct LocallabParams {
bool explog;
bool autocompute;
double sourceGray;
+ double sourceabs;
+ double targabs;
double targetGray;
+ double catad;
+ double saturl;
+ double contl;
bool Autogray;
bool fullimage;
+ bool ciecam;
double blackEv;
double whiteEv;
double detail;
int sensilog;
+ Glib::ustring surround;
double baselog;
double strlog;
double anglog;
@@ -1725,6 +1741,8 @@ private:
struct WaveletParams {
std::vector ccwcurve;
+ std::vector wavdenoise;
+ std::vector wavdenoiseh;
std::vector blcurve;
std::vector levelshc;
std::vector opacityCurveRG;
@@ -1733,6 +1751,8 @@ struct WaveletParams {
std::vector opacityCurveW;
std::vector opacityCurveWL;
std::vector hhcurve;
+ std::vector wavguidcurve;
+ std::vector wavhuecurve;
std::vector Chcurve;
std::vector wavclCurve;
bool enabled;
@@ -1747,6 +1767,10 @@ struct WaveletParams {
int greenhigh;
int bluehigh;
double ballum;
+ double sigm;
+ double levden;
+ double thrden;
+ double limden;
double balchrom;
double chromfi;
double chromco;
@@ -1754,6 +1778,9 @@ struct WaveletParams {
double mergeC;
double softrad;
double softradend;
+ double strend;
+ int detend;
+ double thrend;
bool lipst;
bool avoid;
@@ -1792,6 +1819,10 @@ struct WaveletParams {
Glib::ustring Backmethod;
Glib::ustring Tilesmethod;
Glib::ustring complexmethod;
+ Glib::ustring denmethod;
+ Glib::ustring mixmethod;
+ Glib::ustring slimethod;
+ Glib::ustring quamethod;
Glib::ustring daubcoeffmethod;
Glib::ustring CHmethod;
Glib::ustring Medgreinf;
@@ -1849,6 +1880,8 @@ struct WaveletParams {
Threshold level1noise;
Threshold level2noise;
Threshold level3noise;
+ Threshold leveldenoise;
+ Threshold levelsigm;
WaveletParams();
@@ -1857,6 +1890,8 @@ struct WaveletParams {
void getCurves(
WavCurve& cCurve,
+ WavCurve& wavdenoise,
+ WavCurve& wavdenoiseh,
Wavblcurve& tCurve,
WavOpacityCurveRG& opacityCurveLUTRG,
WavOpacityCurveSH& opacityCurveLUTSH,
@@ -1947,10 +1982,13 @@ struct RAWParams {
struct BayerSensor {
enum class Method {
AMAZE,
+ AMAZEBILINEAR,
AMAZEVNG4,
RCD,
+ RCDBILINEAR,
RCDVNG4,
DCB,
+ DCBBILINEAR,
DCBVNG4,
LMMSE,
IGV,
diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc
index e3a747048..2354f343a 100644
--- a/rtengine/rawimage.cc
+++ b/rtengine/rawimage.cc
@@ -1046,8 +1046,10 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is
}
}
- char name[strlen(make) + strlen(model) + 32];
- sprintf(name, "%s %s", make, model);
+ const std::size_t name_size = strlen(make) + strlen(model) + 32;
+
+ char name[name_size];
+ snprintf(name, name_size, "%s %s", make, model);
for (size_t i = 0; i < sizeof table / sizeof(table[0]); i++) {
if (strcasecmp(name, table[i].prefix) == 0) {
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index c58c043e0..8bfcaa5ab 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1578,8 +1578,11 @@ void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &c
ahd_demosaic ();
} else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZE)) {
amaze_demosaic_RT (0, 0, W, H, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure);
- } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4)
+ } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEBILINEAR)
+ || raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4)
+ || raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCBBILINEAR)
|| raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCBVNG4)
+ || raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::RCDBILINEAR)
|| raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::RCDVNG4)) {
if (!autoContrast) {
double threshold = raw.bayersensor.dualDemosaicContrast;
diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h
index 75aac923c..12db6be74 100644
--- a/rtengine/rawimagesource.h
+++ b/rtengine/rawimagesource.h
@@ -299,7 +299,9 @@ protected:
void xtransborder_interpolate (int border, array2D &red, array2D &green, array2D &blue);
void xtrans_interpolate (const int passes, const bool useCieLab, size_t chunkSize = 1, bool measure = false);
void fast_xtrans_interpolate (const array2D &rawData, array2D &red, array2D &green, array2D &blue);
+ void fast_xtrans_interpolate_blend (const float* const * blend, const array2D &rawData, array2D &red, array2D &green, array2D &blue);
void pixelshift(int winx, int winy, int winw, int winh, const procparams::RAWParams &rawParams, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection);
+ void bayer_bilinear_demosaic(const float *const * blend, const array2D &rawData, array2D &red, array2D &green, array2D &blue);
void hflip (Imagefloat* im);
void vflip (Imagefloat* im);
void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override;
diff --git a/rtengine/rcd_demosaic.cc b/rtengine/rcd_demosaic.cc
index 6587d3930..ff477281b 100644
--- a/rtengine/rcd_demosaic.cc
+++ b/rtengine/rcd_demosaic.cc
@@ -1,7 +1,7 @@
/*
* This file is part of RawTherapee.
*
- * Copyright (c) 2017-2018 Luis Sanz Rodriguez (luis.sanz.rodriguez(at)gmail(dot)com) and Ingo Weyrich (heckflosse67@gmx.de)
+ * Copyright (c) 2017-2020 Luis Sanz Rodriguez (luis.sanz.rodriguez(at)gmail(dot)com) and Ingo Weyrich (heckflosse67@gmx.de)
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -82,8 +82,8 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
const int numTw = W / (tileSizeN) + ((W % (tileSizeN)) ? 1 : 0);
constexpr int w1 = tileSize, w2 = 2 * tileSize, w3 = 3 * tileSize, w4 = 4 * tileSize;
//Tolerance to avoid dividing by zero
- static constexpr float eps = 1e-5f;
- static constexpr float epssq = 1e-10f;
+ constexpr float eps = 1e-5f;
+ constexpr float epssq = 1e-10f;
#ifdef _OPENMP
#pragma omp parallel
@@ -99,16 +99,16 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
#ifdef _OPENMP
#pragma omp for schedule(dynamic, chunkSize) collapse(2) nowait
#endif
- for(int tr = 0; tr < numTh; ++tr) {
- for(int tc = 0; tc < numTw; ++tc) {
+ for (int tr = 0; tr < numTh; ++tr) {
+ for (int tc = 0; tc < numTw; ++tc) {
const int rowStart = tr * tileSizeN;
const int rowEnd = std::min(rowStart + tileSize, H);
- if(rowStart + rcdBorder == rowEnd - rcdBorder) {
+ if (rowStart + rcdBorder == rowEnd - rcdBorder) {
continue;
}
const int colStart = tc * tileSizeN;
const int colEnd = std::min(colStart + tileSize, W);
- if(colStart + rcdBorder == colEnd - rcdBorder) {
+ if (colStart + rcdBorder == colEnd - rcdBorder) {
continue;
}
@@ -125,7 +125,7 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
cfa[indx] = rgb[c0][indx] = LIM01(rawData[row][col] / 65535.f);
cfa[indx + 1] = rgb[c1][indx + 1] = LIM01(rawData[row][col + 1] / 65535.f);
}
- if(col < colEnd) {
+ if (col < colEnd) {
cfa[indx] = rgb[c0][indx] = LIM01(rawData[row][col] / 65535.f);
}
}
@@ -160,36 +160,74 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
* STEP 3: Populate the green channel
*/
// Step 3.1: Populate the green channel at blue and red CFA positions
- for (int row = 4; row < tileRows - 4; row++) {
- for (int col = 4 + (fc(cfarray, row, 0) & 1), indx = row * tileSize + col; col < tilecols - 4; col += 2, indx += 2) {
-
- // Refined vertical and horizontal local discrimination
- float VH_Central_Value = VH_Dir[indx];
- float VH_Neighbourhood_Value = 0.25f * ((VH_Dir[indx - w1 - 1] + VH_Dir[indx - w1 + 1]) + (VH_Dir[indx + w1 - 1] + VH_Dir[indx + w1 + 1]));
-
- float VH_Disc = std::fabs(0.5f - VH_Central_Value) < std::fabs(0.5f - VH_Neighbourhood_Value) ? VH_Neighbourhood_Value : VH_Central_Value;
-
- // Cardinal gradients
- float N_Grad = eps + std::fabs(cfa[indx - w1] - cfa[indx + w1]) + std::fabs(cfa[indx] - cfa[indx - w2]) + std::fabs(cfa[indx - w1] - cfa[indx - w3]) + std::fabs(cfa[indx - w2] - cfa[indx - w4]);
- float S_Grad = eps + std::fabs(cfa[indx - w1] - cfa[indx + w1]) + std::fabs(cfa[indx] - cfa[indx + w2]) + std::fabs(cfa[indx + w1] - cfa[indx + w3]) + std::fabs(cfa[indx + w2] - cfa[indx + w4]);
- float W_Grad = eps + std::fabs(cfa[indx - 1] - cfa[indx + 1]) + std::fabs(cfa[indx] - cfa[indx - 2]) + std::fabs(cfa[indx - 1] - cfa[indx - 3]) + std::fabs(cfa[indx - 2] - cfa[indx - 4]);
- float E_Grad = eps + std::fabs(cfa[indx - 1] - cfa[indx + 1]) + std::fabs(cfa[indx] - cfa[indx + 2]) + std::fabs(cfa[indx + 1] - cfa[indx + 3]) + std::fabs(cfa[indx + 2] - cfa[indx + 4]);
+ for (int row = 4; row < tileRows - 4; row++) {
+ int col = 4 + (fc(cfarray, row, 0) & 1);
+ int indx = row * tileSize + col;
+#ifdef __SSE2__
+ const vfloat zd5v = F2V(0.5f);
+ const vfloat zd25v = F2V(0.25f);
+ const vfloat epsv = F2V(eps);
+ for (; col < tilecols - 7; col += 8, indx += 8) {
+ // Cardinal gradients
+ const vfloat cfai = LC2VFU(cfa[indx]);
+ const vfloat N_Grad = epsv + (vabsf(LC2VFU(cfa[indx - w1]) - LC2VFU(cfa[indx + w1])) + vabsf(cfai - LC2VFU(cfa[indx - w2]))) + (vabsf(LC2VFU(cfa[indx - w1]) - LC2VFU(cfa[indx - w3])) + vabsf(LC2VFU(cfa[indx - w2]) - LC2VFU(cfa[indx - w4])));
+ const vfloat S_Grad = epsv + (vabsf(LC2VFU(cfa[indx - w1]) - LC2VFU(cfa[indx + w1])) + vabsf(cfai - LC2VFU(cfa[indx + w2]))) + (vabsf(LC2VFU(cfa[indx + w1]) - LC2VFU(cfa[indx + w3])) + vabsf(LC2VFU(cfa[indx + w2]) - LC2VFU(cfa[indx + w4])));
+ const vfloat W_Grad = epsv + (vabsf(LC2VFU(cfa[indx - 1]) - LC2VFU(cfa[indx + 1])) + vabsf(cfai - LC2VFU(cfa[indx - 2]))) + (vabsf(LC2VFU(cfa[indx - 1]) - LC2VFU(cfa[indx - 3])) + vabsf(LC2VFU(cfa[indx - 2]) - LC2VFU(cfa[indx - 4])));
+ const vfloat E_Grad = epsv + (vabsf(LC2VFU(cfa[indx - 1]) - LC2VFU(cfa[indx + 1])) + vabsf(cfai - LC2VFU(cfa[indx + 2]))) + (vabsf(LC2VFU(cfa[indx + 1]) - LC2VFU(cfa[indx + 3])) + vabsf(LC2VFU(cfa[indx + 2]) - LC2VFU(cfa[indx + 4])));
// Cardinal pixel estimations
- float N_Est = cfa[indx - w1] * (1.f + (lpf[indx>>1] - lpf[(indx - w2)>>1]) / (eps + lpf[indx>>1] + lpf[(indx - w2)>>1]));
- float S_Est = cfa[indx + w1] * (1.f + (lpf[indx>>1] - lpf[(indx + w2)>>1]) / (eps + lpf[indx>>1] + lpf[(indx + w2)>>1]));
- float W_Est = cfa[indx - 1] * (1.f + (lpf[indx>>1] - lpf[(indx - 2)>>1]) / (eps + lpf[indx>>1] + lpf[(indx - 2)>>1]));
- float E_Est = cfa[indx + 1] * (1.f + (lpf[indx>>1] - lpf[(indx + 2)>>1]) / (eps + lpf[indx>>1] + lpf[(indx + 2)>>1]));
+ const vfloat lpfi = LVFU(lpf[indx>>1]);
+ const vfloat N_Est = LC2VFU(cfa[indx - w1]) + (LC2VFU(cfa[indx - w1]) * (lpfi - LVFU(lpf[(indx - w2)>>1])) / (epsv + lpfi + LVFU(lpf[(indx - w2)>>1])));
+ const vfloat S_Est = LC2VFU(cfa[indx + w1]) + (LC2VFU(cfa[indx + w1]) * (lpfi - LVFU(lpf[(indx + w2)>>1])) / (epsv + lpfi + LVFU(lpf[(indx + w2)>>1])));
+ const vfloat W_Est = LC2VFU(cfa[indx - 1]) + (LC2VFU(cfa[indx - 1]) * (lpfi - LVFU(lpf[(indx - 2)>>1])) / (epsv + lpfi + LVFU(lpf[(indx - 2)>>1])));
+ const vfloat E_Est = LC2VFU(cfa[indx + 1]) + (LC2VFU(cfa[indx + 1]) * (lpfi - LVFU(lpf[(indx + 2)>>1])) / (epsv + lpfi + LVFU(lpf[(indx + 2)>>1])));
// Vertical and horizontal estimations
- float V_Est = (S_Grad * N_Est + N_Grad * S_Est) / (N_Grad + S_Grad);
- float H_Est = (W_Grad * E_Est + E_Grad * W_Est) / (E_Grad + W_Grad);
+ const vfloat V_Est = (S_Grad * N_Est + N_Grad * S_Est) / (N_Grad + S_Grad);
+ const vfloat H_Est = (W_Grad * E_Est + E_Grad * W_Est) / (E_Grad + W_Grad);
// G@B and G@R interpolation
- rgb[1][indx] = VH_Disc * H_Est + (1.f - VH_Disc) * V_Est;
+ // Refined vertical and horizontal local discrimination
+ const vfloat VH_Central_Value = LC2VFU(VH_Dir[indx]);
+ const vfloat VH_Neighbourhood_Value = zd25v * ((LC2VFU(VH_Dir[indx - w1 - 1]) + LC2VFU(VH_Dir[indx - w1 + 1])) + (LC2VFU(VH_Dir[indx + w1 - 1]) + LC2VFU(VH_Dir[indx + w1 + 1])));
+#if defined(__clang__)
+ const vfloat VH_Disc = vself(vmaskf_lt(vabsf(zd5v - VH_Central_Value), vabsf(zd5v - VH_Neighbourhood_Value)), VH_Neighbourhood_Value, VH_Central_Value);
+#else
+ const vfloat VH_Disc = vabsf(zd5v - VH_Central_Value) < vabsf(zd5v - VH_Neighbourhood_Value) ? VH_Neighbourhood_Value : VH_Central_Value;
+#endif
+ STC2VFU(rgb[1][indx], vintpf(VH_Disc, H_Est, V_Est));
+ }
+#endif
+ for (; col < tilecols - 4; col += 2, indx += 2) {
+ // Cardinal gradients
+ const float cfai = cfa[indx];
+ const float N_Grad = eps + (std::fabs(cfa[indx - w1] - cfa[indx + w1]) + std::fabs(cfai - cfa[indx - w2])) + (std::fabs(cfa[indx - w1] - cfa[indx - w3]) + std::fabs(cfa[indx - w2] - cfa[indx - w4]));
+ const float S_Grad = eps + (std::fabs(cfa[indx - w1] - cfa[indx + w1]) + std::fabs(cfai - cfa[indx + w2])) + (std::fabs(cfa[indx + w1] - cfa[indx + w3]) + std::fabs(cfa[indx + w2] - cfa[indx + w4]));
+ const float W_Grad = eps + (std::fabs(cfa[indx - 1] - cfa[indx + 1]) + std::fabs(cfai - cfa[indx - 2])) + (std::fabs(cfa[indx - 1] - cfa[indx - 3]) + std::fabs(cfa[indx - 2] - cfa[indx - 4]));
+ const float E_Grad = eps + (std::fabs(cfa[indx - 1] - cfa[indx + 1]) + std::fabs(cfai - cfa[indx + 2])) + (std::fabs(cfa[indx + 1] - cfa[indx + 3]) + std::fabs(cfa[indx + 2] - cfa[indx + 4]));
+
+ // Cardinal pixel estimations
+ const float lpfi = lpf[indx>>1];
+ const float N_Est = cfa[indx - w1] * (1.f + (lpfi - lpf[(indx - w2)>>1]) / (eps + lpfi + lpf[(indx - w2)>>1]));
+ const float S_Est = cfa[indx + w1] * (1.f + (lpfi - lpf[(indx + w2)>>1]) / (eps + lpfi + lpf[(indx + w2)>>1]));
+ const float W_Est = cfa[indx - 1] * (1.f + (lpfi - lpf[(indx - 2)>>1]) / (eps + lpfi + lpf[(indx - 2)>>1]));
+ const float E_Est = cfa[indx + 1] * (1.f + (lpfi - lpf[(indx + 2)>>1]) / (eps + lpfi + lpf[(indx + 2)>>1]));
+
+ // Vertical and horizontal estimations
+ const float V_Est = (S_Grad * N_Est + N_Grad * S_Est) / (N_Grad + S_Grad);
+ const float H_Est = (W_Grad * E_Est + E_Grad * W_Est) / (E_Grad + W_Grad);
+
+ // G@B and G@R interpolation
+ // Refined vertical and horizontal local discrimination
+ const float VH_Central_Value = VH_Dir[indx];
+ const float VH_Neighbourhood_Value = 0.25f * ((VH_Dir[indx - w1 - 1] + VH_Dir[indx - w1 + 1]) + (VH_Dir[indx + w1 - 1] + VH_Dir[indx + w1 + 1]));
+
+ const float VH_Disc = std::fabs(0.5f - VH_Central_Value) < std::fabs(0.5f - VH_Neighbourhood_Value) ? VH_Neighbourhood_Value : VH_Central_Value;
+ rgb[1][indx] = VH_Disc * H_Est + (1.f - VH_Disc) * V_Est;
}
}
+
/**
* STEP 4: Populate the red and blue channels
*/
@@ -203,7 +241,6 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
float Q_Stat = max(epssq, - 18.f * cfai * (cfa[indx + w1 - 1] + cfa[indx - w1 + 1] + 2.f * (cfa[indx + w2 - 2] + cfa[indx - w2 + 2]) - cfa[indx + w3 - 3] - cfa[indx - w3 + 3]) - 2.f * cfai * (cfa[indx + w4 - 4] + cfa[indx - w4 + 4] - 19.f * cfai) - cfa[indx + w1 - 1] * (70.f * cfa[indx - w1 + 1] - 12.f * cfa[indx + w2 - 2] + 24.f * cfa[indx - w2 + 2] - 38.f * cfa[indx + w3 - 3] + 16.f * cfa[indx - w3 + 3] + 12.f * cfa[indx + w4 - 4] - 6.f * cfa[indx - w4 + 4] + 46.f * cfa[indx + w1 - 1]) + cfa[indx - w1 + 1] * (24.f * cfa[indx + w2 - 2] - 12.f * cfa[indx - w2 + 2] + 16.f * cfa[indx + w3 - 3] - 38.f * cfa[indx - w3 + 3] - 6.f * cfa[indx + w4 - 4] + 12.f * cfa[indx - w4 + 4] + 46.f * cfa[indx - w1 + 1]) + cfa[indx + w2 - 2] * (14.f * cfa[indx - w2 + 2] - 12.f * cfa[indx - w3 + 3] - 2.f * (cfa[indx + w4 - 4] - cfa[indx - w4 + 4]) + 11.f * cfa[indx + w2 - 2]) - cfa[indx - w2 + 2] * (12.f * cfa[indx + w3 - 3] + 2.f * (cfa[indx + w4 - 4] - cfa[indx - w4 + 4]) + 11.f * cfa[indx - w2 + 2]) + cfa[indx + w3 - 3] * (2.f * cfa[indx - w3 + 3] - 6.f * cfa[indx + w4 - 4] + 10.f * cfa[indx + w3 - 3]) - cfa[indx - w3 + 3] * (6.f * cfa[indx - w4 + 4] + 10.f * cfa[indx - w3 + 3]) + cfa[indx + w4 - 4] * cfa[indx + w4 - 4] + cfa[indx - w4 + 4] * cfa[indx - w4 + 4]);
PQ_Dir[indx] = P_Stat / (P_Stat + Q_Stat);
-
}
}
@@ -235,7 +272,6 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
// R@B and B@R interpolation
rgb[c][indx] = rgb[1][indx] + (1.f - PQ_Disc) * P_Est + PQ_Disc * Q_Est;
-
}
}
@@ -279,7 +315,6 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
// R@G and B@G interpolation
rgb[c][indx] = rgb1 + (1.f - VH_Disc) * V_Est + VH_Disc * H_Est;
-
}
}
}
@@ -293,9 +328,9 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
}
}
- if(plistener) {
+ if (plistener) {
progresscounter++;
- if(progresscounter % 32 == 0) {
+ if (progresscounter % 32 == 0) {
#ifdef _OPENMP
#pragma omp critical (rcdprogress)
#endif
@@ -306,7 +341,6 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
}
}
}
-
}
}
@@ -321,7 +355,6 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure)
if (plistener) {
plistener->setProgress(1);
}
- // -------------------------------------------------------------------------
}
} /* namespace */
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index 1be81a7de..593e5b9c9 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -983,6 +983,17 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvLocallabSpotprevMethod
LUMINANCECURVE, // Evlocallabactiv
LUMINANCECURVE, // EvlocallabCHshape
+ LUMINANCECURVE, //EvlocallabquaMethod
+ LUMINANCECURVE, //Evlocallabhishow
+ LUMINANCECURVE, // Evlocallabinvbl
+ LUMINANCECURVE, // Evlocallabcatad
+ LUMINANCECURVE, // Evlocallabciecam
+ LUMINANCECURVE, // Evlocallabsourceabs
+ LUMINANCECURVE, // Evlocallabtargabs
+ LUMINANCECURVE, // Evlocallabsurround
+ LUMINANCECURVE, // Evlocallabsaturl
+ LUMINANCECURVE // Evlocallabcontl
+
};
diff --git a/rtengine/rt_algo.cc b/rtengine/rt_algo.cc
index a5b48af95..81121f58c 100644
--- a/rtengine/rt_algo.cc
+++ b/rtengine/rt_algo.cc
@@ -34,23 +34,14 @@
#include "sleef.h"
namespace {
-float calcBlendFactor(float val, float threshold) {
- // sigmoid function
- // result is in ]0;1] range
- // inflexion point is at (x, y) (threshold, 0.5)
- return 1.f / (1.f + xexpf(16.f - 16.f * val / threshold));
-}
-#ifdef __SSE2__
-vfloat calcBlendFactor(vfloat valv, vfloat thresholdv) {
+template
+T calcBlendFactor(T val, T threshold) {
// sigmoid function
// result is in ]0;1] range
// inflexion point is at (x, y) (threshold, 0.5)
- const vfloat onev = F2V(1.f);
- const vfloat c16v = F2V(16.f);
- return onev / (onev + xexpf(c16v - c16v * valv / thresholdv));
+ return 1.f / (1.f + xexpf(16.f - (16.f / threshold) * val));
}
-#endif
float tileAverage(const float * const *data, size_t tileY, size_t tileX, size_t tilesize) {
diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h
index 1671ae1f5..74214737e 100644
--- a/rtengine/rtengine.h
+++ b/rtengine/rtengine.h
@@ -42,6 +42,9 @@
*
*/
+template
+class array2D;
+
template
class LUT;
@@ -302,6 +305,8 @@ public:
virtual void sizeChanged(int w, int h, int ow, int oh) = 0;
};
+class HistogramObservable;
+
/** This listener is used when the histogram of the final image has changed. */
class HistogramListener
{
@@ -327,8 +332,43 @@ public:
const LUTu& histGreenRaw,
const LUTu& histBlueRaw,
const LUTu& histChroma,
- const LUTu& histLRETI
+ const LUTu& histLRETI,
+ int vectorscopeScale,
+ const array2D& vectorscopeHC,
+ const array2D& vectorscopeHS,
+ int waveformScale,
+ const array2D& waveformRed,
+ const array2D& waveformGreen,
+ const array2D& waveformBlue,
+ const array2D& waveformLuma
) = 0;
+ /** Tells which observable is notifying the listener. */
+ virtual void setObservable(HistogramObservable* observable) = 0;
+ /** Returns if the listener wants the histogram to be updated. */
+ virtual bool updateHistogram(void) const = 0;
+ /** Returns if the listener wants the raw histogram to be updated. */
+ virtual bool updateHistogramRaw(void) const = 0;
+ /** Returns if the listener wants the H-C vectorscope to be updated. */
+ virtual bool updateVectorscopeHC(void) const = 0;
+ /** Returns if the listener wants the H-S vectorscope to be updated. */
+ virtual bool updateVectorscopeHS(void) const = 0;
+ /** Returns if the listener wants the waveform to be updated. */
+ virtual bool updateWaveform(void) const = 0;
+};
+
+class HistogramObservable
+{
+public:
+ /** Tells the observable to update the histogram data. */
+ virtual void requestUpdateHistogram() = 0;
+ /** Tells the observable to update the raw histogram data. */
+ virtual void requestUpdateHistogramRaw() = 0;
+ /** Tells the observable to update the H-C vectorscope data. */
+ virtual void requestUpdateVectorscopeHC() = 0;
+ /** Tells the observable to update the H-S vectorscope data. */
+ virtual void requestUpdateVectorscopeHS() = 0;
+ /** Tells the observable to update the waveform data. */
+ virtual void requestUpdateWaveform() = 0;
};
/** This listener is used when the auto exposure has been recomputed (e.g. when the clipping ratio changed). */
@@ -399,7 +439,7 @@ public:
virtual ~LocallabListener() = default;
virtual void refChanged(const std::vector &ref, int selspot) = 0;
virtual void minmaxChanged(const std::vector &minmax, int selspot) = 0;
- virtual void logencodChanged(const float blackev, const float whiteev, const float sourceg, const float targetg) = 0;
+ virtual void logencodChanged(const float blackev, const float whiteev, const float sourceg, const float sourceab, const float targetg) = 0;
};
class AutoColorTonListener
diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc
index 363819cf7..58f3d12a3 100644
--- a/rtengine/rtlensfun.cc
+++ b/rtengine/rtlensfun.cc
@@ -438,7 +438,7 @@ std::vector LFDatabase::getLenses() const
LFCamera LFDatabase::findCamera(const Glib::ustring &make, const Glib::ustring &model) const
{
LFCamera ret;
- if (data_) {
+ if (data_ && !make.empty()) {
MyMutex::MyLock lock(lfDBMutex);
auto found = data_->FindCamerasExt(make.c_str(), model.c_str());
if (found) {
@@ -453,7 +453,7 @@ LFCamera LFDatabase::findCamera(const Glib::ustring &make, const Glib::ustring &
LFLens LFDatabase::findLens(const LFCamera &camera, const Glib::ustring &name) const
{
LFLens ret;
- if (data_) {
+ if (data_ && !name.empty()) {
MyMutex::MyLock lock(lfDBMutex);
auto found = data_->FindLenses(camera.data_, nullptr, name.c_str());
for (size_t pos = 0; !found && pos < name.size(); ) {
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 357ad3a69..7d0f40f70 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -205,11 +205,6 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
ImageIO* img = imgSrc.getImageIO();
- // agriggio -- hotfix for #3794, to be revised once a proper solution is implemented
- if (std::max(img->getWidth(), img->getHeight()) / std::min(img->getWidth(), img->getHeight()) >= 10) {
- return nullptr;
- }
-
Thumbnail* tpp = new Thumbnail ();
unsigned char* data;
@@ -235,15 +230,29 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
h = img->getHeight();
tpp->scale = 1.;
} else {
- if (fixwh == 1) {
+ if (fixwh < 0 && w > 0 && h > 0) {
+ const int ww = h * img->getWidth() / img->getHeight();
+ const int hh = w * img->getHeight() / img->getWidth();
+ if (ww <= w) {
+ w = ww;
+ tpp->scale = static_cast(img->getHeight()) / h;
+ } else {
+ h = hh;
+ tpp->scale = static_cast(img->getWidth()) / w;
+ }
+ } else if (fixwh == 1) {
w = h * img->getWidth() / img->getHeight();
- tpp->scale = (double)img->getHeight() / h;
+ tpp->scale = static_cast(img->getHeight()) / h;
} else {
h = w * img->getHeight() / img->getWidth();
- tpp->scale = (double)img->getWidth() / w;
+ tpp->scale = static_cast(img->getWidth()) / w;
}
}
+ // Precaution to prevent division by zero later on
+ if (h < 1) h = 1;
+ if (w < 1) w = 1;
+
// bilinear interpolation
if (tpp->thumbImg) {
delete tpp->thumbImg;
@@ -1178,6 +1187,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
rwidth = int (size_t (thumbImg->getWidth()) * size_t (rheight) / size_t (thumbImg->getHeight()));
}
+ if (rwidth < 1) rwidth = 1;
+ if (rheight < 1) rheight = 1;
Imagefloat* baseImg = resizeTo (rwidth, rheight, interp, thumbImg);
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 7b8575635..e56111806 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -918,7 +918,7 @@ private:
ipf.lab2rgb(labcbdl, *baseImg, params.icm.workingProfile);
}
- //gamma TRC working
+/* //gamma TRC working
if (params.icm.workingTRC == "Custom") { //exec TRC IN free
const Glib::ustring profile = params.icm.workingProfile;
@@ -932,7 +932,7 @@ private:
ipf.workingtrc(baseImg, baseImg, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, dummyTransForm, false, true, false);
}
}
-
+*/
// RGB processing
curve1(65536);
@@ -1364,6 +1364,8 @@ private:
LabImage *unshar = nullptr;
WaveletParams WaveParams = params.wavelet;
WavCurve wavCLVCurve;
+ WavCurve wavdenoise;
+ WavCurve wavdenoiseh;
Wavblcurve wavblcurve;
WavOpacityCurveRG waOpacityCurveRG;
WavOpacityCurveSH waOpacityCurveSH;
@@ -1388,14 +1390,14 @@ private:
provradius = new LabImage(*labView, true);
}
- params.wavelet.getCurves(wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
+ params.wavelet.getCurves(wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL);
CurveFactory::diagonalCurve2Lut(params.wavelet.wavclCurve, wavclCurve, 1);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
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);
+ ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
unshar = new LabImage(*labView, true);
params.wavelet.CLmethod = provis;
@@ -1407,7 +1409,7 @@ private:
WaveParams.expnoise = false;
}
- ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
+ ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, wavdenoise, wavdenoiseh, wavblcurve, waOpacityCurveRG, waOpacityCurveSH, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, 1);
if ((WaveParams.ushamethod == "sharp" || WaveParams.ushamethod == "clari") && WaveParams.expclari && WaveParams.CLmethod != "all") {
WaveParams.expcontrast = procont;
diff --git a/rtengine/xtrans_demosaic.cc b/rtengine/xtrans_demosaic.cc
index 5f5afa073..bcad4d7d3 100644
--- a/rtengine/xtrans_demosaic.cc
+++ b/rtengine/xtrans_demosaic.cc
@@ -1027,6 +1027,67 @@ void RawImageSource::fast_xtrans_interpolate (const array2D &rawData, arr
plistener->setProgress (1.0);
}
}
+
+void RawImageSource::fast_xtrans_interpolate_blend (const float* const * blend, const array2D &rawData, array2D &red, array2D &green, array2D &blue)
+{
+
+ if (plistener) {
+ plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_XTRANSFAST")));
+ plistener->setProgress(0.0);
+ }
+
+ int xtrans[6][6];
+ ri->getXtransMatrix(xtrans);
+
+ const float weight[3][3] = {
+ {0.25f, 0.5f, 0.25f},
+ {0.5f, 0.f, 0.5f},
+ {0.25f, 0.5f, 0.25f}
+ };
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic, 16)
+#endif
+ for (int row = 8; row < H - 8; ++row) {
+ for (int col = 8; col < W - 8; ++col) {
+ float sum[3] = {};
+
+ for (int v = -1; v <= 1; v++) {
+ for (int h = -1; h <= 1; h++) {
+ sum[fcol(row + v, col + h)] += rawData[row + v][(col + h)] * weight[v + 1][h + 1];
+ }
+ }
+
+ switch(fcol(row, col)) {
+ case 0: // red pixel
+ red[row][col] = intp(blend[row][col], red[row][col], rawData[row][col]);
+ green[row][col] = intp(blend[row][col], green[row][col], sum[1] * 0.5f);
+ blue[row][col] = intp(blend[row][col], blue[row][col], sum[2]);
+ break;
+
+ case 1: // green pixel
+ green[row][col] = intp(blend[row][col], green[row][col], rawData[row][col]);
+ if (fcol(row, col - 1) == fcol(row, col + 1)) { // Solitary green pixel always has exactly two direct red and blue neighbors in 3x3 grid
+ red[row][col] = intp(blend[row][col], red[row][col], sum[0]);
+ blue[row][col] = intp(blend[row][col], blue[row][col], sum[2]);
+ } else { // Non solitary green pixel always has one direct and one diagonal red and blue neighbor in 3x3 grid
+ red[row][col] = intp(blend[row][col], red[row][col], sum[0] * 1.3333333f);
+ blue[row][col] = intp(blend[row][col], blue[row][col], sum[2] * 1.3333333f);
+ }
+ break;
+
+ case 2: // blue pixel
+ red[row][col] = intp(blend[row][col], red[row][col], sum[0]);
+ green[row][col] = intp(blend[row][col], green[row][col], sum[1] * 0.5f);
+ blue[row][col] = intp(blend[row][col], blue[row][col], rawData[row][col]);
+ break;
+ }
+ }
+ }
+
+ if (plistener) {
+ plistener->setProgress (1.0);
+ }
+}
#undef fcol
#undef isgreen
diff --git a/rtexif/canonattribs.cc b/rtexif/canonattribs.cc
index 529b2314d..57fe6d07e 100644
--- a/rtexif/canonattribs.cc
+++ b/rtexif/canonattribs.cc
@@ -70,7 +70,7 @@ public:
return "undef";
}
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
};
@@ -99,7 +99,7 @@ public:
}
char buffer[32];
- sprintf (buffer, "%.1fs %s", sec / 10., (sec & 0x4000) ? ",Custom" : "");
+ snprintf(buffer, sizeof(buffer), "%.1fs %s", sec / 10., (sec & 0x4000) ? ",Custom" : "");
return buffer;
}
};
@@ -542,7 +542,7 @@ public:
}
char buffer[32];
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
};
@@ -1175,7 +1175,7 @@ public:
}
char buffer[32];
- sprintf (buffer, "%.2fmm", val * 25.4 / 1000);
+ snprintf(buffer, sizeof(buffer), "%.2fmm", val * 25.4 / 1000);
return buffer;
}
};
@@ -1188,7 +1188,7 @@ public:
{
char buffer[32];
double d = pow (2, - t->toInt() / 32.0);
- sprintf (buffer, "%.3f", d);
+ snprintf(buffer, sizeof(buffer), "%.3f", d);
return buffer;
}
};
@@ -1199,7 +1199,7 @@ class CAEVInterpreter : public Interpreter
std::string toString (const Tag* t) const override
{
char buffer[32];
- sprintf (buffer, "%.1f", t->toDouble() / 32.0 );
+ snprintf(buffer, sizeof(buffer), "%.1f", t->toDouble() / 32.0 );
return buffer;
}
};
@@ -1212,7 +1212,7 @@ public:
{
char buffer[32];
int a = t->toInt();
- sprintf (buffer, "%d", a);
+ snprintf(buffer, sizeof(buffer), "%d", a);
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1354,7 +1354,7 @@ public:
}
char buffer[32];
- sprintf (buffer, "%.0f", n / 32. );
+ snprintf(buffer, sizeof(buffer), "%.0f", n / 32. );
return buffer;
}
};
@@ -1409,7 +1409,7 @@ public:
std::string toString (const Tag* t) const override
{
char buffer[32];
- sprintf (buffer, "%.2f", t->toDouble() / 100 );
+ snprintf(buffer, sizeof(buffer), "%.2f", t->toDouble() / 100 );
return buffer;
}
};
@@ -1421,7 +1421,7 @@ public:
std::string toString (const Tag* t) const override
{
char buffer[32];
- sprintf (buffer, "%.1f", t->toDouble() / 8 - 6 );
+ snprintf(buffer, sizeof(buffer), "%.1f", t->toDouble() / 8 - 6 );
return buffer;
}
};
@@ -1557,7 +1557,7 @@ public:
{
unsigned long val = t->toInt (0, LONG);
char buffer[32];
- sprintf (buffer, "%ld", ((val & 0xffc0) >> 6) * 10000 + ((val >> 16) & 0xff) + ((val & 0x3f) << 8) );
+ snprintf(buffer, sizeof(buffer), "%ld", ((val & 0xffc0) >> 6) * 10000 + ((val >> 16) & 0xff) + ((val & 0x3f) << 8) );
return buffer;
}
};
diff --git a/rtexif/nikonattribs.cc b/rtexif/nikonattribs.cc
index 70213e8b0..0ea476a24 100644
--- a/rtexif/nikonattribs.cc
+++ b/rtexif/nikonattribs.cc
@@ -35,7 +35,7 @@ public:
std::string toString (const Tag* t) const override
{
char buffer[32];
- sprintf (buffer, "%d", t->toInt (2));
+ snprintf(buffer, sizeof(buffer), "%d", t->toInt (2));
return buffer;
}
};
@@ -49,7 +49,7 @@ public:
{
char buffer[32];
int a = t->toInt();
- sprintf (buffer, "%d", a);
+ snprintf(buffer, sizeof(buffer), "%d", a);
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -128,7 +128,7 @@ public:
default: {
char buffer[32];
- sprintf (buffer, "0x%04X", a);
+ snprintf(buffer, sizeof(buffer), "0x%04X", a);
return buffer;
}
}
diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc
index d6b9a9c84..f534d549a 100644
--- a/rtexif/pentaxattribs.cc
+++ b/rtexif/pentaxattribs.cc
@@ -422,7 +422,7 @@ public:
return "undef";
}
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
};
@@ -626,7 +626,7 @@ public:
return s.str();
} else {
char buffer[1024];
- t->toString (buffer);
+ t->toString (buffer, sizeof(buffer));
return std::string (buffer);
}
}
@@ -1341,7 +1341,7 @@ public:
}
char buffer[32];
- sprintf (buffer, "%d", a );
+ snprintf(buffer, sizeof(buffer), "%d", a );
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1369,7 +1369,7 @@ public:
if (a > 1.) {
char buffer[32];
- sprintf (buffer, "%.2f", a / 100. );
+ snprintf(buffer, sizeof(buffer), "%.2f", a / 100. );
return buffer;
} else {
return "n/a";
@@ -1399,7 +1399,7 @@ public:
if (b > 1.0) {
char buffer[32];
- sprintf (buffer, "%.2f", b );
+ snprintf(buffer, sizeof(buffer), "%.2f", b );
return buffer;
} else {
return "n/a";
@@ -1428,7 +1428,7 @@ public:
int a = t->toInt (0, BYTE);
char buffer[32];
double v = 100.*exp (double (a - 32) * log (2.) / 8.);
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1456,7 +1456,7 @@ public:
return "undef";
}
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
} else {
return "n/a";
@@ -1485,7 +1485,7 @@ public:
int a = t->toInt (0, BYTE);
char buffer[32];
double v = double (a - 64) / 8.;
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1505,7 +1505,7 @@ public:
int a = t->toInt (0, SBYTE);
char buffer[32];
double v = double (a) / 8.;
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1525,7 +1525,7 @@ public:
int a = t->toInt (0, BYTE);
char buffer[32];
double v = exp ((double (a) - 68.) * log (2.) / 16.);
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1545,7 +1545,7 @@ public:
int a = t->toInt (0, BYTE);
char buffer[32];
double v = 24.*exp (- (double (a) - 32.) * log (2.) / 8.);
- sprintf (buffer, "%.6f", v );
+ snprintf(buffer, sizeof(buffer), "%.6f", v );
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1565,7 +1565,7 @@ public:
char buffer[32];
int a = t->toInt (0, BYTE);
int mina = a & 0x0F;
- sprintf (buffer, "%.1f", double (int (pow (2.0, double (mina + 10) / 4.0) + 0.2)));
+ snprintf(buffer, sizeof(buffer), "%.1f", double (int (pow (2.0, double (mina + 10) / 4.0) + 0.2)));
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1585,7 +1585,7 @@ public:
char buffer[32];
int a = t->toInt (0, BYTE);
int maxa = (a & 0xF0) >> 4;
- sprintf (buffer, "%.1f", double (int (pow (2.0, double (maxa) / 4.0) + 0.2)) );
+ snprintf(buffer, sizeof(buffer), "%.1f", double (int (pow (2.0, double (maxa) / 4.0) + 0.2)) );
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -1702,7 +1702,7 @@ public:
{
char buffer[32];
int b = t->toInt (0, BYTE) & 0x1F;
- sprintf (buffer, "%.0f", pow (2., b / 16. + 4) );
+ snprintf(buffer, sizeof(buffer), "%.0f", pow (2., b / 16. + 4) );
return buffer;
}
};
@@ -1788,7 +1788,7 @@ public:
return r->second;
} else {
char buffer[1024];
- t->toString (buffer);
+ t->toString (buffer, sizeof(buffer));
return std::string (buffer);
}
}
diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc
index f32a9feb1..b3d31b950 100644
--- a/rtexif/rtexif.cc
+++ b/rtexif/rtexif.cc
@@ -1017,13 +1017,13 @@ Tag::Tag (TagDirectory* p, FILE* f, int base)
Tag* tmake = parent->getRoot()->getTag ("Make");
if (tmake) {
- tmake->toString (make);
+ tmake->toString (make, sizeof(make));
}
Tag* tmodel = parent->getRoot()->getTag ("Model");
if (tmodel) {
- tmodel->toString (model);
+ tmodel->toString (model, sizeof(model));
}
if (!strncmp (make, "SONY", 4)) {
@@ -1677,8 +1677,11 @@ void Tag::toRational (int& num, int& denom, int ofs) const
}
}
-void Tag::toString (char* buffer, int ofs) const
+void Tag::toString (char* buffer, std::size_t size, int ofs) const
{
+ if (!buffer || !size) {
+ return;
+ }
if (type == UNDEFINED && !directory) {
bool isstring = true;
@@ -1690,67 +1693,80 @@ void Tag::toString (char* buffer, int ofs) const
}
if (isstring) {
- int j = 0;
+ if (size < 3) {
+ return;
+ }
+
+ std::size_t j = 0;
for (i = 0; i + ofs < count && i < 64 && value[i + ofs]; i++) {
if (value[i + ofs] == '<' || value[i + ofs] == '>') {
buffer[j++] = '\\';
+ if (j > size - 2) {
+ break;
+ }
}
buffer[j++] = value[i + ofs];
+ if (j > size - 2) {
+ break;
+ }
}
buffer[j++] = 0;
return;
}
} else if (type == ASCII) {
- sprintf (buffer, "%.64s", value + ofs);
+ snprintf(buffer, size, "%.64s", value + ofs);
return;
}
size_t maxcount = rtengine::min(count, 10);
- strcpy (buffer, "");
+ buffer[0] = 0;
for (ssize_t i = 0; i < rtengine::min(maxcount, valuesize - ofs); i++) {
- if (i > 0) {
+ std::size_t len = strlen(buffer);
+
+ if (i > 0 && size - len > 2) {
strcat (buffer, ", ");
+ len += 2;
}
- char* b = buffer + strlen (buffer);
+ char* b = buffer + len;
switch (type) {
case UNDEFINED:
case BYTE:
- sprintf (b, "%d", value[i + ofs]);
+ snprintf(b, size - len, "%d", value[i + ofs]);
break;
case SSHORT:
- sprintf (b, "%d", toInt (2 * i + ofs));
+ snprintf(b, size - len, "%d", toInt (2 * i + ofs));
break;
case SHORT:
- sprintf (b, "%u", toInt (2 * i + ofs));
+ snprintf(b, size - len, "%u", toInt (2 * i + ofs));
break;
case SLONG:
- sprintf (b, "%d", toInt (4 * i + ofs));
+ snprintf(b, size - len, "%d", toInt (4 * i + ofs));
break;
case LONG:
- sprintf (b, "%u", toInt (4 * i + ofs));
+ snprintf(b, size - len, "%u", toInt (4 * i + ofs));
break;
case SRATIONAL:
- sprintf (b, "%d/%d", (int)sget4 (value + 8 * i + ofs, getOrder()), (int)sget4 (value + 8 * i + ofs + 4, getOrder()));
+ snprintf(b, size - len, "%d/%d", (int)sget4 (value + 8 * i + ofs, getOrder()), (int)sget4 (value + 8 * i + ofs + 4, getOrder()));
break;
case RATIONAL:
- sprintf (b, "%u/%u", (uint32_t)sget4 (value + 8 * i + ofs, getOrder()), (uint32_t)sget4 (value + 8 * i + ofs + 4, getOrder()));
+ snprintf(b, size - len, "%u/%u", (uint32_t)sget4 (value + 8 * i + ofs, getOrder()), (uint32_t)sget4 (value + 8 * i + ofs + 4, getOrder()));
break;
case FLOAT:
- sprintf (b, "%g", toDouble (8 * i + ofs));
+ snprintf(b, size - len, "%g", toDouble (8 * i + ofs));
break;
default:
@@ -1758,7 +1774,7 @@ void Tag::toString (char* buffer, int ofs) const
}
}
- if (count > maxcount) {
+ if (count > maxcount && size - strlen(buffer) > 3) {
strcat (buffer, "...");
}
}
@@ -1771,7 +1787,7 @@ std::string Tag::nameToString (int i)
if (attrib) {
strncpy (buffer, attrib->name, 1024);
} else {
- sprintf (buffer, "0x%x", tag);
+ snprintf(buffer, sizeof(buffer), "0x%x", tag);
}
if (i > 0) {
@@ -1788,7 +1804,7 @@ std::string Tag::valueToString () const
return attrib->interpreter->toString (this);
} else {
char buffer[1024];
- toString (buffer);
+ toString (buffer, sizeof(buffer));
return buffer;
}
}
@@ -2763,7 +2779,7 @@ parse_leafdata (TagDirectory* root, ByteOrder order)
&tm.tm_mday, &tm.tm_hour,
&tm.tm_min, &tm.tm_sec) == 6) {
char tstr[64];
- sprintf (tstr, "%04d:%02d:%02d %02d:%02d:%02d", tm.tm_year, tm.tm_mon,
+ snprintf(tstr, sizeof(tstr), "%04d:%02d:%02d %02d:%02d:%02d", tm.tm_year, tm.tm_mon,
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
t->initString (tstr);
exif->getDirectory()->addTagFront (t);
diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h
index 5084f70de..dd89b70ce 100644
--- a/rtexif/rtexif.h
+++ b/rtexif/rtexif.h
@@ -304,7 +304,7 @@ public:
double toDouble (int ofs = 0) const;
double* toDoubleArray (int ofs = 0) const;
void toRational (int& num, int& denom, int ofs = 0) const;
- void toString (char* buffer, int ofs = 0) const;
+ void toString (char* buffer, std::size_t size, int ofs = 0) const;
void fromString (const char* v, int size = -1);
void setInt (int v, int ofs = 0, TagType astype = LONG);
int getDistanceFrom (const TagDirectory *root);
@@ -392,7 +392,7 @@ public:
virtual std::string toString (const Tag* t) const
{
char buffer[1024];
- t->toString (buffer);
+ t->toString (buffer, sizeof(buffer));
std::string s (buffer);
std::string::size_type p1 = s.find_first_not_of (' ');
@@ -526,7 +526,7 @@ public:
return r->second;
} else {
char buffer[1024];
- t->toString(buffer);
+ t->toString(buffer, sizeof(buffer));
return buffer;
}
}
diff --git a/rtexif/sonyminoltaattribs.cc b/rtexif/sonyminoltaattribs.cc
index 5eb5c9ec1..95aea1252 100644
--- a/rtexif/sonyminoltaattribs.cc
+++ b/rtexif/sonyminoltaattribs.cc
@@ -1979,7 +1979,7 @@ public:
if (a > 0) {
char buffer[32];
- sprintf (buffer, "%.4f", a);
+ snprintf(buffer, sizeof(buffer), "%.4f", a);
return buffer;
} else {
return "n/a";
@@ -2039,7 +2039,7 @@ public:
if (a) {
char buffer[32];
- sprintf (buffer, "%.1f", a / 100. );
+ snprintf(buffer, sizeof(buffer), "%.1f", a / 100. );
return buffer;
} else {
return "n/a";
@@ -2099,7 +2099,7 @@ public:
if (a) {
char buffer[32];
- sprintf (buffer, "%d", a );
+ snprintf(buffer, sizeof(buffer), "%d", a );
return buffer;
} else {
return "Auto";
@@ -2138,7 +2138,7 @@ public:
{
double a = t->toDouble();
char buffer[32];
- sprintf (buffer, "%.2f", a );
+ snprintf(buffer, sizeof(buffer), "%.2f", a );
return buffer;
}
double toDouble (const Tag* t, int ofs) override
@@ -2158,7 +2158,7 @@ public:
std::string toString (const Tag* t) const override
{
char buffer[32];
- sprintf (buffer, "%d", t->getValue()[0] - 20);
+ snprintf(buffer, sizeof(buffer), "%d", t->getValue()[0] - 20);
return buffer;
}
int toInt (const Tag* t, int ofs, TagType astype) override
@@ -2197,7 +2197,7 @@ public:
std::string toString (const Tag* t) const override
{
char buffer[32];
- sprintf (buffer, "%d", t->getValue()[0] & 0x7f);
+ snprintf(buffer, sizeof(buffer), "%d", t->getValue()[0] & 0x7f);
return buffer;
}
int toInt (const Tag* t, int ofs, TagType astype) override
@@ -2253,7 +2253,7 @@ public:
std::string toString (const Tag* t) const override
{
char buffer[32];
- sprintf (buffer, "%d", t->toInt());
+ snprintf(buffer, sizeof(buffer), "%d", t->toInt());
return buffer;
}
int toInt (const Tag* t, int ofs, TagType astype) override
diff --git a/rtexif/stdattribs.cc b/rtexif/stdattribs.cc
index be7a28a5c..e6e3bb35b 100644
--- a/rtexif/stdattribs.cc
+++ b/rtexif/stdattribs.cc
@@ -334,7 +334,7 @@ public:
return "undef";
}
- sprintf (buffer, "%0.1f", v);
+ snprintf(buffer, sizeof(buffer), "%0.1f", v);
return buffer;
}
};
@@ -353,7 +353,7 @@ public:
return "undef";
}
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
};
@@ -372,7 +372,7 @@ public:
return "undef";
}
- sprintf (buffer, "%+0.2f", v );
+ snprintf(buffer, sizeof(buffer), "%+0.2f", v );
return buffer;
}
};
@@ -388,9 +388,9 @@ public:
double d = pow (2.0, -t->toDouble());
if (d > 0.0 && d <= 0.5) {
- sprintf (buffer, "1/%.0f", 1.0 / d);
+ snprintf(buffer, sizeof(buffer), "1/%.0f", 1.0 / d);
} else {
- sprintf (buffer, "%.1f", d);
+ snprintf(buffer, sizeof(buffer), "%.1f", d);
}
return buffer;
@@ -408,9 +408,9 @@ public:
double d = t->toDouble();
if (d > 0.0 && d <= 0.5) {
- sprintf (buffer, "1/%.0f", 1.0 / d);
+ snprintf(buffer, sizeof(buffer), "1/%.0f", 1.0 / d);
} else {
- sprintf (buffer, "%.1f", d);
+ snprintf(buffer, sizeof(buffer), "%.1f", d);
}
return buffer;
@@ -431,7 +431,7 @@ public:
return "undef";
}
- sprintf (buffer, "%.1f", v );
+ snprintf(buffer, sizeof(buffer), "%.1f", v );
return buffer;
}
};
@@ -637,7 +637,7 @@ public:
int lastSegmentWidth = t->toInt(4, SHORT);
char buffer[32];
- sprintf (buffer, "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth);
+ snprintf(buffer, sizeof(buffer), "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth);
return buffer;
}
};
diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt
index cfadb7928..514204baf 100644
--- a/rtgui/CMakeLists.txt
+++ b/rtgui/CMakeLists.txt
@@ -34,6 +34,7 @@ set(NONCLISOURCEFILES
colorappearance.cc
coloredbar.cc
colortoning.cc
+ controllines.cc
controlspotpanel.cc
coordinateadjuster.cc
crop.cc
diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc
index 142374213..6f8c0e83a 100644
--- a/rtgui/adjuster.cc
+++ b/rtgui/adjuster.cc
@@ -36,7 +36,7 @@ double one2one(double val)
}
}
-Adjuster::Adjuster (
+Adjuster::Adjuster(
Glib::ustring vlabel,
double vmin,
double vmax,
@@ -45,21 +45,20 @@ Adjuster::Adjuster (
Gtk::Image *imgIcon1,
Gtk::Image *imgIcon2,
double2double_fun slider2value,
- double2double_fun value2slider)
-
- :
-
+ double2double_fun value2slider
+) :
adjustmentName(std::move(vlabel)),
grid(nullptr),
label(nullptr),
imageIcon1(imgIcon1),
automatic(nullptr),
adjusterListener(nullptr),
+ spinChange(options.adjusterMinDelay, options.adjusterMaxDelay),
+ sliderChange(options.adjusterMinDelay, options.adjusterMaxDelay),
editedCheckBox(nullptr),
afterReset(false),
blocked(false),
addMode(false),
- eventPending(false),
vMin(vmin),
vMax(vmax),
vStep(vstep),
@@ -67,8 +66,7 @@ Adjuster::Adjuster (
logPivot(0),
logAnchorMiddle(false),
value2slider(value2slider ? value2slider : &one2one),
- slider2value(slider2value ? slider2value : &one2one),
- delay(options.adjusterMinDelay)
+ slider2value(slider2value ? slider2value : &one2one)
{
set_hexpand(true);
@@ -155,8 +153,27 @@ Adjuster::Adjuster (
defaultVal = ctorDefaultVal = shapeValue(vdefault);
editedState = defEditedState = Irrelevant;
- sliderChange = slider->signal_value_changed().connect( sigc::mem_fun(*this, &Adjuster::sliderChanged) );
- spinChange = spin->signal_value_changed().connect( sigc::mem_fun(*this, &Adjuster::spinChanged), true);
+ spinChange.connect(
+ spin->signal_value_changed(),
+ sigc::mem_fun(*this, &Adjuster::spinChanged),
+ [this]()
+ {
+ sliderChange.block(true);
+ setSliderValue(addMode ? spin->get_value() : this->value2slider(spin->get_value()));
+ sliderChange.block(false);
+ }
+ );
+ sliderChange.connect(
+ slider->signal_value_changed(),
+ sigc::mem_fun(*this, &Adjuster::sliderChanged),
+ [this]()
+ {
+ spinChange.block();
+ const double v = shapeValue(getSliderValue());
+ spin->set_value(addMode ? v : this->slider2value(v));
+ spinChange.unblock();
+ }
+ );
reset->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &Adjuster::resetPressed) );
show_all();
@@ -165,9 +182,8 @@ Adjuster::Adjuster (
Adjuster::~Adjuster ()
{
- sliderChange.block(true);
- spinChange.block(true);
- delayConnection.block(true);
+ sliderChange.block();
+ spinChange.block();
adjusterListener = nullptr;
}
@@ -211,8 +227,6 @@ void Adjuster::throwOnButtonRelease(bool throwOnBRelease)
buttonReleaseSpin.disconnect();
}
}
-
- eventPending = false;
}
void Adjuster::setDefault (double def)
@@ -239,9 +253,7 @@ void Adjuster::sliderReleased (GdkEventButton* event)
{
if ((event != nullptr) && (event->button == 1)) {
- if (delayConnection.connected()) {
- delayConnection.disconnect();
- }
+ sliderChange.cancel();
notifyListener();
}
@@ -250,10 +262,8 @@ void Adjuster::sliderReleased (GdkEventButton* event)
void Adjuster::spinReleased (GdkEventButton* event)
{
- if ((event != nullptr) && delay == 0) {
- if (delayConnection.connected()) {
- delayConnection.disconnect();
- }
+ if (event) {
+ spinChange.cancel();
notifyListener();
}
@@ -351,31 +361,15 @@ void Adjuster::setAddMode(bool addM)
}
}
-void Adjuster::spinChanged ()
+void Adjuster::spinChanged()
{
- if (delayConnection.connected()) {
- delayConnection.disconnect();
- }
-
- sliderChange.block(true);
- setSliderValue(addMode ? spin->get_value() : value2slider(spin->get_value()));
- sliderChange.block(false);
-
- if (delay == 0) {
- if (adjusterListener && !blocked) {
- if (!buttonReleaseSlider.connected() || afterReset) {
- eventPending = false;
- if (automatic) {
- setAutoValue(false);
- }
- adjusterListener->adjusterChanged(this, spin->get_value());
- } else {
- eventPending = true;
+ if (adjusterListener && !blocked) {
+ if (!buttonReleaseSlider.connected() || afterReset) {
+ if (automatic) {
+ setAutoValue(false);
}
+ adjusterListener->adjusterChanged(this, spin->get_value());
}
- } else {
- eventPending = true;
- delayConnection = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Adjuster::notifyListener), delay);
}
if (editedState == UnEdited) {
@@ -393,31 +387,13 @@ void Adjuster::spinChanged ()
void Adjuster::sliderChanged ()
{
-
- if (delayConnection.connected()) {
- delayConnection.disconnect();
- }
-
- spinChange.block(true);
- const double v = shapeValue(getSliderValue());
- spin->set_value(addMode ? v : slider2value(v));
- spinChange.block(false);
-
- if (delay == 0 || afterReset) {
- if (adjusterListener && !blocked) {
- if (!buttonReleaseSlider.connected() || afterReset) {
- eventPending = false;
- if (automatic) {
- setAutoValue(false);
- }
- adjusterListener->adjusterChanged(this, spin->get_value());
- } else {
- eventPending = true;
+ if (adjusterListener && !blocked) {
+ if (!buttonReleaseSlider.connected() || afterReset) {
+ if (automatic) {
+ setAutoValue(false);
}
+ adjusterListener->adjusterChanged(this, spin->get_value());
}
- } else {
- eventPending = true;
- delayConnection = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Adjuster::notifyListener), delay);
}
if (!afterReset && editedState == UnEdited) {
@@ -435,12 +411,12 @@ void Adjuster::sliderChanged ()
void Adjuster::setValue (double a)
{
- spinChange.block(true);
+ spinChange.block();
sliderChange.block(true);
spin->set_value(shapeValue(a));
setSliderValue(addMode ? shapeValue(a) : value2slider(shapeValue(a)));
sliderChange.block(false);
- spinChange.block(false);
+ spinChange.unblock();
afterReset = false;
}
@@ -455,16 +431,13 @@ void Adjuster::setAutoValue (bool a)
bool Adjuster::notifyListener ()
{
-
- if (eventPending && adjusterListener != nullptr && !blocked) {
+ if (adjusterListener != nullptr && !blocked) {
if (automatic) {
setAutoValue(false);
}
adjusterListener->adjusterChanged(this, spin->get_value());
}
- eventPending = false;
-
return false;
}
@@ -555,8 +528,6 @@ void Adjuster::editedToggled ()
}
adjusterListener->adjusterChanged(this, spin->get_value());
}
-
- eventPending = false;
}
void Adjuster::trimValue (double &val) const
@@ -706,3 +677,9 @@ bool Adjuster::getAddMode() const
{
return addMode;
}
+
+void Adjuster::setDelay(unsigned int min_delay_ms, unsigned int max_delay_ms)
+{
+ spinChange.setDelay(min_delay_ms, max_delay_ms);
+ sliderChange.setDelay(min_delay_ms, max_delay_ms);
+}
diff --git a/rtgui/adjuster.h b/rtgui/adjuster.h
index 143268786..abafbd730 100644
--- a/rtgui/adjuster.h
+++ b/rtgui/adjuster.h
@@ -19,6 +19,7 @@
#pragma once
#include "editedstate.h"
+#include "delayed.h"
#include "guiutils.h"
class Adjuster;
@@ -35,7 +36,6 @@ typedef double(*double2double_fun)(double val);
class Adjuster final : public Gtk::Grid
{
-
protected:
Glib::ustring adjustmentName;
Gtk::Grid* grid;
@@ -46,9 +46,8 @@ protected:
Gtk::Button* reset;
Gtk::CheckButton* automatic;
AdjusterListener* adjusterListener;
- sigc::connection delayConnection;
- sigc::connection spinChange;
- sigc::connection sliderChange;
+ DelayedConnection<> spinChange;
+ DelayedConnection<> sliderChange;
sigc::connection editedChange;
sigc::connection autoChange;
sigc::connection buttonReleaseSlider;
@@ -62,7 +61,6 @@ protected:
bool afterReset;
bool blocked;
bool addMode;
- bool eventPending;
double vMin;
double vMax;
double vStep;
@@ -78,11 +76,18 @@ protected:
void setSliderValue(double val);
public:
-
- int delay;
-
- Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon1 = nullptr, Gtk::Image *imgIcon2 = nullptr, double2double_fun slider2value = nullptr, double2double_fun value2slider = nullptr);
- ~Adjuster () override;
+ Adjuster(
+ Glib::ustring vlabel,
+ double vmin,
+ double vmax,
+ double vstep,
+ double vdefault,
+ Gtk::Image *imgIcon1 = nullptr,
+ Gtk::Image *imgIcon2 = nullptr,
+ double2double_fun slider2value = nullptr,
+ double2double_fun value2slider = nullptr
+ );
+ ~Adjuster() override;
// Add an "Automatic" checkbox next to the reset button.
void addAutoButton(const Glib::ustring &tooltip = "");
@@ -127,4 +132,5 @@ public:
void trimValue (float &val) const;
void trimValue (int &val) const;
void setLogScale(double base, double pivot, bool anchorMiddle = false);
+ void setDelay(unsigned int min_delay_ms, unsigned int max_delay_ms = 0);
};
diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc
index 8b4583877..19da96fb5 100644
--- a/rtgui/batchqueue.cc
+++ b/rtgui/batchqueue.cc
@@ -344,8 +344,9 @@ bool BatchQueue::loadBatchQueue ()
auto job = rtengine::ProcessingJob::create (source, thumb->getType () == FT_Raw, pparams, fast);
- const auto prevh = getMaxThumbnailHeight ();
- const auto prevw = thumb->getThumbnailWidth(prevh, &pparams);
+ auto prevh = getMaxThumbnailHeight();
+ auto prevw = prevh;
+ thumb->getThumbnailSize(prevw, prevh, &pparams);
auto entry = new BatchQueueEntry (job, pparams, source, prevw, prevh, thumb, options.overwriteOutputFile);
thumb->decreaseRef (); // Removing the refCount acquired by cacheMgr->getEntry
@@ -390,7 +391,7 @@ Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring &filenam
timeval tv;
gettimeofday(&tv, nullptr);
char mseconds[11];
- sprintf(mseconds, "%d", (int)(tv.tv_usec / 1000));
+ snprintf(mseconds, sizeof(mseconds), "%d", (int)(tv.tv_usec / 1000));
time_t rawtime;
struct tm *timeinfo;
char stringTimestamp [80];
@@ -699,7 +700,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/batchqueueentry.cc b/rtgui/batchqueueentry.cc
index 90079b2cc..31a6f40c7 100644
--- a/rtgui/batchqueueentry.cc
+++ b/rtgui/batchqueueentry.cc
@@ -106,8 +106,12 @@ void BatchQueueEntry::refreshThumbnailImage ()
void BatchQueueEntry::calcThumbnailSize ()
{
-
prew = preh * origpw / origph;
+ if (prew > options.maxThumbnailWidth) {
+ const float s = static_cast(options.maxThumbnailWidth) / prew;
+ prew = options.maxThumbnailWidth;
+ preh = std::max(preh * s, 1);
+ }
}
@@ -261,9 +265,8 @@ void BatchQueueEntry::_updateImage (guint8* img, int w, int h)
MYWRITERLOCK(l, lockRW);
prew = w;
- assert (preview == nullptr);
- preview = new guint8 [prew * preh * 3];
- memcpy (preview, img, prew * preh * 3);
+ preview.resize(prew * preh * 3);
+ std::copy(img, img + preview.size(), preview.begin());
if (parent) {
parent->redrawNeeded (this);
diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc
index 0c01213e7..2a1896d80 100644
--- a/rtgui/bayerpreprocess.cc
+++ b/rtgui/bayerpreprocess.cc
@@ -37,18 +37,14 @@ BayerPreProcess::BayerPreProcess() : FoldableToolPanel(this, "bayerpreprocess",
lineDenoise = Gtk::manage(new Adjuster(M("TP_PREPROCESS_LINEDENOISE"), 0, 1000, 1, 0));
lineDenoise->setAdjusterListener(this);
- if (lineDenoise->delay < options.adjusterMaxDelay) {
- lineDenoise->delay = options.adjusterMaxDelay;
- }
+ lineDenoise->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
lineDenoise->show();
greenEqThreshold = Gtk::manage(new Adjuster(M("TP_PREPROCESS_GREENEQUIL"), 0, 100, 1, 0));
greenEqThreshold->setAdjusterListener(this);
- if (greenEqThreshold->delay < options.adjusterMaxDelay) {
- greenEqThreshold->delay = options.adjusterMaxDelay;
- }
+ greenEqThreshold->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
greenEqThreshold->show();
diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc
index 66053a338..d219dbdd1 100644
--- a/rtgui/bayerprocess.cc
+++ b/rtgui/bayerprocess.cc
@@ -60,9 +60,7 @@ BayerProcess::BayerProcess () :
dualDemosaicContrast->setAdjusterListener(this);
dualDemosaicContrast->addAutoButton(M("TP_RAW_DUALDEMOSAICAUTOCONTRAST_TOOLTIP"));
dualDemosaicContrast->setAutoValue(true);
- if (dualDemosaicContrast->delay < options.adjusterMaxDelay) {
- dualDemosaicContrast->delay = options.adjusterMaxDelay;
- }
+ dualDemosaicContrast->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
dualDemosaicContrast->show();
dualDemosaicOptions->pack_start(*dualDemosaicContrast);
@@ -72,9 +70,7 @@ BayerProcess::BayerProcess () :
border = Gtk::manage(new Adjuster(M("TP_RAW_BORDER"), 0, 16, 1, 4));
border->setAdjusterListener (this);
- if (border->delay < options.adjusterMaxDelay) {
- border->delay = options.adjusterMaxDelay;
- }
+ border->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
border->show();
borderbox->pack_start(*border);
@@ -96,22 +92,17 @@ BayerProcess::BayerProcess () :
ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 ));
ccSteps->setAdjusterListener (this);
- if (ccSteps->delay < options.adjusterMaxDelay) {
- ccSteps->delay = options.adjusterMaxDelay;
- }
+ ccSteps->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
ccSteps->show();
pack_start( *ccSteps, Gtk::PACK_SHRINK, 4);
-
dcbOptions = Gtk::manage (new Gtk::VBox ());
dcbIterations = Gtk::manage (new Adjuster (M("TP_RAW_DCBITERATIONS"), 0, 5, 1, 2));
dcbIterations->setAdjusterListener (this);
- if (dcbIterations->delay < options.adjusterMaxDelay) {
- dcbIterations->delay = options.adjusterMaxDelay;
- }
+ dcbIterations->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
dcbIterations->show();
dcbEnhance = Gtk::manage (new CheckBox(M("TP_RAW_DCBENHANCE"), multiImage));
@@ -126,9 +117,7 @@ BayerProcess::BayerProcess () :
lmmseIterations->setAdjusterListener (this);
lmmseIterations->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP"));
- if (lmmseIterations->delay < options.adjusterMaxDelay) {
- lmmseIterations->delay = options.adjusterMaxDelay;
- }
+ lmmseIterations->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
lmmseIterations->show();
lmmseOptions->pack_start(*lmmseIterations);
@@ -209,9 +198,7 @@ BayerProcess::BayerProcess () :
pixelShiftSigma->set_tooltip_text (M("TP_RAW_PIXELSHIFTSIGMA_TOOLTIP"));
pixelShiftSigma->setAdjusterListener (this);
- if (pixelShiftSigma->delay < options.adjusterMaxDelay) {
- pixelShiftSigma->delay = options.adjusterMaxDelay;
- }
+ pixelShiftSigma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
pixelShiftSigma->show();
pixelShiftOptions->pack_start(*pixelShiftSigma);
@@ -221,9 +208,7 @@ BayerProcess::BayerProcess () :
pixelShiftSmooth->set_tooltip_text (M("TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP"));
pixelShiftSmooth->setAdjusterListener (this);
- if (pixelShiftSmooth->delay < options.adjusterMaxDelay) {
- pixelShiftSmooth->delay = options.adjusterMaxDelay;
- }
+ pixelShiftSmooth->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
pixelShiftSmooth->show();
pixelShiftOptions->pack_start(*pixelShiftSmooth);
@@ -232,9 +217,7 @@ BayerProcess::BayerProcess () :
pixelShiftEperIso->set_tooltip_text(M("TP_RAW_PIXELSHIFTEPERISO_TOOLTIP"));
pixelShiftEperIso->setAdjusterListener (this);
- if (pixelShiftEperIso->delay < options.adjusterMaxDelay) {
- pixelShiftEperIso->delay = options.adjusterMaxDelay;
- }
+ pixelShiftEperIso->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
pixelShiftEperIso->show();
pixelShiftOptions->pack_start(*pixelShiftEperIso);
@@ -366,7 +349,10 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params
dcbOptions->set_visible(pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCB) || pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4));
lmmseOptions->set_visible(pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::LMMSE));
dualDemosaicOptions->set_visible(pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4)
+ || pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEBILINEAR)
|| pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4)
+ || pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBBILINEAR)
+ || pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDBILINEAR)
|| pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDVNG4));
if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT)) {
pixelShiftOptions->set_visible(pp->raw.bayersensor.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::PSMotionCorrectionMethod::CUSTOM);
@@ -575,7 +561,12 @@ void BayerProcess::methodChanged ()
lmmseOptions->hide();
}
- if (currentMethod == procparams::RAWParams::BayerSensor::Method::AMAZEVNG4 || currentMethod == procparams::RAWParams::BayerSensor::Method::DCBVNG4 || currentMethod == procparams::RAWParams::BayerSensor::Method::RCDVNG4) {
+ if (currentMethod == procparams::RAWParams::BayerSensor::Method::AMAZEVNG4 ||
+ currentMethod == procparams::RAWParams::BayerSensor::Method::DCBVNG4 ||
+ currentMethod == procparams::RAWParams::BayerSensor::Method::RCDVNG4 ||
+ currentMethod == procparams::RAWParams::BayerSensor::Method::AMAZEBILINEAR ||
+ currentMethod == procparams::RAWParams::BayerSensor::Method::DCBBILINEAR ||
+ currentMethod == procparams::RAWParams::BayerSensor::Method::RCDBILINEAR) {
dualDemosaicOptions->show();
} else {
dualDemosaicOptions->hide();
diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc
index 9d8f9fff8..bb3c3a48a 100644
--- a/rtgui/bayerrawexposure.cc
+++ b/rtgui/bayerrawexposure.cc
@@ -31,33 +31,25 @@ BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, "bayerrawexposur
PexBlack1 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_1"), -2048, 2048, 1.0, 0)); //black level
PexBlack1->setAdjusterListener (this);
- if (PexBlack1->delay < options.adjusterMaxDelay) {
- PexBlack1->delay = options.adjusterMaxDelay;
- }
+ PexBlack1->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
PexBlack1->show();
PexBlack2 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_2"), -2048, 2048, 1.0, 0)); //black level
PexBlack2->setAdjusterListener (this);
- if (PexBlack2->delay < options.adjusterMaxDelay) {
- PexBlack2->delay = options.adjusterMaxDelay;
- }
+ PexBlack2->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
PexBlack2->show();
PexBlack3 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_3"), -2048, 2048, 1.0, 0)); //black level
PexBlack3->setAdjusterListener (this);
- if (PexBlack3->delay < options.adjusterMaxDelay) {
- PexBlack3->delay = options.adjusterMaxDelay;
- }
+ PexBlack3->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
PexBlack3->show();
PexBlack0 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_0"), -2048, 2048, 1.0, 0)); //black level
PexBlack0->setAdjusterListener (this);
- if (PexBlack0->delay < options.adjusterMaxDelay) {
- PexBlack0->delay = options.adjusterMaxDelay;
- }
+ PexBlack0->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
PexBlack0->show();
PextwoGreen = Gtk::manage(new CheckBox(M("TP_RAWEXPOS_TWOGREEN"), multiImage));// two green
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/colorappearance.cc b/rtgui/colorappearance.cc
index bdbe3de3a..b4d5459ce 100644
--- a/rtgui/colorappearance.cc
+++ b/rtgui/colorappearance.cc
@@ -222,11 +222,35 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
Evcatpreset = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_CAT02PRESET");
EvCATAutotempout = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_TEMPOUT");
EvCATillum = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ILLUM");
+ EvCATcomplex = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_CATCOMPLEX");
//preset button cat02
+ Gtk::Frame *genFrame;
+ Gtk::VBox *genVBox;
+ genFrame = Gtk::manage (new Gtk::Frame (M ("TP_COLORAPP_GEN")) );
+ genFrame->set_label_align (0.025, 0.5);
+ genFrame->set_tooltip_markup (M ("TP_COLORAPP_GEN_TOOLTIP"));
+ genVBox = Gtk::manage ( new Gtk::VBox());
+ genVBox->set_spacing (2);
+
+ complexmethod = Gtk::manage (new MyComboBoxText ());
+ complexmethod->append(M("TP_WAVELET_COMPNORMAL"));
+ complexmethod->append(M("TP_WAVELET_COMPEXPERT"));
+ complexmethodconn = complexmethod->signal_changed().connect(sigc::mem_fun(*this, &ColorAppearance::complexmethodChanged));
+ complexmethod->set_tooltip_text(M("TP_WAVELET_COMPLEX_TOOLTIP"));
+ Gtk::HBox* const complexHBox = Gtk::manage(new Gtk::HBox());
+ Gtk::Label* const complexLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_COMPLEXLAB") + ":"));
+ complexHBox->pack_start(*complexLabel, Gtk::PACK_SHRINK, 4);
+ complexHBox->pack_start(*complexmethod);
+ genVBox->pack_start (*complexHBox, Gtk::PACK_SHRINK);
+
+
presetcat02 = Gtk::manage (new Gtk::CheckButton (M ("TP_COLORAPP_PRESETCAT02")));
presetcat02->set_tooltip_markup (M("TP_COLORAPP_PRESETCAT02_TIP"));
presetcat02conn = presetcat02->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::presetcat02pressed));
- pack_start (*presetcat02, Gtk::PACK_SHRINK);
+ genVBox->pack_start (*presetcat02, Gtk::PACK_SHRINK);
+
+ genFrame->add (*genVBox);
+ pack_start (*genFrame, Gtk::PACK_EXPAND_WIDGET, 4);
// ----------------------- Process #1: Converting to CIECAM
@@ -238,15 +262,14 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
p1Frame = Gtk::manage (new Gtk::Frame (M ("TP_COLORAPP_LABEL_SCENE")) );
p1Frame->set_label_align (0.025, 0.5);
-
+ p1Frame->set_tooltip_markup (M ("TP_COLORAPP_SOURCEF_TOOLTIP"));
p1VBox = Gtk::manage ( new Gtk::VBox());
p1VBox->set_spacing (2);
degree = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 90.));
+ degree->set_tooltip_markup (M ("TP_COLORAPP_DEGREE_TOOLTIP"));
- if (degree->delay < options.adjusterMaxDelay) {
- degree->delay = options.adjusterMaxDelay;
- }
+ degree->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
degree->throwOnButtonRelease();
degree->addAutoButton (M ("TP_COLORAPP_CAT02ADAPTATION_TOOLTIP"));
@@ -258,8 +281,8 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
Gtk::HBox* surrHBox1 = Gtk::manage (new Gtk::HBox ());
surrHBox1->set_spacing (2);
- surrHBox1->set_tooltip_markup (M ("TP_COLORAPP_SURROUND_TOOLTIP"));
- Gtk::Label* surrLabel1 = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_SURROUND") + ":"));
+ surrHBox1->set_tooltip_markup (M ("TP_COLORAPP_SURSOURCE_TOOLTIP"));
+ Gtk::Label* surrLabel1 = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_SURROUNDSRC") + ":"));
surrHBox1->pack_start (*surrLabel1, Gtk::PACK_SHRINK);
surrsrc = Gtk::manage (new MyComboBoxText ());
surrsrc->append (M ("TP_COLORAPP_SURROUND_AVER"));
@@ -272,7 +295,11 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
// p1VBox->pack_start (*surrsource, Gtk::PACK_SHRINK);
- Gtk::HBox* wbmHBox = Gtk::manage (new Gtk::HBox ());
+
+
+// Gtk::HBox* wbmHBox = Gtk::manage (new Gtk::HBox ());
+ wbmHBox = Gtk::manage (new Gtk::HBox ());
+
wbmHBox->set_spacing (2);
wbmHBox->set_tooltip_markup (M ("TP_COLORAPP_MODEL_TOOLTIP"));
Gtk::Label* wbmLab = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_MODEL") + ":"));
@@ -287,7 +314,8 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
p1VBox->pack_start (*wbmHBox);
- Gtk::HBox* illumHBox = Gtk::manage (new Gtk::HBox ());
+// Gtk::HBox* illumHBox = Gtk::manage (new Gtk::HBox ());
+ illumHBox = Gtk::manage (new Gtk::HBox ());
illumHBox->set_spacing (2);
illumHBox->set_tooltip_markup (M ("TP_COLORAPP_ILLUM_TOOLTIP"));
Gtk::Label* illumLab = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_ILLUM") + ":"));
@@ -325,19 +353,17 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
// adapscen = Gtk::manage (new Adjuster (M ("TP_COLORAPP_ABSOLUTELUMINANCE"), 0.01, 16384., 0.001, 2000.)); // EV -7 ==> EV 17
adapscen = Gtk::manage (new Adjuster (M ("TP_COLORAPP_ABSOLUTELUMINANCE"), MINLA0, MAXLA0, 0.01, 1997.4, NULL, NULL, &wbSlider2la, &wbla2Slider));
- if (adapscen->delay < options.adjusterMaxDelay) {
- adapscen->delay = options.adjusterMaxDelay;
- }
+ adapscen->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
+ adapscen->set_tooltip_markup (M ("TP_COLORAPP_ADAPSCEN_TOOLTIP"));
adapscen->throwOnButtonRelease();
adapscen->addAutoButton();
p1VBox->pack_start (*adapscen);
ybscen = Gtk::manage (new Adjuster (M ("TP_COLORAPP_MEANLUMINANCE"), 1, 90, 1, 18));
+ ybscen->set_tooltip_markup (M ("TP_COLORAPP_YBSCEN_TOOLTIP"));
- if (ybscen->delay < options.adjusterMaxDelay) {
- ybscen->delay = options.adjusterMaxDelay;
- }
+ ybscen->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
ybscen->throwOnButtonRelease();
ybscen->addAutoButton();
@@ -368,7 +394,8 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
p2VBox = Gtk::manage ( new Gtk::VBox());
p2VBox->set_spacing (2);
- Gtk::HBox* alHBox = Gtk::manage (new Gtk::HBox ());
+// Gtk::HBox* alHBox = Gtk::manage (new Gtk::HBox ());
+ alHBox = Gtk::manage (new Gtk::HBox ());
alHBox->set_spacing (2);
alHBox->set_tooltip_markup (M ("TP_COLORAPP_ALGO_TOOLTIP"));
Gtk::Label* alLabel = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_ALGO") + ":"));
@@ -386,9 +413,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
jlight = Gtk::manage (new Adjuster (M ("TP_COLORAPP_LIGHT"), -100.0, 100.0, 0.1, 0.));
- if (jlight->delay < options.adjusterMaxDelay) {
- jlight->delay = options.adjusterMaxDelay;
- }
+ jlight->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
jlight->throwOnButtonRelease();
jlight->set_tooltip_markup (M ("TP_COLORAPP_LIGHT_TOOLTIP"));
@@ -396,9 +421,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
qbright = Gtk::manage (new Adjuster (M ("TP_COLORAPP_BRIGHT"), -100.0, 100.0, 0.1, 0.));
- if (qbright->delay < options.adjusterMaxDelay) {
- qbright->delay = options.adjusterMaxDelay;
- }
+ qbright->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
qbright->throwOnButtonRelease();
qbright->set_tooltip_markup (M ("TP_COLORAPP_BRIGHT_TOOLTIP"));
@@ -406,9 +429,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
chroma = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CHROMA"), -100.0, 100.0, 0.1, 0.));
- if (chroma->delay < options.adjusterMaxDelay) {
- chroma->delay = options.adjusterMaxDelay;
- }
+ chroma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
chroma->throwOnButtonRelease();
chroma->set_tooltip_markup (M ("TP_COLORAPP_CHROMA_TOOLTIP"));
@@ -417,9 +438,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
schroma = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CHROMA_S"), -100.0, 100.0, 0.1, 0.));
- if (schroma->delay < options.adjusterMaxDelay) {
- schroma->delay = options.adjusterMaxDelay;
- }
+ schroma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
schroma->throwOnButtonRelease();
schroma->set_tooltip_markup (M ("TP_COLORAPP_CHROMA_S_TOOLTIP"));
@@ -427,9 +446,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
mchroma = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CHROMA_M"), -100.0, 100.0, 0.1, 0.));
- if (mchroma->delay < options.adjusterMaxDelay) {
- mchroma->delay = options.adjusterMaxDelay;
- }
+ mchroma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
mchroma->throwOnButtonRelease();
mchroma->set_tooltip_markup (M ("TP_COLORAPP_CHROMA_M_TOOLTIP"));
@@ -437,9 +454,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
rstprotection = Gtk::manage ( new Adjuster (M ("TP_COLORAPP_RSTPRO"), 0., 100., 0.1, 0.) );
- if (rstprotection->delay < options.adjusterMaxDelay) {
- rstprotection->delay = options.adjusterMaxDelay;
- }
+ rstprotection->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
rstprotection->throwOnButtonRelease();
rstprotection->set_tooltip_markup (M ("TP_COLORAPP_RSTPRO_TOOLTIP"));
@@ -447,9 +462,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
contrast = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CONTRAST"), -100.0, 100.0, 0.1, 0.));
- if (contrast->delay < options.adjusterMaxDelay) {
- contrast->delay = options.adjusterMaxDelay;
- }
+ contrast->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
contrast->throwOnButtonRelease();
contrast->set_tooltip_markup (M ("TP_COLORAPP_CONTRAST_TOOLTIP"));
@@ -457,9 +470,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
qcontrast = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CONTRAST_Q"), -100.0, 100.0, 0.1, 0.));
- if (qcontrast->delay < options.adjusterMaxDelay) {
- qcontrast->delay = options.adjusterMaxDelay;
- }
+ qcontrast->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
qcontrast->throwOnButtonRelease();
qcontrast->set_tooltip_markup (M ("TP_COLORAPP_CONTRAST_Q_TOOLTIP"));
@@ -468,9 +479,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
colorh = Gtk::manage (new Adjuster (M ("TP_COLORAPP_HUE"), -100.0, 100.0, 0.1, 0.));
- if (colorh->delay < options.adjusterMaxDelay) {
- colorh->delay = options.adjusterMaxDelay;
- }
+ colorh->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
colorh->throwOnButtonRelease();
colorh->set_tooltip_markup (M ("TP_COLORAPP_HUE_TOOLTIP"));
@@ -607,6 +616,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
p3Frame = Gtk::manage (new Gtk::Frame (M ("TP_COLORAPP_LABEL_VIEWING")) ); // "Editing viewing conditions" ???
p3Frame->set_label_align (0.025, 0.5);
+ p3Frame->set_tooltip_markup (M ("TP_COLORAPP_VIEWINGF_TOOLTIP"));
p3VBox = Gtk::manage ( new Gtk::VBox());
p3VBox->set_spacing (2);
@@ -618,9 +628,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
// adaplum = Gtk::manage (new Adjuster (M ("TP_COLORAPP_ABSOLUTELUMINANCE"), 0.1, 16384., 0.1, 16.));
adaplum = Gtk::manage (new Adjuster (M ("TP_COLORAPP_ABSOLUTELUMINANCE"), MINLA0, MAXLA0, 0.01, 16, NULL, NULL, &wbSlider2la, &wbla2Slider));
- if (adaplum->delay < options.adjusterMaxDelay) {
- adaplum->delay = options.adjusterMaxDelay;
- }
+ adaplum->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
adaplum->throwOnButtonRelease();
adaplum->set_tooltip_markup (M ("TP_COLORAPP_VIEWING_ABSOLUTELUMINANCE_TOOLTIP"));
@@ -631,11 +639,11 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
degreeout = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 90.));
- if (degreeout->delay < options.adjusterMaxDelay) {
- degreeout->delay = options.adjusterMaxDelay;
- }
+ degreeout->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
degreeout->throwOnButtonRelease();
+ degreeout->set_tooltip_markup (M ("TP_COLORAPP_DEGREOUT_TOOLTIP"));
+
degreeout->addAutoButton (M ("TP_COLORAPP_CAT02ADAPTATION_TOOLTIP"));
p3VBox->pack_start (*degreeout);
/*
@@ -647,6 +655,8 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
tempout = Gtk::manage (new Adjuster (M ("TP_WBALANCE_TEMPERATURE"), MINTEMP0, MAXTEMP0, 5, CENTERTEMP0, itempR1, itempL1, &wbSlider2Temp, &wbTemp2Slider));
greenout = Gtk::manage (new Adjuster (M ("TP_WBALANCE_GREEN"), MINGREEN0, MAXGREEN0, 0.001, 1.0, igreenR1, igreenL1));
ybout = Gtk::manage (new Adjuster (M ("TP_COLORAPP_MEANLUMINANCE"), 5, 90, 1, 18));
+ ybout->set_tooltip_markup (M ("TP_COLORAPP_YBOUT_TOOLTIP"));
+
tempout->set_tooltip_markup (M ("TP_COLORAPP_TEMP2_TOOLTIP"));
tempout->throwOnButtonRelease();
tempout->addAutoButton (M ("TP_COLORAPP_TEMPOUT_TOOLTIP"));
@@ -694,9 +704,7 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance"
*/
badpixsl = Gtk::manage (new Adjuster (M ("TP_COLORAPP_BADPIXSL"), 0, 2, 1, 0));
- if (badpixsl->delay < options.adjusterMaxDelay) {
- badpixsl->delay = options.adjusterMaxDelay;
- }
+ badpixsl->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
badpixsl->throwOnButtonRelease();
badpixsl->set_tooltip_markup (M ("TP_COLORAPP_BADPIXSL_TOOLTIP"));
@@ -833,6 +841,7 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited)
{
disableListener ();
+ complexmethodconn.block(true);
tcmodeconn.block (true);
tcmode2conn.block (true);
tcmode3conn.block (true);
@@ -891,6 +900,9 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited)
if (!pedited->colorappearance.curveMode) {
toneCurveMode->set_active (2);
}
+ if (!pedited->colorappearance.complexmethod) {
+ complexmethod->set_active_text(M("GENERAL_UNCHANGED"));
+ }
if (!pedited->colorappearance.curveMode2) {
toneCurveMode2->set_active (2);
@@ -906,6 +918,13 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited)
setEnabled (pp->colorappearance.enabled);
+ if (pp->colorappearance.complexmethod == "normal") {
+ complexmethod->set_active(0);
+ } else if (pp->colorappearance.complexmethod == "expert") {
+ complexmethod->set_active(1);
+ }
+
+
surrsrcconn.block (true);
if (pedited && !pedited->colorappearance.surrsrc) {
@@ -1068,9 +1087,18 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited)
presetcat02conn.block (false);
lastpresetcat02 = pp->colorappearance.presetcat02;
+ if (complexmethod->get_active_row_number() == 0) {
+ updateGUIToMode(0);
+ convertParamToNormal();
+
+ } else {
+ updateGUIToMode(1);
+ }
+
tcmode3conn.block (false);
tcmode2conn.block (false);
tcmodeconn.block (false);
+ complexmethodconn.block(false);
enableListener ();
}
void ColorAppearance::autoOpenCurve ()
@@ -1149,6 +1177,7 @@ void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited)
}
if (pedited) {
+ pedited->colorappearance.complexmethod = complexmethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->colorappearance.degree = degree->getEditedState ();
pedited->colorappearance.degreeout = degreeout->getEditedState ();
pedited->colorappearance.adapscen = adapscen->getEditedState ();
@@ -1196,6 +1225,14 @@ void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited)
}
+ if (complexmethod->get_active_row_number() == 0) {
+ pp->colorappearance.complexmethod = "normal";
+ } else if (complexmethod->get_active_row_number() == 1) {
+ pp->colorappearance.complexmethod = "expert";
+ }
+
+
+
if (surrsrc->get_active_row_number() == 0) {
pp->colorappearance.surrsrc = "Average";
} else if (surrsrc->get_active_row_number() == 1) {
@@ -1254,6 +1291,71 @@ void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited)
}
}
+
+
+void ColorAppearance::updateGUIToMode(int mode)
+{
+ if(mode ==0) {
+ alHBox->hide();
+ wbmHBox->hide();
+ curveEditorG->hide();
+ curveEditorG2->hide();
+ curveEditorG3->hide();
+ greenout->hide();
+ badpixsl->hide();
+ datacie->hide();
+ } else {
+ alHBox->show();
+ wbmHBox->show();
+ curveEditorG->show();
+ curveEditorG2->show();
+ curveEditorG3->show();
+ greenout->show();
+ badpixsl->show();
+ datacie->show();
+ }
+
+}
+
+void ColorAppearance::convertParamToNormal()
+{
+ const ColorAppearanceParams def_params;
+ disableListener();
+ algo->set_active (0);
+ shape->setCurve(def_params.curve);
+ shape2->setCurve(def_params.curve2);
+ shape3->setCurve(def_params.curve3);
+ shape->reset();
+ shape2->reset();
+ shape3->reset();
+ wbmodel->set_active (0);
+ if (presetcat02->get_active ()) {
+ wbmodel->set_active (2);
+ }
+ greenout->setValue(def_params.greenout);
+ badpixsl->setValue(def_params.badpixsl);
+
+ enableListener();
+
+ // Update GUI based on converted widget parameters:
+}
+
+void ColorAppearance::complexmethodChanged()
+{
+ if (complexmethod->get_active_row_number() == 0) {
+ updateGUIToMode(0);
+ convertParamToNormal();
+
+ } else {
+ updateGUIToMode(1);
+ }
+
+ if (listener && (multiImage || getEnabled())) {
+ listener->panelChanged(EvCATcomplex, complexmethod->get_active_text());
+ }
+}
+
+
void ColorAppearance::curveChanged (CurveEditor* ce)
{
@@ -1954,6 +2056,7 @@ void ColorAppearance::wbmodelChanged ()
{
if (wbmodel->get_active_row_number() == 0 || wbmodel->get_active_row_number() == 1) {
illum->hide();
+ illumHBox->hide();
tempsc->hide();
greensc->hide();
tempsc->setValue (5003);
@@ -1961,6 +2064,7 @@ void ColorAppearance::wbmodelChanged ()
}
if (wbmodel->get_active_row_number() == 2) {
+ illumHBox->show();
tempsc->show();
greensc->show();
illum->show();
@@ -2111,6 +2215,7 @@ void ColorAppearance::setBatchMode (bool batchMode)
tempsc->showEditedCB ();
greensc->showEditedCB ();
+ complexmethod->append(M("GENERAL_UNCHANGED"));
surround->append (M ("GENERAL_UNCHANGED"));
surrsrc->append (M ("GENERAL_UNCHANGED"));
wbmodel->append (M ("GENERAL_UNCHANGED"));
diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h
index c326b06f9..6976f4d29 100644
--- a/rtgui/colorappearance.h
+++ b/rtgui/colorappearance.h
@@ -77,6 +77,9 @@ public:
void curveMode3Changed ();
bool curveMode3Changed_ ();
void neutral_pressed ();
+ void complexmethodChanged();
+ void convertParamToNormal();
+ void updateGUIToMode(int mode);
void expandCurve (bool isExpanded);
bool isCurveExpanded ();
@@ -104,6 +107,7 @@ private:
rtengine::ProcEvent Evcatpreset;
rtengine::ProcEvent EvCATAutotempout;
rtengine::ProcEvent EvCATillum;
+ rtengine::ProcEvent EvCATcomplex;
bool bgTTipQuery (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
bool srTTipQuery (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
void foldAllButMe (GdkEventButton* event, MyExpander *expander);
@@ -139,6 +143,7 @@ private:
MyComboBoxText* toneCurveMode;
MyComboBoxText* toneCurveMode2;
MyComboBoxText* toneCurveMode3;
+ MyComboBoxText* complexmethod;
//Adjuster* edge;
Gtk::CheckButton* surrsource;
@@ -165,6 +170,10 @@ private:
sigc::connection surrconn;
sigc::connection gamutconn, datacieconn, tonecieconn /*,badpixconn , sharpcieconn*/;
sigc::connection tcmodeconn, tcmode2conn, tcmode3conn, neutralconn;
+ sigc::connection complexmethodconn;
+ Gtk::HBox* alHBox;
+ Gtk::HBox* wbmHBox;
+ Gtk::HBox* illumHBox;
CurveEditorGroup* curveEditorG;
CurveEditorGroup* curveEditorG2;
CurveEditorGroup* curveEditorG3;
diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc
index ddf917149..77bc31638 100644
--- a/rtgui/colortoning.cc
+++ b/rtgui/colortoning.cc
@@ -488,11 +488,11 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR
pack_start(*labRegionBox, Gtk::PACK_EXPAND_WIDGET, 4);
- labRegionSaturation->delay = options.adjusterMaxDelay;
- labRegionSlope->delay = options.adjusterMaxDelay;
- labRegionOffset->delay = options.adjusterMaxDelay;
- labRegionPower->delay = options.adjusterMaxDelay;
- labRegionMaskBlur->delay = options.adjusterMaxDelay;
+ labRegionSaturation->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
+ labRegionSlope->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
+ labRegionOffset->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
+ labRegionPower->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
+ labRegionMaskBlur->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
//------------------------------------------------------------------------
show_all();
diff --git a/rtgui/controllines.cc b/rtgui/controllines.cc
new file mode 100644
index 000000000..573b3263f
--- /dev/null
+++ b/rtgui/controllines.cc
@@ -0,0 +1,492 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2020 Lawrence Lee
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#include
+
+#include "controllines.h"
+#include "editcallbacks.h"
+#include "editwidgets.h"
+#include "rtsurface.h"
+
+#include "../rtengine/perspectivecorrection.h"
+
+using namespace rtengine;
+
+::ControlLine::~ControlLine() = default;
+
+ControlLineManager::ControlLineManager():
+ EditSubscriber(ET_OBJECTS),
+ canvas_area(new Rectangle()),
+ cursor(CSHandOpen),
+ draw_mode(false),
+ drawing_line(false),
+ edited(false),
+ prev_obj(-1),
+ selected_object(-1)
+{
+ canvas_area->filled = true;
+ canvas_area->topLeft = Coord(0, 0);
+ mouseOverGeometry.push_back(canvas_area.get());
+
+ line_icon_h = Cairo::RefPtr(new RTSurface(
+ "bidirectional-arrow-horizontal-hicontrast.png"));
+ line_icon_v = Cairo::RefPtr(new RTSurface(
+ "bidirectional-arrow-vertical-hicontrast.png"));
+ line_icon_h_prelight = Cairo::RefPtr(new RTSurface(
+ "bidirectional-arrow-horizontal-prelight.png"));
+ line_icon_v_prelight = Cairo::RefPtr(new RTSurface(
+ "bidirectional-arrow-vertical-prelight.png"));
+}
+
+ControlLineManager::~ControlLineManager() = default;
+
+void ControlLineManager::setActive(bool active)
+{
+ EditDataProvider* provider = getEditProvider();
+
+ if (!provider || (this == provider->getCurrSubscriber()) == active) {
+ return;
+ }
+
+ if (active) {
+ subscribe();
+
+ int ih, iw;
+ provider->getImageSize(iw, ih);
+ canvas_area->bottomRight = Coord(iw, ih);
+ } else {
+ unsubscribe();
+ }
+}
+
+void ControlLineManager::setDrawMode(bool draw)
+{
+ draw_mode = draw;
+}
+
+size_t ControlLineManager::size(void) const
+{
+ return control_lines.size();
+}
+
+bool ControlLineManager::button1Pressed(int modifierKey)
+{
+ EditDataProvider* dataProvider = getEditProvider();
+
+ if (!dataProvider) {
+ return false;
+ }
+
+ drag_delta = Coord(0, 0);
+
+ const int object = dataProvider->getObject();
+
+ if (object > 0) { // A control line.
+ if (object % ::ControlLine::OBJ_COUNT == 2) { // Icon.
+ action = Action::PICKING;
+ } else {
+ selected_object = object;
+ action = Action::DRAGGING;
+ }
+ } else if (draw_mode && (modifierKey & GDK_CONTROL_MASK)) { // Add new line.
+ addLine(dataProvider->posImage, dataProvider->posImage);
+ drawing_line = true;
+ selected_object = mouseOverGeometry.size() - 1; // Select endpoint.
+ action = Action::DRAGGING;
+ }
+
+ return true;
+}
+
+bool ControlLineManager::button1Released(void)
+{
+ action = Action::NONE;
+
+ if (selected_object > 0) {
+ mouseOverGeometry[selected_object]->state = Geometry::NORMAL;
+ }
+
+ edited = true;
+ callbacks->lineChanged();
+ drawing_line = false;
+ selected_object = -1;
+ return false;
+}
+
+bool ControlLineManager::button3Pressed(int modifierKey)
+{
+ EditDataProvider* provider = getEditProvider();
+
+ action = Action::NONE;
+
+ if (!provider || provider->getObject() < 1) {
+ return false;
+ }
+
+ action = Action::PICKING;
+ return false;
+}
+
+bool ControlLineManager::pick1(bool picked)
+{
+ action = Action::NONE;
+
+ if (!picked) {
+ return false;
+ }
+
+ EditDataProvider* provider = getEditProvider();
+
+ if (!provider || provider->getObject() % ::ControlLine::OBJ_COUNT != 2) {
+ return false;
+ }
+
+ // Change line type.
+ int object_id = provider->getObject();
+ ::ControlLine& line =
+ *control_lines[(object_id - 1) / ::ControlLine::OBJ_COUNT];
+
+ if (line.type == rtengine::ControlLine::HORIZONTAL) {
+ line.icon = line.icon_v;
+ line.type = rtengine::ControlLine::VERTICAL;
+ } else if (line.type == rtengine::ControlLine::VERTICAL) {
+ line.icon = line.icon_h;
+ line.type = rtengine::ControlLine::HORIZONTAL;
+ }
+
+ visibleGeometry[object_id - 1] = line.icon.get();
+
+ edited = true;
+ callbacks->lineChanged();
+
+ return true;
+}
+
+bool ControlLineManager::pick3(bool picked)
+{
+ action = Action::NONE;
+
+ if (!picked) {
+ return false;
+ }
+
+ EditDataProvider* provider = getEditProvider();
+
+ if (!provider) {
+ return false;
+ }
+
+ removeLine((provider->getObject() - 1) / ::ControlLine::OBJ_COUNT);
+ prev_obj = -1;
+ selected_object = -1;
+ return false;
+}
+
+bool ControlLineManager::drag1(int modifierKey)
+{
+ EditDataProvider* provider = getEditProvider();
+
+ if (!provider || selected_object < 1) {
+ return false;
+ }
+
+ ::ControlLine& control_line =
+ *control_lines[(selected_object - 1) / ::ControlLine::OBJ_COUNT];
+ // 0 == end, 1 == line, 2 == icon, 3 == begin
+ int component = selected_object % ::ControlLine::OBJ_COUNT;
+ Coord mouse = provider->posImage + provider->deltaImage;
+ Coord delta = provider->deltaImage - drag_delta;
+ int ih, iw;
+ provider->getImageSize(iw, ih);
+
+ switch (component) {
+ case (0): // end
+ control_line.end->center = mouse;
+ control_line.end->center.clip(iw, ih);
+ control_line.line->end = control_line.end->center;
+ control_line.end->state = Geometry::DRAGGED;
+ break;
+
+ case (1): { // line
+ // Constrain delta so the end stays above the image.
+ Coord new_delta = control_line.end->center + delta;
+ new_delta.clip(iw, ih);
+ new_delta -= control_line.end->center;
+ // Constrain delta so the beginning stays above the image.
+ new_delta += control_line.begin->center;
+ new_delta.clip(iw, ih);
+ new_delta -= control_line.begin->center;
+ // Move all objects in the control line.
+ control_line.end->center += new_delta;
+ control_line.begin->center += new_delta;
+ control_line.line->end = control_line.end->center;
+ control_line.line->begin = control_line.begin->center;
+ drag_delta += new_delta;
+ control_line.line->state = Geometry::DRAGGED;
+ break;
+ }
+
+ case (3): // begin
+ control_line.begin->center = mouse;
+ control_line.begin->center.clip(iw, ih);
+ control_line.line->begin = control_line.begin->center;
+ control_line.begin->state = Geometry::DRAGGED;
+ break;
+ }
+
+ control_line.icon_h->position.x = (control_line.begin->center.x +
+ control_line.end->center.x) / 2;
+ control_line.icon_h->position.y = (control_line.begin->center.y +
+ control_line.end->center.y) / 2;
+ control_line.icon_v->position.x = control_line.icon_h->position.x;
+ control_line.icon_v->position.y = control_line.icon_h->position.y;
+
+ if (drawing_line) {
+ autoSetLineType(selected_object);
+ }
+
+ return false;
+}
+
+bool ControlLineManager::getEdited(void) const
+{
+ return edited;
+}
+
+CursorShape ControlLineManager::getCursor(int objectID) const
+{
+ return cursor;
+}
+
+bool ControlLineManager::mouseOver(int modifierKey)
+{
+ EditDataProvider* provider = getEditProvider();
+
+ if (!provider) {
+ return false;
+ }
+
+ int cur_obj = provider->getObject();
+
+ if (cur_obj == 0) { // Canvas
+ if (draw_mode && modifierKey & GDK_CONTROL_MASK) {
+ cursor = CSCrosshair;
+ } else {
+ cursor = CSHandOpen;
+ }
+ } else if (cur_obj < 0) { // Nothing
+ cursor = CSArrow;
+ } else if (cur_obj % ::ControlLine::OBJ_COUNT == 2) { // Icon
+ visibleGeometry[cur_obj - 1]->state = Geometry::PRELIGHT;
+ cursor = CSArrow;
+ } else { // Object
+ visibleGeometry[cur_obj - 1]->state = Geometry::PRELIGHT;
+ cursor = CSMove2D;
+ }
+
+ if (prev_obj != cur_obj && prev_obj > 0) {
+ visibleGeometry[prev_obj - 1]->state = Geometry::NORMAL;
+ }
+
+ prev_obj = cur_obj;
+
+ return true;
+}
+
+void ControlLineManager::switchOffEditMode(void)
+{
+ if (callbacks) {
+ callbacks->switchOffEditMode();
+ }
+}
+
+void ControlLineManager::setEdited(bool edited)
+{
+ this->edited = edited;
+}
+
+void ControlLineManager::setEditProvider(EditDataProvider* provider)
+{
+ EditSubscriber::setEditProvider(provider);
+}
+
+void ControlLineManager::setLines(const std::vector&
+ lines)
+{
+ removeAll();
+
+ for (auto&& line : lines) {
+ Coord start(line.x1, line.y1);
+ Coord end(line.x2, line.y2);
+ addLine(start, end, line.type);
+ }
+}
+
+void ControlLineManager::addLine(Coord begin, Coord end,
+ rtengine::ControlLine::Type type)
+{
+ constexpr int line_width = 2;
+ constexpr int handle_radius = 6;
+ std::unique_ptr line;
+ std::shared_ptr icon_h, icon_v;
+ std::unique_ptr begin_c, end_c;
+
+ line = std::unique_ptr(new Line());
+ line->datum = Geometry::IMAGE;
+ line->innerLineWidth = line_width;
+ line->begin = begin;
+ line->end = end;
+
+ const Cairo::RefPtr null_surface =
+ Cairo::RefPtr(nullptr);
+
+ icon_h = std::make_shared