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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence Lee + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + + + 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 @@ - - + inkscape:version="1.0 (4035a4fb49, 2020-05-01)" + sodipodi:docname="histogram-type-histogram-small.svg"> + inkscape:snap-bbox-midpoints="false" + inkscape:document-rotation="0"> image/svg+xml - + - Maciej Dworak + Lawrence Lee @@ -100,40 +99,24 @@ inkscape:groupmode="layer" inkscape:label="Layer 1" transform="translate(0,-8)"> + + y="10" + x="2" + height="12" + width="12" + id="rect1467" + style="opacity:0.3;fill:#2a7fff;stroke-linecap:square;fill-opacity:1" /> - - - + style="opacity:1;fill:none;fill-opacity:0.3;stroke:#000000;stroke-width:0.999999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect849" + width="13" + height="13.000001" + x="1.5" + y="9.5" /> 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence Lee + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence Lee + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence Lee + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence Lee + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + 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(line_icon_h, null_surface, + line_icon_h_prelight, + null_surface, null_surface, + Geometry::DP_CENTERCENTER); + icon_h->position = Coord((begin.x + end.x) / 2, (begin.y + end.y) / 2); + + icon_v = std::make_shared(line_icon_v, null_surface, + line_icon_v_prelight, + null_surface, null_surface, + Geometry::DP_CENTERCENTER); + icon_v->position = Coord((begin.x + end.x) / 2, (begin.y + end.y) / 2); + + begin_c = std::unique_ptr(new Circle()); + begin_c->datum = Geometry::IMAGE; + begin_c->filled = true; + begin_c->radius = handle_radius; + begin_c->center = begin; + + end_c = std::unique_ptr(new Circle()); + end_c->datum = Geometry::IMAGE; + end_c->filled = true; + end_c->radius = handle_radius; + end_c->center = end; + + std::unique_ptr<::ControlLine> control_line(new ::ControlLine()); + control_line->begin = std::move(begin_c); + control_line->end = std::move(end_c); + control_line->icon_h = icon_h; + control_line->icon_v = icon_v; + + if (type == rtengine::ControlLine::HORIZONTAL) { + control_line->icon = icon_h; + } else { + control_line->icon = icon_v; + } + + control_line->line = std::move(line); + control_line->type = type; + + EditSubscriber::visibleGeometry.push_back(control_line->line.get()); + EditSubscriber::visibleGeometry.push_back(control_line->icon.get()); + EditSubscriber::visibleGeometry.push_back(control_line->begin.get()); + EditSubscriber::visibleGeometry.push_back(control_line->end.get()); + + EditSubscriber::mouseOverGeometry.push_back(control_line->line.get()); + EditSubscriber::mouseOverGeometry.push_back(control_line->icon.get()); + EditSubscriber::mouseOverGeometry.push_back(control_line->begin.get()); + EditSubscriber::mouseOverGeometry.push_back(control_line->end.get()); + + control_lines.push_back(std::move(control_line)); +} + +void ControlLineManager::autoSetLineType(int object_id) +{ + int line_id = (object_id - 1) / ::ControlLine::OBJ_COUNT; + ::ControlLine& line = *control_lines[line_id]; + + int dx = line.begin->center.x - line.end->center.x; + int dy = line.begin->center.y - line.end->center.y; + + if (dx < 0) { + dx = -dx; + } + + if (dy < 0) { + dy = -dy; + } + + rtengine::ControlLine::Type type; + std::shared_ptr icon; + + if (dx > dy) { // More horizontal than vertical. + type = rtengine::ControlLine::HORIZONTAL; + icon = line.icon_h; + } else { + type = rtengine::ControlLine::VERTICAL; + icon = line.icon_v; + } + + if (type != line.type) { // Need to update line type. + line.type = type; + line.icon = icon; + visibleGeometry[line_id * ::ControlLine::OBJ_COUNT + 1] = + line.icon.get(); + } +} + +void ControlLineManager::removeAll(void) +{ + visibleGeometry.clear(); + mouseOverGeometry.erase(mouseOverGeometry.begin() + 1, + mouseOverGeometry.end()); + control_lines.clear(); + prev_obj = -1; + selected_object = -1; + edited = true; + callbacks->lineChanged(); +} + +void ControlLineManager::removeLine(size_t line_id) +{ + if (line_id >= control_lines.size()) { + return; + } + + visibleGeometry.erase( + visibleGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id, + visibleGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id + + ::ControlLine::OBJ_COUNT + ); + mouseOverGeometry.erase( + mouseOverGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id + 1, + mouseOverGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id + + ::ControlLine::OBJ_COUNT + 1 + ); + control_lines.erase(control_lines.begin() + line_id); + + edited = true; + callbacks->lineChanged(); +} + +void ControlLineManager::toControlLines(std::vector& + converted) const +{ + converted.clear(); + converted.resize(control_lines.size()); + + for (unsigned int i = 0; i < control_lines.size(); i++) { + converted[i].x1 = control_lines[i]->begin->center.x; + converted[i].y1 = control_lines[i]->begin->center.y; + converted[i].x2 = control_lines[i]->end->center.x; + converted[i].y2 = control_lines[i]->end->center.y; + converted[i].type = control_lines[i]->type; + } +} diff --git a/rtgui/controllines.h b/rtgui/controllines.h new file mode 100644 index 000000000..0ff449092 --- /dev/null +++ b/rtgui/controllines.h @@ -0,0 +1,115 @@ +/* + * 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 . + */ +#pragma once + +#include + +#include "editcallbacks.h" +#include "../rtengine/perspectivecorrection.h" + +class Circle; +class Line; +class OPIcon; +class Rectangle; +class RTSurface; + +struct ControlLine { + static constexpr int OBJ_COUNT = 4; + std::unique_ptr line; + std::shared_ptr icon; + std::shared_ptr icon_h, icon_v; + std::unique_ptr begin, end; + rtengine::ControlLine::Type type; + + ~ControlLine(); +}; + +class ControlLineManager: EditSubscriber +{ + +protected: + /** Hidden object for capturing mouse events. */ + std::unique_ptr canvas_area; + rtengine::Coord drag_delta; + std::vector> control_lines; + CursorShape cursor; + bool draw_mode; + bool drawing_line; + bool edited; + Cairo::RefPtr line_icon_h, line_icon_v; + Cairo::RefPtr line_icon_h_prelight, line_icon_v_prelight; + int prev_obj; + int selected_object; + + void addLine(rtengine::Coord begin, rtengine::Coord end, + rtengine::ControlLine::Type type = rtengine::ControlLine::VERTICAL); + /** + * Set the line type of the line containing the object according to the + * line's angle. + * + * If the line is within 45 degrees of a perfectly vertical + * line, inclusive, the line type is set to vertical. Otherwise, horizontal. + */ + void autoSetLineType(int object_id); + void removeLine(size_t line_id); + +public: + class Callbacks + { + public: + virtual ~Callbacks() {}; + /** Called when a line changed (added, removed, moved, etc.). */ + virtual void lineChanged(void) {}; + /** Called when the EditSubscriber's switchOffEditMode is called. */ + virtual void switchOffEditMode(void) {}; + }; + + /** Callbacks to invoke. */ + std::shared_ptr callbacks; + + ControlLineManager(); + ~ControlLineManager(); + + bool getEdited(void) const; + void removeAll(void); + /** Sets whether or not the lines are visible and interact-able. */ + void setActive(bool active); + /** Set whether or not lines can be drawn and deleted. */ + void setDrawMode(bool draw); + void setEdited(bool edited); + void setEditProvider(EditDataProvider* provider); + void setLines(const std::vector& lines); + /** Returns the number of lines. */ + size_t size(void) const; + /** + * Allocates a new array and populates it with copies of the control lines. + */ + void toControlLines(std::vector& converted) const; + + // EditSubscriber overrides + bool button1Pressed(int modifierKey) override; + bool button1Released(void) override; + bool button3Pressed(int modifierKey) override; + bool pick1(bool picked) override; + bool pick3(bool picked) override; + bool drag1(int modifierKey) override; + CursorShape getCursor(int objectID) const override; + bool mouseOver(int modifierKey) override; + void switchOffEditMode(void) override; +}; diff --git a/rtgui/controlspotpanel.cc b/rtgui/controlspotpanel.cc index 0b66eb986..9ed4c95ee 100644 --- a/rtgui/controlspotpanel.cc +++ b/rtgui/controlspotpanel.cc @@ -77,8 +77,9 @@ ControlSpotPanel::ControlSpotPanel(): colorde_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_COLORDE"), -15, 15, 2, 5, Gtk::manage(new RTImage("circle-blue-yellow-small.png")), Gtk::manage(new RTImage("circle-gray-green-small.png"))))), colorscope_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_COLORSCOPE"), 0., 100.0, 1., 30.))), scopemask_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCOPEMASK"), 0, 100, 1, 60))), - lumask_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LUMASK"), 0, 30, 1, 10))), + lumask_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LUMASK"), -50, 30, 1, 10, Gtk::manage(new RTImage("circle-yellow-small.png")), Gtk::manage(new RTImage("circle-gray-small.png")) ))), + hishow_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_PREVSHOW")))), activ_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ACTIVSPOT")))), avoid_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_AVOID")))), blwh_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_BLWH")))), @@ -108,6 +109,7 @@ ControlSpotPanel::ControlSpotPanel(): maskPrevActive(false) { const bool showtooltip = options.showtooltip; + pack_start(*hishow_); Gtk::HBox* const ctboxprevmethod = Gtk::manage(new Gtk::HBox()); prevMethod_->append(M("TP_LOCALLAB_PREVHIDE")); @@ -117,7 +119,7 @@ ControlSpotPanel::ControlSpotPanel(): sigc::mem_fun( *this, &ControlSpotPanel::prevMethodChanged)); - ctboxprevmethod->pack_start(*prevMethod_); +// ctboxprevmethod->pack_start(*prevMethod_); pack_start(*ctboxprevmethod); @@ -380,6 +382,9 @@ ControlSpotPanel::ControlSpotPanel(): pack_start(*artifBox2); ToolParamBlock* const specCaseBox = Gtk::manage(new ToolParamBlock()); + hishowconn_ = hishow_->signal_toggled().connect( + sigc::mem_fun(*this, &ControlSpotPanel::hishowChanged)); + activConn_ = activ_->signal_toggled().connect( sigc::mem_fun(*this, &ControlSpotPanel::activChanged)); @@ -819,6 +824,7 @@ void ControlSpotPanel::load_ControlSpot_param() balanh_->setValue((double)row[spots_.balanh]); colorde_->setValue((double)row[spots_.colorde]); colorscope_->setValue((double)row[spots_.colorscope]); + hishow_->set_active(row[spots_.hishow]); activ_->set_active(row[spots_.activ]); avoid_->set_active(row[spots_.avoid]); blwh_->set_active(row[spots_.blwh]); @@ -899,7 +905,7 @@ void ControlSpotPanel::prevMethodChanged() Gtk::TreeModel::Row row = *iter; row[spots_.prevMethod] = prevMethod_->get_active_row_number(); - +/* // Update Control Spot GUI according to spotMethod_ combobox state (to be compliant with updateParamVisibility function) if (multiImage && prevMethod_->get_active_text() == M("GENERAL_UNCHANGED")) { expTransGrad_->show(); @@ -925,10 +931,10 @@ void ControlSpotPanel::prevMethodChanged() circrad_->show(); ctboxshape->show(); } - +*/ // Raise event if (listener) { - listener->panelChanged(EvLocallabSpotprevMethod, prevMethod_->get_active_text()); +// listener->panelChanged(EvLocallabSpotprevMethod, prevMethod_->get_active_text()); } } @@ -1179,7 +1185,7 @@ void ControlSpotPanel::updateParamVisibility() excluFrame->show(); } - +/* if (multiImage && prevMethod_->get_active_text() == M("GENERAL_UNCHANGED")) { expTransGrad_->show(); expShapeDetect_->show(); @@ -1188,6 +1194,8 @@ void ControlSpotPanel::updateParamVisibility() circrad_->show(); ctboxshape->show(); } else if (prevMethod_->get_active_row_number() == 0) { // Normal case + */ + if (!hishow_->get_active()) { // Normal case expTransGrad_->hide(); expShapeDetect_->hide(); expSpecCases_->hide(); @@ -1432,6 +1440,50 @@ void ControlSpotPanel::adjusterChanged(Adjuster* a, double newval) } } +void ControlSpotPanel::hishowChanged() +{ + // printf("avoidChanged\n"); + + // Get selected control spot + const auto s = treeview_->get_selection(); + + if (!s->count_selected_rows()) { + return; + } + + const auto iter = s->get_selected(); + Gtk::TreeModel::Row row = *iter; + row[spots_.hishow] = hishow_->get_active(); + + + + if (!hishow_->get_active()) { // Normal case + expTransGrad_->hide(); + expShapeDetect_->hide(); + expSpecCases_->hide(); + expMaskMerge_->hide(); + circrad_->hide(); + ctboxshape->hide(); + shapeMethod_->set_active(0); + + } else { // Excluding case + expTransGrad_->show(); + expShapeDetect_->show(); + expSpecCases_->show(); + expMaskMerge_->show(); + circrad_->show(); + ctboxshape->show(); + } + + // Raise event + if (listener) { + if (hishow_->get_active()) { + listener->panelChanged(Evlocallabhishow, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(Evlocallabhishow, M("GENERAL_DISABLED")); + } + } +} @@ -1677,6 +1729,7 @@ void ControlSpotPanel::disableParamlistener(bool cond) balanh_->block(cond); colorde_->block(cond); colorscope_->block(cond); + hishowconn_.block(cond); activConn_.block(cond); avoidConn_.block(cond); blwhConn_.block(cond); @@ -1720,6 +1773,7 @@ void ControlSpotPanel::setParamEditable(bool cond) balanh_->set_sensitive(cond); colorde_->set_sensitive(cond); colorscope_->set_sensitive(cond); + hishow_->set_sensitive(cond); activ_->set_sensitive(cond); avoid_->set_sensitive(cond); blwh_->set_sensitive(cond); @@ -2401,6 +2455,7 @@ ControlSpotPanel::SpotRow* ControlSpotPanel::getSpot(const int index) r->transitgrad = row[spots_.transitgrad]; r->scopemask = row[spots_.scopemask]; r->lumask = row[spots_.lumask]; + r->hishow = row[spots_.hishow]; r->activ = row[spots_.activ]; r->avoid = row[spots_.avoid]; r->blwh = row[spots_.blwh]; @@ -2531,6 +2586,7 @@ void ControlSpotPanel::addControlSpot(SpotRow* newSpot) row[spots_.balanh] = newSpot->balanh; row[spots_.colorde] = newSpot->colorde; row[spots_.colorscope] = newSpot->colorscope; + row[spots_.hishow] = newSpot->hishow; row[spots_.activ] = newSpot->activ; row[spots_.avoid] = newSpot->avoid; row[spots_.blwh] = newSpot->blwh; @@ -2645,6 +2701,7 @@ ControlSpotPanel::ControlSpots::ControlSpots() add(balanh); add(colorde); add(colorscope); + add(hishow); add(activ); add(avoid); add(blwh); diff --git a/rtgui/controlspotpanel.h b/rtgui/controlspotpanel.h index 720bdf0c1..f8ef41dc0 100644 --- a/rtgui/controlspotpanel.h +++ b/rtgui/controlspotpanel.h @@ -75,6 +75,7 @@ public: double balanh; double colorde; double colorscope; + bool hishow; bool activ; bool avoid; bool blwh; @@ -245,6 +246,7 @@ private: void adjusterChanged(Adjuster* a, double newval) override; + void hishowChanged(); void activChanged(); void avoidChanged(); void blwhChanged(); @@ -305,6 +307,7 @@ private: Gtk::TreeModelColumn balanh; Gtk::TreeModelColumn colorde; Gtk::TreeModelColumn colorscope; + Gtk::TreeModelColumn hishow; Gtk::TreeModelColumn activ; Gtk::TreeModelColumn avoid; Gtk::TreeModelColumn blwh; @@ -355,6 +358,7 @@ private: Gtk::Button* const button_visibility_; sigc::connection buttonvisibilityconn_; + MyComboBoxText* const prevMethod_; sigc::connection prevMethodconn_; MyComboBoxText* const shape_; @@ -393,6 +397,8 @@ private: Adjuster* const scopemask_; Adjuster* const lumask_; + Gtk::CheckButton* const hishow_; + sigc::connection hishowconn_; Gtk::CheckButton* const activ_; sigc::connection activConn_; Gtk::CheckButton* const avoid_; diff --git a/rtgui/crop.cc b/rtgui/crop.cc index 48d1e09af..961f1908b 100644 --- a/rtgui/crop.cc +++ b/rtgui/crop.cc @@ -82,6 +82,7 @@ public: {"17:22", 17.0 / 22.0}, // L1.294..., P0.772... {"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777... {"64:27", 64.0 / 27.0}, // L2.370..., P0.421... + {"13:18", 13.0 / 18.0}, // L1.384..., P0.722... } { } diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index d87876cec..1ed9211a1 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -125,13 +125,13 @@ void CropWindow::initZoomSteps() char lbl[64]; for (int s = 100; s >= 11; --s) { float z = 10.f / s; - sprintf(lbl, "% 2d%%", int(z * 100)); + snprintf(lbl, sizeof(lbl), "% 2d%%", int(z * 100)); bool is_major = (s == s/10 * 10); zoomSteps.push_back(ZoomStep(lbl, z, s, is_major)); } zoom11index = zoomSteps.size(); for (int s = 1; s <= 8; ++s) { - sprintf(lbl, "%d00%%", s); + snprintf(lbl, sizeof(lbl), "%d00%%", s); zoomSteps.push_back(ZoomStep(lbl, s, s * 1000, true)); } zoomSteps.push_back(ZoomStep("1600%", 16, 16000, true)); @@ -414,7 +414,8 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_y = 0; needRedraw = true; } - } else if (iarea->getToolMode () == TMHand + } else if ((iarea->getToolMode () == TMHand + || iarea->getToolMode() == TMPerspective) && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) @@ -429,6 +430,8 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) state = SEditPick1; pickedObject = iarea->getObject(); pickModifierKey = bstate; + } else if (iarea->getToolMode() == TMPerspective) { + state = SCropImgMove; } press_x = x; press_y = y; @@ -592,7 +595,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) } } } else if (button == 3) { - if (iarea->getToolMode () == TMHand) { + if (iarea->getToolMode () == TMHand || iarea->getToolMode() == TMPerspective) { EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { needRedraw = editSubscriber->button3Pressed(bstate); @@ -764,7 +767,10 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) iarea->setObject(ObjectMOBuffer::getObjectID(cropPos)); - bool elemPicked = iarea->getObject() == pickedObject && bstate == pickModifierKey; + int buttonMask = ((state == SEditPick1) ? GDK_BUTTON1_MASK : 0) + | ((state == SEditPick2) ? GDK_BUTTON2_MASK : 0) + | ((state == SEditPick3) ? GDK_BUTTON3_MASK : 0); + bool elemPicked = iarea->getObject() == pickedObject && bstate == (pickModifierKey | buttonMask); if (state == SEditPick1) { needRedraw = editSubscriber->pick1 (elemPicked); diff --git a/rtgui/delayed.h b/rtgui/delayed.h new file mode 100644 index 000000000..b57d7300b --- /dev/null +++ b/rtgui/delayed.h @@ -0,0 +1,240 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (C) 2020 Flössie + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#include "../rtengine/noncopyable.h" + +namespace delayed_helper +{ + + // C++14 + + // See https://gist.github.com/ntessore/dc17769676fb3c6daa1f + template + struct index_sequence + { + }; + + template + struct make_index_sequence : + make_index_sequence + { + }; + + template + struct make_index_sequence<0, Is...> : + index_sequence + { + }; + + // C++17 + + // See https://aherrmann.github.io/programming/2016/02/28/unpacking-tuples-in-cpp14/ + template + void apply_impl(F f, T t, index_sequence) + { + f(std::get(t)...); + } + + template + void apply(F f, T t) + { + apply_impl(f, t, make_index_sequence{}>{}); + } + +} + +template +class DelayedCall final : + public rtengine::NonCopyable +{ +public: + DelayedCall(std::function _function, unsigned int _min_delay_ms, unsigned int _max_delay_ms = 0) : + function(_function), + min_delay_ms(_min_delay_ms), + max_delay_ms(_max_delay_ms) + { + } + + DelayedCall(unsigned int _min_delay_ms, unsigned int _max_delay_ms = 0) : + DelayedCall({}, _min_delay_ms, _max_delay_ms) + { + } + + void setFunction(std::function function) + { + this->function = function; + } + + void operator ()(Ts... ts) + { + if (!function) { + return; + } + + if (!min_delay_ms) { + function(ts...); + return; + } + + params = std::make_tuple(ts...); + + min_timeout.disconnect(); + min_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &DelayedCall::onMinTimeout), min_delay_ms); + + if (max_delay_ms && !max_timeout.connected()) { + max_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &DelayedCall::onMaxTimeout), max_delay_ms); + } + } + + void cancel() + { + min_timeout.disconnect(); + max_timeout.disconnect(); + } + +private: + bool onMinTimeout() + { + max_timeout.disconnect(); + if (function) { + delayed_helper::apply(function, params); + } + return false; + } + + bool onMaxTimeout() + { + min_timeout.disconnect(); + if (function) { + delayed_helper::apply(function, params); + } + return false; + } + + std::function function; + + unsigned int min_delay_ms; + unsigned int max_delay_ms; + + sigc::connection min_timeout; + sigc::connection max_timeout; + + std::tuple params; +}; + +template +class DelayedConnection final : + public rtengine::NonCopyable +{ +public: + DelayedConnection(unsigned int _min_delay_ms, unsigned int _max_delay_ms = 0) : + min_delay_ms(_min_delay_ms), + max_delay_ms(_max_delay_ms) + { + } + + void connect(Glib::SignalProxy signal, const sigc::slot& slot, const sigc::slot& immediate_slot = {}) + { + this->slot = slot; + this->immediate_slot = immediate_slot; + this->signal = signal.connect(sigc::mem_fun(*this, &DelayedConnection::onSignal)); + } + + void block(bool value = true) + { + signal.block(value); + } + + void unblock() + { + signal.unblock(); + } + + void cancel() + { + min_timeout.disconnect(); + max_timeout.disconnect(); + } + + void setDelay(unsigned int min_delay_ms, unsigned int max_delay_ms = 0) + { + this->min_delay_ms = min_delay_ms; + this->max_delay_ms = max_delay_ms; + + min_timeout.disconnect(); + max_timeout.disconnect(); + } + +private: + void onSignal(Ts... ts) + { + if (immediate_slot) { + immediate_slot(ts...); + } + + if (!min_delay_ms) { + slot(ts...); + return; + } + + params = std::make_tuple(ts...); + + min_timeout.disconnect(); + min_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &DelayedConnection::onMinTimeout), min_delay_ms); + + if (max_delay_ms && !max_timeout.connected()) { + max_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &DelayedConnection::onMaxTimeout), max_delay_ms); + } + } + + bool onMinTimeout() + { + max_timeout.disconnect(); + delayed_helper::apply(slot, params); + return false; + } + + bool onMaxTimeout() + { + min_timeout.disconnect(); + delayed_helper::apply(slot, params); + return false; + } + + unsigned int min_delay_ms; + unsigned int max_delay_ms; + + sigc::connection signal; + sigc::connection min_timeout; + sigc::connection max_timeout; + + sigc::slot slot; + sigc::slot immediate_slot; + + std::tuple params; +}; diff --git a/rtgui/editcallbacks.h b/rtgui/editcallbacks.h index 524ec1622..d81e84806 100644 --- a/rtgui/editcallbacks.h +++ b/rtgui/editcallbacks.h @@ -129,19 +129,19 @@ public: @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. @return true if the preview has to be redrawn, false otherwise */ - bool pick1 (bool picked); + virtual bool pick1 (bool picked); /** @brief Triggered when the user is releasing mouse button 2 while in action==ES_ACTION_PICKING mode @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. @return true if the preview has to be redrawn, false otherwise */ - bool pick2 (bool picked); + virtual bool pick2 (bool picked); /** @brief Triggered when the user is releasing mouse button 3 while in action==ES_ACTION_PICKING mode @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. @return true if the preview has to be redrawn, false otherwise */ - bool pick3 (bool picked); + virtual bool pick3 (bool picked); /** @brief Get the geometry to be shown to the user */ const std::vector& getVisibleGeometry (); diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 669dd491a..34d677206 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -21,6 +21,7 @@ #include +#include "../rtengine/array2D.h" #include "../rtengine/imagesource.h" #include "../rtengine/iccstore.h" #include "batchqueue.h" @@ -47,6 +48,8 @@ using namespace rtengine::procparams; +using ScopeType = Options::ScopeType; + namespace { @@ -470,7 +473,8 @@ EditorPanel::EditorPanel (FilePanel* filePanel) iBeforeLockON (nullptr), iBeforeLockOFF (nullptr), previewHandler (nullptr), beforePreviewHandler (nullptr), beforeIarea (nullptr), beforeBox (nullptr), afterBox (nullptr), beforeLabel (nullptr), afterLabel (nullptr), beforeHeaderBox (nullptr), afterHeaderBox (nullptr), parent (nullptr), parentWindow (nullptr), openThm (nullptr), - selectedFrame(0), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false) + selectedFrame(0), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false), + histogram_observable(nullptr), histogram_scope_type(ScopeType::NONE) { epih = new EditorPanelIdleHelper; @@ -1795,7 +1799,7 @@ bool EditorPanel::idle_saveImage (ProgressConnector *pc, bool EditorPanel::idle_imageSaved (ProgressConnector *pc, rtengine::IImagefloat* img, Glib::ustring fname, SaveFormat sf, rtengine::procparams::ProcParams &pparams) { - img->free (); + delete img; if (! pc->returnValue() ) { openThm->imageDeveloped (); @@ -1995,7 +1999,7 @@ bool EditorPanel::saveImmediately (const Glib::ustring &filename, const SaveForm err = 1; } - img->free(); + delete img; return !err; } @@ -2057,7 +2061,7 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *p } if (tries == 1000) { - img->free (); + delete img; return false; } @@ -2078,7 +2082,7 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *p bool EditorPanel::idle_sentToGimp (ProgressConnector *pc, rtengine::IImagefloat* img, Glib::ustring filename) { - img->free (); + delete img; int errore = pc->returnValue(); setProgressState(false); delete pc; @@ -2245,16 +2249,94 @@ void EditorPanel::histogramChanged( 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 ) { if (histogramPanel) { - histogramPanel->histogramChanged(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw); + histogramPanel->histogramChanged(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw, vectorscopeScale, vectorscopeHC, vectorscopeHS, waveformScale, waveformRed, waveformGreen, waveformBlue, waveformLuma); } tpc->updateCurveBackgroundHistogram(histToneCurve, histLCurve, histCCurve, histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma, histLRETI); } +void EditorPanel::setObservable(rtengine::HistogramObservable* observable) +{ + histogram_observable = observable; +} + +bool EditorPanel::updateHistogram(void) const +{ + return histogram_scope_type == ScopeType::HISTOGRAM + || histogram_scope_type == ScopeType::NONE; +} + +bool EditorPanel::updateHistogramRaw(void) const +{ + return histogram_scope_type == ScopeType::HISTOGRAM_RAW + || histogram_scope_type == ScopeType::NONE; +} + +bool EditorPanel::updateVectorscopeHC(void) const +{ + return + histogram_scope_type == ScopeType::VECTORSCOPE_HC + || histogram_scope_type == ScopeType::NONE; +} + +bool EditorPanel::updateVectorscopeHS(void) const +{ + return + histogram_scope_type == ScopeType::VECTORSCOPE_HS + || histogram_scope_type == ScopeType::NONE; +} + +bool EditorPanel::updateWaveform(void) const +{ + return histogram_scope_type == ScopeType::WAVEFORM + || histogram_scope_type == ScopeType::PARADE + || histogram_scope_type == ScopeType::NONE; +} + +void EditorPanel::scopeTypeChanged(ScopeType new_type) +{ + histogram_scope_type = new_type; + + if (!histogram_observable) { + return; + } + + // Make sure the new scope is updated since we only actively update the + // current scope. + switch (new_type) { + case ScopeType::HISTOGRAM: + histogram_observable->requestUpdateHistogram(); + break; + case ScopeType::HISTOGRAM_RAW: + histogram_observable->requestUpdateHistogramRaw(); + break; + case ScopeType::VECTORSCOPE_HC: + histogram_observable->requestUpdateVectorscopeHC(); + break; + case ScopeType::VECTORSCOPE_HS: + histogram_observable->requestUpdateVectorscopeHS(); + break; + case ScopeType::PARADE: + case ScopeType::WAVEFORM: + histogram_observable->requestUpdateWaveform(); + break; + case ScopeType::NONE: + break; + } +} + bool EditorPanel::CheckSidePanelsVisibility() { if (tbTopPanel_1) { @@ -2371,6 +2453,10 @@ void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition) break; } + if (histogramPanel) { + histogramPanel->setPanelListener(this); + } + iareapanel->imageArea->setPointerMotionHListener (histogramPanel); } diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 826793507..a277ffd3a 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -32,6 +32,12 @@ #include "../rtengine/noncopyable.h" #include "../rtengine/rtengine.h" +namespace rtengine +{ +template +class array2D; +} + class BatchQueueEntry; class EditorPanel; class FilePanel; @@ -55,6 +61,7 @@ class EditorPanel final : public ThumbnailListener, public HistoryBeforeLineListener, public rtengine::HistogramListener, + public HistogramPanelListener, public rtengine::NonCopyable { public: @@ -126,8 +133,25 @@ 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 ) override; + void setObservable(rtengine::HistogramObservable* observable) override; + bool updateHistogram(void) const override; + bool updateHistogramRaw(void) const override; + bool updateVectorscopeHC(void) const override; + bool updateVectorscopeHS(void) const override; + bool updateWaveform(void) const override; + + // HistogramPanelListener + void scopeTypeChanged(Options::ScopeType new_type) override; // event handlers void info_toggled (); @@ -260,4 +284,7 @@ private: bool isProcessing; IdleRegister idle_register; + + rtengine::HistogramObservable* histogram_observable; + Options::ScopeType histogram_scope_type; }; diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 341d0f303..3f6bbacb5 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -209,6 +209,9 @@ void ExifPanel::setImageData (const FramesMetaData* id) Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable) { + if (!value.validate()) { + value = "???"; + } Gtk::TreeModel::Row row = * (exifTreeModel->append (root)); row[exifColumns.action] = action; diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index 3129e93e2..432296f38 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -116,9 +116,12 @@ void FileBrowserEntry::refreshQuickThumbnailImage () void FileBrowserEntry::calcThumbnailSize () { - if (thumbnail) { - prew = thumbnail->getThumbnailWidth(preh); + int ow = prew, oh = preh; + thumbnail->getThumbnailSize(prew, preh); + if (ow != prew || oh != preh || preview.size() != static_cast(prew * preh * 3)) { + preview.clear(); + } } } @@ -230,7 +233,7 @@ void FileBrowserEntry::updateImage(rtengine::IImage8* img, double scale, const r --feih->pending; } - img->free(); + delete img; return false; } @@ -255,28 +258,22 @@ void FileBrowserEntry::_updateImage(rtengine::IImage8* img, double s, const rten bool rotated = false; if (preh == img->getHeight()) { - const bool resize = !preview || prew != img->getWidth(); prew = img->getWidth (); // Check if image has been rotated since last time - rotated = preview && newLandscape != landscape; + rotated = !preview.empty() && newLandscape != landscape; - if (resize) { - if (preview) { - delete [] preview; - } - preview = new guint8 [prew * preh * 3]; - } - memcpy(preview, img->getData(), prew * preh * 3); + preview.resize(prew * preh * 3); + std::copy(img->getData(), img->getData() + preview.size(), preview.begin()); { - GThreadLock lock; - updateBackBuffer (); + GThreadLock lock; + updateBackBuffer (); } } landscape = newLandscape; - img->free(); + delete img; if (parent) { if (rotated) { @@ -601,7 +598,7 @@ bool FileBrowserEntry::onArea (CursorArea a, int x, int y) { MYREADERLOCK(l, lockRW); - if (!drawable || !preview) { + if (!drawable || preview.empty()) { return false; } diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 34d6c8aa3..08bcc276b 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -1228,8 +1228,9 @@ void FileCatalog::developRequested(const std::vector& tbe, bo rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType() == FT_Raw, params, fastmode && options.fastexport_use_fast_pipeline); - const int ph = BatchQueue::calcMaxThumbnailHeight(); - const int pw = th->getThumbnailWidth(ph); + int pw; + int ph = BatchQueue::calcMaxThumbnailHeight(); + th->getThumbnailSize (pw, ph); // processThumbImage is the processing intensive part, but adding to queue must be ordered //#pragma omp ordered diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 1b105a3ec..d70c2a067 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -36,9 +36,7 @@ Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring adj->setAdjusterListener(listener); adj->setLogScale(6, 1, true); - if (adj->delay < options.adjusterMaxDelay) { - adj->delay = options.adjusterMaxDelay; - } + adj->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); adj->show(); return adj; diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc index 7433fd4de..69d14c463 100644 --- a/rtgui/flatfield.cc +++ b/rtgui/flatfield.cc @@ -47,9 +47,7 @@ FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_L flatFieldBlurRadius = Gtk::manage(new Adjuster (M("TP_FLATFIELD_BLURRADIUS"), 0, 200, 2, 32)); flatFieldBlurRadius->setAdjusterListener (this); - if (flatFieldBlurRadius->delay < options.adjusterMaxDelay) { - flatFieldBlurRadius->delay = options.adjusterMaxDelay; - } + flatFieldBlurRadius->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); flatFieldBlurRadius->show(); @@ -67,9 +65,7 @@ FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_L flatFieldClipControl->setAdjusterListener(this); flatFieldClipControl->addAutoButton(""); - if (flatFieldClipControl->delay < options.adjusterMaxDelay) { - flatFieldClipControl->delay = options.adjusterMaxDelay; - } + flatFieldClipControl->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); flatFieldClipControl->show(); flatFieldClipControl->set_tooltip_markup (M("TP_FLATFIELD_CLIPCONTROL_TOOLTIP")); diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index b1c0b62df..83db36cb4 100644 --- a/rtgui/histogrampanel.cc +++ b/rtgui/histogrampanel.cc @@ -22,17 +22,51 @@ #include "options.h" #include #include +#include "../rtengine/array2D.h" #include "../rtengine/LUT.h" #include "rtimage.h" #include "../rtengine/color.h" using namespace rtengine; +constexpr float HistogramArea::MAX_BRIGHT; +constexpr float HistogramArea::MIN_BRIGHT; + +using ScopeType = Options::ScopeType; // // // HistogramPanel -HistogramPanel::HistogramPanel () +HistogramPanel::HistogramPanel () : + pointer_moved_delayed_call( + [this](bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int r, int g, int b) + { + bool update_hist_area; + + if (!validPos) { + // do something to un-show vertical bars + if (histogramRGBArea) { + histogramRGBArea->updateBackBuffer(-1, -1, -1); + } + update_hist_area = histogramArea->updatePointer(-1, -1, -1); + } else { + // do something to show vertical bars + if (histogramRGBArea) { + histogramRGBArea->updateBackBuffer(r, g, b, profile, profileW); + } + update_hist_area = histogramArea->updatePointer(r, g, b, profile, profileW); + } + if (histogramRGBArea) { + histogramRGBArea->queue_draw(); + } + if (update_hist_area) { + histogramArea->queue_draw(); + } + }, + 50, + 100 + ), + panel_listener(nullptr) { setExpandAlignProperties(this, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); set_name("HistogramPanel"); @@ -40,30 +74,51 @@ HistogramPanel::HistogramPanel () histogramArea = Gtk::manage (new HistogramArea (this)); setExpandAlignProperties(histogramArea, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - histogramRGBArea = Gtk::manage (new HistogramRGBArea ()); - setExpandAlignProperties(histogramRGBArea, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_END); - histogramRGBArea->show(); + histogramRGBAreaHori.reset(new HistogramRGBAreaHori()); + setExpandAlignProperties(histogramRGBAreaHori.get(), true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_END); + + histogramRGBAreaVert.reset(new HistogramRGBAreaVert()); + setExpandAlignProperties(histogramRGBAreaVert.get(), false, true, Gtk::ALIGN_END, Gtk::ALIGN_FILL); + + switch (options.histogramScopeType) { + case ScopeType::NONE: + case ScopeType::HISTOGRAM_RAW: + case ScopeType::VECTORSCOPE_HC: + case ScopeType::VECTORSCOPE_HS: + histogramRGBArea = nullptr; + break; + case ScopeType::PARADE: + case ScopeType::WAVEFORM: + histogramRGBArea = histogramRGBAreaVert.get(); + break; + case ScopeType::HISTOGRAM: + histogramRGBArea = histogramRGBAreaHori.get(); + break; + } // connecting the two childs - histogramArea->signal_factor_changed().connect( sigc::mem_fun(*histogramRGBArea, &HistogramRGBArea::factorChanged) ); + histogramArea->signal_factor_changed().connect( sigc::mem_fun(*histogramRGBAreaHori, &HistogramRGBArea::factorChanged) ); + histogramArea->signal_factor_changed().connect( sigc::mem_fun(*histogramRGBAreaVert, &HistogramRGBArea::factorChanged) ); gfxGrid = Gtk::manage (new Gtk::Grid ()); - gfxGrid->set_orientation(Gtk::ORIENTATION_VERTICAL); gfxGrid->set_row_spacing(1); gfxGrid->set_column_spacing(1); - histogramRGBArea->setParent(gfxGrid); gfxGrid->add(*histogramArea); - - if (options.histogramBar) { - gfxGrid->add (*histogramRGBArea); - } + gfxGrid->attach_next_to( + *histogramRGBAreaVert, *histogramArea, + options.histogramPosition == 1 ? Gtk::POS_RIGHT : Gtk::POS_LEFT, + 1, + 1 + ); + gfxGrid->attach_next_to(*histogramRGBAreaHori, *histogramArea, Gtk::POS_BOTTOM, 1, 1); + histogramRGBAreaHori->set_no_show_all(); + histogramRGBAreaVert->set_no_show_all(); redImage = new RTImage ("histogram-red-on-small.png"); greenImage = new RTImage ("histogram-green-on-small.png"); blueImage = new RTImage ("histogram-blue-on-small.png"); valueImage = new RTImage ("histogram-silver-on-small.png"); chroImage = new RTImage ("histogram-gold-on-small.png"); - rawImage = new RTImage ("histogram-bayer-on-small.png"); barImage = new RTImage ("histogram-bar-on-small.png"); redImage_g = new RTImage ("histogram-red-off-small.png"); @@ -71,21 +126,41 @@ HistogramPanel::HistogramPanel () blueImage_g = new RTImage ("histogram-blue-off-small.png"); valueImage_g = new RTImage ("histogram-silver-off-small.png"); chroImage_g = new RTImage ("histogram-gold-off-small.png"); - rawImage_g = new RTImage ("histogram-bayer-off-small.png"); barImage_g = new RTImage ("histogram-bar-off-small.png"); mode0Image = new RTImage ("histogram-mode-linear-small.png"); mode1Image = new RTImage ("histogram-mode-logx-small.png"); mode2Image = new RTImage ("histogram-mode-logxy-small.png"); + Gtk::Image* histImage = Gtk::manage(new RTImage("histogram-type-histogram-small.png")); + Gtk::Image* histRawImage = Gtk::manage(new RTImage("histogram-type-histogram-raw-small.png")); + Gtk::Image* paradeImage = Gtk::manage(new RTImage("histogram-type-parade-small.png")); + Gtk::Image* waveImage = Gtk::manage(new RTImage("histogram-type-waveform-small.png")); + Gtk::Image* vectHcImage = Gtk::manage(new RTImage("histogram-type-vectorscope-hc-small.png")); + Gtk::Image* vectHsImage = Gtk::manage(new RTImage("histogram-type-vectorscope-hs-small.png")); + showRed = Gtk::manage (new Gtk::ToggleButton ()); showGreen = Gtk::manage (new Gtk::ToggleButton ()); showBlue = Gtk::manage (new Gtk::ToggleButton ()); showValue = Gtk::manage (new Gtk::ToggleButton ()); showChro = Gtk::manage (new Gtk::ToggleButton ()); - showRAW = Gtk::manage (new Gtk::ToggleButton ()); showMode = Gtk::manage (new Gtk::Button ()); showBAR = Gtk::manage (new Gtk::ToggleButton ()); + scopeOptions = Gtk::manage (new Gtk::ToggleButton ()); + + Gtk::RadioButtonGroup scopeTypeGroup; + scopeHistBtn = Gtk::manage(new Gtk::RadioButton(scopeTypeGroup)); + scopeHistRawBtn = Gtk::manage(new Gtk::RadioButton(scopeTypeGroup)); + scopeParadeBtn = Gtk::manage(new Gtk::RadioButton(scopeTypeGroup)); + scopeWaveBtn = Gtk::manage(new Gtk::RadioButton(scopeTypeGroup)); + scopeVectHcBtn = Gtk::manage(new Gtk::RadioButton(scopeTypeGroup)); + scopeVectHsBtn = Gtk::manage(new Gtk::RadioButton(scopeTypeGroup)); + scopeHistBtn->set_mode(false); + scopeHistRawBtn->set_mode(false); + scopeParadeBtn->set_mode(false); + scopeWaveBtn->set_mode(false); + scopeVectHcBtn->set_mode(false); + scopeVectHsBtn->set_mode(false); showRed->set_name("histButton"); showRed->set_can_focus(false); @@ -97,40 +172,68 @@ HistogramPanel::HistogramPanel () showValue->set_can_focus(false); showChro->set_name("histButton"); showChro->set_can_focus(false); - showRAW->set_name("histButton"); - showRAW->set_can_focus(false); showMode->set_name("histButton"); showMode->set_can_focus(false); + scopeOptions->set_name("histButton"); + scopeOptions->set_can_focus(false); showBAR->set_name("histButton"); showBAR->set_can_focus(false); + scopeHistBtn->set_name("histButton"); + scopeHistBtn->set_can_focus(false); + scopeHistRawBtn->set_name("histButton"); + scopeHistRawBtn->set_can_focus(false); + scopeParadeBtn->set_name("histButton"); + scopeParadeBtn->set_can_focus(false); + scopeWaveBtn->set_name("histButton"); + scopeWaveBtn->set_can_focus(false); + scopeVectHcBtn->set_name("histButton"); + scopeVectHcBtn->set_can_focus(false); + scopeVectHsBtn->set_name("histButton"); + scopeVectHsBtn->set_can_focus(false); showRed->set_relief (Gtk::RELIEF_NONE); showGreen->set_relief (Gtk::RELIEF_NONE); showBlue->set_relief (Gtk::RELIEF_NONE); showValue->set_relief (Gtk::RELIEF_NONE); showChro->set_relief (Gtk::RELIEF_NONE); - showRAW->set_relief (Gtk::RELIEF_NONE); showMode->set_relief (Gtk::RELIEF_NONE); + scopeOptions->set_relief (Gtk::RELIEF_NONE); showBAR->set_relief (Gtk::RELIEF_NONE); + scopeHistBtn->set_relief (Gtk::RELIEF_NONE); + scopeHistRawBtn->set_relief (Gtk::RELIEF_NONE); + scopeParadeBtn->set_relief (Gtk::RELIEF_NONE); + scopeWaveBtn->set_relief (Gtk::RELIEF_NONE); + scopeVectHcBtn->set_relief (Gtk::RELIEF_NONE); + scopeVectHsBtn->set_relief (Gtk::RELIEF_NONE); showRed->set_tooltip_text (M("HISTOGRAM_TOOLTIP_R")); showGreen->set_tooltip_text (M("HISTOGRAM_TOOLTIP_G")); showBlue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_B")); showValue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_L")); showChro->set_tooltip_text (M("HISTOGRAM_TOOLTIP_CHRO")); - showRAW->set_tooltip_text (M("HISTOGRAM_TOOLTIP_RAW")); showMode->set_tooltip_text (M("HISTOGRAM_TOOLTIP_MODE")); - showBAR->set_tooltip_text (M("HISTOGRAM_TOOLTIP_BAR")); + scopeOptions->set_tooltip_text(M("HISTOGRAM_TOOLTIP_SHOW_OPTIONS")); + scopeHistBtn->set_tooltip_text(M("HISTOGRAM_TOOLTIP_TYPE_HISTOGRAM")); + scopeHistRawBtn->set_tooltip_text(M("HISTOGRAM_TOOLTIP_TYPE_HISTOGRAM_RAW")); + scopeParadeBtn->set_tooltip_text(M("HISTOGRAM_TOOLTIP_TYPE_PARADE")); + scopeWaveBtn->set_tooltip_text(M("HISTOGRAM_TOOLTIP_TYPE_WAVEFORM")); + scopeVectHcBtn->set_tooltip_text(M("HISTOGRAM_TOOLTIP_TYPE_VECTORSCOPE_HC")); + scopeVectHsBtn->set_tooltip_text(M("HISTOGRAM_TOOLTIP_TYPE_VECTORSCOPE_HS")); buttonGrid = Gtk::manage (new Gtk::Grid ()); - buttonGrid->set_orientation(Gtk::ORIENTATION_VERTICAL); + buttonGrid->set_orientation(Gtk::ORIENTATION_HORIZONTAL); + persistentButtons = Gtk::manage(new Gtk::Box()); + persistentButtons->set_orientation(Gtk::ORIENTATION_VERTICAL); + optionButtons = Gtk::manage(new Gtk::Box()); + optionButtons->set_orientation(Gtk::ORIENTATION_VERTICAL); + showRed->set_active (options.histogramRed); showGreen->set_active (options.histogramGreen); showBlue->set_active (options.histogramBlue); showValue->set_active (options.histogramLuma); showChro->set_active (options.histogramChroma); - showRAW->set_active (options.histogramRAW); // no showMode->set_active(), as it's not a ToggleButton + scopeOptions->set_active(options.histogramShowOptionButtons); showBAR->set_active (options.histogramBar); showRed->set_image (showRed->get_active() ? *redImage : *redImage_g); @@ -138,66 +241,145 @@ HistogramPanel::HistogramPanel () showBlue->set_image (showBlue->get_active() ? *blueImage : *blueImage_g); showValue->set_image (showValue->get_active() ? *valueImage : *valueImage_g); showChro->set_image (showChro->get_active() ? *chroImage : *chroImage_g); - showRAW->set_image (showRAW->get_active() ? *rawImage : *rawImage_g); if (options.histogramDrawMode == 0) showMode->set_image(*mode0Image); else if (options.histogramDrawMode == 1) showMode->set_image(*mode1Image); else showMode->set_image(*mode2Image); + scopeHistBtn->set_image(*histImage); + scopeHistRawBtn->set_image(*histRawImage); + scopeParadeBtn->set_image(*paradeImage); + scopeWaveBtn->set_image(*waveImage); + scopeVectHcBtn->set_image(*vectHcImage); + scopeVectHsBtn->set_image(*vectHsImage); + switch(options.histogramScopeType) { + case ScopeType::HISTOGRAM: + scopeHistBtn->set_active(); + break; + case ScopeType::HISTOGRAM_RAW: + scopeHistRawBtn->set_active(); + break; + case ScopeType::PARADE: + scopeParadeBtn->set_active(); + break; + case ScopeType::WAVEFORM: + scopeWaveBtn->set_active(); + break; + case ScopeType::VECTORSCOPE_HS: + scopeVectHsBtn->set_active(); + break; + case ScopeType::VECTORSCOPE_HC: + scopeVectHcBtn->set_active(); + break; + case ScopeType::NONE: + break; + } + scopeOptions->set_image(*Gtk::manage(new RTImage("histogram-ellipsis-small.png"))); showBAR->set_image (showBAR->get_active() ? *barImage : *barImage_g); - - raw_toggled(); // Make sure the luma/chroma toggles are enabled or disabled - setExpandAlignProperties(showRed , false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - setExpandAlignProperties(showGreen, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - setExpandAlignProperties(showBlue , false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - setExpandAlignProperties(showValue, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - setExpandAlignProperties(showChro , false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - setExpandAlignProperties(showRAW , false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - setExpandAlignProperties(showMode , false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - setExpandAlignProperties(showBAR , false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + setExpandAlignProperties(showRed , false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + setExpandAlignProperties(showGreen, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + setExpandAlignProperties(showBlue , false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + setExpandAlignProperties(showValue, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + setExpandAlignProperties(showChro , false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + setExpandAlignProperties(showMode , false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + setExpandAlignProperties(scopeOptions, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + setExpandAlignProperties(showBAR , false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + setExpandAlignProperties(scopeOptions, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + setExpandAlignProperties(scopeHistBtn, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + setExpandAlignProperties(scopeHistRawBtn, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + setExpandAlignProperties(scopeParadeBtn, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + setExpandAlignProperties(scopeWaveBtn, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + setExpandAlignProperties(scopeVectHcBtn, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + setExpandAlignProperties(scopeVectHsBtn, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + setExpandAlignProperties(persistentButtons, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); + setExpandAlignProperties(optionButtons, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL); showRed->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::red_toggled), showRed ); showGreen->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::green_toggled), showGreen ); showBlue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::blue_toggled), showBlue ); showValue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::value_toggled), showValue ); showChro->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::chro_toggled), showChro ); - showRAW->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::raw_toggled), showRAW ); showMode->signal_released().connect( sigc::mem_fun(*this, &HistogramPanel::mode_released), showMode ); + scopeOptions->signal_toggled().connect(sigc::mem_fun(*this, &HistogramPanel::scopeOptionsToggled)); showBAR->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::bar_toggled), showBAR ); + scopeHistBtn->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &HistogramPanel::type_selected), scopeHistBtn)); + scopeHistRawBtn->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &HistogramPanel::type_selected), scopeHistRawBtn)); + scopeParadeBtn->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &HistogramPanel::type_selected), scopeParadeBtn)); + scopeWaveBtn->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &HistogramPanel::type_selected), scopeWaveBtn)); + scopeVectHcBtn->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &HistogramPanel::type_selected), scopeVectHcBtn)); + scopeVectHsBtn->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &HistogramPanel::type_selected), scopeVectHsBtn)); - buttonGrid->add (*showRed); - buttonGrid->add (*showGreen); - buttonGrid->add (*showBlue); - buttonGrid->add (*showValue); - buttonGrid->add (*showChro); - buttonGrid->add (*showRAW); - buttonGrid->add (*showMode); - buttonGrid->add (*showBAR); + brightnessWidget = Gtk::manage(new Gtk::Scale(Gtk::ORIENTATION_VERTICAL)); + brightnessWidget->set_inverted(); + brightnessWidget->set_range(log(HistogramArea::MIN_BRIGHT), log(HistogramArea::MAX_BRIGHT)); + brightnessWidget->set_draw_value(false); + brightnessWidget->signal_value_changed().connect(sigc::mem_fun(*this, &HistogramPanel::brightnessWidgetValueChanged)); + brightnessWidget->set_name("histScale"); + brightnessWidget->set_tooltip_text(M("HISTOGRAM_TOOLTIP_TRACE_BRIGHTNESS")); + setExpandAlignProperties(brightnessWidget, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); + + optionButtons->add(*showRed); + optionButtons->add(*showGreen); + optionButtons->add(*showBlue); + optionButtons->add(*showValue); + optionButtons->add(*showChro); + optionButtons->add(*showMode); + optionButtons->add(*showBAR); + optionButtons->add(*brightnessWidget); + + Gtk::VSeparator* separator = Gtk::manage(new Gtk::VSeparator()); + setExpandAlignProperties(separator, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + persistentButtons->add(*scopeHistBtn); + persistentButtons->add(*scopeHistRawBtn); + persistentButtons->add(*scopeParadeBtn); + persistentButtons->add(*scopeWaveBtn); + persistentButtons->add(*scopeVectHsBtn); + persistentButtons->add(*scopeVectHcBtn); + persistentButtons->add(*separator); + persistentButtons->add(*scopeOptions); // Put the button vbox next to the window's border to be less disturbing if (options.histogramPosition == 1) { + buttonGrid->add(*persistentButtons); + buttonGrid->add(*optionButtons); + add (*buttonGrid); add (*gfxGrid); } else { + buttonGrid->add(*optionButtons); + buttonGrid->add(*persistentButtons); + add (*gfxGrid); add (*buttonGrid); } show_all (); + optionButtons->set_no_show_all(); + optionButtons->set_visible(options.histogramShowOptionButtons); + type_changed(); + updateHistAreaOptions(); + if (histogramRGBArea) { + updateHistRGBAreaOptions(); + } + + brightness_changed_connection = histogramArea->getBrighnessChangedSignal().connect(sigc::mem_fun(*this, &HistogramPanel::brightnessUpdated)); rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &HistogramPanel::resized) ); + + histogramArea->setBrightness(options.histogramTraceBrightness); } HistogramPanel::~HistogramPanel () { + pointer_moved_delayed_call.cancel(); + delete redImage; delete greenImage; delete blueImage; delete valueImage; delete chroImage; - delete rawImage; delete mode0Image; delete mode1Image; delete mode2Image; @@ -208,24 +390,51 @@ HistogramPanel::~HistogramPanel () delete blueImage_g; delete valueImage_g; delete chroImage_g; - delete rawImage_g; delete barImage_g; } +void HistogramPanel::showRGBBar() +{ + histogramRGBAreaHori->set_visible( + histogramRGBArea == histogramRGBAreaHori.get() && showBAR->get_active()); + histogramRGBAreaVert->set_visible( + histogramRGBArea == histogramRGBAreaVert.get() && showBAR->get_active()); + histogramRGBAreaHori->setShow(false); + histogramRGBAreaVert->setShow(false); + + if (!histogramRGBArea) { + return; + } + + setHistRGBInvalid(); + histogramRGBArea->setShow(showBAR->get_active()); +} + void HistogramPanel::resized (Gtk::Allocation& req) { + static int old_height = 0; + static int old_width = 0; - histogramArea->updateBackBuffer (); - histogramArea->queue_draw (); + bool size_changed = + old_height != req.get_height() || old_width != req.get_width(); + + if (!histogramArea->updatePending() && size_changed) { + histogramArea->updateBackBuffer (); + histogramArea->queue_draw (); + } // set histogramRGBArea invalid; - histogramRGBArea->updateBackBuffer(-1, -1, -1); - histogramRGBArea->queue_draw (); + if (histogramRGBArea && size_changed) { + histogramRGBArea->updateBackBuffer(-1, -1, -1); + histogramRGBArea->queue_draw (); + } // Store current height of the histogram options.histogramHeight = get_height(); + old_height = req.get_height(); + old_width = req.get_width(); } void HistogramPanel::red_toggled () @@ -258,21 +467,6 @@ void HistogramPanel::chro_toggled () rgbv_toggled(); } -void HistogramPanel::raw_toggled () -{ - if (showRAW->get_active()) { - showRAW->set_image(*rawImage); - showValue->set_sensitive(false); - showChro->set_sensitive(false); - } else { - showRAW->set_image(*rawImage_g); - showValue->set_sensitive(true); - showChro->set_sensitive(true); - } - - rgbv_toggled(); -} - void HistogramPanel::mode_released () { options.histogramDrawMode = (options.histogramDrawMode + 1) % 3; @@ -285,21 +479,141 @@ void HistogramPanel::mode_released () rgbv_toggled(); } +void HistogramPanel::brightnessWidgetValueChanged(void) +{ + ConnectionBlocker blocker(brightness_changed_connection); + histogramArea->setBrightness(exp(brightnessWidget->get_value())); + options.histogramTraceBrightness = histogramArea->getBrightness(); +} + +void HistogramPanel::brightnessUpdated(float brightness) +{ + brightnessWidget->set_value(log(brightness)); + options.histogramTraceBrightness = histogramArea->getBrightness(); +} + +void HistogramPanel::scopeOptionsToggled() +{ + options.histogramShowOptionButtons = scopeOptions->get_active(); + optionButtons->set_visible(scopeOptions->get_active()); +} + +void HistogramPanel::type_selected(Gtk::RadioButton* button) +{ + ScopeType new_type = ScopeType::NONE; + + if (button == scopeHistBtn) { + new_type = ScopeType::HISTOGRAM; + } else if (button == scopeHistRawBtn) { + new_type = ScopeType::HISTOGRAM_RAW; + } else if (button == scopeParadeBtn) { + new_type = ScopeType::PARADE; + } else if (button == scopeWaveBtn) { + new_type = ScopeType::WAVEFORM; + } else if (button == scopeVectHcBtn) { + new_type = ScopeType::VECTORSCOPE_HC; + } else if (button == scopeVectHsBtn) { + new_type = ScopeType::VECTORSCOPE_HS; + } + + if (new_type == options.histogramScopeType) { + return; + } + + options.histogramScopeType = new_type; + + type_changed(); + updateHistAreaOptions(); + if (histogramRGBArea) { + updateHistRGBAreaOptions(); + } + histogramArea->setDirty(true); + histogramArea->queue_draw(); +} + +void HistogramPanel::type_changed() +{ + switch (options.histogramScopeType) { + case ScopeType::HISTOGRAM: + showRed->show(); + showGreen->show(); + showBlue->show(); + showValue->show(); + showChro->show(); + showMode->show(); + showBAR->show(); + showBAR->set_tooltip_text(M("HISTOGRAM_TOOLTIP_BAR")); + brightnessWidget->hide(); + histogramRGBArea = histogramRGBAreaHori.get(); + break; + case ScopeType::HISTOGRAM_RAW: + showRed->show(); + showGreen->show(); + showBlue->show(); + showValue->hide(); + showChro->hide(); + showMode->show(); + showBAR->hide(); + brightnessWidget->hide(); + histogramRGBArea = nullptr; + break; + case ScopeType::PARADE: + case ScopeType::WAVEFORM: + showRed->show(); + showGreen->show(); + showBlue->show(); + showValue->show(); + showChro->hide(); + showMode->hide(); + showBAR->show(); + showBAR->set_tooltip_text(M("HISTOGRAM_TOOLTIP_BAR")); + brightnessWidget->show(); + histogramRGBArea = histogramRGBAreaVert.get(); + break; + case ScopeType::VECTORSCOPE_HC: + case ScopeType::VECTORSCOPE_HS: + showRed->hide(); + showGreen->hide(); + showBlue->hide(); + showValue->hide(); + showChro->hide(); + showMode->hide(); + showBAR->show(); + showBAR->set_tooltip_text(M("HISTOGRAM_TOOLTIP_CROSSHAIR")); + brightnessWidget->show(); + histogramRGBArea = nullptr; + break; + case ScopeType::NONE: + break; + } + + if (panel_listener) { + updateHistAreaOptions(); + panel_listener->scopeTypeChanged(options.histogramScopeType); + } + + showRGBBar(); +} + void HistogramPanel::bar_toggled () { showBAR->set_image(showBAR->get_active() ? *barImage : *barImage_g); rgbv_toggled(); + showRGBBar(); } void HistogramPanel::rgbv_toggled () { // Update Display - histogramArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showChro->get_active(), showRAW->get_active(), options.histogramDrawMode); + updateHistAreaOptions(); + histogramArea->updateBackBuffer (); histogramArea->queue_draw (); - histogramRGBArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showChro->get_active(), showRAW->get_active(), showBAR->get_active()); - histogramRGBArea->updateBackBuffer (0, 0, 0); - histogramRGBArea->queue_draw (); + if (histogramRGBArea) { + updateHistRGBAreaOptions(); + histogramRGBArea->updateBackBuffer(-1, -1, -1); + histogramRGBArea->queue_draw (); + } } void HistogramPanel::setHistRGBInvalid () @@ -311,15 +625,7 @@ void HistogramPanel::setHistRGBInvalid () void HistogramPanel::pointerMoved (bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int x, int y, int r, int g, int b, bool isRaw) { - - if (!validPos) { - // do something to un-show vertical bars - histogramRGBArea->updateBackBuffer(-1, -1, -1); - } else { - // do something to show vertical bars - histogramRGBArea->updateBackBuffer(r, g, b, profile, profileW); - } - histogramRGBArea->queue_draw (); + pointer_moved_delayed_call(validPos, profile, profileW, r, g, b); } /* @@ -333,11 +639,27 @@ void HistogramPanel::reorder (Gtk::PositionType align) removeIfThere(this, gfxGrid, false); add (*gfxGrid); gfxGrid->unreference(); + + gfxGrid->remove(*histogramRGBAreaVert); + gfxGrid->add(*histogramRGBAreaVert); + + optionButtons->reference(); + removeIfThere(buttonGrid, optionButtons, false); + buttonGrid->add(*optionButtons); + optionButtons->unreference(); } else { buttonGrid->reference(); removeIfThere(this, buttonGrid, false); add (*buttonGrid); buttonGrid->unreference(); + + gfxGrid->remove(*histogramRGBAreaVert); + gfxGrid->attach_next_to(*histogramRGBAreaVert, *histogramArea, Gtk::POS_LEFT, 1, 1); + + persistentButtons->reference(); + removeIfThere(buttonGrid, persistentButtons, false); + buttonGrid->add(*persistentButtons); + persistentButtons->unreference(); } } @@ -352,6 +674,41 @@ void HistogramPanel::toggleButtonMode () showMode->set_image(*mode2Image); } +void HistogramPanel::setPanelListener(HistogramPanelListener* listener) +{ + panel_listener = listener; + + if (listener) { + listener->scopeTypeChanged(options.histogramScopeType); + } +} + +void HistogramPanel::updateHistAreaOptions() +{ + histogramArea->updateOptions( + showRed->get_active(), + showGreen->get_active(), + showBlue->get_active(), + showValue->get_active(), + showChro->get_active(), + options.histogramDrawMode, + options.histogramScopeType, + showBAR->get_active() + ); +} + +void HistogramPanel::updateHistRGBAreaOptions() +{ + histogramRGBArea->updateOptions( + showRed->get_active(), + showGreen->get_active(), + showBlue->get_active(), + showValue->get_active(), + showChro->get_active(), + showBAR->get_active() + ); +} + // // // @@ -369,10 +726,9 @@ double HistogramScaling::log(double vsize, double val) HistogramRGBArea::HistogramRGBArea () : val(0), r(0), g(0), b(0), valid(false), needRed(options.histogramRed), needGreen(options.histogramGreen), needBlue(options.histogramBlue), - needLuma(options.histogramLuma), needChroma(options.histogramChroma), rawMode(options.histogramRAW), + needLuma(options.histogramLuma), needChroma(options.histogramChroma), showMode(options.histogramBar), barDisplayed(options.histogramBar), parent(nullptr) { - get_style_context()->add_class("drawingarea"); set_name("HistogramRGBArea"); @@ -394,46 +750,41 @@ HistogramRGBArea::~HistogramRGBArea () } -Gtk::SizeRequestMode HistogramRGBArea::get_request_mode_vfunc () const +void HistogramRGBArea::getPreferredThickness(int& min_thickness, int& natural_thickness) const { - return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH; + int minimumLength = 0; + int naturalLength = 0; + getPreferredLength(minimumLength, naturalLength); + getPreferredThicknessForLength(minimumLength, min_thickness, natural_thickness); } -void HistogramRGBArea::get_preferred_height_vfunc (int &minimum_height, int &natural_height) const -{ - int minimumWidth = 0; - int naturalWidth = 0; - get_preferred_width_vfunc(minimumWidth, naturalWidth); - get_preferred_height_for_width_vfunc (minimumWidth, minimum_height, natural_height); -} - -void HistogramRGBArea::get_preferred_width_vfunc (int &minimum_width, int &natural_width) const +void HistogramRGBArea::getPreferredLength(int& min_length, int& natural_length) const { int s = RTScalable::getScale(); - minimum_width = 60 * s; - natural_width = 200 * s; + min_length = 60 * s; + natural_length = 200 * s; } -void HistogramRGBArea::get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const +void HistogramRGBArea::getPreferredThicknessForLength(int length, int& min_thickness, int& natural_thickness) const { - int bHeight = width / 30; + int bThickness = length / 30; int s = RTScalable::getScale(); - if (bHeight > (10 * s)) { - bHeight = 10 * s; - } else if (bHeight < (5 * s)) { - bHeight = 5 * s; + if (bThickness > (10 * s)) { + bThickness = 10 * s; + } else if (bThickness < (5 * s)) { + bThickness = 5 * s; } - minimum_height = bHeight; - natural_height = bHeight; + min_thickness = bThickness; + natural_thickness = bThickness; } // unused? -void HistogramRGBArea::get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const +void HistogramRGBArea::getPreferredLengthForThickness(int thickness, int& min_length, int& natural_length) const { - get_preferred_width_vfunc (minimum_width, natural_width); + getPreferredLength(min_length, natural_length); } bool HistogramRGBArea::getShow() @@ -441,9 +792,18 @@ bool HistogramRGBArea::getShow() return(showMode); } +void HistogramRGBArea::setShow(bool show) +{ + showMode = show; +} + void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustring &profile, const Glib::ustring &profileW) { - if (!get_realized () || !showMode || rawMode) { + if (!get_realized () || !showMode || !( + options.histogramScopeType == ScopeType::HISTOGRAM + || options.histogramScopeType == ScopeType::PARADE + || options.histogramScopeType == ScopeType::WAVEFORM + )) { return; } @@ -471,75 +831,44 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin cc->set_line_width (1.0 * s); if ( r != -1 && g != -1 && b != -1 ) { - double xpos; if (needRed) { // Red cc->set_source_rgb(1.0, 0.0, 0.0); - if (options.histogramDrawMode < 2) { - xpos = padding + r * (winw - padding * 2.0) / 255.0 + 0.5*s; - } else { - xpos = padding + HistogramScaling::log (255, r) * (winw - padding * 2.0) / 255.0 + 0.5*s; - } - cc->move_to(xpos, 0.0); - cc->line_to(xpos, winh - 0.0); - cc->stroke(); + drawBar(cc, r, 255.0, winw, winh, s); } if (needGreen) { // Green cc->set_source_rgb(0.0, 1.0, 0.0); - if (options.histogramDrawMode < 2) { - xpos = padding + g * (winw - padding * 2.0) / 255.0 + 0.5*s; - } else { - xpos = padding + HistogramScaling::log (255, g) * (winw - padding * 2.0) / 255.0 + 0.5*s; - } - cc->move_to(xpos, 0.0); - cc->line_to(xpos, winh - 0.0); - cc->stroke(); + drawBar(cc, g, 255.0, winw, winh, s); } if (needBlue) { // Blue cc->set_source_rgb(0.0, 0.4, 1.0); - if (options.histogramDrawMode < 2) { - xpos = padding + b * (winw - padding * 2.0) / 255.0 + 0.5*s; - } else { - xpos = padding + HistogramScaling::log (255, b) * (winw - padding * 2.0) / 255.0 + 0.5*s; - } - cc->move_to(xpos, 0.0); - cc->line_to(xpos, winh - 0.0); - cc->stroke(); + drawBar(cc, b, 255.0, winw, winh, s); } - if(needLuma || needChroma) { + if( + (needLuma || needChroma) + && (options.histogramScopeType == ScopeType::HISTOGRAM + || options.histogramScopeType == ScopeType::PARADE + || options.histogramScopeType == ScopeType::WAVEFORM) + ) { float Lab_L, Lab_a, Lab_b; rtengine::Color::rgb2lab01(profile, profileW, r / 255.f, g / 255.f, b / 255.f, Lab_L, Lab_a, Lab_b, options.rtSettings.HistogramWorking); if (needLuma) { // Luma cc->set_source_rgb(1.0, 1.0, 1.0); - if (options.histogramDrawMode < 2) { - xpos = padding + static_cast(Lab_L) * (winw - padding * 2.0) / 100.0 + 0.5*s; - } else { - xpos = padding + HistogramScaling::log(100, Lab_L) * (winw - padding * 2.0) / 100.0 + 0.5*s; - } - cc->move_to(xpos, 0.0); - cc->line_to(xpos, winh - 0.0); - cc->stroke(); + drawBar(cc, Lab_L, 100.0, winw, winh, s); } - if (needChroma) { + if (needChroma && options.histogramScopeType == ScopeType::HISTOGRAM) { // Chroma double chromaval = sqrt(Lab_a * Lab_a + Lab_b * Lab_b) / 1.8; cc->set_source_rgb(0.9, 0.9, 0.0); - if (options.histogramDrawMode < 2) { - xpos = padding + chromaval * (winw - padding * 2.0) / 100.0 + 0.5*s; - } else { - xpos = padding + HistogramScaling::log(100, chromaval) * (winw - padding * 2.0) / 100.0 + 0.5*s; - } - cc->move_to(xpos, 0.0); - cc->line_to(xpos, winh - 0.0); - cc->stroke(); + drawBar(cc, chromaval, 100.0, winw, winh, s); } } } @@ -586,7 +915,7 @@ void HistogramRGBArea::update (int valh, int rh, int gh, int bh) ); } -void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, bool bar) +void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool c, bool bar) { options.histogramRed = needRed = r; @@ -594,18 +923,8 @@ void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool c, bo options.histogramBlue = needBlue = b; options.histogramLuma = needLuma = l; options.histogramChroma = needChroma = c; - options.histogramRAW = rawMode = raw; options.histogramBar = showMode = bar; - // Show/hide the RGB bar widget - if (bar && !barDisplayed) { - parent->add(*this); - barDisplayed = true; - } else if (!bar && barDisplayed) { - removeIfThere(parent, this, false); - barDisplayed = false; - } - } void HistogramRGBArea::on_realize () @@ -650,16 +969,105 @@ void HistogramRGBArea::factorChanged (double newFactor) factor = newFactor; } +void HistogramRGBAreaHori::drawBar(Cairo::RefPtr cc, double value, double max_value, int winw, int winh, double scale) +{ + double pos; + if (options.histogramDrawMode < 2) { + pos = padding + value * (winw - padding * 2.0) / max_value + 0.5 * scale; + } else { + pos = padding + HistogramScaling::log (max_value, value) * (winw - padding * 2.0) / max_value + 0.5 * scale; + } + cc->move_to(pos, 0.0); + cc->line_to(pos, winh - 0.0); + cc->stroke(); +} + +Gtk::SizeRequestMode HistogramRGBAreaHori::get_request_mode_vfunc () const +{ + return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH; +} + +void HistogramRGBAreaHori::get_preferred_height_vfunc (int &minimum_height, int &natural_height) const +{ + getPreferredThickness(minimum_height, natural_height); +} + +void HistogramRGBAreaHori::get_preferred_width_vfunc (int &minimum_width, int &natural_width) const +{ + getPreferredLength(minimum_width, natural_width); +} + +void HistogramRGBAreaHori::get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const +{ + getPreferredThicknessForLength(width, minimum_height, natural_height); +} + +void HistogramRGBAreaHori::get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const +{ + getPreferredLengthForThickness(height, minimum_width, natural_width); +} + +void HistogramRGBAreaVert::drawBar(Cairo::RefPtr cc, double value, double max_value, int winw, int winh, double scale) +{ + double pos; + if (options.histogramDrawMode < 2 || options.histogramScopeType == ScopeType::PARADE || options.histogramScopeType == ScopeType::WAVEFORM) { + pos = padding + value * (winh - padding * 2.0 - 1) / max_value + 0.5 * scale; + } else { + pos = padding + HistogramScaling::log (max_value, value) * (winh - padding * 2.0) / max_value + 0.5 * scale; + } + cc->move_to(0.0, winh - pos); + cc->line_to(winw, winh - pos); + cc->stroke(); +} + +Gtk::SizeRequestMode HistogramRGBAreaVert::get_request_mode_vfunc () const +{ + return Gtk::SIZE_REQUEST_WIDTH_FOR_HEIGHT; +} + +void HistogramRGBAreaVert::get_preferred_height_vfunc (int &minimum_height, int &natural_height) const +{ + getPreferredLength(minimum_height, natural_height); +} + +void HistogramRGBAreaVert::get_preferred_width_vfunc (int &minimum_width, int &natural_width) const +{ + minimum_width = 10 * RTScalable::getScale(); + natural_width = minimum_width; +} + +void HistogramRGBAreaVert::get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const +{ + getPreferredLengthForThickness(width, minimum_height, natural_height); +} + +void HistogramRGBAreaVert::get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const +{ + get_preferred_width_vfunc(minimum_width, natural_width); +} + // // // // HistogramArea HistogramArea::HistogramArea (DrawModeListener *fml) : + vectorscope_scale(0), + vect_hc(0, 0), vect_hs(0, 0), + vect_hc_buffer_dirty(true), vect_hs_buffer_dirty(true), + waveform_scale(0), + rwave(0, 0), gwave(0, 0),bwave(0, 0), lwave(0, 0), + parade_buffer_r_dirty(true), parade_buffer_g_dirty(true), parade_buffer_b_dirty(true), + wave_buffer_dirty(true), wave_buffer_luma_dirty(true), valid(false), drawMode(options.histogramDrawMode), myDrawModeListener(fml), + scopeType(options.histogramScopeType), oldwidth(-1), oldheight(-1), + trace_brightness(1.0), needRed(options.histogramRed), needGreen(options.histogramGreen), needBlue(options.histogramBlue), - needLuma(options.histogramLuma), needChroma(options.histogramChroma), rawMode(options.histogramRAW), - isPressed(false), movingPosition(0.0) + needLuma(options.histogramLuma), needChroma(options.histogramChroma), + isPressed(false), movingPosition(0.0), + needPointer(options.histogramBar), + pointer_red(-1), pointer_green(-1), pointer_blue(-1), + pointer_a(0), pointer_b(0) { rhist(256); @@ -695,7 +1103,7 @@ Gtk::SizeRequestMode HistogramArea::get_request_mode_vfunc () const void HistogramArea::get_preferred_height_vfunc (int &minimum_height, int &natural_height) const { - int s = (int)RTScalable::getScale(); + int s = RTScalable::getScale(); minimum_height = 100 * s; natural_height = 200 * s; } @@ -703,7 +1111,7 @@ void HistogramArea::get_preferred_height_vfunc (int &minimum_height, int &natura void HistogramArea::get_preferred_width_vfunc (int &minimum_width, int &natural_width) const { - int s = (int)RTScalable::getScale(); + int s = RTScalable::getScale(); minimum_width = 200 * s; natural_width = 400 * s; } @@ -720,18 +1128,23 @@ void HistogramArea::get_preferred_width_for_height_vfunc (int height, int &minim get_preferred_width_vfunc (minimum_width, natural_width); } -void HistogramArea::updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, int mode) +void HistogramArea::updateOptions (bool r, bool g, bool b, bool l, bool c, int mode, ScopeType type, bool pointer) { + wave_buffer_dirty = wave_buffer_dirty || needRed != r || needGreen != g || needBlue != b; options.histogramRed = needRed = r; options.histogramGreen = needGreen = g; options.histogramBlue = needBlue = b; options.histogramLuma = needLuma = l; options.histogramChroma = needChroma = c; - options.histogramRAW = rawMode = raw; options.histogramDrawMode = drawMode = mode; + options.histogramScopeType = scopeType = type; + options.histogramBar = needPointer = pointer; +} - updateBackBuffer (); +bool HistogramArea::updatePending(void) +{ + return haih->pending > 0 && !haih->destroyed; } void HistogramArea::update( @@ -742,18 +1155,53 @@ void HistogramArea::update( const LUTu& histChroma, const LUTu& histRedRaw, const LUTu& histGreenRaw, - const LUTu& histBlueRaw + const LUTu& histBlueRaw, + int vectorscopeScale, + const array2D& vectorscopeHC, + const array2D& vectorscopeHS, + int waveformScale, + const array2D& waveformRed, + const array2D& waveformGreen, + const array2D& waveformBlue, + const array2D& waveformLuma ) { if (histRed) { - rhist = histRed; - ghist = histGreen; - bhist = histBlue; - lhist = histLuma; - chist = histChroma; - rhistRaw = histRedRaw; - ghistRaw = histGreenRaw; - bhistRaw = histBlueRaw; + switch (scopeType) { + case ScopeType::HISTOGRAM: + rhist = histRed; + ghist = histGreen; + bhist = histBlue; + lhist = histLuma; + chist = histChroma; + break; + case ScopeType::HISTOGRAM_RAW: + rhistRaw = histRedRaw; + ghistRaw = histGreenRaw; + bhistRaw = histBlueRaw; + break; + case ScopeType::PARADE: + case ScopeType::WAVEFORM: + waveform_scale = waveformScale; + rwave = waveformRed; + gwave = waveformGreen; + bwave = waveformBlue; + lwave = waveformLuma; + parade_buffer_r_dirty = parade_buffer_g_dirty = parade_buffer_b_dirty = wave_buffer_dirty = wave_buffer_luma_dirty = true; + break; + case ScopeType::VECTORSCOPE_HS: + vectorscope_scale = vectorscopeScale; + vect_hs = vectorscopeHS; + vect_hs_buffer_dirty = true; + break; + case ScopeType::VECTORSCOPE_HC: + vectorscope_scale = vectorscopeScale; + vect_hc = vectorscopeHC; + vect_hc_buffer_dirty = true; + break; + case ScopeType::NONE: + break; + } valid = true; } else { valid = false; @@ -788,7 +1236,6 @@ void HistogramArea::update( void HistogramArea::updateBackBuffer () { - if (!get_realized ()) { return; } @@ -822,40 +1269,53 @@ void HistogramArea::updateBackBuffer () cr->set_dash (ch_ds, 0); // determine the number of h-gridlines based on current h - int nrOfHGridPartitions = (int)rtengine::min (16.0, pow (2.0, floor ((h - 100) / 250) + 2)); + int nrOfHGridPartitions = static_cast(rtengine::min (16.0, pow (2.0, floor ((h - 100) / 250) + 2))); int nrOfVGridPartitions = 8; // always show 8 stops (lines at 1,3,7,15,31,63,127) // draw vertical gridlines - for (int i = 0; i <= nrOfVGridPartitions; i++) { - double xpos = padding + 0.5; - if (options.histogramDrawMode < 2) { - xpos += (pow(2.0,i) - 1) * (w - padding * 2.0) / 255.0; - } else { - xpos += HistogramScaling::log (255, pow(2.0,i) - 1) * (w - padding * 2.0) / 255.0; + if (options.histogramScopeType == ScopeType::HISTOGRAM || options.histogramScopeType == ScopeType::HISTOGRAM_RAW) { + for (int i = 0; i <= nrOfVGridPartitions; i++) { + double xpos = padding + 0.5; + if (options.histogramDrawMode < 2) { + xpos += (pow(2.0,i) - 1) * (w - padding * 2.0) / 255.0; + } else { + xpos += HistogramScaling::log (255, pow(2.0,i) - 1) * (w - padding * 2.0) / 255.0; + } + cr->move_to (xpos, 0.); + cr->line_to (xpos, h); + cr->stroke (); } - cr->move_to (xpos, 0.); - cr->line_to (xpos, h); - cr->stroke (); } // draw horizontal gridlines - if (options.histogramDrawMode == 0) { - for (int i = 1; i < nrOfHGridPartitions; i++) { - cr->move_to (padding, i * (double)h / nrOfHGridPartitions + 0.5); - cr->line_to (w - padding, i * (double)h / nrOfHGridPartitions + 0.5); + if (options.histogramScopeType == ScopeType::PARADE || options.histogramScopeType == ScopeType::WAVEFORM) { + for (int i = 0; i <= nrOfVGridPartitions; i++) { + const double ypos = h - padding - (pow(2.0,i) - 1) * (h - 2 * padding - 1) / 255.0; + cr->move_to(0, ypos); + cr->line_to(w, ypos); + cr->stroke(); + } + } else if (options.histogramScopeType == ScopeType::VECTORSCOPE_HC || options.histogramScopeType == ScopeType::VECTORSCOPE_HS) { + // Vectorscope has no gridlines. + } else if (options.histogramDrawMode == 0) { + for (int i = 1; i < nrOfHGridPartitions; i++) { + cr->move_to (padding, i * static_cast(h) / nrOfHGridPartitions + 0.5); + cr->line_to (w - padding, i * static_cast(h) / nrOfHGridPartitions + 0.5); cr->stroke (); } } else { for (int i = 1; i < nrOfHGridPartitions; i++) { - cr->move_to (padding, h - HistogramScaling::log (h, i * (double)h / nrOfHGridPartitions) + 0.5); - cr->line_to (w - padding, h - HistogramScaling::log (h, i * (double)h / nrOfHGridPartitions) + 0.5); + cr->move_to (padding, h - HistogramScaling::log (h, i * static_cast(h) / nrOfHGridPartitions) + 0.5); + cr->line_to (w - padding, h - HistogramScaling::log (h, i * static_cast(h) / nrOfHGridPartitions) + 0.5); cr->stroke (); } } cr->unset_dash(); - if (valid) { + if (valid && (scopeType == ScopeType::HISTOGRAM || scopeType == ScopeType::HISTOGRAM_RAW)) { + bool rawMode = scopeType == ScopeType::HISTOGRAM_RAW; + // For RAW mode use the other hists LUTu& rh = rawMode ? rhistRaw : rhist; LUTu& gh = rawMode ? ghistRaw : ghist; @@ -962,6 +1422,12 @@ void HistogramArea::updateBackBuffer () drawMarks(cr, bhchanged, realhistheight, w, ui, oi); } + } else if (scopeType == ScopeType::PARADE && rwave.getWidth() > 0) { + drawParade(cr, w, h); + } else if (scopeType == ScopeType::WAVEFORM && rwave.getWidth() > 0) { + drawWaveform(cr, w, h); + } else if (scopeType == ScopeType::VECTORSCOPE_HC || scopeType == ScopeType::VECTORSCOPE_HS) { + drawVectorscope(cr, w, h); } // Draw the frame's border @@ -973,6 +1439,24 @@ void HistogramArea::updateBackBuffer () setDirty(false); } +bool HistogramArea::updatePointer(int r, int g, int b, const Glib::ustring &profile, const Glib::ustring &profileW) +{ + if (!needPointer || !(scopeType == ScopeType::VECTORSCOPE_HC || scopeType == ScopeType::VECTORSCOPE_HS)) { + return false; + } + if (pointer_red == r && pointer_green == g && pointer_blue == b) { + return false; + } + + float L; + pointer_red = r; + pointer_green = g; + pointer_blue = b; + Color::rgb2lab01(profile, profileW, r / 255.f, g / 255.f, b / 255.f, L, pointer_a, pointer_b, options.rtSettings.HistogramWorking); + updateBackBuffer(); + return true; +} + void HistogramArea::on_realize () { @@ -990,15 +1474,15 @@ void HistogramArea::drawCurve(Cairo::RefPtr &cr, scale = scale <= 0.0 ? 0.001 : scale; // avoid division by zero and negative values for (int i = 0; i < 256; i++) { - double val = data[i] * (double)vsize / scale; + double val = data[i] * static_cast(vsize) / scale; if (drawMode > 0) { // scale y for single and double log-scale - val = HistogramScaling::log ((double)vsize, val); + val = HistogramScaling::log (static_cast(vsize), val); } double iscaled = i; if (drawMode == 2) { // scale x for double log-scale - iscaled = HistogramScaling::log (255.0, (double)i); + iscaled = HistogramScaling::log (255.0, static_cast(i)); } double posX = padding + iscaled * (hsize - padding * 2.0) / 255.0; @@ -1026,10 +1510,379 @@ void HistogramArea::drawMarks(Cairo::RefPtr &cr, cr->fill(); } +void HistogramArea::drawParade(Cairo::RefPtr &cr, int w, int h) +{ + // Arbitrary scale factor divided by current scale. + const float scale = trace_brightness * 32.f * 255.f / waveform_scale; + const int wave_width = rwave.getWidth(); + const int wave_height = rwave.getHeight(); + + // See Cairo documentation on stride. + const int cairo_stride = Cairo::ImageSurface::format_stride_for_width(Cairo::FORMAT_ARGB32, rwave.getWidth()); + const auto buffer_size = static_cast::size_type>(wave_height) * cairo_stride; + + if (parade_buffer_r_dirty && needRed) { + parade_buffer_r.assign(buffer_size, 0); + assert(parade_buffer_r.size() % 4 == 0); + + for (int val = 0; val < wave_height; val++) { + const int* const r_row = rwave[val]; + std::uint32_t* const buffer_r_row = reinterpret_cast(parade_buffer_r.data() + (255 - val) * cairo_stride); + for (int col = 0; col < wave_width; col++) { + const unsigned char r = std::min(scale * r_row[col], 0xff); + if (r != 0) { + buffer_r_row[col] = (r << 16) | (r << 24); + } + } + } + + parade_buffer_r_dirty = false; + } + + if (parade_buffer_g_dirty && needGreen) { + parade_buffer_g.assign(buffer_size, 0); + assert(parade_buffer_g.size() % 4 == 0); + + for (int val = 0; val < wave_height; val++) { + const int* const g_row = gwave[val]; + std::uint32_t* const buffer_g_row = reinterpret_cast(parade_buffer_g.data() + (255 - val) * cairo_stride); + for (int col = 0; col < wave_width; col++) { + const unsigned char g = std::min(scale * g_row[col], 0xff); + if (g != 0) { + buffer_g_row[col] = (g << 8) | (g << 24); + } + } + } + + parade_buffer_g_dirty = false; + } + + if (parade_buffer_b_dirty && needBlue) { + parade_buffer_b.assign(buffer_size, 0); + assert(parade_buffer_b.size() % 4 == 0); + + for (int val = 0; val < wave_height; val++) { + const int* const b_row = bwave[val]; + std::uint32_t* const buffer_b_row = reinterpret_cast(parade_buffer_b.data() + (255 - val) * cairo_stride); + for (int col = 0; col < wave_width; col++) { + const unsigned char b = std::min(scale * b_row[col], 0xff); + if (b != 0) { + const unsigned char green = b / 2; // Make blue easier to see. + buffer_b_row[col] = b | (green << 8) | (b << 24); + } + } + } + + parade_buffer_b_dirty = false; + } + + if (wave_buffer_luma_dirty && needLuma) { + wave_buffer_luma.assign(buffer_size, 0); + assert(wave_buffer_luma.size() % 4 == 0); + + for (int val = 0; val < wave_height; val++) { + const int* const l_row = lwave[val]; + std::uint32_t* const buffer_row = + reinterpret_cast(wave_buffer_luma.data() + (255 - val) * cairo_stride); + for (int col = 0; col < wave_width; col++) { + const unsigned char l = std::min(scale * l_row[col], 0xff); + buffer_row[col] = l | (l << 8) | (l << 16) | (l << 24); + } + } + + wave_buffer_luma_dirty = false; + } + + std::vector buffers; + if (needLuma) { + buffers.push_back(wave_buffer_luma.data()); + } + if (needRed) { + buffers.push_back(parade_buffer_r.data()); + } + if (needGreen) { + buffers.push_back(parade_buffer_g.data()); + } + if (needBlue) { + buffers.push_back(parade_buffer_b.data()); + } + + auto orig_matrix = cr->get_matrix(); + const double display_wave_width = static_cast(w) / buffers.size(); + for (unsigned i = 0; i < buffers.size(); i++) { + Cairo::RefPtr surface; + cr->translate(i * display_wave_width, padding); + cr->scale(display_wave_width / wave_width, (h - 2 * padding) / wave_height); + surface = Cairo::ImageSurface::create( + buffers[i], Cairo::FORMAT_ARGB32, wave_width, wave_height, cairo_stride); + cr->set_source(surface, 0, 0); + cr->set_operator(Cairo::OPERATOR_OVER); + cr->paint(); + surface->finish(); + cr->set_matrix(orig_matrix); + } +} + +void HistogramArea::drawVectorscope(Cairo::RefPtr &cr, int w, int h) +{ + if (scopeType != ScopeType::VECTORSCOPE_HC && scopeType != ScopeType::VECTORSCOPE_HS) { + return; + } + + const auto& vect = (scopeType == ScopeType::VECTORSCOPE_HC) ? vect_hc : vect_hs; + auto& vect_buffer = (scopeType == ScopeType::VECTORSCOPE_HC) ? vect_hc_buffer : vect_hs_buffer; + auto& vect_buffer_dirty = (scopeType == ScopeType::VECTORSCOPE_HC) ? vect_hc_buffer_dirty : vect_hs_buffer_dirty; + + const int vect_width = vect.getWidth(); + const int vect_height = vect.getHeight(); + // Arbitrary scale factor multiplied by vectorscope area and divided by + // current scale. + const float scale = trace_brightness * 8.f * vect_width * vect_height / vectorscope_scale; + + // See Cairo documentation on stride. + const int cairo_stride = Cairo::ImageSurface::format_stride_for_width(Cairo::FORMAT_ARGB32, vect_width); + + if (vect_buffer_dirty && vectorscope_scale > 0) { + if (vect_buffer.size() != static_cast(cairo_stride) * vect_height) { + vect_buffer.resize(static_cast(cairo_stride) * vect_height); + } + + assert(vect_buffer.size() % 4 == 0); + + for (int y = 0; y < vect_height; y++) { + const int* const vect_row = vect[y]; + std::uint32_t* const buffer_row = + reinterpret_cast(vect_buffer.data() + (vect_height - 1 - y) * cairo_stride); + for (int x = 0; x < vect_width; x++) { + const unsigned char value = std::min(scale * vect_row[x], 0xff); + buffer_row[x] = value | (value << 8) | (value << 16) | (value << 24); + } + } + + vect_buffer_dirty = false; + } + + const bool fit_width = + vect_width * (h - 2 * padding) > vect_height * (w - 2 * padding); + const float scope_scale = fit_width ? + (w - 2 * padding) / vect_width : (h - 2 * padding) / vect_height; + const float scope_size = (vectorscope_scale > 0) ? + scope_scale * std::max(vect_width, vect_height) : std::min(w, h) - 2 * padding; + const float o_x = (w - scope_scale * vect_width) / 2; + const float o_y = (h - scope_scale * vect_height) / 2; + const double s = RTScalable::getScale(); + auto orig_matrix = cr->get_matrix(); + const double line_length = scope_size / 2.0; + std::valarray ch_ds(1); + + cr->translate(w / 2.0, h / 2.0); + cr->set_line_width (1.0 * s); + cr->set_antialias(Cairo::ANTIALIAS_SUBPIXEL); + ch_ds[0] = 4; + + if (scopeType == ScopeType::VECTORSCOPE_HS) { // Hue-Saturation. + // RYGCBM lines. + cr->set_line_width (2.0 * s); + constexpr double color_labels[6][3] = { + {1, 0, 0}, // R + {0, 1, 0}, // G + {0, 0, 1}, // B + {0, 1, 1}, // C + {1, 0, 1}, // M + {1, 1, 0}, // Y + }; + for (int i = 0; i < 3; i++) { + auto gradient = Cairo::LinearGradient::create(-line_length, 0, line_length, 0); + const double (&color_1)[3] = color_labels[i]; + const double (&color_2)[3] = color_labels[i + 3]; + cr->set_source(gradient); + gradient->add_color_stop_rgba(0, color_2[0], color_2[1], color_2[2], 0.5); + gradient->add_color_stop_rgba(0.5, 1, 1, 1, 0.25); + gradient->add_color_stop_rgba(1, color_1[0], color_1[1], color_1[2], 0.5); + cr->move_to(-line_length, 0); + cr->line_to(line_length, 0); + cr->rotate_degrees(-120); + cr->stroke(); + } + cr->set_line_width (1.0 * s); + cr->set_source_rgba (1, 1, 1, 0.25); + // 100% saturation circle. + cr->arc(0, 0, scope_size / 2.0, 0, 2 * RT_PI); + cr->stroke(); + // 25%, 50%, and 75% saturation. + cr->set_dash(ch_ds, 0); + for (int i = 1; i < 4; i++) { + cr->arc(0, 0, i * scope_size / 8.0, 0, 2 * RT_PI); + cr->stroke(); + } + // HSV skin tone line derived from -I axis of YIQ. + cr->rotate(-0.134900 * RT_PI); + cr->move_to(0, 0); + cr->line_to(line_length, 0); + cr->stroke(); + cr->unset_dash(); + } else if (scopeType == ScopeType::VECTORSCOPE_HC) { // Hue-Chroma. + // a and b axes. + Cairo::RefPtr gradient; + cr->set_line_width (2.0 * s); + gradient = Cairo::LinearGradient::create(0, -line_length, 0, line_length); + cr->set_source(gradient); + gradient->add_color_stop_rgba(0, 1, 1, 0, 0.5); // "yellow" + gradient->add_color_stop_rgba(0.5, 1, 1, 1, 0.25); // neutral + gradient->add_color_stop_rgba(1, 0, 0, 1, 0.5); // "blue" + cr->move_to(0, 0); + cr->line_to(0, line_length); + cr->move_to(0, 0); + cr->line_to(0, -line_length); + cr->stroke(); + gradient = Cairo::LinearGradient::create(-line_length, 0, line_length, 0); + cr->set_source(gradient); + gradient->add_color_stop_rgba(0, 0, 1, 0, 0.5); // "green" + gradient->add_color_stop_rgba(0.5, 1, 1, 1, 0.25); // neutral + gradient->add_color_stop_rgba(1, 1, 0, 1, 0.5); // "magenta" + cr->move_to(0, 0); + cr->line_to(line_length, 0); + cr->move_to(0, 0); + cr->line_to(-line_length, 0); + cr->stroke(); + cr->set_source_rgba (1, 1, 1, 0.25); + cr->set_line_width (1.0 * s); + // 25%, 50%, 75%, and 100% of standard chroma range. + cr->set_dash(ch_ds, 0); + for (int i = 1; i <= 4; i++) { + cr->arc(0, 0, i * scope_size / 8.0, 0, 2 * RT_PI); + cr->stroke(); + } + // CIELAB skin tone line, approximated by 50% saturation and + // value along the HSV skin tone line. + cr->rotate(-0.321713 * RT_PI); + cr->move_to(0, 0); + cr->line_to(line_length, 0); + cr->stroke(); + cr->unset_dash(); + } + cr->set_matrix(orig_matrix); + + // Vectorscope trace. + if (vectorscope_scale > 0) { + Cairo::RefPtr surface = Cairo::ImageSurface::create( + vect_buffer.data(), Cairo::FORMAT_ARGB32, vect_width, vect_height, cairo_stride); + cr->translate(o_x, o_y); + cr->scale(scope_scale, scope_scale); + cr->set_source(surface, 0, 0); + cr->set_operator(Cairo::OPERATOR_OVER); + cr->paint(); + surface->finish(); + cr->set_matrix(orig_matrix); + + if (needPointer && pointer_red >= 0 && pointer_green >= 0 && pointer_blue >= 0) { + float cx, cy; + if (scopeType == ScopeType::VECTORSCOPE_HS) { + float H, S, L; + Color::rgb2hslfloat(pointer_red * 257.f, pointer_green * 257.f, pointer_blue * 257.f, H, S, L); + cx = (w + scope_size * S * std::cos(H * 2 * RT_PI_F)) / 2; + cy = (h - scope_size * S * std::sin(H * 2 * RT_PI_F)) / 2; + } else { + constexpr float ab_factor = 1.f / 256.f; + cx = w / 2.f + scope_size * pointer_a * ab_factor; + cy = h / 2.f - scope_size * pointer_b * ab_factor; + } + const float crosshair_size = 20.f * s; + cr->set_source_rgba(1, 1, 1, 0.5); + cr->move_to(cx - crosshair_size, cy); + cr->line_to(cx + crosshair_size, cy); + cr->move_to(cx, cy - crosshair_size); + cr->line_to(cx, cy + crosshair_size); + cr->stroke(); + cr->arc(cx, cy, 3 * s, 0, 2 * RT_PI); + cr->set_source_rgb(1, 1, 1); + cr->fill_preserve(); + cr->set_source_rgb(0, 0, 0); + cr->set_line_width (1.0 * s); + cr->stroke(); + } + } +} + +void HistogramArea::drawWaveform(Cairo::RefPtr &cr, int w, int h) +{ + // Arbitrary scale factor divided by current scale. + const float scale = trace_brightness * 32.f * 255.f / waveform_scale; + const int wave_width = rwave.getWidth(); + const int wave_height = rwave.getHeight(); + + // See Cairo documentation on stride. + const int cairo_stride = Cairo::ImageSurface::format_stride_for_width(Cairo::FORMAT_ARGB32, rwave.getWidth()); + const auto buffer_size = static_cast::size_type>(wave_height) * cairo_stride; + + if (wave_buffer_dirty && (needRed || needGreen || needBlue)) { + wave_buffer.assign(buffer_size, 0); + assert(wave_buffer.size() % 4 == 0); + + for (int val = 0; val < wave_height; val++) { + const int* const r_row = rwave[val]; + const int* const g_row = gwave[val]; + const int* const b_row = bwave[val]; + std::uint32_t* const buffer_row = reinterpret_cast(wave_buffer.data() + (255 - val) * cairo_stride); + for (int col = 0; col < wave_width; col++) { + const unsigned char r = needRed ? std::min(scale * r_row[col], 0xff) : 0; + const unsigned char g = needGreen ? std::min(scale * g_row[col], 0xff) : 0; + const unsigned char b = needBlue ? std::min(scale * b_row[col], 0xff) : 0; + const unsigned char value = rtengine::max(r, g, b); + if (value != 0) { + // Ensures correct order regardless of endianness. + buffer_row[col] = b | (g << 8) | (r << 16) | (value << 24); + } + } + } + + wave_buffer_dirty = false; + } + + if (wave_buffer_luma_dirty && needLuma) { + wave_buffer_luma.assign(buffer_size, 0); + assert(wave_buffer_luma.size() % 4 == 0); + + for (int val = 0; val < wave_height; val++) { + const int* const l_row = lwave[val]; + std::uint32_t* const buffer_row = + reinterpret_cast(wave_buffer_luma.data() + (255 - val) * cairo_stride); + for (int col = 0; col < wave_width; col++) { + const unsigned char l = std::min(scale * l_row[col], 0xff); + buffer_row[col] = l | (l << 8) | (l << 16) | (l << 24); + } + } + + wave_buffer_luma_dirty = false; + } + + Cairo::RefPtr surface; + auto orig_matrix = cr->get_matrix(); + cr->translate(0, padding); + cr->scale(static_cast(w) / wave_width, (h - 2 * padding) / wave_height); + if (needLuma) { + surface = Cairo::ImageSurface::create( + wave_buffer_luma.data(), Cairo::FORMAT_ARGB32, wave_width, wave_height, cairo_stride); + cr->set_source(surface, 0, 0); + cr->set_operator(Cairo::OPERATOR_OVER); + cr->paint(); + surface->finish(); + } + if (needRed || needGreen || needBlue) { + surface = Cairo::ImageSurface::create( + wave_buffer.data(), Cairo::FORMAT_ARGB32, wave_width, wave_height, cairo_stride); + cr->set_source(surface, 0, 0); + cr->set_operator(Cairo::OPERATOR_OVER); + cr->paint(); + surface->finish(); + } + cr->set_matrix(orig_matrix); +} + bool HistogramArea::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) { - if (get_width() != oldwidth || get_height() != oldheight || isDirty ()) { + if (!updatePending() && (get_width() != oldwidth || get_height() != oldheight || isDirty())) { updateBackBuffer (); } @@ -1046,7 +1899,10 @@ bool HistogramArea::on_button_press_event (GdkEventButton* event) isPressed = true; movingPosition = event->x; - if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { + if ( + event->type == GDK_2BUTTON_PRESS && event->button == 1 + && (scopeType == ScopeType::HISTOGRAM || scopeType == ScopeType::HISTOGRAM_RAW) + ) { drawMode = (drawMode + 1) % 3; options.histogramDrawMode = (options.histogramDrawMode + 1) % 3; @@ -1070,8 +1926,18 @@ bool HistogramArea::on_button_release_event (GdkEventButton* event) bool HistogramArea::on_motion_notify_event (GdkEventMotion* event) { - if (isPressed) - { + if ( + drawMode == 0 + && (scopeType == ScopeType::HISTOGRAM || scopeType == ScopeType::HISTOGRAM_RAW) + ) { + return false; + } + + if (!isPressed) { + return true; + } + + if (scopeType == ScopeType::HISTOGRAM || scopeType == ScopeType::HISTOGRAM_RAW) { // Adjust log scale. double mod = 1 + (event->x - movingPosition) / get_width(); factor /= mod; @@ -1084,11 +1950,45 @@ bool HistogramArea::on_motion_notify_event (GdkEventMotion* event) setDirty(true); queue_draw (); + } else if ( + scopeType == ScopeType::PARADE + || scopeType == ScopeType::WAVEFORM + || scopeType == ScopeType::VECTORSCOPE_HC + || scopeType == ScopeType::VECTORSCOPE_HS + ) { // Adjust brightness. + constexpr float RANGE = MAX_BRIGHT / MIN_BRIGHT; + double dx = (event->x - movingPosition) / get_width(); + float new_brightness = LIM(trace_brightness * pow(RANGE, dx), MIN_BRIGHT, MAX_BRIGHT); + setBrightness(new_brightness); + movingPosition = event->x; } return true; } +float HistogramArea::getBrightness(void) +{ + return trace_brightness; +} + +void HistogramArea::setBrightness(float brightness) +{ + brightness = LIM(brightness, MIN_BRIGHT, MAX_BRIGHT); + if (brightness != trace_brightness) { + parade_buffer_r_dirty = parade_buffer_g_dirty = parade_buffer_b_dirty = wave_buffer_dirty = wave_buffer_luma_dirty = vect_hc_buffer_dirty = vect_hs_buffer_dirty = true; + trace_brightness = brightness; + setDirty(true); + queue_draw(); + + signal_brightness_changed.emit(trace_brightness); + } +} + +HistogramArea::SignalBrightnessChanged HistogramArea::getBrighnessChangedSignal(void) +{ + return signal_brightness_changed; +} + HistogramArea::type_signal_factor_changed HistogramArea::signal_factor_changed() { return sigFactorChanged; diff --git a/rtgui/histogrampanel.h b/rtgui/histogrampanel.h index 2a29ded9a..393df51a5 100644 --- a/rtgui/histogrampanel.h +++ b/rtgui/histogrampanel.h @@ -18,15 +18,20 @@ */ #pragma once +#include + #include #include #include +#include "delayed.h" #include "guiutils.h" +#include "options.h" #include "pointermotionlistener.h" +#include "../rtengine/array2D.h" #include "../rtengine/LUT.h" #include "../rtengine/noncopyable.h" @@ -53,7 +58,7 @@ public: double log (double vsize, double val); }; -class HistogramRGBArea final : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling, public rtengine::NonCopyable +class HistogramRGBArea : public Gtk::DrawingArea, public BackBuffer, protected HistogramScaling, public rtengine::NonCopyable { private: typedef const double (*TMatrix)[3]; @@ -73,7 +78,6 @@ protected: bool needBlue; bool needLuma; bool needChroma; - bool rawMode; bool showMode; bool barDisplayed; @@ -83,32 +87,58 @@ protected: HistogramRGBAreaIdleHelper* harih; + /** Draw an indicator bar for the value. */ + virtual void drawBar(Cairo::RefPtr cc, double value, double max_value, int winw, int winh, double scale) = 0; + + void getPreferredThickness(int& min_thickness, int& natural_length) const; + void getPreferredLength(int& min_length, int& natural_length) const; + void getPreferredThicknessForLength(int length, int& min_thickness, int& natural_length) const; + void getPreferredLengthForThickness(int thickness, int& min_length, int& natural_length) const; + public: HistogramRGBArea(); ~HistogramRGBArea() override; void updateBackBuffer (int r, int g, int b, const Glib::ustring &profile = "", const Glib::ustring &profileW = ""); bool getShow (); + void setShow(bool show); void setParent (Gtk::Grid* p) { parent = p; }; void update (int val, int rh, int gh, int bh); - void updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, bool show); + void updateOptions (bool r, bool g, bool b, bool l, bool c, bool show); void on_realize() override; bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; bool on_button_press_event (GdkEventButton* event) override; void factorChanged (double newFactor); +}; + +class HistogramRGBAreaHori final : public HistogramRGBArea +{ private: + void drawBar(Cairo::RefPtr cc, double value, double max_value, int winw, int winh, double scale) override; + Gtk::SizeRequestMode get_request_mode_vfunc () const override; void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override; void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override; void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const override; void get_preferred_width_for_height_vfunc (int h, int &minimum_width, int &natural_width) const override; +}; +class HistogramRGBAreaVert final : public HistogramRGBArea +{ +private: + void drawBar(Cairo::RefPtr cc, double value, double max_value, int winw, int winh, double scale) override; + + Gtk::SizeRequestMode get_request_mode_vfunc () const override; + void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override; + void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override; + void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const override; + void get_preferred_width_for_height_vfunc (int h, int &minimum_width, int &natural_width) const override; }; class DrawModeListener @@ -122,7 +152,10 @@ class HistogramArea final : public Gtk::DrawingArea, public BackBuffer, private { public: typedef sigc::signal type_signal_factor_changed; + typedef sigc::signal SignalBrightnessChanged; + static constexpr float MIN_BRIGHT = 0.1; + static constexpr float MAX_BRIGHT = 3; private: IdleRegister idle_register; type_signal_factor_changed sigFactorChanged; @@ -130,26 +163,49 @@ private: protected: LUTu rhist, ghist, bhist, lhist, chist; LUTu rhistRaw, ghistRaw, bhistRaw, lhistRaw; //lhistRaw is unused? + int vectorscope_scale; + array2D vect_hc, vect_hs; + std::vector vect_hc_buffer, vect_hs_buffer; + bool vect_hc_buffer_dirty, vect_hs_buffer_dirty; + int waveform_scale; + array2D rwave, gwave, bwave, lwave; + std::vector parade_buffer_r; + std::vector parade_buffer_g; + std::vector parade_buffer_b; + bool parade_buffer_r_dirty, parade_buffer_g_dirty, parade_buffer_b_dirty; + std::vector wave_buffer; + std::vector wave_buffer_luma; + bool wave_buffer_dirty, wave_buffer_luma_dirty; bool valid; int drawMode; DrawModeListener *myDrawModeListener; + Options::ScopeType scopeType; int oldwidth, oldheight; + /// Intensity of waveform and vectorscope trace. + float trace_brightness; bool needRed, needGreen, needBlue, needLuma, needChroma; - bool rawMode; bool isPressed; double movingPosition; + bool needPointer; double padding = 5.0; HistogramAreaIdleHelper* haih; + int pointer_red, pointer_green, pointer_blue; + float pointer_a, pointer_b; + + SignalBrightnessChanged signal_brightness_changed; + public: explicit HistogramArea(DrawModeListener *fml = nullptr); ~HistogramArea() override; void updateBackBuffer (); + /// Update pointer values. Returns true if widget needs redrawing. + bool updatePointer(int r, int g, int b, const Glib::ustring &profile = "", const Glib::ustring &profileW = ""); void update( const LUTu& histRed, const LUTu& histGreen, @@ -158,19 +214,35 @@ public: const LUTu& histChroma, const LUTu& histRedRaw, const LUTu& histGreenRaw, - const LUTu& histBlueRaw + const LUTu& histBlueRaw, + int vectorscopeScale, + const array2D& vectorscopeHC, + const array2D& vectorscopeHS, + int waveformScale, + const array2D& waveformRed, + const array2D& waveformGreen, + const array2D& waveformBlue, + const array2D& waveformLuma ); - void updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, int mode); + void updateOptions (bool r, bool g, bool b, bool l, bool c, int mode, Options::ScopeType type, bool pointer); + bool updatePending(); void on_realize() override; bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; bool on_button_press_event (GdkEventButton* event) override; bool on_button_release_event (GdkEventButton* event) override; bool on_motion_notify_event (GdkEventMotion* event) override; + float getBrightness(void); + /** Set the trace brightness, with 1 being normal. */ + void setBrightness(float brightness); + SignalBrightnessChanged getBrighnessChangedSignal(void); type_signal_factor_changed signal_factor_changed(); private: void drawCurve(Cairo::RefPtr &cr, const LUTu & data, double scale, int hsize, int vsize); void drawMarks(Cairo::RefPtr &cr, const LUTu & data, double scale, int hsize, int & ui, int & oi); + void drawParade(Cairo::RefPtr &cr, int hsize, int vsize); + void drawVectorscope(Cairo::RefPtr &cr, int hsize, int vsize); + void drawWaveform(Cairo::RefPtr &cr, int hsize, int vsize); Gtk::SizeRequestMode get_request_mode_vfunc () const override; void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override; void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override; @@ -178,29 +250,48 @@ private: void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override; }; +class HistogramPanelListener +{ +public: + virtual void scopeTypeChanged(Options::ScopeType new_type) = 0; +}; + class HistogramPanel final : public Gtk::Grid, public PointerMotionListener, public DrawModeListener, public rtengine::NonCopyable { +private: + DelayedCall pointer_moved_delayed_call; protected: Gtk::Grid* gfxGrid; Gtk::Grid* buttonGrid; + Gtk::Box* persistentButtons; + Gtk::Box* optionButtons; HistogramArea* histogramArea; HistogramRGBArea* histogramRGBArea; + std::unique_ptr histogramRGBAreaHori; + std::unique_ptr histogramRGBAreaVert; Gtk::ToggleButton* showRed; Gtk::ToggleButton* showGreen; Gtk::ToggleButton* showBlue; Gtk::ToggleButton* showValue; - Gtk::ToggleButton* showRAW; Gtk::ToggleButton* showBAR; Gtk::ToggleButton* showChro; Gtk::Button* showMode; + Gtk::ToggleButton* scopeOptions; + Gtk::Scale* brightnessWidget; + + Gtk::RadioButton* scopeHistBtn; + Gtk::RadioButton* scopeHistRawBtn; + Gtk::RadioButton* scopeParadeBtn; + Gtk::RadioButton* scopeWaveBtn; + Gtk::RadioButton* scopeVectHcBtn; + Gtk::RadioButton* scopeVectHsBtn; Gtk::Image *redImage; Gtk::Image *greenImage; Gtk::Image *blueImage; Gtk::Image *valueImage; - Gtk::Image *rawImage; Gtk::Image *barImage; Gtk::Image *chroImage; @@ -208,7 +299,6 @@ protected: Gtk::Image *greenImage_g; Gtk::Image *blueImage_g; Gtk::Image *valueImage_g; - Gtk::Image *rawImage_g; Gtk::Image *barImage_g; Gtk::Image *chroImage_g; @@ -216,8 +306,14 @@ protected: Gtk::Image *mode1Image; Gtk::Image *mode2Image; + HistogramPanelListener* panel_listener; + + sigc::connection brightness_changed_connection; sigc::connection rconn; void setHistInvalid (); + void showRGBBar(); + void updateHistAreaOptions(); + void updateHistRGBAreaOptions(); public: @@ -232,9 +328,18 @@ public: const LUTu& histChroma, const LUTu& histRedRaw, const LUTu& histGreenRaw, - const LUTu& histBlueRaw) + const LUTu& histBlueRaw, + int vectorscopeScale, + const array2D& vectorscopeHC, + const array2D& vectorscopeHS, + int waveformScale, + const array2D& waveformRed, + const array2D& waveformGreen, + const array2D& waveformBlue, + const array2D& waveformLuma + ) { - histogramArea->update(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw); + histogramArea->update(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw, vectorscopeScale, vectorscopeHC, vectorscopeHS, waveformScale, waveformRed, waveformGreen, waveformBlue, waveformLuma); } // pointermotionlistener interface void pointerMoved (bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int x, int y, int r, int g, int b, bool isRaw = false) override; @@ -247,13 +352,19 @@ public: void green_toggled (); void blue_toggled (); void value_toggled (); - void raw_toggled (); void chro_toggled (); void bar_toggled (); void mode_released (); + void brightnessWidgetValueChanged(); + void brightnessUpdated(float brightness); + void scopeOptionsToggled(); + void type_selected(Gtk::RadioButton* button); + void type_changed (); void rgbv_toggled (); void resized (Gtk::Allocation& req); // drawModeListener interface void toggleButtonMode () override; + + void setPanelListener(HistogramPanelListener* listener); }; diff --git a/rtgui/iccprofilecreator.cc b/rtgui/iccprofilecreator.cc index c9639f70b..3f1ed4089 100644 --- a/rtgui/iccprofilecreator.cc +++ b/rtgui/iccprofilecreator.cc @@ -151,9 +151,7 @@ ICCProfileCreator::ICCProfileCreator(RTWindow *rtwindow) aGamma = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_GAMMA"), 1, 3.5, 0.00001, 2.4)); setExpandAlignProperties(aGamma, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); - if (aGamma->delay < options.adjusterMaxDelay) { - aGamma->delay = options.adjusterMaxDelay; - } + aGamma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); aGamma->show(); mainGrid->attach(*aGamma, 1, 3, 1, 1); //gamma @@ -161,9 +159,7 @@ ICCProfileCreator::ICCProfileCreator(RTWindow *rtwindow) aSlope = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_SLOPE"), 0, 15, 0.00001, 12.92310)); setExpandAlignProperties(aSlope, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); - if (aSlope->delay < options.adjusterMaxDelay) { - aSlope->delay = options.adjusterMaxDelay; - } + aSlope->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); aSlope->show(); mainGrid->attach(*aSlope, 1, 4, 1, 1); //slope @@ -328,7 +324,7 @@ ICCProfileCreator::ICCProfileCreator(RTWindow *rtwindow) close->signal_clicked().connect(sigc::mem_fun(*this, &ICCProfileCreator::closePressed)); get_action_area()->pack_start(*close); - //--------------- Show childrens + //--------------- Show children show_all_children(); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index 3e3c0508c..92827bf30 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -194,33 +194,29 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha wTRCHBox->pack_start(*wtrclab, Gtk::PACK_SHRINK); wTRC = Gtk::manage(new MyComboBoxText()); wTRCHBox->pack_start(*wTRC, Gtk::PACK_EXPAND_WIDGET); - wProfVBox->pack_start(*wTRCHBox, Gtk::PACK_EXPAND_WIDGET); + // wProfVBox->pack_start(*wTRCHBox, Gtk::PACK_EXPAND_WIDGET); wTRC->append(M("TP_ICM_WORKING_TRC_NONE")); wTRC->append(M("TP_ICM_WORKING_TRC_CUSTOM")); - wTRC->set_active(0); - wTRC->set_tooltip_text(M("TP_ICM_WORKING_TRC_TOOLTIP")); +// wTRC->set_active(0); +// wTRC->set_tooltip_text(M("TP_ICM_WORKING_TRC_TOOLTIP")); wGamma = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_TRC_GAMMA"), 0.40, 15.0, 0.001, 2.4)); wSlope = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_TRC_SLOPE"), 0., 150., 0.01, 12.92310)); - wProfVBox->pack_start(*wGamma, Gtk::PACK_SHRINK); - wGamma->show(); +// wProfVBox->pack_start(*wGamma, Gtk::PACK_SHRINK); +// wGamma->show(); - wProfVBox->pack_start(*wSlope, Gtk::PACK_SHRINK); - wSlope->show(); +// wProfVBox->pack_start(*wSlope, Gtk::PACK_SHRINK); +// wSlope->show(); wGamma->setAdjusterListener(this); wSlope->setAdjusterListener(this); - if (wGamma->delay < options.adjusterMaxDelay) { - wGamma->delay = options.adjusterMaxDelay; - } + wGamma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - if (wSlope->delay < options.adjusterMaxDelay) { - wSlope->delay = options.adjusterMaxDelay; - } + wSlope->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); wFrame->add(*wProfVBox); @@ -428,8 +424,8 @@ void ICMPanel::updateDCP(int dcpIlluminant, Glib::ustring dcp_name) if (illuminants.will_interpolate) { if (dcpTemperatures[0] != illuminants.temperature_1 || dcpTemperatures[1] != illuminants.temperature_2) { char tempstr1[64], tempstr2[64]; - sprintf(tempstr1, "%.0fK", illuminants.temperature_1); - sprintf(tempstr2, "%.0fK", illuminants.temperature_2); + snprintf(tempstr1, sizeof(tempstr1), "%.0fK", illuminants.temperature_1); + snprintf(tempstr2, sizeof(tempstr2), "%.0fK", illuminants.temperature_2); int curr_active = dcpIll->get_active_row_number(); dcpIll->remove_all(); dcpIll->append(M("TP_ICM_DCPILLUMINANT_INTERPOLATED")); diff --git a/rtgui/lensgeomlistener.h b/rtgui/lensgeomlistener.h index 810b7ed98..b9979f9a2 100644 --- a/rtgui/lensgeomlistener.h +++ b/rtgui/lensgeomlistener.h @@ -18,6 +18,15 @@ */ #pragma once +#include +#include + +namespace rtengine +{ +class ControlLine; +class ProcEvent; +} + class LensGeomListener { public: @@ -25,5 +34,6 @@ public: virtual void straightenRequested () = 0; virtual void autoCropRequested () = 0; virtual double autoDistorRequested () = 0; - virtual void autoPerspRequested (bool corr_pitch, bool corr_yaw, double& rot, double& pitch, double& yaw) = 0; + virtual void autoPerspRequested (bool corr_pitch, bool corr_yaw, double& rot, double& pitch, double& yaw, const std::vector *lines = nullptr) = 0; + virtual void updateTransformPreviewRequested (rtengine::ProcEvent event, bool render_perspective) = 0; }; diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index 883ef9aa2..5ca46bc99 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -311,6 +311,7 @@ void Locallab::read(const rtengine::procparams::ProcParams* pp, const ParamsEdit r->balanh = pp->locallab.spots.at(i).balanh; r->colorde = pp->locallab.spots.at(i).colorde; r->colorscope = pp->locallab.spots.at(i).colorscope; + r->hishow = pp->locallab.spots.at(i).hishow; r->activ = pp->locallab.spots.at(i).activ; r->avoid = pp->locallab.spots.at(i).avoid; r->blwh = pp->locallab.spots.at(i).blwh; @@ -486,6 +487,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited r->balanh = newSpot->balanh; r->colorde = newSpot->colorde; r->colorscope = newSpot->colorscope; + r->hishow = newSpot->hishow; r->activ = newSpot->activ; r->avoid = newSpot->avoid; r->blwh = newSpot->blwh; @@ -918,6 +920,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited pp->locallab.spots.at(pp->locallab.selspot).balanh = r->balanh; pp->locallab.spots.at(pp->locallab.selspot).colorde = r->colorde; pp->locallab.spots.at(pp->locallab.selspot).colorscope = r->colorscope; + pp->locallab.spots.at(pp->locallab.selspot).hishow = r->hishow; pp->locallab.spots.at(pp->locallab.selspot).activ = r->activ; pp->locallab.spots.at(pp->locallab.selspot).avoid = r->avoid; pp->locallab.spots.at(pp->locallab.selspot).blwh = r->blwh; @@ -1014,10 +1017,10 @@ void Locallab::minmaxChanged(const std::vector &minmax, int } } -void Locallab::logencodChanged(const float blackev, const float whiteev, const float sourceg, const float targetg) +void Locallab::logencodChanged(const float blackev, const float whiteev, const float sourceg, const float sourceab, const float targetg) { // Update Locallab Log Encoding accordingly - explog->updateAutocompute(blackev, whiteev, sourceg, targetg); + explog->updateAutocompute(blackev, whiteev, sourceg, sourceab, targetg); } void Locallab::refChanged(const std::vector &ref, int selspot) diff --git a/rtgui/locallab.h b/rtgui/locallab.h index 44e408d49..a6491ebd6 100644 --- a/rtgui/locallab.h +++ b/rtgui/locallab.h @@ -141,7 +141,7 @@ public: void minmaxChanged(const std::vector &minmax, int selspot) override; // Locallab Log Encoding autocompute function - void logencodChanged(const float blackev, const float whiteev, const float sourceg, const float targetg) override; + void logencodChanged(const float blackev, const float whiteev, const float sourceg, const float sourceab, const float targetg) override; // Locallab tools mask background management function void refChanged(const std::vector &ref, int selspot) override; diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc index 42574d15c..68908b33a 100644 --- a/rtgui/locallabtools.cc +++ b/rtgui/locallabtools.cc @@ -2,8 +2,7 @@ * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath frame - * - * +fft * * 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 @@ -461,6 +460,7 @@ LocallabColor::LocallabColor(): labgridmerg(Gtk::manage(new LabGrid(EvLocallabLabGridmergValue, M("TP_LOCALLAB_LABGRID_VALUES"), false))), merlucol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MERLUCOL"), 0.0, 100.0, 0.5, 32., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), expmaskcol(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWC")))), + mergecolFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_MERGECOLFRA")))), showmaskcolMethod(Gtk::manage(new MyComboBoxText())), showmaskcolMethodinv(Gtk::manage(new MyComboBoxText())), enaColorMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), @@ -476,6 +476,7 @@ LocallabColor::LocallabColor(): contcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTCOL"), 0., 200., 0.5, 0.))), blurcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURCOL"), 0.2, 100., 0.5, 0.2))), blendmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + toolcolFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK")))), radmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), 0.0, 100.0, 0.1, 0.))), lapmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), chromaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), @@ -757,7 +758,7 @@ LocallabColor::LocallabColor(): LLmaskcolshapewav->setIdentityValue(0.); LLmaskcolshapewav->setResetCurve(FlatCurveType(defSpot.LLmaskcolcurvewav.at(0)), defSpot.LLmaskcolcurvewav); - LLmaskcolshapewav->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); +// LLmaskcolshapewav->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); mask2CurveEditorGwav->curveListComplete(); @@ -830,7 +831,6 @@ LocallabColor::LocallabColor(): mask7Box->pack_start(*mask7); expmaskcol1->add(*mask7Box, false); pack_start(*expmaskcol1, false, false); - Gtk::Frame* const mergecolFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_MERGECOLFRA"))); mergecolFrame->set_label_align(0.025, 0.5); ToolParamBlock* const maskcolBox = Gtk::manage(new ToolParamBlock()); maskcolBox->pack_start(*showmaskcolMethod, Gtk::PACK_SHRINK, 4); @@ -849,7 +849,7 @@ LocallabColor::LocallabColor(): blurFrame->add(*blurmBox); maskcolBox->pack_start(*blurFrame, Gtk::PACK_SHRINK, 0); maskcolBox->pack_start(*blendmaskcol, Gtk::PACK_SHRINK, 0); - Gtk::Frame* const toolcolFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK"))); +// Gtk::Frame* const toolcolFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK"))); toolcolFrame->set_label_align(0.025, 0.5); ToolParamBlock* const toolcolBox = Gtk::manage(new ToolParamBlock()); toolcolBox->pack_start(*radmaskcol, Gtk::PACK_SHRINK, 0); @@ -919,6 +919,12 @@ void LocallabColor::updateAdviceTooltips(const bool showTooltips) if (showTooltips) { lumFrame->set_tooltip_text(M("TP_LOCALLAB_EXPCOLOR_TOOLTIP")); lightness->set_tooltip_text(M("TP_LOCALLAB_LIGHTN_TOOLTIP")); + gridMethod->set_tooltip_text(M("TP_LOCALLAB_GRIDMETH_TOOLTIP")); + strengthgrid->set_tooltip_text(M("TP_LOCALLAB_STRENGRID_TOOLTIP")); + blurcolde->set_tooltip_text(M("TP_LOCALLAB_BLURCOLDE_TOOLTIP")); + softradiuscol->set_tooltip_text(M("TP_LOCALLAB_SOFTRADIUSCOL_TOOLTIP")); + expgradcol->set_tooltip_text(M("TP_LOCALLAB_EXPGRADCOL_TOOLTIP")); + rgbCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_RGBCURVE_TOOLTIP")); sensi->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); structcol->set_tooltip_text(M("TP_LOCALLAB_STRUCT_TOOLTIP")); strcol->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); @@ -938,31 +944,62 @@ void LocallabColor::updateAdviceTooltips(const bool showTooltips) blurFrame->set_tooltip_text(M("TP_LOCALLAB_BLURMASK_TOOLTIP")); blendmaskcol->set_tooltip_text(M("TP_LOCALLAB_BLENDMASK_TOOLTIP")); radmaskcol->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); - lapmaskcol->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); maskHCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_HHMASK_TOOLTIP")); mask2CurveEditorG->set_tooltip_text(M("TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP")); Lmaskshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); mask2CurveEditorGwav->set_tooltip_text(M("TP_LOCALLAB_WAVMASK_TOOLTIP")); LLmaskcolshapewav->setTooltip(M("TP_LOCALLAB_LMASK_LEVEL_TOOLTIP")); + mergecolFrame->set_tooltip_markup(M("TP_LOCALLAB_MERGECOLFRMASK_TOOLTIP")); + maskCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + strumaskcol->set_tooltip_text(M("TP_LOCALLAB_STRUSTRMASK_TOOLTIP")); + toolcol->set_tooltip_text(M("TP_LOCALLAB_TOOLMASK_TOOLTIP")); + toolcolFrame->set_tooltip_text(M("TP_LOCALLAB_TOOLCOLFRMASK_TOOLTIP")); + fftColorMask->set_tooltip_text(M("TP_LOCALLAB_FFTMASK_TOOLTIP")); + gammaskcol->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromaskcol->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slomaskcol->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + shadmaskcol->set_tooltip_text(M("TP_LOCALLAB_SHADMASK_TOOLTIP")); + contcol->set_tooltip_text(M("TP_LOCALLAB_CONTTHMASK_TOOLTIP")); + blurcol->set_tooltip_text(M("TP_LOCALLAB_BLURRMASK_TOOLTIP")); + lapmaskcol->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); + csThresholdcol->set_tooltip_text(M("TP_LOCALLAB_WAVEMASK_LEVEL_TOOLTIP")); } else { lumFrame->set_tooltip_text(""); lightness->set_tooltip_text(""); + gridMethod->set_tooltip_text(""); + strengthgrid->set_tooltip_text(""); + blurcolde->set_tooltip_text(""); + softradiuscol->set_tooltip_text(""); + expgradcol->set_tooltip_text(""); + rgbCurveEditorG->set_tooltip_text(""); sensi->set_tooltip_text(""); structcol->set_tooltip_text(""); strcol->set_tooltip_text(""); angcol->set_tooltip_text(""); - qualitycurveMethod->set_tooltip_text(""); + qualitycurveMethod->set_tooltip_markup(""); special->set_tooltip_text(""); expmaskcol1->set_tooltip_text(""); + maskCurveEditorG->set_tooltip_markup(""); mercol->set_tooltip_text(""); opacol->set_tooltip_text(""); conthrcol->set_tooltip_text(""); gridmerFrame->set_tooltip_text(""); - expmaskcol->set_tooltip_text(""); + expmaskcol->set_tooltip_markup(""); + mergecolFrame->set_tooltip_markup(""); CCmaskshape->setTooltip(""); LLmaskshape->setTooltip(""); HHmaskshape->setTooltip(""); struFrame->set_tooltip_text(""); + strumaskcol->set_tooltip_text(""); + toolcol->set_tooltip_text(""); + toolcolFrame->set_tooltip_text(""); + fftColorMask->set_tooltip_text(""); + gammaskcol->set_tooltip_text(""); + chromaskcol->set_tooltip_text(""); + slomaskcol->set_tooltip_text(""); + shadmaskcol->set_tooltip_text(""); + contcol->set_tooltip_text(""); + blurcol->set_tooltip_text(""); blurFrame->set_tooltip_text(""); blendmaskcol->set_tooltip_text(""); radmaskcol->set_tooltip_text(""); @@ -972,6 +1009,7 @@ void LocallabColor::updateAdviceTooltips(const bool showTooltips) Lmaskshape->setTooltip(""); mask2CurveEditorGwav->set_tooltip_text(""); LLmaskcolshapewav->setTooltip(""); + csThresholdcol->set_tooltip_text(""); } } @@ -2311,13 +2349,16 @@ LocallabExposure::LocallabExposure(): // Exposure specific widgets expMethod(Gtk::manage(new MyComboBoxText())), - pdeFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_PDEFRA")))), +// pdeFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_PDEFRA")))), + exppde(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_PDEFRA")))), laplacexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPLACEXP"), 0.0, 100.0, 0.1, 0.))), - linear(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LINEAR"), 0., 1., 0.01, 0.05))), + linear(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LINEAR"), 0.01, 1., 0.01, 0.05))), balanexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BALANEXP"), 0.5, 1.5, 0.01, 1.0))), gamm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMM"), 0.2, 1.3, 0.01, 0.4))), + labelexpmethod(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_NOISEMETH") + ":"))), exnoiseMethod(Gtk::manage(new MyComboBoxText())), - fatFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_FATFRA")))), +// fatFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_FATFRA")))), + expfat(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_FATFRA")))), fatamount(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATAMOUNT"), 1., 100., 1., 1.))), fatdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATDETAIL"), -100., 300., 1., 0.))), fatlevel(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATLEVEL"), 0.25, 2.5, 0.05, 1.))), @@ -2369,7 +2410,9 @@ LocallabExposure::LocallabExposure(): expMethod->set_active(0); expMethodConn = expMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabExposure::expMethodChanged)); - pdeFrame->set_label_align(0.025, 0.5); +// pdeFrame->set_label_align(0.025, 0.5); + setExpandAlignProperties(exppde, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + setExpandAlignProperties(expfat, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); laplacexp->setAdjusterListener(this); @@ -2385,7 +2428,7 @@ LocallabExposure::LocallabExposure(): exnoiseMethod->set_active(0); exnoiseMethodConn = exnoiseMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabExposure::exnoiseMethodChanged)); - fatFrame->set_label_align(0.025, 0.5); + // fatFrame->set_label_align(0.025, 0.5); fatamount->setAdjusterListener(this); @@ -2505,26 +2548,30 @@ LocallabExposure::LocallabExposure(): mask2expCurveEditorG->curveListComplete(); // Add Color & Light specific widgets to GUI - pack_start(*expMethod); +// pack_start(*expMethod); ToolParamBlock* const pdeBox = Gtk::manage(new ToolParamBlock()); pdeBox->pack_start(*laplacexp); pdeBox->pack_start(*linear); pdeBox->pack_start(*balanexp); pdeBox->pack_start(*gamm); Gtk::HBox* const ctboxexpmethod = Gtk::manage(new Gtk::HBox()); - Gtk::Label* const labelexpmethod = Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_NOISEMETH") + ":")); +// Gtk::Label* const labelexpmethod = Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_NOISEMETH") + ":")); ctboxexpmethod->pack_start(*labelexpmethod, Gtk::PACK_SHRINK, 4); ctboxexpmethod->pack_start(*exnoiseMethod); pdeBox->pack_start(*ctboxexpmethod); - pdeFrame->add(*pdeBox); - pack_start(*pdeFrame); + exppde->add(*pdeBox, false); +// pdeFrame->add(*pdeBox); +// pack_start(*pdeFrame); + pack_start(*exppde); ToolParamBlock* const fatBox = Gtk::manage(new ToolParamBlock()); fatBox->pack_start(*fatamount); fatBox->pack_start(*fatdetail); fatBox->pack_start(*fatlevel); fatBox->pack_start(*fatanchor); - fatFrame->add(*fatBox); - pack_start(*fatFrame); +// fatFrame->add(*fatBox); + expfat->add(*fatBox, false); +// pack_start(*fatFrame); + pack_start(*expfat); pack_start(*expcomp); pack_start(*sensiex); pack_start(*structexp); @@ -2602,14 +2649,18 @@ void LocallabExposure::updateAdviceTooltips(const bool showTooltips) { if (showTooltips) { exp->set_tooltip_text(M("TP_LOCALLAB_EXPOSURE_TOOLTIP")); - expMethod->set_tooltip_text(M("TP_LOCALLAB_EXPMETHOD_TOOLTIP")); - pdeFrame->set_tooltip_text(M("TP_LOCALLAB_PDEFRAME_TOOLTIP")); +// expMethod->set_tooltip_text(M("TP_LOCALLAB_EXPMETHOD_TOOLTIP")); +// pdeFrame->set_tooltip_text(M("TP_LOCALLAB_PDEFRAME_TOOLTIP")); + exppde->set_tooltip_text(M("TP_LOCALLAB_PDEFRAME_TOOLTIP")); + blurexpde->set_tooltip_text(M("TP_LOCALLAB_BLURCOLDE_TOOLTIP")); laplacexp->set_tooltip_text(M("TP_LOCALLAB_EXPLAP_TOOLTIP")); linear->set_tooltip_text(M("TP_LOCALLAB_EXPLAPLIN_TOOLTIP")); balanexp->set_tooltip_text(M("TP_LOCALLAB_EXPLAPBAL_TOOLTIP")); gamm->set_tooltip_text(M("TP_LOCALLAB_EXPLAPGAMM_TOOLTIP")); + labelexpmethod->set_tooltip_text(M("TP_LOCALLAB_EXPNOISEMETHOD_TOOLTIP")); exnoiseMethod->set_tooltip_text(M("TP_LOCALLAB_EXPNOISEMETHOD_TOOLTIP")); - fatFrame->set_tooltip_text(M("TP_LOCALLAB_FATFRAME_TOOLTIP")); +// fatFrame->set_tooltip_text(M("TP_LOCALLAB_FATFRAME_TOOLTIP")); + expfat->set_tooltip_text(M("TP_LOCALLAB_FATFRAME_TOOLTIP")); expcomp->set_tooltip_text(M("TP_LOCALLAB_EXPCOMP_TOOLTIP")); sensiex->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); structexp->set_tooltip_text(M("TP_LOCALLAB_STRUCT_TOOLTIP")); @@ -2622,42 +2673,53 @@ void LocallabExposure::updateAdviceTooltips(const bool showTooltips) HHmaskexpshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); blendmaskexp->set_tooltip_text(M("TP_LOCALLAB_BLENDMASK_TOOLTIP")); radmaskexp->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); - lapmaskexp->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + lapmaskexp->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); strmaskexp->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); mask2expCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP")); Lmaskexpshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + maskexpCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + gammaskexp->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromaskexp->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slomaskexp->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + lapmaskexp->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); } else { exp->set_tooltip_text(""); - expMethod->set_tooltip_text(""); - pdeFrame->set_tooltip_text(""); + exppde->set_tooltip_text(""); + blurexpde->set_tooltip_text(""); laplacexp->set_tooltip_text(""); linear->set_tooltip_text(""); balanexp->set_tooltip_text(""); gamm->set_tooltip_text(""); + labelexpmethod->set_tooltip_text(""); exnoiseMethod->set_tooltip_text(""); - fatFrame->set_tooltip_text(""); + expfat->set_tooltip_text(""); expcomp->set_tooltip_text(""); sensiex->set_tooltip_text(""); structexp->set_tooltip_text(""); expchroma->set_tooltip_text(""); shapeexpos->setTooltip(""); strexp->set_tooltip_text(""); - expmaskexp->set_tooltip_text(""); + expmaskexp->set_tooltip_markup(""); CCmaskexpshape->setTooltip(""); LLmaskexpshape->setTooltip(""); HHmaskexpshape->setTooltip(""); blendmaskexp->set_tooltip_text(""); radmaskexp->set_tooltip_text(""); - lapmaskexp->set_tooltip_text(""); strmaskexp->set_tooltip_text(""); mask2expCurveEditorG->set_tooltip_text(""); Lmaskexpshape->setTooltip(""); + gammaskexp->set_tooltip_text(""); + chromaskexp->set_tooltip_text(""); + slomaskexp->set_tooltip_text(""); + lapmaskexp->set_tooltip_text(""); } } void LocallabExposure::setDefaultExpanderVisibility() { exptoolexp->set_expanded(false); + exppde->set_expanded(false); + expfat->set_expanded(false); expgradexp->set_expanded(false); expmaskexp->set_expanded(false); } @@ -2704,13 +2766,13 @@ void LocallabExposure::read(const rtengine::procparams::ProcParams* pp, const Pa exp->set_visible(spot.visiexpose); exp->setEnabled(spot.expexpose); complexity->set_active(spot.complexexpose); - +/* if (spot.expMethod == "std") { expMethod->set_active(0); } else if (spot.expMethod == "pde") { expMethod->set_active(1); } - +*/ laplacexp->setValue(spot.laplacexp); linear->setValue(spot.linear); balanexp->setValue(spot.balanexp); @@ -2787,13 +2849,13 @@ void LocallabExposure::write(rtengine::procparams::ProcParams* pp, ParamsEdited* spot.expexpose = exp->getEnabled(); spot.visiexpose = exp->get_visible(); spot.complexexpose = complexity->get_active_row_number(); - +/* if (expMethod->get_active_row_number() == 0) { spot.expMethod = "std"; } else if (expMethod->get_active_row_number() == 1) { spot.expMethod = "pde"; } - +*/ spot.laplacexp = laplacexp->getValue(); spot.linear = linear->getValue(); spot.balanexp = balanexp->getValue(); @@ -3395,19 +3457,24 @@ void LocallabExposure::updateExposureGUI1() } void LocallabExposure::updateExposureGUI2() -{ +{ /* // Update exposure GUI according to expMethod value if (expMethod->get_active_row_number() == 0) { - pdeFrame->hide(); - fatFrame->hide(); +// pdeFrame->hide(); +// fatFrame->hide(); + exppde->hide(); + expfat->hide(); softradiusexp->set_sensitive(true); sensiex->set_sensitive(true); } else if (expMethod->get_active_row_number() == 1) { - pdeFrame->show(); - fatFrame->show(); + // pdeFrame->show(); + // fatFrame->show(); + exppde->show(); + expfat->show(); softradiusexp->set_sensitive(false); sensiex->set_sensitive(true); } + */ } void LocallabExposure::updateExposureGUI3() @@ -3490,7 +3557,7 @@ LocallabShadow::LocallabShadow(): blurSHde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))), gamFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GAMFRA")))), gamSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMSH"), 0.25, 15.0, 0.01, 2.4))), - sloSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOSH"), 0.0, 150.0, 0.01, 12.92))), + sloSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOSH"), 0.0, 500.0, 0.01, 12.92))), expgradsh(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPGRAD")))), strSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4., 4., 0.05, 0.))), angSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), @@ -3544,6 +3611,7 @@ LocallabShadow::LocallabShadow(): blurSHde->setAdjusterListener(this); gamSH->setAdjusterListener(this); + sloSH->setLogScale(16, 0); sloSH->setAdjusterListener(this); @@ -3709,25 +3777,43 @@ void LocallabShadow::updateAdviceTooltips(const bool showTooltips) sloSH->set_tooltip_text(M("TP_LOCALLAB_SHTRC_TOOLTIP")); strSH->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); expmasksh->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + blurSHde->set_tooltip_text(M("TP_LOCALLAB_BLURCOLDE_TOOLTIP")); CCmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); LLmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); HHmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); blendmaskSH->set_tooltip_text(M("TP_LOCALLAB_BLENDMASK_TOOLTIP")); radmaskSH->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); - lapmaskSH->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); mask2SHCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP")); LmaskSHshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + maskSHCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + gammaskSH->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromaskSH->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slomaskSH->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + lapmaskSH->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); + /* + highlights->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + h_tonalwidth->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + shadows->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + s_tonalwidth->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + sh_radius->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + */ + highlights->set_tooltip_text(""); + h_tonalwidth->set_tooltip_text(""); + shadows->set_tooltip_text(""); + s_tonalwidth->set_tooltip_text(""); + sh_radius->set_tooltip_text(""); + } else { exp->set_tooltip_text(""); for (const auto multiplier : multipliersh) { multiplier->set_tooltip_text(""); } - gamSH->set_tooltip_text(""); sloSH->set_tooltip_text(""); strSH->set_tooltip_text(""); - expmasksh->set_tooltip_text(""); + blurSHde->set_tooltip_text(""); + expmasksh->set_tooltip_markup(""); CCmaskSHshape->setTooltip(""); LLmaskSHshape->setTooltip(""); HHmaskSHshape->setTooltip(""); @@ -3736,6 +3822,16 @@ void LocallabShadow::updateAdviceTooltips(const bool showTooltips) lapmaskSH->set_tooltip_text(""); mask2SHCurveEditorG->set_tooltip_text(""); LmaskSHshape->setTooltip(""); + maskSHCurveEditorG->set_tooltip_markup(""); + gammaskSH->set_tooltip_text(""); + chromaskSH->set_tooltip_text(""); + slomaskSH->set_tooltip_text(""); + highlights->set_tooltip_text(""); + h_tonalwidth->set_tooltip_text(""); + shadows->set_tooltip_text(""); + s_tonalwidth->set_tooltip_text(""); + sh_radius->set_tooltip_text(""); + } } @@ -4609,17 +4705,55 @@ void LocallabVibrance::updateAdviceTooltips(const bool showTooltips) blendmaskvib->set_tooltip_text(M("TP_LOCALLAB_BLENDMASK_TOOLTIP")); mask2vibCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP")); Lmaskvibshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + maskvibCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + gammaskvib->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromaskvib->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slomaskvib->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + lapmaskvib->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); +/* + saturated->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + pastels->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + psThreshold->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + protectSkins->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + avoidColorShift->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + pastSatTog->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + sensiv->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + curveEditorGG->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); +*/ + + saturated->set_tooltip_text(""); + pastels->set_tooltip_text(""); + psThreshold->set_tooltip_text(""); + protectSkins->set_tooltip_text(""); + avoidColorShift->set_tooltip_text(""); + pastSatTog->set_tooltip_text(""); + sensiv->set_tooltip_text(""); + curveEditorGG->set_tooltip_text(""); + } else { exp->set_tooltip_text(""); warm->set_tooltip_text(""); strvib->set_tooltip_text(""); - expmaskvib->set_tooltip_text(""); + expmaskvib->set_tooltip_markup(""); CCmaskvibshape->setTooltip(""); LLmaskvibshape->setTooltip(""); HHmaskvibshape->setTooltip(""); blendmaskvib->set_tooltip_text(""); mask2vibCurveEditorG->set_tooltip_text(""); Lmaskvibshape->setTooltip(""); + maskvibCurveEditorG->set_tooltip_markup(""); + gammaskvib->set_tooltip_text(""); + chromaskvib->set_tooltip_text(""); + slomaskvib->set_tooltip_text(""); + lapmaskvib->set_tooltip_text(""); + saturated->set_tooltip_text(""); + pastels->set_tooltip_text(""); + psThreshold->set_tooltip_text(""); + protectSkins->set_tooltip_text(""); + avoidColorShift->set_tooltip_text(""); + pastSatTog->set_tooltip_text(""); + sensiv->set_tooltip_text(""); + curveEditorGG->set_tooltip_text(""); } } @@ -5278,11 +5412,14 @@ void LocallabSoft::updateAdviceTooltips(const bool showTooltips) showmasksoftMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKSOFT_TOOLTIP")); streng->set_tooltip_text(M("TP_LOCALLAB_ORRETISTREN_TOOLTIP")); laplace->set_tooltip_text(M("TP_LOCALLAB_ORRETILAP_TOOLTIP")); + sensisf->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + } else { exp->set_tooltip_text(""); - showmasksoftMethod->set_tooltip_text(""); + showmasksoftMethod->set_tooltip_markup(""); streng->set_tooltip_text(""); laplace->set_tooltip_text(""); + sensisf->set_tooltip_text(""); } } @@ -5614,11 +5751,13 @@ LocallabBlur::LocallabBlur(): guidbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GUIDBL"), 0, 1000, 1, 0))), strbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRBL"), 0, 100, 1, 50))), epsbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_EPSBL"), -10, 10, 1, 0))), - sensibn(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIBN"), 0, 100, 1, 40))), + sensibn(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 40))), blurMethod(Gtk::manage(new MyComboBoxText())), + invbl(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVBL")))), chroMethod(Gtk::manage(new MyComboBoxText())), activlum(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ACTIV")))), expdenoise(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI_EXP")))), + quamethod(Gtk::manage(new MyComboBoxText())), LocalcurveEditorwavden(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVDEN"))), wavshapeden(static_cast(LocalcurveEditorwavden->addCurve(CT_Flat, "", nullptr, false, false))), noiselumf0(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINEZERO"), MINCHRO, MAXCHRO, 0.01, 0.))), @@ -5633,7 +5772,7 @@ LocallabBlur::LocallabBlur(): detailthr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DETAILTHR"), 0, 100, 1, 0))), adjblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ADJ"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-yellow-small.png")), Gtk::manage(new RTImage("circle-red-green-small.png"))))), bilateral(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BILATERAL"), 0, 100, 1, 0))), - sensiden(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIDEN"), 0, 100, 1, 60))), + sensiden(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 60))), expmaskbl(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWPLUS")))), showmaskblMethod(Gtk::manage(new MyComboBoxText())), showmaskblMethodtyp(Gtk::manage(new MyComboBoxText())), @@ -5644,6 +5783,7 @@ LocallabBlur::LocallabBlur(): HHmaskblshape(static_cast(maskblCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), strumaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUMASKCOL"), 0., 200., 0.1, 0.))), toolbl(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_TOOLCOL")))), + toolblFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK")))), blendmaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), radmaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), 0.0, 100.0, 0.1, 0.))), lapmaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), @@ -5656,6 +5796,7 @@ LocallabBlur::LocallabBlur(): Lmaskblshape(static_cast(mask2blCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), mask2blCurveEditorGwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), LLmaskblshapewav(static_cast(mask2blCurveEditorGwav->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + quaHBox(Gtk::manage(new Gtk::HBox())), csThresholdblur(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))) { const LocallabParams::LocallabSpot defSpot; @@ -5670,6 +5811,7 @@ LocallabBlur::LocallabBlur(): blMethodConn = blMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::blMethodChanged)); fftwblConn = fftwbl->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::fftwblChanged)); + invblConn = invbl->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::invblChanged)); radius->setAdjusterListener(this); @@ -5717,6 +5859,14 @@ LocallabBlur::LocallabBlur(): setExpandAlignProperties(expdenoise, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + quamethod->append(M("TP_WAVELET_QUACONSER")); + quamethod->append(M("TP_WAVELET_QUAAGRES")); + quamethodconn = quamethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::quamethodChanged)); + Gtk::Label* const quaLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_DENQUA") + ":")); + quaHBox->pack_start(*quaLabel, Gtk::PACK_SHRINK, 4); + quaHBox->pack_start(*quamethod); + LocalcurveEditorwavden->setCurveListener(this); wavshapeden->setIdentityValue(0.); @@ -5832,7 +5982,7 @@ LocallabBlur::LocallabBlur(): ToolParamBlock* const grainBox = Gtk::manage(new ToolParamBlock()); grainBox->pack_start(*isogr); grainBox->pack_start(*strengr); - grainBox->pack_start(*scalegr); +// grainBox->pack_start(*scalegr); grainFrame->add(*grainBox); blnoisebox->pack_start(*grainFrame); blnoisebox->pack_start(*medMethod); @@ -5841,7 +5991,8 @@ LocallabBlur::LocallabBlur(): blnoisebox->pack_start(*strbl); blnoisebox->pack_start(*epsbl); blnoisebox->pack_start(*sensibn); - blnoisebox->pack_start(*blurMethod); +// blnoisebox->pack_start(*blurMethod); + blnoisebox->pack_start(*invbl); blnoisebox->pack_start(*chroMethod); // blnoisebox->pack_start(*activlum); expblnoise->add(*blnoisebox, false); @@ -5849,6 +6000,7 @@ LocallabBlur::LocallabBlur(): ToolParamBlock* const denoisebox = Gtk::manage(new ToolParamBlock()); Gtk::Frame* const wavFrame = Gtk::manage(new Gtk::Frame()); ToolParamBlock* const wavBox = Gtk::manage(new ToolParamBlock()); + wavBox->pack_start(*quaHBox); wavBox->pack_start(*LocalcurveEditorwavden, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor // wavBox->pack_start(*noiselumf0); // wavBox->pack_start(*noiselumf); @@ -5877,7 +6029,6 @@ LocallabBlur::LocallabBlur(): Gtk::HSeparator* const separatorstrubl = Gtk::manage(new Gtk::HSeparator()); maskblBox->pack_start(*separatorstrubl, Gtk::PACK_SHRINK, 2); maskblBox->pack_start(*blendmaskbl, Gtk::PACK_SHRINK, 0); - Gtk::Frame* const toolblFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK"))); toolblFrame->set_label_align(0.025, 0.5); ToolParamBlock* const toolblBox = Gtk::manage(new ToolParamBlock()); toolblBox->pack_start(*radmaskbl, Gtk::PACK_SHRINK, 0); @@ -5926,10 +6077,29 @@ void LocallabBlur::updateAdviceTooltips(const bool showTooltips) if (showTooltips) { expblnoise->set_tooltip_markup(M("TP_LOCALLAB_BLUMETHOD_TOOLTIP")); radius->set_tooltip_text(M("TP_LOCALLAB_RADIUS_TOOLTIP")); - sensibn->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); + strength->set_tooltip_text(M("TP_LOCALLAB_NOISE_TOOLTIP")); + grainFrame->set_tooltip_text(M("TP_LOCALLAB_GRAIN_TOOLTIP")); + sensibn->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + medMethod->set_tooltip_text(M("TP_LOCALLAB_MEDIAN_TOOLTIP")); + itera->set_tooltip_text(M("TP_LOCALLAB_MEDIANITER_TOOLTIP")); + fftwbl->set_tooltip_text(M("TP_LOCALLAB_FFTMASK_TOOLTIP")); + guidbl->set_tooltip_text(M("TP_LOCALLAB_GUIDBL_TOOLTIP")); + strbl->set_tooltip_text(M("TP_LOCALLAB_GUIDSTRBL_TOOLTIP")); + epsbl->set_tooltip_text(M("TP_LOCALLAB_GUIDEPSBL_TOOLTIP")); blurMethod->set_tooltip_markup(M("TP_LOCALLAB_BLMETHOD_TOOLTIP")); + invbl->set_tooltip_markup(M("TP_LOCALLAB_INVBL_TOOLTIP")); expdenoise->set_tooltip_markup(M("TP_LOCALLAB_DENOI_TOOLTIP")); + quamethod->set_tooltip_markup(M("TP_LOCALLAB_DENOIQUA_TOOLTIP")); wavshapeden->setTooltip(M("TP_LOCALLAB_WASDEN_TOOLTIP")); + LocalcurveEditorwavden->setTooltip(M("TP_LOCALLAB_WASDEN_TOOLTIP")); + noiselequal->set_tooltip_text(M("TP_LOCALLAB_DENOIEQUAL_TOOLTIP")); + noiselumdetail->set_tooltip_text(M("TP_LOCALLAB_DENOILUMDETAIL_TOOLTIP")); + noisechrof->set_tooltip_text(M("TP_LOCALLAB_DENOICHROF_TOOLTIP")); + noisechroc->set_tooltip_text(M("TP_LOCALLAB_DENOICHROC_TOOLTIP")); + noisechrodetail->set_tooltip_text(M("TP_LOCALLAB_DENOICHRODET_TOOLTIP")); + detailthr->set_tooltip_text(M("TP_LOCALLAB_DENOITHR_TOOLTIP")); + adjblur->set_tooltip_text(M("TP_LOCALLAB_DENOIEQUALCHRO_TOOLTIP")); + bilateral->set_tooltip_text(M("TP_LOCALLAB_DENOIBILAT_TOOLTIP")); noiselumc->set_tooltip_text(M("TP_LOCALLAB_NOISECHROC_TOOLTIP")); expmaskbl->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); showmaskblMethodtyp->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKTYP_TOOLTIP")); @@ -5941,16 +6111,50 @@ void LocallabBlur::updateAdviceTooltips(const bool showTooltips) lapmaskbl->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); Lmaskblshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); LLmaskblshapewav->setTooltip(M("TP_LOCALLAB_LMASK_LEVEL_TOOLTIP")); + maskblCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + strumaskbl->set_tooltip_text(M("TP_LOCALLAB_STRUSTRMASK_TOOLTIP")); + toolbl->set_tooltip_text(M("TP_LOCALLAB_TOOLMASK_TOOLTIP")); + toolblFrame->set_tooltip_text(M("TP_LOCALLAB_TOOLCOLFRMASK_TOOLTIP")); + gammaskbl->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromaskbl->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slomaskbl->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + shadmaskbl->set_tooltip_text(M("TP_LOCALLAB_SHADHMASK_TOOLTIP")); + shadmaskblsha->set_tooltip_text(M("TP_LOCALLAB_SHADMASK_TOOLTIP")); + lapmaskbl->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); + csThresholdblur->set_tooltip_text(M("TP_LOCALLAB_WAVEMASK_LEVEL_TOOLTIP")); + sensiden->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + } else { - expblnoise->set_tooltip_text(""); + + expblnoise->set_tooltip_markup(""); radius->set_tooltip_text(""); + strength->set_tooltip_text(""); + grainFrame->set_tooltip_text(""); sensibn->set_tooltip_text(""); - blurMethod->set_tooltip_text(""); - expdenoise->set_tooltip_text(""); + medMethod->set_tooltip_text(""); + itera->set_tooltip_text(""); + fftwbl->set_tooltip_text(""); + guidbl->set_tooltip_text(""); + strbl->set_tooltip_text(""); + epsbl->set_tooltip_text(""); + blurMethod->set_tooltip_markup(""); + quamethod->set_tooltip_markup(""); + LocalcurveEditorwavden->setTooltip(""); + noiselequal->set_tooltip_text(""); + noiselumdetail->set_tooltip_text(""); + noisechrof->set_tooltip_text(""); + noisechroc->set_tooltip_text(""); + noisechrodetail->set_tooltip_text(""); + detailthr->set_tooltip_text(""); + adjblur->set_tooltip_text(""); + bilateral->set_tooltip_text(""); + sensibn->set_tooltip_text(""); + blurMethod->set_tooltip_markup(""); + expdenoise->set_tooltip_markup(""); wavshapeden->setTooltip(""); noiselumc->set_tooltip_text(""); - expmaskbl->set_tooltip_text(""); - showmaskblMethodtyp->set_tooltip_text(""); + expmaskbl->set_tooltip_markup(""); + showmaskblMethodtyp->set_tooltip_markup(""); CCmaskblshape->setTooltip(""); LLmaskblshape->setTooltip(""); HHmaskblshape->setTooltip(""); @@ -5959,6 +6163,18 @@ void LocallabBlur::updateAdviceTooltips(const bool showTooltips) lapmaskbl->set_tooltip_text(""); Lmaskblshape->setTooltip(""); LLmaskblshapewav->setTooltip(""); + maskblCurveEditorG->set_tooltip_markup(""); + strumaskbl->set_tooltip_text(""); + toolbl->set_tooltip_text(""); + toolblFrame->set_tooltip_text(""); + gammaskbl->set_tooltip_text(""); + chromaskbl->set_tooltip_text(""); + slomaskbl->set_tooltip_text(""); + shadmaskbl->set_tooltip_text(""); + shadmaskblsha->set_tooltip_text(""); + csThresholdblur->set_tooltip_text(""); + sensiden->set_tooltip_text(""); + } } @@ -5975,9 +6191,11 @@ void LocallabBlur::disableListener() blMethodConn.block(true); fftwblConn.block(true); + invblConn.block(true); medMethodConn.block(true); blurMethodConn.block(true); chroMethodConn.block(true); + quamethodconn.block(true); activlumConn.block(true); showmaskblMethodConn.block(true); showmaskblMethodtypConn.block(true); @@ -5991,9 +6209,11 @@ void LocallabBlur::enableListener() blMethodConn.block(false); fftwblConn.block(false); + invblConn.block(false); medMethodConn.block(false); blurMethodConn.block(false); chroMethodConn.block(false); + quamethodconn.block(false); activlumConn.block(false); showmaskblMethodConn.block(false); showmaskblMethodtypConn.block(false); @@ -6027,6 +6247,7 @@ void LocallabBlur::read(const rtengine::procparams::ProcParams* pp, const Params } fftwbl->set_active(spot.fftwbl); + invbl->set_active(spot.invbl); radius->setValue(spot.radius); strength->setValue(spot.strength); isogr->setValue((double)spot.isogr); @@ -6065,6 +6286,12 @@ void LocallabBlur::read(const rtengine::procparams::ProcParams* pp, const Params chroMethod->set_active(2); } + if (spot.quamethod == "cons") { + quamethod->set_active(0); + } else if (spot.quamethod == "agre") { + quamethod->set_active(1); + } + activlum->set_active(spot.activlum); wavshapeden->setCurve(spot.locwavcurveden); noiselumf0->setValue(spot.noiselumf0); @@ -6140,6 +6367,7 @@ void LocallabBlur::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped } spot.fftwbl = fftwbl->get_active(); + spot.invbl = invbl->get_active(); spot.radius = radius->getValue(); spot.strength = strength->getIntValue(); spot.isogr = isogr->getIntValue(); @@ -6178,6 +6406,12 @@ void LocallabBlur::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped spot.chroMethod = "all"; } + if (quamethod->get_active_row_number() == 0) { + spot.quamethod = "cons"; + } else if (quamethod->get_active_row_number() == 1) { + spot.quamethod = "agre"; + } + spot.activlum = activlum->get_active(); spot.locwavcurveden = wavshapeden->getCurve(); spot.noiselumf0 = noiselumf0->getValue(); @@ -6714,6 +6948,21 @@ void LocallabBlur::fftwblChanged() } } +void LocallabBlur::invblChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (invbl->get_active()) { + listener->panelChanged(Evlocallabinvbl, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabinvbl, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + void LocallabBlur::medMethodChanged() { if (isLocActivated && exp->getEnabled()) { @@ -6744,6 +6993,17 @@ void LocallabBlur::chroMethodChanged() } } +void LocallabBlur::quamethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabquaMethod, + quamethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + + void LocallabBlur::activlumChanged() { if (isLocActivated && exp->getEnabled()) { diff --git a/rtgui/locallabtools.h b/rtgui/locallabtools.h index 8b5152968..ff8d6e6f6 100644 --- a/rtgui/locallabtools.h +++ b/rtgui/locallabtools.h @@ -225,6 +225,7 @@ private: LabGrid* const labgridmerg; Adjuster* const merlucol; MyExpander* const expmaskcol; + Gtk::Frame* const mergecolFrame ; MyComboBoxText* const showmaskcolMethod; MyComboBoxText* const showmaskcolMethodinv; Gtk::CheckButton* const enaColorMask; @@ -240,6 +241,7 @@ private: Adjuster* const contcol; Adjuster* const blurcol; Adjuster* const blendmaskcol; + Gtk::Frame* const toolcolFrame; Adjuster* const radmaskcol; Adjuster* const lapmaskcol; Adjuster* const chromaskcol; @@ -317,13 +319,16 @@ class LocallabExposure: private: // Exposure specific widgets MyComboBoxText* const expMethod; - Gtk::Frame* const pdeFrame; +// Gtk::Frame* const pdeFrame; + MyExpander* const exppde; Adjuster* const laplacexp; Adjuster* const linear; Adjuster* const balanexp; Adjuster* const gamm; + Gtk::Label* const labelexpmethod; MyComboBoxText* const exnoiseMethod; - Gtk::Frame* const fatFrame; +// Gtk::Frame* const fatFrame; + MyExpander* const expfat; Adjuster* const fatamount; Adjuster* const fatdetail; Adjuster* const fatlevel; @@ -409,6 +414,7 @@ private: void updateExposureGUI3(); }; + /* ==== LocallabShadow ==== */ class LocallabShadow: public Gtk::VBox, @@ -646,9 +652,11 @@ private: Adjuster* const epsbl; Adjuster* const sensibn; MyComboBoxText* const blurMethod; + Gtk::CheckButton* const invbl; MyComboBoxText* const chroMethod; Gtk::CheckButton* const activlum; MyExpander* const expdenoise; + MyComboBoxText* const quamethod; CurveEditorGroup* const LocalcurveEditorwavden; FlatCurveEditor* const wavshapeden; Adjuster* const noiselumf0; @@ -674,6 +682,7 @@ private: FlatCurveEditor* const HHmaskblshape; Adjuster* const strumaskbl; Gtk::CheckButton* const toolbl; + Gtk::Frame* const toolblFrame; Adjuster* const blendmaskbl; Adjuster* const radmaskbl; Adjuster* const lapmaskbl; @@ -686,10 +695,11 @@ private: DiagonalCurveEditor* const Lmaskblshape; CurveEditorGroup* const mask2blCurveEditorGwav; FlatCurveEditor* const LLmaskblshapewav; + Gtk::HBox* const quaHBox; ThresholdAdjuster* const csThresholdblur; - sigc::connection blMethodConn, fftwblConn, medMethodConn, blurMethodConn, chroMethodConn, activlumConn, showmaskblMethodConn, showmaskblMethodtypConn, enablMaskConn, toolblConn; - + sigc::connection blMethodConn, fftwblConn, invblConn, medMethodConn, blurMethodConn, chroMethodConn, activlumConn, showmaskblMethodConn, showmaskblMethodtypConn, enablMaskConn, toolblConn; + sigc::connection quamethodconn; public: LocallabBlur(); ~LocallabBlur(); @@ -724,6 +734,7 @@ private: void blMethodChanged(); void fftwblChanged(); + void invblChanged(); void medMethodChanged(); void blurMethodChanged(); void chroMethodChanged(); @@ -732,6 +743,7 @@ private: void showmaskblMethodtypChanged(); void enablMaskChanged(); void toolblChanged(); + void quamethodChanged(); void updateBlurGUI(); }; @@ -812,6 +824,7 @@ class LocallabRetinex: { private: // Retinex specific widgets + Gtk::Frame* const dehaFrame; Adjuster* const dehaz; Adjuster* const depth; Gtk::CheckButton* const lumonly; @@ -1177,25 +1190,39 @@ class LocallabLog: public LocallabTool { private: + Gtk::CheckButton* const ciecam; Gtk::ToggleButton* const autocompute; Gtk::Frame* const logPFrame; Adjuster* const blackEv; Adjuster* const whiteEv; Gtk::CheckButton* const fullimage; + Gtk::Frame* const logFrame; Gtk::CheckButton* const Autogray; Adjuster* const sourceGray; + Adjuster* const sourceabs; + Gtk::Frame* const log1Frame; + Gtk::Frame* const log2Frame; Adjuster* const targetGray; Adjuster* const detail; + Adjuster* const catad; + Adjuster* const contl; + Adjuster* const saturl; + Adjuster* const targabs; + MyComboBoxText* const surround; + Gtk::HBox* const surrHBox; + Adjuster* const baselog; Adjuster* const sensilog; Adjuster* const strlog; Adjuster* const anglog; - sigc::connection autoconn, fullimageConn, AutograyConn; + sigc::connection autoconn, ciecamconn, fullimageConn, AutograyConn; + sigc::connection surroundconn; public: LocallabLog(); void updateAdviceTooltips(const bool showTooltips) override; + void surroundChanged(); void disableListener() override; void enableListener() override; @@ -1204,7 +1231,7 @@ public: void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void adjusterChanged(Adjuster* a, double newval) override; - void updateAutocompute(const float blackev, const float whiteev, const float sourceg, const float targetg); + void updateAutocompute(const float blackev, const float whiteev, const float sourceg, const float sourceab, const float targetg); private: void enabledChanged() override; @@ -1212,8 +1239,10 @@ private: void autocomputeToggled(); void fullimageChanged(); void AutograyChanged(); + void ciecamChanged(); void updateLogGUI(); + void updateLogGUI2(); }; diff --git a/rtgui/locallabtools2.cc b/rtgui/locallabtools2.cc index a025d5791..a87e35786 100644 --- a/rtgui/locallabtools2.cc +++ b/rtgui/locallabtools2.cc @@ -285,10 +285,15 @@ void LocallabTone::updateAdviceTooltips(const bool showTooltips) LLmasktmshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); HHmasktmshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); blendmasktm->set_tooltip_text(M("TP_LOCALLAB_BLENDMASK_TOOLTIP")); - lapmasktm->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); radmasktm->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); mask2tmCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP")); Lmasktmshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + masktmCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + gammasktm->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromasktm->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slomasktm->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + lapmasktm->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); + } else { exp->set_tooltip_text(""); equiltm->set_tooltip_text(""); @@ -297,15 +302,21 @@ void LocallabTone::updateAdviceTooltips(const bool showTooltips) scaltm->set_tooltip_text(""); rewei->set_tooltip_text(""); sensitm->set_tooltip_text(""); - expmasktm->set_tooltip_text(""); + expmasktm->set_tooltip_markup(""); CCmasktmshape->setTooltip(""); LLmasktmshape->setTooltip(""); HHmasktmshape->setTooltip(""); blendmasktm->set_tooltip_text(""); - lapmasktm->set_tooltip_text(""); radmasktm->set_tooltip_text(""); mask2tmCurveEditorG->set_tooltip_text(""); Lmasktmshape->setTooltip(""); + mask2tmCurveEditorG->set_tooltip_text(""); + Lmasktmshape->setTooltip(""); + masktmCurveEditorG->set_tooltip_markup(""); + gammasktm->set_tooltip_text(""); + chromasktm->set_tooltip_text(""); + slomasktm->set_tooltip_text(""); + lapmasktm->set_tooltip_text(""); } } @@ -672,13 +683,14 @@ LocallabRetinex::LocallabRetinex(): LocallabTool(this, M("TP_LOCALLAB_RET_TOOLNAME"), M("TP_LOCALLAB_RETI"), true), // Retinex specific widgets + dehaFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_DEHAFRA")))), dehaz(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DEHAZ"), -100, 100, 1, 0))), depth(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DEPTH"), 0, 100, 1, 25))), lumonly(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_LUMONLY")))), retiFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_RETIFRA")))), str(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STR"), 0., 100., 0.2, 0.))), loglin(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_LOGLIN")))), - sensih(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIH"), 0, 100, 1, 60))), + sensih(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 60))), retitoolFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_RETITOOLFRA")))), retinexMethod(Gtk::manage(new MyComboBoxText())), fftwreti(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTW")))), @@ -722,7 +734,6 @@ LocallabRetinex::LocallabRetinex(): const LocallabParams::LocallabSpot defSpot; // Parameter Retinex specific widgets - dehaz->set_tooltip_text(M("TP_LOCALLAB_DEHAZ_TOOLTIP")); dehaz->setAdjusterListener(this); depth->setAdjusterListener(this); @@ -849,7 +860,7 @@ LocallabRetinex::LocallabRetinex(): // Add Retinex specific widgets to GUI ToolParamBlock* const auxBox = Gtk::manage(new ToolParamBlock()); - Gtk::Frame* const dehaFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_DEHAFRA"))); +// Gtk::Frame* const dehaFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_DEHAFRA"))); dehaFrame->set_label_align(0.025, 0.5); ToolParamBlock* const dehaBox = Gtk::manage(new ToolParamBlock()); dehaBox->pack_start(*dehaz); @@ -964,9 +975,12 @@ void LocallabRetinex::getMaskView(int &colorMask, int &colorMaskinv, int &expMas void LocallabRetinex::updateAdviceTooltips(const bool showTooltips) { if (showTooltips) { + dehaFrame->set_tooltip_text(M("TP_LOCALLAB_DEHAZFRAME_TOOLTIP")); + dehaz->set_tooltip_text(M("TP_LOCALLAB_DEHAZ_TOOLTIP")); + retiFrame->set_tooltip_text(M("TP_LOCALLAB_RETIFRAME_TOOLTIP")); loglin->set_tooltip_text(M("TP_LOCALLAB_RETI_LOGLIN_TOOLTIP")); - sensih->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); - fftwreti->set_tooltip_text(M("TP_LOCALLAB_RETI_FFTW_TOOLTIP")); + sensih->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + fftwreti->set_tooltip_text(M("TP_LOCALLAB_LC_FFTW_TOOLTIP")); equilret->set_tooltip_text(M("TP_LOCALLAB_EQUILTM_TOOLTIP")); neigh->set_tooltip_text(M("TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP")); vart->set_tooltip_text(M("TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP")); @@ -980,6 +994,7 @@ void LocallabRetinex::updateAdviceTooltips(const bool showTooltips) cTtransshape->setTooltip(M("TP_LOCALLAB_TRANSMISSION_TOOLTIP")); mMLabels->set_tooltip_markup(M("TP_LOCALLAB_MLABEL_TOOLTIP")); transLabels->set_tooltip_markup(M("TP_LOCALLAB_TLABEL_TOOLTIP")); + transLabels2->set_tooltip_markup(M("TP_LOCALLAB_TLABEL_TOOLTIP")); cTgainshape->setTooltip(M("TP_RETINEX_GAINTRANSMISSION_TOOLTIP")); expmaskreti->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); enaretiMasktmap->set_tooltip_markup(M("TP_LOCALLAB_ENARETIMASKTMAP_TOOLTIP")); @@ -988,10 +1003,18 @@ void LocallabRetinex::updateAdviceTooltips(const bool showTooltips) HHmaskretishape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); blendmaskreti->set_tooltip_text(M("TP_LOCALLAB_BLENDMASK_TOOLTIP")); radmaskreti->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); - lapmaskreti->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); mask2retiCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP")); Lmaskretishape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + maskretiCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + gammaskreti->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromaskreti->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slomaskreti->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + lapmaskreti->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); + } else { + dehaFrame->set_tooltip_text(""); + dehaz->set_tooltip_text(""); + retiFrame->set_tooltip_text(""); loglin->set_tooltip_text(""); sensih->set_tooltip_text(""); fftwreti->set_tooltip_text(""); @@ -1006,19 +1029,24 @@ void LocallabRetinex::updateAdviceTooltips(const bool showTooltips) cliptm->set_tooltip_text(""); softradiusret->set_tooltip_text(""); cTtransshape->setTooltip(""); - mMLabels->set_tooltip_text(""); - transLabels->set_tooltip_text(""); + mMLabels->set_tooltip_markup(""); + transLabels->set_tooltip_markup(""); + transLabels2->set_tooltip_markup(""); cTgainshape->setTooltip(""); - expmaskreti->set_tooltip_text(""); - enaretiMasktmap->set_tooltip_text(""); + expmaskreti->set_tooltip_markup(""); + enaretiMasktmap->set_tooltip_markup(""); CCmaskretishape->setTooltip(""); LLmaskretishape->setTooltip(""); HHmaskretishape->setTooltip(""); blendmaskreti->set_tooltip_text(""); radmaskreti->set_tooltip_text(""); - lapmaskreti->set_tooltip_text(""); mask2retiCurveEditorG->set_tooltip_text(""); Lmaskretishape->setTooltip(""); + maskretiCurveEditorG->set_tooltip_markup(""); + gammaskreti->set_tooltip_text(""); + chromaskreti->set_tooltip_text(""); + slomaskreti->set_tooltip_text(""); + lapmaskreti->set_tooltip_text(""); } } @@ -1752,7 +1780,7 @@ LocallabSharp::LocallabSharp(): shardamping(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARDAMPING"), 0, 100, 1, 0))), shariter(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARITER"), 5, 100, 1, 30))), sharradius(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARRADIUS"), 0.4, 2.5, 0.01, 0.75))), - sensisha(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIS"), 0, 100, 1, 40))), + sensisha(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 40))), inverssha(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))), sharFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_SHARFRAME")))), showmasksharMethod(Gtk::manage(new MyComboBoxText())) @@ -1818,7 +1846,7 @@ void LocallabSharp::updateAdviceTooltips(const bool showTooltips) { if (showTooltips) { exp->set_tooltip_text(M("TP_LOCALLAB_EXPSHARP_TOOLTIP")); - sensisha->set_tooltip_text(M("TP_LOCALLAB_SENSIS_TOOLTIP")); + sensisha->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); } else { exp->set_tooltip_text(""); sensisha->set_tooltip_text(""); @@ -2111,7 +2139,7 @@ LocallabContrast::LocallabContrast(): residshathr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDSHATHR"), 0., 100., 1., 30.))), residhi(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDHI"), -100., 100., 1., 0.))), residhithr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDHITHR"), 0., 100., 1., 70.))), - sensilc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIS"), 0, 100, 1, 60))), + sensilc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 60))), clariFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_CLARIFRA")))), clarilres(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLARILRES"), -20., 100., 0.5, 0.))), claricres(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLARICRES"), -20., 100., 0.5, 0.))), @@ -2203,7 +2231,7 @@ LocallabContrast::LocallabContrast(): wavshape->setIdentityValue(0.); wavshape->setResetCurve(FlatCurveType(defSpot.locwavcurve.at(0)), defSpot.locwavcurve); - wavshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); +// wavshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); LocalcurveEditorwav->curveListComplete(); @@ -2270,7 +2298,7 @@ LocallabContrast::LocallabContrast(): wavshapeedg->setIdentityValue(0.); wavshapeedg->setResetCurve(FlatCurveType(defSpot.locedgwavcurve.at(0)), defSpot.locedgwavcurve); - wavshapeedg->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); +// wavshapeedg->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); LocalcurveEditorwavedg->curveListComplete(); @@ -2370,7 +2398,7 @@ LocallabContrast::LocallabContrast(): wavshapecomp->setIdentityValue(0.); wavshapecomp->setResetCurve(FlatCurveType(defSpot.loccompwavcurve.at(0)), defSpot.loccompwavcurve); - wavshapecomp->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); +// wavshapecomp->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); LocalcurveEditorwavcomp->curveListComplete(); @@ -2399,7 +2427,7 @@ LocallabContrast::LocallabContrast(): LLmasklcshape->setIdentityValue(0.); LLmasklcshape->setResetCurve(FlatCurveType(defSpot.LLmasklccurve.at(0)), defSpot.LLmasklccurve); - LLmasklcshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); +// LLmasklcshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); HHmasklcshape->setIdentityValue(0.); HHmasklcshape->setResetCurve(FlatCurveType(defSpot.HHmasklccurve.at(0)), defSpot.HHmasklccurve); @@ -2428,10 +2456,11 @@ LocallabContrast::LocallabContrast(): pack_start(*lcamount); pack_start(*lcdarkness); pack_start(*lclightness); + pack_start(*csThreshold); ToolParamBlock* const coBox = Gtk::manage(new ToolParamBlock()); coBox->pack_start(*sigmalc); coBox->pack_start(*LocalcurveEditorwav, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor - coBox->pack_start(*csThreshold); + // coBox->pack_start(*csThreshold); contFrame->add(*coBox); pack_start(*contFrame); // pack_start(*levelwav); @@ -2602,10 +2631,49 @@ void LocallabContrast::updateAdviceTooltips(const bool showTooltips) { if (showTooltips) { contFrame->set_tooltip_text(M("TP_LOCALLAB_EXPCONTRAST_TOOLTIP")); - LocalcurveEditorwav->set_tooltip_markup(M("TP_LOCALLAB_LEVELLOCCONTRAST_TOOLTIP")); + LocalcurveEditorwav->set_tooltip_markup(M("TP_LOCALLAB_WAT_LEVELLOCCONTRAST_TOOLTIP")); + csThreshold->set_tooltip_markup(M("TP_LOCALLAB_WAT_THRESHOLDWAV_TOOLTIP")); levelwav->set_tooltip_markup(M("TP_LOCALLAB_LEVELWAV_TOOLTIP")); clariFrame->set_tooltip_markup(M("TP_LOCALLAB_CLARI_TOOLTIP")); clarisoft->set_tooltip_markup(M("TP_LOCALLAB_CLARISOFT_TOOLTIP")); + + wavshape->setTooltip(M("TP_LOCALLAB_WAT_WAVSHAPE_TOOLTIP")); + clarilres->set_tooltip_text(M("TP_LOCALLAB_WAT_CLARIL_TOOLTIP")); + claricres->set_tooltip_text(M("TP_LOCALLAB_WAT_CLARIC_TOOLTIP")); + sigmalc->set_tooltip_text(M("TP_LOCALLAB_WAT_SIGMALC_TOOLTIP")); + sigmalc2->set_tooltip_text(M("TP_LOCALLAB_WAT_SIGMALC_TOOLTIP")); + sigmaed->set_tooltip_text(M("TP_LOCALLAB_WAT_SIGMALC_TOOLTIP")); + sigmabl->set_tooltip_text(M("TP_LOCALLAB_WAT_SIGMALC_TOOLTIP")); + sigma->set_tooltip_text(M("TP_LOCALLAB_WAT_SIGMALC_TOOLTIP")); + sigmadc->set_tooltip_text(M("TP_LOCALLAB_WAT_SIGMALC_TOOLTIP")); + sigmadr->set_tooltip_text(M("TP_LOCALLAB_WAT_SIGMALC_TOOLTIP")); + origlc->set_tooltip_text(M("TP_LOCALLAB_WAT_ORIGLC_TOOLTIP")); + strwav->set_tooltip_text(M("TP_LOCALLAB_WAT_STRWAV_TOOLTIP")); + angwav->set_tooltip_text(M("TP_LOCALLAB_WAT_STRWAV_TOOLTIP")); + strengthw->set_tooltip_text(M("TP_LOCALLAB_WAT_STRENGTHW_TOOLTIP")); + LocalcurveEditorwavedg->set_tooltip_markup(M("TP_LOCALLAB_WAT_LOCCONTRASTEDG_TOOLTIP")); + wavshapeedg->setTooltip(M("TP_LOCALLAB_WAT_LOCCONTRASTEDG_TOOLTIP")); + gradw->set_tooltip_text(M("TP_LOCALLAB_WAT_GRADW_TOOLTIP")); + waveshow->set_tooltip_text(M("TP_LOCALLAB_WAT_WAVESHOW_TOOLTIP")); + LocalcurveEditorwavlev->set_tooltip_markup(M("TP_LOCALLAB_WAT_WAVBLURCURV_TOOLTIP")); + wavshapelev->setTooltip(M("TP_LOCALLAB_WAT_WAVBLURCURV_TOOLTIP")); + levelblur->set_tooltip_text(M("TP_LOCALLAB_WAT_WAVLEVELBLUR_TOOLTIP")); + residblur->set_tooltip_text(M("TP_LOCALLAB_WAT_RESIDBLUR_TOOLTIP")); + blurlc->set_tooltip_text(M("TP_LOCALLAB_WAT_BLURLC_TOOLTIP")); + offset->set_tooltip_text(M("TP_LOCALLAB_WAT_CONTOFFSET_TOOLTIP")); + chromalev->set_tooltip_text(M("TP_LOCALLAB_WAT_CONTCHROMALEV_TOOLTIP")); + LocalcurveEditorwavcon->set_tooltip_markup(M("TP_LOCALLAB_WAT_WAVCBDL_TOOLTIP")); + wavshapecon->setTooltip(M("TP_LOCALLAB_WAT_WAVCBDL_TOOLTIP")); + LocalcurveEditorwavcompre->set_tooltip_markup(M("TP_LOCALLAB_WAT_WAVTM_TOOLTIP")); + wavshapecompre->setTooltip(M("TP_LOCALLAB_WAT_WAVTM_TOOLTIP")); + deltad->set_tooltip_text(M("TP_LOCALLAB_WAT_DELTABAL_TOOLTIP")); + LocalcurveEditorwavcomp->set_tooltip_markup(M("TP_LOCALLAB_WAT_WAVDELTABAL_TOOLTIP")); + wavshapecomp->setTooltip(M("TP_LOCALLAB_WAT_WAVDELTABAL_TOOLTIP")); + threswav->set_tooltip_text(M("TP_LOCALLAB_WAT_BALTHRES_TOOLTIP")); + residcomp->set_tooltip_text(M("TP_LOCALLAB_WAT_RESIDCOMP_TOOLTIP")); + + + expresidpyr->set_tooltip_text(M("TP_LOCALLAB_WAT_EXPRESID_TOOLTIP")); expcontrastpyr->set_tooltip_text(M("TP_LOCALLAB_EXPCONTRASTPYR_TOOLTIP")); wavgradl->set_tooltip_text(M("TP_LOCALLAB_WAVGRAD_TOOLTIP")); wavedg->set_tooltip_text(M("TP_LOCALLAB_WAVEEDG_TOOLTIP")); @@ -2624,12 +2692,17 @@ void LocallabContrast::updateAdviceTooltips(const bool showTooltips) blendmasklc->set_tooltip_text(M("TP_LOCALLAB_BLENDMASK_TOOLTIP")); mask2lcCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP")); Lmasklcshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + masklcCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + chromasklc->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + sensilc->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); } else { contFrame->set_tooltip_text(""); - LocalcurveEditorwav->set_tooltip_text(""); - levelwav->set_tooltip_text(""); - clariFrame->set_tooltip_text(""); - clarisoft->set_tooltip_text(""); + LocalcurveEditorwav->set_tooltip_markup(""); + csThreshold->set_tooltip_markup(""); + expresidpyr->set_tooltip_text(""); + levelwav->set_tooltip_markup(""); + clariFrame->set_tooltip_markup(""); + clarisoft->set_tooltip_markup(""); expcontrastpyr->set_tooltip_text(""); wavgradl->set_tooltip_text(""); wavedg->set_tooltip_text(""); @@ -2641,13 +2714,52 @@ void LocallabContrast::updateAdviceTooltips(const bool showTooltips) wavcompre->set_tooltip_text(""); wavcomp->set_tooltip_text(""); fftwlc->set_tooltip_text(""); - expmasklc->set_tooltip_text(""); + expmasklc->set_tooltip_markup(""); CCmasklcshape->setTooltip(""); LLmasklcshape->setTooltip(""); HHmasklcshape->setTooltip(""); blendmasklc->set_tooltip_text(""); mask2lcCurveEditorG->set_tooltip_text(""); Lmasklcshape->setTooltip(""); + masklcCurveEditorG->set_tooltip_markup(""); + chromasklc->set_tooltip_text(""); + sensilc->set_tooltip_text(""); + + wavshape->setTooltip(""); + clarilres->set_tooltip_text(""); + claricres->set_tooltip_text(""); + sigmalc->set_tooltip_text(""); + sigmalc2->set_tooltip_text(""); + sigmaed->set_tooltip_text(""); + sigmabl->set_tooltip_text(""); + sigma->set_tooltip_text(""); + sigmadc->set_tooltip_text(""); + sigmadr->set_tooltip_text(""); + origlc->set_tooltip_text(""); + strwav->set_tooltip_text(""); + angwav->set_tooltip_text(""); + strengthw->set_tooltip_text(""); + LocalcurveEditorwavedg->set_tooltip_markup(""); + wavshapeedg->setTooltip(""); + gradw->set_tooltip_text(""); + waveshow->set_tooltip_text(""); + LocalcurveEditorwavlev->set_tooltip_markup(""); + wavshapelev->setTooltip(""); + residblur->set_tooltip_text(""); + blurlc->set_tooltip_text(""); + levelblur->set_tooltip_text(""); + offset->set_tooltip_text(""); + chromalev->set_tooltip_text(""); + LocalcurveEditorwavcon->set_tooltip_markup(""); + wavshapecon->setTooltip(""); + LocalcurveEditorwavcompre->set_tooltip_markup(""); + wavshapecompre->setTooltip(""); + deltad->set_tooltip_text(""); + LocalcurveEditorwavcomp->set_tooltip_markup(""); + wavshapecomp->setTooltip(""); + threswav->set_tooltip_text(""); + residcomp->set_tooltip_text(""); + } } @@ -3801,6 +3913,7 @@ void LocallabContrast::updateContrastGUI1() lcdarkness->show(); lclightness->show(); contFrame->hide(); + csThreshold->hide(); levelwav->hide(); expresidpyr->hide(); clariFrame->hide(); @@ -3816,6 +3929,7 @@ void LocallabContrast::updateContrastGUI1() lcdarkness->hide(); lclightness->hide(); contFrame->show(); + csThreshold->show(); levelwav->show(); expresidpyr->show(); clariFrame->show(); @@ -3882,7 +3996,7 @@ LocallabCBDL::LocallabCBDL(): clarityml(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLARITYML"), 0.1, 100., 0.1, 0.1))), contresid(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTRESID"), -100, 100, 1, 0))), softradiuscb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.5, 0.))), - sensicb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSICB"), 0, 100, 1, 60))), + sensicb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 60))), expmaskcb(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWCB")))), showmaskcbMethod(Gtk::manage(new MyComboBoxText())), enacbMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), @@ -4055,16 +4169,20 @@ void LocallabCBDL::updateAdviceTooltips(const bool showTooltips) chromacbdl->set_tooltip_text(M("TP_LOCALLAB_CHROMACB_TOOLTIP")); threshold->set_tooltip_text(M("TP_LOCALLAB_CBDL_THRES_TOOLTIP")); clarityml->set_tooltip_text(M("TP_LOCALLAB_CBDLCLARI_TOOLTIP")); - sensicb->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); + sensicb->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); expmaskcb->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); CCmaskcbshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); LLmaskcbshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); HHmaskcbshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); blendmaskcb->set_tooltip_text(M("TP_LOCALLAB_BLENDMASK_TOOLTIP")); radmaskcb->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); - lapmaskcb->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); mask2cbCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP")); Lmaskcbshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + maskcbCurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + gammaskcb->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromaskcb->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slomaskcb->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + lapmaskcb->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); } else { levFrame->set_tooltip_text(""); @@ -4076,15 +4194,19 @@ void LocallabCBDL::updateAdviceTooltips(const bool showTooltips) threshold->set_tooltip_text(""); clarityml->set_tooltip_text(""); sensicb->set_tooltip_text(""); - expmaskcb->set_tooltip_text(""); + expmaskcb->set_tooltip_markup(""); CCmaskcbshape->setTooltip(""); LLmaskcbshape->setTooltip(""); HHmaskcbshape->setTooltip(""); blendmaskcb->set_tooltip_text(""); radmaskcb->set_tooltip_text(""); - lapmaskcb->set_tooltip_text(""); mask2cbCurveEditorG->set_tooltip_text(""); Lmaskcbshape->setTooltip(""); + maskcbCurveEditorG->set_tooltip_markup(""); + gammaskcb->set_tooltip_text(""); + chromaskcb->set_tooltip_text(""); + slomaskcb->set_tooltip_text(""); + lapmaskcb->set_tooltip_text(""); } } @@ -4530,17 +4652,29 @@ LocallabLog::LocallabLog(): LocallabTool(this, M("TP_LOCALLAB_LOG_TOOLNAME"), M("TP_LOCALLAB_LOG"), false, false), // Log encoding specific widgets + ciecam(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_CIEC")))), autocompute(Gtk::manage(new Gtk::ToggleButton(M("TP_LOCALLAB_LOGAUTO")))), logPFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LOGPFRA")))), blackEv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLACK_EV"), -16.0, 0.0, 0.1, -5.0))), - whiteEv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_WHITE_EV"), 0.0, 32.0, 0.1, 10.0))), + whiteEv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_WHITE_EV"), 0., 32.0, 0.1, 10.0))), fullimage(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FULLIMAGE")))), + logFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LOGFRA")))), Autogray(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_AUTOGRAY")))), sourceGray(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOURCE_GRAY"), 1.0, 100.0, 0.1, 10.0))), + sourceabs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOURCE_ABS"), 0.01, 16384.0, 0.01, 2000.0))), + log1Frame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LOG1FRA")))), + log2Frame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LOG2FRA")))), targetGray(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TARGET_GRAY"), 5.0, 80.0, 0.1, 18.0))), detail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DETAIL"), 0., 1., 0.01, 0.6))), - baselog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BASELOG"), 1.3, 8., 0.05, 2., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), - sensilog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSILOG"), 0, 100, 1, 60))), + catad(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CATAD"), -100., 100., 0.5, 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-orange-small.png"))))), + contl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTL"), -100., 100., 0.5, 0.))), + saturl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SATURV"), -100., 100., 0.5, 0.))), + targabs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOURCE_ABS"), 0.01, 16384.0, 0.01, 16.0))), + surround(Gtk::manage (new MyComboBoxText ())), + surrHBox(Gtk::manage(new Gtk::HBox())), + + baselog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BASELOG"), 1.3, 3., 0.05, 2., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), + sensilog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 60))), strlog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -2.0, 2.0, 0.05, 0.))), anglog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))) { @@ -4552,6 +4686,7 @@ LocallabLog::LocallabLog(): whiteEv->setLogScale(16, 0); whiteEv->setAdjusterListener(this); + ciecamconn = ciecam->signal_toggled().connect(sigc::mem_fun(*this, &LocallabLog::ciecamChanged)); fullimageConn = fullimage->signal_toggled().connect(sigc::mem_fun(*this, &LocallabLog::fullimageChanged)); @@ -4559,10 +4694,24 @@ LocallabLog::LocallabLog(): sourceGray->setAdjusterListener(this); + sourceabs->setLogScale(500, 0); + + sourceabs->setAdjusterListener(this); + targetGray->setAdjusterListener(this); detail->setAdjusterListener(this); + catad->setAdjusterListener(this); + + saturl->setAdjusterListener(this); + + contl->setAdjusterListener(this); + + targabs->setLogScale(500, 0); + + targabs->setAdjusterListener(this); + baselog->setAdjusterListener(this); sensilog->setAdjusterListener(this); @@ -4571,7 +4720,21 @@ LocallabLog::LocallabLog(): anglog->setAdjusterListener(this); +// Gtk::HBox* surrHBox = Gtk::manage (new Gtk::HBox ()); + surrHBox->set_spacing (2); + surrHBox->set_tooltip_markup (M ("TP_COLORAPP_SURROUND_TOOLTIP")); + Gtk::Label* surrLabel = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_SURROUND") + ":")); + surrHBox->pack_start (*surrLabel, Gtk::PACK_SHRINK); + surround->append (M ("TP_COLORAPP_SURROUND_AVER")); + surround->append (M ("TP_COLORAPP_SURROUND_DIM")); + surround->append (M ("TP_COLORAPP_SURROUND_DARK")); + surround->append (M ("TP_COLORAPP_SURROUND_EXDARK")); + surround->set_active (0); + surrHBox->pack_start (*surround); + surroundconn = surround->signal_changed().connect ( sigc::mem_fun (*this, &LocallabLog::surroundChanged) ); + // Add Log encoding specific widgets to GUI + pack_start(*ciecam); logPFrame->set_label_align(0.025, 0.5); ToolParamBlock* const logPBox = Gtk::manage(new ToolParamBlock()); logPBox->pack_start(*autocompute); @@ -4580,16 +4743,31 @@ LocallabLog::LocallabLog(): logPBox->pack_start(*fullimage); logPFrame->add(*logPBox); pack_start(*logPFrame); - Gtk::Frame* const logFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LOGFRA"))); +// Gtk::Frame* const logFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LOGFRA"))); logFrame->set_label_align(0.025, 0.5); ToolParamBlock* const logFBox = Gtk::manage(new ToolParamBlock()); logFBox->pack_start(*Autogray); logFBox->pack_start(*sourceGray); + logFBox->pack_start(*sourceabs); +// logFBox->pack_start(*baselog); logFrame->add(*logFBox); pack_start(*logFrame); - pack_start(*targetGray); - pack_start(*detail); - pack_start(*baselog); + log1Frame->set_label_align(0.025, 0.5); + ToolParamBlock* const logP1Box = Gtk::manage(new ToolParamBlock()); + logP1Box->pack_start(*detail); + logP1Box->pack_start(*contl); + logP1Box->pack_start(*saturl); + log1Frame->add(*logP1Box); + pack_start(*log1Frame); + log2Frame->set_label_align(0.025, 0.5); + ToolParamBlock* const logP2Box = Gtk::manage(new ToolParamBlock()); + logP2Box->pack_start(*targetGray); + logP2Box->pack_start(*targabs); + logP2Box->pack_start(*catad); + logP2Box->pack_start (*surrHBox); + log2Frame->add(*logP2Box); + pack_start(*log2Frame); +// pack_start(*baselog); pack_start(*sensilog); Gtk::Frame* const gradlogFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRADLOGFRA"))); gradlogFrame->set_label_align(0.025, 0.5); @@ -4605,25 +4783,56 @@ void LocallabLog::updateAdviceTooltips(const bool showTooltips) if (showTooltips) { exp->set_tooltip_text(M("TP_LOCALLAB_LOGENCOD_TOOLTIP")); logPFrame->set_tooltip_text(M("TP_LOCALLAB_LOGFRAME_TOOLTIP")); + logFrame->set_tooltip_text(M("TP_LOCALLAB_LOGSCENE_TOOLTIP")); + log1Frame->set_tooltip_text(M("TP_LOCALLAB_LOGIMAGE_TOOLTIP")); + log2Frame->set_tooltip_text(M("TP_LOCALLAB_LOGVIEWING_TOOLTIP")); autocompute->set_tooltip_text(M("TP_LOCALLAB_LOGAUTO_TOOLTIP")); - blackEv->set_tooltip_text(M("TP_LOCALLAB_LOGBLACKWHEV_TOOLTIP")); - whiteEv->set_tooltip_text(M("TP_LOCALLAB_LOGBLACKWHEV_TOOLTIP")); - sourceGray->set_tooltip_text(M("TP_LOCALLAB_LOGSRCGREY_TOOLTIP")); - targetGray->set_tooltip_text(M("TP_LOCALLAB_LOGTARGGREY_TOOLTIP")); + // blackEv->set_tooltip_text(M("TP_LOCALLAB_LOGBLACKWHEV_TOOLTIP")); + // whiteEv->set_tooltip_text(M("TP_LOCALLAB_LOGBLACKWHEV_TOOLTIP")); + blackEv->set_tooltip_text(""); + whiteEv->set_tooltip_text(""); + sourceGray->set_tooltip_text(""); + sourceabs->set_tooltip_text(M("TP_COLORAPP_ADAPSCEN_TOOLTIP")); + targabs->set_tooltip_text(M("TP_COLORAPP_VIEWING_ABSOLUTELUMINANCE_TOOLTIP")); + targetGray->set_tooltip_text(M("TP_COLORAPP_YBOUT_TOOLTIP")); baselog->set_tooltip_text(M("TP_LOCALLAB_LOGBASE_TOOLTIP")); strlog->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); anglog->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + contl->set_tooltip_text(M("TP_LOCALLAB_LOGCONTL_TOOLTIP")); + saturl->set_tooltip_text(M("TP_LOCALLAB_LOGSATURL_TOOLTIP")); + detail->set_tooltip_text(M("TP_LOCALLAB_LOGDETAIL_TOOLTIP")); + catad->set_tooltip_text(M("TP_LOCALLAB_LOGCATAD_TOOLTIP")); + // detail->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + // Autogray->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + // sensilog->set_tooltip_text(M("TP_LOCALLAB_NUL_TOOLTIP")); + Autogray->set_tooltip_text(""); + sensilog->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + fullimage->set_tooltip_text(M("TP_LOCALLAB_FULLIMAGELOG_TOOLTIP")); + ciecam->set_tooltip_text(M("TP_LOCALLAB_CIECAMLOG_TOOLTIP")); } else { exp->set_tooltip_text(""); logPFrame->set_tooltip_text(""); + logFrame->set_tooltip_text(""); + log1Frame->set_tooltip_text(""); + log2Frame->set_tooltip_text(""); autocompute->set_tooltip_text(""); blackEv->set_tooltip_text(""); whiteEv->set_tooltip_text(""); sourceGray->set_tooltip_text(""); + sourceabs->set_tooltip_text(""); + targabs->set_tooltip_text(""); targetGray->set_tooltip_text(""); baselog->set_tooltip_text(""); strlog->set_tooltip_text(""); anglog->set_tooltip_text(""); + detail->set_tooltip_text(""); + Autogray->set_tooltip_text(""); + sensilog->set_tooltip_text(""); + fullimage->set_tooltip_text(""); + ciecam->set_tooltip_text(""); + contl->set_tooltip_text(""); + saturl->set_tooltip_text(""); + catad->set_tooltip_text(""); } } @@ -4633,6 +4842,8 @@ void LocallabLog::disableListener() autoconn.block(true); fullimageConn.block(true); + ciecamconn.block(true); + surroundconn.block (true); AutograyConn.block(true); } @@ -4642,6 +4853,8 @@ void LocallabLog::enableListener() autoconn.block(false); fullimageConn.block(false); + ciecamconn.block(false); + surroundconn.block (false); AutograyConn.block(false); } @@ -4663,10 +4876,31 @@ void LocallabLog::read(const rtengine::procparams::ProcParams* pp, const ParamsE autocompute->set_active(spot.autocompute); blackEv->setValue(spot.blackEv); + whiteEv->setValue(spot.whiteEv); +/* if(whiteEv->getValue() < 1.5){ + whiteEv->setValue(1.5); + } +*/ + if (spot.surround == "Average") { + surround->set_active (0); + } else if (spot.surround == "Dim") { + surround->set_active (1); + } else if (spot.surround == "Dark") { + surround->set_active (2); + } else if (spot.surround == "ExtremelyDark") { + surround->set_active (3); + } + + ciecam->set_active(spot.ciecam); fullimage->set_active(spot.fullimage); Autogray->set_active(spot.Autogray); sourceGray->setValue(spot.sourceGray); + sourceabs->setValue(spot.sourceabs); + catad->setValue(spot.catad); + saturl->setValue(spot.saturl); + contl->setValue(spot.contl); + targabs->setValue(spot.targabs); targetGray->setValue(spot.targetGray); detail->setValue(spot.detail); baselog->setValue(spot.baselog); @@ -4680,6 +4914,7 @@ void LocallabLog::read(const rtengine::procparams::ProcParams* pp, const ParamsE // Update Log Encoding GUI according to autocompute button state updateLogGUI(); + updateLogGUI2(); // Note: No need to manage pedited as batch mode is deactivated for Locallab } @@ -4698,14 +4933,32 @@ void LocallabLog::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedi spot.blackEv = blackEv->getValue(); spot.whiteEv = whiteEv->getValue(); spot.fullimage = fullimage->get_active(); + spot.ciecam = ciecam->get_active(); spot.Autogray = Autogray->get_active(); spot.sourceGray = sourceGray->getValue(); + spot.sourceabs = sourceabs->getValue(); + spot.targabs = targabs->getValue(); spot.targetGray = targetGray->getValue(); + spot.catad = catad->getValue(); + spot.saturl = saturl->getValue(); + spot.contl = contl->getValue(); spot.detail = detail->getValue(); spot.baselog = baselog->getValue(); spot.sensilog = sensilog->getIntValue(); spot.strlog = strlog->getValue(); spot.anglog = anglog->getValue(); + + + if (surround->get_active_row_number() == 0) { + spot.surround = "Average"; + } else if (surround->get_active_row_number() == 1) { + spot.surround = "Dim"; + } else if (surround->get_active_row_number() == 2) { + spot.surround = "Dark"; + } else if (surround->get_active_row_number() == 3) { + spot.surround = "ExtremelyDark"; + } + } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -4722,7 +4975,12 @@ void LocallabLog::setDefaults(const rtengine::procparams::ProcParams* defParams, blackEv->setDefault(defSpot.blackEv); whiteEv->setDefault(defSpot.whiteEv); sourceGray->setDefault(defSpot.sourceGray); + sourceabs->setDefault(defSpot.sourceabs); + targabs->setDefault(defSpot.targabs); targetGray->setDefault(defSpot.targetGray); + catad->setDefault(defSpot.catad); + saturl->setDefault(defSpot.saturl); + contl->setDefault(defSpot.contl); detail->setDefault(defSpot.detail); baselog->setDefault(defSpot.baselog); sensilog->setDefault((double)defSpot.sensilog); @@ -4757,6 +5015,20 @@ void LocallabLog::adjusterChanged(Adjuster* a, double newval) } } + if (a == sourceabs) { + if (listener) { + listener->panelChanged(Evlocallabsourceabs, + sourceabs->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == targabs) { + if (listener) { + listener->panelChanged(Evlocallabtargabs, + targabs->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == targetGray) { if (listener) { listener->panelChanged(EvlocallabtargetGray, @@ -4764,6 +5036,27 @@ void LocallabLog::adjusterChanged(Adjuster* a, double newval) } } + if (a == catad) { + if (listener) { + listener->panelChanged(Evlocallabcatad, + catad->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == saturl) { + if (listener) { + listener->panelChanged(Evlocallabsaturl, + saturl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == contl) { + if (listener) { + listener->panelChanged(Evlocallabcontl, + contl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == detail) { if (listener) { listener->panelChanged(Evlocallabdetail, @@ -4801,10 +5094,10 @@ void LocallabLog::adjusterChanged(Adjuster* a, double newval) } } -void LocallabLog::updateAutocompute(const float blackev, const float whiteev, const float sourceg, const float targetg) +void LocallabLog::updateAutocompute(const float blackev, const float whiteev, const float sourceg, const float sourceab, const float targetg) { idle_register.add( - [this, blackev, whiteev, sourceg, targetg]() -> bool { + [this, blackev, whiteev, sourceg, sourceab, targetg]() -> bool { GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected // Update adjuster values according to autocomputed ones @@ -4813,6 +5106,7 @@ void LocallabLog::updateAutocompute(const float blackev, const float whiteev, co blackEv->setValue(blackev); whiteEv->setValue(whiteev); sourceGray->setValue(sourceg); + sourceabs->setValue(sourceab); targetGray->setValue(targetg); enableListener(); @@ -4837,6 +5131,16 @@ void LocallabLog::enabledChanged() } } +void LocallabLog::surroundChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(Evlocallabsurround, + surround->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + void LocallabLog::autocomputeToggled() { // Update Log Encoding GUI according to autocompute button state @@ -4855,6 +5159,43 @@ void LocallabLog::autocomputeToggled() } } +void LocallabLog::ciecamChanged() +{ + if(ciecam->get_active()){ + /* sourceabs->set_sensitive(true); + targabs->set_sensitive(true); + catad->set_sensitive(true); + surrHBox->set_sensitive(true); + */ + sourceabs->show(); + targabs->show(); + catad->show(); + saturl->show(); + contl->show(); + surrHBox->show(); + } else { + sourceabs->hide(); + targabs->hide(); + saturl->hide(); + contl->hide(); + catad->hide(); + surrHBox->hide(); + } + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (ciecam->get_active()) { + listener->panelChanged(Evlocallabciecam, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabciecam, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + + void LocallabLog::fullimageChanged() { if (isLocActivated && exp->getEnabled()) { @@ -4885,16 +5226,42 @@ void LocallabLog::AutograyChanged() } } +void LocallabLog::updateLogGUI2() +{ + if(ciecam->get_active()){ + sourceabs->show(); + targabs->show(); + catad->show(); + saturl->show(); + contl->show(); + surrHBox->show(); + } else { + sourceabs->hide(); + targabs->hide(); + catad->hide(); + saturl->hide(); + contl->hide(); + surrHBox->hide(); + } +} + + void LocallabLog::updateLogGUI() { if (autocompute->get_active()) { blackEv->set_sensitive(false); whiteEv->set_sensitive(false); sourceGray->set_sensitive(false); + sourceabs->set_sensitive(false); } else { blackEv->set_sensitive(true); whiteEv->set_sensitive(true); sourceGray->set_sensitive(true); + if(ciecam->get_active()){ + sourceabs->set_sensitive(true); + } else { + sourceabs->set_sensitive(false); + } } } @@ -5028,7 +5395,7 @@ LocallabMask::LocallabMask(): LLmask_shapewav->setIdentityValue(0.); LLmask_shapewav->setResetCurve(FlatCurveType(defSpot.LLmask_curvewav.at(0)), defSpot.LLmask_curvewav); - LLmask_shapewav->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); +// LLmask_shapewav->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); mask2CurveEditorGwav->curveListComplete(); @@ -5117,12 +5484,25 @@ void LocallabMask::updateAdviceTooltips(const bool showTooltips) HHmask_shape->setTooltip(M("TP_LOCALLAB_CURVEEDITORM_CC_TOOLTIP")); struFrame->set_tooltip_text(M("TP_LOCALLAB_STRUMASK_TOOLTIP")); radmask->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); - lapmask->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); mask_HCurveEditorG->set_tooltip_text(M("TP_LOCALLAB_HHMASK_TOOLTIP")); mask2CurveEditorG->set_tooltip_text(M("TP_LOCALLAB_WAVMASK_TOOLTIP")); Lmask_shape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); mask2CurveEditorGwav->set_tooltip_text(M("TP_LOCALLAB_WAVMASK_TOOLTIP")); LLmask_shapewav->setTooltip(M("TP_LOCALLAB_LMASK_LEVEL_TOOLTIP")); + mask_CurveEditorG->set_tooltip_markup(M("TP_LOCALLAB_MASKCURVE_TOOLTIP")); + strumaskmask->set_tooltip_text(M("TP_LOCALLAB_STRUSTRMASK_TOOLTIP")); + blurFrame->set_tooltip_text(M("TP_LOCALLAB_BLURMASK_TOOLTIP")); + toolmask->set_tooltip_text(M("TP_LOCALLAB_TOOLMASK_TOOLTIP")); + toolmaskFrame->set_tooltip_text(M("TP_LOCALLAB_TOOLCOLFRMASK_TOOLTIP")); + fftmask->set_tooltip_text(M("TP_LOCALLAB_FFTMASK_TOOLTIP")); + gammask->set_tooltip_text(M("TP_LOCALLAB_GAMMASK_TOOLTIP")); + chromask->set_tooltip_text(M("TP_LOCALLAB_CHROMASK_TOOLTIP")); + slopmask->set_tooltip_text(M("TP_LOCALLAB_SLOMASK_TOOLTIP")); + shadmask->set_tooltip_text(M("TP_LOCALLAB_SHADMASK_TOOLTIP")); + contmask->set_tooltip_text(M("TP_LOCALLAB_CONTTHMASK_TOOLTIP")); + blurmask->set_tooltip_text(M("TP_LOCALLAB_BLURRMASK_TOOLTIP")); + lapmask->set_tooltip_text(M("TP_LOCALLAB_LAPRAD1_TOOLTIP")); + csThresholdmask->set_tooltip_text(M("TP_LOCALLAB_WAVEMASK_LEVEL_TOOLTIP")); } else { exp->set_tooltip_text(""); sensimask->set_tooltip_text(""); @@ -5133,12 +5513,25 @@ void LocallabMask::updateAdviceTooltips(const bool showTooltips) HHmask_shape->setTooltip(""); struFrame->set_tooltip_text(""); radmask->set_tooltip_text(""); - lapmask->set_tooltip_text(""); mask_HCurveEditorG->set_tooltip_text(""); mask2CurveEditorG->set_tooltip_text(""); Lmask_shape->setTooltip(""); mask2CurveEditorGwav->set_tooltip_text(""); LLmask_shapewav->setTooltip(""); + mask_CurveEditorG->set_tooltip_markup(""); + strumaskmask->set_tooltip_text(""); + blurFrame->set_tooltip_text(""); + toolmask->set_tooltip_text(""); + toolmaskFrame->set_tooltip_text(""); + fftmask->set_tooltip_text(""); + gammask->set_tooltip_text(""); + chromask->set_tooltip_text(""); + slopmask->set_tooltip_text(""); + shadmask->set_tooltip_text(""); + contmask->set_tooltip_text(""); + blurmask->set_tooltip_text(""); + lapmask->set_tooltip_text(""); + csThresholdmask->set_tooltip_text(""); } } @@ -5549,9 +5942,9 @@ void LocallabMask::convertParamToSimple() disableListener(); // Set hidden specific GUI widgets in Simple mode to default spot values - radmask->setValue(defSpot.radmask); - chromask->setValue(defSpot.chromask); - Lmask_shape->setCurve(defSpot.Lmask_curve); + gammask->setValue(defSpot.gammask); + slopmask->setValue(defSpot.slopmask); + //Lmask_shape->setCurve(defSpot.Lmask_curve); // Enable all listeners enableListener(); @@ -5562,21 +5955,29 @@ void LocallabMask::updateGUIToMode(const modeType new_type) switch (new_type) { case Simple: // Expert and Normal mode widgets are hidden in Simple mode - softradiusmask->hide(); + softradiusmask->show(); + toolmaskFrame->show(); struFrame->hide(); blurFrame->hide(); - toolmaskFrame->hide(); + gammask->hide(); + slopmask->hide(); + shadmask->hide(); + lapmask->hide(); + mask_HCurveEditorG->hide(); + mask2CurveEditorGwav->hide(); + csThresholdmask->hide(); + gradFramemask->hide(); break; case Normal: // Expert mode widgets are hidden in Normal mode - softradiusmask->hide(); + softradiusmask->show(); struFrame->hide(); blurFrame->hide(); lapmask->hide(); - gammask->hide(); - slopmask->hide(); + gammask->show(); + slopmask->show(); shadmask->hide(); mask_HCurveEditorG->hide(); mask2CurveEditorGwav->hide(); @@ -5589,19 +5990,20 @@ void LocallabMask::updateGUIToMode(const modeType new_type) case Expert: // Show widgets hidden in Normal and Simple mode - softradiusmask->hide(); - struFrame->hide(); - blurFrame->hide(); - toolmaskFrame->hide(); - lapmask->hide(); - gammask->hide(); - slopmask->hide(); - shadmask->hide(); - mask_HCurveEditorG->hide(); - mask2CurveEditorGwav->hide(); - csThresholdmask->hide(); - gradFramemask->hide(); + softradiusmask->show(); + struFrame->show(); + blurFrame->show(); + toolmaskFrame->show(); + lapmask->show(); + gammask->show(); + slopmask->show(); + shadmask->show(); + mask_HCurveEditorG->show(); + mask2CurveEditorGwav->show(); + csThresholdmask->show(); + gradFramemask->show(); } + } void LocallabMask::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc index c60cba070..feef93564 100644 --- a/rtgui/main-cli.cc +++ b/rtgui/main-cli.cc @@ -832,7 +832,7 @@ int processLineParams ( int argc, char **argv ) } ii->decreaseRef(); - resultImage->free(); + delete resultImage; } if (imgParams) { diff --git a/rtgui/main.cc b/rtgui/main.cc index 7bb4afdc9..9f623a6df 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -460,7 +460,7 @@ int main (int argc, char **argv) SetConsoleCtrlHandler ( NULL, true ); // Set title of console char consoletitle[128]; - sprintf (consoletitle, "RawTherapee %s Console", RTVERSION); + snprintf(consoletitle, sizeof(consoletitle), "RawTherapee %s Console", RTVERSION); SetConsoleTitle (consoletitle); // increase size of screen buffer COORD c; diff --git a/rtgui/navigator.cc b/rtgui/navigator.cc index 619ea0cfd..9397cfc67 100644 --- a/rtgui/navigator.cc +++ b/rtgui/navigator.cc @@ -26,8 +26,50 @@ using namespace rtengine; -Navigator::Navigator () : currentRGBUnit(options.navRGBUnit), currentHSVUnit(options.navHSVUnit) +Navigator::Navigator() : + pointer_moved_delayed_call(50, 100), + currentRGBUnit(options.navRGBUnit), + currentHSVUnit(options.navHSVUnit) { + pointer_moved_delayed_call.setFunction( + [this](bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b, bool isRaw) + { + if (!validPos) { + setInvalid (x, y); + } else { + Glib::ustring s1, s2, s3; + + position->set_text (Glib::ustring::compose ("x: %1, y: %2", x, y)); + + getRGBText (r, g, b, s1, s2, s3, isRaw); + R->set_text (s1); + G->set_text (s2); + B->set_text (s3); + if (isRaw) { + H->set_text ("--"); + S->set_text ("--"); + V->set_text ("--"); + LAB_L->set_text ("--"); + LAB_A->set_text ("--"); + LAB_B->set_text ("--"); + } else { + float h, s, v; + float LAB_a, LAB_b, LAB_l; + Color::rgb2hsv01(r / 255.f, g / 255.f, b / 255.f, h, s, v); + getHSVText (h, s, v, s1, s2, s3); + H->set_text (s1); + S->set_text (s2); + V->set_text (s3); + + Color::rgb2lab01(profile, profileW, r / 255.f, g / 255.f, b / 255.f, LAB_l, LAB_a, LAB_b, options.rtSettings.HistogramWorking); // TODO: Really sure this function works? + getLABText (LAB_l, LAB_a, LAB_b, s1, s2, s3); + LAB_L->set_text (s1); + LAB_A->set_text (s2); + LAB_B->set_text (s3); + } + } + } + ); set_label (M("MAIN_MSG_NAVIGATOR")); Gtk::VBox* mbox = Gtk::manage (new Gtk::VBox ()); @@ -202,6 +244,11 @@ Navigator::Navigator () : currentRGBUnit(options.navRGBUnit), currentHSVUnit(opt show_all (); } +Navigator::~Navigator() +{ + pointer_moved_delayed_call.cancel(); +} + void Navigator::setInvalid (int fullWidth, int fullHeight) { if (fullWidth > 0 && fullHeight > 0) { @@ -278,41 +325,7 @@ void Navigator::getLABText (float l, float a, float b, Glib::ustring &sL, Glib:: // if !validPos then x/y contain the full image size void Navigator::pointerMoved (bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int x, int y, int r, int g, int b, bool isRaw) { - - if (!validPos) { - setInvalid (x, y); - } else { - Glib::ustring s1, s2, s3; - - position->set_text (Glib::ustring::compose ("x: %1, y: %2", x, y)); - - getRGBText (r, g, b, s1, s2, s3, isRaw); - R->set_text (s1); - G->set_text (s2); - B->set_text (s3); - if (isRaw) { - H->set_text ("--"); - S->set_text ("--"); - V->set_text ("--"); - LAB_L->set_text ("--"); - LAB_A->set_text ("--"); - LAB_B->set_text ("--"); - } else { - float h, s, v; - float LAB_a, LAB_b, LAB_l; - Color::rgb2hsv01(r / 255.f, g / 255.f, b / 255.f, h, s, v); - getHSVText (h, s, v, s1, s2, s3); - H->set_text (s1); - S->set_text (s2); - V->set_text (s3); - - Color::rgb2lab01(profile, profileW, r / 255.f, g / 255.f, b / 255.f, LAB_l, LAB_a, LAB_b, options.rtSettings.HistogramWorking); // TODO: Really sure this function works? - getLABText (LAB_l, LAB_a, LAB_b, s1, s2, s3); - LAB_L->set_text (s1); - LAB_A->set_text (s2); - LAB_B->set_text (s3); - } - } + pointer_moved_delayed_call(validPos, profile, profileW, x, y, r, g, b, isRaw); } void Navigator::cycleUnitsRGB (GdkEventButton *event) { diff --git a/rtgui/navigator.h b/rtgui/navigator.h index e9d40e309..4c2a3fd32 100644 --- a/rtgui/navigator.h +++ b/rtgui/navigator.h @@ -20,6 +20,7 @@ #include +#include "delayed.h" #include "options.h" #include "pointermotionlistener.h" @@ -33,6 +34,8 @@ class Navigator final : typedef const double (*TMatrix)[3]; private: + DelayedCall pointer_moved_delayed_call; + Options::NavigatorUnit currentRGBUnit; Options::NavigatorUnit currentHSVUnit; void cycleUnitsRGB (GdkEventButton *event); @@ -53,7 +56,8 @@ protected: public: PreviewWindow* previewWindow; - Navigator (); + Navigator(); + ~Navigator() override; // pointermotionlistener interface // void pointerMoved (bool validPos, int x, int y, int r, int g, int b); diff --git a/rtgui/options.cc b/rtgui/options.cc index 625ac9918..ce03db434 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -400,6 +400,7 @@ void Options::setDefaults() overwriteOutputFile = false; // if TRUE, existing output JPGs/PNGs are overwritten, instead of adding ..-1.jpg, -2.jpg etc. theme = "RawTherapee"; maxThumbnailHeight = 250; + maxThumbnailWidth = 800; maxCacheEntries = 20000; thumbInterp = 1; autoSuffix = true; @@ -446,10 +447,12 @@ void Options::setDefaults() histogramBlue = true; histogramLuma = false; histogramChroma = false; - histogramRAW = false; histogramBar = true; histogramHeight = 200; histogramDrawMode = 0; + histogramScopeType = ScopeType::HISTOGRAM; + histogramShowOptionButtons = false; + histogramTraceBrightness = 1; curvebboxpos = 1; complexity = 2; inspectorWindow = false; @@ -1019,6 +1022,10 @@ void Options::readFromFile(Glib::ustring fname) maxThumbnailHeight = keyFile.get_integer("File Browser", "MaxPreviewHeight"); } + if (keyFile.has_key("File Browser", "MaxPreviewWidth")) { + maxThumbnailWidth = keyFile.get_integer("File Browser", "MaxPreviewWidth"); + } + if (keyFile.has_key("File Browser", "MaxCacheEntries")) { maxCacheEntries = keyFile.get_integer("File Browser", "MaxCacheEntries"); } @@ -1419,7 +1426,10 @@ void Options::readFromFile(Glib::ustring fname) } if (keyFile.has_key("GUI", "HistogramRAW")) { - histogramRAW = keyFile.get_boolean("GUI", "HistogramRAW"); + // Legacy option, replaced by HistogramScopeType. + if (keyFile.get_boolean("GUI", "HistogramRAW")) { + histogramScopeType = ScopeType::HISTOGRAM_RAW; + } } if (keyFile.has_key("GUI", "HistogramBar")) { @@ -1434,6 +1444,18 @@ void Options::readFromFile(Glib::ustring fname) histogramDrawMode = keyFile.get_integer("GUI", "HistogramDrawMode"); } + if (keyFile.has_key("GUI", "HistogramScopeType")) { + histogramScopeType = static_cast(keyFile.get_integer("GUI", "HistogramScopeType")); + } + + if (keyFile.has_key("GUI", "HistogramShowOptionButtons")) { + histogramShowOptionButtons = keyFile.get_boolean("GUI", "HistogramShowOptionButtons"); + } + + if (keyFile.has_key("GUI", "HistogramTraceBrightness")) { + histogramTraceBrightness = keyFile.get_double("GUI", "HistogramTraceBrightness"); + } + if (keyFile.has_key("GUI", "NavigatorRGBUnit")) { navRGBUnit = (NavigatorUnit)keyFile.get_integer("GUI", "NavigatorRGBUnit"); } @@ -2106,6 +2128,7 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_integer("File Browser", "ThumbnailSizeQueue", thumbSizeQueue); keyFile.set_integer("File Browser", "SameThumbSize", sameThumbSize); keyFile.set_integer("File Browser", "MaxPreviewHeight", maxThumbnailHeight); + keyFile.set_integer("File Browser", "MaxPreviewWidth", maxThumbnailWidth); keyFile.set_integer("File Browser", "MaxCacheEntries", maxCacheEntries); Glib::ArrayHandle pext = parseExtensions; keyFile.set_string_list("File Browser", "ParseExtensions", pext); @@ -2260,10 +2283,12 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_boolean("GUI", "HistogramBlue", histogramBlue); keyFile.set_boolean("GUI", "HistogramLuma", histogramLuma); keyFile.set_boolean("GUI", "HistogramChroma", histogramChroma); - keyFile.set_boolean("GUI", "HistogramRAW", histogramRAW); keyFile.set_boolean("GUI", "HistogramBar", histogramBar); keyFile.set_integer("GUI", "HistogramHeight", histogramHeight); keyFile.set_integer("GUI", "HistogramDrawMode", histogramDrawMode); + keyFile.set_integer("GUI", "HistogramScopeType", rtengine::toUnderlying(histogramScopeType)); + keyFile.set_boolean("GUI", "HistogramShowOptionButtons", histogramShowOptionButtons); + keyFile.set_double("GUI", "HistogramTraceBrightness", histogramTraceBrightness); keyFile.set_integer("GUI", "NavigatorRGBUnit", (int)navRGBUnit); keyFile.set_integer("GUI", "NavigatorHSVUnit", (int)navHSVUnit); keyFile.set_boolean("GUI", "ShowFilmStripToolBar", showFilmStripToolBar); diff --git a/rtgui/options.h b/rtgui/options.h index fcac5c7bb..03b551efe 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -168,13 +168,23 @@ private: const Glib::ustring& entryName, Glib::ustring& destination); public: - enum class NavigatorUnit { PERCENT, R0_255, R0_1, _COUNT }; + + enum class ScopeType { + NONE = -1, + HISTOGRAM, + HISTOGRAM_RAW, + PARADE, + VECTORSCOPE_HC, + VECTORSCOPE_HS, + WAVEFORM + }; + bool savesParamsAtExit; SaveFormat saveFormat, saveFormatBatch; Glib::ustring savePathTemplate; @@ -271,6 +281,7 @@ public: CPBKeyType CPBKeys; // Custom Profile Builder's key type int editorToSendTo; int maxThumbnailHeight; + int maxThumbnailWidth; std::size_t maxCacheEntries; int thumbInterp; // 0: nearest, 1: bilinear std::vector parseExtensions; // List containing all extensions type @@ -310,10 +321,13 @@ public: int histogramPosition; // 0=disabled, 1=left pane, 2=right pane bool histogramRed, histogramGreen, histogramBlue; - bool histogramLuma, histogramChroma, histogramRAW; + bool histogramLuma, histogramChroma; bool histogramBar; int histogramHeight; int histogramDrawMode; + ScopeType histogramScopeType; + bool histogramShowOptionButtons; + float histogramTraceBrightness; bool FileBrowserToolbarSingleRow; bool hideTPVScrollbar; int whiteBalanceSpotSize; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 3cd93064e..fbe9d7315 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -244,6 +244,7 @@ void ParamsEdited::set(bool v) colorappearance.curveMode = v; colorappearance.curveMode2 = v; colorappearance.curveMode3 = v; + colorappearance.complexmethod = v; colorappearance.tempout = v; colorappearance.autotempout = v; colorappearance.greenout = v; @@ -354,6 +355,7 @@ void ParamsEdited::set(bool v) perspective.projection_shift_horiz = v; perspective.projection_shift_vert = v; perspective.projection_yaw = v; + perspective.control_lines = v; gradient.enabled = v; gradient.degree = v; gradient.feather = v; @@ -515,6 +517,10 @@ void ParamsEdited::set(bool v) wavelet.bluelow = v; wavelet.lipst = v; wavelet.ballum = v; + wavelet.sigm = v; + wavelet.levden = v; + wavelet.thrden = v; + wavelet.limden = v; wavelet.balchrom = v; wavelet.chromfi = v; wavelet.chromco = v; @@ -522,6 +528,9 @@ void ParamsEdited::set(bool v) wavelet.mergeC = v; wavelet.softrad = v; wavelet.softradend = v; + wavelet.strend = v; + wavelet.detend = v; + wavelet.thrend = v; wavelet.Medgreinf = v; wavelet.ushamethod = v; wavelet.avoid = v; @@ -533,6 +542,10 @@ void ParamsEdited::set(bool v) wavelet.Backmethod = v; wavelet.Tilesmethod = v; wavelet.complexmethod = v; + wavelet.denmethod = v; + wavelet.mixmethod = v; + wavelet.slimethod = v; + wavelet.quamethod = v; wavelet.daubcoeffmethod = v; wavelet.CHmethod = v; wavelet.CHSLmethod = v; @@ -586,14 +599,20 @@ void ParamsEdited::set(bool v) wavelet.level1noise = v; wavelet.level2noise = v; wavelet.level3noise = v; + wavelet.leveldenoise = v; + wavelet.levelsigm = v; wavelet.ccwcurve = v; wavelet.blcurve = v; wavelet.opacityCurveSH = v; wavelet.opacityCurveRG = v; wavelet.opacityCurveBY = v; + wavelet.wavdenoise = v; + wavelet.wavdenoiseh = v; wavelet.opacityCurveW = v; wavelet.opacityCurveWL = v; wavelet.hhcurve = v; + wavelet.wavguidcurve = v; + wavelet.wavhuecurve = v; wavelet.Chcurve = v; wavelet.wavclCurve = v; @@ -894,6 +913,7 @@ void ParamsEdited::initFrom(const std::vector& colorappearance.curveMode = colorappearance.curveMode && p.colorappearance.curveMode == other.colorappearance.curveMode; colorappearance.curveMode2 = colorappearance.curveMode2 && p.colorappearance.curveMode2 == other.colorappearance.curveMode2; colorappearance.curveMode3 = colorappearance.curveMode3 && p.colorappearance.curveMode3 == other.colorappearance.curveMode3; + colorappearance.complexmethod = colorappearance.complexmethod && p.colorappearance.complexmethod == other.colorappearance.complexmethod; colorappearance.tempout = colorappearance.tempout && p.colorappearance.tempout == other.colorappearance.tempout; colorappearance.autotempout = colorappearance.autotempout && p.colorappearance.autotempout == other.colorappearance.autotempout; colorappearance.greenout = colorappearance.greenout && p.colorappearance.greenout == other.colorappearance.greenout; @@ -1009,6 +1029,7 @@ void ParamsEdited::initFrom(const std::vector& perspective.projection_shift_horiz = perspective.projection_shift_horiz && p.perspective.projection_shift_horiz == other.perspective.projection_shift_horiz; perspective.projection_shift_vert = perspective.projection_shift_vert && p.perspective.projection_shift_vert == other.perspective.projection_shift_vert; perspective.projection_yaw = perspective.projection_yaw && p.perspective.projection_yaw == other.perspective.projection_yaw; + perspective.control_lines = perspective.control_lines && p.perspective.control_line_values == other.perspective.control_line_values && p.perspective.control_line_types == other.perspective.control_line_types; gradient.enabled = gradient.enabled && p.gradient.enabled == other.gradient.enabled; gradient.degree = gradient.degree && p.gradient.degree == other.gradient.degree; gradient.feather = gradient.feather && p.gradient.feather == other.gradient.feather; @@ -1051,6 +1072,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).colorscope = locallab.spots.at(j).colorscope && pSpot.colorscope == otherSpot.colorscope; locallab.spots.at(j).transitweak = locallab.spots.at(j).transitweak && pSpot.transitweak == otherSpot.transitweak; locallab.spots.at(j).transitgrad = locallab.spots.at(j).transitgrad && pSpot.transitgrad == otherSpot.transitgrad; + locallab.spots.at(j).hishow = locallab.spots.at(j).hishow && pSpot.hishow == otherSpot.hishow; locallab.spots.at(j).activ = locallab.spots.at(j).activ && pSpot.activ == otherSpot.activ; locallab.spots.at(j).avoid = locallab.spots.at(j).avoid && pSpot.avoid == otherSpot.avoid; locallab.spots.at(j).blwh = locallab.spots.at(j).blwh && pSpot.blwh == otherSpot.blwh; @@ -1256,6 +1278,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).epsbl = locallab.spots.at(j).epsbl && pSpot.epsbl == otherSpot.epsbl; locallab.spots.at(j).blMethod = locallab.spots.at(j).blMethod && pSpot.blMethod == otherSpot.blMethod; locallab.spots.at(j).chroMethod = locallab.spots.at(j).chroMethod && pSpot.chroMethod == otherSpot.chroMethod; + locallab.spots.at(j).quamethod = locallab.spots.at(j).quamethod && pSpot.quamethod == otherSpot.quamethod; locallab.spots.at(j).blurMethod = locallab.spots.at(j).blurMethod && pSpot.blurMethod == otherSpot.blurMethod; locallab.spots.at(j).medMethod = locallab.spots.at(j).medMethod && pSpot.medMethod == otherSpot.medMethod; locallab.spots.at(j).activlum = locallab.spots.at(j).activlum && pSpot.activlum == otherSpot.activlum; @@ -1279,6 +1302,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).HHmaskblcurve = locallab.spots.at(j).HHmaskblcurve && pSpot.HHmaskblcurve == otherSpot.HHmaskblcurve; locallab.spots.at(j).enablMask = locallab.spots.at(j).enablMask && pSpot.enablMask == otherSpot.enablMask; locallab.spots.at(j).fftwbl = locallab.spots.at(j).fftwbl && pSpot.fftwbl == otherSpot.fftwbl; + locallab.spots.at(j).invbl = locallab.spots.at(j).invbl && pSpot.invbl == otherSpot.invbl; locallab.spots.at(j).toolbl = locallab.spots.at(j).toolbl && pSpot.toolbl == otherSpot.toolbl; locallab.spots.at(j).blendmaskbl = locallab.spots.at(j).blendmaskbl && pSpot.blendmaskbl == otherSpot.blendmaskbl; locallab.spots.at(j).radmaskbl = locallab.spots.at(j).radmaskbl && pSpot.radmaskbl == otherSpot.radmaskbl; @@ -1472,12 +1496,19 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).explog = locallab.spots.at(j).explog && pSpot.explog == otherSpot.explog; locallab.spots.at(j).autocompute = locallab.spots.at(j).autocompute && pSpot.autocompute == otherSpot.autocompute; locallab.spots.at(j).sourceGray = locallab.spots.at(j).sourceGray && pSpot.sourceGray == otherSpot.sourceGray; + locallab.spots.at(j).sourceabs = locallab.spots.at(j).sourceabs && pSpot.sourceabs == otherSpot.sourceabs; + locallab.spots.at(j).targabs = locallab.spots.at(j).targabs && pSpot.targabs == otherSpot.targabs; locallab.spots.at(j).targetGray = locallab.spots.at(j).targetGray && pSpot.targetGray == otherSpot.targetGray; + locallab.spots.at(j).catad = locallab.spots.at(j).catad && pSpot.catad == otherSpot.catad; + locallab.spots.at(j).saturl = locallab.spots.at(j).saturl && pSpot.saturl == otherSpot.saturl; + locallab.spots.at(j).contl = locallab.spots.at(j).contl && pSpot.contl == otherSpot.contl; locallab.spots.at(j).Autogray = locallab.spots.at(j).Autogray && pSpot.Autogray == otherSpot.Autogray; locallab.spots.at(j).fullimage = locallab.spots.at(j).fullimage && pSpot.fullimage == otherSpot.fullimage; + locallab.spots.at(j).ciecam = locallab.spots.at(j).ciecam && pSpot.ciecam == otherSpot.ciecam; locallab.spots.at(j).blackEv = locallab.spots.at(j).blackEv && pSpot.blackEv == otherSpot.blackEv; locallab.spots.at(j).whiteEv = locallab.spots.at(j).whiteEv && pSpot.whiteEv == otherSpot.whiteEv; locallab.spots.at(j).detail = locallab.spots.at(j).detail && pSpot.detail == otherSpot.detail; + locallab.spots.at(j).surround = locallab.spots.at(j).surround && pSpot.surround == otherSpot.surround; locallab.spots.at(j).sensilog = locallab.spots.at(j).sensilog && pSpot.sensilog == otherSpot.sensilog; locallab.spots.at(j).baselog = locallab.spots.at(j).baselog && pSpot.baselog == otherSpot.baselog; locallab.spots.at(j).strlog = locallab.spots.at(j).strlog && pSpot.strlog == otherSpot.strlog; @@ -1666,6 +1697,10 @@ void ParamsEdited::initFrom(const std::vector& wavelet.lipst = wavelet.lipst && p.wavelet.lipst == other.wavelet.lipst; wavelet.bluehigh = wavelet.bluehigh && p.wavelet.bluehigh == other.wavelet.bluehigh; wavelet.ballum = wavelet.ballum && p.wavelet.ballum == other.wavelet.ballum; + wavelet.sigm = wavelet.sigm && p.wavelet.sigm == other.wavelet.sigm; + wavelet.levden = wavelet.levden && p.wavelet.levden == other.wavelet.levden; + wavelet.thrden = wavelet.thrden && p.wavelet.thrden == other.wavelet.thrden; + wavelet.limden = wavelet.limden && p.wavelet.limden == other.wavelet.limden; wavelet.balchrom = wavelet.balchrom && p.wavelet.balchrom == other.wavelet.balchrom; wavelet.chromfi = wavelet.chromfi && p.wavelet.chromfi == other.wavelet.chromfi; wavelet.chromco = wavelet.chromco && p.wavelet.chromco == other.wavelet.chromco; @@ -1673,6 +1708,9 @@ void ParamsEdited::initFrom(const std::vector& wavelet.mergeC = wavelet.mergeC && p.wavelet.mergeC == other.wavelet.mergeC; wavelet.softrad = wavelet.softrad && p.wavelet.softrad == other.wavelet.softrad; wavelet.softradend = wavelet.softradend && p.wavelet.softradend == other.wavelet.softradend; + wavelet.strend = wavelet.strend && p.wavelet.strend == other.wavelet.strend; + wavelet.detend = wavelet.detend && p.wavelet.detend == other.wavelet.detend; + wavelet.thrend = wavelet.thrend && p.wavelet.thrend == other.wavelet.thrend; wavelet.ushamethod = wavelet.ushamethod && p.wavelet.ushamethod == other.wavelet.ushamethod; wavelet.avoid = wavelet.avoid && p.wavelet.avoid == other.wavelet.avoid; wavelet.showmask = wavelet.showmask && p.wavelet.showmask == other.wavelet.showmask; @@ -1683,6 +1721,10 @@ void ParamsEdited::initFrom(const std::vector& wavelet.Backmethod = wavelet.Backmethod && p.wavelet.Backmethod == other.wavelet.Backmethod; wavelet.Tilesmethod = wavelet.Tilesmethod && p.wavelet.Tilesmethod == other.wavelet.Tilesmethod; wavelet.complexmethod = wavelet.complexmethod && p.wavelet.complexmethod == other.wavelet.complexmethod; + wavelet.denmethod = wavelet.denmethod && p.wavelet.denmethod == other.wavelet.denmethod; + wavelet.mixmethod = wavelet.mixmethod && p.wavelet.mixmethod == other.wavelet.mixmethod; + wavelet.slimethod = wavelet.slimethod && p.wavelet.slimethod == other.wavelet.slimethod; + wavelet.quamethod = wavelet.quamethod && p.wavelet.quamethod == other.wavelet.quamethod; wavelet.daubcoeffmethod = wavelet.daubcoeffmethod && p.wavelet.daubcoeffmethod == other.wavelet.daubcoeffmethod; wavelet.CHmethod = wavelet.CHmethod && p.wavelet.CHmethod == other.wavelet.CHmethod; wavelet.CHSLmethod = wavelet.CHSLmethod && p.wavelet.CHSLmethod == other.wavelet.CHSLmethod; @@ -1735,6 +1777,8 @@ void ParamsEdited::initFrom(const std::vector& wavelet.level1noise = wavelet.level1noise && p.wavelet.level1noise == other.wavelet.level1noise; wavelet.level2noise = wavelet.level2noise && p.wavelet.level2noise == other.wavelet.level2noise; wavelet.level3noise = wavelet.level3noise && p.wavelet.level3noise == other.wavelet.level3noise; + wavelet.leveldenoise = wavelet.leveldenoise && p.wavelet.leveldenoise == other.wavelet.leveldenoise; + wavelet.levelsigm = wavelet.levelsigm && p.wavelet.levelsigm == other.wavelet.levelsigm; wavelet.pastlev = wavelet.pastlev && p.wavelet.pastlev == other.wavelet.pastlev; wavelet.satlev = wavelet.satlev && p.wavelet.satlev == other.wavelet.satlev; wavelet.ccwcurve = wavelet.ccwcurve && p.wavelet.ccwcurve == other.wavelet.ccwcurve; @@ -1742,10 +1786,14 @@ void ParamsEdited::initFrom(const std::vector& wavelet.opacityCurveSH = wavelet.opacityCurveSH && p.wavelet.opacityCurveSH == other.wavelet.opacityCurveSH; wavelet.opacityCurveRG = wavelet.opacityCurveRG && p.wavelet.opacityCurveRG == other.wavelet.opacityCurveRG; wavelet.opacityCurveBY = wavelet.opacityCurveBY && p.wavelet.opacityCurveBY == other.wavelet.opacityCurveBY; + wavelet.wavdenoise = wavelet.wavdenoise && p.wavelet.wavdenoise == other.wavelet.wavdenoise; + wavelet.wavdenoiseh = wavelet.wavdenoiseh && p.wavelet.wavdenoiseh == other.wavelet.wavdenoiseh; wavelet.opacityCurveW = wavelet.opacityCurveW && p.wavelet.opacityCurveW == other.wavelet.opacityCurveW; wavelet.opacityCurveWL = wavelet.opacityCurveWL && p.wavelet.opacityCurveWL == other.wavelet.opacityCurveWL; wavelet.wavclCurve = wavelet.wavclCurve && p.wavelet.wavclCurve == other.wavelet.wavclCurve; wavelet.hhcurve = wavelet.hhcurve && p.wavelet.hhcurve == other.wavelet.hhcurve; + wavelet.wavguidcurve = wavelet.wavguidcurve && p.wavelet.wavguidcurve == other.wavelet.wavguidcurve; + wavelet.wavhuecurve = wavelet.wavhuecurve && p.wavelet.wavhuecurve == other.wavelet.wavhuecurve; wavelet.Chcurve = wavelet.Chcurve && p.wavelet.Chcurve == other.wavelet.Chcurve; wavelet.skinprotect = wavelet.skinprotect && p.wavelet.skinprotect == other.wavelet.skinprotect; // wavelet.enacont = wavelet.enacont && p.wavelet.enacont == other.wavelet.enacont; @@ -2566,6 +2614,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.colorappearance.curveMode3 = mods.colorappearance.curveMode3; } + if (colorappearance.complexmethod) { + toEdit.colorappearance.complexmethod = mods.colorappearance.complexmethod; + } + if (colorappearance.enabled) { toEdit.colorappearance.enabled = mods.colorappearance.enabled; } @@ -3025,6 +3077,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.perspective.projection_yaw = dontforceSet && options.baBehav[ADDSET_PERSP_PROJ_ANGLE] ? toEdit.perspective.projection_yaw + mods.perspective.projection_yaw : mods.perspective.projection_yaw; } + if (perspective.control_lines) { + toEdit.perspective.control_line_values = mods.perspective.control_line_values; + toEdit.perspective.control_line_types = mods.perspective.control_line_types; + } + if (gradient.enabled) { toEdit.gradient.enabled = mods.gradient.enabled; } @@ -3168,6 +3225,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).transitgrad = mods.locallab.spots.at(i).transitgrad; } + if (locallab.spots.at(i).hishow) { + toEdit.locallab.spots.at(i).hishow = mods.locallab.spots.at(i).hishow; + } + if (locallab.spots.at(i).activ) { toEdit.locallab.spots.at(i).activ = mods.locallab.spots.at(i).activ; } @@ -3956,6 +4017,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).chroMethod = mods.locallab.spots.at(i).chroMethod; } + if (locallab.spots.at(i).quamethod) { + toEdit.locallab.spots.at(i).quamethod = mods.locallab.spots.at(i).quamethod; + } + if (locallab.spots.at(i).blurMethod) { toEdit.locallab.spots.at(i).blurMethod = mods.locallab.spots.at(i).blurMethod; } @@ -4048,6 +4113,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).fftwbl = mods.locallab.spots.at(i).fftwbl; } + if (locallab.spots.at(i).invbl) { + toEdit.locallab.spots.at(i).invbl = mods.locallab.spots.at(i).invbl; + } + if (locallab.spots.at(i).toolbl) { toEdit.locallab.spots.at(i).toolbl = mods.locallab.spots.at(i).toolbl; } @@ -4789,10 +4858,30 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).sourceGray = mods.locallab.spots.at(i).sourceGray; } + if (locallab.spots.at(i).sourceabs) { + toEdit.locallab.spots.at(i).sourceabs = mods.locallab.spots.at(i).sourceabs; + } + + if (locallab.spots.at(i).targabs) { + toEdit.locallab.spots.at(i).targabs = mods.locallab.spots.at(i).targabs; + } + if (locallab.spots.at(i).targetGray) { toEdit.locallab.spots.at(i).targetGray = mods.locallab.spots.at(i).targetGray; } + if (locallab.spots.at(i).catad) { + toEdit.locallab.spots.at(i).catad = mods.locallab.spots.at(i).catad; + } + + if (locallab.spots.at(i).saturl) { + toEdit.locallab.spots.at(i).saturl = mods.locallab.spots.at(i).saturl; + } + + if (locallab.spots.at(i).contl) { + toEdit.locallab.spots.at(i).contl = mods.locallab.spots.at(i).contl; + } + if (locallab.spots.at(i).Autogray) { toEdit.locallab.spots.at(i).Autogray = mods.locallab.spots.at(i).Autogray; } @@ -4801,6 +4890,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).fullimage = mods.locallab.spots.at(i).fullimage; } + if (locallab.spots.at(i).ciecam) { + toEdit.locallab.spots.at(i).ciecam = mods.locallab.spots.at(i).ciecam; + } + if (locallab.spots.at(i).blackEv) { toEdit.locallab.spots.at(i).blackEv = mods.locallab.spots.at(i).blackEv; } @@ -4821,6 +4914,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).baselog = mods.locallab.spots.at(i).baselog; } + if (locallab.spots.at(i).surround) { + toEdit.locallab.spots.at(i).surround = mods.locallab.spots.at(i).surround; + } + if (locallab.spots.at(i).strlog) { toEdit.locallab.spots.at(i).strlog = mods.locallab.spots.at(i).strlog; } @@ -5510,6 +5607,22 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.ballum = mods.wavelet.ballum; } + if (wavelet.sigm) { + toEdit.wavelet.sigm = mods.wavelet.sigm; + } + + if (wavelet.levden) { + toEdit.wavelet.levden = mods.wavelet.levden; + } + + if (wavelet.thrden) { + toEdit.wavelet.thrden = mods.wavelet.thrden; + } + + if (wavelet.limden) { + toEdit.wavelet.limden = mods.wavelet.limden; + } + if (wavelet.balchrom) { toEdit.wavelet.balchrom = mods.wavelet.balchrom; } @@ -5538,6 +5651,18 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.softradend = mods.wavelet.softradend; } + if (wavelet.strend) { + toEdit.wavelet.strend = mods.wavelet.strend; + } + + if (wavelet.detend) { + toEdit.wavelet.detend = mods.wavelet.detend; + } + + if (wavelet.thrend) { + toEdit.wavelet.thrend = mods.wavelet.thrend; + } + if (wavelet.lipst) { toEdit.wavelet.lipst = mods.wavelet.lipst; } @@ -5586,6 +5711,22 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.complexmethod = mods.wavelet.complexmethod; } + if (wavelet.denmethod) { + toEdit.wavelet.denmethod = mods.wavelet.denmethod; + } + + if (wavelet.mixmethod) { + toEdit.wavelet.mixmethod = mods.wavelet.mixmethod; + } + + if (wavelet.slimethod) { + toEdit.wavelet.slimethod = mods.wavelet.slimethod; + } + + if (wavelet.quamethod) { + toEdit.wavelet.quamethod = mods.wavelet.quamethod; + } + if (wavelet.daubcoeffmethod) { toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; } @@ -5682,6 +5823,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.level3noise = mods.wavelet.level3noise; } + if (wavelet.leveldenoise) { + toEdit.wavelet.leveldenoise = mods.wavelet.leveldenoise; + } + + if (wavelet.levelsigm) { + toEdit.wavelet.levelsigm = mods.wavelet.levelsigm; + } + if (wavelet.pastlev) { toEdit.wavelet.pastlev = mods.wavelet.pastlev; } @@ -5710,6 +5859,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.opacityCurveBY = mods.wavelet.opacityCurveBY; } + if (wavelet.wavdenoise) { + toEdit.wavelet.wavdenoise = mods.wavelet.wavdenoise; + } + + if (wavelet.wavdenoiseh) { + toEdit.wavelet.wavdenoiseh = mods.wavelet.wavdenoiseh; + } + if (wavelet.opacityCurveW) { toEdit.wavelet.opacityCurveW = mods.wavelet.opacityCurveW; } @@ -5722,6 +5879,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.hhcurve = mods.wavelet.hhcurve; } + if (wavelet.wavguidcurve) { + toEdit.wavelet.wavguidcurve = mods.wavelet.wavguidcurve; + } + + if (wavelet.wavhuecurve) { + toEdit.wavelet.wavhuecurve = mods.wavelet.wavhuecurve; + } + if (wavelet.Chcurve) { toEdit.wavelet.Chcurve = mods.wavelet.Chcurve; } @@ -6094,6 +6259,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : colorscope(v), transitweak(v), transitgrad(v), + hishow(v), activ(v), avoid(v), blwh(v), @@ -6295,6 +6461,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : epsbl(v), blMethod(v), chroMethod(v), + quamethod(v), blurMethod(v), medMethod(v), activlum(v), @@ -6318,6 +6485,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : HHmaskblcurve(v), enablMask(v), fftwbl(v), + invbl(v), toolbl(v), blendmaskbl(v), radmaskbl(v), @@ -6507,12 +6675,19 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : explog(v), autocompute(v), sourceGray(v), + sourceabs(v), + targabs(v), targetGray(v), + catad(v), + saturl(v), + contl(v), Autogray(v), fullimage(v), + ciecam(v), blackEv(v), whiteEv(v), detail(v), + surround(v), sensilog(v), baselog(v), strlog(v), @@ -6578,6 +6753,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) colorscope = v; transitweak = v; transitgrad = v; + hishow = v; activ = v; avoid = v; blwh = v; @@ -6783,6 +6959,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) epsbl = v; blMethod = v; chroMethod = v; + quamethod = v; blurMethod = v; medMethod = v; activlum = v; @@ -6806,6 +6983,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) HHmaskblcurve = v; enablMask = v; fftwbl = v; + invbl = v; toolbl = v; blendmaskbl = v; radmaskbl = v; @@ -6999,12 +7177,19 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) explog = v; autocompute = v; sourceGray = v; + sourceabs = v; + targabs = v; targetGray = v; + catad = v; + saturl = v; + contl = v; Autogray = v; fullimage = v; + ciecam = v; blackEv = v; whiteEv = v; detail = v; + surround = v; sensilog = v; baselog = v; strlog = v; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index f8230a577..a66399883 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -266,6 +266,7 @@ struct ColorAppearanceParamsEdited { bool curveMode; bool curveMode2; bool curveMode3; + bool complexmethod; bool enabled; bool degree; bool autodegree; @@ -415,6 +416,7 @@ public: bool colorscope; bool transitweak; bool transitgrad; + bool hishow; bool activ; bool avoid; bool blwh; @@ -616,6 +618,7 @@ public: bool epsbl; bool blMethod; bool chroMethod; + bool quamethod; bool blurMethod; bool medMethod; bool activlum; @@ -639,6 +642,7 @@ public: bool HHmaskblcurve; bool enablMask; bool fftwbl; + bool invbl; bool toolbl; bool blendmaskbl; bool radmaskbl; @@ -828,12 +832,19 @@ public: bool explog; bool autocompute; bool sourceGray; + bool sourceabs; + bool targabs; bool targetGray; + bool catad; + bool saturl; + bool contl; bool Autogray; bool fullimage; + bool ciecam; bool blackEv; bool whiteEv; bool detail; + bool surround; bool sensilog; bool baselog; bool strlog; @@ -911,6 +922,7 @@ struct PerspectiveParamsEdited { bool projection_shift_horiz; bool projection_shift_vert; bool projection_yaw; + bool control_lines; }; struct GradientParamsEdited { @@ -1041,6 +1053,10 @@ struct WaveletParamsEdited { bool Backmethod; bool Tilesmethod; bool complexmethod; + bool denmethod; + bool mixmethod; + bool slimethod; + bool quamethod; bool daubcoeffmethod; bool Dirmethod; bool sigma; @@ -1087,14 +1103,20 @@ struct WaveletParamsEdited { bool level1noise; bool level2noise; bool level3noise; + bool leveldenoise; + bool levelsigm; bool ccwcurve; bool blcurve; bool opacityCurveSH; bool opacityCurveBY; + bool wavdenoise; + bool wavdenoiseh; bool opacityCurveRG; bool opacityCurveW; bool opacityCurveWL; bool hhcurve; + bool wavguidcurve; + bool wavhuecurve; bool Chcurve; bool pastlev; bool satlev; @@ -1106,6 +1128,10 @@ struct WaveletParamsEdited { bool greenhigh; bool bluehigh; bool ballum; + bool sigm; + bool levden; + bool thrden; + bool limden; bool balchrom; bool chromfi; bool chromco; @@ -1113,6 +1139,9 @@ struct WaveletParamsEdited { bool mergeC; bool softrad; bool softradend; + bool strend; + bool detend; + bool thrend; bool expcontrast; bool expchroma; bool expedge; diff --git a/rtgui/pdsharpening.cc b/rtgui/pdsharpening.cc index 8bbf19620..1b98fd3ac 100644 --- a/rtgui/pdsharpening.cc +++ b/rtgui/pdsharpening.cc @@ -81,10 +81,10 @@ PdSharpening::PdSharpening() : dradiusOffset->setAdjusterListener(this); diter->setAdjusterListener(this); - contrast->delay = std::max(contrast->delay, options.adjusterMaxDelay); - dradius->delay = std::max(dradius->delay, options.adjusterMaxDelay); - dradiusOffset->delay = std::max(dradiusOffset->delay, options.adjusterMaxDelay); - diter->delay = std::max(diter->delay, options.adjusterMaxDelay); + contrast->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); + dradius->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); + dradiusOffset->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); + diter->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); } PdSharpening::~PdSharpening() diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index bdba2dcc1..55013ec4a 100644 --- a/rtgui/perspective.cc +++ b/rtgui/perspective.cc @@ -20,16 +20,75 @@ #include "perspective.h" #include "rtimage.h" +#include "rtsurface.h" #include "../rtengine/procparams.h" using namespace rtengine; using namespace rtengine::procparams; +namespace +{ + +void controlLinesToValues(const std::vector& lines, + std::vector& values, std::vector& types) +{ + values.clear(); + types.clear(); + + for (auto&& line : lines) { + values.push_back(line.x1); + values.push_back(line.y1); + values.push_back(line.x2); + values.push_back(line.y2); + + int type = -1; + switch (line.type) { + case rtengine::ControlLine::VERTICAL: + type = 0; + break; + case rtengine::ControlLine::HORIZONTAL: + type = 1; + break; + } + types.push_back(type); + } +} + +std::vector valuesToControlLines( + const std::vector& values, const std::vector& types) +{ + int line_count = min(values.size() / 4, types.size()); + std::vector lines(line_count); + + auto values_iter = values.begin(); + auto types_iter = types.begin(); + for (auto&& line : lines) { + line.x1 = *(values_iter++); + line.y1 = *(values_iter++); + line.x2 = *(values_iter++); + line.y2 = *(values_iter++); + + switch (*(types_iter++)) { + case 0: + line.type = rtengine::ControlLine::VERTICAL; + break; + case 1: + line.type = rtengine::ControlLine::HORIZONTAL; + break; + } + } + + return lines; +} + +} + PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M("TP_PERSPECTIVE_LABEL")) { auto mapper = ProcEventMapper::getInstance(); + // Normal events. EvPerspCamAngle = mapper->newEvent(TRANSFORM, "HISTORY_MSG_PERSP_CAM_ANGLE"); EvPerspCamFocalLength = mapper->newEvent(TRANSFORM, "HISTORY_MSG_PERSP_CAM_FL"); EvPerspCamShift = mapper->newEvent(TRANSFORM, "HISTORY_MSG_PERSP_CAM_SHIFT"); @@ -37,9 +96,25 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M(" EvPerspProjAngle = mapper->newEvent(TRANSFORM, "HISTORY_MSG_PERSP_PROJ_ANGLE"); EvPerspProjRotate = mapper->newEvent(TRANSFORM, "HISTORY_MSG_PERSP_PROJ_ROTATE"); EvPerspProjShift = mapper->newEvent(TRANSFORM, "HISTORY_MSG_PERSP_PROJ_SHIFT"); + EvPerspRender = mapper->newEvent(TRANSFORM); + // Void events. + EvPerspCamAngleVoid = mapper->newEvent(M_VOID, "HISTORY_MSG_PERSP_CAM_ANGLE"); + EvPerspCamFocalLengthVoid = mapper->newEvent(M_VOID, "HISTORY_MSG_PERSP_CAM_FL"); + EvPerspCamShiftVoid = mapper->newEvent(M_VOID, "HISTORY_MSG_PERSP_CAM_SHIFT"); + EvPerspProjAngleVoid = mapper->newEvent(M_VOID, "HISTORY_MSG_PERSP_PROJ_ANGLE"); + EvPerspProjRotateVoid = mapper->newEvent(M_VOID, "HISTORY_MSG_PERSP_PROJ_ROTATE"); + EvPerspProjShiftVoid = mapper->newEvent(M_VOID, "HISTORY_MSG_PERSP_PROJ_SHIFT"); + setCamBasedEventsActive(); + EvPerspControlLines = mapper->newEvent(M_VOID, "HISTORY_MSG_PERSP_CTRL_LINE"); + lens_geom_listener = nullptr; + panel_listener = nullptr; metadata = nullptr; + Gtk::Image* ipers_draw(new RTImage ("draw.png")); + Gtk::Image* ipers_trash = Gtk::manage (new RTImage ("trash-empty.png")); + Gtk::Image* ipers_apply = Gtk::manage (new RTImage ("tick.png")); + Gtk::Image* ipersHL = Gtk::manage (new RTImage ("perspective-horizontal-left-small.png")); Gtk::Image* ipersHR = Gtk::manage (new RTImage ("perspective-horizontal-right-small.png")); Gtk::Image* ipersVL = Gtk::manage (new RTImage ("perspective-vertical-bottom-small.png")); @@ -108,6 +183,39 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M(" -60, 60, 0.1, 0, ipers_cam_yaw_left, ipers_cam_yaw_right)); camera_yaw->setAdjusterListener (this); + // Begin control lines interface. + lines_button_apply = Gtk::manage (new Gtk::Button()); + lines_button_apply->set_image(*ipers_apply); + lines_button_apply->set_tooltip_text(M("GENERAL_APPLY")); + lines_button_apply->set_sensitive(false); + lines_button_apply->signal_pressed().connect(sigc::mem_fun( + *this, &::PerspCorrection::linesApplyButtonPressed)); + + lines_button_edit = Gtk::manage (new Gtk::ToggleButton()); + lines_button_edit->set_image(*ipers_draw); + lines_button_edit->set_tooltip_text(M("GENERAL_EDIT")); + lines_button_edit->signal_toggled().connect(sigc::mem_fun( + *this, &::PerspCorrection::linesEditButtonPressed)); + + lines_button_erase = Gtk::manage (new Gtk::Button()); + lines_button_erase->set_image(*ipers_trash); + lines_button_erase->set_tooltip_text(M("GENERAL_DELETE_ALL")); + lines_button_erase->set_sensitive(false); + lines_button_erase->signal_pressed().connect(sigc::mem_fun( + *this, &::PerspCorrection::linesEraseButtonPressed)); + + lines = std::unique_ptr(new ControlLineManager()); + lines->callbacks = std::make_shared(this); + + Gtk::HBox* control_lines_box = Gtk::manage (new Gtk::HBox()); + Gtk::Label* control_lines_label = Gtk::manage (new Gtk::Label (M("TP_PERSPECTIVE_CONTROL_LINES") + ": ")); + control_lines_label->set_tooltip_markup( M("TP_PERSPECTIVE_CONTROL_LINES_TOOLTIP") ); + control_lines_box->pack_start(*control_lines_label, Gtk::PACK_SHRINK); + control_lines_box->pack_start(*lines_button_edit); + control_lines_box->pack_start(*lines_button_apply); + control_lines_box->pack_start(*lines_button_erase); + // End control lines interface. + auto_pitch = Gtk::manage (new Gtk::Button ()); auto_pitch->set_image(*ipers_auto_pitch); auto_pitch->signal_pressed().connect( sigc::bind(sigc::mem_fun(*this, &PerspCorrection::autoCorrectionPressed), auto_pitch) ); @@ -165,6 +273,9 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M(" camera_vbox->pack_start (*camera_roll); camera_vbox->pack_start (*camera_pitch); camera_vbox->pack_start (*camera_yaw); + camera_vbox->pack_start (*Gtk::manage (new Gtk::HSeparator())); + camera_vbox->pack_start (*control_lines_box); + camera_vbox->pack_start (*Gtk::manage (new Gtk::HSeparator())); camera_vbox->pack_start (*auto_hbox); camera_frame->add(*camera_vbox); camera_based->pack_start(*camera_frame); @@ -213,6 +324,7 @@ void PerspCorrection::read (const ProcParams* pp, const ParamsEdited* pedited) projection_shift_horiz->setEditedState (pedited->perspective.projection_shift_horiz ? Edited : UnEdited); projection_shift_vert->setEditedState (pedited->perspective.projection_shift_vert ? Edited : UnEdited); projection_yaw->setEditedState (pedited->perspective.projection_yaw ? Edited : UnEdited); + lines->setEdited (pedited->perspective.control_lines); } horiz->setValue (pp->perspective.horizontal); @@ -228,6 +340,8 @@ void PerspCorrection::read (const ProcParams* pp, const ParamsEdited* pedited) projection_shift_horiz->setValue (pp->perspective.projection_shift_horiz); projection_shift_vert->setValue (pp->perspective.projection_shift_vert); projection_yaw->setValue (pp->perspective.projection_yaw); + lines->setLines(valuesToControlLines(pp->perspective.control_line_values, + pp->perspective.control_line_types)); if (pedited && !pedited->perspective.method) { method->set_active (2); @@ -243,6 +357,8 @@ void PerspCorrection::read (const ProcParams* pp, const ParamsEdited* pedited) void PerspCorrection::write (ProcParams* pp, ParamsEdited* pedited) { + pp->perspective.render = render; + pp->perspective.horizontal = horiz->getValue (); pp->perspective.vertical = vert->getValue (); pp->perspective.camera_crop_factor= camera_crop_factor->getValue (); @@ -258,6 +374,11 @@ void PerspCorrection::write (ProcParams* pp, ParamsEdited* pedited) pp->perspective.projection_shift_vert = projection_shift_vert->getValue (); pp->perspective.projection_yaw = projection_yaw->getValue (); + std::vector control_lines; + lines->toControlLines(control_lines); + controlLinesToValues(control_lines, pp->perspective.control_line_values, + pp->perspective.control_line_types); + if (method->get_active_row_number() == 0) { pp->perspective.method = "simple"; } else if (method->get_active_row_number() == 1) { @@ -280,6 +401,7 @@ void PerspCorrection::write (ProcParams* pp, ParamsEdited* pedited) pedited->perspective.projection_shift_horiz = projection_shift_horiz->getEditedState(); pedited->perspective.projection_shift_vert = projection_shift_vert->getEditedState(); pedited->perspective.projection_yaw = projection_yaw->getEditedState(); + pedited->perspective.control_lines = lines->getEdited(); } } @@ -345,21 +467,21 @@ void PerspCorrection::adjusterChanged(Adjuster* a, double newval) M("TP_PERSPECTIVE_VERTICAL"), vert->getValue())); } else if (a == camera_focal_length || a == camera_crop_factor) { - listener->panelChanged (EvPerspCamFocalLength, + listener->panelChanged (*event_persp_cam_focal_length, Glib::ustring::compose("%1=%2\n%3=%4", M("TP_PERSPECTIVE_CAMERA_FOCAL_LENGTH"), camera_focal_length->getValue(), M("TP_PERSPECTIVE_CAMERA_CROP_FACTOR"), camera_crop_factor->getValue())); } else if (a == camera_shift_horiz || a == camera_shift_vert) { - listener->panelChanged (EvPerspCamShift, + listener->panelChanged (*event_persp_cam_shift, Glib::ustring::compose("%1=%2\n%3=%4", M("TP_PERSPECTIVE_CAMERA_SHIFT_HORIZONTAL"), camera_shift_horiz->getValue(), M("TP_PERSPECTIVE_CAMERA_SHIFT_VERTICAL"), camera_shift_vert->getValue())); } else if (a == camera_pitch || a == camera_roll|| a == camera_yaw) { - listener->panelChanged (EvPerspCamAngle, + listener->panelChanged (*event_persp_cam_angle, Glib::ustring::compose("%1=%2\n%3=%4\n%5=%6", M("TP_PERSPECTIVE_CAMERA_ROLL"), camera_roll->getValue(), @@ -368,17 +490,17 @@ void PerspCorrection::adjusterChanged(Adjuster* a, double newval) M("TP_PERSPECTIVE_CAMERA_PITCH"), camera_pitch->getValue())); } else if (a == projection_shift_horiz || a == projection_shift_vert) { - listener->panelChanged (EvPerspProjShift, + listener->panelChanged (*event_persp_proj_shift, Glib::ustring::compose("%1=%2\n%3=%4", M("TP_PERSPECTIVE_PROJECTION_SHIFT_HORIZONTAL"), projection_shift_horiz->getValue(), M("TP_PERSPECTIVE_PROJECTION_SHIFT_VERTICAL"), projection_shift_vert->getValue())); } else if (a == projection_rotate) { - listener->panelChanged (EvPerspProjRotate, + listener->panelChanged (*event_persp_proj_rotate, Glib::ustring::format(projection_rotate->getValue())); } else if (a == projection_pitch || a == projection_yaw) { - listener->panelChanged (EvPerspProjAngle, + listener->panelChanged (*event_persp_proj_angle, Glib::ustring::compose("%1=%2\n%3=%4", M("TP_PERSPECTIVE_PROJECTION_PITCH"), projection_pitch->getValue(), @@ -388,6 +510,39 @@ void PerspCorrection::adjusterChanged(Adjuster* a, double newval) } } +void PerspCorrection::applyControlLines(void) +{ + if (!lens_geom_listener) { + return; + } + + std::vector control_lines; + int h_count = 0, v_count = 0; + double rot = camera_roll->getValue(); + double pitch = camera_pitch->getValue(); + double yaw = camera_yaw->getValue(); + + lines->toControlLines(control_lines); + + for (unsigned int i = 0; i < lines->size(); i++) { + if (control_lines[i].type == rtengine::ControlLine::HORIZONTAL) { + h_count++; + } else if (control_lines[i].type == rtengine::ControlLine::VERTICAL) { + v_count++; + } + } + lens_geom_listener->autoPerspRequested(v_count > 1, h_count > 1, rot, pitch, + yaw, &control_lines); + + disableListener(); + camera_pitch->setValue(pitch); + camera_roll->setValue(rot); + camera_yaw->setValue(yaw); + enableListener(); + + adjusterChanged(camera_pitch, pitch); +} + void PerspCorrection::autoCorrectionPressed(Gtk::Button* b) { if (!lens_geom_listener) { @@ -427,6 +582,11 @@ void PerspCorrection::methodChanged (void) } else if (method->get_active_row_number() == 1) { pack_start (*camera_based); } + + // If no longer in camera-based mode and control lines are being edited. + if (method->get_active_row_number() != 1 && lines_button_edit->get_active()) { + lines_button_edit->set_active(false); + } } if (listener) { @@ -454,6 +614,17 @@ void PerspCorrection::setAdjusterBehavior (bool badd, bool camera_focal_length_a projection_yaw->setAddMode(projection_angle_add); } +void PerspCorrection::setControlLineEditMode(bool active) +{ + // Only camera-based mode supports control lines, so the mode must be + // switched if not in camera-based mode. + if (method->get_active_row_number() != 1) { + method->set_active(1); + } + + lines_button_edit->set_active(active); +} + void PerspCorrection::setMetadata (const rtengine::FramesMetaData* metadata) { this->metadata = metadata; @@ -497,6 +668,7 @@ void PerspCorrection::setBatchMode (bool batchMode) projection_shift_vert->showEditedCB (); projection_yaw->showEditedCB (); + lines_button_edit->set_sensitive(false); auto_pitch->set_sensitive(false); auto_yaw->set_sensitive(false); auto_pitch_yaw->set_sensitive(false); @@ -549,3 +721,110 @@ void PerspCorrection::setFocalLengthValue (const ProcParams* pparams, const Fram camera_focal_length->setValue(default_focal_length); } } + +void PerspCorrection::switchOffEditMode(void) +{ + lines_button_edit->set_active(false); +} + +void PerspCorrection::setEditProvider(EditDataProvider* provider) +{ + lines->setEditProvider(provider); +} + +void PerspCorrection::lineChanged(void) +{ + if (listener) { + listener->panelChanged(EvPerspControlLines, M("HISTORY_CHANGED")); + } +} + +void PerspCorrection::linesApplyButtonPressed(void) +{ + if (method->get_active_row_number() == 1) { + // Calculate perspective distortion if in camera-based mode. + applyControlLines(); + } + lines_button_edit->set_active(false); +} + +void PerspCorrection::linesEditButtonPressed(void) +{ + if (lines_button_edit->get_active()) { // Enter edit mode. + lines->setActive(true); + lines->setDrawMode(true); + render = false; + if (lens_geom_listener) { + lens_geom_listener->updateTransformPreviewRequested(EvPerspRender, false); + } + lines_button_apply->set_sensitive(true); + lines_button_erase->set_sensitive(true); + setCamBasedEventsActive(false); + if (panel_listener) { + panel_listener->controlLineEditModeChanged(true); + } + } else { // Leave edit mode. + setCamBasedEventsActive(true); + lines_button_apply->set_sensitive(false); + lines_button_erase->set_sensitive(false); + render = true; + if (lens_geom_listener) { + lens_geom_listener->updateTransformPreviewRequested(EvPerspRender, true); + } + lines->setDrawMode(false); + lines->setActive(false); + if (panel_listener) { + panel_listener->controlLineEditModeChanged(false); + } + } +} + +void PerspCorrection::linesEraseButtonPressed(void) +{ + lines->removeAll(); +} + +void PerspCorrection::requestApplyControlLines(void) +{ + if (lines_button_apply->is_sensitive()) { + linesApplyButtonPressed(); + } +} + +void PerspCorrection::setCamBasedEventsActive(bool active) +{ + if (active) { + event_persp_cam_focal_length = &EvPerspCamFocalLength; + event_persp_cam_shift = &EvPerspCamShift; + event_persp_cam_angle = &EvPerspCamAngle; + event_persp_proj_shift = &EvPerspProjShift; + event_persp_proj_rotate = &EvPerspProjRotate; + event_persp_proj_angle = &EvPerspProjAngle; + } else { + event_persp_cam_focal_length = &EvPerspCamFocalLengthVoid; + event_persp_cam_shift = &EvPerspCamShiftVoid; + event_persp_cam_angle = &EvPerspCamAngleVoid; + event_persp_proj_shift = &EvPerspProjShiftVoid; + event_persp_proj_rotate = &EvPerspProjRotateVoid; + event_persp_proj_angle = &EvPerspProjAngleVoid; + } +} + +LinesCallbacks::LinesCallbacks(PerspCorrection* tool): + tool(tool) +{ +} + +void LinesCallbacks::lineChanged(void) +{ + if (tool) { + tool->lineChanged(); + } +} + +void LinesCallbacks::switchOffEditMode(void) +{ + if (tool) { + tool->switchOffEditMode(); + } +} diff --git a/rtgui/perspective.h b/rtgui/perspective.h index 1be392f7c..6ba169b60 100644 --- a/rtgui/perspective.h +++ b/rtgui/perspective.h @@ -21,9 +21,18 @@ #include #include "adjuster.h" +#include "controllines.h" #include "lensgeomlistener.h" #include "toolpanel.h" +class PerspCorrectionPanelListener +{ +public: + virtual ~PerspCorrectionPanelListener() = default; + + virtual void controlLineEditModeChanged(bool active) = 0; +}; + class PerspCorrection final : public ToolParamBlock, public AdjusterListener, @@ -31,6 +40,7 @@ class PerspCorrection final : { protected: + bool render = true; MyComboBoxText* method; Gtk::VBox* simple; Adjuster* horiz; @@ -46,6 +56,10 @@ protected: Adjuster* camera_shift_horiz; Adjuster* camera_shift_vert; Adjuster* camera_yaw; + std::unique_ptr lines; + Gtk::Button* lines_button_apply; + Gtk::ToggleButton* lines_button_edit; + Gtk::Button* lines_button_erase; Adjuster* projection_pitch; Adjuster* projection_rotate; Adjuster* projection_shift_horiz; @@ -54,13 +68,30 @@ protected: rtengine::ProcEvent EvPerspCamFocalLength; rtengine::ProcEvent EvPerspCamShift; rtengine::ProcEvent EvPerspCamAngle; + rtengine::ProcEvent EvPerspControlLines; rtengine::ProcEvent EvPerspMethod; rtengine::ProcEvent EvPerspProjShift; rtengine::ProcEvent EvPerspProjRotate; rtengine::ProcEvent EvPerspProjAngle; + rtengine::ProcEvent EvPerspRender; + rtengine::ProcEvent EvPerspCamFocalLengthVoid; + rtengine::ProcEvent EvPerspCamShiftVoid; + rtengine::ProcEvent EvPerspCamAngleVoid; + rtengine::ProcEvent EvPerspProjShiftVoid; + rtengine::ProcEvent EvPerspProjRotateVoid; + rtengine::ProcEvent EvPerspProjAngleVoid; + rtengine::ProcEvent* event_persp_cam_focal_length; + rtengine::ProcEvent* event_persp_cam_shift; + rtengine::ProcEvent* event_persp_cam_angle; + rtengine::ProcEvent* event_persp_proj_shift; + rtengine::ProcEvent* event_persp_proj_rotate; + rtengine::ProcEvent* event_persp_proj_angle; LensGeomListener* lens_geom_listener; + PerspCorrectionPanelListener* panel_listener; const rtengine::FramesMetaData* metadata; + void applyControlLines (void); + void setCamBasedEventsActive (bool active = true); void setFocalLengthValue (const rtengine::procparams::ProcParams* pparams, const rtengine::FramesMetaData* metadata); public: @@ -74,12 +105,35 @@ public: void adjusterChanged (Adjuster* a, double newval) override; void autoCorrectionPressed (Gtk::Button* b); + void lineChanged (void); + void linesApplyButtonPressed (void); + void linesEditButtonPressed (void); + void linesEraseButtonPressed (void); void methodChanged (void); + void requestApplyControlLines(void); void setAdjusterBehavior (bool badd, bool camera_focal_length_add, bool camera_shift_add, bool camera_angle_add, bool projection_angle_add, bool projection_shift_add, bool projection_rotate_add); + void setControlLineEditMode(bool active); + void setEditProvider (EditDataProvider* provider) override; void setLensGeomListener (LensGeomListener* listener) { lens_geom_listener = listener; } + void setPerspCorrectionPanelListener(PerspCorrectionPanelListener* listener) + { + panel_listener = listener; + } void setMetadata (const rtengine::FramesMetaData* metadata); + void switchOffEditMode (void); void trimValues (rtengine::procparams::ProcParams* pp) override; }; + +class LinesCallbacks: public ControlLineManager::Callbacks +{ +protected: + PerspCorrection* tool; + +public: + explicit LinesCallbacks(PerspCorrection* tool); + void lineChanged (void) override; + void switchOffEditMode (void) override; +}; diff --git a/rtgui/preprocess.cc b/rtgui/preprocess.cc index 4a663ad07..f33a87a28 100644 --- a/rtgui/preprocess.cc +++ b/rtgui/preprocess.cc @@ -46,9 +46,7 @@ PreProcess::PreProcess () : FoldableToolPanel(this, "preprocess", M("TP_PREPROCE hdThreshold->set_tooltip_markup (M("TP_RAW_HD_TOOLTIP")); hdThreshold->setAdjusterListener (this); - if (hdThreshold->delay < options.adjusterMaxDelay) { - hdThreshold->delay = options.adjusterMaxDelay; - } + hdThreshold->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); hdThreshold->show(); pack_start( *hdThreshold, Gtk::PACK_SHRINK, 4); diff --git a/rtgui/previewhandler.cc b/rtgui/previewhandler.cc index 1dad0676e..76def26b4 100644 --- a/rtgui/previewhandler.cc +++ b/rtgui/previewhandler.cc @@ -110,7 +110,7 @@ void PreviewHandler::delImage(IImage8* i) oldImg->getMutex().unlock(); } - i->free(); + delete i; pih->phandler->previewImgMutex.lock(); pih->phandler->previewImg.clear(); pih->phandler->previewImgMutex.unlock(); diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index 9e5c592ef..58c7995f9 100644 --- a/rtgui/rawcacorrection.cc +++ b/rtgui/rawcacorrection.cc @@ -47,24 +47,18 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_RAWCA caAutoiterations->setAdjusterListener (this); caAutoiterations->set_tooltip_markup(M("TP_RAWCACORR_AUTOIT_TOOLTIP")); - if (caAutoiterations->delay < options.adjusterMaxDelay) { - caAutoiterations->delay = options.adjusterMaxDelay; - } + caAutoiterations->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); caRed = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CARED"), -4.0, 4.0, 0.1, 0, icaredL, icaredR)); caRed->setAdjusterListener (this); - if (caRed->delay < options.adjusterMaxDelay) { - caRed->delay = options.adjusterMaxDelay; - } + caRed->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); caRed->show(); caBlue = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CABLUE"), -8.0, 8.0, 0.1, 0, icablueL, icablueR)); caBlue->setAdjusterListener (this); - if (caBlue->delay < options.adjusterMaxDelay) { - caBlue->delay = options.adjusterMaxDelay; - } + caBlue->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); caBlue->show(); diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc index 7548bf4be..7b5ecabc9 100644 --- a/rtgui/rawexposure.cc +++ b/rtgui/rawexposure.cc @@ -33,9 +33,7 @@ RAWExposure::RAWExposure () : FoldableToolPanel(this, "rawexposure", M("TP_EXPOS PexPos = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_LINEAR"), 0.1, 16.0, 0.01, 1)); PexPos->setAdjusterListener (this); - if (PexPos->delay < options.adjusterMaxDelay) { - PexPos->delay = options.adjusterMaxDelay; - } + PexPos->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); PexPos->show(); pack_start( *PexPos, Gtk::PACK_SHRINK, 4);//exposi diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index feab8e6a5..ec250d69b 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -502,112 +502,58 @@ Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL") str->setAdjusterListener (this); - - if (str->delay < 200) { - str->delay = 200; - } + str->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); scal->setAdjusterListener (this); - - if (scal->delay < 200) { - scal->delay = 200; - } + scal->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); iter->setAdjusterListener (this); - - if (iter->delay < 200) { - iter->delay = 200; - } + iter->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); grad->setAdjusterListener (this); - - if (grad->delay < 200) { - grad->delay = 200; - } + grad->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); grads->setAdjusterListener (this); - - if (grads->delay < 200) { - grads->delay = 200; - } + grads->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); gam->setAdjusterListener (this); - - if (gam->delay < 500) { - gam->delay = 500; - } + gam->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay) * 2.5f); slope->setAdjusterListener (this); - - if (slope->delay < 500) { - slope->delay = 500; - } + slope->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay) * 2.5f); neigh->setAdjusterListener (this); - - if (neigh->delay < 200) { - neigh->delay = 200; - } + neigh->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); offs->setAdjusterListener (this); - - if (offs->delay < 200) { - offs->delay = 200; - } + offs->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); vart->setAdjusterListener (this); - - if (vart->delay < 200) { - vart->delay = 200; - } + offs->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); limd->setAdjusterListener (this); - - if (limd->delay < 200) { - limd->delay = 200; - } + limd->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); highl->setAdjusterListener (this); - - if (highl->delay < 200) { - highl->delay = 200; - } + highl->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); radius->setAdjusterListener (this); - - if (radius->delay < 200) { - radius->delay = 200; - } + radius->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); highlights->setAdjusterListener (this); - - if (highlights->delay < 200) { - highlights->delay = 200; - } + highlights->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); h_tonalwidth->setAdjusterListener (this); - - if (h_tonalwidth->delay < 200) { - h_tonalwidth->delay = 200; - } + h_tonalwidth->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); shadows->setAdjusterListener (this); - - if (shadows->delay < 200) { - shadows->delay = 200; - } + shadows->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); s_tonalwidth->setAdjusterListener (this); - - if (s_tonalwidth->delay < 200) { - s_tonalwidth->delay = 200; - } + s_tonalwidth->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); skal->setAdjusterListener (this); - - if (skal->delay < 200) { - skal->delay = 200; - } + skal->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); disableListener(); retinexColorSpaceChanged(); diff --git a/rtgui/sharpenedge.cc b/rtgui/sharpenedge.cc index f4415bb15..552169fc1 100644 --- a/rtgui/sharpenedge.cc +++ b/rtgui/sharpenedge.cc @@ -36,16 +36,12 @@ SharpenEdge::SharpenEdge () : FoldableToolPanel(this, "sharpenedge", M("TP_SHARP passes = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_PASSES"), 1, 4, 1, 2)); passes->setAdjusterListener (this); - if (passes->delay < options.adjusterMaxDelay) { - passes->delay = options.adjusterMaxDelay; - } + passes->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); amount = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_AMOUNT"), 0, 100, 1, 50)); amount->setAdjusterListener (this); - if (amount->delay < options.adjusterMaxDelay) { - amount->delay = options.adjusterMaxDelay; - } + amount->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); threechannels = Gtk::manage(new Gtk::CheckButton((M("TP_SHARPENEDGE_THREE"))));// L + a + b threechannels->set_active (false); diff --git a/rtgui/soundman.cc b/rtgui/soundman.cc index a4cf5337b..d038ffd72 100644 --- a/rtgui/soundman.cc +++ b/rtgui/soundman.cc @@ -26,7 +26,7 @@ #include #endif -#ifdef __linux__ +#if defined(__linux__) && defined(USE_CANBERRA) #include #endif @@ -67,7 +67,7 @@ void SoundManager::playSoundAsync(const Glib::ustring &sound) wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (sound.c_str(), -1, NULL, NULL, NULL); PlaySoundW(wfilename, NULL, sndParam); g_free( wfilename ); -#elif defined(__linux__) +#elif defined(__linux__) && defined(USE_CANBERRA) ca_context_play(ca_gtk_context_get(), 0, CA_PROP_EVENT_ID, sound.c_str(), CA_PROP_MEDIA_FILENAME, sound.c_str(), NULL); #endif } diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index 3840c8bf9..0c71cea2c 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -135,7 +135,6 @@ ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) : textGap(6), sideMargin(8), lowerMargin(8), - preview(nullptr), dispname(Glib::path_get_basename(fname)), buttonSet(nullptr), width(0), @@ -171,7 +170,6 @@ ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) : ThumbBrowserEntryBase::~ThumbBrowserEntryBase () { - delete[] preview; delete buttonSet; } @@ -207,7 +205,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () bbSelected = selected; bbFramed = framed; - bbPreview = preview; + bbPreview = preview.data(); Cairo::RefPtr cc = Cairo::Context::create(surface); @@ -237,16 +235,20 @@ void ThumbBrowserEntryBase::updateBackBuffer () if (buttonSet) { int tmp; - buttonSet->getAllocatedDimensions (tmp, bsHeight); + buttonSet->getAllocatedDimensions(tmp, bsHeight); } + int infow, infoh; + getTextSizes(infow, infoh); + // draw preview frame //backBuffer->draw_rectangle (cc, false, (exp_width-prew)/2, upperMargin+bsHeight, prew+1, preh+1); // draw thumbnail image - if (preview) { + if (!preview.empty()) { prex = borderWidth + (exp_width - prew) / 2; - prey = upperMargin + bsHeight + borderWidth; - backBuffer->copyRGBCharData(preview, 0, 0, prew, preh, prew * 3, prex, prey); + const int hh = exp_height - (upperMargin + bsHeight + borderWidth + infoh + lowerMargin); + prey = upperMargin + bsHeight + borderWidth + std::max((hh - preh) / 2, 0); + backBuffer->copyRGBCharData(preview.data(), 0, 0, prew, preh, prew * 3, prex, prey); } customBackBufferUpdate (cc); @@ -255,9 +257,6 @@ void ThumbBrowserEntryBase::updateBackBuffer () bbIcons = getIconsOnImageArea (); bbSpecificityIcons = getSpecificityIconsOnImageArea (); - int infow, infoh; - getTextSizes (infow, infoh); - int iofs_x = 4, iofs_y = 4; int istartx = prex; int istarty = prey; @@ -356,7 +355,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () textposx_dt = 0; } - textposy = upperMargin + bsHeight + 2 * borderWidth + preh + borderWidth + textGap; + textposy = exp_height - lowerMargin - infoh; textw = exp_width - 2 * textGap; if (selected) { @@ -556,10 +555,7 @@ void ThumbBrowserEntryBase::resize (int h) } if (preh != old_preh || prew != old_prew) { // if new thumbnail height or new orientation - if (preview) { - delete [] preview; - preview = nullptr; - } + preview.clear(); refreshThumbnailImage (); } else if (backBuffer) { backBuffer->setDirty(true); // This will force a backBuffer update on queue_draw @@ -620,7 +616,7 @@ void ThumbBrowserEntryBase::draw (Cairo::RefPtr cc) bbHeight = backBuffer->getHeight(); } - if (!backBuffer || selected != bbSelected || framed != bbFramed || preview != bbPreview + if (!backBuffer || selected != bbSelected || framed != bbFramed || preview.data() != bbPreview || exp_width != bbWidth || exp_height != bbHeight || getIconsOnImageArea () != bbIcons || getSpecificityIconsOnImageArea() != bbSpecificityIcons || backBuffer->isDirty()) { @@ -680,7 +676,7 @@ rtengine::Coord2D ThumbBrowserEntryBase::getPosInImgSpace (int x, int y) const { rtengine::Coord2D coord(-1., -1.); - if (preview) { + if (!preview.empty()) { x -= ofsX + startx; y -= ofsY + starty; diff --git a/rtgui/thumbbrowserentrybase.h b/rtgui/thumbbrowserentrybase.h index dbc6cf73e..764f806fd 100644 --- a/rtgui/thumbbrowserentrybase.h +++ b/rtgui/thumbbrowserentrybase.h @@ -59,7 +59,7 @@ protected: MyRWMutex lockRW; // Locks access to all image thumb changing actions - guint8* preview; // holds the preview image. used in updateBackBuffer. TODO Olli: Make a cache to reduce mem significantly + std::vector preview; // holds the preview image. used in updateBackBuffer. Glib::ustring dispname; diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index c1884edeb..324a0c0c1 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -121,7 +121,7 @@ void Thumbnail::_generateThumbnailImage () tpp = nullptr; delete [] lastImg; lastImg = nullptr; - tw = -1; + tw = options.maxThumbnailWidth; th = options.maxThumbnailHeight; imgRatio = -1.; @@ -138,20 +138,20 @@ void Thumbnail::_generateThumbnailImage () if (ext == "jpg" || ext == "jpeg") { infoFromImage (fname); - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal); + tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal); if (tpp) { cfs.format = FT_Jpeg; } } else if (ext == "png") { - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal); + tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal); if (tpp) { cfs.format = FT_Png; } } else if (ext == "tif" || ext == "tiff") { infoFromImage (fname); - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal); + tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal); if (tpp) { cfs.format = FT_Tiff; @@ -589,10 +589,13 @@ void Thumbnail::decreaseRef () cachemgr->closeThumbnail (this); } -int Thumbnail::getThumbnailWidth (const int h, const rtengine::procparams::ProcParams *pparams) const +void Thumbnail::getThumbnailSize(int &w, int &h, const rtengine::procparams::ProcParams *pparams) { + MyMutex::MyLock lock(mutex); + int tw_ = tw; int th_ = th; + float imgRatio_ = imgRatio; if (pparams) { @@ -617,10 +620,16 @@ int Thumbnail::getThumbnailWidth (const int h, const rtengine::procparams::ProcP } } - if (imgRatio_ > 0.f) { - return imgRatio_ * h; + if (imgRatio_ > 0.) { + w = imgRatio_ * static_cast(h); } else { - return tw_ * h / th_; + w = tw_ * h / th_; + } + + if (w > options.maxThumbnailWidth) { + const float s = static_cast(options.maxThumbnailWidth) / w; + w = options.maxThumbnailWidth; + h = std::max(h * s, 1); } } diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index c22c80cea..aee5ee0a6 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -119,7 +119,7 @@ public: // unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); rtengine::IImage8* upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); - int getThumbnailWidth (int h, const rtengine::procparams::ProcParams *pparams = nullptr) const; + void getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams = nullptr); void getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h); void getOriginalSize (int& w, int& h); diff --git a/rtgui/toolbar.cc b/rtgui/toolbar.cc index e642ae51b..5cdfc2787 100644 --- a/rtgui/toolbar.cc +++ b/rtgui/toolbar.cc @@ -77,6 +77,12 @@ ToolBar::ToolBar () : showColPickers(true), listener (nullptr), pickerListener(n pack_start (*straTool); + perspTool = Gtk::manage(new Gtk::ToggleButton()); + Gtk::Image* perspimg = Gtk::manage(new RTImage("perspective-vertical-bottom.png")); + perspTool->set_image(*perspimg); + perspTool->set_relief(Gtk::RELIEF_NONE); + pack_start(*perspTool); + handTool->set_active (true); current = TMHand; @@ -87,12 +93,14 @@ ToolBar::ToolBar () : showColPickers(true), listener (nullptr), pickerListener(n cpConn = colPickerTool->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &ToolBar::colPicker_pressed)); cropConn = cropTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::crop_pressed)); straConn = straTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::stra_pressed)); + perspConn = perspTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::persp_pressed)); handTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_HAND")); wbTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_WB")); colPickerTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_COLORPICKER")); cropTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_CROP")); straTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_STRAIGHTEN")); + perspTool->set_tooltip_markup(M("TOOLBAR_TOOLTIP_PERSPECTIVE")); } // @@ -107,9 +115,10 @@ void ToolBar::setTool (ToolMode tool) ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); - stopEdit = tool == TMHand && handTool->get_active() && editingMode && !blockEdit; + stopEdit = tool == TMHand && (handTool->get_active() || (perspTool && perspTool->get_active())) && editingMode && !blockEdit; handTool->set_active (false); @@ -122,6 +131,9 @@ void ToolBar::setTool (ToolMode tool) if (colPickerTool) { colPickerTool->set_active (false); } + if (perspTool) { + perspTool->set_active(false); + } if (tool == TMHand) { handTool->set_active (true); @@ -138,6 +150,12 @@ void ToolBar::setTool (ToolMode tool) if (colPickerTool) { colPickerTool->set_active (true); } + } else if (tool == TMPerspective) { + if (perspTool) { + perspTool->set_active(true); + // Perspective is a hand tool, but has its own button. + handTool->set_image(*handimg); + } } current = tool; @@ -160,6 +178,7 @@ void ToolBar::startEditMode() ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (current != TMHand) { @@ -172,6 +191,9 @@ void ToolBar::startEditMode() cropTool->set_active (false); straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } current = TMHand; } handTool->set_active (true); @@ -204,6 +226,7 @@ void ToolBar::hand_pressed () ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (editingMode && !blockEdit) { @@ -222,6 +245,9 @@ void ToolBar::hand_pressed () cropTool->set_active (false); straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } handTool->set_active (true); if (current != TMHand) { @@ -244,6 +270,7 @@ void ToolBar::wb_pressed () ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (current != TMSpotWB) { @@ -256,6 +283,9 @@ void ToolBar::wb_pressed () handTool->set_active (false); cropTool->set_active (false); straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } if (colPickerTool) { colPickerTool->set_active(false); } @@ -288,6 +318,9 @@ void ToolBar::colPicker_pressed (GdkEventButton* event) wbTool->set_active (false); } straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } if (current != TMColorPicker) { // Disabling all other tools, enabling the Picker tool and entering the "visible pickers" mode @@ -359,6 +392,7 @@ void ToolBar::crop_pressed () ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (editingMode) { @@ -376,6 +410,9 @@ void ToolBar::crop_pressed () } straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } cropTool->set_active (true); if (current != TMCropSelect) { @@ -399,6 +436,7 @@ void ToolBar::stra_pressed () ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (editingMode) { @@ -416,6 +454,9 @@ void ToolBar::stra_pressed () } cropTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } straTool->set_active (true); if (current != TMStraighten) { @@ -432,6 +473,35 @@ void ToolBar::stra_pressed () } } +void ToolBar::persp_pressed () +{ + if (listener && !perspTool->get_active()) { + listener->toolDeselected(TMPerspective); + return; + } + + // Unlike other modes, mode switching is handled by the perspective panel. + { + ConnectionBlocker handBlocker(handConn); + ConnectionBlocker straBlocker(straConn); + ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); + ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); + + if (editingMode) { + stopEditMode(); + if (listener) { + listener->editModeSwitchedOff(); + } + } + + } + + if (listener) { + listener->toolSelected(TMPerspective); + } +} + bool ToolBar::handleShortcutKey (GdkEventKey* event) { @@ -485,6 +555,11 @@ void ToolBar::setBatchMode() removeIfThere(this, colPickerTool, false); colPickerTool = nullptr; } + if (perspTool) { + perspConn.disconnect(); + removeIfThere(this, perspTool, false); + perspTool = nullptr; + } allowNoTool = true; switch (current) { diff --git a/rtgui/toolbar.h b/rtgui/toolbar.h index a4525019f..85a0c3345 100644 --- a/rtgui/toolbar.h +++ b/rtgui/toolbar.h @@ -30,6 +30,8 @@ class ToolBarListener public: virtual ~ToolBarListener() = default; + /// Callback when a tool is deselected. WARNING: Not yet called for most tools. + virtual void toolDeselected(ToolMode tool) = 0; /// Callback when a tool is selected virtual void toolSelected(ToolMode tool) = 0; @@ -51,6 +53,7 @@ private: void colPicker_pressed (GdkEventButton* event); void crop_pressed (); void stra_pressed (); + void persp_pressed (); bool showColorPickers(bool showCP); void switchColorPickersVisibility(); @@ -60,6 +63,7 @@ protected: Gtk::ToggleButton* colPickerTool; Gtk::ToggleButton* cropTool; Gtk::ToggleButton* straTool; + Gtk::ToggleButton* perspTool; ToolBarListener* listener; LockablePickerToolListener* pickerListener; ToolMode current; @@ -71,6 +75,7 @@ protected: sigc::connection cpConn; sigc::connection cropConn; sigc::connection straConn; + sigc::connection perspConn; public: ToolBar (); diff --git a/rtgui/toolenum.h b/rtgui/toolenum.h index c3bc873f1..424afca87 100644 --- a/rtgui/toolenum.h +++ b/rtgui/toolenum.h @@ -18,4 +18,4 @@ */ #pragma once -enum ToolMode {TMNone = -1, TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3, TMColorPicker = 4}; +enum ToolMode {TMNone = -1, TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3, TMColorPicker = 4, TMPerspective = 5}; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 53ad0cbe5..30c3d22ef 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -282,6 +282,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit lensgeom->setLensGeomListener(this); rotate->setLensGeomListener(this); perspective->setLensGeomListener(this); + perspective->setPerspCorrectionPanelListener(this); distortion->setLensGeomListener(this); crop->setCropPanelListener(this); icm->setICMPanelListener(this); @@ -363,6 +364,7 @@ void ToolPanelCoordinator::imageTypeChanged(bool isRaw, bool isBayer, bool isXtr bayerprocess->FoldableToolPanel::show(); bayerpreprocess->FoldableToolPanel::show(); rawcacorrection->FoldableToolPanel::show(); + preprocessWB->FoldableToolPanel::show(); preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); filmNegative->FoldableToolPanel::show(); @@ -383,6 +385,7 @@ void ToolPanelCoordinator::imageTypeChanged(bool isRaw, bool isBayer, bool isXtr bayerprocess->FoldableToolPanel::hide(); bayerpreprocess->FoldableToolPanel::hide(); rawcacorrection->FoldableToolPanel::hide(); + preprocessWB->FoldableToolPanel::show(); preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); filmNegative->FoldableToolPanel::show(); @@ -986,7 +989,7 @@ void ToolPanelCoordinator::straightenRequested() toolBar->setTool(TMStraighten); } -void ToolPanelCoordinator::autoPerspRequested (bool corr_pitch, bool corr_yaw, double& rot, double& pitch, double& yaw) +void ToolPanelCoordinator::autoPerspRequested (bool corr_pitch, bool corr_yaw, double& rot, double& pitch, double& yaw, const std::vector *lines) { if (!(ipc && (corr_pitch || corr_yaw))) { return; @@ -1000,7 +1003,7 @@ void ToolPanelCoordinator::autoPerspRequested (bool corr_pitch, bool corr_yaw, d rtengine::procparams::ProcParams params; ipc->getParams(¶ms); - auto res = rtengine::PerspectiveCorrection::autocompute(src, corr_pitch, corr_yaw, ¶ms, src->getMetaData()); + auto res = rtengine::PerspectiveCorrection::autocompute(src, corr_pitch, corr_yaw, ¶ms, src->getMetaData(), lines); rot = res.angle; pitch = res.pitch; yaw = res.yaw; @@ -1015,6 +1018,16 @@ double ToolPanelCoordinator::autoDistorRequested() return rtengine::ImProcFunctions::getAutoDistor(ipc->getInitialImage()->getFileName(), 400); } +void ToolPanelCoordinator::updateTransformPreviewRequested(rtengine::ProcEvent event, bool render_perspective) +{ + if (!ipc) { + return; + } + + ipc->beginUpdateParams()->perspective.render = render_perspective; + ipc->endUpdateParams(event); +} + void ToolPanelCoordinator::spotWBRequested(int size) { @@ -1035,6 +1048,17 @@ void ToolPanelCoordinator::cropSelectRequested() toolBar->setTool(TMCropSelect); } +void ToolPanelCoordinator::controlLineEditModeChanged(bool active) +{ + if (!ipc) { + return; + } + + if (active) { + toolBar->setTool(TMPerspective); + } +} + void ToolPanelCoordinator::saveInputICCReference(const Glib::ustring& fname, bool apply_wb) { if (ipc) { @@ -1162,6 +1186,13 @@ void ToolPanelCoordinator::updateTPVScrollbar(bool hide) updateVScrollbars(hide); } +void ToolPanelCoordinator::toolDeselected(ToolMode tool) +{ + if (tool == TMPerspective) { + perspective->requestApplyControlLines(); + } +} + void ToolPanelCoordinator::toolSelected(ToolMode tool) { GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected @@ -1206,6 +1237,20 @@ void ToolPanelCoordinator::toolSelected(ToolMode tool) break; } + case TMPerspective: { + toolBar->blockEditDeactivation(false); // To allow deactivating Locallab when switching to another tool using toolbar + perspective->setControlLineEditMode(true); + perspective->setExpanded(true); + bool isFavorite = checkFavorite(perspective); + if (!isFavorite) { + isFavorite = checkFavorite(lensgeom); + lensgeom->setExpanded(true); + } + toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(isFavorite ? *favoritePanelSW : *transformPanelSW)); + prevPage = toolPanelNotebook->get_nth_page(toolPanelNotebook->get_current_page()); // Updating prevPage as "signal_switch_page" event + break; + } + default: break; } diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index cc4e17e46..0dcee59eb 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -102,6 +102,7 @@ class ToolPanelCoordinator : public LensGeomListener, public SpotWBListener, public CropPanelListener, + public PerspCorrectionPanelListener, public ICMPanelListener, public ImageAreaToolListener, public rtengine::ImageTypeListener, @@ -313,8 +314,9 @@ public: // rotatelistener interface void straightenRequested () override; void autoCropRequested () override; - void autoPerspRequested (bool corr_pitch, bool corr_yaw, double& rot, double& pitch, double& yaw) override; + void autoPerspRequested (bool corr_pitch, bool corr_yaw, double& rot, double& pitch, double& yaw, const std::vector *lines = nullptr) override; double autoDistorRequested () override; + void updateTransformPreviewRequested (rtengine::ProcEvent event, bool render_perspective) override; // spotwblistener interface void spotWBRequested (int size) override; @@ -322,6 +324,9 @@ public: // croppanellistener interface void cropSelectRequested () override; + // PerspCorrectionPanelListener interface + void controlLineEditModeChanged(bool active) override; + // icmpanellistener interface void saveInputICCReference(const Glib::ustring& fname, bool apply_wb) override; @@ -338,6 +343,7 @@ public: bool handleShortcutKey(GdkEventKey* event); // ToolBarListener interface + void toolDeselected(ToolMode tool) override; void toolSelected (ToolMode tool) override; void editModeSwitchedOff () final; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 19d458dad..909b906ad 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . * - * 2014 - 2019Jacques Desmis + * 2014 - 2020 Jacques Desmis */ #include "wavelet.h" @@ -29,6 +29,7 @@ #include "eventmapper.h" #include "labgrid.h" #include "../rtengine/color.h" +#include using namespace rtengine; using namespace rtengine::procparams; @@ -72,6 +73,10 @@ Wavelet::Wavelet() : separatoredge(Gtk::manage(new Gtk::HSeparator())), opaCurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_COLORT"))), opacityCurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITY"))), + CurveEditorwavnoise(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_DENOISE"))), + CurveEditorwavnoiseh(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_DENOISEH"))), + CurveEditorwavguid(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_DENOISEGUID"))), + CurveEditorwavhue(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_DENOISEHUE"))), opacityCurveEditorW(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITYW"))), opacityCurveEditorWL(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITYWL"))), median(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_MEDI")))), @@ -88,7 +93,7 @@ Wavelet::Wavelet() : offset(Gtk::manage(new Adjuster(M("TP_WAVELET_WAVOFFSET"), 0.33, 1.66, 0.01, 1., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), lowthr(Gtk::manage(new Adjuster(M("TP_WAVELET_WAVLOWTHR"), 20., 100., 0.5, 40.))), rescon(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCON"), -100, 100, 1, 0))), - resconH(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCONH"), -100, 100, 1, 0))), + resconH(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCONH"), 0, 100, 1, 0))), reschro(Gtk::manage(new Adjuster(M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0))), resblur(Gtk::manage(new Adjuster(M("TP_WAVELET_RESBLUR"), 0, 100, 1, 0))), resblurc(Gtk::manage(new Adjuster(M("TP_WAVELET_RESBLURC"), 0, 100, 1, 0))), @@ -99,7 +104,7 @@ Wavelet::Wavelet() : gamma(Gtk::manage(new Adjuster(M("TP_WAVELET_COMPGAMMA"), 0.4, 2.0, 0.01, 1.0))), sup(Gtk::manage(new Adjuster(M("TP_WAVELET_SUPE"), -100, 350, 1, 0))), sky(Gtk::manage(new Adjuster(M("TP_WAVELET_SKY"), -100., 100.0, 1., 0.))), - thres(Gtk::manage(new Adjuster(M("TP_WAVELET_LEVELS"), 4, 9, 1, 7))),//3 + thres(Gtk::manage(new Adjuster(M("TP_WAVELET_LEVELS"), 5, 9, 1, 7))),//3 chroma(Gtk::manage(new Adjuster(M("TP_WAVELET_CHRO"), 1, 9, 1, 5))), chro(Gtk::manage(new Adjuster(M("TP_WAVELET_CHR"), 0., 100., 1., 0.))), contrast(Gtk::manage(new Adjuster(M("TP_WAVELET_CONTRA"), -100, 100, 1, 0))), @@ -131,6 +136,12 @@ Wavelet::Wavelet() : level1noise(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_LEVONE"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., nullptr, false))), level2noise(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_LEVTWO"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., nullptr, false))), level3noise(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_LEVTHRE"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., nullptr, false))), + leveldenoise(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_LEVFOUR"), 0., 100., 0., M("TP_WAVELET_DEN5THR"), 1, 0., 100., 0., M("TP_WAVELET_NOIS"), 1., nullptr, false))), + levelsigm(Gtk::manage(new ThresholdAdjuster(M("TP_WAVELET_LEVELSIGM"), 0.05, 3., 1., M("TP_WAVELET_LEVELHIGH"), 1, 0.05, 3., 1., M("TP_WAVELET_LEVELLOW"), 1., nullptr, false))), + sigm(Gtk::manage(new Adjuster(M("TP_WAVELET_SIGM"), 0.05, 3.5, 0.01, 1.))), + levden(Gtk::manage(new Adjuster(M("TP_WAVELET_LEVDEN"), 0., 100., 0.5, 0.))), + thrden(Gtk::manage(new Adjuster(M("TP_WAVELET_DENLH"), 0., 100., 0.5, 0.))), + limden(Gtk::manage(new Adjuster(M("TP_WAVELET_LIMDEN"), 0., 1., 0.01, 0.))), threshold(Gtk::manage(new Adjuster(M("TP_WAVELET_THRESHOLD"), 1, 9, 1, 4))), // threshold2(Gtk::manage(new Adjuster(M("TP_WAVELET_THRESHOLD2"), 1, 9, 1, 4))), threshold2(Gtk::manage(new Adjuster(M("TP_WAVELET_THRESHOLD2"), 3, 9, 1, 5))), @@ -146,7 +157,10 @@ Wavelet::Wavelet() : mergeL(Gtk::manage(new Adjuster(M("TP_WAVELET_MERGEL"), -50, 100, 1, 20))), mergeC(Gtk::manage(new Adjuster(M("TP_WAVELET_MERGEC"), -50, 100, 1, 20))), softrad(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 100., 0.5, 0.))), - softradend(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 100., 0.5, 0.))), + softradend(Gtk::manage(new Adjuster(M("TP_WAVELET_SOFTRAD"), 0.0, 1000., 1., 0.))), + strend(Gtk::manage(new Adjuster(M("TP_WAVELET_STREND"), 0.0, 100., 1.0, 50.))), + detend(Gtk::manage(new Adjuster(M("TP_WAVELET_DETEND"), -10, 10, 1, 0))), + thrend(Gtk::manage(new Adjuster(M("TP_WAVELET_THREND"), 0.0, 100., 0.5, 0.))), chrwav(Gtk::manage(new Adjuster(M("TP_WAVELET_CHRWAV"), 0., 100., 0.5, 0.))), Lmethod(Gtk::manage(new MyComboBoxText())), CHmethod(Gtk::manage(new MyComboBoxText())), @@ -164,6 +178,10 @@ Wavelet::Wavelet() : Dirmethod(Gtk::manage(new MyComboBoxText())), Medgreinf(Gtk::manage(new MyComboBoxText())), ushamethod(Gtk::manage(new MyComboBoxText())), + denmethod(Gtk::manage(new MyComboBoxText())), + mixmethod(Gtk::manage(new MyComboBoxText())), + quamethod(Gtk::manage(new MyComboBoxText())), + slimethod(Gtk::manage(new MyComboBoxText())), chanMixerHLFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_HIGHLIGHT")))), chanMixerMidFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_MIDTONES")))), chanMixerShadowsFrame(Gtk::manage(new Gtk::Frame(M("TP_COLORTONING_SHADOWS")))), @@ -175,6 +193,7 @@ Wavelet::Wavelet() : fincFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_FINCFRAME")))), dirFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_DIRFRAME")))), tonFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_TONFRAME")))), + guidFrame(Gtk::manage(new Gtk::Frame(M("TP_WAVELET_GUIDFRAME")))), wavLabels(Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER))), labmC(Gtk::manage(new Gtk::Label(M("TP_WAVELET_CTYPE") + ":"))), labmNP(Gtk::manage(new Gtk::Label(M("TP_WAVELET_NPTYPE") + ":"))), @@ -193,6 +212,10 @@ Wavelet::Wavelet() : neutrHBox(Gtk::manage(new Gtk::HBox())), usharpHBox(Gtk::manage(new Gtk::HBox())), ctboxch(Gtk::manage(new Gtk::HBox())), + quaHBox(Gtk::manage(new Gtk::HBox())), + sliHBox(Gtk::manage(new Gtk::HBox())), + denHBox(Gtk::manage(new Gtk::HBox())), + mixHBox(Gtk::manage(new Gtk::HBox())), ctboxBA(Gtk::manage(new Gtk::VBox())) { @@ -232,6 +255,24 @@ Wavelet::Wavelet() : EvWavprotab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_PROTAB"); EvWavlevelshc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_LEVELSHC"); EvWavcomplexmet = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_COMPLEX"); + EvWavsigm = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSIGM"); + EvWavdenoise = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVDENOISE"); + EvWavdenmethod = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVDENMET"); + EvWavmixmethod = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVMIXMET"); + EvWavquamethod = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVQUAMET"); + EvWavlevden = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVLEVDEN"); + EvWavdenoiseh = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVDENOISEH"); + EvWavstrend = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSTREND"); + EvWavdetend = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVDETEND"); + EvWavlevdenois = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVDENLH"); + EvWavslimethod = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVSLIMET"); + EvWavthrend = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVTHREND"); + EvWavguid = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVGUIDH"); + EvWavhue = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVHUE"); + EvWavthrden = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVTHRDEN"); + EvWavlevelsigm = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVLEVELSIGM"); + EvWavlimden = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_WAVLIMDEN"); + labgrid = Gtk::manage(new LabGrid(EvWavLabGridValue, M("TP_WAVELET_LABGRID_VALUES"))); @@ -447,7 +488,7 @@ Wavelet::Wavelet() : curveEditorC->set_tooltip_text(M("TP_WAVELET_FINCOAR_TOOLTIP")); - opacityShapeSH = static_cast(curveEditorC->addCurve(CT_Flat, "", nullptr, false, false)); + opacityShapeSH = static_cast(curveEditorC->addCurve(CT_Flat, "", nullptr, false, false)); opacityShapeSH->setIdentityValue(0.); opacityShapeSH->setResetCurve(FlatCurveType(default_params.opacityCurveSH.at(0)), default_params.opacityCurveSH); @@ -605,13 +646,121 @@ Wavelet::Wavelet() : level3noise->setAdjusterListener(this); level3noise->setUpdatePolicy(RTUP_DYNAMIC); + + leveldenoise->setAdjusterListener(this); + leveldenoise->setUpdatePolicy(RTUP_DYNAMIC); + + levelsigm->setAdjusterListener(this); + levelsigm->setUpdatePolicy(RTUP_DYNAMIC); + ballum->setAdjusterListener(this); + sigm->setAdjusterListener(this); + levden->setAdjusterListener(this); + thrden->setAdjusterListener(this); + limden->setAdjusterListener(this); + CurveEditorwavnoise->setCurveListener(this); + CurveEditorwavnoiseh->setCurveListener(this); + CurveEditorwavguid->setCurveListener(this); + CurveEditorwavhue->setCurveListener(this); + + quamethod->append(M("TP_WAVELET_QUACONSER")); + quamethod->append(M("TP_WAVELET_QUAAGRES")); + quamethodconn = quamethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::quamethodChanged)); +// quamethod->set_tooltip_text(M("TP_WAVELET_DENQUA_TOOLTIP")); + Gtk::Label* const quaLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_DENQUA") + ":")); + quaHBox->pack_start(*quaLabel, Gtk::PACK_SHRINK, 4); + quaHBox->pack_start(*quamethod); + + slimethod->append(M("TP_WAVELET_DENSLI")); + slimethod->append(M("TP_WAVELET_DENCURV")); + slimethodconn = slimethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::slimethodChanged)); +// slimethod->set_tooltip_text(M("TP_WAVELET_DENSLI_TOOLTIP")); + Gtk::Label* const sliLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_DENSLILAB") + ":")); + sliHBox->pack_start(*sliLabel, Gtk::PACK_SHRINK, 4); + sliHBox->pack_start(*slimethod); + + + denmethod->append(M("TP_WAVELET_DENEQUAL")); + denmethod->append(M("TP_WAVELET_DEN14PLUS")); + denmethod->append(M("TP_WAVELET_DEN14LOW")); + denmethod->append(M("TP_WAVELET_DEN12PLUS")); + denmethod->append(M("TP_WAVELET_DEN12LOW")); + denmethodconn = denmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::denmethodChanged)); + denmethod->set_tooltip_text(M("TP_WAVELET_DENEQUAL_TOOLTIP")); +// Gtk::HBox* const denHBox = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const denLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_DENCONTRAST") + ":")); + denHBox->pack_start(*denLabel, Gtk::PACK_SHRINK, 4); + denHBox->pack_start(*denmethod); + + mixmethod->append(M("TP_WAVELET_MIXNOISE")); + mixmethod->append(M("TP_WAVELET_MIXMIX")); + mixmethod->append(M("TP_WAVELET_MIXMIX70")); + mixmethod->append(M("TP_WAVELET_MIXDENOISE")); + mixmethodconn = mixmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::mixmethodChanged)); + mixmethod->set_tooltip_text(M("TP_WAVELET_DENMIX_TOOLTIP")); + Gtk::Label* const mixLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_MIXCONTRAST") + ":")); + mixHBox->pack_start(*mixLabel, Gtk::PACK_SHRINK, 4); + mixHBox->pack_start(*mixmethod); + + wavdenoise = static_cast(CurveEditorwavnoise->addCurve(CT_Flat, "", nullptr, false, false)); + wavdenoise->setIdentityValue(0.); + wavdenoise->setResetCurve(FlatCurveType(default_params.wavdenoise.at(0)), default_params.wavdenoise); + CurveEditorwavnoise->set_tooltip_text(M("TP_WAVELET_DENLOCAL_TOOLTIP")); + + CurveEditorwavnoise->curveListComplete(); + CurveEditorwavnoise->show(); + const std::vector milestones4 = makeWholeHueRange(); + + wavdenoiseh = static_cast(CurveEditorwavnoiseh->addCurve(CT_Flat, "", nullptr, false, false)); + wavdenoiseh->setIdentityValue(0.); + wavdenoiseh->setResetCurve(FlatCurveType(default_params.wavdenoiseh.at(0)), default_params.wavdenoiseh); + CurveEditorwavnoiseh->set_tooltip_text(M("TP_WAVELET_DENLOCAL_TOOLTIP")); + CurveEditorwavnoiseh->curveListComplete(); + CurveEditorwavnoiseh->show(); + + wavhue = static_cast(CurveEditorwavhue->addCurve(CT_Flat, M("TP_WAVELET_CURVEEDITOR_HH"))); +// wavhue->setTooltip(M("TP_WAVELET_WAVHUE_HH_TOOLTIP")); + wavhue->setCurveColorProvider(this, 5); + CurveEditorwavhue->set_tooltip_text(M("TP_WAVELET_DENWAVHUE_TOOLTIP")); + CurveEditorwavhue->curveListComplete(); + wavhue->setBottomBarBgGradient(milestones4); + + + + + wavguidf = static_cast(CurveEditorwavguid->addCurve(CT_Flat, M("TP_WAVELET_CURVEEDITOR_HH"))); +// wavguidf->setTooltip(M("TP_WAVELET_WAVGUID_HH_TOOLTIP")); + wavguidf->setCurveColorProvider(this, 5); + CurveEditorwavguid->set_tooltip_text(M("TP_WAVELET_DENWAVGUID_TOOLTIP")); + CurveEditorwavguid->curveListComplete(); + wavguidf->setBottomBarBgGradient(milestones4); + + + + levelsigm->set_tooltip_text(M("TP_WAVELET_DENSIGMA_TOOLTIP")); +// levden->set_tooltip_text(M("TP_WAVELET_DENLEV_TOOLTIP")); + thrden->set_tooltip_text(M("TP_WAVELET_THRDEN_TOOLTIP")); +// limden->set_tooltip_text(M("TP_WAVELET_LIMDEN_TOOLTIP")); noiseBox->pack_start(*ballum); + noiseBox->pack_start(*CurveEditorwavhue); noiseBox->pack_start(*level0noise, Gtk::PACK_SHRINK, 0); noiseBox->pack_start(*level1noise, Gtk::PACK_SHRINK, 0); noiseBox->pack_start(*level2noise, Gtk::PACK_SHRINK, 0); noiseBox->pack_start(*level3noise, Gtk::PACK_SHRINK, 0); + // noiseBox->pack_start(*levden); + noiseBox->pack_start(*leveldenoise, Gtk::PACK_SHRINK, 0); + noiseBox->pack_start(*thrden); + noiseBox->pack_start(*quaHBox); + noiseBox->pack_start(*sliHBox); + noiseBox->pack_start(*denHBox); + noiseBox->pack_start(*mixHBox); + noiseBox->pack_start(*levelsigm, Gtk::PACK_SHRINK, 0); + noiseBox->pack_start(*limden); + noiseBox->pack_start(*sigm); + noiseBox->pack_start(*CurveEditorwavnoise); +// noiseBox->pack_start(*CurveEditorwavnoiseh); + balchrom->setAdjusterListener(this); chromfi->setAdjusterListener(this); @@ -624,7 +773,7 @@ Wavelet::Wavelet() : chroBox->pack_start(*chromco); chroFrame->add(*chroBox); noiseBox->pack_start(*chroFrame); - noiseBox->set_tooltip_text(M("TP_WAVELET_NOISE_TOOLTIP")); +// noiseBox->set_tooltip_text(M("TP_WAVELET_NOISE_TOOLTIP")); //Clarity @@ -1043,6 +1192,9 @@ Wavelet::Wavelet() : balance->setAdjusterListener(this); balance->set_tooltip_text(M("TP_WAVELET_BALANCE_TOOLTIP")); softradend->setAdjusterListener(this); + strend->setAdjusterListener(this); + detend->setAdjusterListener(this); + thrend->setAdjusterListener(this); opacityCurveEditorW->setCurveListener(this); @@ -1108,7 +1260,18 @@ Wavelet::Wavelet() : finalBox->pack_start(*fincFrame); finalBox->pack_start(*curveEditorG, Gtk::PACK_SHRINK, 4); - finalBox->pack_start(*softradend); + thrend->set_tooltip_text(M("TP_WAVELET_FINTHR_TOOLTIP")); + + guidFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const guidBox = Gtk::manage(new ToolParamBlock()); + guidBox->pack_start(*softradend); + guidBox->pack_start(*strend); + guidBox->pack_start(*detend); + guidBox->pack_start(*thrend); + guidBox->pack_start(*CurveEditorwavguid); + guidFrame->add(*guidBox); + finalBox->pack_start(*guidFrame); + //----------------------------- @@ -1167,6 +1330,10 @@ Wavelet::~Wavelet() delete opaCurveEditorG; delete curveEditorC; delete opacityCurveEditorG; + delete CurveEditorwavnoise; + delete CurveEditorwavnoiseh; + delete CurveEditorwavguid; + delete CurveEditorwavhue; delete curveEditorbl; delete CCWcurveEditorG; delete curveEditorRES; @@ -1253,6 +1420,10 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) Backmethodconn.block(true); Tilesmethodconn.block(true); complexmethodconn.block(true); + denmethodconn.block(true); + mixmethodconn.block(true); + slimethodconn.block(true); + quamethodconn.block(true); daubcoeffmethodconn.block(true); Dirmethodconn.block(true); CHmethodconn.block(true); @@ -1380,6 +1551,39 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) complexmethod->set_active(1); } + if (pp->wavelet.denmethod == "equ") { + denmethod->set_active(0); + } else if (pp->wavelet.denmethod == "high") { + denmethod->set_active(1); + } else if (pp->wavelet.denmethod == "low") { + denmethod->set_active(2); + } else if (pp->wavelet.denmethod == "12high") { + denmethod->set_active(3); + } else if (pp->wavelet.denmethod == "12low") { + denmethod->set_active(4); + } + + if (pp->wavelet.mixmethod == "nois") { + mixmethod->set_active(0); + } else if (pp->wavelet.mixmethod == "mix") { + mixmethod->set_active(1); + } else if (pp->wavelet.mixmethod == "mix7") { + mixmethod->set_active(2); + } else if (pp->wavelet.mixmethod == "den") { + mixmethod->set_active(3); + } + + if (pp->wavelet.slimethod == "sli") { + slimethod->set_active(0); + } else if (pp->wavelet.slimethod == "cur") { + slimethod->set_active(1); + } + + if (pp->wavelet.quamethod == "cons") { + quamethod->set_active(0); + } else if (pp->wavelet.quamethod == "agre") { + quamethod->set_active(1); + } //Tilesmethod->set_active (2); if (pp->wavelet.Tilesmethod == "full") { @@ -1420,11 +1624,15 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) ccshape->setCurve(pp->wavelet.ccwcurve); blshape->setCurve(pp->wavelet.blcurve); opacityShapeRG->setCurve(pp->wavelet.opacityCurveRG); + wavdenoise->setCurve(pp->wavelet.wavdenoise); + wavdenoiseh->setCurve(pp->wavelet.wavdenoiseh); opacityShapeSH->setCurve(pp->wavelet.opacityCurveSH); opacityShapeBY->setCurve(pp->wavelet.opacityCurveBY); opacityShape->setCurve(pp->wavelet.opacityCurveW); opacityShapeWL->setCurve(pp->wavelet.opacityCurveWL); hhshape->setCurve(pp->wavelet.hhcurve); + wavguidf->setCurve(pp->wavelet.wavguidcurve); + wavhue->setCurve(pp->wavelet.wavhuecurve); Chshape->setCurve(pp->wavelet.Chcurve); clshape->setCurve(pp->wavelet.wavclCurve); expcontrast->setEnabled(pp->wavelet.expcontrast); @@ -1534,8 +1742,15 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) mergeC->setValue(pp->wavelet.mergeC); softrad->setValue(pp->wavelet.softrad); softradend->setValue(pp->wavelet.softradend); + strend->setValue(pp->wavelet.strend); + detend->setValue(pp->wavelet.detend); + thrend->setValue(pp->wavelet.thrend); labgrid->setParams(pp->wavelet.labgridALow / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridBLow / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridAHigh / WaveletParams::LABGRID_CORR_MAX, pp->wavelet.labgridBHigh / WaveletParams::LABGRID_CORR_MAX, false); + sigm->setValue(pp->wavelet.sigm); + levden->setValue(pp->wavelet.levden); + thrden->setValue(pp->wavelet.thrden); + limden->setValue(pp->wavelet.limden); ballum->setValue(pp->wavelet.ballum); balchrom->setValue(pp->wavelet.balchrom); chromfi->setValue(pp->wavelet.chromfi); @@ -1544,6 +1759,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) level1noise->setValue(pp->wavelet.level1noise); level2noise->setValue(pp->wavelet.level2noise); level3noise->setValue(pp->wavelet.level3noise); + leveldenoise->setValue(pp->wavelet.leveldenoise); + levelsigm->setValue(pp->wavelet.levelsigm); strength->setValue(pp->wavelet.strength); balance->setValue(pp->wavelet.balance); iter->setValue(pp->wavelet.iter); @@ -1585,6 +1802,21 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) complexmethod->set_active_text(M("GENERAL_UNCHANGED")); } + if (!pedited->wavelet.denmethod) { + denmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.mixmethod) { + mixmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.slimethod) { + slimethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.quamethod) { + quamethod->set_active_text(M("GENERAL_UNCHANGED")); + } if (!pedited->wavelet.Tilesmethod) { Tilesmethod->set_active_text(M("GENERAL_UNCHANGED")); @@ -1650,9 +1882,13 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) opacityShapeRG->setCurve(pp->wavelet.opacityCurveRG); opacityShapeSH->setCurve(pp->wavelet.opacityCurveSH); opacityShapeBY->setCurve(pp->wavelet.opacityCurveBY); + wavdenoise->setCurve(pp->wavelet.wavdenoise); + wavdenoiseh->setCurve(pp->wavelet.wavdenoiseh); opacityShape->setCurve(pp->wavelet.opacityCurveW); opacityShapeWL->setCurve(pp->wavelet.opacityCurveWL); hhshape->setUnChanged(!pedited->wavelet.hhcurve); + wavguidf->setUnChanged(!pedited->wavelet.wavguidcurve); + wavhue->setUnChanged(!pedited->wavelet.wavhuecurve); Chshape->setUnChanged(!pedited->wavelet.Chcurve); clshape->setUnChanged(!pedited->wavelet.wavclCurve); avoid->set_inconsistent(!pedited->wavelet.avoid); @@ -1703,7 +1939,14 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) mergeC->setEditedState(pedited->wavelet.mergeC ? Edited : UnEdited); softrad->setEditedState(pedited->wavelet.softrad ? Edited : UnEdited); softradend->setEditedState(pedited->wavelet.softradend ? Edited : UnEdited); + strend->setEditedState(pedited->wavelet.strend ? Edited : UnEdited); + detend->setEditedState(pedited->wavelet.detend ? Edited : UnEdited); + thrend->setEditedState(pedited->wavelet.thrend ? Edited : UnEdited); + sigm->setEditedState(pedited->wavelet.sigm ? Edited : UnEdited); + levden->setEditedState(pedited->wavelet.levden ? Edited : UnEdited); + thrden->setEditedState(pedited->wavelet.thrden ? Edited : UnEdited); + limden->setEditedState(pedited->wavelet.limden ? Edited : UnEdited); ballum->setEditedState(pedited->wavelet.ballum ? Edited : UnEdited); balchrom->setEditedState(pedited->wavelet.balchrom ? Edited : UnEdited); chromfi->setEditedState(pedited->wavelet.chromfi ? Edited : UnEdited); @@ -1737,6 +1980,8 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) level1noise->setEditedState(pedited->wavelet.level1noise ? Edited : UnEdited); level2noise->setEditedState(pedited->wavelet.level2noise ? Edited : UnEdited); level3noise->setEditedState(pedited->wavelet.level3noise ? Edited : UnEdited); + leveldenoise->setEditedState(pedited->wavelet.leveldenoise ? Edited : UnEdited); + levelsigm->setEditedState(pedited->wavelet.levelsigm ? Edited : UnEdited); for (int i = 0; i < 9; i++) { correction[i]->setEditedState(pedited->wavelet.c[i] ? Edited : UnEdited); @@ -1824,6 +2069,10 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) Backmethodconn.block(false); Tilesmethodconn.block(false); complexmethodconn.block(false); + denmethodconn.block(false); + mixmethodconn.block(false); + slimethodconn.block(false); + quamethodconn.block(false); daubcoeffmethodconn.block(false); CHmethodconn.block(false); CHSLmethodconn.block(false); @@ -1853,9 +2102,13 @@ void Wavelet::setEditProvider(EditDataProvider *provider) opacityShapeRG->setEditProvider(provider); opacityShapeSH->setEditProvider(provider); opacityShapeBY->setEditProvider(provider); + wavdenoise->setEditProvider(provider); + wavdenoiseh->setEditProvider(provider); opacityShape->setEditProvider(provider); opacityShapeWL->setEditProvider(provider); hhshape->setEditProvider(provider); + wavguidf->setEditProvider(provider); + wavhue->setEditProvider(provider); Chshape->setEditProvider(provider); clshape->setEditProvider(provider); } @@ -1926,20 +2179,30 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.level1noise = level1noise->getValue (); pp->wavelet.level2noise = level2noise->getValue (); pp->wavelet.level3noise = level3noise->getValue (); + pp->wavelet.leveldenoise = leveldenoise->getValue (); + pp->wavelet.levelsigm = levelsigm->getValue (); pp->wavelet.ccwcurve = ccshape->getCurve(); pp->wavelet.blcurve = blshape->getCurve(); pp->wavelet.opacityCurveRG = opacityShapeRG->getCurve(); pp->wavelet.opacityCurveSH = opacityShapeSH->getCurve(); pp->wavelet.opacityCurveBY = opacityShapeBY->getCurve(); + pp->wavelet.wavdenoise = wavdenoise->getCurve(); + pp->wavelet.wavdenoiseh = wavdenoiseh->getCurve(); pp->wavelet.opacityCurveW = opacityShape->getCurve(); pp->wavelet.opacityCurveWL = opacityShapeWL->getCurve(); pp->wavelet.hhcurve = hhshape->getCurve(); + pp->wavelet.wavguidcurve = wavguidf->getCurve(); + pp->wavelet.wavhuecurve = wavhue->getCurve(); pp->wavelet.Chcurve = Chshape->getCurve(); pp->wavelet.pastlev = pastlev->getValue (); pp->wavelet.satlev = satlev->getValue (); pp->wavelet.strength = (int) strength->getValue(); pp->wavelet.balance = (int) balance->getValue(); pp->wavelet.balchrom = balchrom->getValue(); + pp->wavelet.sigm = sigm->getValue(); + pp->wavelet.levden = levden->getValue(); + pp->wavelet.thrden = thrden->getValue(); + pp->wavelet.limden = limden->getValue(); pp->wavelet.ballum = ballum->getValue(); pp->wavelet.chromfi = chromfi->getValue(); pp->wavelet.chromco = chromco->getValue(); @@ -1959,6 +2222,9 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.mergeC = mergeC->getValue(); pp->wavelet.softrad = softrad->getValue(); pp->wavelet.softradend = softradend->getValue(); + pp->wavelet.strend = strend->getValue(); + pp->wavelet.detend = detend->getIntValue(); + pp->wavelet.thrend = thrend->getValue(); pp->wavelet.expcontrast = expcontrast->getEnabled(); pp->wavelet.expchroma = expchroma->getEnabled(); pp->wavelet.expedge = expedge->getEnabled(); @@ -2004,6 +2270,10 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.Backmethod = Backmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.Tilesmethod = Tilesmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.complexmethod = complexmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.denmethod = denmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.mixmethod = mixmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.slimethod = slimethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.quamethod = quamethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.daubcoeffmethod = daubcoeffmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.CHmethod = CHmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.CHSLmethod = CHSLmethod->get_active_text() != M("GENERAL_UNCHANGED"); @@ -2058,12 +2328,18 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.level1noise = level1noise->getEditedState(); pedited->wavelet.level2noise = level2noise->getEditedState(); pedited->wavelet.level3noise = level3noise->getEditedState(); + pedited->wavelet.leveldenoise = leveldenoise->getEditedState(); + pedited->wavelet.levelsigm = levelsigm->getEditedState(); pedited->wavelet.opacityCurveRG = !opacityShapeRG->isUnChanged(); pedited->wavelet.opacityCurveSH = !opacityShapeSH->isUnChanged(); pedited->wavelet.opacityCurveBY = !opacityShapeBY->isUnChanged(); + pedited->wavelet.wavdenoise = !wavdenoise->isUnChanged(); + pedited->wavelet.wavdenoiseh = !wavdenoiseh->isUnChanged(); pedited->wavelet.opacityCurveW = !opacityShape->isUnChanged(); pedited->wavelet.opacityCurveWL = !opacityShapeWL->isUnChanged(); pedited->wavelet.hhcurve = !hhshape->isUnChanged(); + pedited->wavelet.wavguidcurve = !wavguidf->isUnChanged(); + pedited->wavelet.wavhuecurve = !wavhue->isUnChanged(); pedited->wavelet.Chcurve = !Chshape->isUnChanged(); pedited->wavelet.bllev = bllev->getEditedState(); pedited->wavelet.pastlev = pastlev->getEditedState(); @@ -2075,6 +2351,10 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.bluemed = bluemed->getEditedState(); pedited->wavelet.greenhigh = greenhigh->getEditedState(); pedited->wavelet.bluehigh = bluehigh->getEditedState(); + pedited->wavelet.sigm = sigm->getEditedState(); + pedited->wavelet.levden = levden->getEditedState(); + pedited->wavelet.thrden = thrden->getEditedState(); + pedited->wavelet.limden = limden->getEditedState(); pedited->wavelet.ballum = ballum->getEditedState(); pedited->wavelet.balchrom = balchrom->getEditedState(); pedited->wavelet.chromfi = chromfi->getEditedState(); @@ -2083,6 +2363,9 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.mergeC = mergeC->getEditedState(); pedited->wavelet.softrad = softrad->getEditedState(); pedited->wavelet.softradend = softradend->getEditedState(); + pedited->wavelet.strend = strend->getEditedState(); + pedited->wavelet.detend = detend->getEditedState(); + pedited->wavelet.thrend = thrend->getEditedState(); pedited->wavelet.balance = balance->getEditedState(); pedited->wavelet.iter = iter->getEditedState(); pedited->wavelet.sigmafin = sigmafin->getEditedState(); @@ -2213,6 +2496,40 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pp->wavelet.complexmethod = "expert"; } + if (denmethod->get_active_row_number() == 0) { + pp->wavelet.denmethod = "equ"; + } else if (denmethod->get_active_row_number() == 1) { + pp->wavelet.denmethod = "high"; + } else if (denmethod->get_active_row_number() == 2) { + pp->wavelet.denmethod = "low"; + } else if (denmethod->get_active_row_number() == 3) { + pp->wavelet.denmethod = "12high"; + } else if (denmethod->get_active_row_number() == 4) { + pp->wavelet.denmethod = "12low"; + } + + if (mixmethod->get_active_row_number() == 0) { + pp->wavelet.mixmethod = "nois"; + } else if (mixmethod->get_active_row_number() == 1) { + pp->wavelet.mixmethod = "mix"; + } else if (mixmethod->get_active_row_number() == 2) { + pp->wavelet.mixmethod = "mix7"; + } else if (mixmethod->get_active_row_number() == 3) { + pp->wavelet.mixmethod = "den"; + } + + if (slimethod->get_active_row_number() == 0) { + pp->wavelet.slimethod = "sli"; + } else if (slimethod->get_active_row_number() == 1) { + pp->wavelet.slimethod = "cur"; + } + + if (quamethod->get_active_row_number() == 0) { + pp->wavelet.quamethod = "cons"; + } else if (quamethod->get_active_row_number() == 1) { + pp->wavelet.quamethod = "agre"; + } + if (daubcoeffmethod->get_active_row_number() == 0) { pp->wavelet.daubcoeffmethod = "2_"; } else if (daubcoeffmethod->get_active_row_number() == 1) { @@ -2252,12 +2569,20 @@ void Wavelet::curveChanged(CurveEditor* ce) listener->panelChanged(EvWavlevelshc, M("HISTORY_CUSTOMCURVE")); } else if (ce == opacityShapeBY) { listener->panelChanged(EvWavOpac, M("HISTORY_CUSTOMCURVE")); + } else if (ce == wavdenoise) { + listener->panelChanged(EvWavdenoise, M("HISTORY_CUSTOMCURVE")); + } else if (ce == wavdenoiseh) { + listener->panelChanged(EvWavdenoiseh, M("HISTORY_CUSTOMCURVE")); } else if (ce == opacityShape) { listener->panelChanged(EvWavopacity, M("HISTORY_CUSTOMCURVE")); } else if (ce == opacityShapeWL) { listener->panelChanged(EvWavopacityWL, M("HISTORY_CUSTOMCURVE")); } else if (ce == hhshape) { listener->panelChanged(EvWavHHCurve, M("HISTORY_CUSTOMCURVE")); + } else if (ce == wavguidf) { + listener->panelChanged(EvWavguid, M("HISTORY_CUSTOMCURVE")); + } else if (ce == wavhue) { + listener->panelChanged(EvWavhue, M("HISTORY_CUSTOMCURVE")); } else if (ce == Chshape) { listener->panelChanged(EvWavCHCurve, M("HISTORY_CUSTOMCURVE")); } else if (ce == clshape) { @@ -2331,6 +2656,12 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit level1noise->setDefault (defParams->wavelet.level1noise); level2noise->setDefault (defParams->wavelet.level2noise); level3noise->setDefault (defParams->wavelet.level3noise); + leveldenoise->setDefault (defParams->wavelet.leveldenoise); + levelsigm->setDefault (defParams->wavelet.levelsigm); + sigm->setDefault(defParams->wavelet.sigm); + levden->setDefault(defParams->wavelet.levden); + thrden->setDefault(defParams->wavelet.thrden); + limden->setDefault(defParams->wavelet.limden); ballum->setDefault(defParams->wavelet.ballum); balchrom->setDefault(defParams->wavelet.balchrom); chromfi->setDefault(defParams->wavelet.chromfi); @@ -2347,6 +2678,9 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit mergeC->setDefault(defParams->wavelet.mergeC); softrad->setDefault(defParams->wavelet.softrad); softradend->setDefault(defParams->wavelet.softradend); + strend->setDefault(defParams->wavelet.strend); + detend->setDefault(defParams->wavelet.detend); + thrend->setDefault(defParams->wavelet.thrend); if (pedited) { greenlow->setDefaultEditedState(pedited->wavelet.greenlow ? Edited : UnEdited); @@ -2359,6 +2693,13 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit mergeC->setDefaultEditedState(pedited->wavelet.mergeC ? Edited : UnEdited); softrad->setDefaultEditedState(pedited->wavelet.softrad ? Edited : UnEdited); softradend->setDefaultEditedState(pedited->wavelet.softradend ? Edited : UnEdited); + strend->setDefaultEditedState(pedited->wavelet.strend ? Edited : UnEdited); + detend->setDefaultEditedState(pedited->wavelet.detend ? Edited : UnEdited); + thrend->setDefaultEditedState(pedited->wavelet.thrend ? Edited : UnEdited); + sigm->setDefaultEditedState(pedited->wavelet.sigm ? Edited : UnEdited); + levden->setDefaultEditedState(pedited->wavelet.levden ? Edited : UnEdited); + thrden->setDefaultEditedState(pedited->wavelet.thrden ? Edited : UnEdited); + limden->setDefaultEditedState(pedited->wavelet.limden ? Edited : UnEdited); ballum->setDefaultEditedState(pedited->wavelet.ballum ? Edited : UnEdited); balchrom->setDefaultEditedState(pedited->wavelet.balchrom ? Edited : UnEdited); chromfi->setDefaultEditedState(pedited->wavelet.chromfi ? Edited : UnEdited); @@ -2420,6 +2761,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit level1noise->setDefaultEditedState(pedited->wavelet.level1noise ? Edited : UnEdited); level2noise->setDefaultEditedState(pedited->wavelet.level2noise ? Edited : UnEdited); level3noise->setDefaultEditedState(pedited->wavelet.level3noise ? Edited : UnEdited); + leveldenoise->setDefaultEditedState(pedited->wavelet.leveldenoise ? Edited : UnEdited); + levelsigm->setDefaultEditedState(pedited->wavelet.levelsigm ? Edited : UnEdited); for (int i = 0; i < 9; i++) { correction[i]->setDefaultEditedState(pedited->wavelet.c[i] ? Edited : UnEdited); @@ -2473,6 +2816,8 @@ void Wavelet::setDefaults(const ProcParams* defParams, const ParamsEdited* pedit level1noise->setDefaultEditedState(Irrelevant); level2noise->setDefaultEditedState(Irrelevant); level3noise->setDefaultEditedState(Irrelevant); + leveldenoise->setDefaultEditedState(Irrelevant); + levelsigm->setDefaultEditedState(Irrelevant); pastlev->setDefaultEditedState(Irrelevant); satlev->setDefaultEditedState(Irrelevant); strength->setDefaultEditedState(Irrelevant); @@ -2511,6 +2856,13 @@ void Wavelet::adjusterChanged(ThresholdAdjuster* a, double newBottom, double new } else if (a == level3noise) { listener->panelChanged(EvWavlev3nois, Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS") + ": %1" + "\n" + M("TP_WAVELET_STREN") + ": %2"), int(newTop), int(newBottom))); + } else if (a == leveldenoise) { + listener->panelChanged(EvWavlevdenois, + Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS") + ": %1" + "\n" + M("TP_WAVELET_DEN5THR") + ": %2"), int(newTop), int(newBottom))); + } else if (a == levelsigm) { + usleep(150); + listener->panelChanged(EvWavlevelsigm, + Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_LEVELLOW") + ": %1" + "\n" + M("TP_WAVELET_LEVELHIGH") + ": %2"), (newTop), (newBottom))); } } @@ -2896,6 +3248,15 @@ void Wavelet::convertParamToNormal() //denoise chromfi->setValue(def_params.chromfi); chromco->setValue(def_params.chromco); + denmethod->set_active(4); + mixmethod->set_active(2); + slimethod->set_active(0); + levelsigm->setValue(def_params.levelsigm); + leveldenoise->setValue(def_params.leveldenoise); + limden->setValue(def_params.limden); + +// quamethod->set_active(0); +// sigm->setValue(def_params.sigm); //toning exptoning->setEnabled(def_params.exptoning); //gamut @@ -2945,6 +3306,17 @@ void Wavelet::updateGUIToMode(int mode) blurFrame->hide(); cbenab->hide(); sigmafin->hide(); + denHBox->hide(); + mixHBox->hide(); + sliHBox->hide(); + sigm->show(); + levelsigm->hide(); + CurveEditorwavnoiseh->hide(); + CurveEditorwavnoise->hide(); + // levden->hide(); + thrden->show(); + leveldenoise->hide(); + limden->hide(); } else { offset->show(); sigma->show(); @@ -2962,6 +3334,28 @@ void Wavelet::updateGUIToMode(int mode) blurFrame->show(); cbenab->show(); sigmafin->show(); + denHBox->hide(); + mixHBox->show(); + sigm->hide(); + levelsigm->show(); + limden->show(); + levden->show(); + sliHBox->show(); + if (slimethod->get_active_row_number() == 0){ + leveldenoise->show(); + thrden->show(); + CurveEditorwavnoiseh->hide(); + CurveEditorwavnoise->hide(); + } else { + thrden->hide(); + leveldenoise->show(); + CurveEditorwavnoiseh->show(); + CurveEditorwavnoise->show(); + } + disableListener(); + denmethod->set_active(4); + enableListener(); + } } @@ -2982,7 +3376,54 @@ void Wavelet::complexmethodChanged() } } +void Wavelet::denmethodChanged() +{ + if (listener && (multiImage || getEnabled())) { + listener->panelChanged(EvWavdenmethod, denmethod->get_active_text()); + } +} + +void Wavelet::mixmethodChanged() +{ + + if (listener && (multiImage || getEnabled())) { + listener->panelChanged(EvWavmixmethod, mixmethod->get_active_text()); + } +} + +void Wavelet::slimethodChanged() +{ + + if (slimethod->get_active_row_number() == 0 && complexmethod->get_active_row_number() == 0) { + updateGUIToMode(0); + convertParamToNormal(); + leveldenoise->show(); + } else if (slimethod->get_active_row_number() == 0 && complexmethod->get_active_row_number() == 1){ + updateGUIToMode(1); + leveldenoise->show(); + CurveEditorwavnoiseh->hide(); + CurveEditorwavnoise->hide(); + } else if (slimethod->get_active_row_number() == 1 && complexmethod->get_active_row_number() == 1){ + updateGUIToMode(1); + leveldenoise->show(); + CurveEditorwavnoiseh->show(); + CurveEditorwavnoise->show(); + } + + + if (listener && (multiImage || getEnabled())) { + listener->panelChanged(EvWavslimethod, slimethod->get_active_text()); + } +} + +void Wavelet::quamethodChanged() +{ + + if (listener && (multiImage || getEnabled())) { + listener->panelChanged(EvWavquamethod, quamethod->get_active_text()); + } +} void Wavelet::TilesmethodChanged() { @@ -3066,6 +3507,10 @@ void Wavelet::setBatchMode(bool batchMode) Backmethod->append(M("GENERAL_UNCHANGED")); Tilesmethod->append(M("GENERAL_UNCHANGED")); complexmethod->append(M("GENERAL_UNCHANGED")); + denmethod->append(M("GENERAL_UNCHANGED")); + mixmethod->append(M("GENERAL_UNCHANGED")); + slimethod->append(M("GENERAL_UNCHANGED")); + quamethod->append(M("GENERAL_UNCHANGED")); daubcoeffmethod->append(M("GENERAL_UNCHANGED")); CHmethod->append(M("GENERAL_UNCHANGED")); Medgreinf->append(M("GENERAL_UNCHANGED")); @@ -3081,6 +3526,10 @@ void Wavelet::setBatchMode(bool batchMode) opaCurveEditorG->setBatchMode(batchMode); curveEditorC->setBatchMode(batchMode); opacityCurveEditorG->setBatchMode(batchMode); + CurveEditorwavnoise->setBatchMode(batchMode); + CurveEditorwavnoiseh->setBatchMode(batchMode); + CurveEditorwavguid->setBatchMode(batchMode); + CurveEditorwavhue->setBatchMode(batchMode); opacityCurveEditorW->setBatchMode(batchMode); opacityCurveEditorWL->setBatchMode(batchMode); curveEditorbl->setBatchMode(batchMode); @@ -3141,6 +3590,8 @@ void Wavelet::setBatchMode(bool batchMode) level1noise->showEditedCB(); level2noise->showEditedCB(); level3noise->showEditedCB(); + leveldenoise->showEditedCB(); + levelsigm->showEditedCB(); ToolPanel::setBatchMode(batchMode); @@ -3279,6 +3730,13 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval) } else { sup->hide(); } + if(z >= 8 ) { + expnoise->setEnabled(false); + expnoise->set_sensitive(false); + } else { + // expnoise->setEnabled(pp->wavelet.expnoise); + expnoise->set_sensitive(true); + } listener->panelChanged(EvWavthres, thres->getTextValue()); updateGUImaxlev(); @@ -3309,6 +3767,14 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval) listener->panelChanged(EvWavbluehigh, bluehigh->getTextValue()); } else if (a == ballum) { listener->panelChanged(EvWavballum, ballum->getTextValue()); + } else if (a == sigm) { + listener->panelChanged(EvWavsigm, sigm->getTextValue()); + } else if (a == levden) { + listener->panelChanged(EvWavlevden, levden->getTextValue()); + } else if (a == thrden) { + listener->panelChanged(EvWavthrden, thrden->getTextValue()); + } else if (a == limden) { + listener->panelChanged(EvWavlimden, limden->getTextValue()); } else if (a == balchrom) { listener->panelChanged(EvWavbalchrom, balchrom->getTextValue()); } else if (a == chromfi) { @@ -3323,6 +3789,12 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval) listener->panelChanged(EvWavsoftrad, softrad->getTextValue()); } else if (a == softradend) { listener->panelChanged(EvWavsoftradend, softradend->getTextValue()); + } else if (a == strend) { + listener->panelChanged(EvWavstrend, strend->getTextValue()); + } else if (a == detend) { + listener->panelChanged(EvWavdetend, detend->getTextValue()); + } else if (a == thrend) { + listener->panelChanged(EvWavthrend, thrend->getTextValue()); } else if (a == greenmed) { listener->panelChanged(EvWavgreenmed, greenmed->getTextValue()); } else if (a == bluemed) { @@ -3387,6 +3859,13 @@ void Wavelet::enabledUpdateUI() sup->hide(); } + if(z >= 8) { + expnoise->setEnabled(false); + expnoise->set_sensitive(false); + } else { + expnoise->set_sensitive(true); + } + // adjusterUpdateUI(tmrs); } } diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index a497d2c4f..c7e002a64 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . * - * 2014 Jacques Desmis + * 2014 2020 Jacques Desmis */ #pragma once @@ -102,6 +102,23 @@ private: rtengine::ProcEvent EvWavprotab; rtengine::ProcEvent EvWavlevelshc; rtengine::ProcEvent EvWavcomplexmet; + rtengine::ProcEvent EvWavsigm; + rtengine::ProcEvent EvWavdenoise; + rtengine::ProcEvent EvWavdenmethod; + rtengine::ProcEvent EvWavmixmethod; + rtengine::ProcEvent EvWavquamethod; + rtengine::ProcEvent EvWavlevden; + rtengine::ProcEvent EvWavdenoiseh; + rtengine::ProcEvent EvWavstrend; + rtengine::ProcEvent EvWavdetend; + rtengine::ProcEvent EvWavlevdenois; + rtengine::ProcEvent EvWavslimethod; + rtengine::ProcEvent EvWavthrend; + rtengine::ProcEvent EvWavguid; + rtengine::ProcEvent EvWavhue; + rtengine::ProcEvent EvWavthrden; + rtengine::ProcEvent EvWavlevelsigm; + rtengine::ProcEvent EvWavlimden; LabGrid *labgrid; @@ -122,6 +139,10 @@ private: void MedgreinfChanged(); void TMmethodChanged(); void complexmethodChanged(); + void denmethodChanged(); + void mixmethodChanged(); + void quamethodChanged(); + void slimethodChanged(); void TilesmethodChanged(); void avoidToggled(); void showmaskToggled (); @@ -183,6 +204,14 @@ private: FlatCurveEditor* opacityShapeRG; CurveEditorGroup* const opacityCurveEditorG; FlatCurveEditor* opacityShapeBY; + CurveEditorGroup* const CurveEditorwavnoise; + FlatCurveEditor* wavdenoise; + CurveEditorGroup* const CurveEditorwavnoiseh; + FlatCurveEditor* wavdenoiseh; + CurveEditorGroup* const CurveEditorwavguid; + FlatCurveEditor* wavguidf; + CurveEditorGroup* const CurveEditorwavhue; + FlatCurveEditor* wavhue; CurveEditorGroup* const opacityCurveEditorW; CurveEditorGroup* const opacityCurveEditorWL; FlatCurveEditor* opacityShape; @@ -261,7 +290,13 @@ private: ThresholdAdjuster* const level1noise; ThresholdAdjuster* const level2noise; ThresholdAdjuster* const level3noise; + ThresholdAdjuster* const leveldenoise; + ThresholdAdjuster* const levelsigm; + Adjuster* const sigm; + Adjuster* const levden; + Adjuster* const thrden; + Adjuster* const limden; Adjuster* const threshold; Adjuster* const threshold2; Adjuster* const edgedetect; @@ -277,6 +312,9 @@ private: Adjuster* const mergeC; Adjuster* const softrad; Adjuster* const softradend; + Adjuster* const strend; + Adjuster* const detend; + Adjuster* const thrend; Adjuster* const chrwav; MyComboBoxText* const Lmethod; @@ -311,6 +349,14 @@ private: sigc::connection MedgreinfConn; MyComboBoxText* const ushamethod; sigc::connection ushamethodconn; + MyComboBoxText* const denmethod; + sigc::connection denmethodconn; + MyComboBoxText* const mixmethod; + sigc::connection mixmethodconn; + MyComboBoxText* const quamethod; + sigc::connection quamethodconn; + MyComboBoxText* const slimethod; + sigc::connection slimethodconn; Gtk::Frame* const chanMixerHLFrame; Gtk::Frame* const chanMixerMidFrame; @@ -323,6 +369,7 @@ private: Gtk::Frame* const fincFrame; Gtk::Frame* const dirFrame; Gtk::Frame* const tonFrame; + Gtk::Frame* const guidFrame; Gtk::Label* const wavLabels; Gtk::Label* const labmC; @@ -343,6 +390,10 @@ private: Gtk::HBox* const neutrHBox; Gtk::HBox* const usharpHBox; Gtk::HBox* const ctboxch; + Gtk::HBox* const quaHBox; + Gtk::HBox* const sliHBox; + Gtk::HBox* const denHBox; + Gtk::HBox* const mixHBox; Gtk::VBox* const ctboxBA;// = Gtk::manage(new Gtk::VBox()); sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enabletmConn, enableFinalConn, enableclariConn; diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index a371bad88..db63c68be 100644 --- a/rtgui/xtransprocess.cc +++ b/rtgui/xtransprocess.cc @@ -79,9 +79,7 @@ XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP 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); @@ -91,9 +89,7 @@ XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP border = Gtk::manage(new Adjuster(M("TP_RAW_BORDER"), 0, 16, 1, 7)); 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); @@ -103,9 +99,7 @@ XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP 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); diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index 28059e69c..655a036c7 100644 --- a/rtgui/xtransrawexposure.cc +++ b/rtgui/xtransrawexposure.cc @@ -33,25 +33,19 @@ XTransRAWExposure::XTransRAWExposure () : FoldableToolPanel(this, "xtransrawexpo PexBlackRed = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_RED"), -2048, 2048, 1.0, 0)); //black level PexBlackRed->setAdjusterListener (this); - if (PexBlackRed->delay < options.adjusterMaxDelay) { - PexBlackRed->delay = options.adjusterMaxDelay; - } + PexBlackRed->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); PexBlackRed->show(); PexBlackGreen = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_GREEN"), -2048, 2048, 1.0, 0)); //black level PexBlackGreen->setAdjusterListener (this); - if (PexBlackGreen->delay < options.adjusterMaxDelay) { - PexBlackGreen->delay = options.adjusterMaxDelay; - } + PexBlackGreen->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); PexBlackGreen->show(); PexBlackBlue = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_BLUE"), -2048, 2048, 1.0, 0)); //black level PexBlackBlue->setAdjusterListener (this); - if (PexBlackBlue->delay < options.adjusterMaxDelay) { - PexBlackBlue->delay = options.adjusterMaxDelay; - } + PexBlackBlue->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); PexBlackBlue->show();