diff --git a/AUTHORS.txt b/AUTHORS.txt
index ec40f75e1..b880db000 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -33,6 +33,7 @@ Development contributors, in last name alphabetical order:
Jan Rinze
Alberto Romei
Ben S.
+ Simon Segerblom Rex
Andrey Skvortsov
Fabio Suprani
Anders Torger
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f94454b63..041b273df 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -16,6 +16,7 @@ The most useful feedback is based on the latest development code, and in the cas
- Announce and discuss your plans in GitHub before starting work.
- Work in a new branch. Fork if necessary.
- Keep branches small so that completed and working features can be merged into the "dev" branch often, and so that they can be abandoned if they head in the wrong direction.
+- Documentation for your work must be provided in order for your branch to be merged if it changes or adds anything the user should know about. The documentation can be provided in plain-text or markdown form as a comment in the issue or pull request.
- Use C++11.
- To break header dependencies use forward declarations as much as possible. See [#5197](https://github.com/Beep6581/RawTherapee/pull/5197#issuecomment-468938190) for some tips.
- The naming isn't homogeneous throughout the code but here is a rough guideline:
diff --git a/licenses/sleef_LICENSE.txt b/licenses/sleef_LICENSE.txt
new file mode 100644
index 000000000..8170d3224
--- /dev/null
+++ b/licenses/sleef_LICENSE.txt
@@ -0,0 +1,30 @@
+=============================================================================
+Boost Software License - Version 1.0
+
+This license applies to selected portions of the software derived from SLEEF
+(https://sleef.org/), as noted in the applicable source file headers.
+=============================================================================
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/rtdata/images/svg/spot-active.svg b/rtdata/images/svg/spot-active.svg
new file mode 100644
index 000000000..bc36a7a19
--- /dev/null
+++ b/rtdata/images/svg/spot-active.svg
@@ -0,0 +1,81 @@
+
+
+
+
diff --git a/rtdata/images/svg/spot-normal.svg b/rtdata/images/svg/spot-normal.svg
new file mode 100644
index 000000000..d0320e31f
--- /dev/null
+++ b/rtdata/images/svg/spot-normal.svg
@@ -0,0 +1,73 @@
+
+
+
+
diff --git a/rtdata/images/svg/spot-prelight.svg b/rtdata/images/svg/spot-prelight.svg
new file mode 100644
index 000000000..9cfc1acfa
--- /dev/null
+++ b/rtdata/images/svg/spot-prelight.svg
@@ -0,0 +1,74 @@
+
+
+
+
diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais
index 6d9a06afb..8377b6cbc 100644
--- a/rtdata/languages/Francais
+++ b/rtdata/languages/Francais
@@ -764,6 +764,8 @@ HISTORY_MSG_SHARPENING_CONTRAST;Netteté - Seuil de contraste
HISTORY_MSG_SH_COLORSPACE;O/HL - Espace couleur
HISTORY_MSG_SOFTLIGHT_ENABLED;Lumière douce
HISTORY_MSG_SOFTLIGHT_STRENGTH;Lumière douce - Force
+HISTORY_MSG_SPOT;Retrait de taches
+HISTORY_MSG_SPOT_ENTRY;Retrait de taches - Modif. de points
HISTORY_MSG_TM_FATTAL_ANCHOR;CPD - Ancre
HISTORY_NEWSNAPSHOT;Ajouter
HISTORY_NEWSNAPSHOT_TOOLTIP;Raccourci: Alt-s
@@ -809,7 +811,7 @@ ICCPROFCREATOR_PROF_V2;ICC v2
ICCPROFCREATOR_PROF_V4;ICC v4
ICCPROFCREATOR_SAVEDIALOG_TITLE;Enregistrer le profil ICC sous...
ICCPROFCREATOR_SLOPE;Pente
-ICCPROFCREATOR_TRC_PRESET;Courbe de réponse tonale:
+ICCPROFCREATOR_TRC_PRESET;Courbe de réponse tonale
IPTCPANEL_CATEGORY;Catégorie
IPTCPANEL_CATEGORYHINT;Identifie le sujet de l'image selon l'opinion du fournisseur.
IPTCPANEL_CITY;Ville
@@ -1024,6 +1026,7 @@ PARTIALPASTE_SHARPENEDGE;Bords
PARTIALPASTE_SHARPENING;Netteté
PARTIALPASTE_SHARPENMICRO;Microcontraste
PARTIALPASTE_SOFTLIGHT;Lumière douce
+PARTIALPASTE_SPOT;Retrait de taches
PARTIALPASTE_TM_FATTAL;Compression de plage dynamique
PARTIALPASTE_VIBRANCE;Vibrance
PARTIALPASTE_VIGNETTING;Correction du vignettage
@@ -1297,8 +1300,8 @@ TP_BWMIX_AUTOCH;Auto
TP_BWMIX_CC_ENABLED;Ajuster les couleurs complémentaires
TP_BWMIX_CC_TOOLTIP;Activer pour permettre l'ajustage automatique des couleur complémentaire dans le mode ROJVCBPM
TP_BWMIX_CHANNEL;Égaliseur de Luminance
-TP_BWMIX_CURVEEDITOR1;Courbe 'avant'
-TP_BWMIX_CURVEEDITOR2;Courbe 'après'
+TP_BWMIX_CURVEEDITOR1;Courbe 'avant':
+TP_BWMIX_CURVEEDITOR2;Courbe 'après':
TP_BWMIX_CURVEEDITOR_AFTER_TOOLTIP;Courbe tonale, après la conversion en N&B, à la fin du traitement
TP_BWMIX_CURVEEDITOR_BEFORE_TOOLTIP;Courbe tonale, juste avant la conversion en N&B\nPeut prendre en compte les composantes couleur
TP_BWMIX_CURVEEDITOR_LH_TOOLTIP;Modifie la luminance en fonction de la teinte\nFaites attention aux valeurs extrêmes qui peuvent causer des artefacts
@@ -1438,7 +1441,7 @@ TP_COLORTONING_AUTOSAT;Automatique
TP_COLORTONING_BALANCE;Balance
TP_COLORTONING_BY;o C/L
TP_COLORTONING_CHROMAC;Opacité
-TP_COLORTONING_COLOR;Couleur
+TP_COLORTONING_COLOR;Couleur:
TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP;Opacité chroma en fonction de la luminance oC=f(L)
TP_COLORTONING_HIGHLIGHT;Hautes lumières
TP_COLORTONING_HUE;Teinte
@@ -1520,11 +1523,11 @@ TP_DEHAZE_STRENGTH;Force
TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Multi-zones auto
TP_DIRPYRDENOISE_CHROMINANCE_AUTOGLOBAL;Global automatique
TP_DIRPYRDENOISE_CHROMINANCE_BLUEYELLOW;Chrominance - Bleu-Jaune
-TP_DIRPYRDENOISE_CHROMINANCE_CURVE;Courbe de chrominance
+TP_DIRPYRDENOISE_CHROMINANCE_CURVE;Courbe de chrominance:
TP_DIRPYRDENOISE_CHROMINANCE_CURVE_TOOLTIP;Augmente (multiplie) la valeur de tous les curseurs de chrominance.\nCette courbe vous permet d'ajuster la force de la réduction de bruit chromatique en fonction de la chromaticité, par exemple pour augmenter l'action dans les zones faiblement saturées et pour la diminuer dans celles très saturées.
TP_DIRPYRDENOISE_CHROMINANCE_FRAME;Chrominance
TP_DIRPYRDENOISE_CHROMINANCE_MANUAL;Manuel
-TP_DIRPYRDENOISE_CHROMINANCE_MASTER;Chrominance - Maître
+TP_DIRPYRDENOISE_CHROMINANCE_MASTER;Chrominance-Maître
TP_DIRPYRDENOISE_CHROMINANCE_METHOD;Méthode
TP_DIRPYRDENOISE_CHROMINANCE_METHODADVANCED_TOOLTIP;Manuel\nAgit sur l'image entière.\nVous controlez les paramètres de réduction de bruit manuellement.\n\nGlobal automatique\nAgit sur l'image entière.\n9 zones sont utilisées pour calculer un réglage de réduction de bruit de chroma.\n\nAperçu\nAgit sur l'image entière.\nLa partie visible de l'image dans l'aperçu est utilisé pour calculer un réglage de réduction de bruit de chroma.
TP_DIRPYRDENOISE_CHROMINANCE_METHOD_TOOLTIP;Manuel\nAgit sur l'image entière.\nVous controlez les paramètres de réduction de bruit manuellement.\n\nGlobal automatique\nAgit sur l'image entière.\n9 zones sont utilisées pour calculer un réglage de réduction de bruit de chroma.\n\nAutomatique multi-zones\nPas d'aperçu - ne fonctionne que lors de l'enregistrement, mais utiliser la méthode "Aperçu" en faisant correspondre la taille et le centre de la tuile à la taille et au centre de l'aperçu, vous permet d'avoir une idée des résultats attendus.\nL'image est divisé en tuiles (entre 10 et 70 en fonction de la taille de l'image) et chaque tuile reçoit son propre réglage de réduction de bruit de chrominance.\n\nAperçu\nAgit sur l'image entière.\nLa partie de l'image visible dans l'aperçu est utilisé pour calculer un réglage de réduction de bruit de chroma.
@@ -1538,7 +1541,7 @@ TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_TILEINFO;Taille des tuiles =%1, Centre: Tx=
TP_DIRPYRDENOISE_CHROMINANCE_REDGREEN;Chrominance - Rouge-Vert
TP_DIRPYRDENOISE_LABEL;Réduction de Bruit
TP_DIRPYRDENOISE_LUMINANCE_CONTROL;Contrôle de luminance
-TP_DIRPYRDENOISE_LUMINANCE_CURVE;Courbe de luminance
+TP_DIRPYRDENOISE_LUMINANCE_CURVE;Courbe de luminance:
TP_DIRPYRDENOISE_LUMINANCE_DETAIL;Niveau de détails de Luminance
TP_DIRPYRDENOISE_LUMINANCE_FRAME;Luminance
TP_DIRPYRDENOISE_LUMINANCE_SMOOTHING;Luminance
@@ -1657,7 +1660,7 @@ TP_HLREC_ENA_TOOLTIP;Peut être activé par le bouton Niveau Auto
TP_HLREC_LABEL;Reconstruction des hautes lumières
TP_HLREC_LUMINANCE;Récupération de la luminance
TP_HLREC_METHOD;Méthode:
-TP_HSVEQUALIZER_CHANNEL;Canal
+TP_HSVEQUALIZER_CHANNEL;Canal:
TP_HSVEQUALIZER_HUE;T
TP_HSVEQUALIZER_LABEL;Égaliseur TSV
TP_HSVEQUALIZER_SAT;S
@@ -1755,7 +1758,7 @@ TP_LOCALCONTRAST_LIGHTNESS;Niveau des hautes-lumières
TP_LOCALCONTRAST_RADIUS;Rayon
TP_LOCALLAB_ACTIV;Luminosité seulement
TP_LOCALLAB_ACTIVSPOT;Activer le Spot
-TP_LOCALLAB_ADJ;Egalisateur Bleu-jaune Rouge-vert
+TP_LOCALLAB_ADJ;Egalisateur couleur
TP_LOCALLAB_ALL;Toutes les rubriques
TP_LOCALLAB_AMOUNT;Quantité
TP_LOCALLAB_ARTIF;Détection de forme
@@ -1771,8 +1774,8 @@ TP_LOCALLAB_BILATERAL;Filtre Bilateral
TP_LOCALLAB_BLACK_EV;Noir Ev
TP_LOCALLAB_BLCO;Chrominance seulement
TP_LOCALLAB_BLENDMASKCOL;Mélange - fusion
-TP_LOCALLAB_BLENDMASKMASK;Ajout / soustrait le masque Luminance
-TP_LOCALLAB_BLENDMASKMASKAB;Ajout / soustrait le masque Chrominance
+TP_LOCALLAB_BLENDMASKMASK;Ajout/soustrait masque Luminance
+TP_LOCALLAB_BLENDMASKMASKAB;Ajout/soustrait masque Chro.
TP_LOCALLAB_BLENDMASK_TOOLTIP;Si fusion = 0 seule la détection de forme est améliorée.\nSi fusion > 0 le masque est ajouté à l'image. Si fusion < 0 le masque est soustrait à l'image
TP_LOCALLAB_BLENDMASKMASK_TOOLTIP;Si ce curseur = 0 pas d'action.\nAjoute ou soustrait le masque de l'image originale
TP_LOCALLAB_BLGUID;Filtre guidé
@@ -1804,14 +1807,14 @@ 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 par niveaux détail
+TP_LOCALLAB_CBDL;Contr. par niveaux 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étail - 2
TP_LOCALLAB_CENTER_X;Centre X
TP_LOCALLAB_CENTER_Y;Centre Y
-TP_LOCALLAB_CH;Courbes CL - LC
+TP_LOCALLAB_CH;CL - LC
TP_LOCALLAB_CHROMA;Chrominance
TP_LOCALLAB_CHROMABLU;Niveaux Chroma
TP_LOCALLAB_CHROMABLU_TOOLTIP;Agit comme un amplificateur-reducteur d'action en comparant aux réglages de luma.\nEn dessous de 1 reduit, au dessus de 1 amplifie
@@ -1824,7 +1827,7 @@ TP_LOCALLAB_CHRRT;Chroma
TP_LOCALLAB_CIRCRADIUS;Taille Spot
TP_LOCALLAB_CIRCRAD_TOOLTIP;Contient les références du RT-spot, utile pour la détection de forme (couleur, luma, chroma, Sobel).\nLes faibles valeurs peuvent être utiles pour les feuillages.\nLes valeurs élevées peuvent être utile pour la peau
TP_LOCALLAB_CLARICRES;Fusion Chroma
-TP_LOCALLAB_CLARIFRA;Clarté & Masque de netteté - Fusion & adoucir images
+TP_LOCALLAB_CLARIFRA;Clarté & Masque netteté/Fusion & adoucir
TP_LOCALLAB_CLARILRES;Fusion Luma
TP_LOCALLAB_CLARISOFT;Rayon adoucir
TP_LOCALLAB_CLARISOFT_TOOLTIP;Actif pour Clarté et Masque de netteté si différent de zéro.\n\nActif pour toutes les pyramides ondelettes.\nInactif si rayon = 0
@@ -1832,7 +1835,7 @@ TP_LOCALLAB_CLARITYML;Clarté
TP_LOCALLAB_CLARI_TOOLTIP;En dessous ou égal à 4, 'Masque netteté' est actif.\nAu dessus du niveau ondelettes 5 'Clarté' est actif.\nUtilesu=i vous utilisez 'Compression dynamique des niveaux'
TP_LOCALLAB_CLIPTM;Clip Recupère données (gain)
TP_LOCALLAB_COFR;Couleur & Lumière
-TP_LOCALLAB_COLORDE;Couleur prévisualisation sélection ΔE - Intensité
+TP_LOCALLAB_COLORDE;Couleur prévis. sélection ΔE - Intensité
TP_LOCALLAB_COLORDEPREV_TOOLTIP;Bouton Prévisualisation ΔE a besoin qu'un seul outil soit activé (expander).\nPour pouvoir avoir une Prévisualisation ΔE avec plusieurs outils activés utiliser Masque et modifications - Prévisualisation ΔE
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
@@ -1854,8 +1857,8 @@ 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
-TP_LOCALLAB_CSTHRESHOLDBLUR;Ψ Masque Ondelettes niveau
+TP_LOCALLAB_CSTHRESHOLD;Ondelettes niveaux
+TP_LOCALLAB_CSTHRESHOLDBLUR;Masque Ondelettes niveau
TP_LOCALLAB_CURV;Luminosité - Contraste - Chrominance "Super"
TP_LOCALLAB_CURVCURR;Normal
TP_LOCALLAB_CURVEEDITOR_CC_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).
@@ -1892,9 +1895,9 @@ TP_LOCALLAB_DENOIEQUALCHRO_TOOLTIP;Equilibre l'action de denoise chrominance ent
TP_LOCALLAB_DENOIBILAT_TOOLTIP;Traite le bruit d'impulsion (poivre et sel)
TP_LOCALLAB_DEPTH;Profondeur
TP_LOCALLAB_DETAIL;Contraste local
-TP_LOCALLAB_DETAILFRA;Détection de bord
+TP_LOCALLAB_DETAILFRA;Détection bord - DCT
TP_LOCALLAB_DETAILSH;Details
-TP_LOCALLAB_DETAILTHR;Seuil Detail Luminance Chroma (DCT ƒ)
+TP_LOCALLAB_DETAILTHR;Seuil Detail Luma-Chroma
TP_LOCALLAB_DUPLSPOTNAME;Copier
TP_LOCALLAB_EDGFRA;Netteté des bords
TP_LOCALLAB_EDGSHOW;Montre tous les outils
@@ -1955,15 +1958,15 @@ TP_LOCALLAB_FATFRA;Compression Dynamique ƒ
TP_LOCALLAB_FATFRAME_TOOLTIP;PDE Fattal - utilise Fattal Tone mapping algorithme.
TP_LOCALLAB_FATLEVEL;Sigma
TP_LOCALLAB_FATRES;Quantité de Residual Image
-TP_LOCALLAB_FATSHFRA;Compression Dynamique Masque ƒ
+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_FEATVALUE;Adouc. 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_FULLIMAGE;Calcule les valeurs NoirEv-blancEv - 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)
@@ -1999,7 +2002,7 @@ 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
+TP_LOCALLAB_HLH;H
TP_LOCALLAB_IND;Independant (souris)
TP_LOCALLAB_INDSL;Independant (souris + curseurs)
TP_LOCALLAB_INVERS;Inverse
@@ -2024,7 +2027,7 @@ TP_LOCALLAB_LC_FFTW_TOOLTIP;FFT améliore la qualité et autorise de grands rayo
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
+TP_LOCALLAB_LEVELWAV;Ondelettes Niveaux
TP_LOCALLAB_LEVELWAV_TOOLTIP;Le niveau est automatiquement adapté à la taille du spot et de la prévisualisation.\nDu niveau 9 taille max 512 jusqu'au niveau 1 taille max = 4
TP_LOCALLAB_LEVFRA;Niveaux
TP_LOCALLAB_LIGHTNESS;Luminosité
@@ -2036,11 +2039,11 @@ TP_LOCALLAB_LIST_TOOLTIP;Vous pouvez choisir 3 niveaux de complexité pour chaqu
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;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
-TP_LOCALLAB_LOC_CONTRASTPYR;Ψ Pyramide 1:
-TP_LOCALLAB_LOC_CONTRASTPYR2;Ψ Pyramide 2:
-TP_LOCALLAB_LOC_CONTRASTPYR2LAB; Contr. par niveaux- TM - Cont.Dir.
-TP_LOCALLAB_LOC_CONTRASTPYRLAB; Filtre Gradué - Netteté bords - Flou
+TP_LOCALLAB_LOC_CONTRAST;Contr. Local & Ondelettes
+TP_LOCALLAB_LOC_CONTRASTPYR;Pyramide 1:
+TP_LOCALLAB_LOC_CONTRASTPYR2;Pyramide 2:
+TP_LOCALLAB_LOC_CONTRASTPYR2LAB; Contr. par niveaux/TM/Cont.Dir.
+TP_LOCALLAB_LOC_CONTRASTPYRLAB; Filtre Gradué/Netteté bords/Flou
TP_LOCALLAB_LOC_RESIDPYR;Image Residuelle
TP_LOCALLAB_LOG;Codage log
TP_LOCALLAB_LOG1FRA;Ajustements Image
@@ -2069,7 +2072,8 @@ TP_LOCALLAB_LOGLIGHTQ;Brillance (Q)
TP_LOCALLAB_LOGLIGHTQ_TOOLTIP;Taux de perception de lumière émanant d'un stimulus.\nIndicateur qu'un stimulus apparaît être plus ou moins brillant, clair.
TP_LOCALLAB_LOGLIN;Logarithme mode
TP_LOCALLAB_LOGPFRA;Niveaux d'Exposition relatif
-TP_LOCALLAB_LOGREPART;Force
+TP_LOCALLAB_LOGREPART;Force globale
+TP_LOCALLAB_LOGREPART_TOOLTIP;Vous permet d'ajuster le nivaeu de l'image 'codage log' par rapport à l'image originale.\nNe concerne pas la composante Ciecam.
TP_LOCALLAB_LOGSATURL_TOOLTIP;Saturation (s) CIECAM16 correspond à la couleur d'un stimulus en relation avec sa propre brillance.\nAgit principalement sur les tons moyens et hauts.
TP_LOCALLAB_LOGSCENE_TOOLTIP;Correspond aux conditions de prise de vue.
TP_LOCALLAB_LOGSURSOUR_TOOLTIP;Change les tons et couleurs en prenant en compte les conditions de prise de vue.\n\nMoyen: Environnement lumineux moyen (standard). L'image ne change pas.\n\nTamisé: Environnement tamisé. L'iamge va devenir un peu plus claire.
@@ -2077,9 +2081,9 @@ TP_LOCALLAB_LOGSRCGREY_TOOLTIP;Estime la valeur du point gris de l'image, tôt d
TP_LOCALLAB_LOGTARGGREY_TOOLTIP;Vous pouvez changer cette valeur pour l'adapter à votre goût.
TP_LOCALLAB_LOG_TOOLNAME;Codage log - 0
TP_LOCALLAB_LOGVIEWING_TOOLTIP;Correspond au medium sur lequel l'image finale sera vue (moniteur, TV, projecteur, imprimante,..), ainsi que son environnement.
-TP_LOCALLAB_LUM;Courbes LL - CC
+TP_LOCALLAB_LUM;LL - CC
TP_LOCALLAB_LUMADARKEST;Plus Sombre
-TP_LOCALLAB_LUMASK;Maqsue Luminance arrière plan
+TP_LOCALLAB_LUMASK;Masque 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 clair
TP_LOCALLAB_LUMONLY;Luminance seulement
@@ -2093,12 +2097,12 @@ TP_LOCALLAB_MASK;Masque
TP_LOCALLAB_MASK2;Courbe de Contraste
TP_LOCALLAB_MASKCOL;Masque Courbes
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_MASKLCTHRMID;Zones grises de-bruite luminance
-TP_LOCALLAB_MASKLCTHRMIDCH;Zones grises de-bruite chrominance
+TP_LOCALLAB_MASKLCTHRMID;Zones grises de-bruite lumina
+TP_LOCALLAB_MASKLCTHRMIDCH;Zones grises de-bruite chroma
TP_LOCALLAB_MASKLC_TOOLTIP;Vous autorise à cibler le de-bruite en se basant sur les informations du masque dans L(L) ou LC(H) (Masque et Modifications).\n Les masques L(L) ou LC(H) doivent être activés pour utiliser cette fonction.\n si le masque est très sombre - sous le seuil 'sombre' - de-bruite sera accru si renforce > 1.\n si le masque est clair - au-dessus du seuil 'clair' - de-bruite sera progressivement réduit.\n entre les deux, de-bruite sera maintenu aux réglages sans masques.
TP_LOCALLAB_MASKLCTHR;Seuil luminance zones claires
TP_LOCALLAB_MASKLCTHRLOW;Seuil luminance zones sombres
-TP_LOCALLAB_MASKLNOISELOW;Renforce de-bruite zones sombres et claires
+TP_LOCALLAB_MASKLNOISELOW;Renf. de-bruite sombres/claires
TP_LOCALLAB_MASKH;Courbe teinte
TP_LOCALLAB_MASKRECOTHRES;Seuil de Récupération
TP_LOCALLAB_MASKDE_TOOLTIP;Utilisé pour diriger l'action de de-bruite basé sur les informations des courbes masques L(L) ou LC(H) (Masque et modifications).\n Les masques L(L) ou LC(H) doivent être activés pour utiliser cette fonction.\n Si le masque est en dessous du seuil sombre le De-bruite sera appliqué progressivement.\n Si le masque est au-dessus du seuil 'clair', le De-bruite sera appliqué progressivement.\n Entre les deux, les réglages sans De-bruite seront maintenus, sauf si vous agissez sur les curseurs "Zones grise dé-bruite luminance" or "Zones grise de-bruite chrominance".
@@ -2181,7 +2185,7 @@ TP_LOCALLAB_MERTHR;Difference
TP_LOCALLAB_MERTWE;Exclusion
TP_LOCALLAB_MERTWO;Soustrait
TP_LOCALLAB_METHOD_TOOLTIP;'Enhanced + chroma denoise' significantly increases processing times.\nBut reduce artifacts.
-TP_LOCALLAB_MLABEL;Récupère les données Min=%1 Max=%2 (Clip - décalage)
+TP_LOCALLAB_MLABEL;Réc. données Min=%1 Max=%2
TP_LOCALLAB_MLABEL_TOOLTIP;'Doit être' près de min=0 max=32768 (log mode) mais d'autres valeurs sont possibles.\nVous pouvez agir sur les données récupérées (CLIP) et décalage pour normaliser.\n\nRécupère les données image sans mélange.
TP_LOCALLAB_MODE_EXPERT;Avancé
TP_LOCALLAB_MODE_NORMAL;Standard
@@ -2204,12 +2208,12 @@ TP_LOCALLAB_NLRAD;Taille maximum du 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 ƒ)
+TP_LOCALLAB_NOISECHRODETAIL;Récup. détails Chroma(DCT)
TP_LOCALLAB_NOISECHROFINE;Chroma fin (Ond)
TP_LOCALLAB_NOISEDETAIL_TOOLTIP;Désactivé si curseur = 100
TP_LOCALLAB_NOISELEQUAL;Egalisateurs blanc-noir
TP_LOCALLAB_NOISELUMCOARSE;Luminance gros (ond)
-TP_LOCALLAB_NOISELUMDETAIL;Récupération Luminance fin(DCT ƒ)
+TP_LOCALLAB_NOISELUMDETAIL;Récup. Luminance détail(DCT)
TP_LOCALLAB_NOISELUMFINE;Luminance fin 1 (ond)
TP_LOCALLAB_NOISELUMFINETWO;Luminance fin 2 (ond)
TP_LOCALLAB_NOISELUMFINEZERO;Luminance fin 0 (ond)
@@ -2233,7 +2237,7 @@ TP_LOCALLAB_QUALCURV_METHOD;Types de Courbes
TP_LOCALLAB_QUAL_METHOD;Qualité globale
TP_LOCALLAB_QUACONSER;Conservatif
TP_LOCALLAB_QUAAGRES;Aggressif
-TP_LOCALLAB_QUANONEWAV;Débruitage par morceaux - luminance seulement
+TP_LOCALLAB_QUANONEWAV;Débruit. par morceaux-luminance seulement
TP_LOCALLAB_QUANONEALL;Rien
TP_LOCALLAB_RADIUS;Rayon
TP_LOCALLAB_RADIUS_TOOLTIP;Au-dessus de Rayon 30 Utilise 'Fast Fourier Transform'
@@ -2244,6 +2248,12 @@ TP_LOCALLAB_RECURS_TOOLTIP;Recalcule les références pour teinte, luma, chroma
TP_LOCALLAB_REFLABEL;Ref. (0..1) Chroma=%1 Luma=%2 teinte=%3
TP_LOCALLAB_REN_DIALOG_LAB;Entrer le nouveau nom de Spot
TP_LOCALLAB_REN_DIALOG_NAME;Renomme le Controle Spot
+TP_LOCALLAB_REPARW_TOOLTIP;Vous permet d'ajuster le niveau de l'image modifiée par Contraste local et Ondelettes par rapport à l'image originale.
+TP_LOCALLAB_REPARCOL_TOOLTIP;Vous permet d'ajuster le niveau de l'image modifiée par Couleurs et lumiéres par rapport à l'image originale.
+TP_LOCALLAB_REPARDEN_TOOLTIP;Vous permet d'ajuster le niveau de l'image modifiée par De-bruite par rapport à l'image originale.
+TP_LOCALLAB_REPARSH_TOOLTIP;Vous permet d'ajuster le niveau de l'image modifiée Ombres et Lumières et Egaliseur par rapport à l'image originale..
+TP_LOCALLAB_REPAREXP_TOOLTIP;Vous permet d'ajuster le niveau de l'image modifiée par Compression dynammique et Exposition par rapport à l'image originale..
+TP_LOCALLAB_REPARTM_TOOLTIP;Vous permet d'ajuster le niveau de l'image modifiée par Compression tonale par rapport à l'image originale..
TP_LOCALLAB_RESETSHOW;Annuler Montrer Toutes les Modifications
TP_LOCALLAB_RESID;Image Résiduelle
TP_LOCALLAB_RESIDBLUR;Flouter Image Résiduelle
@@ -2294,7 +2304,7 @@ TP_LOCALLAB_SH1;Ombres Lumières
TP_LOCALLAB_SH2;Egaliseur
TP_LOCALLAB_SHADEX;Ombres
TP_LOCALLAB_SHADEXCOMP;Compression ombres & profondeur tonale
-TP_LOCALLAB_SHADHIGH;Ombres/Lumières-Egaliseur
+TP_LOCALLAB_SHADHIGH;Ombres/Lumières&Egaliseur
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;Ombres
TP_LOCALLAB_SHADMASK_TOOLTIP;Relève les ombres du masque de la même manière que l'algorithme "ombres/lumières"
@@ -2331,7 +2341,7 @@ TP_LOCALLAB_SHOWMODIF;Montrer modifications sans masque
TP_LOCALLAB_SHOWMODIF2;Montrer modifications
TP_LOCALLAB_SHOWMODIFMASK;Montrer modifications avec masque
TP_LOCALLAB_SHOWNORMAL;Normalise luminance (non)
-TP_LOCALLAB_SHOWPLUS;Masque et modifications - Adoucir-flouter & De-bruite
+TP_LOCALLAB_SHOWPLUS;Masque et modifications
TP_LOCALLAB_SHOWPOISSON;Poisson (pde ƒ)
TP_LOCALLAB_SHOWR;Masque et modifications
TP_LOCALLAB_SHOWREF;Prévisualisation ΔE
@@ -2348,7 +2358,7 @@ TP_LOCALLAB_SIM;Simple
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_SOFT;Lumière douce/Orig. Retinex
TP_LOCALLAB_SOFTM;Lumière douce (soft light)
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
@@ -2388,10 +2398,10 @@ TP_LOCALLAB_THRES;Seuil structure
TP_LOCALLAB_THRESDELTAE;Seuil ΔE-Etendue
TP_LOCALLAB_THRESRETI;Seuil
TP_LOCALLAB_THRESWAV;Balance Seuil
-TP_LOCALLAB_TLABEL;TM Datas Min=%1 Max=%2 Mean=%3 Sigma=%4 (Seuil)
+TP_LOCALLAB_TLABEL;TM Min=%1 Max=%2 Mea=%3 Sig=%4
TP_LOCALLAB_TLABEL2;TM Effectif 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;Compression tonale - Texture
+TP_LOCALLAB_TM;Compression tonale
TP_LOCALLAB_TM_MASK;Utilise transmission map
TP_LOCALLAB_TONEMAPESTOP_TOOLTIP;Ce paramètre affecte la sensibilité aux bords.\n Plus grand il est, plus la luminosité change peut être considéré comme un bord.\n Si réglé à zéro 'compression tonale' va avoir un effet similaire à masque flou.
TP_LOCALLAB_TONEMAPGAM_TOOLTIP;Gamma déplace l'action de 'compression tonale' des ombres vers les lumières.
@@ -2407,7 +2417,7 @@ 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
TP_LOCALLAB_TRANSITVALUE;Transition valeur
-TP_LOCALLAB_TRANSITWEAK;Transition affaiblissement (linéaire-log)
+TP_LOCALLAB_TRANSITWEAK;Transition affaiblissement (lin-log)
TP_LOCALLAB_TRANSITWEAK_TOOLTIP;Ajuste l'affaiblissement de la transition : change le processus d'affaiblissement - 1 linéaire - 2 parabolique - 3 cubique - ^25.\nPeut être utilisé en conjonction avec de très faibles valeurs de transition pour traiter/réduire les défauts (CBDL, Ondelettes, Couleur et lumière)
TP_LOCALLAB_TRANSIT_TOOLTIP;Ajuste la progressions de la transition enttre les zones affectées ou non affectées, comme un pourcentage du "rayon"
TP_LOCALLAB_TRANSMISSIONGAIN;Transmission gain
@@ -2426,9 +2436,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 - 2
TP_LOCALLAB_LOG_TOOLNAME;Codage log - 0
-TP_LOCALLAB_MASKCOM_TOOLNAME;Masque Commun Couleur - 13
+TP_LOCALLAB_MASKCOM_TOOLNAME;Masque Commun Couleur - 12
TP_LOCALLAB_VIS_TOOLTIP;Click pour montrer/cacher le Spot sélectionné.\nCtrl+click pour montrer/cacher tous les Spot.
-TP_LOCALLAB_WAMASKCOL;Ψ 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à.
@@ -2465,18 +2475,18 @@ TP_LOCALLAB_WAVCOMPRE_TOOLTIP;Réalise un 'Tone-mapping' ou une réduction du co
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
TP_LOCALLAB_WAVCONTF_TOOLTIP;Similaire à Contrast By Detail Levels : en abscisse niveaux.
-TP_LOCALLAB_WAVDEN;de-bruite luminance par niveau (0 1 2 -3 et plus)
-TP_LOCALLAB_WAVE;Ψ Ondelette
+TP_LOCALLAB_WAVDEN;de-bruite lum. par niveau
+TP_LOCALLAB_WAVE;Ondelette
TP_LOCALLAB_WAVEDG;Contrast Local
TP_LOCALLAB_WAVEEDG_TOOLTIP;Améliore la netteté prenant en compte la notion de "ondelettes bords".\nNécessite au moins que les 4 premiers niveaux sont utilisables
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;Ψ Niveau contraste local
+TP_LOCALLAB_WAVHIGH;Ondelette haut
+TP_LOCALLAB_WAVLEV;Flou par niveau
+TP_LOCALLAB_WAVLOW;Ondelette bas
+TP_LOCALLAB_WAVMASK;Contr. local (par niveau)
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_WAVMED;Ondelette normal
TP_LOCALLAB_WEDIANHI;Median Haut
TP_LOCALLAB_WHITE_EV;Blanc Ev
TP_METADATA_EDIT;Appliquer les modifications
@@ -2604,7 +2614,7 @@ TP_RESIZE_APPLIESTO;S'applique à:
TP_RESIZE_CROPPEDAREA;La zone recadrée
TP_RESIZE_FITBOX;Boîte englobante
TP_RESIZE_FULLIMAGE;L'image entière
-TP_RESIZE_H;H:
+TP_RESIZE_H;H
TP_RESIZE_HEIGHT;Hauteur
TP_RESIZE_LABEL;Redimensionnement
TP_RESIZE_LANCZOS;Lanczos
@@ -2616,7 +2626,7 @@ TP_RESIZE_W;L:
TP_RESIZE_WIDTH;Largeur
TP_RETINEX_CONTEDIT_HSL;Égaliseur d'histogramme TSV
TP_RETINEX_CONTEDIT_LAB;Égaliseur d'histogramme L*a*b*
-TP_RETINEX_CONTEDIT_LH;Égaliseur de teinte
+TP_RETINEX_CONTEDIT_LH;Égaliseur teinte:
TP_RETINEX_CONTEDIT_MAP;Égaliseur
TP_RETINEX_CURVEEDITOR_CD;L=f(L)
TP_RETINEX_CURVEEDITOR_CD_TOOLTIP;Luminance en fonction de la luminance L=f(L)\nCorrige les données raw pour réduire halos et artéfacts.
@@ -2628,7 +2638,7 @@ TP_RETINEX_EQUAL;Égaliseur
TP_RETINEX_FREEGAMMA;Gamma manuel
TP_RETINEX_GAIN;Gain
TP_RETINEX_GAINOFFS;Gain et Décalage (brillance)
-TP_RETINEX_GAINTRANSMISSION;Gain sur Transmission
+TP_RETINEX_GAINTRANSMISSION;Gain Transmission:
TP_RETINEX_GAINTRANSMISSION_TOOLTIP;Amplifie ou réduit le canal transmission pour atteindre la luminance souhaitée.\nAbscisses: transmission ; min = 0, max = valeurs.\nOrdonnées: gain.
TP_RETINEX_GAMMA;Gamma
TP_RETINEX_GAMMA_FREE;Manuel
@@ -2681,7 +2691,7 @@ TP_RETINEX_TLABEL;CT Min=%1 Max=%2 Moyen=%3 Sigma=%4
TP_RETINEX_TLABEL2;CT Tm=%1 TM=%2
TP_RETINEX_TLABEL_TOOLTIP;Résultat du calcul de transmission.\nMin et Max sont utilisés par Variance.\nMoyen et Sigma.\nTm=Min TM=Niveau maximum de transmission.
TP_RETINEX_TRANF;Transmission
-TP_RETINEX_TRANSMISSION;Modulation du canal 'transmission'
+TP_RETINEX_TRANSMISSION;Modulation 'transmission'
TP_RETINEX_TRANSMISSION_TOOLTIP;Transmission en fonction de la transmission.\nAbscisses: transmission des valeurs négatives (min), moyennes, et positives (max).\nOrdonnées: amplification ou réduction.
TP_RETINEX_UNIFORM;Uniforme
TP_RETINEX_VARIANCE;Contraste
@@ -2738,6 +2748,10 @@ TP_SHARPENMICRO_MATRIX;Matrice 3×3 au lieu de 5×5
TP_SHARPENMICRO_UNIFORMITY;Uniformité
TP_SOFTLIGHT_LABEL;Lumière douce
TP_SOFTLIGHT_STRENGTH;Force
+TP_SPOT_COUNTLABEL;%1 point(s)
+TP_SPOT_ENTRYCHANGED;Modification d'un point
+TP_SPOT_HINT;Cliquez sur ce bouton pour pouvoir opérer sur la zone de prévisualisation.\n\nPour ajouter un spot, pressez Ctrl et le bouton gauche de la souris, tirez le cercle (la touche Ctrl peut être relâchée) vers la position source, puis relâchez le bouton de la souris.\n\nPour éditer un spot, placez le curseur au-dessus de la marque blanche situant une zone éditée, faisant apparaître la géométrie d'édition.\n\nPour déplacer le spot source ou destination, placez le curseur en son centre et tirez le.\n\nLe cercle intérieur (zone d'effet maximum) et le cercle "d'adoucicement" peuvent être redimmensionné en plaçant le curseur dessus (le cercle devient orange) et en le tirant (le cercle devient rouge).\n\nQuand les changements sont terminés, un clic droit en dehors de tout spot termine le mode d'édition, ou cliquez à nouveau sur ce bouton.
+TP_SPOT_LABEL;Retrait de taches
TP_TM_FATTAL_AMOUNT;Quantité
TP_TM_FATTAL_ANCHOR;Ancre
TP_TM_FATTAL_LABEL;Compression de Plage Dynamique
@@ -2809,7 +2823,7 @@ TP_WAVELET_COMPCONT;Contraste
TP_WAVELET_COMPGAMMA;Compression gamma
TP_WAVELET_COMPGAMMA_TOOLTIP;Ajuster le gamma de l'image résiduelle vous permet d'équiilibrer les données de l'histogramme.
TP_WAVELET_COMPTM;Compression tonale
-TP_WAVELET_CONTEDIT;Courbe de contraste 'Après'
+TP_WAVELET_CONTEDIT;Courbe contraste 'Après'
TP_WAVELET_CONTR;Gamut
TP_WAVELET_CONTRA;Contraste
TP_WAVELET_CONTRAST_MINUS;Contraste -
@@ -2897,7 +2911,7 @@ TP_WAVELET_NPTYPE;Pixels voisins
TP_WAVELET_NPTYPE_TOOLTIP;Cet algorithme utilise la proximité d'un pixel et huit de ses voisins. Si moins de différence, les bords sont renforcés.
TP_WAVELET_OPACITY;Opacité Bleu-Jaune
TP_WAVELET_OPACITYW;Courbe de contraste d/v-h
-TP_WAVELET_OPACITYWL;Contraste local final
+TP_WAVELET_OPACITYWL;Contraste local
TP_WAVELET_OPACITYWL_TOOLTIP;Modifie le contraste local final à la fin du traitement par ondelettes.\n\nLe côté gauche représente les plus faibles contrastes locaaux, progressant jusqu'aux plus grands contrastes locaux vers la droite.
TP_WAVELET_PASTEL;Chroma des Pastels
TP_WAVELET_PROC;Procédé
diff --git a/rtdata/languages/default b/rtdata/languages/default
index 605f0d95d..538c25b00 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -1289,6 +1289,13 @@ HISTORY_MSG_1040;Local - Spot - soft radius
HISTORY_MSG_1041;Local - Spot - Munsell
HISTORY_MSG_1042;Local - Log encoding - threshold
HISTORY_MSG_1043;Local - Exp - normalize
+HISTORY_MSG_1044;Local - Local contrast strength
+HISTORY_MSG_1045;Local - Color and Light strength
+HISTORY_MSG_1046;Local - Denoise strength
+HISTORY_MSG_1047;Local - SH and Tone Equalizer strength
+HISTORY_MSG_1048;Local - DR and Exposure strength
+HISTORY_MSG_1049;Local - TM strength
+HISTORY_MSG_1050;Local - Log encoding chroma
HISTORY_MSG_BLSHAPE;Blur by level
HISTORY_MSG_BLURCWAV;Blur chroma
HISTORY_MSG_BLURWAV;Blur luminance
@@ -1332,10 +1339,22 @@ HISTORY_MSG_HLBL;Color propagation - blur
HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries
HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D
HISTORY_MSG_ICM_OUTPUT_TYPE;Output - Type
-HISTORY_MSG_ICM_WORKING_GAMMA;Working - Gamma
-HISTORY_MSG_ICM_WORKING_SLOPE;Working - Slope
-HISTORY_MSG_ICM_WORKING_TRC_METHOD;Working - TRC method
+HISTORY_MSG_ICM_WORKING_GAMMA;TRC - Gamma
+HISTORY_MSG_ICM_WORKING_SLOPE;TRC - Slope
+HISTORY_MSG_ICM_WORKING_TRC_METHOD;TRC method
+HISTORY_MSG_ICM_WORKING_ILLUM_METHOD;Illuminant method
+HISTORY_MSG_ICM_WORKING_PRIM_METHOD;Primaries method
+HISTORY_MSG_ICM_REDX;Primaries Red X
+HISTORY_MSG_ICM_REDY;Primaries Red Y
+HISTORY_MSG_ICM_GREX;Primaries Green X
+HISTORY_MSG_ICM_GREY;Primaries Green Y
+HISTORY_MSG_ICM_BLUX;Primaries Blue X
+HISTORY_MSG_ICM_BLUY;Primaries Blue Y
+HISTORY_MSG_ICL_LABGRIDCIEXY;Cie xy
+HISTORY_MSG_ICM_AINTENT;Abstract profile intent
HISTORY_MSG_ILLUM;Illuminant
+HISTORY_MSG_ICM_FBW;Black and White
+HISTORY_MSG_ICM_PRESER;Preserve neutral
HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount
HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness
HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast
@@ -1369,6 +1388,8 @@ HISTORY_MSG_RAWCACORR_AUTOIT;Raw CA Correction - Iterations
HISTORY_MSG_RAWCACORR_COLORSHIFT;Raw CA Correction - Avoid color shift
HISTORY_MSG_RAW_BORDER;Raw border
HISTORY_MSG_RESIZE_ALLOWUPSCALING;Resize - Allow upscaling
+HISTORY_MSG_RESIZE_LONGEDGE;Resize - Long Edge
+HISTORY_MSG_RESIZE_SHORTEDGE;Resize - Short Edge
HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius
HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold
HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace
@@ -1378,6 +1399,8 @@ HISTORY_MSG_SIGMAFIN;Final contrast Attenuation response
HISTORY_MSG_SIGMATON;Toning Attenuation response
HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light
HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength
+HISTORY_MSG_SPOT;Spot removal
+HISTORY_MSG_SPOT_ENTRY;Spot removal - Point modif.
HISTORY_MSG_TEMPOUT;CAM02 automatic temperature
HISTORY_MSG_THRESWAV;Balance threshold
HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor
@@ -1462,7 +1485,8 @@ ICCPROFCREATOR_PROF_V2;ICC v2
ICCPROFCREATOR_PROF_V4;ICC v4
ICCPROFCREATOR_SAVEDIALOG_TITLE;Save ICC profile as...
ICCPROFCREATOR_SLOPE;Slope
-ICCPROFCREATOR_TRC_PRESET;Tone response curve:
+ICCPROFCREATOR_TRC_PRESET;Tone response curve
+INSPECTOR_WINDOW_TITLE;Inspector
IPTCPANEL_CATEGORY;Category
IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider.
IPTCPANEL_CITY;City
@@ -1680,6 +1704,7 @@ PARTIALPASTE_SHARPENEDGE;Edges
PARTIALPASTE_SHARPENING;Sharpening (USM/RL)
PARTIALPASTE_SHARPENMICRO;Microcontrast
PARTIALPASTE_SOFTLIGHT;Soft light
+PARTIALPASTE_SPOT;Spot removal
PARTIALPASTE_TM_FATTAL;Dynamic range compression
PARTIALPASTE_VIBRANCE;Vibrance
PARTIALPASTE_VIGNETTING;Vignetting correction
@@ -1759,6 +1784,12 @@ PREFERENCES_EXTERNALEDITOR;External Editor
PREFERENCES_EXTERNALEDITOR_CHANGE;Change Application
PREFERENCES_EXTERNALEDITOR_COLUMN_NAME;Name
PREFERENCES_EXTERNALEDITOR_COLUMN_COMMAND;Command
+PREFERENCES_EXTEDITOR_DIR;Output directory
+PREFERENCES_EXTEDITOR_DIR_TEMP;OS temp dir
+PREFERENCES_EXTEDITOR_DIR_CURRENT;Same as input image
+PREFERENCES_EXTEDITOR_DIR_CUSTOM;Custom
+PREFERENCES_EXTEDITOR_FLOAT32;32-bit float TIFF output
+PREFERENCES_EXTEDITOR_BYPASS_OUTPUT_PROFILE;Bypass output profile
PREFERENCES_FBROWSEROPTS;File Browser / Thumbnail Options
PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Compact toolbars in File Browser
PREFERENCES_FLATFIELDFOUND;Found
@@ -2144,7 +2175,7 @@ TP_COLORTONING_AUTOSAT;Automatic
TP_COLORTONING_BALANCE;Balance
TP_COLORTONING_BY;o C/L
TP_COLORTONING_CHROMAC;Opacity
-TP_COLORTONING_COLOR;Color
+TP_COLORTONING_COLOR;Color:
TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP;Chroma opacity as a function of luminance oC=f(L)
TP_COLORTONING_HIGHLIGHT;Highlights
TP_COLORTONING_HUE;Hue
@@ -2179,7 +2210,7 @@ TP_COLORTONING_METHOD_TOOLTIP;"L*a*b* blending", "RGB sliders" and "RGB curves"
TP_COLORTONING_MIDTONES;Midtones
TP_COLORTONING_NEUTRAL;Reset sliders
TP_COLORTONING_NEUTRAL_TIP;Reset all values (Shadows, Midtones, Highlights) to default.
-TP_COLORTONING_OPACITY;Opacity
+TP_COLORTONING_OPACITY;Opacity:
TP_COLORTONING_RGBCURVES;RGB - Curves
TP_COLORTONING_RGBSLIDERS;RGB - Sliders
TP_COLORTONING_SA;Saturation Protection
@@ -2393,10 +2424,14 @@ TP_ICM_APPLYHUESATMAP;Base table
TP_ICM_APPLYHUESATMAP_TOOLTIP;Employ the embedded DCP base table (HueSatMap). The setting is only available if the selected DCP has one.
TP_ICM_APPLYLOOKTABLE;Look table
TP_ICM_APPLYLOOKTABLE_TOOLTIP;Employ the embedded DCP look table. The setting is only available if the selected DCP has one.
+TP_ICM_BLUFRAME;Blue Primaries
TP_ICM_BPC;Black Point Compensation
TP_ICM_DCPILLUMINANT;Illuminant
TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolated
TP_ICM_DCPILLUMINANT_TOOLTIP;Select which embedded DCP illuminant to employ. Default is "interpolated" which is a mix between the two based on white balance. The setting is only available if a dual-illuminant DCP with interpolation support is selected.
+TP_ICM_FBW;Black-and-White
+TP_ICM_GREFRAME;Green Primaries
+TP_ICM_ILLUMPRIM_TOOLTIP;Choose the illuminant closest to the shooting conditions.\nChanges can only be made when the ‘Destination primaries’ selection is set to ‘Custom (sliders)’.
TP_ICM_INPUTCAMERA;Camera standard
TP_ICM_INPUTCAMERAICC;Auto-matched camera profile
TP_ICM_INPUTCAMERAICC_TOOLTIP;Use RawTherapee's camera-specific DCP or ICC input color profiles. These profiles are more precise than simpler matrix ones. They are not available for all cameras. These profiles are stored in the /iccprofiles/input and /dcpprofiles folders and are automatically retrieved based on a file name matching to the exact model name of the camera.
@@ -2409,22 +2444,67 @@ TP_ICM_INPUTEMBEDDED_TOOLTIP;Use color profile embedded in non-raw files.
TP_ICM_INPUTNONE;No profile
TP_ICM_INPUTNONE_TOOLTIP;Use no input color profile at all.\nUse only in special cases.
TP_ICM_INPUTPROFILE;Input Profile
-TP_ICM_LABEL;Color Management
+TP_ICM_LABEL;Color Management
+TP_ICM_LABGRID_CIEXY;R(x)=%1 R(y)=%2\nG(x)=%3 G(y)=%4\nB(x)=%5 B(y)=%6
+TP_ICM_NEUTRAL;Reset
TP_ICM_NOICM;No ICM: sRGB Output
TP_ICM_OUTPUTPROFILE;Output Profile
+TP_ICM_OUTPUTPROFILE_TOOLTIP;By default all RTv4 or RTv2 profiles are with TRC - sRGB: g=2.4 s=12.92\n\nWith 'ICC Profile Creator' you can generate v4 or v2 profiles with the following choices;\n-Primaries: Aces AP0, Aces AP1, AdobeRGB, Prophoto, Rec2020, sRGB, Widegamut, BestRGB, BetaRGB, BruceRGB, Custom\n-TRC: BT709, sRGB, linear, standard g=2.2, standard g=1.8, Custom\n-Illuminant: D41, D50, D55, D60, D65, D80, stdA 2856K
+TP_ICM_PRIMRED_TOOLTIP;Primaries Red:\nsRGB x=0.64 y=0.33\nAdobe x=0.64 y=0.33\nWidegamut x=0.735 y=0.265\nRec2020 x=0.708 y=0.292\nACES P1 x=0.713 y= 0.293\nACES P0 x=0.7347 y=0.2653\nProphoto x=0.7347 y=0.2653\nBruceRGB x=0.64 y=0.33\nBeta RGB x=0.688 y=0.3112\nBestRGB x=0.7347 y=0.2653
+TP_ICM_PRIMGRE_TOOLTIP;Primaries Green:\nsRGB x=0.3 y=0.6\nAdobe x=0.21 y=0.71\nWidegamut x=0.115 y=0.826\nRec2020 x=0.17 y=0.797\nACES P1 x=0.165 y= 0.83\nACES P0 x=0.0 y=1.0\nProphoto x=0.1596 y=0.8404\nBruceRGB x=0.28 y=0.65\nBeta RGB x=0.1986 y=0.7551\nBest RGB x=0.2150 0.7750
+TP_ICM_PRIMBLU_TOOLTIP;Primaries Blue:\nsRGB x=0.15 y=0.06\nAdobe x=0.15 y=0.06\nWidegamut x=0.157 y=0.018\nRec2020 x=0.131 y=0.046\nACES P1 x=0.128 y= 0.044\nACES P0 x=0.0001 y=-0.077\nProphoto x=0.0366 y=0.0001\nBruceRGB x=0.15 y=0.06\nBeta RGB x=0.1265 y=0.0352\nBestRGB x=0.131 y=0.046
TP_ICM_PROFILEINTENT;Rendering Intent
+TP_ICM_REDFRAME;Custom Primaries
TP_ICM_SAVEREFERENCE;Save Reference Image
TP_ICM_SAVEREFERENCE_APPLYWB;Apply white balance
TP_ICM_SAVEREFERENCE_APPLYWB_TOOLTIP;Generally, apply the white balance when saving images to create ICC profiles, and do not apply the white balance to create DCP profiles.
TP_ICM_SAVEREFERENCE_TOOLTIP;Save the linear TIFF image before the input profile is applied. The result can be used for calibration purposes and generation of a camera profile.
TP_ICM_TONECURVE;Tone curve
TP_ICM_TONECURVE_TOOLTIP;Employ the embedded DCP tone curve. The setting is only available if the selected DCP has a tone curve.
+TP_ICM_TRCFRAME;Abstract Profile
+TP_ICM_TRCFRAME_TOOLTIP;Also known as ‘synthetic’ or ‘virtual’ profiles, which are applied at the end of the processing pipeline (prior to ciecam) allowing you to create custom image effects.\nYou can make changes to the:\n ‘Tone response curve’, which modifies the tones of the image.\n ‘Illuminant’ : which allows you to change the profile primaries to adapt them to the shooting conditions.\n ‘Destination primaries’: which allows you to change the destination primaries with two main uses - channel mixer and calibration.\nNote: Abstract profiles take into account the built-in Working profiles without modifying them. They do not work with custom Working profiles.
+TP_ICM_WORKING_CIEDIAG;CIE xy diagram
TP_ICM_WORKINGPROFILE;Working Profile
+TP_ICM_WORKING_PRESER;Preserves Pastel tones
TP_ICM_WORKING_TRC;Tone response curve:
+TP_ICM_WORKING_TRC_BT709;BT709 g=2.22 s=4.5
+TP_ICM_WORKING_TRC_SRGB;sRGB g=2.4 s=12.92
+TP_ICM_WORKING_TRC_22;Adobe g=2.2
+TP_ICM_WORKING_TRC_18;Prophoto g=1.8
+TP_ICM_WORKING_TRC_LIN;Linear g=1
TP_ICM_WORKING_TRC_CUSTOM;Custom
TP_ICM_WORKING_TRC_GAMMA;Gamma
TP_ICM_WORKING_TRC_NONE;None
TP_ICM_WORKING_TRC_SLOPE;Slope
+TP_ICM_TRC_TOOLTIP;Allows you to change the default sRGB ‘Tone response curve’ in RT (g=2.4 s=12.92).\nThis TRC modifies the tones of the image. The RGB and Lab values, histogram and output (screen, TIF, JPG) are changed:\n-Gamma acts mainly on light tones -Slope acts mainly on dark tones.\nYou can choose any pair of 'gamma and slope' (values >1) and the algorithm will ensure that there is continuity between the linear and parabolic parts of the curve.\nA selection other than 'none' activates the 'Illuminant' and 'Destination primaries' menus.
+TP_ICM_WORKING_ILLU;Illuminant
+TP_ICM_WORKING_ILLU_NONE;Default
+TP_ICM_WORKING_ILLU_D41;D41
+TP_ICM_WORKING_ILLU_D50;D50
+TP_ICM_WORKING_ILLU_D55;D55
+TP_ICM_WORKING_ILLU_D60;D60
+TP_ICM_WORKING_ILLU_D65;D65
+TP_ICM_WORKING_ILLU_D80;D80
+TP_ICM_WORKING_ILLU_D120;D120
+TP_ICM_WORKING_ILLU_STDA;stdA 2875K
+TP_ICM_WORKING_ILLU_2000;Tungsten 2000K
+TP_ICM_WORKING_ILLU_1500;Tungsten 1500K
+TP_ICM_WORKING_PRIM;Destination primaries
+TP_ICM_PRIMILLUM_TOOLTIP;You can change an image from its original mode (‘working profile’) to a different mode (‘destination primaries’). When you choose a different color mode for an image, you permanently change the color values in the image.\n\nChanging the ‘primaries’ is quite complex and difficult to use. It requires a lot of experimenting.\n It is capable of making exotic color adjustments as Channel Mixer primaries.\n Allows you to modify the camera calibration with Custom (sliders).
+TP_ICM_WORKING_PRIM_NONE;Default
+TP_ICM_WORKING_PRIM_SRGB;sRGB
+TP_ICM_WORKING_PRIM_ADOB;Adobe RGB
+TP_ICM_WORKING_PRIM_PROP;ProPhoto
+TP_ICM_WORKING_PRIM_REC;Rec2020
+TP_ICM_WORKING_PRIM_ACE;ACESp1
+TP_ICM_WORKING_PRIM_WID;WideGamut
+TP_ICM_WORKING_PRIM_AC0;ACESp0
+TP_ICM_WORKING_PRIM_BRU;BruceRGB
+TP_ICM_WORKING_PRIM_BET;Beta RGB
+TP_ICM_WORKING_PRIM_BST;BestRGB
+TP_ICM_WORKING_PRIM_CUS;Custom (sliders)
+TP_ICM_WORKING_PRIM_CUSGR;Custom (CIE xy Diagram)
+TP_ICM_WORKING_PRIMFRAME_TOOLTIP;When ‘Custom CIE xy diagram’ is selected in ‘Destination- primaries’’ combobox, you can modify the values of the 3 primaries directly on the graph.\nNote that in this case, the white point position on the graph will not be updated.
TP_ICM_WORKING_TRC_TOOLTIP;Only for built-in profiles.
TP_IMPULSEDENOISE_LABEL;Impulse Noise Reduction
TP_IMPULSEDENOISE_THRESH;Threshold
@@ -2487,7 +2567,7 @@ 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 Color
TP_LOCALLAB_ALL;All rubrics
TP_LOCALLAB_AMOUNT;Amount
TP_LOCALLAB_ARTIF;Shape detection
@@ -2505,8 +2585,8 @@ TP_LOCALLAB_BILATERAL;Bilateral filter
TP_LOCALLAB_BLACK_EV;Black Ev
TP_LOCALLAB_BLCO;Chrominance only
TP_LOCALLAB_BLENDMASKCOL;Blend
-TP_LOCALLAB_BLENDMASKMASK;Add/subtract luminance mask
-TP_LOCALLAB_BLENDMASKMASKAB;Add/subtract chrominance mask
+TP_LOCALLAB_BLENDMASKMASK;Add/subtract luma mask
+TP_LOCALLAB_BLENDMASKMASKAB;Add/subtract chroma mask
TP_LOCALLAB_BLENDMASKMASK_TOOLTIP;If this slider = 0 no action.\nAdd or subtract the mask from the original image
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_BLGUID;Guided Filter
@@ -2514,12 +2594,12 @@ TP_LOCALLAB_BLINV;Inverse
TP_LOCALLAB_BLLC;Luminance & Chrominance
TP_LOCALLAB_BLLO;Luminance only
TP_LOCALLAB_BLMED;Median
-TP_LOCALLAB_BLMETHOD_TOOLTIP;Normal - direct blur and noise with all settings.\nInverse blur and noise with all settings. Be careful some results may be curious
+TP_LOCALLAB_BLMETHOD_TOOLTIP;Normal: direct blur and noise with all settings.\nInverse: blur and noise with all settings. Warning, some settings may give curious results.
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 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_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
@@ -2538,7 +2618,7 @@ TP_LOCALLAB_BUTTON_DEL;Delete
TP_LOCALLAB_BUTTON_DUPL;Duplicate
TP_LOCALLAB_BUTTON_REN;Rename
TP_LOCALLAB_BUTTON_VIS;Show/Hide
-TP_LOCALLAB_CATAD;Chromatic adaptation - Cat16
+TP_LOCALLAB_CATAD;Chromatic adaptation/Cat16
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.
@@ -2546,7 +2626,7 @@ TP_LOCALLAB_CBDL_THRES_TOOLTIP;Prevents the sharpening of noise
TP_LOCALLAB_CBDL_TOOLNAME;Contrast by Detail Levels
TP_LOCALLAB_CENTER_X;Center X
TP_LOCALLAB_CENTER_Y;Center Y
-TP_LOCALLAB_CH;Curves CL - LC
+TP_LOCALLAB_CH;CL - LC
TP_LOCALLAB_CHROMA;Chrominance
TP_LOCALLAB_CHROMABLU;Chroma levels
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.
@@ -2555,49 +2635,50 @@ TP_LOCALLAB_CHROMACB_TOOLTIP;Increases or reduces the effect depending on the lu
TP_LOCALLAB_CHROMALEV;Chroma levels
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_CHROML;Chroma (C)
TP_LOCALLAB_CHRRT;Chroma
TP_LOCALLAB_CIEC;Use Ciecam environment parameters
TP_LOCALLAB_CIECAMLOG_TOOLTIP;This module is based on the CIECAM 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 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 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_CIRCRAD_TOOLTIP;Contains the references of the RT-spot, useful for shape detection (hue, luma, chroma, Sobel).\nLow values may be useful for processing foliage.\nHigh values may be useful for processing skin.
TP_LOCALLAB_CLARICRES;Merge chroma
-TP_LOCALLAB_CLARIFRA;Clarity & Sharp mask - Blend & Soften Images
+TP_LOCALLAB_CLARIFRA;Clarity & Sharp mask/Blend & Soften Images
TP_LOCALLAB_CLARILRES;Merge luma
TP_LOCALLAB_CLARISOFT;Soft radius
-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_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;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;ΔE preview color - intensity
-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_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_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_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
TP_LOCALLAB_COL_NAME;Name
TP_LOCALLAB_COL_VIS;Status
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_COMPFRAME_TOOLTIP;Allows you to create special effects. You can reduce artifacts with 'Clarity and Sharp mask - Blend and 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_COMPLEX_TOOLTIP; Allow user to select Local adjustments complexity.
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_COMPRESS_TOOLTIP;If necessary, use the module 'Clarity and Sharp mask and Blend and 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_CONTRAST;Contrast
-TP_LOCALLAB_CONTRASTCURVMASK1_TOOLTIP;Allows you to freely modify the contrast of the mask (gamma and slope), instead of using a continuous and progressive curve. However it can create artifacts that have to be dealt with using the “Smooth radius” or “Laplacian threshold sliders”.
+TP_LOCALLAB_CONTRASTCURVMASK1_TOOLTIP;Allows you to freely modify the contrast of the mask (gamma and slope), instead of using a continuous and progressive curve. However it can create artifacts that have to be dealt with using the ‘Smooth radius’ or ‘Laplacian threshold sliders’.
TP_LOCALLAB_CONTRASTCURVMASK_TOOLTIP;Allows you to freely change the contrast of the mask.\n Has a similar function to the Gamma and Slope sliders.\n It allows you to target certain parts of the image (usually the lightest parts of the mask by using the curve to exclude the darker parts).May create artifacts.
TP_LOCALLAB_CONTRESID;Contrast
TP_LOCALLAB_CONTTHMASK_TOOLTIP;Allows you to determine which parts of the image will be impacted based on the texture.
TP_LOCALLAB_CONTTHR;Contrast Threshold
TP_LOCALLAB_CONTWFRA;Local contrast
-TP_LOCALLAB_CSTHRESHOLD;Ψ Wavelet levels
-TP_LOCALLAB_CSTHRESHOLDBLUR;Ψ Wavelet level selection
+TP_LOCALLAB_CSTHRESHOLD;Wavelet levels
+TP_LOCALLAB_CSTHRESHOLDBLUR;Wavelet level selection
TP_LOCALLAB_CURV;Lightness - Contrast - Chrominance "Super"
TP_LOCALLAB_CURVCURR;Normal
-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_CURVEEDITORM_CC_TOOLTIP;If the 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_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_CURVEEDITOR_LL_TOOLTIP;To activate the curves, set the ‘Curve type’ combobox to ‘Normal’
TP_LOCALLAB_CURVEEDITOR_TONES_LABEL;Tone curve
@@ -2624,16 +2705,16 @@ TP_LOCALLAB_DENOIEQUAL_TOOLTIP;Allows you to carry out more or less noise reduct
TP_LOCALLAB_DENOI1_EXP;Denoise based on luminance mask
TP_LOCALLAB_DENOI2_EXP;Recovery based on luminance mask
TP_LOCALLAB_DENOILUMDETAIL_TOOLTIP;Allows you to recover luminance detail by progressively applying a Fourier transform (DCT).
-TP_LOCALLAB_DENOIQUA_TOOLTIP;Conservative mode preserves low frequency detail. Aggressive mode removes low frequency detail.\nConservative and Aggressive use wavelets and DCT, can be used in conjunction with "Non-local Means - Luminance".
-TP_LOCALLAB_DENOIS;Ψ Denoise
+TP_LOCALLAB_DENOIQUA_TOOLTIP;Conservative mode preserves low frequency detail. Aggressive mode removes low frequency detail.\nConservative and Aggressive modes use wavelets and DCT and can be used in conjunction with ‘Non-local Means – Luminance’.
+TP_LOCALLAB_DENOIS;Denoise
TP_LOCALLAB_DENOITHR_TOOLTIP;Adjusts edge detection to help reduce noise in uniform, low-contrast areas.
TP_LOCALLAB_DENOI_EXP;Denoise
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).
TP_LOCALLAB_DEPTH;Depth
TP_LOCALLAB_DETAIL;Local contrast
-TP_LOCALLAB_DETAILFRA;Edge detection
+TP_LOCALLAB_DETAILFRA;Edge detection - DCT
TP_LOCALLAB_DETAILSH;Details
-TP_LOCALLAB_DETAILTHR;Luminance & chroma detail threshold (DCT ƒ)
+TP_LOCALLAB_DETAILTHR;Luma-chro detail threshold
TP_LOCALLAB_DIVGR;Gamma
TP_LOCALLAB_DUPLSPOTNAME;Copy
TP_LOCALLAB_EDGFRA;Edge sharpness
@@ -2642,7 +2723,7 @@ 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
-TP_LOCALLAB_ENARETIMASKTMAP_TOOLTIP;If enabled Mask uses Restored Datas after Transmission Map instead of Original datas
+TP_LOCALLAB_ENARETIMASKTMAP_TOOLTIP;If enabled the Mask uses Restored Data after Transmission Map instead of Original data.
TP_LOCALLAB_ENH;Enhanced
TP_LOCALLAB_ENHDEN;Enhanced + chroma denoise
TP_LOCALLAB_EPSBL;Detail
@@ -2667,9 +2748,9 @@ TP_LOCALLAB_EXPCHROMA_TOOLTIP;Use in association with ‘Exposure compensation f
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 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_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_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 with defects.\nUse 'Clarity and Sharp mask and Blend and Soften Images' if necessary by adjusting 'Soft radius' to reduce artifacts.
TP_LOCALLAB_EXPCURV;Curves
TP_LOCALLAB_EXPGRAD;Graduated Filter
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.
@@ -2677,13 +2758,13 @@ 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_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;Applies a median filter before the Laplace transform to prevent artifacts (noise).\nYou can also use the "Denoise" tool.
+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 ‘Transition decay’ and ‘Scope’ values to simulate smaller RT-spots.
+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;Dynamic Range & Exposure
@@ -2697,19 +2778,19 @@ TP_LOCALLAB_FATLEVEL;Sigma
TP_LOCALLAB_FATRES;Amount Residual Image
TP_LOCALLAB_FATSHFRA;Dynamic Range Compression Mask ƒ
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_FEATVALUE;Feather gradient (Grad. Filters)
TP_LOCALLAB_FFTCOL_MASK;FFTW ƒ
TP_LOCALLAB_FFTMASK_TOOLTIP;Use a Fourier transform for better quality (increased processing time and memory requirements)
TP_LOCALLAB_FFTW;ƒ - Use Fast Fourier Transform
TP_LOCALLAB_FFTW2;ƒ - Use Fast Fourier Transform (TIF, JPG,..)
TP_LOCALLAB_FFTWBLUR;ƒ - Always Use Fast Fourier Transform
-TP_LOCALLAB_FULLIMAGE;Dark-Ev & white-Ev for the whole image
+TP_LOCALLAB_FULLIMAGE;Black-Ev and White-Ev for whole image
TP_LOCALLAB_FULLIMAGELOG_TOOLTIP;Calculates the Ev levels for the whole image.
TP_LOCALLAB_GAM;Gamma
TP_LOCALLAB_GAMFRA;Tone response curve (TRC)
TP_LOCALLAB_GAMM;Gamma
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_GAMMASK_TOOLTIP;Adjusting Gamma and Slope can provide 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
@@ -2718,18 +2799,17 @@ TP_LOCALLAB_GRADGEN_TOOLTIP;Adjusts luminance gradient strength
TP_LOCALLAB_GRADLOGFRA;Graduated Filter Luminance
TP_LOCALLAB_GRADSTR;Gradient strength
TP_LOCALLAB_GRADSTRAB_TOOLTIP;Adjusts chroma gradient strength
-TP_LOCALLAB_GRADSTRCHRO;Chrominance gradient strength
+TP_LOCALLAB_GRADSTRCHRO;Chroma 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_GRADSTRLUM;Luma gradient strength
TP_LOCALLAB_GRADSTR_TOOLTIP;Filter strength in stops
TP_LOCALLAB_GRAINFRA;Film Grain 1:1
TP_LOCALLAB_GRAINFRA2;Coarseness
-
TP_LOCALLAB_GRAIN_TOOLTIP;Adds film-like grain to the image
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_GRIDFRAME_TOOLTIP;You can use this tool as a brush. Use a small spot and adapt the ‘Transition value’ and ‘Transition decay’\nOnly 'Normal' mode and possibly Hue, Saturation, Color, Luminosity are concerned by Merge background (ΔE)
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_GRIDONE;Color Toning
TP_LOCALLAB_GRIDTWO;Direct
@@ -2741,13 +2821,13 @@ 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
-TP_LOCALLAB_HLH;Curves H
+TP_LOCALLAB_HLH;H
TP_LOCALLAB_IND;Independent (mouse)
TP_LOCALLAB_INDSL;Independent (mouse + sliders)
TP_LOCALLAB_INVBL;Inverse
-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_INVBL_TOOLTIP;Alternative to ‘Inverse’ mode: use two spots\nFirst Spot:\n Full Image\n\nSecond spot : Excluding spot
TP_LOCALLAB_INVERS;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_INVERS_TOOLTIP;Fewer possibilities if selected (Inverse).\n\nAlternative: use two spots\nFirst Spot:\n Full Image\n \nSecond spot: Excluding spot
TP_LOCALLAB_INVMASK;Inverse algorithm
TP_LOCALLAB_ISOGR;Distribution (ISO)
TP_LOCALLAB_LABBLURM;Blur Mask
@@ -2763,11 +2843,11 @@ TP_LOCALLAB_LAPMASKCOL;Laplacian threshold
TP_LOCALLAB_LAPRAD1_TOOLTIP;Increases the contrast of the mask by increasing the luminance values of the lighter areas. Can be used in conjunction with the L(L) and LC(H) curves.
TP_LOCALLAB_LAPRAD2_TOOLTIP;Smooth radius uses a guided filter to decrease artifacts and smooth out the transition
TP_LOCALLAB_LAPRAD_TOOLTIP;Smooth radius uses a guided filter to decrease artifacts and smooth out the transition
-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_LAP_MASK_TOOLTIP;Solves PDEs for all Laplacian masks.\nIf enabled the Laplacian threshold mask reduces artifacts and smooths the result.\nIf disabled the response is linear.
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
TP_LOCALLAB_LEVELBLUR;Maximum blur levels
-TP_LOCALLAB_LEVELWAV;Ψ Wavelet 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
@@ -2780,20 +2860,20 @@ TP_LOCALLAB_LMASK_LEVEL_TOOLTIP;Allows you to decrease or increase the effect on
TP_LOCALLAB_LMASK_LL_TOOLTIP;Allows you to freely change the contrast of the mask.\n Has a similar function to the Gamma and Slope sliders.\n It allows you to target certain parts of the image (usually the lightest parts of the mask by using the curve to exclude the darker parts). May create artifacts.
TP_LOCALLAB_LOCCONT;Unsharp Mask
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 level - TM - Directional contrast
-TP_LOCALLAB_LOC_CONTRASTPYRLAB; Graduated Filter - Edge Sharpness - Blur
+TP_LOCALLAB_LOC_CONTRASTPYR;Pyramid 1:
+TP_LOCALLAB_LOC_CONTRASTPYR2;Pyramid 2:
+TP_LOCALLAB_LOC_CONTRASTPYR2LAB; Contrast by level/TM/Directional contrast
+TP_LOCALLAB_LOC_CONTRASTPYRLAB; Graduated Filter/Edge Sharpness/Blur
TP_LOCALLAB_LOC_RESIDPYR;Residual image (Main)
TP_LOCALLAB_LOG;Log Encoding
TP_LOCALLAB_LOG1FRA;Image Adjustments
TP_LOCALLAB_LOG2FRA;Viewing Conditions
TP_LOCALLAB_LOGAUTO;Automatic
-TP_LOCALLAB_LOGAUTOGRAY_TOOLTIP;Automatically calculates the 'mean luminance' for the scene conditons when the ‘Automatic’ button in Relative Exposure Levels is pressed.
-TP_LOCALLAB_LOGAUTO_TOOLTIP;Pressing this button will calculate the 'dynamic range' and 'mean luminance' for the scene conditions if the "Auto mean luminance (Yb%)” is checked).\nAlso calculates the absolute luminance at the time of shooting.\nPress the button again to adjust the automatically calculated values.
+TP_LOCALLAB_LOGAUTOGRAY_TOOLTIP;Automatically calculates the 'Mean luminance' for the scene conditions when the ‘Automatic’ button in Relative Exposure Levels is pressed.
+TP_LOCALLAB_LOGAUTO_TOOLTIP;Pressing this button will calculate the dynamic range and 'Mean luminance' for the scene conditions if the "Auto mean luminance (Yb%)” is checked).\nAlso calculates the absolute luminance at the time of shooting.\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_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_LOGBLACKWHEV_TOOLTIP;Estimated values of dynamic range i.e. Black Ev and White Ev
+TP_LOCALLAB_LOGCATAD_TOOLTIP;The chromatic adaptation allows us to interpret a color according to its spatio-temporal environment.\nUseful when the white balance deviates significantly from the D50 reference.\nAdapts colors to the illuminant of the output device.
TP_LOCALLAB_LOGCOLORFL;Colorfulness (M)
TP_LOCALLAB_LOGCOLORF_TOOLTIP;Perceived amount of hue in relation to gray.\nIndicator that a stimulus appears more or less colored.
TP_LOCALLAB_LOGCONQL;Contrast (Q)
@@ -2807,34 +2887,34 @@ TP_LOCALLAB_LOGENCOD_TOOLTIP;Tone Mapping with Logarithmic encoding (ACES).\nUse
TP_LOCALLAB_LOGEXP;All tools
TP_LOCALLAB_LOGFRA;Scene Conditions
TP_LOCALLAB_LOGFRAME_TOOLTIP;Allows you to calculate and adjust the Ev levels and the 'Mean luminance Yb%' (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 shooting.
-TP_LOCALLAB_LOGIMAGE_TOOLTIP;Takes into account corresponding Ciecam variables (mainly Contrast 'J' and Saturation 's', and also 'advanced' Contrast 'Q' , Brightness 'Q', Lightness (J), Colorfulness (M)).
+TP_LOCALLAB_LOGIMAGE_TOOLTIP;Takes into account corresponding Ciecam variables (mainly Contrast 'J' and Saturation 's', and also Contrast (Q) , Brightness (Q), Lightness (J), Colorfulness (M) in Advanced mode).
TP_LOCALLAB_LOGLIGHTL;Lightness (J)
TP_LOCALLAB_LOGLIGHTL_TOOLTIP;Close to lightness (L*a*b*), takes into account the increase in perceived coloration.
TP_LOCALLAB_LOGLIGHTQ;Brightness (Q)
TP_LOCALLAB_LOGLIGHTQ_TOOLTIP;Perceived amount of light emanating from a stimulus.\nIndicator that a stimulus appears to be more or less bright, clear.
TP_LOCALLAB_LOGLIN;Logarithm mode
TP_LOCALLAB_LOGPFRA;Relative Exposure Levels
-TP_LOCALLAB_LOGREPART;Strength
+TP_LOCALLAB_LOGREPART;Overall strength
TP_LOCALLAB_LOGREPART_TOOLTIP;Allows you to adjust the relative strength of the log-encoded image with respect to the original image.\nDoes not affect the Ciecam component.
TP_LOCALLAB_LOGSATURL_TOOLTIP;Saturation (s) in CIECAM16 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_LOGSURSOUR_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.
+TP_LOCALLAB_LOGSURSOUR_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 brighter.\n\nDark: Dark environment. The image will become more bright.
TP_LOCALLAB_LOGTARGGREY_TOOLTIP;You can adjust this value to suit.
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_LOG_TOOLNAME;Log Encoding
-TP_LOCALLAB_LUM;Curves LL - CC
+TP_LOCALLAB_LUM;LL - CC
TP_LOCALLAB_LUMADARKEST;Darkest
-TP_LOCALLAB_LUMASK;Background color for luminance mask
+TP_LOCALLAB_LUMASK;Background color/luma mask
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_MASFRAME;Mask and Merge
-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;Contrast
+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;Curves
TP_LOCALLAB_MASK2;Contrast curve
-TP_LOCALLAB_MASKCOL;Mask Curves
+TP_LOCALLAB_MASKCOL;
TP_LOCALLAB_MASKCOM;Common Color Mask
TP_LOCALLAB_MASKCOM_TOOLNAME;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.
@@ -2842,7 +2922,7 @@ TP_LOCALLAB_MASKCURVE_TOOLTIP;The 3 curves are set to 1 (maximum) by default:\nC
TP_LOCALLAB_MASKDDECAY;Decay strength
TP_LOCALLAB_MASKDECAY_TOOLTIP;Manages the rate of decay for the gray levels in the mask.\n Decay = 1 linear, Decay > 1 sharper parabolic transitions, Decay < 1 more gradual transitions
TP_LOCALLAB_MASKH;Hue curve
-TP_LOCALLAB_MASKLC_TOOLTIP;This allows you to target the denoise based on the image luminance information contained in the L(L) or LC(H) mask (Mask and Modifications).\n The L(L) mask or the LC(H) mask must be enabled to use this function.\n 'Dark area luminance threshold'. If 'Reinforce denoise in dark and light areas' > 1 the denoise is progressively increased from 0% at the threshold settings to 100% at the maximum black value (determined by mask).\n 'Light area luminance threshold' .The denoise is progressively decreased from 100% at the threshold setting to 0% at the maximum white value (determined by mask).\n In the area between the two thresholds, the denoise settings are not affected by the mask.
+TP_LOCALLAB_MASKLC_TOOLTIP;This allows you to target the denoise based on the image luminance information contained in the L(L) or LC(H) mask (Mask and Modifications).\n The L(L) mask or the LC(H) mask must be enabled to use this function.\n 'Dark area luminance threshold'. If 'Reinforce denoise in dark and light areas' > 1 the denoise is progressively increased from 0% at the threshold setting to 100% at the maximum black value (determined by mask).\n 'Light area luminance threshold'. The denoise is progressively decreased from 100% at the threshold setting to 0% at the maximum white value (determined by mask).\n In the area between the two thresholds, the denoise settings are not affected by the mask.
TP_LOCALLAB_MASKDE_TOOLTIP;Used to target the denoise as a function of the image luminance information contained in the L(L) or LC(H) masks (Mask and modifications).\n The L(L) mask or the LC(H) mask must be enabled to use this function.\n If the mask is below the ‘dark’ threshold, then the Denoise will be applied progressively.\n if the mask is above the ‘light’ threshold, then the Denoise will be applied progressively.\n Between the two, the image settings without the Denoise will be maintained, unless you adjust the sliders "Gray area luminance denoise" or "Gray area chrominance denoise".
TP_LOCALLAB_MASKGF_TOOLTIP;Used to target the Guided Filter as a function of the image luminance information contained in the L(L) or LC(H) masks (Mask and modifications).\n The L(L) mask or the LC(H) mask must be enabled to use this function.\n If the mask is below the ‘dark’ threshold, then the GF will be applied progressively.\n if the mask is above the ‘light’ threshold, then the GF will be applied progressively.\n Between the two, the image settings without the GF will be maintained.
TP_LOCALLAB_MASKRECOL_TOOLTIP;Used to modulate the effect of the Color and Light settings based on the image luminance information contained in the L(L) or LC(H) masks (Mask and modifications).\n The L(L) mask or the LC(H) mask must be enabled to use this function.\n The ‘dark’ and ‘light’ areas below the dark threshold and above the light threshold will be restored progressively to their original values prior to being modified by the Color and Light settings \n In between these two areas, the full value of the Color and Light settings will be applied
@@ -2855,33 +2935,35 @@ TP_LOCALLAB_MASKRESVIB_TOOLTIP;Used to modulate the effect of the Vibrance and W
TP_LOCALLAB_MASKRESWAV_TOOLTIP;Used to modulate the effect of the Local contrast and Wavelet settings based on the image luminance information contained in the L(L) or LC(H) masks (Mask and modifications).\n The L(L) mask or the LC(H) mask must be enabled to use this function.\n The ‘dark’ and ‘light’ areas below the dark threshold and above the light threshold will be restored progressively to their original values prior to being modified by the Local contrast and Wavelet settings \n In between these two areas, the full value of the Local contrast and Wavelet settings will be applied
TP_LOCALLAB_MASKRELOG_TOOLTIP;Used to modulate the effect of the Log encoding settings based on the image luminance information contained in the L(L) or LC(H) masks (Mask and modifications).\n The L(L) mask or the LC(H) mask must be enabled to use this function.\n The ‘dark’ and ‘light’ areas below the dark threshold and above the light threshold will be restored progressively to their original values prior to being modified by the Log encoding settings - can be used to restore highlights reconstructed by Color propagation \n In between these two areas, the full value of the Log encoding settings will be applied
TP_LOCALLAB_MASKDEINV_TOOLTIP;Reverses the way the algorithm interprets the mask.\nIf checked black and very light areas will be decreased.
-TP_LOCALLAB_MASKHIGTHRESC_TOOLTIP;Light-tone limit above which Color and Light will be restored progressively to their original values prior to being modified by the Color and Light settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘structure mask’, 'Blur mask', ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’, ‘Local contrast wavelet’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESS_TOOLTIP;Light-tone limit above which Shadows Highlights will be restored progressively to their original values prior to being modified by the Shadows Highlights settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESCB_TOOLTIP;Light-tone limit above which CBDL (Luminance only) will be restored progressively to their original values prior to being modified by the CBDL settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESRETI_TOOLTIP;Light-tone limit above which Retinex (Luminance only) will be restored progressively to their original values prior to being modified by the Retinex settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESTM_TOOLTIP;Light-tone limit above which Tone Mapping will be restored progressively to their original values prior to being modified by the Tone Mapping settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESVIB_TOOLTIP;Light-tone limit above which Vibrance and Warm Cool will be restored progressively to their original values prior to being modified by the Vibrance and Warm Cool settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESWAV_TOOLTIP;Light-tone limit above which Local contrast and Wavelet will be restored progressively to their original values prior to being modified by the Local contrast and Wavelet settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESE_TOOLTIP;Light-tone limit above which 'Dynamic range and Exposure' will be restored progressively to their original values prior to being modified by the 'Dynamic range and Exposure' settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESL_TOOLTIP;Light-tone limit above which Log encoding will be restored progressively to their original values prior to being modified by the Log encoding settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKHIGTHRESD_TOOLTIP; The denoise is progressively decreased from 100% at the threshold setting to 0% at the maximum white value (as determined by the mask).\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘structure mask’, ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’, ‘Local contrast wavelet’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
+TP_LOCALLAB_MASKHIGTHRESC_TOOLTIP;Lighter-tone limit above which the parameters will be restored progressively to their original values prior to being modified by the Color and Light settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Structure mask’, 'Blur mask', ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’, ‘Local contrast’ (wavelets).\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESS_TOOLTIP;Lighter-tone limit above which the parameters will be restored progressively to their original values prior to being modified by the Shadows Highlights settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESCB_TOOLTIP;Lighter-tone limit above which CBDL (Luminance only) parameters will be restored progressively to their original values prior to being modified by the CBDL settings .\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESRETI_TOOLTIP;Lighter-tone limit above which Retinex (Luminance only) parameters will be restored progressively to their original values prior to being modified by the Retinex settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESTM_TOOLTIP;Lighter-tone limit above which the parameters will be restored progressively to their original values prior to being modified by the Tone Mapping settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESVIB_TOOLTIP;Lighter-tone limit above which the parameters will be restored progressively to their original values prior to being modified by the Vibrance and Warm Cool settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESWAV_TOOLTIP;Lighter-tone limit above which the parameters will be restored progressively to their original values prior to being modified by the Local contrast and Wavelet settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESE_TOOLTIP;Lighter-tone limit above which the parameters will be restored progressively to their original values prior to being modified by the 'Dynamic range and Exposure' settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable colorpicker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESL_TOOLTIP;Lighter-tone limit above which the parameters will be restored progressively to their original values prior to being modified by the Log encoding settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKHIGTHRESD_TOOLTIP; The denoise is progressively decreased from 100% at the threshold setting to 0% at the maximum white value (as determined by the mask).\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Structure mask’, ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’, ‘Local contrast’ (wavelets).\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask'=0 in Settings.
TP_LOCALLAB_MASKHIGTHRES_TOOLTIP; The Guided Filter is progressively decreased from 100% at the threshold setting to 0% at the maximum white value (as determined by the mask).\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘structure mask’, ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’, ‘Local contrast wavelet’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
TP_LOCALLAB_MASKLCTHR;Light area luminance threshold
+TP_LOCALLAB_MASKLCTHR2;Light area luma threshold
TP_LOCALLAB_MASKLCTHRLOW;Dark area luminance threshold
-TP_LOCALLAB_MASKLNOISELOW;Reinforce denoise in dark and light areas
-TP_LOCALLAB_MASKLOWTHRES_TOOLTIP;The Guided Filter is progressively increased from 0% at the threshold setting to 100% at the maximum black value (as determined by the mask).\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘structure mask’, ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’, ‘Local contrast wavelet’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESD_TOOLTIP;The denoise is progressively increased from 0% at the threshold setting to 100% at the maximum black value (as determined by the mask).\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘structure mask’, ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’, ‘Local contrast wavelet’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESC_TOOLTIP;Dark-tone limit below which Color and Light will be restored progressively to their original values prior to being modified by the Color and Light settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘structure mask’, 'blur mask', ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’, ‘Local contrast wavelet’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESL_TOOLTIP;Dark-tone limit below which Log encoding will be restored progressively to their original values prior to being modified by the Log encoding settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESE_TOOLTIP;Dark-tone limit below which 'Dynamic range and Exposure' will be restored progressively to their original values prior to being modified by the 'Dynamic range and Exposure' settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESS_TOOLTIP;Dark-tone limit below which Shadows Highligts will be restored progressively to their original values prior to being modified by the Shadows Highlights settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESCB_TOOLTIP;Dark-tone limit below which CBDL (Luminance only) will be restored progressively to their original values prior to being modified by the CBDL settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESRETI_TOOLTIP;Dark-tone limit below which Retinex (Luminance only) will be restored progressively to their original values prior to being modified by the Retinex settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESTM_TOOLTIP;Dark-tone limit below which Tone Mapping will be restored progressively to their original values prior to being modified by the Tone Mapping settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESVIB_TOOLTIP;Dark-tone limit below which Vibrance and Warm Cool will be restored progressively to their original values prior to being modified by the Vibrance and Warm Cool settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLOWTHRESWAV_TOOLTIP;Dark-tone limit below which Local contrast and Wavelet will be restored progressively to their original values prior to being modified by the Local contrast and Wavelet settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, ‘Gamma and slope’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Be carefull in 'settings' to Background color mask = 0
-TP_LOCALLAB_MASKLCTHRMID;Gray area luminance denoise
-TP_LOCALLAB_MASKLCTHRMIDCH;Gray area chrominance denoise
+TP_LOCALLAB_MASKLCTHRLOW2;Dark area luma threshold
+TP_LOCALLAB_MASKLNOISELOW;Reinforce dark/light areas
+TP_LOCALLAB_MASKLOWTHRES_TOOLTIP;The Guided Filter is progressively increased from 0% at the threshold setting to 100% at the maximum black value (as determined by the mask).\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Structure mask’, ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’, ‘Local contrast’ (wavelets).\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESD_TOOLTIP;The denoise is progressively increased from 0% at the threshold setting to 100% at the maximum black value (as determined by the mask).\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Structure mask’, ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’, ‘Local contrast’ (wavelets).\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESC_TOOLTIP;Dark-tone limit below which the parameters will be restored progressively to their original values prior to being modified by the Color and Light settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Structure mask’, 'blur mask', ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’, ‘Local contrast’ (wavelets).\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESL_TOOLTIP;Dark-tone limit below which the parameters will be restored progressively to their original values prior to being modified by the Log encoding settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels:‘Smooth radius’, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESE_TOOLTIP;Dark-tone limit below which the parameters will be restored progressively to their original values prior to being modified by the 'Dynamic range and Exposure' settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESS_TOOLTIP;Dark-tone limit below which the parameters will be restored progressively to their original values prior to being modified by the Shadows Highlights settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESCB_TOOLTIP;Dark-tone limit below which the CBDL parameters (Luminance only) will be restored progressively to their original values prior to being modified by the CBDL settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESRETI_TOOLTIP;Dark-tone limit below which the Retinex (Luminance only) parameters will be restored progressively to their original values prior to being modified by the Retinex settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESTM_TOOLTIP;Dark-tone limit below which the parameters will be restored progressively to their original values prior to being modified by the Tone Mapping settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESVIB_TOOLTIP;Dark-tone limit below which the parameters will be restored progressively to their original values prior to being modified by the Vibrance and Warm Cool settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLOWTHRESWAV_TOOLTIP;Dark-tone limit below which the parameters will be restored progressively to their original values prior to being modified by the Local contrast and Wavelet settings.\n You can use certain tools in ‘Mask and modifications’ to change the gray levels: ‘Smooth radius’, Gamma and Slope, ‘Contrast curve’.\n Use a ‘lockable color picker’ on the mask to see which areas will be affected. Make sure you set ‘Background color mask’ = 0 in Settings.
+TP_LOCALLAB_MASKLCTHRMID;Gray area luma denoise
+TP_LOCALLAB_MASKLCTHRMIDCH;Gray area chroma denoise
TP_LOCALLAB_MASKUSABLE;Mask enabled (Mask & modifications)
TP_LOCALLAB_MASKUNUSABLE;Mask disabled (Mask & modifications)
TP_LOCALLAB_MASKRECOTHRES;Recovery threshold
@@ -2897,19 +2979,19 @@ TP_LOCALLAB_MERELE;Lighten only
TP_LOCALLAB_MERFIV;Addition
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_MERGE1COLFRA;Merge with Original/Previous/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;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 = % 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_MERGETHR;Original + Mask LCh
+TP_LOCALLAB_MERGETWO;Original
TP_LOCALLAB_MERGETYPE;Merge image and mask
-TP_LOCALLAB_MERGETYPE_TOOLTIP;None, use all mask in LCH mode.\nShort curves 'L' mask, use a short circuit for mask 2, 3, 4, 6, 7.\nOriginal mask 8, blend current image with original
+TP_LOCALLAB_MERGETYPE_TOOLTIP;None, use all mask in LCh mode.\nShort curves 'L' mask, use a short circuit for mask 2, 3, 4, 6, 7.\nOriginal mask 8, blend current image with original
TP_LOCALLAB_MERHEI;Overlay
TP_LOCALLAB_MERHUE;Hue
TP_LOCALLAB_MERLUCOL;Luminance
@@ -2928,7 +3010,7 @@ TP_LOCALLAB_MERTHR;Difference
TP_LOCALLAB_MERTWE;Exclusion
TP_LOCALLAB_MERTWO;Subtract
TP_LOCALLAB_METHOD_TOOLTIP;'Enhanced + chroma denoise' significantly increases processing times.\nBut reduce artifacts.
-TP_LOCALLAB_MLABEL;Restored data Min=%1 Max=%2 (Clip - Offset)
+TP_LOCALLAB_MLABEL;Restored data Min=%1 Max=%2
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
@@ -2953,12 +3035,12 @@ TP_LOCALLAB_NLPAT;Maximum patch size
TP_LOCALLAB_NLRAD;Maximum radius size
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_NOISECHRODETAIL;Chroma detail recovery
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)
-TP_LOCALLAB_NOISELUMDETAIL;Luminance detail recovery (DCT ƒ)
+TP_LOCALLAB_NOISELUMDETAIL;Luma detail recovery
TP_LOCALLAB_NOISELUMFINE;Luminance fine 1 (Wav)
TP_LOCALLAB_NOISELUMFINETWO;Luminance fine 2 (Wav)
TP_LOCALLAB_NOISELUMFINEZERO;Luminance fine 0 (Wav)
@@ -2995,6 +3077,12 @@ TP_LOCALLAB_RECURS_TOOLTIP;Forces the algorithm to recalculate the references af
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_REPARW_TOOLTIP;Allows you to adjust the relative strength of the local contrast and wavelet image with respect to the original image.
+TP_LOCALLAB_REPARCOL_TOOLTIP;Allows you to adjust the relative strength of the Color and Light image with respect to the original image.
+TP_LOCALLAB_REPARDEN_TOOLTIP;Allows you to adjust the relative strength of the Denoise image with respect to the original image.
+TP_LOCALLAB_REPARSH_TOOLTIP;Allows you to adjust the relative strength of the Shadows/Highlights and Tone Equalizer image with respect to the original image.
+TP_LOCALLAB_REPAREXP_TOOLTIP;Allows you to adjust the relative strength of the Dynamic Range and Exposure image with respect to the original image.
+TP_LOCALLAB_REPARTM_TOOLTIP;Allows you to adjust the relative strength of the Tone mapping image with respect to the original image.
TP_LOCALLAB_RESETSHOW;Reset All Show Modifications
TP_LOCALLAB_RESID;Residual Image
TP_LOCALLAB_RESIDBLUR;Blur residual image
@@ -3039,8 +3127,8 @@ TP_LOCALLAB_SETTINGS;Settings
TP_LOCALLAB_SH1;Shadows Highlights
TP_LOCALLAB_SH2;Equalizer
TP_LOCALLAB_SHADEX;Shadows
-TP_LOCALLAB_SHADEXCOMP;Shadow compression & tonal width
-TP_LOCALLAB_SHADHIGH;Shadows/Highlights-Equalizer
+TP_LOCALLAB_SHADEXCOMP;Shadow compression
+TP_LOCALLAB_SHADHIGH;Shadows/Highlights & Tone Equalizer
TP_LOCALLAB_SHADHMASK_TOOLTIP;Lowers the highlights of the mask in the same way as the shadows/highlights algorithm
TP_LOCALLAB_SHADMASK_TOOLTIP;Lifts the shadows of the mask in the same way as the shadows/highlights algorithm
TP_LOCALLAB_SHADOWHIGHLIGHT_TOOLTIP;Adjust shadows and 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.
@@ -3071,7 +3159,8 @@ TP_LOCALLAB_SHOWMASKSOFT_TOOLTIP;Allows you to visualize the different stages of
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_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_SHOWMASKTYP_TOOLTIP;Can be used with ‘Mask and modifications’.\nIf ‘Blur and noise’ is selected, the mask cannot be used for Denoise.\nIf Denoise is selected, the mask cannot be used for ‘Blur and noise’.\nIf ‘Blur and noise + Denoise’ is selected, the mask is shared. Note that in this case, the Scope sliders for both ‘Blur and noise’ and Denoise will be active so it is advisable to use the option ‘Show modifications with mask’ when making any adjustments.
TP_LOCALLAB_SHOWMNONE;Show modified image
TP_LOCALLAB_SHOWMODIF;Show modified areas without mask
TP_LOCALLAB_SHOWMODIF2;Show modified areas
@@ -3082,8 +3171,8 @@ 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 spot structure(advanced)
-TP_LOCALLAB_SHOWSTRUCEX;Show spot structure(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
@@ -3092,7 +3181,7 @@ TP_LOCALLAB_SH_TOOLNAME;Shadows/Highlights & Tone Equalizer
TP_LOCALLAB_SIGMAWAV;Attenuation response
TP_LOCALLAB_SIM;Simple
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_SLOMASK_TOOLTIP;Adjusting Gamma and Slope can provide 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_SOFTM;Soft Light
@@ -3106,7 +3195,7 @@ 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;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_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
@@ -3121,9 +3210,9 @@ TP_LOCALLAB_STRRETI_TOOLTIP;if Strength Retinex < 0.2 only Dehaze is enabled.\ni
TP_LOCALLAB_STRUC;Structure
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_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;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_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 (Blur and denoise") and mask(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.
@@ -3134,7 +3223,7 @@ TP_LOCALLAB_THRES;Threshold structure
TP_LOCALLAB_THRESDELTAE;ΔE scope threshold
TP_LOCALLAB_THRESRETI;Threshold
TP_LOCALLAB_THRESWAV;Balance threshold
-TP_LOCALLAB_TLABEL;TM Data Min=%1 Max=%2 Mean=%3 Sigma=%4 (Threshold)
+TP_LOCALLAB_TLABEL;TM Min=%1 Max=%2 Mean=%3 Sig=%4
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 normalize the results with the threshold slider.
TP_LOCALLAB_TM;Tone Mapping
@@ -3148,7 +3237,8 @@ TP_LOCALLAB_TONE_TOOLNAME;Tone Mapping
TP_LOCALLAB_TOOLCOL;Structure mask as tool
TP_LOCALLAB_TOOLCOLFRMASK_TOOLTIP;Allows you to modify the mask, if one exists
TP_LOCALLAB_TOOLMASK;Mask Tools
-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_TOOLMASK_2;Wavelets
+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_TRANSIT;Transition Gradient
TP_LOCALLAB_TRANSITGRAD;Transition differentiation XY
TP_LOCALLAB_TRANSITGRAD_TOOLTIP;Allows you to vary the y-axis transition
@@ -3165,7 +3255,7 @@ 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
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_WAMASKCOL;Mask Wavelet level
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 including the dark-gray/light-gray boundary 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, 4, 5, 6).
@@ -3173,24 +3263,24 @@ TP_LOCALLAB_WAT_BALTHRES_TOOLTIP;Balances the action within each level.
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_CLARIC_TOOLTIP;“Merge chroma” is used to select the intensity of the desired effect on chrominance.
TP_LOCALLAB_WAT_CLARIL_TOOLTIP;“Merge luma” is used to select the intensity of the desired effect on luminance.
-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_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_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_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_EXPRESID_TOOLTIP;The residual image behaves in the same way as the main image when making adjustments to contrast, chroma etc.
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_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_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_ORIGLC_TOOLTIP;“Merge only with original image”, prevents the “Wavelet Pyramid” settings from interfering with “Clarity” and “Sharp mask”.
+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_RESIDBLUR_TOOLTIP;Blurs the residual image, independent of the levels.
TP_LOCALLAB_WAT_RESIDCOMP_TOOLTIP;Compresses the residual image to increase or reduce contrast.
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_STRENGTHW_TOOLTIP;Intensity of edge-effect detection.
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_THRESHOLDWAV_TOOLTIP;Range of wavelet levels used throughout the "Wavelets" module.
+TP_LOCALLAB_WAT_THRESHOLDWAV_TOOLTIP;Range of wavelet levels used throughout the ‘Wavelets’ module.
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_WAVCBDL_TOOLTIP;Similar to Contrast By Detail Levels. Fine to coarse detail levels from left to right on the x-axis.
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_WAT_WAVESHOW_TOOLTIP;Shows all of the "Edge sharpness" tools. It is advisable to read the Wavelet Levels documentation.
+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_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_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.
@@ -3202,19 +3292,20 @@ TP_LOCALLAB_WAVCOMPRE_TOOLTIP;Allows you to apply tone mapping or reduce local c
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_WAVDEN;Luminance denoise
+TP_LOCALLAB_WAVE;Wavelets
TP_LOCALLAB_WAVEDG;Local contrast
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_WAVEMASK_LEVEL_TOOLTIP;Range of wavelet levels used in “Local contrast (by wavelet level)”
+TP_LOCALLAB_WAVEMASK_LEVEL_TOOLTIP;Range of wavelet levels used in ‘Local contrast’ (by wavelet level).
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_WAVHIGH;Wavelet high
TP_LOCALLAB_WAVHUE_TOOLTIP;Allows you to reduce or increase the denoise based on hue.
TP_LOCALLAB_WAVLEV;Blur by level
-TP_LOCALLAB_WAVLOW;Ψ Wavelet low
-TP_LOCALLAB_WAVMASK;Ψ Local contrast (by wavelet level)
+TP_LOCALLAB_WAVLOW;Wavelet low
+TP_LOCALLAB_WAVMASK;Local contrast
TP_LOCALLAB_WAVMASK_TOOLTIP;Uses wavelets to modify the local contrast of the mask and reinforce or reduce the structure (skin, buildings...)
-TP_LOCALLAB_WAVMED;Ψ Wavelet normal
+//TP_LOCALLAB_WAVMED;Ψ Wavelet normal
+TP_LOCALLAB_WAVMED;Wavelet normal
TP_LOCALLAB_WEDIANHI;Median Hi
TP_LOCALLAB_WHITE_EV;White Ev
TP_LOCAL_HEIGHT;Bottom
@@ -3236,6 +3327,7 @@ TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Roundness:\n0 = rectangle,\n50 = fitted ellipse,
TP_PCVIGNETTE_STRENGTH;Strength
TP_PCVIGNETTE_STRENGTH_TOOLTIP;Filter strength in stops (reached in corners).
TP_PDSHARPENING_LABEL;Capture Sharpening
+TP_PERSPECTIVE_CONTROL_LINE_APPLY_INVALID_TOOLTIP;At least two horizontal or two vertical control lines required.
TP_PERSPECTIVE_CAMERA_CROP_FACTOR;Crop factor
TP_PERSPECTIVE_CAMERA_FOCAL_LENGTH;Focal length
TP_PERSPECTIVE_CAMERA_FRAME;Correction
@@ -3279,6 +3371,12 @@ TP_PREPROCWB_LABEL;Preprocess White Balance
TP_PREPROCWB_MODE;Mode
TP_PREPROCWB_MODE_AUTO;Auto
TP_PREPROCWB_MODE_CAMERA;Camera
+TC_PRIM_BLUX;Bx
+TC_PRIM_BLUY;By
+TC_PRIM_GREX;Gx
+TC_PRIM_GREY;Gy
+TC_PRIM_REDX;Rx
+TC_PRIM_REDY;Ry
TP_PRSHARPENING_LABEL;Post-Resize Sharpening
TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions.
TP_RAWCACORR_AUTO;Auto-correction
@@ -3380,10 +3478,14 @@ TP_RESIZE_H;Height:
TP_RESIZE_HEIGHT;Height
TP_RESIZE_LABEL;Resize
TP_RESIZE_LANCZOS;Lanczos
+TP_RESIZE_LE;Long Edge:
+TP_RESIZE_LONG;Long Edge
TP_RESIZE_METHOD;Method:
TP_RESIZE_NEAREST;Nearest
TP_RESIZE_SCALE;Scale
TP_RESIZE_SPECIFY;Specify:
+TP_RESIZE_SE;Short Edge:
+TP_RESIZE_SHORT;Short Edge
TP_RESIZE_W;Width:
TP_RESIZE_WIDTH;Width
TP_RETINEX_CONTEDIT_HSL;HSL histogram
@@ -3512,6 +3614,10 @@ TP_SHARPENMICRO_MATRIX;3×3 matrix instead of 5×5
TP_SHARPENMICRO_UNIFORMITY;Uniformity
TP_SOFTLIGHT_LABEL;Soft Light
TP_SOFTLIGHT_STRENGTH;Strength
+TP_SPOT_COUNTLABEL;%1 point(s)
+TP_SPOT_ENTRYCHANGED;Point changed
+TP_SPOT_HINT;Click on this button to be able to operate on the preview area.\n\nTo edit a spot, hover the white mark locating an edited area, making the editing geometry appear.\n\nTo add a spot, press Ctrl and left mouse button, drag the circle (Ctrl key can be released) to a source location, then release the mouse button.\n\nTo move the source or destination spot, hover its center then drag it.\n\nThe inner circle (maximum effect area) and the "feather" circle can be resized by hovering them (the circle becomes orange) and dragging it (the circle becomes red).\n\nWhen the changes are done, right click outside any spot to end the Spot editing mode, or click on this button again.
+TP_SPOT_LABEL;Spot Removal
TP_TM_FATTAL_AMOUNT;Amount
TP_TM_FATTAL_ANCHOR;Anchor
TP_TM_FATTAL_LABEL;Dynamic Range Compression
@@ -3559,7 +3665,7 @@ TP_WAVELET_BACUR;Curve
TP_WAVELET_BALANCE;Contrast balance d/v-h
TP_WAVELET_BALANCE_TOOLTIP;Alters the balance between the wavelet directions: vertical-horizontal and diagonal.\nIf contrast, chroma or residual tone mapping are activated, the effect due to balance is amplified.
TP_WAVELET_BALCHRO;Chroma balance
-TP_WAVELET_BALCHROM;Denoise equalizer Blue-Yellow/Red-Green
+TP_WAVELET_BALCHROM;Equalizer Color
TP_WAVELET_BALCHRO_TOOLTIP;If enabled, the 'Contrast balance' curve or slider also modifies chroma balance.
TP_WAVELET_BALLUM;Denoise equalizer White-Black
TP_WAVELET_BANONE;None
@@ -3634,9 +3740,9 @@ TP_WAVELET_DENCURV;Curve
TP_WAVELET_DENEQUAL;1 2 3 4 Equal
TP_WAVELET_DENH;Threshold
TP_WAVELET_DENL;Correction structure
-TP_WAVELET_DENLH;Guided threshold by detail levels 1-4
+TP_WAVELET_DENLH;Guided threshold levels 1-4
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_DENMIX_TOOLTIP;The local-contrast reference value used by the guided filter.\nDepending on the image, results can vary depending on whether the noise is measured before or after the noise reduction. These four choices allow you to take into account various combinations of the original and modified (denoised) images to find the best compromise.
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
@@ -3719,7 +3825,7 @@ 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_MIXCONTRAST;Reference local contrast
+TP_WAVELET_MIXCONTRAST;Reference
TP_WAVELET_MIXDENOISE;Denoise
TP_WAVELET_MIXMIX;Mixed 50% noise - 50% denoise
TP_WAVELET_MIXMIX70;Mixed 30% noise - 70% denoise
@@ -3776,7 +3882,7 @@ TP_WAVELET_STREND;Strength
TP_WAVELET_STRENGTH;Strength
TP_WAVELET_SUPE;Extra
TP_WAVELET_THR;Shadows 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 curve used to guide the noise reduction as a function of local contrast. The denoise will be applied to uniform low local-contrast areas. Areas with detail (higher local contrast) will be preserved.
TP_WAVELET_THREND;Local contrast threshold
TP_WAVELET_THRESHOLD;Finer levels
TP_WAVELET_THRESHOLD2;Coarser levels
@@ -3866,4 +3972,4 @@ ZOOMPANEL_ZOOMOUT;Zoom Out\nShortcut: -
//TP_LOCALLAB_CIECAMLOG_TOOLTIP;This module is based on the CIECAM 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_WAVELET_DENH;Low levels (1234)- Finest details
//TP_WAVELET_DENL;High levels - Coarsest details
-//TP_WAVELET_DENLH;Guided threshold by detail levels 1-4
+//TP_WAVELET_DENLH;Guided threshold for detail levels 1-4
diff --git a/rtdata/profiles/Film Negative - Black and White.pp3 b/rtdata/profiles/Film Negative - Black and White.pp3
new file mode 100644
index 000000000..ad2a38e1e
--- /dev/null
+++ b/rtdata/profiles/Film Negative - Black and White.pp3
@@ -0,0 +1,41 @@
+[Exposure]
+Auto=false
+Compensation=0
+HistogramMatching=false
+CurveFromHistogramMatching=false
+ClampOOG=false
+CurveMode=Standard
+CurveMode2=Standard
+Curve=1;0;0;0.88544601940051371;1;
+Curve2=1;0;0;0.0397505754145333;0.020171771436200074;0.54669745433149319;0.69419974733677647;1;1;
+
+[HLRecovery]
+Enabled=false
+Method=Blend
+
+[Black & White]
+Enabled=true
+
+[Crop]
+FixedRatio=false
+
+[Color Management]
+InputProfile=(camera)
+ToneCurve=false
+ApplyLookTable=false
+ApplyHueSatMap=false
+WorkingProfile=Rec2020
+WorkingTRC=none
+
+[RAW Bayer]
+Method=rcd
+
+[Film Negative]
+Enabled=true
+RedRatio=1.0
+GreenExponent=1.5
+BlueRatio=1.0
+ColorSpace=1
+RefInput=0;0;0;
+RefOutput=0;0;0;
+BackCompat=0
diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index ee575ae47..1f3cf352b 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -64,6 +64,7 @@ endif()
set(CAMCONSTSFILE "camconst.json")
set(RTENGINESOURCEFILES
+ alpha.cc
ahd_demosaic_RT.cc
amaze_demosaic_RT.cc
badpixels.cc
@@ -139,7 +140,6 @@ set(RTENGINESOURCEFILES
jpeg_ijg/jpeg_memsrc.cc
labimage.cc
lcp.cc
- lj92.c
lmmse_demosaic.cc
loadinitial.cc
munselllch.cc
@@ -164,6 +164,7 @@ set(RTENGINESOURCEFILES
rtthumbnail.cc
shmap.cc
simpleprocess.cc
+ spot.cc
stdimagesource.cc
tmo_fattal02.cc
utils.cc
diff --git a/rtengine/EdgePreservingDecomposition.cc b/rtengine/EdgePreservingDecomposition.cc
index 5ae023122..dcb05c29a 100644
--- a/rtengine/EdgePreservingDecomposition.cc
+++ b/rtengine/EdgePreservingDecomposition.cc
@@ -208,7 +208,7 @@ bool MultiDiagonalSymmetricMatrix::CreateDiagonal(int index, int StartRow)
return true;
}
-inline int MultiDiagonalSymmetricMatrix::FindIndex(int StartRow)
+inline int MultiDiagonalSymmetricMatrix::FindIndex(int StartRow) const
{
//There's GOT to be a better way to do this. "Bidirectional map?"
// Issue 1895 : Changed start of loop from zero to one
diff --git a/rtengine/EdgePreservingDecomposition.h b/rtengine/EdgePreservingDecomposition.h
index c90123ed3..73a7b1732 100644
--- a/rtengine/EdgePreservingDecomposition.h
+++ b/rtengine/EdgePreservingDecomposition.h
@@ -97,7 +97,7 @@ public:
int *StartRows;
bool CreateDiagonal(int index, int StartRow);
int n, m; //The matrix is n x n, with m diagonals on the lower triangle. Don't change these. They should be private but aren't for convenience.
- inline int DiagonalLength(int StartRow) //Gives number of elements in a diagonal.
+ inline int DiagonalLength(int StartRow) const //Gives number of elements in a diagonal.
{
return n - StartRow;
};
@@ -109,7 +109,7 @@ public:
void VectorProduct(float *Product, float *x);
//Given the start row, attempts to find the corresponding index, or -1 if the StartRow doesn't exist.
- inline int FindIndex(int StartRow) __attribute__((always_inline));
+ inline int FindIndex(int StartRow) const __attribute__((always_inline));
//This is the same as above, but designed to take this class as a pass through variable. By this way you can feed
//the meat of this class into an independent function, such as SparseConjugateGradient.
diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc
index 474196843..400dea05b 100644
--- a/rtengine/FTblockDN.cc
+++ b/rtengine/FTblockDN.cc
@@ -667,7 +667,7 @@ BENCHFUN
const float gain = std::pow(2.0, expcomp);
const double params_Ldetail = std::min(dnparams.Ldetail, 99.9); // max out to avoid div by zero when using noisevar_Ldetail as divisor
- const float noisevar_Ldetail = SQR(SQR(100. - params_Ldetail) + 50.0 * (100.0 - params_Ldetail) * TS * 0.5);
+ const float noisevar_Ldetail = SQR((SQR(100. - params_Ldetail) + 50.0 * (100.0 - params_Ldetail)) * TS * 0.5);
array2D tilemask_in(TS, TS);
array2D tilemask_out(TS, TS);
diff --git a/rtengine/alpha.cc b/rtengine/alpha.cc
new file mode 100644
index 000000000..34132b879
--- /dev/null
+++ b/rtengine/alpha.cc
@@ -0,0 +1,96 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 "alpha.h"
+
+namespace rtengine
+{
+
+Alpha::Alpha () {}
+
+Alpha::Alpha (int width, int height)
+{
+ if (width > 0 && height > 0) {
+ surface = Cairo::ImageSurface::create (Cairo::FORMAT_A8, width, height);
+ }
+}
+
+/*
+Alpha::~Alpha () {
+ surface->unreference();
+}
+*/
+
+void Alpha::setSize (int width, int height)
+{
+ if (width > 0 && height > 0) {
+ if (surface) {
+ if (width != getWidth() && height != getHeight()) {
+ surface.clear(); // does this delete the referenced object? Unreferencing doesn't work, since Cairo expect to have a non null refCount in the destructor!
+ } else {
+ return;
+ }
+ }
+
+ surface = Cairo::ImageSurface::create (Cairo::FORMAT_A8, width, height);
+ } else if (surface) {
+ surface.clear();
+ }
+}
+
+int Alpha::getWidth() const
+{
+ if (surface) {
+ return surface->get_width();
+ }
+
+ return -1;
+}
+
+int Alpha::getHeight() const
+{
+ if (surface) {
+ return surface->get_height();
+ }
+
+ return -1;
+}
+
+
+Cairo::RefPtr Alpha::getSurface () const
+{
+ return surface; // to be used in bitmap edition
+}
+
+unsigned char Alpha::operator () (unsigned row, unsigned col) const
+{
+ return * (surface->get_data () + row * surface->get_width () + col);
+}
+
+unsigned char& Alpha::operator () (unsigned row, unsigned col)
+{
+ return * (surface->get_data () + row * surface->get_width () + col);
+}
+
+unsigned char* Alpha::operator () (unsigned row) const
+{
+ return surface->get_data () + row * surface->get_width ();
+}
+
+}
diff --git a/rtengine/alpha.h b/rtengine/alpha.h
new file mode 100644
index 000000000..1fe2a7a7c
--- /dev/null
+++ b/rtengine/alpha.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ */
+#ifndef _ALPHA_H_
+#define _ALPHA_H_
+
+#include
+#include
+
+#define CHECK_BOUNDS 0
+
+namespace rtengine
+{
+
+/// Alpha channel class (8 bits)
+class Alpha
+{
+protected:
+ Cairo::RefPtr surface;
+
+public:
+ Alpha ();
+ Alpha (int width, int height);
+ //~Alpha ();
+
+ void setSize (int width, int height);
+ int getWidth() const;
+ int getHeight() const;
+
+ Cairo::RefPtr getSurface () const;
+
+ // TODO: to make the editing faster, we should add an iterator class
+
+ // Will send back the start of a row
+ unsigned char* operator () (unsigned row) const;
+ // Will send back a value at a given row, col position
+ unsigned char& operator () (unsigned row, unsigned col);
+ unsigned char operator () (unsigned row, unsigned col) const;
+};
+
+}
+
+#endif
diff --git a/rtengine/badpixels.cc b/rtengine/badpixels.cc
index 97294bdf7..f04afb1ee 100644
--- a/rtengine/badpixels.cc
+++ b/rtengine/badpixels.cc
@@ -182,7 +182,7 @@ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array
/* interpolateBadPixelsNcolors: correct raw pixels looking at the bitmap
* takes into consideration if there are multiple bad pixels in the neighborhood
*/
-int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, const int colors)
+int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, const int colours)
{
constexpr float eps = 1.f;
int counter = 0;
@@ -204,9 +204,9 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
continue;
}
- float wtdsum[colors];
- float norm[colors];
- for (int c = 0; c < colors; ++c) {
+ float wtdsum[colours];
+ float norm[colours];
+ for (int c = 0; c < colours; ++c) {
wtdsum[c] = norm[c] = 0.f;
}
@@ -216,41 +216,41 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
continue;
}
- for (int c = 0; c < colors; ++c) {
- const float dirwt = 0.70710678f / (fabsf(rawData[row - 1][(col + dx) * colors + c] - rawData[row + 1][(col - dx) * colors + c]) + eps);
- wtdsum[c] += dirwt * (rawData[row - 1][(col + dx) * colors + c] + rawData[row + 1][(col - dx) * colors + c]);
+ for (int c = 0; c < colours; ++c) {
+ const float dirwt = 0.70710678f / (fabsf(rawData[row - 1][(col + dx) * colours + c] - rawData[row + 1][(col - dx) * colours + c]) + eps);
+ wtdsum[c] += dirwt * (rawData[row - 1][(col + dx) * colours + c] + rawData[row + 1][(col - dx) * colours + c]);
norm[c] += dirwt;
}
}
// horizontal interpolation
if (!(bitmapBads.get(col - 1, row) || bitmapBads.get(col + 1, row))) {
- for (int c = 0; c < colors; ++c) {
- const float dirwt = 1.f / (fabsf(rawData[row][(col - 1) * colors + c] - rawData[row][(col + 1) * colors + c]) + eps);
- wtdsum[c] += dirwt * (rawData[row][(col - 1) * colors + c] + rawData[row][(col + 1) * colors + c]);
+ for (int c = 0; c < colours; ++c) {
+ const float dirwt = 1.f / (fabsf(rawData[row][(col - 1) * colours + c] - rawData[row][(col + 1) * colours + c]) + eps);
+ wtdsum[c] += dirwt * (rawData[row][(col - 1) * colours + c] + rawData[row][(col + 1) * colours + c]);
norm[c] += dirwt;
}
}
// vertical interpolation
if (!(bitmapBads.get(col, row - 1) || bitmapBads.get(col, row + 1))) {
- for (int c = 0; c < colors; ++c) {
- const float dirwt = 1.f / (fabsf(rawData[row - 1][col * colors + c] - rawData[row + 1][col * colors + c]) + eps);
- wtdsum[c] += dirwt * (rawData[row - 1][col * colors + c] + rawData[row + 1][col * colors + c]);
+ for (int c = 0; c < colours; ++c) {
+ const float dirwt = 1.f / (fabsf(rawData[row - 1][col * colours + c] - rawData[row + 1][col * colours + c]) + eps);
+ wtdsum[c] += dirwt * (rawData[row - 1][col * colours + c] + rawData[row + 1][col * colours + c]);
norm[c] += dirwt;
}
}
if (LIKELY(norm[0] > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelihood of this case is about 99.999%
- for (int c = 0; c < colors; ++c) {
- rawData[row][col * colors + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
+ for (int c = 0; c < colours; ++c) {
+ rawData[row][col * colours + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
}
counter++;
} else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens
int tot = 0;
- float sum[colors];
- for (int c = 0; c < colors; ++c) {
+ float sum[colours];
+ for (int c = 0; c < colours; ++c) {
sum[c] = 0.f;
}
@@ -260,8 +260,8 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
continue;
}
- for (int c = 0; c < colors; ++c) {
- sum[c] += rawData[row + dy][(col + dx) * colors + c];
+ for (int c = 0; c < colours; ++c) {
+ sum[c] += rawData[row + dy][(col + dx) * colours + c];
}
tot++;
@@ -269,8 +269,8 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
}
if (tot > 0) {
- for (int c = 0; c < colors; ++c) {
- rawData[row][col * colors + c] = sum[c] / tot;
+ for (int c = 0; c < colours; ++c) {
+ rawData[row][col * colours + c] = sum[c] / tot;
}
counter ++;
diff --git a/rtengine/camconst.json b/rtengine/camconst.json
index 4736e1cd5..4aae51a29 100644
--- a/rtengine/camconst.json
+++ b/rtengine/camconst.json
@@ -314,7 +314,7 @@ Camera constants:
{ // Quality A
"make_model": "Canon EOS 5D Mark II",
- "dcraw_matrix": [ 4716,603,-830,-7798,15474,2480,-1496,1937,6651 ],
+ "dcraw_matrix": [ 4716,603,-830,-7799,15474,2480,-1496,1937,6651 ],
"ranges": {
// black levels are read from raw masked pixels
// white levels are same for all colors, but vary on ISO
@@ -360,6 +360,11 @@ Camera constants:
}
},
+ { // Quality C
+ "make_model": "Canon EOS-1Ds",
+ "dcraw_matrix": [ 3925, 4060, -1739, -8973, 16552, 2545, -3287, 3945, 8243 ] // DNG
+ },
+
{ // Quality C, INTERMEDIATE ISO SAMPLES MISSING
"make_model": "Canon EOS-1D X Mark II",
"dcraw_matrix": [ 7596,-978,-967,-4808,12571,2503,-1398,2567,5752 ],
@@ -410,7 +415,7 @@ Camera constants:
{ // Quality A
"make_model": "Canon EOS 5D Mark III",
- "dcraw_matrix": [ 6722,-635,-963,-4287,12460,2028,-908,2162,5668 ],
+ "dcraw_matrix": [ 6722,-635,-963,-4287,12460,2028,-909,2162,5668 ],
"ranges": {
// black levels are read from raw masked pixels
// white levels are same for all colors, but vary on ISO
@@ -438,7 +443,7 @@ Camera constants:
{ // Quality B, some intermediate ISO samples missing, LENR samples missing so White Levels not properly indicated, some aperture scaling missing
"make_model": "Canon EOS 5D Mark IV",
"global_green_equilibration" : true,
- "dcraw_matrix": [ 6446,-366,-864,-4436,12204,2513,-952,2496,6348 ], // DNG_V9.7 D65
+ "dcraw_matrix": [ 6445,-366,-864,-4436,12204,2513,-953,2496,6348 ], // DNG v13.2
"raw_crop": [ 136, 42, 6740, 4500 ], // full size 6880x4544, official crop 148,54,6867,4533
"masked_areas": [ 54, 4, 4534, 132 ],
"ranges": {
@@ -526,10 +531,10 @@ Camera constants:
}
},
- { // Quality B, some missing scaling factors are safely guessed; assuming the RP is the same as the 6DII because they share sensors
+ { // Quality B, some missing scaling factors are safely guessed
"make_model": [ "Canon EOS 6D Mark II", "Canon EOS RP" ],
"dcraw_matrix": [ 6875,-970,-932,-4691,12459,2501,-874,1953,5809 ], // DNG v_9.12 D65
- "raw_crop": [ 120, 44, 6264, 4180 ], // fullraw size 6384x4224 useful 120,44,6264x4180
+ "raw_crop": [ 120, 44, 6264, 4180 ], // fullraw size 6384x4224 useful 120,44,6264x4180 // TODO: See EOS RP
// "raw_crop": [ 128, 52, 6248, 4168 ], // official jpeg crop 120+12,44+12,6240x4160
"masked_areas": [ 44, 4, 4220, 116 ],
"ranges": {
@@ -561,10 +566,44 @@ Camera constants:
}
},
+ { // Quality B, taken from 6D Mark II because identical sensor (different matrix)
+ "make_model": "Canon EOS RP",
+ "dcraw_matrix": [ 8608,-2097,-1178,-5425,13265,2383,-1149,2238,5680 ], // DNG v13.2
+ // Let dcraw handle crop, because camconst shouldn't override for diferent crop factors. See #6255
+ "masked_areas": [ 44, 4, 4220, 116 ], // Potential problem for different crop factor as well
+ "ranges": {
+ "white": [
+ { "iso": [ 50, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200 ], "levels": 16300 }, // typical 16383
+ { "iso": [ 4000, 6400, 8000, 12800 ], "levels": 16200 }, // typical 16383
+ { "iso": [ 16000, 25600 ], "levels": 16100 }, // typical 16383
+ { "iso": [ 160 ], "levels": 13000 }, // typical 13044
+ { "iso": [ 320, 640, 1250, 2500 ], "levels": 13250 }, // typical 13337
+ { "iso": [ 5000, 10000 ], "levels": 13100 }, // typical 13367
+ { "iso": [ 20000, 40000 ], "levels": 12900 }, // typical 13367
+ { "iso": [ 51200, 102400 ], "levels": 15900 } // typical 16383
+ ],
+ "white_max": 16383,
+ "aperture_scaling": [
+ // no scale factors known for f/1.0 (had no lenses to test with), but the
+ // ISO 160-320... 13044 white levels maxes out at "white_max" for f/1.2 and below anyway.
+ { "aperture": 1.2, "scale_factor": 1.130 }, // guessed
+ { "aperture": 1.4, "scale_factor": 1.100 }, // guessed
+ { "aperture": 1.6, "scale_factor": 1.080 }, // guessed
+ { "aperture": 1.8, "scale_factor": 1.060 }, // 13890/13044=1.065 11284/10512 = 1.073
+ { "aperture": 2.0, "scale_factor": 1.040 }, // 13602/13044=1.042 11151/10512 = 1.060
+ { "aperture": 2.2, "scale_factor": 1.030 }, // 10982/10512=1.045
+ { "aperture": 2.5, "scale_factor": 1.020 }, // 10840/10512 = 1.030
+ { "aperture": 2.8, "scale_factor": 1.010 }, // 13530/13367= 1.012 - 12225/12048 = 1.015
+ { "aperture": 3.2, "scale_factor": 1.005 }, // 12194/12048 = 1.012
+ { "aperture": 3.5, "scale_factor": 1.000 } // 12092/12048 = 1.004
+ ]
+ }
+ },
+
{ // Quality A, ISO and aperture WL data by CharlyW at RawTherapee forums, missing samples safely guessed
"make_model": "Canon EOS 7D",
"dcraw_matrix": [ 5962,-171,-732,-4189,12307,2099,-911,1981,6304 ], // Colin Walker
- //"dcraw_matrix": [ 6844,-996,-856,-3876,11761,2396,-593,1772,6198 ], // dcraw
+ //"dcraw_matrix": [ 6843,-996,-856,-3876,11761,2396,-593,1772,6198 ], // DNG v13.2
"ranges": {
"white": [
{ "iso": [ 100, 125 ], "levels": 13480 }, // typical 13584
@@ -618,7 +657,7 @@ Camera constants:
{ // Quality A - ISO and aperture WL data by Ilias at Avclub gr forums
"make_model": "Canon EOS 40D",
- "dcraw_matrix": [ 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 ],
+ "dcraw_matrix": [ 6070,-746,-856,-7652,15365,2442,-2026,2553,7314 ], // DNG v13.2
"raw_crop": [ 30, 18, 3908, 2602 ],
"masked_areas": [ 20, 2, 2616, 20 ],
"ranges": {
@@ -647,7 +686,7 @@ Camera constants:
{ // Quality A, ISO and aperture WL data by Ayshih at Magic Lantern forums
"make_model": "Canon EOS 50D",
- "dcraw_matrix": [ 4920,616,-593,-6493,13964,2784,-1774,3178,7005 ],
+ "dcraw_matrix": [ 4920,616,-593,-6494,13965,2784,-1774,3178,7004 ], // DNG v13.2
"ranges": {
"white": [
{ "iso": [ 100, 125 ], "levels": 13300 }, // typical 13432
@@ -697,7 +736,8 @@ Camera constants:
{ // Quality A, ISO and aperture WL data by Shalrath at RawTherapee forums
"make_model": "Canon EOS 60D",
- "dcraw_matrix": [ 6719,-994,-925,-4408,12426,2211,-887,2129,6051 ],
+ "dcraw_matrix": [ 6719,-994,-925,-4408,12426,2211,-887,2129,6051 ], // Origin unknown
+ //"dcraw_matrix": [ 6941, -1164, -857, -3825, 11597, 2534, -416, 1540, 6039 ], // DNG v13.2
"ranges": {
"white": [
{ "iso": [ 100, 125 ], "levels": 13480 }, // typical 13583
@@ -750,7 +790,7 @@ Camera constants:
{ // Quality B, White Levels not properly indicated, aperture scaling..missing scaling factors are guessed
"make_model": "Canon EOS 80D",
- "dcraw_matrix": [ 7457,-671,-937,-4849,12495,2643,-1213,2354,5492 ], // DNG_V9.5 D65
+ "dcraw_matrix": [ 7457,-672,-937,-4849,12495,2643,-1213,2354,5492 ], // DNG v13.2
"raw_crop": [ 264, 34, 6024, 4022 ], // full size 6288x4056, official crop 276,46,6275,4045
"masked_areas": [ 40, 96, 4000, 260 ],
"ranges": {
@@ -815,7 +855,8 @@ Camera constants:
// Canon mid-range DSLRs (Rebels)
{ // Quality C
- "make_model": [ "Canon EOS 400D DIGITAL" ],
+ "make_model": "Canon EOS 400D DIGITAL",
+ "dcraw_matrix": [ 7054, -1501, -990, -8156, 15544, 2812, -1278, 1414, 7796 ],
"ranges": {
"white": 4056
}
@@ -930,7 +971,7 @@ Camera constants:
{ // Quality C, white levels and aperture scaling copied from Canon EOS77d
"make_model": [ "Canon EOS Rebel T7i", "Canon EOS 800D", "Canon EOS Kiss X9i" ],
- "dcraw_matrix": [ 6970,-512,-968,-4425,12161,2553,-739,1982,5601 ], // DNG_V9.10.1 D65
+ "dcraw_matrix": [ 6969,-512,-968,-4425,12161,2553,-739,1981,5601 ], // DNG v13.2
"raw_crop": [ 264, 36, 6024, 4020 ], // full size 6288x4056, official crop 276,48,6275,4047
"masked_areas": [ 40, 96, 4000, 260 ],
"ranges": {
@@ -1061,7 +1102,7 @@ Camera constants:
{ // Quality C, inconsistent WL per ISO, missing scaling factors
"make_model": "Canon EOS M10",
- "dcraw_matrix": [ 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 ], // DNGv9.3 D65
+ "dcraw_matrix": [ 6400,-480,-888,-5294,13415,2047,-1296,2203,6137 ], // DNG v13.2
"ranges": {
"white": [
{ "iso": [ 100, 125, 160, 320, 500, 2000, 4000, 6400 ], "levels": 16300 }, // typical 16383
@@ -1170,7 +1211,7 @@ Camera constants:
{ // Quality C
"make_model": "Canon EOS R5",
"dcraw_matrix" : [9766, -2953, -1254, -4276, 12116, 2433, -437, 1336, 5131],
- "raw_crop" : [ 124, 92, 8220, 5486 ],
+ "raw_crop" : [ 128, 96, 8224, 5490 ],
"masked_areas" : [ 94, 20, 5578, 122 ],
"ranges" : { "white" : 16382 }
},
@@ -1230,7 +1271,8 @@ Camera constants:
{ // Quality B
"make_model": "Canon PowerShot G3 X",
- "dcraw_matrix": [ 9701,-3857,-921,-3149,11537,1817,-786,1817,5147 ], // DNG_V9.1.1 D65
+ //"dcraw_matrix": [ 9701,-3857,-921,-3149,11537,1817,-786,1817,5147 ], // DNG_V9.1.1 D65
+ "dcraw_matrix": [ 6941, -1164, -857, -3825, 11597, 2534, -416, 1540, 6039 ], // DNG v13.2 - looks worse
"raw_crop": [ 128, 36, 5480, 3656 ], // Default official 3/2 frame 5472X3648, 4pix borders, Left Border 132-4, Top border 40-4
"masked_areas": [ 40, 4, 3680, 76 ],
"ranges": { "white": 16300 }
@@ -1238,7 +1280,7 @@ Camera constants:
{ // Quality B,
"make_model": "Canon PowerShot G7 X",
- "dcraw_matrix": [ 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 ], // DNG_V8.7 D65
+ "dcraw_matrix": [ 9602,-3823,-937,-2984,11495,1675,-407,1414,5049 ], // DNG v13.2
//"raw_crop": [ 116, 24, 5504, 3680 ], // Sensor size 5632x3710. Largest useful frame 120-5616X28-3702 = 5504x3682, 4pix RTborders, Left Border 120-4, Top border 28-4
"raw_crop": [ 128, 36, 5480, 3656 ], // Default official 3/2 frame 5472X3648, 4pix borders, Left Border 132-4, Top border 40-4
"masked_areas": [ 40, 4, 3680, 76 ],
@@ -1246,17 +1288,27 @@ Camera constants:
},
{ // Quality B,
- "make_model": [ "Canon PowerShot G5 X", "Canon PowerShot G9 X", "Canon PowerShot G7 X Mark II", "Canon PowerShot G9 X Mark II" ],
- "dcraw_matrix": [ 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 ], // DNG_V8.7 D65
+ "make_model": [ "Canon PowerShot G5 X", "Canon PowerShot G7 X Mark II" ],
+ "dcraw_matrix": [ 9602,-3823,-937,-2984,11495,1675,-407,1414,5049 ], // DNG v13.2
//"raw_crop": [ 116, 24, 5504, 3680 ], // Sensor size 5632x3710. Largest useful frame 120-5616X28-3702 = 5504x3682, 4pix RTborders, Left Border 120-4, Top border 28-4
"raw_crop": [ 128, 36, 5480, 3656 ], // Default official 3/2 frame 5472X3648, 4pix borders, Left Border 132-4, Top border 40-4
"masked_areas": [ 40, 4, 3680, 76 ],
"ranges": { "white": 15500 } // some sporadic samples are clipped lower than 16383, one ISO125 sample at 15500
},
+ { // Quality B, separated entry from above due to alternate color matrix (effect unsure)
+ "make_model": "Canon PowerShot G9 X Mark II",
+ "dcraw_matrix": [ 10056, -4131, -944, -2576, 11143, 1625, -239, 1293, 5179 ], // DNG v13.2
+ //"dcraw_matrix": [ 9602,-3823,-937,-2984,11495,1675,-407,1414,5049 ], // DNG v8.7
+ "raw_crop": [ 128, 36, 5480, 3656 ],
+ "masked_areas": [ 40, 4, 3680, 76 ],
+ "ranges": { "white": 15500 }
+ },
+
{ // Quality A, changes for raw crop which is wrong (larger) in dcraw
"make_model": "Canon PowerShot S120",
- "dcraw_matrix": [ 6961, -1685, -695, -4625, 12945, 1836, -1114, 2152, 5518 ], // ColorMatrix2 using illuminant D65 from Adobe DNG Converter 12.2
+ "dcraw_matrix": [ 6941, -1164, -857, -3825, 11597, 2534, -416, 1540, 6039 ], // Adobe DNG v13.2
+ //"dcraw_matrix": [ 6961, -1685, -695, -4625, 12945, 1836, -1114, 2152, 5518 ], // Adobe DNG v12.2
"raw_crop": [ 120, 30, 4024, 3030 ],
"masked_areas": [ 32, 2, 3028, 80 ],
"ranges": { "white": 4050 }
@@ -1264,12 +1316,13 @@ Camera constants:
{ // Quality C
"make_model": "Canon PowerShot SX50 HS",
+ "dcraw_matrix": [ 12432, -4753, -1247, -2110, 10691, 1629, -412, 1623, 4926 ],
"ranges": { "white": 4050 }
},
{ // Quality B
"make_model": "Canon PowerShot SX60 HS",
- "dcraw_matrix": [ 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 ], // DNG_V8.7 D65
+ "dcraw_matrix": [ 13161,-5451,-1344,-1989,10653,1531,-47,1271,4955 ], // DNG v13.2
"raw_crop": [ 120, 34, 4616, 3464 ], // full raw 4768x3516, Usable 96,16,4672,3498 - Canon official 4608x3456 left 124 top 38,
"masked_areas": [ 20, 2, 3480, 80 ],
"ranges": { "white": 4050 } // nominal 4080-4093
@@ -1308,8 +1361,8 @@ Camera constants:
},
{ // Quality C
- "make_model": "FUJIFILM GFX 100",
- "dcraw_matrix" : [16212, -8423, -1583, -4336, 12583, 1937, -195, 726, 6199], // taken from ART
+ "make_model": [ "FUJIFILM GFX 100", "FUJIFILM GFX100S" ],
+ "dcraw_matrix" : [ 16212, -8423, -1583, -4336, 12583, 1937, -195, 726, 6199 ], // taken from ART
"raw_crop": [ 0, 2, 11664, 8734 ]
},
@@ -1380,6 +1433,11 @@ Camera constants:
"ranges": { "white": 4050 }
},
+ { // Quality C
+ "make_model": "Fujifilm X-A20",
+ "ranges": { "white": 3838 }
+ },
+
{ // Quality B
"make_model": [ "FUJIFILM X-T10", "FUJIFILM X-E2" ],
"dcraw_matrix": [ 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 ], // DNG D65
@@ -1425,6 +1483,7 @@ Camera constants:
{ // Quality C
"make_model": "FUJIFILM X-E4",
+ "dcraw_matrix": [ 13426, -6334, -1177, -4244, 12136, 2371, -580, 1303, 5980 ], // DNG v13.2
"raw_crop": [ 0, 5, 6252, 4126 ]
},
@@ -1469,10 +1528,16 @@ Camera constants:
"dcraw_matrix": [ 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 ], // DNG_v8.8 D65
"ranges": { "white": 4040 }
},
+
+ { // Quality C, Leica C-Lux names can differ?
+ "make_model" : [ "LEICA C-LUX", "LEICA CAM-DC25" ],
+ "dcraw_matrix" : [7790, -2736, -755, -3452, 11870, 1769, -628, 1647, 4898]
+ },
- { // Quality B, Matrix from ART
+ { // Quality B
"make_model" : "LEICA D-LUX 7",
- "dcraw_matrix" : [11577, -4230, -1106, -3967, 12211, 1957, -758, 1762, 5610]
+ "dcraw_matrix" : [11577, -4230, -1106, -3967, 12211, 1957, -758, 1762, 5610] // DNG
+ // "dcraw_matrix" : [8585, -3127, -833, -4005, 12250, 1953, -650, 1494, 4862] // DNG alternate
},
{ // Quality B, Matrix from Adobe's dcp D65 instead of the internal in Leica's DNG
@@ -1481,6 +1546,12 @@ Camera constants:
"raw_crop": [ 4, 4, -4, -4 ] // full raw 6016x4016, Official 6000x4000
},
+ { // Quality C
+ "make_model": "LEICA M8",
+ "dcraw_matrix": [ 7675, -2196, -305, -5860, 14119, 1855, -2425, 4006, 6578 ] // DNG
+ // Do not set white level, probably special handling by dcraw (see #6237)
+ },
+
{ // Quality C
"make_model": "LEICA Q2",
"raw_crop": [ 0, 0, 8392, 5624 ]
@@ -1502,9 +1573,9 @@ Camera constants:
"raw_crop": [ 0, 2, 6024, 4042 ] // 2 rows at top and 4 rows at bottom are black
},
- { // Quality B, Matrix from ART
- "make_model" : "LEICA V-LUX 5",
- "dcraw_matrix" : [9803, -4185, -992, -4066, 12578, 1628, -838, 1824, 5288]
+ { // Quality C
+ "make_model" : ["LEICA V-LUX 5","Panasonic DC-FZ1000M2"],
+ "dcraw_matrix" : [9803, -4185, -992, -4066, 12578, 1628, -838, 1824, 5288] // DNG
},
{ // Quality C
@@ -1522,15 +1593,21 @@ Camera constants:
},
{ // Quality A
- "make_model": [ "Nikon 1 V3", "Nikon 1 J4" ], // Same format
+ "make_model": "Nikon 1 V3",
"dcraw_matrix": [ 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 ], // matrix from DNG_v8.5 d65
//"dcraw_matrix": [ 5306,-1066,-469,-3865,11189,3076,-399,1341,5120 ], // matrix dXo D50,
"ranges": { "white": 4080 } // Black is auto extracted from Exif, lower WL to 4080 from 4095 due to some non linearity detected at raw highlights
},
+ { // Quality A
+ "make_model": "Nikon 1 J4", // Similar to V3, different matrix
+ "dcraw_matrix": [ 6588, -1305, -693, -3277, 10987, 2634, -355, 2016, 5106 ], // DNG v13.2
+ "ranges": { "white": 4080 }
+ },
+
{ // Quality B
"make_model": "Nikon 1 J5", //
- "dcraw_matrix": [ 7520,-2518,-645,-3844,12102,1945,-913,2249,6835 ], // DNG_v9.1 D65
+ "dcraw_matrix": [ 7520,-2519,-645,-3844,12102,1945,-914,2249,6835 ], // DNG v13.2
//"dcraw_matrix": [ 7651,-2102,-751,-3299,11101,1651,-1011,2242,5770 ], // matrix from ICC converted to dcraw format XYZ on ImagingResource still life sample
"ranges": {
"white": [
@@ -1546,6 +1623,16 @@ Camera constants:
"dcraw_matrix": [ 6612,-1342,-618,-3338,11055,2623,-174,1792,5075 ], // matrix from DNG_v8.5 d65
"ranges": { "white": 4080 } // BL autodetected from Exif
},
+
+ { // Quality C
+ "make_model": "Nikon D2Hs",
+ "dcraw_matrix": [ 5733, -911, -629, -7967, 15987, 2055, -3050, 4013, 7048 ] // DNG
+ },
+
+ { // Quality C
+ "make_model": "Nikon D2Xs",
+ "dcraw_matrix": [ 10230, -2768, -1255, -8302, 15900, 2551, -797, 680, 7148 ] // DNG
+ },
// For all Nikon DSLRs which have multiple bitdepth options (14- and 12-bit) we define the 14-bit value and RT adapts it to 12-bit
// when a 12-bit bitdepth is detected (WL12 = WL14*4095/16383)
@@ -1553,7 +1640,7 @@ Camera constants:
{ // Quality B, samples by Johan Thor at RT.Issues, measures at long exposures with LENR are missing
// but a safety margin is included - aperture scaling makes no significant difference
"make_model": "Nikon D3S",
- "dcraw_matrix": [ 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 ], // dcp d65
+ "dcraw_matrix": [ 8828,-2406,-694,-4874,12603,2541,-660,1509,7586 ], // DNG v13.2
"ranges": {
"white": [
{ "iso": [ 100, 125, 160, 200, 250, 320, 400, 500 ], "levels": 15520 }, // typical G1,G2 15520-15800 R,B 16383
@@ -1588,6 +1675,7 @@ Camera constants:
{ // Quality B, lacks aperture and ISO scaling, known to exist, but little to gain as the levels are so close to white_max
"make_model": "Nikon D7000",
"dcraw_matrix": [ 7530,-1942,-255,-4318,11390,3362,-926,1694,7649 ], // matrix provided by Tanveer(tsk1979)
+ //"dcraw_matrix": [ 8198, -2239, -725, -4871, 12388, 2798, -1043, 2050, 7181 ], // DNG v13.2
"ranges": {
// measured at ISO 100. ISO differences not measured, but known to exist
"white": [ 16300, 15700, 16300 ], // typical R 16383, G 15778, B 16383
@@ -1598,7 +1686,7 @@ Camera constants:
{ // Quality B
"make_model": "NIKON COOLPIX A",
- "dcraw_matrix": [ 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 ], // dng_d65
+ "dcraw_matrix": [ 8198,-2239,-725,-4871,12388,2798,-1043,2050,7181 ], // DNG v13.2
"ranges": {
"white": [
{ "iso": [ 100, 125, 160, 200, 250, 320, 400, 500, 640, 800 ], "levels": [ 16300, 15700, 16300 ] }, // typical G1,G2 15760-15800 R,B 16383
@@ -1625,7 +1713,7 @@ Camera constants:
// Sensor shows some non-uniformity, need other sample to verify
// There seems to be some aperture scaling, but insufficient data to accurately determine
"make_model": "Nikon COOLPIX P950",
- "dcraw_matrix": [ 13307,-5641,-1290,-2048,10581,1689,-64,1222,5176 ], // ColorMatrix2 from Adobe DNG Converter 13.1
+ "dcraw_matrix": [ 13307,-5642,-1290,-2048,10581,1689,-64,1222,5175 ], // DNG v13.2
"ranges": {
"black": 200,
"white": [
@@ -1639,16 +1727,26 @@ Camera constants:
{ // Quality B, no LENR samples
"make_model": "Nikon D5",
- "dcraw_matrix": [ 9200,-3522,-992,-5755,13803,2117,-753,1486,6338 ], // adobe dng_v9.5 d65
+ "dcraw_matrix": [ 9200,-3522,-992,-5755,13803,2117,-754,1486,6338 ], // DNG v13.2
"ranges": { "black": 0, "white": 16300 } // WL typical 16383 set to 16300 for safety
},
+ { // Quality C
+ "make_model": "Nikon D6",
+ "dcraw_matrix": [ 9028, -3423, -1035, -6321, 14265, 2217, -1013, 1683, 6928 ] // DNG
+ },
+
{ // Quality B
"make_model": "Nikon D3400",
"dcraw_matrix": [ 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 ], // adobe dng_v9.7 d65
"ranges": { "white": 16300 } // WL value is for 14-bit files, RT auto adapts it for 12-bit files. WL typical 16383 set to 16300 for safety
},
+ { // Quality C
+ "make_model": "Nikon D3500",
+ "dcraw_matrix": [ 8821, -2938, -785, -4178, 12142, 2287, -824, 1651, 6860 ] // DNG
+ },
+
{ // Quality B
"make_model": "Nikon D5300",
"dcraw_matrix": [ 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 ], // adobe dng_v8.8 d65
@@ -1672,6 +1770,12 @@ Camera constants:
"dcraw_matrix": [ 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 ], // adobe dng_v9.12 d65
"ranges": { "white": 16300 } // WL value is for 14-bit files, RT auto adapts it for 12-bit files. WL typical 16383 set to 16300 for safety,
},
+
+ { // Quality C
+ "make_model": "Nikon D300s",
+ "dcraw_matrix": [ 9030, -1992, -716, -8465, 16302, 2256, -2689, 3217, 8068 ] // DNG
+ //"dcraw_matrix": [ 9000, -1966, -711, -7030, 14976, 2185, -2354, 2959, 7990 ] // DNG alternate
+ },
{ // Quality B, samples by joachip at RT forums, are measures at long exposures with LongExposureNoiseReduction
// aperture scaling known to exist, but little to gain as the levels are so close to white_max
@@ -1708,7 +1812,7 @@ Camera constants:
{ // Quality B, data from RusselCottrell at RT forums. sensor is not uniform
"make_model": "Nikon D700",
- "dcraw_matrix": [ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 ],
+ "dcraw_matrix": [ 8139,-2171,-664,-8748,16541,2296,-1924,2008,8093 ], // DNG v13.2
//"dcraw_matrix": [ 9336,-3405,14,-7321,14779,2764,-914,1171,8248 ], // illuminant A
"ranges": { "white": [ 15500, 15500, 15500 ] }
// Non linearities start at 15500 (hi ISOs) 15850 (low ISOs) with long exposures (>2sec) and LENR ON .. nominal 15892
@@ -1717,9 +1821,14 @@ Camera constants:
{ // Quality B,
"make_model": "Nikon D750",
- "dcraw_matrix": [ 9020,-2890,-715,-4535,12436,2348,-934,1919,7086 ], // adobe dcp d65 DNGv8.7
+ "dcraw_matrix": [ 9020,-2890,-715,-4535,12436,2348,-934,1918,7086 ], // DNG v13.2
"ranges": { "white": 16300 } // WL values for 14-bit files, RT auto adapts it for 12-bit files. TypicalWL 16383 set to 16300 for safety
},
+
+ { // Quality C
+ "make_model": "Nikon D780",
+ "dcraw_matrix": [ 9943, -3270, -839, -5323, 13269, 2259, -1198, 2083, 7557 ] // DNG
+ },
{ // Quality B, data from RussellCottrell at RT forums. Largest aperture scale factor is 1.013, about 1/50th of a stop
"make_model": [ "Nikon D800", "Nikon D800E" ],
@@ -1739,10 +1848,15 @@ Camera constants:
"raw_crop": [ 0, 0, 7380, 4928 ], // Official raw crop 7380x4928,
"ranges": { "white": 16300 } // WL values for 14-bit files, RT auto adapts it for 12-bit files. Typical WL at 16383
},
+
+ { // Quality C
+ "make_model": "Nikon D810A",
+ "dcraw_matrix": [ 11973, -5685, -888, -1965, 10326, 1901, -115, 1123, 7169 ] // DNG
+ },
{ // Quality A, Samples by zorgtool at RT forums
"make_model": "Nikon D850",
- "dcraw_matrix": [ 10405,-3755,-1270,-5461,13787,1793,-1040,2015,6785 ], // DNGv9.12.1 d65
+ "dcraw_matrix": [ 10405,-3755,-1270,-5461,13787,1792,-1040,2015,6785 ], // DNG v13.2
"ranges": {
"white": [
{ "iso": [ 64, 80, 100, 125, 160, 200, 250, 320 ], "levels": [ 16250, 16050, 16250 ] }, // R,B 16383 G1,G2 16145-16155
@@ -1772,29 +1886,44 @@ Camera constants:
}
},
+ { // Quality C
+ "make_model": "Nikon D70s",
+ "dcraw_matrix": [ 7732, -2421, -789, -8238, 15883, 2498, -859, 783, 7330 ] // DNG
+ },
+
{ // Quality B
"make_model": "Nikon D80",
- "dcraw_matrix": [ 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 ], // Dcraw.c d65
+ "dcraw_matrix": [ 8628,-2410,-883,-9055,16940,2171,-1491,1363,8520 ], // DNG v13.2
"ranges": { "white": 3980 } // 12-bit files.
},
{ // Quality C, only color matrix and PDAF lines info
"make_model" : "Nikon Z 7",
- "dcraw_matrix" : [10405,-3755,-1270,-5461,13787,1793,-1040,2015,6785], // Adobe DNG Converter 11.0 ColorMatrix2
+ "dcraw_matrix" : [10405,-3755,-1270,-5461,13787,1792,-1040,2015,6785], // DNG v13.2
"pdaf_pattern" : [0, 12],
"pdaf_offset" : 29
},
+
+ { // Quality C
+ "make_model" : "Nikon Z 7_2",
+ "dcraw_matrix" : [13705, -6004, -1401, -5464, 13568, 2062, -940, 1706, 7618] // DNG
+ },
{ // Quality C, only color matrix and PDAF lines info
"make_model" : "Nikon Z 6",
- "dcraw_matrix" : [8210, -2534, -683, -5355, 13338, 2212, -1143, 1929, 6464], // Adobe DNG Converter 11.1 Beta ColorMatrix2
+ "dcraw_matrix" : [8210, -2534, -683, -5355, 13338, 2212, -1143, 1928, 6464], // DNG v13.2
"pdaf_pattern" : [0, 12],
"pdaf_offset" : 32
},
+
+ { // Quality C
+ "make_model" : "Nikon Z 6_2",
+ "dcraw_matrix" : [9943, -3270, -839, -5323, 13269, 2259, -1198, 2083, 7557] // DNG
+ },
- { // Quality C, only dcraw looted from ART commit ad88c7d97
+ { // Quality C
"make_model" : "NIKON Z 5",
- "dcraw_matrix" : [8695, -2558, -648, -5015, 12711, 2575, -1279, 2215, 7514]
+ "dcraw_matrix" : [8695, -2559, -648, -5015, 12710, 2575, -1280, 2215, 7514] // DNG v13.2
},
{ // Quality A, white levels and PDAF lines measured by Yann Leprince #5851
@@ -1859,6 +1988,11 @@ Camera constants:
}
},
+ { // Quality C
+ "make_model": "OLYMPUS E-M5MarkIII",
+ "dcraw_matrix": [ 11896, -5110, -1076, -3181, 11378, 2048, -519, 1224, 5165 ] // DNG
+ },
+
{ // Quality B, 20Mp and 80Mp raw frames
"make_model": "OLYMPUS PEN-F",
"dcraw_matrix": [ 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 ], // dng_v9.5 D65
@@ -1874,8 +2008,7 @@ Camera constants:
{ // Quality B, 20Mp and 80Mp raw frames,
"make_model": "OLYMPUS E-M1MarkII",
- "dcraw_matrix": [ 9383,-3170,-763,-2457,10702,2020,-384,1236,5552 ], // dng_V9.10 D65
- //"dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 ], // beta, dng_v9.8 D65
+ "dcraw_matrix": [ 9383,-3170,-764,-2457,10702,2020,-384,1236,5552 ], // dng_V9.10 D65
"raw_crop": [ 8, 8, -16, -8 ], // full raw 5240X3912, jpeg top12,left12,5184x3888, full hires 10400X7792, jpeg crop 8,8,10368x7776
"ranges": {
"white": [
@@ -1893,42 +2026,60 @@ Camera constants:
"dcraw_matrix": [ 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 ], // dng d65
"ranges": { "white": 4080 } // nominal 4095-4094, spread with some settings as long exposure
},
+
+ { // Quality C
+ "make_model": "OLYMPUS E-M1MarkIII",
+ "dcraw_matrix": [ 11896, -5110, -1076, -3181, 11378, 2048, -519, 1224, 5165 ] // DNG
+ },
{ // Quality C, only raw crop for highres mode
"make_model": "OLYMPUS E-M1X",
+ "dcraw_matrix": [ 11896, -5110, -1076, -3181, 11378, 2048, -519, 1224, 5165 ], // DNG v11.2
"raw_crop": [ 0, 0, 10388, 0 ] // Highres mode largest valid, full 80Mp 10400X7792, works also for non highres mode because larger width will be ignored
},
{ // Quality B, crop correction
"make_model": [ "OLYMPUS E-M10", "OLYMPUS E-M10MarkII", "OLYMPUS E-M10 Mark III" ],
- "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 ],
+ "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-628,1427,5437 ], // DNG v13.2
"raw_crop": [ 0, 0, 4624, 3472 ], // largest valid - full frame is 4640x3472
//"raw_crop": [ 4, 4, 4616, 3464 ], // olympus jpeg crop 8, 8, 4608, 3456
"ranges": { "white": 4080 }
},
+
+ { // Quality C
+ "make_model": "OLYMPUS E-M10MarkIV",
+ "dcraw_matrix": [ 9476, -3182, -765, -2613, 10958, 1893, -449, 1315, 5268 ],
+ "range": { "white": 4000, "black": 254 }
+ },
{ // Quality A, white level correction
"make_model": "OLYMPUS E-PM2",
"global_green_equilibration" : true,
- "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 ],
+ "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-628,1427,5437 ], // DNG v13.2
"ranges": { "white": 4040 } // nominal 4056
},
{ // Quality C
"make_model": [ "OLYMPUS E-PL9" ],
+ "dcraw_matrix": [ 8380, -2630, -639, -2887, 10725, 2496, -628, 1427, 5437 ],
"ranges": { "white": 4080 } // nominal 4093
},
+
+ { // Quality C
+ "make_model": [ "OLYMPUS E-PL10" ],
+ "dcraw_matrix": [ 9197, -3190, -659, -2606, 10830, 2039, -458, 1250, 5457 ]
+ },
{ // Quality B, with long exposure noise reduction White Level gets WL-BL = around 256_12-bit levels less
"make_model": [ "OLYMPUS E-PL7", "OLYMPUS E-PL8" ],
"global_green_equilibration" : true,
- "dcraw_matrix": [ 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 ], // DNG_v9.8 D65
+ "dcraw_matrix": [ 9197,-3190,-659,-2606,10830,2039,-458,1250,5457 ], // DNG v13.2
"ranges": { "white": 4080 } // nominal 4093
},
{ // Quality B, per ISO WL measures missing
"make_model": [ "OLYMPUS SH-2", "Olympus SH-3" ],
- "dcraw_matrix": [ 10156,-3425,-1077,-2611,11177,1624,-385,1592,5080 ], // DNG_V9.1 D65
+ "dcraw_matrix": [ 10156,-3426,-1077,-2611,11177,1624,-385,1592,5080 ], // DNG v13.2
"ranges": { "white": 4050 } // safe for worst case detected, nominal is 4093
},
@@ -1939,9 +2090,9 @@ Camera constants:
"ranges": { "white": 4050 } // safe for worst case detected, nominal is 4093
},
- { // Quality C, only raw crop
+ { // Quality B
"make_model": "OLYMPUS TG-6",
- "dcraw_matrix" : [10899, -3832, -1082, -2112, 10736, 1575, -267, 1452, 5269], // taken from ART
+ "dcraw_matrix" : [10899, -3833, -1082, -2112, 10736, 1575, -267, 1452, 5269], // DNG v13.2
"raw_crop": [ 0, 0, -24, 0 ] // 24 pixels at right are garbage
},
@@ -1950,16 +2101,22 @@ Camera constants:
"global_green_equilibration" : true
},
- { // Quality X
+ { // Quality C
+ "make_model": ["OLYMPUS STYLUS1", "OLYMPUS STYLUS1,1s"],
+ "dcraw_matrix" : [8360, -2420, -880, -3928, 12353, 1739, -1381, 2416, 5173] // DNG
+ },
+
+ { // Quality B
"make_model": [ "Panasonic DC-LX100M2" ],
- "dcraw_matrix": [ 11577, -4230, -1106, -3967, 12211, 1957, -758, 1762, 5610 ], // Adobe DNG Converter 11.0 ColorMatrix2
+ "dcraw_matrix": [ 11577, -4230, -1106, -3967, 12211, 1957, -759, 1762, 5610 ], // DNG v13.2
+ //"dcraw_matrix": [ 8585, -3127, -833, -4005, 12250, 1953, -650, 1494, 4862 ], // DNG v13.2 alternate
"raw_crop": [ 0, 0, 0, 0 ],
"ranges": { "black": 15 }
},
{ // Quality C, proper ISO 100-125-160 samples missing, pixelshift files have no black offset etc. #4574
"make_model": [ "Panasonic DC-G9" ],
- "dcraw_matrix": [ 7685, -2375, -634, -3687, 11700, 2249, -748, 1546, 5111 ], // Adobe DNG Converter 10.3 ColorMatrix2
+ "dcraw_matrix": [ 7685, -2375, -634, -3688, 11700, 2249, -748, 1545, 5111 ], // DNG v13.2
"ranges": {
"black": 15, // 15 is BL offset. dcraw/RT reads the base black from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -1970,13 +2127,21 @@ Camera constants:
}
},
+ { // Quality C
+ "make_model": [ "Panasonic DC-G90", "Panasonic DC-G95", "Panasonic DC-G99" ],
+ "dcraw_matrix": [ 9657, -3963, -748, -3361, 11378, 2258, -568, 1414, 5158 ] // DNG
+ },
+
+ { // Quality C
+ "make_model": [ "Panasonic DC-G100", "Panasonic DC-G110" ],
+ "dcraw_matrix": [ 8370, -2869, -710, -3389, 11372, 2298, -640, 1598, 4887 ] // DNG
+ },
+
{ // Quality C, only color matrix
"make_model" : "Panasonic DC-GF10",
- "dcraw_matrix": [ 7610, -2780, -576, -4614, 12195, 2733, -1375, 2393, 6490 ], // ColorMatrix2 from Adobe DNG Converter 11.3
+ "dcraw_matrix": [ 7610, -2781, -576, -4614, 12195, 2733, -1375, 2393, 6490 ], // DNG v13.2
"raw_crop": [ 0, 0, 4600, 0 ], // SensorWidth=4816 SensorHeight=3464. Width=4600 to match DNG.
- "ranges": {
- "black": 15
- }
+ "ranges": { "black": 15 }
},
{ // Quality B, CameraPhone, some samples are missing but has the same sensor as FZ1000 ..
@@ -1994,7 +2159,7 @@ Camera constants:
{ // Quality B
"make_model": [ "Panasonic DC-FZ80", "Panasonic DC-FZ81", "Panasonic DC-FZ82", "Panasonic DC-FZ83" ],
- "dcraw_matrix": [ 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 ], // DNGv9.10.1 D65
+ "dcraw_matrix": [ 11532, -4324, -1066, -2375, 10847, 1749, -564, 1699, 4351 ], // DNG v13.2
"raw_crop": [ 0, 6, -8, -2 ], // fullraw4/3 5040x3688 official 8,8,4904,3680 = 4896X3672. Dcraw 0,0,4912,3688 RT's frame gets smaller than dcraw but works better with auto distortion
"ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset
},
@@ -2013,7 +2178,7 @@ Camera constants:
{ // Quality A, samples by helices at RT forums
"make_model": [ "Panasonic DMC-FZ1000", "Leica V-LUX (Typ 114)" ],
- "dcraw_matrix": [ 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 ], // dcp_v8.6 d65
+ "dcraw_matrix": [ 7830,-2696,-764,-3325,11667,1865,-641,1712,4824 ], // DNG v13.2
"ranges": {
"black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -2026,7 +2191,7 @@ Camera constants:
{ // Quality B,
"make_model": [ "Panasonic DMC-FZ2500", "Panasonic DMC-FZ2000", "Panasonic DMC-FZH1" ],
- "dcraw_matrix": [ 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 ], // dcp_v9.8 d65
+ "dcraw_matrix": [ 7386,-2443,-743,-3437,11863,1757,-608,1660,4766 ], // DNG v13.2
"ranges": {
"black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -2071,6 +2236,11 @@ Camera constants:
"ranges": { "black": 14, "white": 4050 } // 12+1+1 is BL offset
},
+ { // Quality C
+ "make_model": [ "Panasonic DMC-ZS60", "Panasonic DMC-TZ80", "Panasonic DMC-TZ85" ],
+ "dcraw_matrix": [ 8550, -2908, -842, -3195, 11529, 1881, -338, 1603, 4631 ] // DNG
+ },
+
{ // Quality A, samples by Hombre
"make_model": [ "Panasonic DC-ZS70", "Panasonic DC-TZ90", "Panasonic DC-TZ91", "Panasonic DC-TZ92", "Panasonic DC-TZ93" ],
"dcraw_matrix": [ 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 ], // DNG_V9.10.1 D65
@@ -2078,6 +2248,12 @@ Camera constants:
"ranges": { "black": 16, "white": 4050 } // 12+3+1 is BL offset
},
+ { // Quality C
+ "make_model": [ "Panasonic DC-ZS80", "Panasonic DC-TZ95" ],
+ "dcraw_matrix": [ 12194, -5340, -1329, -3035, 11394, 1858, -50, 1418, 5219 ] // DNG
+ },
+
+
// Panasonic DMC-FZ150,G10,G1,G2,G3,G5,GF1,GF2,GF3 are included as overwrites of the same items of rawimage.cc to test the dcraw9.21 patch
{ // Quality A, Replicated from rawimage.cc
@@ -2190,7 +2366,7 @@ Camera constants:
{ // Quality B, some ISO WLevels are safely guessed
"make_model": "Panasonic DMC-GH4",
- "dcraw_matrix": [ 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 ], // dng_v8.5 d65
+ "dcraw_matrix": [ 7122,-2108,-512,-3155,11201,2231,-541,1423,5044 ], // DNG v13.2
"ranges": {
"black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -2203,7 +2379,7 @@ Camera constants:
{ // Quality C
"make_model": "Panasonic DC-GH5",
- "dcraw_matrix": [ 7641,-2336,-605,-3218,11299,2187,-485,1338,5121 ], // DNG_v9.9 D65
+ "dcraw_matrix": [ 7641,-2336,-605,-3218,11298,2187,-485,1338,5121 ], // DNG v13.2
"ranges": {
"black": 15, // 16 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -2254,7 +2430,7 @@ Camera constants:
{ // Quality A
"make_model": [ "Panasonic DMC-G7", "Panasonic DMC-G70" ],
- "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG_v9.1 D65
+ "dcraw_matrix": [ 7610,-2781,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG v13.2
"ranges": {
"black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -2267,7 +2443,7 @@ Camera constants:
{ // Quality B
"make_model": [ "Panasonic DMC-GX80", "Panasonic DMC-GX85", "Panasonic DMC-GX7MK2" ],
- "dcraw_matrix": [ 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 ], // DNG_v9.6 D65
+ "dcraw_matrix": [ 7771,-3020,-629,-4029,11950,2345,-822,1976,6119 ], // DNG v13.2
"ranges": {
"black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -2280,7 +2456,7 @@ Camera constants:
{ // Quality X, no white-frames nor black-frames yet, see #4550
"make_model": [ "Panasonic DC-GX9" ],
- "dcraw_matrix": [ 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 ], // ColorMatrix2 from Adobe DNG Converter 10.3
+ "dcraw_matrix": [ 7564,-2263,-606,-3149,11238,2177,-540,1435,4853 ], // DNG v13.2
"ranges": {
"black": 16,
"white": 4080
@@ -2289,7 +2465,7 @@ Camera constants:
{ // Quality B, Same as Panasonic G7
"make_model": [ "Panasonic DMC-G8", "Panasonic DMC-G80", "Panasonic DMC-G81", "Panasonic DMC-G85" ],
- "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG_v9.7 D65
+ "dcraw_matrix": [ 7610,-2781,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG v13.2
"ranges": {
"black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -2302,7 +2478,7 @@ Camera constants:
{ // Quality B
"make_model": "Panasonic DMC-GX8",
- "dcraw_matrix": [ 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 ], // DNG_v9.1.1 D65
+ "dcraw_matrix": [ 7564,-2263,-606,-3149,11238,2177,-540,1435,4853 ], // DNG v13.2
"ranges": {
"black": 15, // 16 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset
"white": [
@@ -2371,6 +2547,16 @@ Camera constants:
]
}
},
+
+ { // Quality C
+ "make_model": "Panasonic DC-S1H",
+ "dcraw_matrix": [ 9397, -3719, -805, -5425, 13326, 2309, -972, 1715, 6034 ] // DNG
+ },
+
+ { // Quality C, possibly the same as DC-S1. We have a custom DCP which is better.
+ "make_model": "Panasonic DC-S5",
+ "dcraw_matrix": [ 9744, -3905, -779, -4899, 12807, 2324, -798, 1630, 5827 ] // DNG
+ },
{ // Quality B, per ISO info missing
"make_model": "PENTAX K-x",
@@ -2425,7 +2611,7 @@ Camera constants:
{ // Quality B, Intemediate ISO samples missing, Pentax_DNG WLtags are after BL sutraction and not valid
"make_model": [ "RICOH PENTAX K-1", "PENTAX K-1" ],
- "dcraw_matrix": [ 8596,-2981,-639,-4202,12046,2431,-685,1424,6122 ], // adobe DNG v9.7 D65
+ "dcraw_matrix": [ 8596,-2981,-639,-4202,12045,2431,-685,1424,6122 ], // DNG v13.2
//"dcraw_matrix": [ 8566,-2746,-1201,-3612,12204,1550,-893,1680,6264 ], // PENTAX DNG
//"raw_crop": [ 6, 18, 7376, 4932 ], // full frame 7392x4950, cropped to official DNG raw_crop 6,18,7382,4950, official jpeg crop 8,10,7360x4912
"ranges": {
@@ -2439,6 +2625,11 @@ Camera constants:
}
},
+ { // Quality C, possibly the same as K-1
+ "make_model": [ "RICOH PENTAX K-1 Mark II", "PENTAX K-1 Mark II" ],
+ "dcraw_matrix": [ 8596, -2981, -639, -4202, 12045, 2431, -685, 1424, 6122 ] // DNG
+ },
+
{ // Quality B, intermediate ISOs info missing
"make_model": [ "RICOH PENTAX K-3", "PENTAX K-3" ],
"dcraw_matrix": [ 7415,-2052,-721,-5186,12788,2682,-1446,2157,6773 ], // adobe dcp d65
@@ -2456,6 +2647,12 @@ Camera constants:
}
},
+ { // Quality C
+ "make_model": ["RICOH PENTAX K-3 MARK III", "PENTAX K-3 MARK III"],
+ "dcraw_matrix" : [7003, -1618, -887, -4614, 12728, 2065, -645, 1441, 5734],
+ "raw_crop": [ 24, 34, -28, -14 ]
+ },
+
{ // Quality B, intermediate ISOs info missing
"make_model": [ "RICOH PENTAX 645Z", "PENTAX 645Z" ],
"dcraw_matrix": [ 9519,-3591,-664,-4074,11725,2671,-624,1501,6653 ], // adobe dcp d65
@@ -2473,7 +2670,7 @@ Camera constants:
{ // Quality B, intermediate ISOs info missing, spread due to blackframe subtraction guessed to be around 10levels
"make_model": "PENTAX K10D",
- "dcraw_matrix": [ 9566,-2863,-803,-7170,15172,2112,-818,803,9705 ], // adobe DNG d65
+ "dcraw_matrix": [ 9679, -2965, -811, -8622, 16514, 2182, -975, 883, 9793 ], // DNG v13.2
//"raw_crop": [ 0, , 3888, 2608 ],
"ranges": {
"white": [
@@ -2571,16 +2768,27 @@ Camera constants:
"make_model": "Sigma sd Quattro",
"raw_crop": [ 200, 74, 5632, 3698 ]
},
+
+ { // Quality C
+ "make_model": "Sigma fp",
+ "dcraw_matrix": [ 12431, -5541, -1000, -4387, 12361, 2265, -732, 1526, 5970 ] // DNG
+ },
+
+ { // Quality C
+ "make_model": "Sony NEX-F3",
+ "dcraw_matrix": [ 5991, -1456, -455, -4764, 12135, 2980, -707, 1424, 6701 ] // DNG
+ },
+
{ // Quality A, correction for color matrix from Colin Walker's d50 to dng d65
"make_model": "Sony NEX-C3",
//"dcraw_matrix": [ 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 ], // Colin walker's d50 kept for possible consistency issues
- "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 ],
+ "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1424,6701 ], // DNG v13.2
"ranges": { "black": 512, "white": 16300 }
},
{ // Quality A, correction for frame width
"make_model": "Sony NEX-5N",
- "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 ],
+ "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1424,6701 ], // DNG v13.2
"raw_crop": [ 0, 0, 4920, 3276 ],
"ranges": { "black": 512, "white": 16300 }
},
@@ -2594,35 +2802,40 @@ Camera constants:
{ // Quality B
"make_model": "Sony ILCA-68",
- "dcraw_matrix": [ 6435,-1903,-536,-4722,12449,2550,-663,1363,6517 ], // adobe DNGv9.5 d65
+ "dcraw_matrix": [ 6435,-1903,-536,-4722,12448,2550,-663,1363,6516 ], // DNG v13.2
"raw_crop": [ 0, 0, -30, 0 ],
"ranges": { "black": 512, "white": 16300 }
},
{ // Quality B, correction for frame width, crop modes covered
"make_model": "Sony ILCA-99M2",
- "dcraw_matrix": [ 6660,-1918,-471,-4613,12398,2485,-649,1433,6447 ], // DNG_v9.8 D65
+ "dcraw_matrix": [ 6660,-1918,-472,-4613,12398,2485,-649,1433,6447 ], // DNG v13.2
"raw_crop": [ 0, 0, -36, 0 ], // full raw frame 8000x5320 - 36 rightmost columns are garbage
"ranges": { "black": 512, "white": 16300 }
},
+
+ { // Quality C
+ "make_model": "Sony ILCE-1",
+ "dcraw_matrix": [ 8161, -2947, -739, -4811, 12668, 2389, -437, 1229, 6524 ] // DNG v13.2
+ },
{ // Quality A, correction for frame width
"make_model": [ "Sony ILCE-3000", "Sony ILCE-3500", "Sony ILCE-5000", "Sony ILCE-QX1" ],
- "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 ], // adobe dcp d65
+ "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1424,6701 ], // DNG v13.2
"ranges": { "black": 512, "white": 16300 },
"raw_crop": [ 0, 0, 5476, 3656 ]
},
{ // Quality A
"make_model": "Sony ILCE-5100",
- "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 ], // adobe dcp d65
+ "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1424,6701 ], // DNG v13.2
"raw_crop": [ 0, 0, 6024, 4024 ],
"ranges": { "black": 512, "white": 16300 }
},
{ // Quality A
"make_model": "Sony ILCE-6000",
- "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 ], // adobe dcp d65
+ "dcraw_matrix": [ 5991,-1456,-455,-4764,12135,2980,-707,1424,6701 ], // adobe dcp d65
"raw_crop": [ 0, 0, 6024, 4024 ],
"ranges": { "black": 512, "white": 16300 },
// detected by hand, using the picture from https://www.dpreview.com/forums/thread/3923513
@@ -2631,9 +2844,18 @@ Camera constants:
"pdaf_offset" : 3
},
+ { // Quality B, probably similar to ILCE-6000 / 6300 / 6500, not checked
+ "make_model": [ "Sony ILCE-6100","Sony ILCE-6400","Sony ILCE-6600" ],
+ "dcraw_matrix": [ 7657, -2847, -607, -4083, 11966, 2389, -684, 1418, 5844 ], // DNG
+ "raw_crop": [ 0, 0, 6024, 4024 ],
+ "ranges": { "black": 512, "white": 16300 },
+ "pdaf_pattern" : [ 0,12,36,54,72,90,114,126,144,162,180,204,216,240,252,270,294,306,324,342,366,384,396,414,432,450,474,492,504,522,540,564,576,594,606,630 ],
+ "pdaf_offset" : 3
+ },
+
{ // Quality A
"make_model": [ "Sony ILCE-6300","Sony ILCE-6500" ],
- "dcraw_matrix": [ 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 ], // DNG_v9.8 D65
+ "dcraw_matrix": [ 5973,-1696,-419,-3826,11797,2293,-639,1398,5789 ], // DNG_v9.8 D65
"raw_crop": [ 0, 0, 6024, 4024 ],
"ranges": { "black": 512, "white": 16300 },
// contributed by Horshak from https://www.dpreview.com/forums/post/60873077
@@ -2641,6 +2863,11 @@ Camera constants:
"pdaf_offset" : 3
},
+ { // Quality C
+ "make_model": "Sony ILCE-7C",
+ "dcraw_matrix": [ 7374, -2389, -551, -5435, 13162, 2519, -1006, 1795, 6552 ]
+ },
+
{ // Quality A, correction for frame width
"make_model": "Sony ILCE-7R",
"dcraw_matrix": [ 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 ],
@@ -2657,9 +2884,15 @@ Camera constants:
{ // Quality C, correction for frame width
"make_model": [ "Sony DSC-RX0", "Sony DSC-RX0M2" ],
+ "dcraw_matrix": [ 9396, -3507, -843, -2497, 11111, 1572, -343, 1355, 5089 ],
"raw_crop": [ 0, 0, -8, 0 ] // 8 rightmost columns are garbage
},
+ { // Quality C
+ "make_model": "Sony DSC-RX1R",
+ "dcraw_matrix": [ 6344, -1612, -462, -4863, 12477, 2681, -865, 1786, 6899 ]
+ },
+
{ // Quality B, correction for frame width, crop modes covered
"make_model": [ "Sony ILCE-7RM2", "Sony DSC-RX1RM2" ],
"dcraw_matrix": [ 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 ], // DNG_v9.1.1 D65
@@ -2672,7 +2905,7 @@ Camera constants:
{ // Quality C, color matrix copied from ILCE-9, LongExposures 2-3sec only
"make_model": "Sony ILCE-7M3",
- "dcraw_matrix": [ 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 ], // ILCE-9, DNG_v9.12 D65
+ "dcraw_matrix": [ 7374, -2389, -551, -5435, 13162, 2519, -1006, 1795, 6552 ], // DNG v13.2
// "raw_crop": [ 8, 8, 6008, 4008 ], // full raw frame 6048x4024 Dcraw auto identify 6024x4024, jpeg 12,12,6000x4000
// "ranges": { "black": 512, "white": 16300 }
"ranges": {
@@ -2701,7 +2934,7 @@ Camera constants:
{ // Quality C,
"make_model": "Sony ILCE-7RM3",
- "dcraw_matrix": [ 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 ], // DNG_v10.1 D65
+ "dcraw_matrix": [ 6640,-1847,-503,-5238,13010,2474,-993,1673,6526 ], // DNG v13.2
"raw_crop": [ 0, 0, -36, 0 ], // full raw frame 8000x5320 - 36 rightmost columns are garbage
"ranges": { "black": 512, "white": 16300 },
"pdaf_pattern" : [0, 24, 36, 60, 84, 120, 132, 156, 192, 204, 240, 252, 276, 300, 324, 360, 372, 396, 420, 444, 480, 492, 504, 540, 564, 576, 612, 636, 660, 696, 720, 732, 756, 780, 804, 840],
@@ -2710,11 +2943,12 @@ Camera constants:
{ // Quality C,
"make_model": "Sony ILCE-7RM4",
+ "dcraw_matrix": [ 7662, -2686, -660, -5240, 12965, 2530, -796, 1508, 6167 ],
"raw_crop": [ 0, 0, -32, 0 ] // full raw frame 9600x6376 - 32 rightmost columns are garbage. Using -32 instead of 9568 to support also 16-shot pixelshift files
},
- { // Quality B, color matrix copied from a7rm2
- "make_model": "Sony ILCE-9",
+ { // Quality B, assumed correct for 9M2 as well
+ "make_model": ["Sony ILCE-9","Sony ILCE-9M2"],
"dcraw_matrix": [ 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 ], // DNG_v9.12 D65
"raw_crop": [ 8, 8, 6008, 4008 ], // full raw frame 6048x4024 Dcraw auto identify 6024x4024, jpeg 12,12,6000x4000
"ranges": { "black": 512, "white": 16300 },
@@ -2733,8 +2967,15 @@ Camera constants:
},
{ // Quality C
- "make_model": [ "Sony DSC-HX99" ],
- "raw_crop": [ 0, 0, -8, 0 ] // 8 rightmost columns are garbage
+ "make_model": "Sony ILCE-7SM3",
+ "dcraw_matrix": [ 6912, -2127, -469, -4470, 12175, 2587, -398, 1477, 6492 ] // DNG
+ },
+
+ { // Quality C
+ "make_model": [ "Sony DSC-HX95", "Sony DSC-HX99" ],
+ "dcraw_matrix": [ 13076, -5686, -1481, -4027, 12851, 1251, -167, 725, 4937 ],
+ "raw_crop": [ 0, 0, -8, 0 ], // 8 rightmost columns are garbage
+ "ranges": { "black": 800, "white": 16300 }
},
{ // Quality B
@@ -2743,18 +2984,58 @@ Camera constants:
"ranges": { "white": 16368 }
},
+ { // Quality C
+ "make_model": "Sony DSC-RX100",
+ "dcraw_matrix": [ 8651, -2754, -1057, -3464, 12206, 1373, -568, 1398, 4434 ], // DNG
+ "ranges": { "black": 800, "white": 16300 }
+ },
+
{ // Quality A
"make_model": [ "Sony DSC-RX100M2", "Sony DSC-RX100M3", "Sony DSC-RX100M4", "Sony DSC-RX100M5" ],
"dcraw_matrix": [ 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 ], // DNG_v9.8 D65
"ranges": { "black": 800, "white": 16300 }
},
- { // Quality B
- "make_model": [ "Sony DSC-RX10M2", "Sony DSC-RX10M3", "Sony DSC-RX10M4" ],
- "dcraw_matrix": [ 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 ], // DNG_v9.6 D65
+ { // Quality C
+ "make_model": "Sony DSC-RX100M5A",
+ "dcraw_matrix": [ 11176, -4700, -965, -4004, 12184, 2032, -764, 1726, 5876 ], // DNG
"ranges": { "black": 800, "white": 16300 }
},
+ { // Quality C
+ "make_model": "Sony DSC-RX100M6",
+ "dcraw_matrix": [ 7325, -2321, -596, -3494, 11674, 2055, -668, 1562, 5031 ], // DNG
+ "ranges": { "black": 800, "white": 16300 }
+ },
+
+ { // Quality C
+ "make_model": "Sony DSC-RX100M7",
+ "dcraw_matrix": [ 10315, -4390, -937, -4859, 12734, 2365, -735, 1537, 5997 ], // DNG
+ "ranges": { "black": 800, "white": 16300 }
+ },
+
+ { // Quality B
+ "make_model": [ "Sony DSC-RX10M2", "Sony DSC-RX10M3" ],
+ "dcraw_matrix": [ 6679,-1825,-745,-5047,13255,1953,-1580,2422,5183 ], //DNG v13.2
+ "ranges": { "black": 800, "white": 16300 }
+ },
+
+ { // Quality B
+ "make_model": "Sony DSC-RX10M4", // Similar to M2 and M3, different matrix
+ "dcraw_matrix": [ 7699, -2566, -629, -2967, 11270, 1928, -378, 1286, 4807 ], // DNG v13.2
+ "ranges": { "black": 800, "white": 16300 }
+ },
+
+ { // Quality C
+ "make_model": "Sony DCZV1B", // Sony ZV-1
+ "dcraw_matrix": [ 8280, -2987, -703, -3532, 11645, 2133, -550, 1542, 5312 ] // DNG
+ },
+
+ { // Quality C
+ "make_model": "Sony SLT-A99V",
+ "dcraw_matrix": [ 6344, -1612, -462, -4863, 12477, 2681, -865, 1786, 6899 ] // DNG
+ },
+
{ // Quality C, No proper color data, beta samples, frame set to official jpeg,
"make_model": [ "XIAOYI M1", "YI TECHNOLOGY M1" ],
"dcraw_matrix": [ 7158,-1911,-606,-3603,10669,2530,-659,1236,5530 ], // XIAO YI DNG D65
@@ -2825,7 +3106,7 @@ Camera constants:
{ // Quality B
"make_model": ["HASSELBLAD NEX-7", "SONY NEX-7"], // Hasselblad NEX-7 also known as Hasselblad Lunar
- "dcraw_matrix": [ 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 ], // adobe DNGv12.2 d65
+ "dcraw_matrix": [ 5491,-1192,-363,-4951,12342,2948,-911,1722,7191 ], // DNG v13.2
"ranges": { "black": 512, "white": 16372 } // Typical white level (samples provided by @ggc on Pixls, influence from LENR unknown
},
@@ -2873,6 +3154,11 @@ Camera constants:
"make_model": [ "Hasselblad H6D-100cMS" ],
"raw_crop": [ 64, 108, 11608, 8708 ]
},
+
+ { // Quality C
+ "make_model": "Hasselblad L1D-20c", // DJI Mavic 2 Pro
+ "dcraw_matrix": [ 6267, -2021, -687, -4664, 13343, 1399, -234, 1019, 5524 ] // DNG 13.2
+ },
{
"make_model": [ "HUAWEI DLI-L22" ],
diff --git a/rtengine/color.cc b/rtengine/color.cc
index 3fcd44eb8..d6c35208d 100644
--- a/rtengine/color.cc
+++ b/rtengine/color.cc
@@ -944,6 +944,7 @@ void Color::xyz2Prophoto (float x, float y, float z, float &r, float &g, float &
g = ((prophoto_xyz[1][0] * x + prophoto_xyz[1][1] * y + prophoto_xyz[1][2] * z)) ;
b = ((prophoto_xyz[2][0] * x + prophoto_xyz[2][1] * y + prophoto_xyz[2][2] * z)) ;
}
+
void Color::Prophotoxyz (float r, float g, float b, float &x, float &y, float &z)
{
x = ((xyz_prophoto[0][0] * r + xyz_prophoto[0][1] * g + xyz_prophoto[0][2] * b)) ;
diff --git a/rtengine/curves.h b/rtengine/curves.h
index 8800e54db..02503aff2 100644
--- a/rtengine/curves.h
+++ b/rtengine/curves.h
@@ -142,11 +142,19 @@ protected:
double lx = xlog(x);
return m2 * x + (1.0 - m2) * (2.0 - xexp(k * lx)) * xexp(l * lx);
}
+ static inline double basel_alt(double x)
+ {
+ return (2.0 - x) * x * x * x;
+ }
// basic concave function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point
static inline double baseu(double x, double m1, double m2)
{
return 1.0 - basel(1.0 - x, m1, m2);
}
+ static inline double baseu_alt(double x)
+ {
+ return x * (2.0 + (x - 2.0) * x * x);
+ }
// convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery
static inline double cupper(double x, double m, double hr)
{
@@ -448,6 +456,13 @@ protected:
{
return (1 - sh) * (1 - hl) * p00(x, prot) + sh * hl * p11(x, prot) + (1 - sh) * hl * p01(x, prot) + sh * (1 - hl) * p10(x, prot);
}
+ static inline double pfull_alt(double x, double sh, double hl)
+ {
+ double t = (1.0 - sh) * (1.0 - hl) * CurveFactory::basel_alt(x) + sh * hl * CurveFactory::baseu_alt(x);
+ return x <= 0.5
+ ? t + (1.0 - sh) * hl * CurveFactory::basel_alt(2.0 * x) * 0.5 + sh * (1.0 - hl) * CurveFactory::baseu_alt(2.0 * x) * 0.5
+ : t + (1.0 - sh) * hl * (0.5 + CurveFactory::baseu_alt(2.0 * x - 1.0) * 0.5) + sh * (1.0 - hl) * (0.5 + CurveFactory::basel_alt(2.0 * x - 1.0) * 0.5);
+ }
void fillHash();
void fillDyByDx();
diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc
index 89256bba4..b65bb5f72 100644
--- a/rtengine/dcp.cc
+++ b/rtengine/dcp.cc
@@ -1768,7 +1768,7 @@ inline void DCPProfile::hsdApply(const HsdTableInfo& table_info, const std::vect
}
}
-bool DCPProfile::isValid()
+bool DCPProfile::isValid() const
{
return valid;
}
@@ -1850,7 +1850,7 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll)
}
}
-bool DCPStore::isValidDCPFileName(const Glib::ustring& filename) const
+bool DCPStore::isValidDCPFileName(const Glib::ustring& filename)
{
if (!Glib::file_test(filename, Glib::FILE_TEST_EXISTS) || Glib::file_test(filename, Glib::FILE_TEST_IS_DIR)) {
return false;
diff --git a/rtengine/dcp.h b/rtengine/dcp.h
index 573349348..2aec6da12 100644
--- a/rtengine/dcp.h
+++ b/rtengine/dcp.h
@@ -63,7 +63,7 @@ public:
bool getHasBaselineExposureOffset() const;
Illuminants getIlluminants() const;
- bool isValid();
+ bool isValid() const;
void apply(
Imagefloat* img,
@@ -159,7 +159,7 @@ public:
void init(const Glib::ustring& rt_profile_dir, bool loadAll = true);
- bool isValidDCPFileName(const Glib::ustring& filename) const;
+ static bool isValidDCPFileName(const Glib::ustring& filename);
DCPProfile* getProfile(const Glib::ustring& filename) const;
DCPProfile* getStdProfile(const Glib::ustring& camShortName) const;
diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc
index bd2e8546c..ef0b4e8dc 100644
--- a/rtengine/dcraw.cc
+++ b/rtengine/dcraw.cc
@@ -21,7 +21,6 @@
/*RT*/#define LOCALTIME
/*RT*/#define DJGPP
/*RT*/#include "jpeg.h"
-/*RT*/#include "lj92.h"
/*RT*/#ifdef _OPENMP
/*RT*/#include
/*RT*/#endif
@@ -923,7 +922,7 @@ ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
}
getbits(-1);
}
- FORC3 row[c] = (jh->row + ((jrow & 1) + 1) * (jh->wide*jh->clrs*((jrow+c) & 1)));
+ FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
for (col=0; col < jh->wide; col++)
FORC(jh->clrs) {
diff = ljpeg_diff (jh->huff[c]);
@@ -1126,61 +1125,6 @@ void CLASS ljpeg_idct (struct jhead *jh)
FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c]+0.5);
}
-void CLASS lossless_dnglj92_load_raw()
-{
- BENCHFUN
-
- tiff_bps = 16;
-
- int save = ifp->pos;
- uint16_t *lincurve = !strncmp(make,"Blackmagic",10) ? curve : nullptr;
- tile_width = tile_length < INT_MAX ? tile_width : raw_width;
- size_t tileCount = raw_width / tile_width;
-
- size_t dataOffset[tileCount];
- if(tile_length < INT_MAX) {
- for (size_t t = 0; t < tileCount; ++t) {
- dataOffset[t] = get4();
- }
- } else {
- dataOffset[0] = ifp->pos;
- }
- const int data_length = ifp->size;
- const std::unique_ptr data(new uint8_t[data_length]);
- fseek(ifp, 0, SEEK_SET);
- // read whole file
- fread(data.get(), 1, data_length, ifp);
- lj92 lj;
- int newwidth, newheight, newbps;
- lj92_open(&lj, &data[dataOffset[0]], data_length, &newwidth, &newheight, &newbps);
- lj92_close(lj);
- if (newwidth * newheight * tileCount != raw_width * raw_height) {
- // not a lj92 file
- fseek(ifp, save, SEEK_SET);
- lossless_dng_load_raw();
- return;
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for num_threads(std::min(tileCount, omp_get_max_threads()))
-#endif
- for (size_t t = 0; t < tileCount; ++t) {
- size_t tcol = t * tile_width;
- lj92 lj;
- int newwidth, newheight, newbps;
- lj92_open(&lj, &data[dataOffset[t]], data_length, &newwidth, &newheight, &newbps);
-
- const std::unique_ptr target(new uint16_t[newwidth * newheight]);
- lj92_decode(lj, target.get(), tile_width, 0, lincurve, 0x1000);
- for (int y = 0; y < height; ++y) {
- for(int x = 0; x < tile_width; ++x) {
- RAW(y, x + tcol) = target[y * tile_width + x];
- }
- }
- lj92_close(lj);
- }
-}
-
void CLASS lossless_dng_load_raw()
{
unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col, i, j;
@@ -9078,7 +9022,7 @@ void CLASS adobe_coeff (const char *make, const char *model)
RT_matrix_from_constant = ThreeValBool::T;
}
// -- RT --------------------------------------------------------------------
-
+
for (i=0; i < sizeof table / sizeof *table; i++)
if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
if (RT_blacklevel_from_constant == ThreeValBool::T && table[i].black) black = (ushort) table[i].black;
@@ -9231,6 +9175,7 @@ void CLASS identify()
{ 3944, 2622, 30, 18, 6, 2 },
{ 3948, 2622, 42, 18, 0, 2 },
{ 3984, 2622, 76, 20, 0, 2, 14 },
+ { 4032, 2656, 112, 44, 10, 0 },
{ 4104, 3048, 48, 12, 24, 12 },
{ 4116, 2178, 4, 2, 0, 0 },
{ 4152, 2772, 192, 12, 0, 0 },
@@ -9568,7 +9513,7 @@ void CLASS identify()
apply_tiff();
if (!strcmp(model, "X-T3")) {
height = raw_height - 2;
- } else if (!strcmp(model, "GFX 100")) {
+ } else if (!strcmp(model, "GFX 100") || !strcmp(model, "GFX100S")) {
load_flags = 0;
}
if (!load_raw) {
@@ -9768,7 +9713,7 @@ void CLASS identify()
switch (tiff_compress) {
case 0:
case 1: load_raw = &CLASS packed_dng_load_raw; break;
- case 7: load_raw = (!strncmp(make,"Blackmagic",10) || !strncmp(make,"Canon",5)) ? &CLASS lossless_dnglj92_load_raw : &CLASS lossless_dng_load_raw; break;
+ case 7: load_raw = &CLASS lossless_dng_load_raw; break;
case 8: load_raw = &CLASS deflate_dng_load_raw; break;
case 34892: load_raw = &CLASS lossy_dng_load_raw; break;
default: load_raw = 0;
diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h
index 89c1fcaff..10c7b9ba6 100644
--- a/rtengine/dcraw.h
+++ b/rtengine/dcraw.h
@@ -329,7 +329,6 @@ void ljpeg_idct (struct jhead *jh);
void canon_sraw_load_raw();
void adobe_copy_pixel (unsigned row, unsigned col, ushort **rp);
void lossless_dng_load_raw();
-void lossless_dnglj92_load_raw();
void packed_dng_load_raw();
void deflate_dng_load_raw();
void init_fuji_compr(struct fuji_compressed_params* info);
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index 790a2bf0d..09e420c8e 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -19,9 +19,11 @@
*/
#include "cieimage.h"
+#include "color.h"
#include "curves.h"
#include "dcp.h"
#include "dcrop.h"
+#include "guidedfilter.h"
#include "image8.h"
#include "imagefloat.h"
#include "improccoordinator.h"
@@ -30,9 +32,9 @@
#include "procparams.h"
#include "refreshmap.h"
#include "rt_math.h"
-#include "color.h"
+#include "utils.h"
+
#include "../rtgui/editcallbacks.h"
-#include "guidedfilter.h"
#pragma GCC diagnostic warning "-Wall"
#pragma GCC diagnostic warning "-Wextra"
@@ -52,7 +54,7 @@ namespace rtengine
{
Crop::Crop(ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow)
- : PipetteBuffer(editDataProvider), origCrop(nullptr), laboCrop(nullptr), labnCrop(nullptr),
+ : PipetteBuffer(editDataProvider), origCrop(nullptr), spotCrop(nullptr), laboCrop(nullptr), labnCrop(nullptr),
cropImg(nullptr), shbuf_real(nullptr), transCrop(nullptr), cieCrop(nullptr), shbuffer(nullptr),
updating(false), newUpdatePending(false), skip(10),
cropx(0), cropy(0), cropw(-1), croph(-1),
@@ -96,7 +98,7 @@ void Crop::setListener(DetailedCropListener* il)
}
}
-EditUniqueID Crop::getCurrEditID()
+EditUniqueID Crop::getCurrEditID() const
{
const EditSubscriber *subscriber = PipetteBuffer::dataProvider ? PipetteBuffer::dataProvider->getCurrSubscriber() : nullptr;
return subscriber ? subscriber->getEditID() : EUID_None;
@@ -151,6 +153,7 @@ void Crop::update(int todo)
// give possibility to the listener to modify crop window (as the full image dimensions are already known at this point)
int wx, wy, ww, wh, ws;
const bool overrideWindow = cropImageListener;
+ bool spotsDone = false;
if (overrideWindow) {
cropImageListener->getWindow(wx, wy, ww, wh, ws);
@@ -278,7 +281,7 @@ void Crop::update(int todo)
crW = 250;
}
- // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
+ // if (settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
if (settings->leveldnv == 2) {
crW = int (tileWskip / 2);
}
@@ -402,7 +405,7 @@ void Crop::update(int todo)
crH = 250;
}
- // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
+ // if (settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
if (settings->leveldnv == 2) {
crW = int (tileWskip / 2);
crH = int (tileHskip / 2);
@@ -607,12 +610,19 @@ void Crop::update(int todo)
//end evaluate noise
}
- // if(params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto
+ // if (params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto
if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
}
+ if ((todo & M_SPOT) && params.spot.enabled && !params.spot.entries.empty()) {
+ spotsDone = true;
+ PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
+ //parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
+ parent->ipf.removeSpots(origCrop, parent->imgsrc, params.spot.entries, pp, parent->currWB, nullptr, tr);
+ }
+
DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise;
if (params.dirpyrDenoise.Lmethod == "CUR") {
@@ -695,6 +705,28 @@ void Crop::update(int todo)
// has to be called after setCropSizes! Tools prior to this point can't handle the Edit mechanism, but that shouldn't be a problem.
createBuffer(cropw, croph);
+ // Apply Spot removal
+ if ((todo & M_SPOT) && !spotsDone) {
+ if (params.spot.enabled && !params.spot.entries.empty()) {
+ if(!spotCrop) {
+ spotCrop = new Imagefloat (cropw, croph);
+ }
+ baseCrop->copyData (spotCrop);
+ PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip);
+ int tr = getCoarseBitMask(params.coarse);
+ parent->ipf.removeSpots (spotCrop, parent->imgsrc, params.spot.entries, pp, parent->currWB, ¶ms.icm, tr);
+ } else {
+ if (spotCrop) {
+ delete spotCrop;
+ spotCrop = nullptr;
+ }
+ }
+ }
+
+ if (spotCrop) {
+ baseCrop = spotCrop;
+ }
+
std::unique_ptr fattalCrop;
if ((todo & M_HDR) && (params.fattal.enabled || params.dehaze.enabled)) {
@@ -720,7 +752,7 @@ void Crop::update(int todo)
parent->imgsrc->getImage(parent->currWB, tr, f, pp, params.toneCurve, params.raw);
parent->imgsrc->convertColorSpace(f, params.icm, parent->currWB);
- if (params.dirpyrDenoise.enabled) {
+ if (params.dirpyrDenoise.enabled || params.filmNegative.enabled || params.spot.enabled) {
// copy the denoised crop
int oy = trafy / skip;
int ox = trafx / skip;
@@ -975,7 +1007,7 @@ void Crop::update(int todo)
double hlcomprthresh = params.locallab.spots.at(sp).hlcomprthresh;
double shcompr = params.locallab.spots.at(sp).shcompr;
double br = params.locallab.spots.at(sp).lightness;
- if(black < 0. && params.locallab.spots.at(sp).expMethod == "pde" ) {
+ if (black < 0. && params.locallab.spots.at(sp).expMethod == "pde" ) {
black *= 1.5;
}
@@ -1053,7 +1085,7 @@ void Crop::update(int todo)
parent->previewDeltaE, parent->locallColorMask, parent->locallColorMaskinv, parent->locallExpMask, parent->locallExpMaskinv, parent->locallSHMask, parent->locallSHMaskinv, parent->locallvibMask, parent->localllcMask, parent->locallsharMask, parent->locallcbMask, parent->locallretiMask, parent->locallsoftMask, parent->localltmMask, parent->locallblMask,
parent->localllogMask, parent->locall_Mask, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
meantme, stdtme, meanretie, stdretie);
- if(parent->previewDeltaE || parent->locallColorMask == 5 || parent->locallvibMask == 4 || parent->locallExpMask == 5 || parent->locallSHMask == 4 || parent->localllcMask == 4 || parent->localltmMask == 4 || parent->localllogMask == 4 || parent->locallsoftMask == 6 || parent->localllcMask == 4) {
+ if (parent->previewDeltaE || parent->locallColorMask == 5 || parent->locallvibMask == 4 || parent->locallExpMask == 5 || parent->locallSHMask == 4 || parent->localllcMask == 4 || parent->localltmMask == 4 || parent->localllogMask == 4 || parent->locallsoftMask == 6 || parent->localllcMask == 4) {
params.blackwhite.enabled = false;
params.colorToning.enabled = false;
params.rgbCurves.enabled = false;
@@ -1136,34 +1168,15 @@ 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;
- if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") {
- const int cw = baseCrop->getWidth();
- const int ch = baseCrop->getHeight();
- workingCrop = new Imagefloat(cw, ch);
- //first put gamma TRC to 1
- parent->ipf.workingtrc(baseCrop, workingCrop, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310, parent->getCustomTransformIn(), true, false, true);
- //adjust gamma TRC
- 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);
LUTu histToneCurve;
- parent->ipf.rgbProc (workingCrop, laboCrop, this, parent->hltonecurve, parent->shtonecurve, parent->tonecurve,
+ parent->ipf.rgbProc (baseCrop, laboCrop, this, parent->hltonecurve, parent->shtonecurve, parent->tonecurve,
params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, parent->colourToningSatLimit, parent->colourToningSatLimitOpacity, parent->ctColorCurve, parent->ctOpacityCurve, parent->opautili, parent->clToningcurve, parent->cl2Toningcurve,
parent->customToneCurve1, parent->customToneCurve2, parent->beforeToneCurveBW, parent->afterToneCurveBW, rrm, ggm, bbm,
parent->bwAutoR, parent->bwAutoG, parent->bwAutoB, dcpProf, as, histToneCurve);
-
- if (workingCrop != baseCrop) {
- delete workingCrop;
- }
}
// apply luminance operations
@@ -1228,7 +1241,7 @@ void Crop::update(int todo)
int minwin = min(labnCrop->W, labnCrop->H);
int maxlevelcrop = 10;
- // if(cp.mul[9]!=0)maxlevelcrop=10;
+ // if (cp.mul[9]!=0)maxlevelcrop=10;
// adap maximum level wavelet to size of crop
if (minwin * skip < 1024) {
maxlevelcrop = 9; //sampling wavelet 512
@@ -1314,7 +1327,7 @@ void Crop::update(int todo)
bool proton = WaveParams.exptoning;
bool pronois = WaveParams.expnoise;
- if(WaveParams.showmask) {
+ if (WaveParams.showmask) {
// WaveParams.showmask = false;
// WaveParams.expclari = true;
}
@@ -1441,7 +1454,7 @@ void Crop::update(int todo)
}
float indic = 1.f;
- if(WaveParams.showmask){
+ if (WaveParams.showmask){
mL0 = mC0 = -1.f;
indic = -1.f;
mL = fabs(mL);
@@ -1476,6 +1489,50 @@ void Crop::update(int todo)
parent->ipf.softLight(labnCrop, params.softlight);
+ if (params.icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) {
+ const int GW = labnCrop->W;
+ const int GH = labnCrop->H;
+ std::unique_ptr provis;
+ const float pres = 0.01f * params.icm.preser;
+ if (pres > 0.f && params.icm.wprim != ColorManagementParams::Primaries::DEFAULT) {
+ provis.reset(new LabImage(GW, GH));
+ provis->CopyFrom(labnCrop);
+ }
+
+ const std::unique_ptr tmpImage1(new Imagefloat(GW, GH));
+
+ parent->ipf.lab2rgb(*labnCrop, *tmpImage1, params.icm.workingProfile);
+
+ const float gamtone = parent->params->icm.workingTRCGamma;
+ const float slotone = parent->params->icm.workingTRCSlope;
+
+ int illum = rtengine::toUnderlying(params.icm.will);
+ const int prim = rtengine::toUnderlying(params.icm.wprim);
+
+ Glib::ustring prof = params.icm.workingProfile;
+
+ cmsHTRANSFORM cmsDummy = nullptr;
+ int ill = 0;
+ parent->ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, cmsDummy, true, false, false);
+ parent->ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, cmsDummy, false, true, true);
+
+ parent->ipf.rgb2lab(*tmpImage1, *labnCrop, params.icm.workingProfile);
+ //labnCrop and provis
+ if (provis) {
+ parent->ipf.preserv(labnCrop, provis.get(), GW, GH);
+ }
+ if (params.icm.fbw) {
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+ for (int x = 0; x < GH; x++)
+ for (int y = 0; y < GW; y++) {
+ labnCrop->a[x][y] = 0.f;
+ labnCrop->b[x][y] = 0.f;
+ }
+ }
+ }
+
if (params.colorappearance.enabled) {
float fnum = parent->imgsrc->getMetaData()->getFNumber(); // F number
float fiso = parent->imgsrc->getMetaData()->getISOSpeed() ; // ISO
@@ -1519,6 +1576,8 @@ void Crop::update(int todo)
// all pipette buffer processing should be finished now
PipetteBuffer::setReady();
+
+
// Computing the preview image, i.e. converting from lab->Monitor color space (soft-proofing disabled) or lab->Output profile->Monitor color space (soft-proofing enabled)
parent->ipf.lab2monitorRgb(labnCrop, cropImg);
@@ -1620,7 +1679,7 @@ bool check_need_larger_crop_for_lcp_distortion(int fw, int fh, int x, int y, int
* If the scale changes, this method will free all buffers and reallocate ones of the new size.
* It will then tell to the SizeListener that size has changed (sizeChanged)
*/
-bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool internal)
+bool Crop::setCropSizes(int cropX, int cropY, int cropW, int cropH, int skip, bool internal)
{
if (!internal) {
@@ -1629,10 +1688,10 @@ bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool inter
bool changed = false;
- rqcropx = rcx;
- rqcropy = rcy;
- rqcropw = rcw;
- rqcroph = rch;
+ rqcropx = cropX;
+ rqcropy = cropY;
+ rqcropw = cropW;
+ rqcroph = cropH;
// store and set requested crop size
int rqx1 = LIM(rqcropx, 0, parent->fullw - 1);
diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h
index 1840eabfa..19d84c3f3 100644
--- a/rtengine/dcrop.h
+++ b/rtengine/dcrop.h
@@ -38,6 +38,7 @@ class Crop final : public DetailedCrop, public PipetteBuffer
protected:
// --- permanently allocated in RAM and only renewed on size changes
Imagefloat* origCrop; // "one chunk" allocation
+ Imagefloat* spotCrop; // "one chunk" allocation
LabImage* laboCrop; // "one chunk" allocation
LabImage* labnCrop; // "one chunk" allocation
Image8* cropImg; // "one chunk" allocation ; displayed image in monitor color space, showing the output profile as well (soft-proofing enabled, which then correspond to workimg) or not
@@ -64,7 +65,7 @@ protected:
MyMutex cropMutex;
ImProcCoordinator* const parent;
const bool isDetailWindow;
- EditUniqueID getCurrEditID();
+ EditUniqueID getCurrEditID() const;
bool setCropSizes(int cropX, int cropY, int cropW, int cropH, int skip, bool internal);
void freeAll();
diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc
index 6961a4b54..7dde668eb 100644
--- a/rtengine/dfmanager.cc
+++ b/rtengine/dfmanager.cc
@@ -367,7 +367,7 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool)
auto info = file->query_info("standard::name,standard::type,standard::is-hidden");
- if (!info && info->get_file_type() == Gio::FILE_TYPE_DIRECTORY) {
+ if (!info || info->get_file_type() == Gio::FILE_TYPE_DIRECTORY) {
return nullptr;
}
diff --git a/rtengine/diagonalcurves.cc b/rtengine/diagonalcurves.cc
index 622683ea2..1173f8803 100644
--- a/rtengine/diagonalcurves.cc
+++ b/rtengine/diagonalcurves.cc
@@ -116,8 +116,8 @@ DiagonalCurve::DiagonalCurve (const std::vector& p, int poly_pn)
}
mc = -xlog(2.0) / xlog(x[2]);
- double mbase = pfull (0.5, x[8], x[6], x[5]);
- mfc = mbase <= 1e-14 ? 0.0 : xexp(xlog(mbase) / mc); // value of the curve at the center point
+ double mbase = pfull_alt (0.5, x[6], x[5]);
+ mfc = xexp(xlog(mbase) / mc); // value of the curve at the center point
msc = -xlog(2.0) / xlog(x[1] / x[2]);
mhc = -xlog(2.0) / xlog((x[3] - x[2]) / (1 - x[2]));
}
@@ -424,7 +424,6 @@ void DiagonalCurve::catmull_rom_set()
/*****************************************************************************/
-
double DiagonalCurve::getVal (double t) const
{
@@ -435,20 +434,24 @@ double DiagonalCurve::getVal (double t) const
return 0.0;
}
- double tv = xexp(mc * xlog(t));
- double base = pfull (tv, x[8], x[6], x[5]);
- double stretched = base <= 1e-14 ? 0.0 : xexp(xlog(base) / mc);
+ double tv = xexp(max(mc * xlog(t),-236.0)); // prevents numerical issues when calling pfull, at the cost of minor artifacts
+ double base = pfull_alt (tv, x[6], x[5]);
+ double stretched = xexp(xlog(base) / mc);
if (t < x[2]) {
// add shadows effect:
- double stv = xexp(msc * xlog(stretched / mfc));
- double sbase = pfull (stv, x[8], x[7], 0.5);
- return mfc * (sbase <= 1e-14 ? 0.0 : xexp(xlog(sbase) / msc));
+ double stv = xexp(max(msc * xlog(stretched / mfc),-236.0));
+ double sbase = pfull_alt (stv, x[7], 0.5);
+ return mfc * xexp(xlog(sbase) / msc);
} else {
// add highlights effect:
- double htv = xexp(mhc * xlog((stretched - mfc) / (1 - mfc)));
- double hbase = pfull (htv, x[8], 0.5, x[4]);
- return mfc + (1 - mfc) * (hbase <= 1e-14 ? 0.0 : xexp(xlog(hbase) / mhc));
+ double htv = xexp(max(mhc * xlog((stretched - mfc) / (1.0 - mfc)),-236.0));
+ if (htv < 1e-6) {
+ return stretched; // this part of the curve isn't affected by highlight, return the base curve
+ } else {
+ double hbase = pfull_alt (htv, 0.5, x[4]);
+ return mfc + (1.0 - mfc) * xexp(xlog(hbase) / mhc);
+ }
}
break;
diff --git a/rtengine/fujicompressed.cc b/rtengine/fujicompressed.cc
index 45622eb7f..c1c620657 100644
--- a/rtengine/fujicompressed.cc
+++ b/rtengine/fujicompressed.cc
@@ -25,7 +25,7 @@ int bitDiff (int value1, int value2)
int decBits = 0;
if ( value2 < value1 )
- while (decBits <= 12 && (value2 << ++decBits) < value1)
+ while (decBits <= 14 && (value2 << ++decBits) < value1)
;
return decBits;
@@ -42,7 +42,7 @@ void CLASS init_fuji_compr (struct fuji_compressed_params* info)
derror();
}
- info->q_table = (char *) malloc (32768);
+ info->q_table = (char *) malloc (2 << fuji_bits);
merror (info->q_table, "init_fuji_compr()");
if (fuji_raw_type == 16) {
@@ -83,19 +83,23 @@ void CLASS init_fuji_compr (struct fuji_compressed_params* info)
}
// populting gradients
- if (info->q_point[4] == 0x3FFF) {
- info->total_values = 0x4000;
- info->raw_bits = 14;
- info->max_bits = 56;
- info->maxDiff = 256;
- } else if (info->q_point[4] == 0xFFF) {
- info->total_values = 4096;
- info->raw_bits = 12;
- info->max_bits = 48;
- info->maxDiff = 64;
- } else {
- derror();
- }
+ //if (info->q_point[4] == 0x3FFF) {
+ // info->total_values = 0x4000;
+ // info->raw_bits = 14;
+ // info->max_bits = 56;
+ // info->maxDiff = 256;
+ //} else if (info->q_point[4] == 0xFFF) {
+ // info->total_values = 4096;
+ // info->raw_bits = 12;
+ // info->max_bits = 48;
+ // info->maxDiff = 64;
+ //} else {
+ // derror();
+ //}
+ info->total_values = (1 << fuji_bits);
+ info->raw_bits = fuji_bits;
+ info->max_bits = 4 * info->raw_bits;
+ info->maxDiff = info->total_values >> 6;
}
#define FUJI_BUF_SIZE 0x10000u
@@ -1017,7 +1021,7 @@ void CLASS parse_fuji_compressed_header()
|| h_total_lines > 0x800
|| h_total_lines == 0
|| h_total_lines != h_raw_height / 6
- || (h_raw_bits != 12 && h_raw_bits != 14)
+ || (h_raw_bits != 12 && h_raw_bits != 14 && h_raw_bits != 16)
|| (h_raw_type != 16 && h_raw_type != 0)) {
xtransCompressed = false;
return;
diff --git a/rtengine/helperavx.h b/rtengine/helperavx.h
index 528760a92..de4ecf880 100644
--- a/rtengine/helperavx.h
+++ b/rtengine/helperavx.h
@@ -3,6 +3,11 @@
// this code was taken from http://shibatch.sourceforge.net/
// Many thanks to the author: Naoki Shibata
//
+// Copyright Naoki Shibata and contributors 2010 - 2021.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file sleef_LICENSE.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
////////////////////////////////////////////////////////////////
#ifndef __AVX__
#error Please specify -mavx.
diff --git a/rtengine/helpersse2.h b/rtengine/helpersse2.h
index e8c489b04..8e87032f0 100644
--- a/rtengine/helpersse2.h
+++ b/rtengine/helpersse2.h
@@ -3,6 +3,11 @@
// this code was taken from http://shibatch.sourceforge.net/
// Many thanks to the author of original version: Naoki Shibata
//
+// Copyright Naoki Shibata and contributors 2010 - 2021.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file sleef_LICENSE.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
// This version contains modifications made by Ingo Weyrich
//
////////////////////////////////////////////////////////////////
diff --git a/rtengine/iimage.h b/rtengine/iimage.h
index 984b98a6f..2c75a0d59 100644
--- a/rtengine/iimage.h
+++ b/rtengine/iimage.h
@@ -347,6 +347,23 @@ public:
}
}
+ /** Copy the a sub-region of the data to another PlanarRGBData */
+ void copyData(PlanarWhateverData *dest, int x, int y, int width, int height)
+ {
+ assert (dest != NULL);
+ // Make sure that the size is the same, reallocate if necessary
+ dest->allocate(width, height);
+
+ if (dest->width == -1) {
+ printf("ERROR: PlanarRGBData::copyData >>> allocation failed!\n");
+ return;
+ }
+
+ for (int i = y, j = 0; i < y + height; ++i, ++j) {
+ memcpy (dest->v(i) + x, v(j), width * sizeof(T));
+ }
+ }
+
void rotate (int deg) override
{
@@ -756,6 +773,25 @@ public:
}
}
+ /** Copy the a sub-region of the data to another PlanarRGBData */
+ void copyData(PlanarRGBData *dest, int x, int y, int width, int height)
+ {
+ assert (dest != NULL);
+ // Make sure that the size is the same, reallocate if necessary
+ dest->allocate(width, height);
+
+ if (dest->width == -1) {
+ printf("ERROR: PlanarRGBData::copyData >>> allocation failed!\n");
+ return;
+ }
+
+ for (int i = y, j = 0; i < y + height; ++i, ++j) {
+ memcpy (dest->r(i) + x, r(j), width * sizeof(T));
+ memcpy (dest->g(i) + x, g(j), width * sizeof(T));
+ memcpy (dest->b(i) + x, b(j), width * sizeof(T));
+ }
+ }
+
void rotate (int deg) final
{
@@ -1392,6 +1428,23 @@ public:
memcpy (dest->data, data, 3 * width * height * sizeof(T));
}
+ /** Copy the a sub-region of the data to another PlanarRGBData */
+ void copyData(ChunkyRGBData *dest, int x, int y, int width, int height)
+ {
+ assert (dest != NULL);
+ // Make sure that the size is the same, reallocate if necessary
+ dest->allocate(width, height);
+
+ if (dest->width == -1) {
+ printf("ERROR: PlanarRGBData::copyData >>> allocation failed!\n");
+ return;
+ }
+
+ for (int i = y, j = 0; i < y + height; ++i, ++j) {
+ memcpy (dest->r(i) + x, r(j), 3 * width * sizeof(T));
+ }
+ }
+
void rotate (int deg) final
{
diff --git a/rtengine/image16.cc b/rtengine/image16.cc
index 1a9130b5d..ae981c7bd 100644
--- a/rtengine/image16.cc
+++ b/rtengine/image16.cc
@@ -134,7 +134,21 @@ Image16* Image16::copy() const
return cp;
}
-void Image16::getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const
+Image16* Image16::copySubRegion (int x, int y, int width, int height)
+{
+ Image16* cp = NULL;
+ int realWidth = LIM(x + width, 0, this->width) - x;
+ int realHeight = LIM(y + height, 0, this->height) - y;
+
+ if (realWidth > 0 && realHeight > 0) {
+ cp = new Image16 (realWidth, realHeight);
+ copyData(cp, x, y, realWidth, realHeight);
+ }
+
+ return cp;
+}
+
+void Image16::getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp) const
{
// compute channel multipliers
diff --git a/rtengine/image16.h b/rtengine/image16.h
index de9718708..25b777832 100644
--- a/rtengine/image16.h
+++ b/rtengine/image16.h
@@ -39,8 +39,9 @@ public:
~Image16() override;
Image16* copy() const;
+ Image16* copySubRegion (int x, int y, int width, int height);
- void getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const override;
+ void getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp) const override;
const char* getType() const override
{
diff --git a/rtengine/image8.cc b/rtengine/image8.cc
index 67b38d0c1..1b4e49d84 100644
--- a/rtengine/image8.cc
+++ b/rtengine/image8.cc
@@ -100,7 +100,7 @@ Image8* Image8::copy () const
return cp;
}
-void Image8::getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const
+void Image8::getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp) const
{
// compute channel multipliers
float rm = 1.f, gm = 1.f, bm = 1.f;
diff --git a/rtengine/image8.h b/rtengine/image8.h
index dd3be5d9b..76a580bb6 100644
--- a/rtengine/image8.h
+++ b/rtengine/image8.h
@@ -38,7 +38,7 @@ public:
Image8* copy () const;
- void getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const override;
+ void getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp) const override;
const char* getType () const override
{
diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc
index 16b6a4c91..5ecfa8414 100644
--- a/rtengine/imagedata.cc
+++ b/rtengine/imagedata.cc
@@ -339,7 +339,6 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
iso_speed = isoTag->toDouble();
}
}
-
}
if (lens == "Unknown") {
diff --git a/rtengine/imagedimensions.cc b/rtengine/imagedimensions.cc
index 5b60e5da7..5e780558c 100644
--- a/rtengine/imagedimensions.cc
+++ b/rtengine/imagedimensions.cc
@@ -54,6 +54,14 @@ int PreviewProps::getSkip() const
return skip;
}
+void PreviewProps::set (int x, int y, int w, int h, int skip) {
+ this->x = x;
+ this->y = y;
+ this->width = w;
+ this->height = h;
+ this->skip = skip;
+}
+
ImageDimensions::ImageDimensions() :
width(-1),
height(-1)
diff --git a/rtengine/imagedimensions.h b/rtengine/imagedimensions.h
index eb92798c3..fce7a4dea 100644
--- a/rtengine/imagedimensions.h
+++ b/rtengine/imagedimensions.h
@@ -29,6 +29,7 @@ public:
int getWidth() const;
int getHeight() const;
int getSkip() const;
+ void set (int x, int y, int w, int h, int skip);
private:
int x;
diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc
index d9ac841eb..7bc75fe6d 100644
--- a/rtengine/imagefloat.cc
+++ b/rtengine/imagefloat.cc
@@ -165,8 +165,22 @@ Imagefloat* Imagefloat::copy () const
return cp;
}
+Imagefloat* Imagefloat::copySubRegion (int x, int y, int width, int height)
+{
+ Imagefloat* cp = NULL;
+ int realWidth = LIM(x + width, 0, this->width) - x;
+ int realHeight = LIM(y + height, 0, this->height) - y;
+
+ if (realWidth > 0 && realHeight > 0) {
+ cp = new Imagefloat (realWidth, realHeight);
+ copyData(cp, x, y, realWidth, realHeight);
+ }
+
+ return cp;
+}
+
// This is called by the StdImageSource class. We assume that fp images from StdImageSource don't have to deal with gamma
-void Imagefloat::getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const
+void Imagefloat::getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp) const
{
// compute channel multipliers
diff --git a/rtengine/imagefloat.h b/rtengine/imagefloat.h
index 3362afcda..fc3ba318d 100644
--- a/rtengine/imagefloat.h
+++ b/rtengine/imagefloat.h
@@ -44,8 +44,9 @@ public:
~Imagefloat () override;
Imagefloat* copy () const;
+ Imagefloat* copySubRegion (int x, int y, int width, int height);
- void getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const override;
+ void getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp) const override;
const char* getType () const override
{
diff --git a/rtengine/imageio.h b/rtengine/imageio.h
index 866855bfe..566fef13b 100644
--- a/rtengine/imageio.h
+++ b/rtengine/imageio.h
@@ -93,7 +93,7 @@ public:
void setSampleArrangement(IIOSampleArrangement sArrangement);
IIOSampleArrangement getSampleArrangement() const;
- virtual void getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const = 0;
+ virtual void getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp) const = 0;
virtual int getBPS () const = 0;
virtual void getScanline (int row, unsigned char* buffer, int bps, bool isFloat = false) const = 0;
virtual void setScanline (int row, const unsigned char* buffer, int bps, unsigned int numSamples = 3) = 0;
diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h
index 25c024ed2..6cb279efc 100644
--- a/rtengine/imagesource.h
+++ b/rtengine/imagesource.h
@@ -171,7 +171,7 @@ public:
outCurve = { 0.0 };
}
- double getDirPyrDenoiseExpComp ( )
+ double getDirPyrDenoiseExpComp () const
{
return dirpyrdenoiseExpComp;
}
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 71468fd8f..938048169 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -17,6 +17,7 @@
* along with RawTherapee. If not, see .
*/
#include
+
#include
#include "improccoordinator.h"
@@ -27,6 +28,7 @@
#include "colortemp.h"
#include "curves.h"
#include "dcp.h"
+#include "guidedfilter.h"
#include "iccstore.h"
#include "image8.h"
#include "imagefloat.h"
@@ -34,8 +36,9 @@
#include "labimage.h"
#include "lcp.h"
#include "procparams.h"
+#include "tweakoperator.h"
#include "refreshmap.h"
-#include "guidedfilter.h"
+#include "utils.h"
#include "../rtgui/options.h"
@@ -56,6 +59,7 @@ namespace rtengine
ImProcCoordinator::ImProcCoordinator() :
orig_prev(nullptr),
oprevi(nullptr),
+ spotprev(nullptr),
oprevl(nullptr),
nprevl(nullptr),
fattal_11_dcrop_cache(nullptr),
@@ -165,6 +169,7 @@ ImProcCoordinator::ImProcCoordinator() :
hListener(nullptr),
resultValid(false),
params(new procparams::ProcParams),
+ tweakOperator(nullptr),
lastOutputProfile("BADFOOD"),
lastOutputIntent(RI__COUNT),
lastOutputBPC(false),
@@ -278,9 +283,32 @@ void ImProcCoordinator::assign(ImageSource* imgsrc)
this->imgsrc = imgsrc;
}
-void ImProcCoordinator::getParams(procparams::ProcParams* dst)
+void ImProcCoordinator::getParams(procparams::ProcParams* dst, bool tweaked)
{
- *dst = *params;
+ if (!tweaked && paramsBackup.operator bool()) {
+ *dst = *paramsBackup;
+ } else {
+ *dst = *params;
+ }
+}
+
+void ImProcCoordinator::backupParams()
+{
+ if (!params) {
+ return;
+ }
+ if (!paramsBackup) {
+ paramsBackup.reset(new ProcParams());
+ }
+ *paramsBackup = *params;
+}
+
+void ImProcCoordinator::restoreParams()
+{
+ if (!paramsBackup || !params) {
+ return;
+ }
+ *params = *paramsBackup;
}
DetailedCrop* ImProcCoordinator::createCrop(::EditDataProvider *editDataProvider, bool isDetailWindow)
@@ -320,6 +348,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
RAWParams rp = params->raw;
ColorManagementParams cmp = params->icm;
LCurveParams lcur = params->labCurve;
+ bool spotsDone = false;
if (!highDetailNeeded) {
// if below 100% magnification, take a fast path
@@ -583,6 +612,13 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
ipf.setScale(scale);
imgsrc->getImage(currWB, tr, orig_prev, pp, params->toneCurve, params->raw);
+
+ if ((todo & M_SPOT) && params->spot.enabled && !params->spot.entries.empty()) {
+ spotsDone = true;
+ PreviewProps pp(0, 0, fw, fh, scale);
+ ipf.removeSpots(orig_prev, imgsrc, params->spot.entries, pp, currWB, nullptr, tr);
+ }
+
denoiseInfoStore.valid = false;
//ColorTemp::CAT02 (orig_prev, ¶ms) ;
// printf("orig_prevW=%d\n scale=%d",orig_prev->width, scale);
@@ -600,16 +636,16 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
float max_r[nbw*nbh];
float max_b[nbw*nbh];
- if(denoiseParams.Lmethod == "CUR") {
- if(noiseLCurve)
+ if (denoiseParams.Lmethod == "CUR") {
+ if (noiseLCurve)
denoiseParams.luma = 0.5f;
else
denoiseParams.luma = 0.0f;
- } else if(denoiseParams.Lmethod == "SLI")
+ } else if (denoiseParams.Lmethod == "SLI")
noiseLCurve.Reset();
- if(noiseLCurve || noiseCCurve){//only allocate memory if enabled and scale=1
+ if (noiseLCurve || noiseCCurve){//only allocate memory if enabled and scale=1
// we only need image reduced to 1/4 here
calclum = new Imagefloat ((pW+1)/2, (pH+1)/2);//for luminance denoise curve
for(int ii=0;iispot.enabled && !params->spot.entries.empty()) {
+ allocCache(spotprev);
+ orig_prev->copyData(spotprev);
+ PreviewProps pp(0, 0, fw, fh, scale);
+ ipf.removeSpots(spotprev, imgsrc, params->spot.entries, pp, currWB, ¶ms->icm, tr);
+ } else {
+ if (spotprev) {
+ delete spotprev;
+ spotprev = nullptr;
+ }
+ }
+ }
+ if (spotprev) {
+ spotprev->copyData(orig_prev);
+ }
+
if ((todo & M_HDR) && (params->fattal.enabled || params->dehaze.enabled)) {
if (fattal_11_dcrop_cache) {
delete fattal_11_dcrop_cache;
@@ -666,12 +721,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
}
- oprevi = orig_prev;
-
// Remove transformation if unneeded
bool needstransform = ipf.needsTransform(fw, fh, imgsrc->getRotateDegree(), imgsrc->getMetaData());
if ((needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled && !params->colorappearance.enabled))) {
+ // Forking the image
assert(oprevi);
Imagefloat *op = oprevi;
oprevi = new Imagefloat(pW, pH);
@@ -829,42 +883,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
}
- if (todo & (M_AUTOEXP | M_RGBCURVE)) {
- /* if (params->icm.workingTRC == "Custom") { //exec TRC IN free
- if (oprevi == orig_prev) {
- oprevi = new Imagefloat(pW, pH);
- orig_prev->copyData(oprevi);
- }
- const Glib::ustring profile = params->icm.workingProfile;
-
- if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") {
- const int cw = oprevi->getWidth();
- const int ch = oprevi->getHeight();
-
- // put gamma TRC to 1
- if (customTransformIn) {
- cmsDeleteTransform(customTransformIn);
- customTransformIn = nullptr;
- }
-
- ipf.workingtrc(oprevi, oprevi, cw, ch, -5, params->icm.workingProfile, 2.4, 12.92310, customTransformIn, true, false, true);
-
- //adjust TRC
- if (customTransformOut) {
- cmsDeleteTransform(customTransformOut);
- customTransformOut = nullptr;
- }
-
- ipf.workingtrc(oprevi, oprevi, cw, ch, 5, params->icm.workingProfile, params->icm.workingTRCGamma, params->icm.workingTRCSlope, customTransformOut, false, true, true);
- }
- }
- */
- }
-
- // if ((todo & (M_LUMINANCE + M_COLOR)) || (todo & M_AUTOEXP)) {
- // if (todo & M_RGBCURVE) {
- if (((todo & (M_AUTOEXP | M_RGBCURVE)) || (todo & M_CROP)) && params->locallab.enabled && !params->locallab.spots.empty()) {
+ if ((todo & (M_AUTOEXP | M_RGBCURVE | M_CROP)) && params->locallab.enabled && !params->locallab.spots.empty()) {
ipf.rgb2lab(*oprevi, *oprevl, params->icm.workingProfile);
@@ -920,11 +940,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
for (int sp = 0; sp < (int)params->locallab.spots.size(); sp++) {
- if(params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap) {
+ if (params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap) {
savenormtm.reset(new LabImage(*oprevl, true));
}
- if(params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) {
+ if (params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) {
savenormreti.reset(new LabImage(*oprevl, true));
}
// Set local curves of current spot to LUT
@@ -1034,7 +1054,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
float yend = 1.f;
float xsta = 0.f;
float xend = 1.f;
- if(istm || isreti) {
+ if (istm || isreti) {
locx = params->locallab.spots.at(sp).loc.at(0) / 2000.0;
locy = params->locallab.spots.at(sp).loc.at(2) / 2000.0;
locxl= params->locallab.spots.at(sp).loc.at(1) / 2000.0;
@@ -1054,10 +1074,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
int yys = ysta * hh;
int yye = yend * hh;
- if(istm) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
+ if (istm) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
ipf.mean_sig (nprevl->L, meantme, stdtme, xxs, xxe, yys, yye);
}
- if(isreti) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
+ if (isreti) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
ipf.mean_sig (nprevl->L, meanretie, stdretie,xxs, xxe, yys, yye) ;
}
@@ -1146,20 +1166,20 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
- if(istm) { //calculate mean and sigma on full image for use by normalize_mean_dt
+ if (istm) { //calculate mean and sigma on full image for use by normalize_mean_dt
float meanf = 0.f;
float stdf = 0.f;
- ipf.mean_sig (savenormtm.get()->L, meanf, stdf, xxs, xxe, yys, yye);
+ ipf.mean_sig (savenormtm->L, meanf, stdf, xxs, xxe, yys, yye);
//using 2 unused variables noiselumc and softradiustm
params->locallab.spots.at(sp).noiselumc = (int) meanf;
params->locallab.spots.at(sp).softradiustm = stdf ;
}
- if(isreti) { //calculate mean and sigma on full image for use by normalize_mean_dt
+ if (isreti) { //calculate mean and sigma on full image for use by normalize_mean_dt
float meanf = 0.f;
float stdf = 0.f;
- ipf.mean_sig (savenormreti.get()->L, meanf, stdf,xxs, xxe, yys, yye );
+ ipf.mean_sig (savenormreti->L, meanf, stdf,xxs, xxe, yys, yye );
//using 2 unused variables sensihs and sensiv
params->locallab.spots.at(sp).sensihs = (int) meanf;
params->locallab.spots.at(sp).sensiv = (int) stdf;
@@ -1334,7 +1354,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
lhist16.clear();
#ifdef _OPENMP
const int numThreads = min(max(pW * pH / (int)lhist16.getSize(), 1), omp_get_max_threads());
- #pragma omp parallel num_threads(numThreads) if(numThreads>1)
+ #pragma omp parallel num_threads(numThreads) if (numThreads>1)
#endif
{
LUTu lhist16thr(lhist16.getSize());
@@ -1414,7 +1434,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
bool proton = WaveParams.exptoning;
bool pronois = WaveParams.expnoise;
- if(WaveParams.showmask) {
+ if (WaveParams.showmask) {
// WaveParams.showmask = false;
// WaveParams.expclari = true;
}
@@ -1540,7 +1560,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
float indic = 1.f;
- if(WaveParams.showmask){
+ if (WaveParams.showmask){
mL0 = mC0 = -1.f;
indic = -1.f;
mL = fabs(mL);
@@ -1611,6 +1631,134 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
ipf.softLight(nprevl, params->softlight);
+ if (params->icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) {
+ const int GW = nprevl->W;
+ const int GH = nprevl->H;
+ std::unique_ptr provis;
+ const float pres = 0.01f * params->icm.preser;
+ if (pres > 0.f && params->icm.wprim != ColorManagementParams::Primaries::DEFAULT) {
+ provis.reset(new LabImage(GW, GH));
+ provis->CopyFrom(nprevl);
+ }
+
+ std::unique_ptr tmpImage1(new Imagefloat(GW, GH));
+
+ ipf.lab2rgb(*nprevl, *tmpImage1, params->icm.workingProfile);
+
+ const float gamtone = params->icm.workingTRCGamma;
+ const float slotone = params->icm.workingTRCSlope;
+
+ int illum = toUnderlying(params->icm.will);
+ const int prim = toUnderlying(params->icm.wprim);
+
+ Glib::ustring prof = params->icm.workingProfile;
+ cmsHTRANSFORM dummy = nullptr;
+ int ill = 0;
+ ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false);
+ ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, dummy, false, true, true);
+
+ ipf.rgb2lab(*tmpImage1, *nprevl, params->icm.workingProfile);
+ //nprevl and provis
+ if (provis) {
+ ipf.preserv(nprevl, provis.get(), GW, GH);
+ }
+ if (params->icm.fbw) {
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+ for (int x = 0; x < GH; x++)
+ for (int y = 0; y < GW; y++) {
+ nprevl->a[x][y] = 0.f;
+ nprevl->b[x][y] = 0.f;
+ }
+ }
+
+ tmpImage1.reset();
+
+ if (prim == 12) {//pass red gre blue xy in function of area dats Ciexy
+ float redgraphx = params->icm.labgridcieALow;
+ float redgraphy = params->icm.labgridcieBLow;
+ float blugraphx = params->icm.labgridcieAHigh;
+ float blugraphy = params->icm.labgridcieBHigh;
+ float gregraphx = params->icm.labgridcieGx;
+ float gregraphy = params->icm.labgridcieGy;
+ float redxx = 0.55f * (redgraphx + 1.f) - 0.1f;
+ redxx = rtengine::LIM(redxx, 0.41f, 1.f);
+ float redyy = 0.55f * (redgraphy + 1.f) - 0.1f;
+ redyy = rtengine::LIM(redyy, 0.f, 0.7f);
+ float bluxx = 0.55f * (blugraphx + 1.f) - 0.1f;
+ bluxx = rtengine::LIM(bluxx, -0.1f, 0.5f);
+ float bluyy = 0.55f * (blugraphy + 1.f) - 0.1f;
+ bluyy = rtengine::LIM(bluyy, -0.1f, 0.5f);
+
+ float grexx = 0.55f * (gregraphx + 1.f) - 0.1f;
+ grexx = rtengine::LIM(grexx, -0.1f, 0.4f);
+ float greyy = 0.55f * (gregraphy + 1.f) - 0.1f;
+ greyy = rtengine::LIM(greyy, 0.5f, 1.f);
+
+ if (primListener) {
+ primListener->primChanged (redxx, redyy, bluxx, bluyy, grexx, greyy);
+ }
+ } else {//all other cases - pass Cie xy to update graph Ciexy
+ float r_x = params->icm.redx;
+ float r_y = params->icm.redy;
+ float b_x = params->icm.blux;
+ float b_y = params->icm.bluy;
+ float g_x = params->icm.grex;
+ float g_y = params->icm.grey;
+ //printf("rx=%f ry=%f \n", (double) r_x, (double) r_y);
+ float wx = 0.33f;
+ float wy = 0.33f;
+
+ switch (illum) {
+ case 1://D41
+ wx = 0.37798f;
+ wy = 0.38123f;
+ break;
+ case 2://D50
+ wx = 0.3457f;
+ wy = 0.3585f;
+ break;
+ case 3://D55
+ wx = 0.3324f;
+ wy = 0.3474f;
+ break;
+ case 4://D60
+ wx = 0.3217f;
+ wy = 0.3377f;
+ break;
+ case 5://D65
+ wx = 0.3127f;
+ wy = 0.3290f;
+ break;
+ case 6://D80
+ wx = 0.2937f;
+ wy = 0.3092f;
+ break;
+ case 7://D120
+ wx = 0.2697f;
+ wy = 0.2808f;
+ break;
+ case 8://stdA
+ wx = 0.4476f;
+ wy = 0.4074f;
+ break;
+ case 9://2000K
+ wx = 0.5266f;
+ wy = 0.4133f;
+ break;
+ case 10://1500K
+ wx = 0.5857f;
+ wy = 0.3932f;
+ break;
+ }
+
+ if (primListener) {
+ primListener->iprimChanged (r_x, r_y, b_x, b_y, g_x, g_y, wx, wy);
+ }
+ }
+ }
+
if (params->colorappearance.enabled) {
// L histo and Chroma histo for ciecam
// histogram well be for Lab (Lch) values, because very difficult to do with J,Q, M, s, C
@@ -1718,6 +1866,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
}
+ // if (todo & (M_AUTOEXP | M_RGBCURVE)) {
+
// Update the monitor color transform if necessary
if ((todo & M_MONITOR) || (lastOutputProfile != params->icm.outputProfile) || lastOutputIntent != params->icm.outputIntent || lastOutputBPC != params->icm.outputBPC) {
lastOutputProfile = params->icm.outputProfile;
@@ -1787,15 +1937,31 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
delete oprevi;
oprevi = nullptr;
}
-
-
}
+void ImProcCoordinator::setTweakOperator (TweakOperator *tOperator)
+{
+ if (tOperator) {
+ tweakOperator = tOperator;
+ }
+}
+
+void ImProcCoordinator::unsetTweakOperator (TweakOperator *tOperator)
+{
+ if (tOperator && tOperator == tweakOperator) {
+ tweakOperator = nullptr;
+ }
+}
void ImProcCoordinator::freeAll()
{
if (allocated) {
+ if (spotprev && spotprev != oprevi) {
+ delete spotprev;
+ }
+ spotprev = nullptr;
+
if (orig_prev != oprevi) {
delete oprevi;
}
@@ -1828,6 +1994,15 @@ void ImProcCoordinator::freeAll()
allocated = false;
}
+void ImProcCoordinator::allocCache (Imagefloat* &imgfloat)
+{
+ if (imgfloat == nullptr) {
+ imgfloat = new Imagefloat(pW, pH);
+ } else {
+ imgfloat->allocate(pW, pH);
+ }
+}
+
/** @brief Handles image buffer (re)allocation and trigger sizeChanged of SizeListener[s]
* If the scale change, this method will free all buffers and reallocate ones of the new size.
* It will then tell to the SizeListener that size has changed (sizeChanged)
@@ -1846,9 +2021,9 @@ void ImProcCoordinator::setScale(int prevscale)
do {
prevscale--;
- PreviewProps pp(0, 0, fw, fh, prevscale);
- imgsrc->getSize(pp, nW, nH);
- } while (nH < 400 && prevscale > 1 && (nW * nH < 1000000)); // sctually hardcoded values, perhaps a better choice is possible
+ PreviewProps pp (0, 0, fw, fh, prevscale);
+ imgsrc->getSize (pp, nW, nH);
+ } while (nH < 400 && prevscale > 1 && (nW * nH < 1000000)); // actually hardcoded values, perhaps a better choice is possible
if (nW != pW || nH != pH) {
@@ -2289,35 +2464,37 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
MyMutex::MyLock lock(mProcessing);
int fW, fH;
+ std::unique_ptr validParams(new ProcParams());
+ getParams(validParams.get());
- int tr = getCoarseBitMask(params->coarse);
+ int tr = getCoarseBitMask(validParams->coarse);
imgsrc->getFullSize(fW, fH, tr);
PreviewProps pp(0, 0, fW, fH, 1);
- ProcParams ppar = *params;
+ ProcParams ppar = *validParams;
ppar.toneCurve.hrenabled = false;
ppar.icm.inputProfile = "(none)";
Imagefloat* im = new Imagefloat(fW, fH);
imgsrc->preprocess(ppar.raw, ppar.lensProf, ppar.coarse);
double dummy = 0.0;
imgsrc->demosaic(ppar.raw, false, dummy);
- ColorTemp currWB = ColorTemp(params->wb.temperature, params->wb.green, params->wb.equal, params->wb.method);
+ ColorTemp currWB = ColorTemp(validParams->wb.temperature, validParams->wb.green, validParams->wb.equal, validParams->wb.method);
- if (params->wb.method == "Camera") {
+ if (validParams->wb.method == "Camera") {
currWB = imgsrc->getWB();
- } else if (params->wb.method == "autold") {
- if (lastAwbEqual != params->wb.equal || lastAwbTempBias != params->wb.tempBias) {
+ } else if (validParams->wb.method == "autold") {
+ if (lastAwbEqual != validParams->wb.equal || lastAwbTempBias != validParams->wb.tempBias) {
double rm, gm, bm;
imgsrc->getAutoWBMultipliers(rm, gm, bm);
if (rm != -1.) {
- autoWB.update(rm, gm, bm, params->wb.equal, params->wb.tempBias);
- lastAwbEqual = params->wb.equal;
- lastAwbTempBias = params->wb.tempBias;
+ autoWB.update(rm, gm, bm, validParams->wb.equal, validParams->wb.tempBias);
+ lastAwbEqual = validParams->wb.equal;
+ lastAwbTempBias = validParams->wb.tempBias;
} else {
lastAwbEqual = -1.;
lastAwbTempBias = 0.0;
- autoWB.useDefaults(params->wb.equal);
+ autoWB.useDefaults(validParams->wb.equal);
}
}
@@ -2339,12 +2516,12 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
im = trImg;
}
- if (params->crop.enabled) {
- Imagefloat *tmpim = new Imagefloat(params->crop.w, params->crop.h);
- int cx = params->crop.x;
- int cy = params->crop.y;
- int cw = params->crop.w;
- int ch = params->crop.h;
+ if (validParams->crop.enabled) {
+ Imagefloat *tmpim = new Imagefloat(validParams->crop.w, validParams->crop.h);
+ int cx = validParams->crop.x;
+ int cy = validParams->crop.y;
+ int cw = validParams->crop.w;
+ int ch = validParams->crop.h;
#ifdef _OPENMP
#pragma omp parallel for
#endif
@@ -2375,7 +2552,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
}
int imw, imh;
- double tmpScale = ipf.resizeScale(params.get(), fW, fH, imw, imh);
+ double tmpScale = ipf.resizeScale(validParams.get(), fW, fH, imw, imh);
if (tmpScale != 1.0) {
Imagefloat* tempImage = new Imagefloat(imw, imh);
@@ -2484,12 +2661,22 @@ void ImProcCoordinator::process()
|| params->dehaze != nextParams->dehaze
|| params->pdsharpening != nextParams->pdsharpening
|| params->filmNegative != nextParams->filmNegative
+ || params->spot.enabled != nextParams->spot.enabled
|| sharpMaskChanged;
sharpMaskChanged = false;
*params = *nextParams;
int change = changeSinceLast;
changeSinceLast = 0;
+
+ if (tweakOperator) {
+ // TWEAKING THE PROCPARAMS FOR THE SPOT ADJUSTMENT MODE
+ backupParams();
+ tweakOperator->tweakParams(*params);
+ } else if (paramsBackup) {
+ paramsBackup.release();
+ }
+
paramsUpdateMutex.unlock();
// M_VOID means no update, and is a bit higher that the rest
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index 9735f8be8..8e4586c6d 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -42,6 +42,7 @@ namespace rtengine
using namespace procparams;
class Crop;
+class TweakOperator;
/** @brief Manages the image processing, espc. of the preview windows
*
@@ -62,6 +63,7 @@ class ImProcCoordinator final : public StagedImageProcessor, public HistogramObs
protected:
Imagefloat *orig_prev;
Imagefloat *oprevi;
+ Imagefloat *spotprev;
LabImage *oprevl;
LabImage *nprevl;
Imagefloat *fattal_11_dcrop_cache; // global cache for ToneMapFattal02 used in 1:1 detail windows (except when denoise is active)
@@ -190,6 +192,7 @@ protected:
ImageTypeListener *imageTypeListener;
FilmNegListener *filmNegListener;
AutoColorTonListener* actListener;
+ AutoprimListener* primListener;
AutoChromaListener* adnListener;
WaveletListener* awavListener;
RetinexListener* dehaListener;
@@ -205,6 +208,9 @@ protected:
MyMutex minit; // to gain mutually exclusive access to ... to what exactly?
+ void backupParams();
+ void restoreParams();
+ void allocCache (Imagefloat* &imgfloat);
void notifyHistogramChanged();
void reallocAll();
/// Updates L, R, G, and B histograms. Returns true unless not updated.
@@ -219,7 +225,9 @@ protected:
void updatePreviewImage (int todo, bool panningRelatedChange);
MyMutex mProcessing;
- const std::unique_ptr params;
+ const std::unique_ptr params; // used for the rendering, can be eventually tweaked
+ std::unique_ptr paramsBackup; // backup of the untweaked procparams
+ TweakOperator* tweakOperator;
// for optimization purpose, the output profile, output rendering intent and
// output BPC will trigger a regeneration of the profile on parameter change only
@@ -368,7 +376,7 @@ public:
~ImProcCoordinator () override;
void assign (ImageSource* imgsrc);
- void getParams (procparams::ProcParams* dst) override;
+ void getParams (procparams::ProcParams* dst, bool tweaked=false) override;
void startProcessing (int changeCode) override;
ProcParams* beginUpdateParams () override;
@@ -409,6 +417,8 @@ public:
DetailedCrop* createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow) override;
+ void setTweakOperator (TweakOperator *tOperator) override;
+ void unsetTweakOperator (TweakOperator *tOperator) override;
bool getAutoWB (double& temp, double& green, double equal, double tempBias) override;
void getCamWB (double& temp, double& green) override;
void getSpotWB (int x, int y, int rectSize, double& temp, double& green) override;
@@ -501,6 +511,10 @@ public:
{
actListener = bwct;
}
+ void setAutoprimListener (AutoprimListener* pri) override
+ {
+ primListener = pri;
+ }
void setAutoChromaListener (AutoChromaListener* adn) override
{
adnListener = adn;
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index 047f045e2..c421f72d1 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -3582,21 +3582,13 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
}
if (sCurveEnabled) {
- delete sCurve;
+ delete sCurve;
}
if (vCurveEnabled) {
delete vCurve;
}
- // shadowsHighlights(lab);
- // shadowsHighlights(lab, params->sh.enabled, params->sh.lab,params->sh.highlights ,params->sh.shadows, params->sh.radius, scale, params->sh.htonalwidth, params->sh.stonalwidth);
-/*
- if (params->localContrast.enabled) {
- // Alberto's local contrast
- localContrast(lab, lab->L, params->localContrast, false, scale);
- }
- */
}
/**
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index c11f0810b..ae914fcda 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -23,6 +23,7 @@
#include "coord2d.h"
#include "gamutwarning.h"
+#include "imagedimensions.h"
#include "jaggedarray.h"
#include "pipettebuffer.h"
#include "array2D.h"
@@ -78,12 +79,15 @@ class Image8;
class Imagefloat;
class LabImage;
class wavelet_decomposition;
+class ImageSource;
+class ColorTemp;
namespace procparams
{
class ProcParams;
+struct SpotEntry;
struct DehazeParams;
struct FattalToneMappingParams;
struct ColorManagementParams;
@@ -448,6 +452,9 @@ enum class BlurType {
float Mad(const float * DataList, int datalen);
float MadRgb(const float * DataList, int datalen);
+ // spot removal tool
+ void removeSpots (rtengine::Imagefloat* img, rtengine::ImageSource* imgsrc, const std::vector &entries, const PreviewProps &pp, const rtengine::ColorTemp &currWB, const procparams::ColorManagementParams *cmp, int tr);
+
// pyramid wavelet
void cbdl_local_temp(float ** src, float ** loctemp, int srcwidth, int srcheight, const float * mult, float kchro, const double dirpyrThreshold, const float mergeL, const float contres, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale, bool multiThread);
void dirpyr_equalizer(const float * const * src, float ** dst, int srcwidth, int srcheight, const float * const * l_a, const float * const * l_b, const double * mult, double dirpyrThreshold, double skinprot, float b_l, float t_l, float t_r, int scale); //Emil's directional pyramid wavelet
@@ -477,7 +484,8 @@ enum class BlurType {
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;
+ void workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, Glib::ustring &profile, double gampos, double slpos, int &illum, int prim, cmsHTRANSFORM &transform, bool normalizeIn = true, bool normalizeOut = true, bool keepTransForm = false) const;
+ void preserv(LabImage *nprevl, LabImage *provis, int cw, int ch);
bool transCoord(int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr) const;
bool transCoord(int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr) const;
diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc
index 81a304fd3..f07601c45 100644
--- a/rtengine/iplab2rgb.cc
+++ b/rtengine/iplab2rgb.cc
@@ -16,18 +16,20 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
*/
-#include "rtengine.h"
-#include "image8.h"
-#include "imagefloat.h"
-#include "labimage.h"
-#include "improcfun.h"
#include
-#include "iccstore.h"
-#include "iccmatrices.h"
-#include "settings.h"
+
#include "alignedbuffer.h"
#include "color.h"
+#include "iccmatrices.h"
+#include "iccstore.h"
+#include "image8.h"
+#include "imagefloat.h"
+#include "improcfun.h"
+#include "labimage.h"
#include "procparams.h"
+#include "rtengine.h"
+#include "settings.h"
+#include "utils.h"
namespace rtengine
{
@@ -120,6 +122,19 @@ inline void copyAndClamp(const LabImage *src, unsigned char *dst, const double r
} // namespace
+
+float gammalog(float x, float p, float s, float g3, float g4)
+{
+ return x <= g3 ? x * s : (1.f + g4) * xexpf(xlogf(x) / p) - g4;//continuous
+}
+
+#ifdef __SSE2__
+vfloat gammalog(vfloat x, vfloat p, vfloat s, vfloat g3, vfloat g4)
+{
+ return vself(vmaskf_le(x, g3), x * s, (F2V(1.f) + g4) * xexpf(xlogf(x) / p) - g4);//continuous
+}
+#endif
+
// Used in ImProcCoordinator::updatePreviewImage (rtengine/improccoordinator.cc)
// Crop::update (rtengine/dcrop.cc)
// Thumbnail::processImage (rtengine/rtthumbnail.cc)
@@ -373,8 +388,31 @@ Imagefloat* ImProcFunctions::lab2rgbOut(LabImage* lab, int cx, int cy, int cw, i
return image;
}
+void ImProcFunctions::preserv(LabImage *nprevl, LabImage *provis, int cw, int ch)
+{//avoid too strong in middle values chroma when changing primaries
+ float pres = 0.01f * params->icm.preser;
+ float neutral = 2000000000.f;//if a2 + b2 < 200000000 scale 0..100 a and b about : 140 > a & b > -140 decrease effect
+ float medneutral = 10000000.f;//plein effect 10 > a & b > -10
+ float aaneu = 1.f / (medneutral - neutral);
+ float bbneu = - aaneu * neutral;
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic, 16) nowait
+#endif
+ for (int i = 0; i < ch; ++i)
+ for (int j = 0; j < cw; ++j) {
+ float neu = SQR(provis->a[i][j]) + SQR(provis->b[i][j]);
+ if (neu < medneutral) {//plein effect
+ nprevl->a[i][j] = intp(pres, provis->a[i][j], nprevl->a[i][j]);
+ nprevl->b[i][j] = intp(pres, provis->b[i][j], nprevl->b[i][j]);
+ } else if (neu < neutral) {//decrease effect
+ float presred = aaneu * neu + bbneu;
+ nprevl->a[i][j] = intp(pres * presred, provis->a[i][j], nprevl->a[i][j]);
+ nprevl->b[i][j] = intp(pres * presred, provis->b[i][j], nprevl->b[i][j]);
+ }
+ }
+}
-void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, const Glib::ustring &profile, double gampos, double slpos, cmsHTRANSFORM &transform, bool normalizeIn, bool normalizeOut, bool keepTransForm) const
+void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, Glib::ustring &profile, double gampos, double slpos, int &illum, int prim, cmsHTRANSFORM &transform, bool normalizeIn, bool normalizeOut, bool keepTransForm) const
{
const TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile);
@@ -394,6 +432,163 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
}
};
+ if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") {
+ if (settings->verbose) {
+ printf("Profile=%s\n", profile.c_str());
+ }
+ } else {
+ if (settings->verbose) {
+ printf("profile not accepted\n");
+ }
+ return;
+ }
+
+ if (mul == -5 && gampos == 2.4 && slpos == 12.92310) {//must be change if we change settings RT sRGB
+ //only in this case we can shortcut..all process..no gamut control..because we reduce...leads to very small differences, but big speedup
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic, 16) if (multiThread)
+#endif
+
+ for (int i = 0; i < ch; ++i)
+ for (int j = 0; j < cw; ++j) {
+ float r = src->r(i, j);
+ float g = src->g(i, j);
+ float b = src->b(i, j);
+ r = (Color::igammatab_srgb[r]) / 65535.f;
+ g = (Color::igammatab_srgb[g]) / 65535.f;
+ b = (Color::igammatab_srgb[b]) / 65535.f;
+ dst->r(i, j) = r;
+ dst->g(i, j) = g;
+ dst->b(i, j) = b;
+ }
+ return;
+
+ }
+
+ if (mul == 1 ||(params->icm.wprim == ColorManagementParams::Primaries::DEFAULT && params->icm.will == ColorManagementParams::Illuminant::DEFAULT)) {//shortcut and speedup when no call primaries and illuminant - no gamut control...in this case be carefull
+ GammaValues g_a; //gamma parameters
+ double pwr = 1.0 / static_cast(gampos);
+ Color::calcGamma(pwr, slpos, g_a); // call to calcGamma with selected gamma and slope
+
+#ifdef _OPENMP
+# pragma omp parallel for schedule(dynamic,16) if (multiThread)
+#endif
+ for (int y = 0; y < ch; ++y) {
+ int x = 0;
+#ifdef __SSE2__
+ for (; x < cw - 3; x += 4) {
+ STVFU(dst->r(y,x), F2V(65536.f) * gammalog(LVFU(src->r(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
+ STVFU(dst->g(y,x), F2V(65536.f) * gammalog(LVFU(src->g(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
+ STVFU(dst->b(y,x), F2V(65536.f) * gammalog(LVFU(src->b(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
+ }
+#endif
+ for (; x < cw; ++x) {
+ dst->r(y,x) = 65536.f * gammalog(src->r(y,x), gampos, slpos, g_a[3], g_a[4]);
+ dst->g(y,x) = 65536.f * gammalog(src->g(y,x), gampos, slpos, g_a[3], g_a[4]);
+ dst->b(y,x) = 65536.f * gammalog(src->b(y,x), gampos, slpos, g_a[3], g_a[4]);
+ }
+ }
+ return;
+ }
+
+
+ float redxx = params->icm.redx;
+ float redyy = params->icm.redy;
+ float bluxx = params->icm.blux;
+ float bluyy = params->icm.bluy;
+ float grexx = params->icm.grex;
+ float greyy = params->icm.grey;
+
+ if (prim == 12) {//convert datas area to xy
+ float redgraphx = params->icm.labgridcieALow;
+ float redgraphy = params->icm.labgridcieBLow;
+ float blugraphx = params->icm.labgridcieAHigh;
+ float blugraphy = params->icm.labgridcieBHigh;
+ float gregraphx = params->icm.labgridcieGx;
+ float gregraphy = params->icm.labgridcieGy;
+ redxx = 0.55f * (redgraphx + 1.f) - 0.1f;
+ redxx = rtengine::LIM(redxx, 0.41f, 1.f);//limit values for xy (arbitrary)
+ redyy = 0.55f * (redgraphy + 1.f) - 0.1f;
+ redyy = rtengine::LIM(redyy, 0.f, 0.7f);
+ bluxx = 0.55f * (blugraphx + 1.f) - 0.1f;
+ bluxx = rtengine::LIM(bluxx, -0.1f, 0.5f);
+ bluyy = 0.55f * (blugraphy + 1.f) - 0.1f;
+ bluyy = rtengine::LIM(bluyy, -0.1f, 0.5f);
+ grexx = 0.55f * (gregraphx + 1.f) - 0.1f;
+ grexx = rtengine::LIM(grexx, -0.1f, 0.4f);
+ greyy = 0.55f * (gregraphy + 1.f) - 0.1f;
+ greyy = rtengine::LIM(greyy, 0.5f, 1.f);
+ }
+
+ switch (ColorManagementParams::Primaries(prim)) {
+ case ColorManagementParams::Primaries::DEFAULT: {
+ break;
+ }
+
+ case ColorManagementParams::Primaries::SRGB: {
+ profile = "sRGB";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::ADOBE_RGB: {
+ profile = "Adobe RGB";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::PRO_PHOTO: {
+ profile = "ProPhoto";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::REC2020: {
+ profile = "Rec2020";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::ACES_P1: {
+ profile = "ACESp1";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::WIDE_GAMUT: {
+ profile = "WideGamut";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::ACES_P0: {
+ profile = "ACESp0";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::BRUCE_RGB: {
+ profile = "BruceRGB";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::BETA_RGB: {
+ profile = "Beta RGB";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::BEST_RGB: {
+ profile = "BestRGB";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::CUSTOM: {
+ profile = "Custom";
+ break;
+ }
+
+ case ColorManagementParams::Primaries::CUSTOM_GRID: {
+ profile = "Custom";
+ break;
+ }
+ }
+
+ if (settings->verbose && prim != 0) {
+ printf("prim=%i Profile Destination=%s\n", prim, profile.c_str());
+ }
cmsHTRANSFORM hTransform = nullptr;
if (transform) {
hTransform = transform;
@@ -418,8 +613,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
D60 = 6005 // for ACES AP0 and AP1
};
- ColorTemp temp = ColorTemp::D50;
-
+ double tempv4 = 5003.;
float p[6]; //primaries
//primaries for 10 working profiles ==> output profiles
@@ -430,6 +624,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 0.8260;
p[4] = 0.1570;
p[5] = 0.0180;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D50);
} else if (profile == "Adobe RGB") {
p[0] = 0.6400; //Adobe primaries
p[1] = 0.3300;
@@ -437,7 +632,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 0.7100;
p[4] = 0.1500;
p[5] = 0.0600;
- temp = ColorTemp::D65;
+ tempv4 = 6504.;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D65);
} else if (profile == "sRGB") {
p[0] = 0.6400; // sRGB primaries
p[1] = 0.3300;
@@ -445,7 +641,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 0.6000;
p[4] = 0.1500;
p[5] = 0.0600;
- temp = ColorTemp::D65;
+ tempv4 = 6504.;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D65);
} else if (profile == "BruceRGB") {
p[0] = 0.6400; // Bruce primaries
p[1] = 0.3300;
@@ -453,14 +650,16 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 0.6500;
p[4] = 0.1500;
p[5] = 0.0600;
- temp = ColorTemp::D65;
- } else if (profile == "Beta RGB") {
+ tempv4 = 6504.;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D65);
+ } else if (profile == "Beta RGB") {
p[0] = 0.6888; // Beta primaries
p[1] = 0.3112;
p[2] = 0.1986;
p[3] = 0.7551;
p[4] = 0.1265;
p[5] = 0.0352;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D50);
} else if (profile == "BestRGB") {
p[0] = 0.7347; // Best primaries
p[1] = 0.2653;
@@ -468,6 +667,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 0.7750;
p[4] = 0.1300;
p[5] = 0.0350;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D50);
} else if (profile == "Rec2020") {
p[0] = 0.7080; // Rec2020 primaries
p[1] = 0.2920;
@@ -475,7 +675,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 0.7970;
p[4] = 0.1310;
p[5] = 0.0460;
- temp = ColorTemp::D65;
+ tempv4 = 6504.;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D65);
} else if (profile == "ACESp0") {
p[0] = 0.7347; // ACES P0 primaries
p[1] = 0.2653;
@@ -483,7 +684,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 1.0;
p[4] = 0.0001;
p[5] = -0.0770;
- temp = ColorTemp::D60;
+ tempv4 = 6004.;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D60);
} else if (profile == "ACESp1") {
p[0] = 0.713; // ACES P1 primaries
p[1] = 0.293;
@@ -491,7 +693,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 0.830;
p[4] = 0.128;
p[5] = 0.044;
- temp = ColorTemp::D60;
+ tempv4 = 6004.;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D60);
} else if (profile == "ProPhoto") {
p[0] = 0.7347; //ProPhoto and default primaries
p[1] = 0.2653;
@@ -499,6 +702,14 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[3] = 0.8404;
p[4] = 0.0366;
p[5] = 0.0001;
+ illum = toUnderlying(ColorManagementParams::Illuminant::D50);
+ } else if (profile == "Custom") {
+ p[0] = redxx;
+ p[1] = redyy;
+ p[2] = grexx;
+ p[3] = greyy;
+ p[4] = bluxx;
+ p[5] = bluyy;
} else {
p[0] = 0.7347; //default primaries always unused
p[1] = 0.2653;
@@ -528,27 +739,145 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
// 7 parameters for smoother curves
cmsCIExyY xyD;
- cmsWhitePointFromTemp(&xyD, (double)temp);
- if (profile == "ACESp0") {
- xyD = {0.32168, 0.33767, 1.0};//refine white point to avoid differences
+ Glib::ustring ills = "D50";
+ switch (ColorManagementParams::Illuminant(illum)) {
+ case ColorManagementParams::Illuminant::DEFAULT:
+ case ColorManagementParams::Illuminant::STDA:
+ case ColorManagementParams::Illuminant::TUNGSTEN_2000K:
+ case ColorManagementParams::Illuminant::TUNGSTEN_1500K: {
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D41: {
+ tempv4 = 4100.;
+ ills = "D41";
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D50: {
+ tempv4 = 5003.;
+ ills = "D50";
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D55: {
+ tempv4 = 5500.;
+ ills = "D55";
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D60: {
+ tempv4 = 6004.;
+ ills = "D60";
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D65: {
+ tempv4 = 6504.;
+ ills = "D65";
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D80: {
+ tempv4 = 8000.;
+ ills = "D80";
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D120: {
+ tempv4 = 12000.;
+ ills = "D120";
+ break;
+ }
}
+ cmsWhitePointFromTemp(&xyD, tempv4);
+
+ switch (ColorManagementParams::Illuminant(illum)) {
+ case ColorManagementParams::Illuminant::DEFAULT:
+ case ColorManagementParams::Illuminant::D55:
+ case ColorManagementParams::Illuminant::D80: {
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D41: {
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D50: {
+ xyD = {0.3457, 0.3585, 1.0}; // near LCMS values but not perfect... it's a compromise!!
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D60: {
+ xyD = {0.32168, 0.33767, 1.0};
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D65: {
+ xyD = {0.312700492, 0.329000939, 1.0};
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::D120: {
+ xyD = {0.269669, 0.28078, 1.0};
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::STDA: {
+ xyD = {0.447573, 0.407440, 1.0};
+ ills = "stdA 2875K";
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::TUNGSTEN_2000K: {
+ xyD = {0.526591, 0.41331, 1.0};
+ ills = "Tungsten 2000K";
+ break;
+ }
+
+ case ColorManagementParams::Illuminant::TUNGSTEN_1500K: {
+ xyD = {0.585703, 0.393157, 1.0};
+ ills = "Tungsten 1500K";
+ break;
+ }
+ }
+
+ //D41 0.377984 0.381229
+ //D55 0.332424 0.347426
+ //D80 0.293755 0.309185
+ //D75 0.299021 0.314852
cmsToneCurve* GammaTRC[3];
GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, five, gammaParams);//5 = more smoother than 4
+ cmsHPROFILE oprofdef = nullptr;
const cmsCIExyYTRIPLE Primaries = {
{p[0], p[1], 1.0}, // red
{p[2], p[3], 1.0}, // green
{p[4], p[5], 1.0} // blue
};
- const cmsHPROFILE oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC);
- cmsFreeToneCurve(GammaTRC[0]);
+ oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC);
+ cmsWriteTag(oprofdef, cmsSigRedTRCTag, GammaTRC[0]);
+ cmsWriteTag(oprofdef, cmsSigGreenTRCTag, GammaTRC[1]);
+ cmsWriteTag(oprofdef, cmsSigBlueTRCTag, GammaTRC[2]);
+ //to read XYZ values and illuminant
+ if (rtengine::settings->verbose) {
+ cmsCIEXYZ *redT = static_cast(cmsReadTag(oprofdef, cmsSigRedMatrixColumnTag));
+ cmsCIEXYZ *greenT = static_cast(cmsReadTag(oprofdef, cmsSigGreenMatrixColumnTag));
+ cmsCIEXYZ *blueT = static_cast(cmsReadTag(oprofdef, cmsSigBlueMatrixColumnTag));
+ printf("Illuminant=%s\n", ills.c_str());
+ printf("rX=%f gX=%f bX=%f\n", redT->X, greenT->X, blueT->X);
+ printf("rY=%f gY=%f bY=%f\n", redT->Y, greenT->Y, blueT->Y);
+ printf("rZ=%f gZ=%f bZ=%f\n", redT->Z, greenT->Z, blueT->Z);
+ }
+
+ cmsFreeToneCurve(GammaTRC[0]);
if (oprofdef) {
- constexpr cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
+ constexpr cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | cmsFLAGS_BLACKPOINTCOMPENSATION | cmsFLAGS_GAMUTCHECK;
const cmsHPROFILE iprof = ICCStore::getInstance()->getXYZProfile();
lcmsMutex->lock();
- hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.outputIntent, flags);
+ hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.aRendIntent, flags);
lcmsMutex->unlock();
}
}
diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc
index ca1319052..fcc8a9462 100644
--- a/rtengine/iplocallab.cc
+++ b/rtengine/iplocallab.cc
@@ -439,6 +439,8 @@ struct local_params {
float thr;
float stru;
int chro, cont, sens, sensh, senscb, sensbn, senstm, sensex, sensexclu, sensden, senslc, senssf, senshs, senscolor;
+ float reparden;
+ float repartm;
float clarityml;
float contresid;
bool deltaem;
@@ -785,9 +787,10 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
float laplac = ((float)locallab.spots.at(sp).laplace);
float thre = locallab.spots.at(sp).thresh;
- if (thre > 8.f || thre < 0.f) {//to avoid artifacts if user does not clear cache with new settings. Can be suppressed after
- thre = 2.f;
- }
+// if (thre > 8.f || thre < 0.f) {//to avoid artifacts if user does not clear cache with new settings. Can be suppressed after
+// thre = 2.f;
+// }
+ thre = LIM(thre, 0.f, 10.0f);
double local_x = locallab.spots.at(sp).loc.at(0) / 2000.0;
double local_y = locallab.spots.at(sp).loc.at(2) / 2000.0;
@@ -800,9 +803,10 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
float balanch = (float) locallab.spots.at(sp).balanh;
int colorde = (int) locallab.spots.at(sp).colorde;
- if (iterati > 4.f || iterati < 0.2f) {//to avoid artifacts if user does not clear cache with new settings Can be suppressed after
- iterati = 2.f;
- }
+// if (iterati > 4.f || iterati < 0.2f) {//to avoid artifacts if user does not clear cache with new settings Can be suppressed after
+// iterati = 2.f;
+// }
+ iterati = LIM(iterati, 0.2f, 10.0f);
float neigh = float (locallab.spots.at(sp).neigh);
float chromaPastel = float (locallab.spots.at(sp).pastels) / 100.0f;
@@ -1122,6 +1126,8 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
int local_noiselequal = locallab.spots.at(sp).noiselequal;
float local_noisechrodetail = (float)locallab.spots.at(sp).noisechrodetail;
int local_sensiden = locallab.spots.at(sp).sensiden;
+ float local_reparden = locallab.spots.at(sp).reparden;
+ float local_repartm = locallab.spots.at(sp).repartm;
float local_detailthr = (float)locallab.spots.at(sp).detailthr;
float local_recothr = (float)locallab.spots.at(sp).recothres;
float local_lowthr = (float)locallab.spots.at(sp).lowthres;
@@ -1580,6 +1586,8 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
lp.noisecf = local_noisecf;
lp.noisecc = local_noisecc;
lp.sensden = local_sensiden;
+ lp.reparden = local_reparden;
+ lp.repartm = local_repartm;
lp.bilat = locallab.spots.at(sp).bilateral;
lp.nldet = locallab.spots.at(sp).nldet;
lp.nlstr = locallab.spots.at(sp).nlstr;
@@ -1639,13 +1647,6 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
lp.hlcomp = locallab.spots.at(sp).hlcompr;
lp.hlcompthr = locallab.spots.at(sp).hlcomprthresh;
lp.expcomp = LIM(locallab.spots.at(sp).expcomp, -2.0, 4.0); //to prevent crash with Old pp3 with integer
- //increase sensitivity for low values
- float proexp = lp.expcomp;
- if (std::fabs(proexp) < 0.6f) {
- float interm = std::fabs(proexp) / 0.6f;
- interm = pow(interm, 3.f);
- lp.expcomp = proexp * interm;
- }
lp.expchroma = locallab.spots.at(sp).expchroma / 100.;
lp.sensex = local_sensiex;
lp.war = local_warm;
@@ -2557,6 +2558,10 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab, int call)
f = 0.9f;
c = 0.59f;
nc = 0.9f;
+ } else if (params->locallab.spots.at(sp).sursour == "Dark") {
+ f = 0.8f;
+ c = 0.525f;
+ nc = 0.8f;
}
//viewing condition for surround
@@ -2609,8 +2614,15 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab, int call)
float schr = 0.f;
float mchr = 0.f;
+ float cchr = 0.f;
if (ciec) {
+
+ cchr = params->locallab.spots.at(sp).chroml;
+ if (cchr == -100.0f) {
+ cchr = -99.8f;
+ }
+
schr = params->locallab.spots.at(sp).saturl;
if (schr > 0.f) {
@@ -2765,7 +2777,7 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab, int call)
if(ciec) {
Qpro = CAMBrightCurveQ[(float)(Qpro * coefQ)] / coefQ; //brightness and contrast
float rstprotection = 50.f;//default value to avoid 1 slider
- float chr = 0.f;//no use of chroma
+ // float chr = 0.f;//no use of chroma
float Mp, sres;
Mp = Mpro / 100.0f;
Ciecam02::curvecolorfloat(mchr, Mp, sres, 2.5f);
@@ -2793,7 +2805,7 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab, int call)
Qpro = QproFactor * sqrtf(Jpro);
float Cp = (spro * spro * Qpro) / (1000000.f);
Cpro = Cp * 100.f;
- Ciecam02::curvecolorfloat(chr, Cp, sres, 1.8f);
+ Ciecam02::curvecolorfloat(cchr, Cp, sres, 1.8f);
Color::skinredfloat(Jpro, hpro, sres, Cp, 55.f, 30.f, 1, rstprotection, 100.f, Cpro);
}
@@ -2991,6 +3003,7 @@ void ImProcFunctions::exlabLocal(local_params& lp, float strlap, int bfh, int bf
const bool exec = (lp.expmet == 1 && linear > 0.f && lp.laplacexp > 0.1f);
if(!exec) {//for standard exposure
+
const float cexp_scale = std::pow(2.f, lp.expcomp);
const float ccomp = (rtengine::max(0.f, lp.expcomp) + 1.f) * lp.hlcomp / 100.f;
const float cshoulder = ((maxran / rtengine::max(1.0f, cexp_scale)) * (lp.hlcompthr / 200.f)) + 0.1f;
@@ -3261,6 +3274,11 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, Lab
difa = tmp1.a[loy - begy][lox - begx] - original->a[y][x];
difb = tmp1.b[loy - begy][lox - begx] - original->b[y][x];
} else { //dcrop
+ const float repart = 1.0f - 0.01f * lp.reparden;
+ tmp1.L[y][x] = intp(repart, original->L[y][x], tmp1.L[y][x]);
+ tmp1.a[y][x] = intp(repart, original->a[y][x], tmp1.a[y][x]);
+ tmp1.b[y][x] = intp(repart, original->b[y][x], tmp1.b[y][x]);
+
difL = tmp1.L[y][x] - original->L[y][x];
difa = tmp1.a[y][x] - original->a[y][x];
difb = tmp1.b[y][x] - original->b[y][x];
@@ -3407,16 +3425,14 @@ void ImProcFunctions::DeNoise_Local2(const struct local_params& lp, LabImage* or
float difL, difa, difb;
- // if (call == 2 /*|| call == 1 || call == 3 */) { //simpleprocess
- // difL = tmp1.L[loy - begy][lox - begx] - original->L[y][x];
- // difa = tmp1.a[loy - begy][lox - begx] - original->a[y][x];
- // difb = tmp1.b[loy - begy][lox - begx] - original->b[y][x];
- // } else { //dcrop
+ const float repart = 1.0f - 0.01f * lp.reparden;
+ tmp1.L[y-ystart][x-xstart] = intp(repart, original->L[y][x], tmp1.L[y-ystart][x-xstart]);
+ tmp1.a[y-ystart][x-xstart] = intp(repart, original->a[y][x], tmp1.a[y-ystart][x-xstart]);
+ tmp1.b[y-ystart][x-xstart] = intp(repart, original->b[y][x], tmp1.b[y-ystart][x-xstart]);
- difL = tmp1.L[y-ystart][x-xstart] - original->L[y][x];
- difa = tmp1.a[y-ystart][x-xstart] - original->a[y][x];
- difb = tmp1.b[y-ystart][x-xstart] - original->b[y][x];
- // }
+ difL = tmp1.L[y-ystart][x-xstart] - original->L[y][x];
+ difa = tmp1.a[y-ystart][x-xstart] - original->a[y][x];
+ difb = tmp1.b[y-ystart][x-xstart] - original->b[y][x];
difL *= localFactor * reducdEL;
difa *= localFactor * reducdEa;
@@ -4396,6 +4412,7 @@ void ImProcFunctions::retinex_pde(const float * datain, float * dataout, int bfw
*/
// BENCHFUN
+
#ifdef RT_FFTW3F_OMP
if (multiThread) {
fftwf_init_threads();
@@ -5047,7 +5064,7 @@ void ImProcFunctions::maskcalccol(bool invmask, bool pde, int bfw, int bfh, int
if (delt) {
const std::unique_ptr> rdEBuffer(new JaggedArray(bfw, bfh));
- float** rdE = *(rdEBuffer.get());
+ float** rdE = *rdEBuffer;
deltaEforMask(rdE, bfw, bfh, bufreserv.get(), hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, iterat, limscope, scope, lp.balance, lp.balanceh);
#ifdef _OPENMP
@@ -6058,13 +6075,16 @@ void ImProcFunctions::InverseColorLight_Local(bool tonequ, bool tonecurv, int sp
const std::unique_ptr tmpImage(new Imagefloat(GW, GH));
lab2rgb(*temp, *tmpImage, params->icm.workingProfile);
-
+ Glib::ustring prof = params->icm.workingProfile;
if (tonecurv) { //Tone response curve : does nothing if gamma=2.4 and slope=12.92 ==> gamma sRGB
const float gamtone = params->locallab.spots.at(sp).gamSH;
const float slotone = params->locallab.spots.at(sp).sloSH;
+ int ill = 0;
cmsHTRANSFORM dummy = nullptr;
- workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, -5, params->icm.workingProfile, 2.4, 12.92310, dummy, true, false, false);
- workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, 5, params->icm.workingProfile, gamtone, slotone, dummy, false, true, true);
+ workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false);
+ // workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, 5, prof, gamtone, slotone, illum, 0, dummy, false, true, true);//to keep if we want improve with illuminant and primaries
+ workingtrc(tmpImage.get(), tmpImage.get(), GW, GH, 1, prof, gamtone, slotone, ill, 0, dummy, false, true, true);//be carefull no gamut control
+
}
if (tonequ) {
@@ -6935,6 +6955,8 @@ void ImProcFunctions::transit_shapedetect2(int sp, float meantm, float stdtm, in
}
}
+
+
if (lp.equtm && senstype == 8) { //normalize luminance for Tone mapping , at this place we can use for others senstype!
float *datain = new float[bfh * bfw];
float *data = new float[bfh * bfw];
@@ -6974,6 +6996,24 @@ void ImProcFunctions::transit_shapedetect2(int sp, float meantm, float stdtm, in
delete [] data;
}
+
+ if (senstype == 8) {//strength Tone mapping
+ const float repart = 1.0f - 0.01f * lp.repartm;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if(multiThread)
+#endif
+
+ for (int y = ystart; y < yend; y++){
+ for (int x = xstart; x < xend; x++) {
+ bufexpfin->L[y - ystart][x - xstart]= intp(repart, original->L[y][x], bufexpfin->L[y - ystart][x - xstart]);
+ bufexpfin->a[y - ystart][x - xstart]= intp(repart, original->a[y][x], bufexpfin->a[y - ystart][x - xstart]);
+ bufexpfin->b[y - ystart][x - xstart]= intp(repart, original->b[y][x], bufexpfin->b[y - ystart][x - xstart]);
+ }
+ }
+ }
+
+
#ifdef _OPENMP
#pragma omp parallel if (multiThread)
#endif
@@ -7076,6 +7116,7 @@ void ImProcFunctions::transit_shapedetect2(int sp, float meantm, float stdtm, in
}
}
+
//deltaE
float abdelta2 = SQR(refa - maskptr->a[y][x]) + SQR(refb - maskptr->b[y][x]);
float chrodelta2 = SQR(std::sqrt(SQR(maskptr->a[y][x]) + SQR(maskptr->b[y][x])) - (chromaref * 327.68f));
@@ -11516,7 +11557,7 @@ void ImProcFunctions::Lab_Local(
}
}
- rgb2lab(*(tmpImage.get()), *bufexpfin, params->icm.workingProfile);
+ rgb2lab(*tmpImage, *bufexpfin, params->icm.workingProfile);
tmpImageorig.reset();
tmpImage.reset();
@@ -12298,7 +12339,7 @@ void ImProcFunctions::Lab_Local(
ImProcFunctions::impulse_nr(bufwv.get(), threshold);
}
- DeNoise_Local(call, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *(bufwv.get()), cx, cy, sk);
+ DeNoise_Local(call, lp, originalmaskbl.get(), levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *bufwv, cx, cy, sk);
if (lp.recur) {
original->CopyFrom(transformed, multiThread);
@@ -12565,6 +12606,8 @@ void ImProcFunctions::Lab_Local(
}
// transit_shapedetect_retinex(call, 4, bufgb.get(),bufmaskorigtm.get(), originalmasktm.get(), buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
+
+
transit_shapedetect2(sp, meantm, stdtm, call, 8, bufgb.get(), tmp1.get(), originalmasktm.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
// transit_shapedetect(8, tmp1.get(), originalmasktm.get(), bufchro, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
@@ -12708,7 +12751,7 @@ void ImProcFunctions::Lab_Local(
const float refb = chromaref * sin(hueref);
const std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd));
- float** reducDE = *(reducDEBuffer.get());
+ float** reducDE = *reducDEBuffer;
float ade = 0.01f * raddE;
float bde = 100.f - raddE;
@@ -12724,10 +12767,10 @@ void ImProcFunctions::Lab_Local(
}
const std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd));
- float** orig = *(origBuffer.get());
+ float** orig = *origBuffer;
const std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd));
- float** orig1 = *(origBuffer1.get());
+ float** orig1 = *origBuffer1;
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
@@ -13055,7 +13098,7 @@ void ImProcFunctions::Lab_Local(
const float refb = chromaref * sin(hueref);
const std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd));
- float** reducDE = *(reducDEBuffer.get());
+ float** reducDE = *reducDEBuffer;
float ade = 0.01f * raddE;
float bde = 100.f - raddE;
float sensibefore = ade * lp.sensh + bde;//we can change sensitivity 0.1 90 or 0.3 70 or 0.4 60
@@ -13071,10 +13114,10 @@ void ImProcFunctions::Lab_Local(
}
const std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd));
- float** orig = *(origBuffer.get());
+ float** orig = *origBuffer;
const std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd));
- float** orig1 = *(origBuffer1.get());
+ float** orig1 = *origBuffer1;
LabImage *tmpl = nullptr;
@@ -13907,13 +13950,16 @@ void ImProcFunctions::Lab_Local(
Imagefloat *tmpImage = nullptr;
tmpImage = new Imagefloat(bfw, bfh);
lab2rgb(*bufexpfin, *tmpImage, params->icm.workingProfile);
+ Glib::ustring prof = params->icm.workingProfile;
if (tonecurv) { //Tone response curve : does nothing if gamma=2.4 and slope=12.92 ==> gamma sRGB
- const float gamtone = params->locallab.spots.at(sp).gamSH;
- const float slotone = params->locallab.spots.at(sp).sloSH;
- cmsHTRANSFORM dummyTransForm = nullptr;
- workingtrc(tmpImage, tmpImage, bfw, bfh, -5, params->icm.workingProfile, 2.4, 12.92310, dummyTransForm, true, false, false);
- workingtrc(tmpImage, tmpImage, bfw, bfh, 5, params->icm.workingProfile, gamtone, slotone, dummyTransForm, false, true, true);
+ float gamtone = params->locallab.spots.at(sp).gamSH;
+ float slotone = params->locallab.spots.at(sp).sloSH;
+ cmsHTRANSFORM dummy = nullptr;
+ int ill =0;
+ workingtrc(tmpImage, tmpImage, bfw, bfh, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false);
+ // workingtrc(tmpImage, tmpImage, bfw, bfh, 5, prof, gamtone, slotone, 0, 0, dummy, false, true, true); //to keep if we want improve with illuminant and primaries
+ workingtrc(tmpImage, tmpImage, bfw, bfh, 1, prof, gamtone, slotone, ill, 0, dummy, false, true, true);//be carefull no gamut control
}
if (tonequ) {
@@ -13940,6 +13986,21 @@ void ImProcFunctions::Lab_Local(
maskrecov(bufexpfin.get(), original, bufmaskorigSH.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
}
+ const float repart = 1.0 - 0.01 * params->locallab.spots.at(sp).reparsh;
+ int bw = bufexporig->W;
+ int bh = bufexporig->H;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if(multiThread)
+#endif
+ for (int x = 0; x < bh; x++) {
+ for (int y = 0; y < bw; y++) {
+ bufexpfin->L[x][y] = intp(repart, bufexporig->L[x][y], bufexpfin->L[x][y]);
+ bufexpfin->a[x][y] = intp(repart, bufexporig->a[x][y], bufexpfin->a[x][y]);
+ bufexpfin->b[x][y] = intp(repart, bufexporig->b[x][y], bufexpfin->b[x][y]);
+ }
+ }
+
transit_shapedetect2(sp, 0.f, 0.f, call, 9, bufexporig.get(), bufexpfin.get(), originalmaskSH.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
if (lp.recur) {
@@ -14074,7 +14135,6 @@ void ImProcFunctions::Lab_Local(
if (lp.softmet == 0) {
ImProcFunctions::softLight(bufexpfin.get(), softLightParams);
} else if (lp.softmet == 1) {
-
const std::unique_ptr datain(new float[bfwr * bfhr]);
const std::unique_ptr dataout(new float[bfwr * bfhr]);
const std::unique_ptr dE(new float[bfwr * bfhr]);
@@ -14565,6 +14625,20 @@ void ImProcFunctions::Lab_Local(
bool invmask = false;
maskrecov(tmp1.get(), original, bufmaskoriglc.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
}
+ const float repart = 1.0 - 0.01 * params->locallab.spots.at(sp).reparw;
+ int bw = bufgb->W;
+ int bh = bufgb->H;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if(multiThread)
+#endif
+ for (int x = 0; x < bh; x++) {
+ for (int y = 0; y < bw; y++) {
+ tmp1->L[x][y] = intp(repart, bufgb->L[x][y], tmp1->L[x][y]);
+ tmp1->a[x][y] = intp(repart, bufgb->a[x][y], tmp1->a[x][y]);
+ tmp1->b[x][y] = intp(repart, bufgb->b[x][y], tmp1->b[x][y]);
+ }
+ }
transit_shapedetect2(sp, 0.f, 0.f, call, 10, bufgb.get(), tmp1.get(), originalmasklc.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk);
tmp1.reset();
@@ -14823,6 +14897,10 @@ void ImProcFunctions::Lab_Local(
} else {
+ if (lp.expcomp == 0.f && (lp.linear > 0.01f && lp.laplacexp > 0.1f)) {
+ lp.expcomp = 0.001f;// to enabled
+ }
+
if (lp.expcomp != 0.f ) { // || lp.laplacexp > 0.1f
if(lp.laplacexp <= 0.1f) {
lp.laplacexp = 0.2f; //force to use Laplacian wth very small values
@@ -14863,13 +14941,17 @@ void ImProcFunctions::Lab_Local(
fatParams.enabled = true;
fatParams.threshold = params->locallab.spots.at(sp).fatdetail;
fatParams.amount = params->locallab.spots.at(sp).fatamount;
- fatParams.anchor = 50.f; //params->locallab.spots.at(sp).fatanchor;
+ fatParams.anchor = params->locallab.spots.at(sp).fatanchor;
//const float sigm = 1.f; //params->locallab.spots.at(sp).fatlevel;
//const float mean = 1.f;// params->locallab.spots.at(sp).fatanchor;
const std::unique_ptr tmpImagefat(new Imagefloat(bfwr, bfhr));
- lab2rgb(*bufexpfin, *(tmpImagefat.get()), params->icm.workingProfile);
- ToneMapFattal02(tmpImagefat.get(), fatParams, 3, 0, nullptr, 0, 0, 1);//last parameter = 1 ==>ART algorithm
- rgb2lab(*(tmpImagefat.get()), *bufexpfin, params->icm.workingProfile);
+ lab2rgb(*bufexpfin, *tmpImagefat, params->icm.workingProfile);
+ int alg = 0;
+ if(fatParams.anchor == 50.f) {
+ alg = 1;
+ }
+ ToneMapFattal02(tmpImagefat.get(), fatParams, 3, 0, nullptr, 0, 0, alg);//last parameter = 1 ==>ART algorithm
+ rgb2lab(*tmpImagefat, *bufexpfin, params->icm.workingProfile);
}
@@ -14980,6 +15062,22 @@ void ImProcFunctions::Lab_Local(
}
float meansob = 0.f;
+
+ const float repart = 1.0 - 0.01 * params->locallab.spots.at(sp).reparexp;
+ int bw = bufexporig->W;
+ int bh = bufexporig->H;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if(multiThread)
+#endif
+ for (int x = 0; x < bh; x++) {
+ for (int y = 0; y < bw; y++) {
+ bufexpfin->L[x][y] = intp(repart, bufexporig->L[x][y], bufexpfin->L[x][y]);
+ bufexpfin->a[x][y] = intp(repart, bufexporig->a[x][y], bufexpfin->a[x][y]);
+ bufexpfin->b[x][y] = intp(repart, bufexporig->b[x][y], bufexpfin->b[x][y]);
+ }
+ }
+
transit_shapedetect2(sp, 0.f, 0.f, call, 1, bufexporig.get(), bufexpfin.get(), originalmaskexp.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
}
@@ -15086,10 +15184,7 @@ void ImProcFunctions::Lab_Local(
const float b_base = lp.lowB / scaling;
const bool ctoning = (a_scale != 0.f || b_scale != 0.f || a_base != 0.f || b_base != 0.f);
const float a_scalemerg = (lp.highAmerg - lp.lowAmerg) / factor / scaling;
- const float a_basemerg = lp.lowAmerg / scaling;
const float b_scalemerg = (lp.highBmerg - lp.lowBmerg) / factor / scaling;
- const float b_basemerg = lp.lowBmerg / scaling;
- const bool ctoningmerg = (a_scalemerg != 0.f || b_scalemerg != 0.f || a_basemerg != 0.f || b_basemerg != 0.f);
if (!lp.inv && (lp.chro != 0 || lp.ligh != 0.f || lp.cont != 0 || ctoning || lp.mergemet > 0 || lp.strcol != 0.f || lp.strcolab != 0.f || lp.qualcurvemet != 0 || lp.showmaskcolmet == 2 || lp.enaColorMask || lp.showmaskcolmet == 3 || lp.showmaskcolmet == 4 || lp.showmaskcolmet == 5 || lp.prevdE) && lp.colorena) { // || lllocalcurve)) { //interior ellipse renforced lightness and chroma //locallutili
int ystart = rtengine::max(static_cast(lp.yc - lp.lyT) - cy, 0);
@@ -15267,7 +15362,7 @@ void ImProcFunctions::Lab_Local(
usergb = true;
const std::unique_ptr tmpImage(new Imagefloat(bfw, bfh));
- lab2rgb(*buftemp, *(tmpImage.get()), params->icm.workingProfile);
+ lab2rgb(*buftemp, *tmpImage, params->icm.workingProfile);
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
@@ -15334,7 +15429,7 @@ void ImProcFunctions::Lab_Local(
}
}
- rgb2lab(*(tmpImage.get()), *buftemp, params->icm.workingProfile);
+ rgb2lab(*tmpImage, *buftemp, params->icm.workingProfile);
// end rgb curves
}
@@ -15564,7 +15659,7 @@ void ImProcFunctions::Lab_Local(
bufcolreserv->L[y][x] = lastorig->L[y + ystart][x + xstart];
bufcolreserv->a[y][x] = lastorig->a[y + ystart][x + xstart];
bufcolreserv->b[y][x] = lastorig->b[y + ystart][x + xstart];
- } else if (lp.mergemet == 4 && ctoningmerg) {
+ } else if (lp.mergemet == 4) {
bufcolreserv->L[y][x] = merlucol * 327.68f;
bufcolreserv->a[y][x] = 9.f * scaledirect * a_scalemerg;
bufcolreserv->b[y][x] = 9.f * scaledirect * b_scalemerg;
@@ -15651,7 +15746,7 @@ void ImProcFunctions::Lab_Local(
}
const std::unique_ptr> rdEBuffer(new JaggedArray(bfw, bfh));
- float** rdE = *(rdEBuffer.get());
+ float** rdE = *rdEBuffer;
deltaEforMask(rdE, bfw, bfh, bufreser.get(), hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, mercol, lp.balance, lp.balanceh);
@@ -15813,11 +15908,11 @@ void ImProcFunctions::Lab_Local(
//prepare RGB values in 0 1(or more)for current image and reserved
std::unique_ptr tmpImageorig(new Imagefloat(bfw, bfh));
- lab2rgb(*bufcolfin, *(tmpImageorig.get()), params->icm.workingProfile);
+ lab2rgb(*bufcolfin, *tmpImageorig, params->icm.workingProfile);
tmpImageorig->normalizeFloatTo1();
std::unique_ptr tmpImagereserv(new Imagefloat(bfw, bfh));
- lab2rgb(*bufcolreserv, *(tmpImagereserv.get()), params->icm.workingProfile);
+ lab2rgb(*bufcolreserv, *tmpImagereserv, params->icm.workingProfile);
tmpImagereserv->normalizeFloatTo1();
float minR = tmpImagereserv->r(0, 0);
@@ -16043,6 +16138,21 @@ void ImProcFunctions::Lab_Local(
softproc(bufcolreserv.get(), bufcolfin.get(), lp.softradiuscol, bfh, bfw, 0.001, 0.00001, 0.5f, sk, multiThread, 1);
}
float meansob = 0.f;
+ const float repart = 1.0 - 0.01 * params->locallab.spots.at(sp).reparcol;
+ int bw = bufcolreserv->W;
+ int bh = bufcolreserv->H;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if(multiThread)
+#endif
+ for (int x = 0; x < bh; x++) {
+ for (int y = 0; y < bw; y++) {
+ bufcolfin->L[x][y] = intp(repart, bufcolreserv->L[x][y], bufcolfin->L[x][y]);
+ bufcolfin->a[x][y] = intp(repart, bufcolreserv->a[x][y], bufcolfin->a[x][y]);
+ bufcolfin->b[x][y] = intp(repart, bufcolreserv->b[x][y], bufcolfin->b[x][y]);
+ }
+ }
+
transit_shapedetect2(sp, 0.f, 0.f, call, 0, bufcolreserv.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
}
@@ -16125,6 +16235,21 @@ void ImProcFunctions::Lab_Local(
bool invmask = false;
maskrecov(bufcolfin.get(), original, bufmaskblurcol.get(), bfh, bfw, ystart, xstart, hig, low, recoth, decay, invmask, sk, multiThread);
}
+ const float repart = 1.0 - 0.01 * params->locallab.spots.at(sp).reparcol;
+ int bw = bufcolorig->W;
+ int bh = bufcolorig->H;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16) if(multiThread)
+#endif
+ for (int x = 0; x < bh; x++) {
+ for (int y = 0; y < bw; y++) {
+ bufcolfin->L[x][y] = intp(repart, bufcolorig->L[x][y], bufcolfin->L[x][y]);
+ bufcolfin->a[x][y] = intp(repart, bufcolorig->a[x][y], bufcolfin->a[x][y]);
+ bufcolfin->b[x][y] = intp(repart, bufcolorig->b[x][y], bufcolfin->b[x][y]);
+ }
+ }
+
float meansob = 0.f;
transit_shapedetect2(sp, 0.f, 0.f, call, 0, bufcolorig.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk);
}
diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc
index b9e234b63..b6bdc5ede 100644
--- a/rtengine/ipresize.cc
+++ b/rtengine/ipresize.cc
@@ -379,6 +379,26 @@ float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, in
dScale = (dScale > 1.0 && !params->resize.allowUpscaling) ? 1.0 : dScale;
break;
+
+ case (4):
+
+ // Long Edge
+ if (refw > refh) {
+ dScale = (double)params->resize.longedge / (double)refw;
+ } else {
+ dScale = (double)params->resize.longedge / (double)refh;
+ }
+ break;
+
+ case (5):
+
+ // Short Edge
+ if (refw > refh) {
+ dScale = (double)params->resize.shortedge / (double)refh;
+ } else {
+ dScale = (double)params->resize.shortedge / (double)refw;
+ }
+ break;
default:
// Scale
diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc
index 67db52e55..491e17cb9 100644
--- a/rtengine/ipretinex.cc
+++ b/rtengine/ipretinex.cc
@@ -397,7 +397,7 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
}
std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L));
- float** src = *(srcBuffer.get());
+ float** src = *srcBuffer;
#ifdef _OPENMP
#pragma omp parallel for
@@ -1238,7 +1238,7 @@ void ImProcFunctions::MSRLocal(int call, int sp, bool fftw, int lum, float** red
const int H_L = height;
const int W_L = width;
std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L));
- float** src = *(srcBuffer.get());
+ float** src = *srcBuffer;
#ifdef _OPENMP
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index 982557d93..19ff01d92 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -448,7 +448,11 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
for (int m = 0; m < maxmul; m++) {
cp.mulC[m] = waparams.ch[m];
}
-
+ for (int m = maxmul; m < 9; m++) {
+ cp.mulC[m] = 0.f;
+ }
+
+//printf("maxmul=%i\n", maxmul);
cp.factor = WaveletParams::LABGRID_CORR_MAX * 3.276f;
cp.scaling = WaveletParams::LABGRID_CORR_SCALE;
cp.scaledirect = WaveletParams::LABGRIDL_DIRECT_SCALE;
@@ -536,6 +540,9 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
for (int m = 0; m < maxmul; m++) {
cp.mul[m] = waparams.c[m];
}
+ for (int m = maxmul; m < 10; m++) {
+ cp.mul[m] = 0.f;
+ }
cp.mul[9] = (float) waparams.sup;
@@ -1038,13 +1045,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
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--;
- }
- }
+ // printf("cp4=%f cpmul5=%f cp6=%f cp7=%f cp8=%f\n", (double)cp.mul[4], (double)cp.mul[5],(double)cp.mul[6],(double)cp.mul[7],(double)cp.mul[8]);
if (levwavL == 6 && cp.noiseena && cp.chromfi == 0.f) {
cp.chromfi = 0.01f;
@@ -1055,12 +1056,17 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
levwavL = 7;
}
}
- bool isdenoisL = (cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f || cp.lev4n > 0.1f);
-
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 (!exblurL && cp.contrast == 0.f && cp.blurres == 0.f && !cp.noiseena && !cp.tonemap && !cp.resena && !cp.chromena && !cp.toningena && !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--;
+ }
+ }
+ bool isdenoisL = (cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f || cp.lev4n > 0.1f);
+
/*
if(cp.denoicurvh || cp.levdenhigh > 0.01f) {
@@ -1724,7 +1730,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 && !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
+ if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && !cp.noiseena && !cp.tonemap && !cp.resena && !cp.chromena && !cp.toningena && !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--;
}
@@ -1777,7 +1783,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
int levwavb = levwav;
- 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
+ if (!exblurab && cp.chrores == 0.f && cp.blurcres == 0.f && !cp.noiseena && !cp.tonemap && !cp.resena && !cp.chromena && !cp.toningena && !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--;
}
@@ -4532,6 +4538,10 @@ void ImProcFunctions::ContAllAB(LabImage * labco, int maxlvl, float ** varhue, f
}
if ((useOpacity && level < 9 && mulOpacity != 0.f) && cp.toningena) { //toning
+ // if (settings->verbose) {
+ // printf("Toning enabled\n");
+ // }
+
float mea[10];
float effect = cp.sigmaton;
float betaab;
diff --git a/rtengine/lj92.c b/rtengine/lj92.c
deleted file mode 100644
index d72075a62..000000000
--- a/rtengine/lj92.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
-lj92.c
-(c) Andrew Baldwin 2014
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include
-#include
-#include
-#include
-
-#include "lj92.h"
-
-typedef uint8_t u8;
-typedef uint16_t u16;
-typedef uint32_t u32;
-
-//#define SLOW_HUFF
-//#define DEBUG
-
-typedef struct _ljp {
- u8* data;
- u8* dataend;
- int datalen;
- int scanstart;
- int ix;
- int x; // Width
- int y; // Height
- int bits; // Bit depth
- int writelen; // Write rows this long
- int skiplen; // Skip this many values after each row
- u16* linearize; // Linearization table
- int linlen;
- int sssshist[16];
-
- // Huffman table - only one supported, and probably needed
-#ifdef SLOW_HUFF
- int* maxcode;
- int* mincode;
- int* valptr;
- u8* huffval;
- int* huffsize;
- int* huffcode;
-#else
- u16* hufflut;
- int huffbits;
-#endif
- // Parse state
- int cnt;
- u32 b;
- u16* image;
- u16* rowcache;
- u16* outrow[2];
-} ljp;
-
-static int find(ljp* self) {
- int ix = self->ix;
- u8* data = self->data;
- while (data[ix] != 0xFF && ix<(self->datalen-1)) {
- ix += 1;
- }
- ix += 2;
- if (ix>=self->datalen) return -1;
- self->ix = ix;
- return data[ix-1];
-}
-
-#define BEH(ptr) ((((int)(*&ptr))<<8)|(*(&ptr+1)))
-
-static int parseHuff(ljp* self) {
- int ret = LJ92_ERROR_CORRUPT;
- u8* huffhead = &self->data[self->ix]; // xstruct.unpack('>HB16B',self.data[self.ix:self.ix+19])
- u8* bits = &huffhead[2];
- bits[0] = 0; // Because table starts from 1
- unsigned int hufflen = BEH(huffhead[0]);
- if ((self->ix + hufflen) >= self->datalen) return ret;
-#ifdef SLOW_HUFF
- u8* huffval = calloc(hufflen - 19,sizeof(u8));
- if (huffval == NULL) return LJ92_ERROR_NO_MEMORY;
- self->huffval = huffval;
- for (int hix=0;hix<(hufflen-19);hix++) {
- huffval[hix] = self->data[self->ix+19+hix];
-#ifdef DEBUG
- printf("huffval[%d]=%d\n",hix,huffval[hix]);
-#endif
- }
- self->ix += hufflen;
- // Generate huffman table
- int k = 0;
- int i = 1;
- int j = 1;
- int huffsize_needed = 1;
- // First calculate how long huffsize needs to be
- while (i<=16) {
- while (j<=bits[i]) {
- huffsize_needed++;
- k = k+1;
- j = j+1;
- }
- i = i+1;
- j = 1;
- }
- // Now allocate and do it
- int* huffsize = calloc(huffsize_needed,sizeof(int));
- if (huffsize == NULL) return LJ92_ERROR_NO_MEMORY;
- self->huffsize = huffsize;
- k = 0;
- i = 1;
- j = 1;
- // First calculate how long huffsize needs to be
- int hsix = 0;
- while (i<=16) {
- while (j<=bits[i]) {
- huffsize[hsix++] = i;
- k = k+1;
- j = j+1;
- }
- i = i+1;
- j = 1;
- }
- huffsize[hsix++] = 0;
-
- // Calculate the size of huffcode array
- int huffcode_needed = 0;
- k = 0;
- int code = 0;
- int si = huffsize[0];
- while (1) {
- while (huffsize[k] == si) {
- huffcode_needed++;
- code = code+1;
- k = k+1;
- }
- if (huffsize[k] == 0)
- break;
- while (huffsize[k] != si) {
- code = code << 1;
- si = si + 1;
- }
- }
- // Now fill it
- int* huffcode = calloc(huffcode_needed,sizeof(int));
- if (huffcode == NULL) return LJ92_ERROR_NO_MEMORY;
- self->huffcode = huffcode;
- int hcix = 0;
- k = 0;
- code = 0;
- si = huffsize[0];
- while (1) {
- while (huffsize[k] == si) {
- huffcode[hcix++] = code;
- code = code+1;
- k = k+1;
- }
- if (huffsize[k] == 0)
- break;
- while (huffsize[k] != si) {
- code = code << 1;
- si = si + 1;
- }
- }
-
- i = 0;
- j = 0;
-
- int* maxcode = calloc(17,sizeof(int));
- if (maxcode == NULL) return LJ92_ERROR_NO_MEMORY;
- self->maxcode = maxcode;
- int* mincode = calloc(17,sizeof(int));
- if (mincode == NULL) return LJ92_ERROR_NO_MEMORY;
- self->mincode = mincode;
- int* valptr = calloc(17,sizeof(int));
- if (valptr == NULL) return LJ92_ERROR_NO_MEMORY;
- self->valptr = valptr;
-
- while (1) {
- while (1) {
- i++;
- if (i>16)
- break;
- if (bits[i]!=0)
- break;
- maxcode[i] = -1;
- }
- if (i>16)
- break;
- valptr[i] = j;
- mincode[i] = huffcode[j];
- j = j+bits[i]-1;
- maxcode[i] = huffcode[j];
- j++;
- }
- free(huffsize);
- self->huffsize = NULL;
- free(huffcode);
- self->huffcode = NULL;
- ret = LJ92_ERROR_NONE;
-#else
- /* Calculate huffman direct lut */
- // How many bits in the table - find highest entry
- u8* huffvals = &self->data[self->ix+19];
- int maxbits = 16;
- while (maxbits>0) {
- if (bits[maxbits]) break;
- maxbits--;
- }
- self->huffbits = maxbits;
- /* Now fill the lut */
- u16* hufflut = (u16*)malloc((1<hufflut = hufflut;
- int i = 0;
- int hv = 0;
- int rv = 0;
- int vl = 0; // i
- int hcode;
- int bitsused = 1;
-#ifdef DEBUG
- printf("%04x:%x:%d:%x\n",i,huffvals[hv],bitsused,1<<(maxbits-bitsused));
-#endif
- while (i<1<maxbits) {
- break; // Done. Should never get here!
- }
- if (vl >= bits[bitsused]) {
- bitsused++;
- vl = 0;
- continue;
- }
- if (rv == 1 << (maxbits-bitsused)) {
- rv = 0;
- vl++;
- hv++;
-#ifdef DEBUG
- printf("%04x:%x:%d:%x\n",i,huffvals[hv],bitsused,1<<(maxbits-bitsused));
-#endif
- continue;
- }
- hcode = huffvals[hv];
- hufflut[i] = hcode<<8 | bitsused;
- //printf("%d %d %d\n",i,bitsused,hcode);
- i++;
- rv++;
- }
- ret = LJ92_ERROR_NONE;
-#endif
- return ret;
-}
-
-static int parseSof3(ljp* self) {
- if (self->ix+6 >= self->datalen) return LJ92_ERROR_CORRUPT;
- self->y = BEH(self->data[self->ix+3]);
- self->x = BEH(self->data[self->ix+5]);
- self->bits = self->data[self->ix+2];
- self->ix += BEH(self->data[self->ix]);
- return LJ92_ERROR_NONE;
-}
-
-static int parseBlock(ljp* self,int marker) {
- self->ix += BEH(self->data[self->ix]);
- if (self->ix >= self->datalen) return LJ92_ERROR_CORRUPT;
- return LJ92_ERROR_NONE;
-}
-
-#ifdef SLOW_HUFF
-static int nextbit(ljp* self) {
- u32 b = self->b;
- if (self->cnt == 0) {
- u8* data = &self->data[self->ix];
- u32 next = *data++;
- b = next;
- if (next == 0xff) {
- data++;
- self->ix++;
- }
- self->ix++;
- self->cnt = 8;
- }
- int bit = b >> 7;
- self->cnt--;
- self->b = (b << 1)&0xFF;
- return bit;
-}
-
-static int decode(ljp* self) {
- int i = 1;
- int code = nextbit(self);
- while (code > self->maxcode[i]) {
- i++;
- code = (code << 1) + nextbit(self);
- }
- int j = self->valptr[i];
- j = j + code - self->mincode[i];
- int value = self->huffval[j];
- return value;
-}
-
-static int receive(ljp* self,int ssss) {
- int i = 0;
- int v = 0;
- while (i != ssss) {
- i++;
- v = (v<<1) + nextbit(self);
- }
- return v;
-}
-
-static int extend(ljp* self,int v,int t) {
- int vt = 1<<(t-1);
- if (v < vt) {
- vt = (-1 << t) + 1;
- v = v + vt;
- }
- return v;
-}
-#endif
-
-inline static int nextdiff(ljp* self, int Px) {
-#ifdef SLOW_HUFF
- int t = decode(self);
- int diff = receive(self,t);
- diff = extend(self,diff,t);
- //printf("%d %d %d %x\n",Px+diff,Px,diff,t);//,index,usedbits);
-#else
- u32 b = self->b;
- int cnt = self->cnt;
- int huffbits = self->huffbits;
- int ix = self->ix;
- int next;
- while (cnt < huffbits) {
- next = *(u16*)&self->data[ix];
- int one = next&0xFF;
- int two = next>>8;
- b = (b<<16)|(one<<8)|two;
- cnt += 16;
- ix += 2;
- if (one==0xFF) {
- //printf("%x %x %x %x %d\n",one,two,b,b>>8,cnt);
- b >>= 8;
- cnt -= 8;
- } else if (two==0xFF) ix++;
- }
- int index = b >> (cnt - huffbits);
- u16 ssssused = self->hufflut[index];
- int usedbits = ssssused&0xFF;
- int t = ssssused>>8;
- self->sssshist[t]++;
- cnt -= usedbits;
- int keepbitsmask = (1 << cnt)-1;
- b &= keepbitsmask;
- while (cnt < t) {
- next = *(u16*)&self->data[ix];
- int one = next&0xFF;
- int two = next>>8;
- b = (b<<16)|(one<<8)|two;
- cnt += 16;
- ix += 2;
- if (one==0xFF) {
- b >>= 8;
- cnt -= 8;
- } else if (two==0xFF) ix++;
- }
- cnt -= t;
- int diff = b >> cnt;
- int vt = 1<<(t-1);
- if (diff < vt) {
- vt = (-1 << t) + 1;
- diff += vt;
- }
- keepbitsmask = (1 << cnt)-1;
- self->b = b & keepbitsmask;
- self->cnt = cnt;
- self->ix = ix;
- //printf("%d %d\n",t,diff);
- //printf("%d %d %d %x %x %d\n",Px+diff,Px,diff,t,index,usedbits);
-#ifdef DEBUG
-#endif
-#endif
- return diff;
-}
-
-static int parsePred6(ljp* self) {
- int ret = LJ92_ERROR_CORRUPT;
- self->ix = self->scanstart;
- //int compcount = self->data[self->ix+2];
- self->ix += BEH(self->data[self->ix]);
- self->cnt = 0;
- self->b = 0;
- int write = self->writelen;
- // Now need to decode huffman coded values
- int c = 0;
- int pixels = self->y * self->x;
- u16* out = self->image;
- u16* temprow;
- u16* thisrow = self->outrow[0];
- u16* lastrow = self->outrow[1];
-
- // First pixel predicted from base value
- int diff;
- int Px;
- int col = 0;
- int row = 0;
- int left = 0;
- int linear;
-
- // First pixel
- diff = nextdiff(self,0);
- Px = 1 << (self->bits-1);
- left = Px + diff;
- if (self->linearize)
- linear = self->linearize[left];
- else
- linear = left;
- thisrow[col++] = left;
- out[c++] = linear;
- if (self->ix >= self->datalen) return ret;
- --write;
- int rowcount = self->x-1;
- while (rowcount--) {
- diff = nextdiff(self,0);
- Px = left;
- left = Px + diff;
- if (self->linearize)
- linear = self->linearize[left];
- else
- linear = left;
- thisrow[col++] = left;
- out[c++] = linear;
- //printf("%d %d %d %d %x\n",col-1,diff,left,thisrow[col-1],&thisrow[col-1]);
- if (self->ix >= self->datalen) return ret;
- if (--write==0) {
- out += self->skiplen;
- write = self->writelen;
- }
- }
- temprow = lastrow;
- lastrow = thisrow;
- thisrow = temprow;
- row++;
- //printf("%x %x\n",thisrow,lastrow);
- while (clinearize) {
- if (left>self->linlen) return LJ92_ERROR_CORRUPT;
- linear = self->linearize[left];
- } else
- linear = left;
- thisrow[col++] = left;
- //printf("%d %d %d %d\n",col,diff,left,lastrow[col]);
- out[c++] = linear;
- if (self->ix >= self->datalen) break;
- rowcount = self->x-1;
- if (--write==0) {
- out += self->skiplen;
- write = self->writelen;
- }
- while (rowcount--) {
- diff = nextdiff(self,0);
- Px = lastrow[col] + ((left - lastrow[col-1])>>1);
- left = Px + diff;
- //printf("%d %d %d %d %d %x\n",col,diff,left,lastrow[col],lastrow[col-1],&lastrow[col]);
- if (self->linearize) {
- if (left>self->linlen) return LJ92_ERROR_CORRUPT;
- linear = self->linearize[left];
- } else
- linear = left;
- thisrow[col++] = left;
- out[c++] = linear;
- if (--write==0) {
- out += self->skiplen;
- write = self->writelen;
- }
- }
- temprow = lastrow;
- lastrow = thisrow;
- thisrow = temprow;
- if (self->ix >= self->datalen) break;
- }
- if (c >= pixels) ret = LJ92_ERROR_NONE;
- return ret;
-}
-
-static int parseScan(ljp* self) {
- int ret = LJ92_ERROR_CORRUPT;
- memset(self->sssshist,0,sizeof(self->sssshist));
- self->ix = self->scanstart;
- int compcount = self->data[self->ix+2];
- int pred = self->data[self->ix+3+2*compcount];
- if (pred<0 || pred>7) return ret;
- if (pred==6) return parsePred6(self); // Fast path
- self->ix += BEH(self->data[self->ix]);
- self->cnt = 0;
- self->b = 0;
- int write = self->writelen;
- // Now need to decode huffman coded values
- int c = 0;
- int pixels = self->y * self->x;
- u16* out = self->image;
- u16* thisrow = self->outrow[0];
- u16* lastrow = self->outrow[1];
-
- // First pixel predicted from base value
- int diff;
- int Px = 0;
- int col = 0;
- int row = 0;
- int left = 0;
- while (cbits-1);
- } else if (row==0) {
- Px = left;
- } else if (col==0) {
- Px = lastrow[col]; // Use value above for first pixel in row
- } else {
- switch (pred) {
- case 0:
- Px = 0; break; // No prediction... should not be used
- case 1:
- Px = left; break;
- case 2:
- Px = lastrow[col]; break;
- case 3:
- Px = lastrow[col-1];break;
- case 4:
- Px = left + lastrow[col] - lastrow[col-1];break;
- case 5:
- Px = left + ((lastrow[col] - lastrow[col-1])>>1);break;
- /* case 6 has a shortcut above
- case 6:
- Px = lastrow[col] + ((left - lastrow[col-1])>>1);break;
- */
- case 7:
- Px = (left + lastrow[col])>>1;break;
- }
- }
- diff = nextdiff(self,Px);
- left = Px + diff;
- //printf("%d %d %d\n",c,diff,left);
- int linear;
- if (self->linearize) {
- if (left>self->linlen) return LJ92_ERROR_CORRUPT;
- linear = self->linearize[left];
- } else
- linear = left;
- thisrow[col] = left;
- out[c++] = linear;
- if (++col==self->x) {
- col = 0;
- row++;
- u16* temprow = lastrow;
- lastrow = thisrow;
- thisrow = temprow;
- }
- if (--write==0) {
- out += self->skiplen;
- write = self->writelen;
- }
- if (self->ix >= self->datalen+2) break;
- }
- if (c >= pixels) ret = LJ92_ERROR_NONE;
- /*for (int h=0;h<17;h++) {
- printf("ssss:%d=%d (%f)\n",h,self->sssshist[h],(float)self->sssshist[h]/(float)(pixels));
- }*/
- return ret;
-}
-
-static int parseImage(ljp* self) {
- int ret = LJ92_ERROR_NONE;
- while (1) {
- int nextMarker = find(self);
- if (nextMarker == 0xc4)
- ret = parseHuff(self);
- else if (nextMarker == 0xc3)
- ret = parseSof3(self);
- else if (nextMarker == 0xfe)// Comment
- ret = parseBlock(self,nextMarker);
- else if (nextMarker == 0xd9) // End of image
- break;
- else if (nextMarker == 0xda) {
- self->scanstart = self->ix;
- ret = LJ92_ERROR_NONE;
- break;
- } else if (nextMarker == -1) {
- ret = LJ92_ERROR_CORRUPT;
- break;
- } else
- ret = parseBlock(self,nextMarker);
- if (ret != LJ92_ERROR_NONE) break;
- }
- return ret;
-}
-
-static int findSoI(ljp* self) {
- int ret = LJ92_ERROR_CORRUPT;
- if (find(self)==0xd8)
- ret = parseImage(self);
- return ret;
-}
-
-static void free_memory(ljp* self) {
-#ifdef SLOW_HUFF
- free(self->maxcode);
- self->maxcode = NULL;
- free(self->mincode);
- self->mincode = NULL;
- free(self->valptr);
- self->valptr = NULL;
- free(self->huffval);
- self->huffval = NULL;
- free(self->huffsize);
- self->huffsize = NULL;
- free(self->huffcode);
- self->huffcode = NULL;
-#else
- free(self->hufflut);
- self->hufflut = NULL;
-#endif
- free(self->rowcache);
- self->rowcache = NULL;
-}
-
-int lj92_open(lj92* lj,
- uint8_t* data, int datalen,
- int* width,int* height, int* bitdepth) {
- ljp* self = (ljp*)calloc(sizeof(ljp),1);
- if (self==NULL) return LJ92_ERROR_NO_MEMORY;
-
- self->data = (u8*)data;
- self->dataend = self->data + datalen;
- self->datalen = datalen;
-
- int ret = findSoI(self);
-
- if (ret == LJ92_ERROR_NONE) {
- u16* rowcache = (u16*)calloc(self->x * 2,sizeof(u16));
- if (rowcache == NULL) ret = LJ92_ERROR_NO_MEMORY;
- else {
- self->rowcache = rowcache;
- self->outrow[0] = rowcache;
- self->outrow[1] = &rowcache[self->x];
- }
- }
-
- if (ret != LJ92_ERROR_NONE) { // Failed, clean up
- *lj = NULL;
- free_memory(self);
- free(self);
- } else {
- *width = self->x;
- *height = self->y;
- *bitdepth = self->bits;
- *lj = self;
- }
- return ret;
-}
-
-int lj92_decode(lj92 lj,
- uint16_t* target,int writeLength, int skipLength,
- uint16_t* linearize,int linearizeLength) {
- int ret = LJ92_ERROR_NONE;
- ljp* self = lj;
- if (self == NULL) return LJ92_ERROR_BAD_HANDLE;
- self->image = target;
- self->writelen = writeLength;
- self->skiplen = skipLength;
- self->linearize = linearize;
- self->linlen = linearizeLength;
- ret = parseScan(self);
- return ret;
-}
-
-void lj92_close(lj92 lj) {
- ljp* self = lj;
- if (self != NULL)
- free_memory(self);
- free(self);
-}
diff --git a/rtengine/lj92.h b/rtengine/lj92.h
deleted file mode 100644
index bc8bf7604..000000000
--- a/rtengine/lj92.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-lj92.h
-(c) Andrew Baldwin 2014
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#ifndef LJ92_H
-#define LJ92_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-enum LJ92_ERRORS {
- LJ92_ERROR_NONE = 0,
- LJ92_ERROR_CORRUPT = -1,
- LJ92_ERROR_NO_MEMORY = -2,
- LJ92_ERROR_BAD_HANDLE = -3,
- LJ92_ERROR_TOO_WIDE = -4,
-};
-
-typedef struct _ljp* lj92;
-
-/* Parse a lossless JPEG (1992) structure returning
- * - a handle that can be used to decode the data
- * - width/height/bitdepth of the data
- * Returns status code.
- * If status == LJ92_ERROR_NONE, handle must be closed with lj92_close
- */
-int lj92_open(lj92* lj, // Return handle here
- uint8_t* data,int datalen, // The encoded data
- int* width,int* height,int* bitdepth); // Width, height and bitdepth
-
-/* Release a decoder object */
-void lj92_close(lj92 lj);
-
-/*
- * Decode previously opened lossless JPEG (1992) into a 2D tile of memory
- * Starting at target, write writeLength 16bit values, then skip 16bit skipLength value before writing again
- * If linearize is not NULL, use table at linearize to convert data values from output value to target value
- * Data is only correct if LJ92_ERROR_NONE is returned
- */
-int lj92_decode(lj92 lj,
- uint16_t* target, int writeLength, int skipLength, // The image is written to target as a tile
- uint16_t* linearize, int linearizeLength); // If not null, linearize the data using this table
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/rtengine/opthelper.h b/rtengine/opthelper.h
index f431c0ec9..8de3b781b 100644
--- a/rtengine/opthelper.h
+++ b/rtengine/opthelper.h
@@ -20,7 +20,7 @@
////////////////////////////////////////////////////////////////
#pragma once
-#define pow_F(a,b) (xexpf(b*xlogf(a)))
+#define pow_F(a,b) (xexpf((b)*xlogf(a)))
#ifdef __SSE2__
#include "sleefsseavx.h"
diff --git a/rtengine/pipettebuffer.h b/rtengine/pipettebuffer.h
index 6f017a196..3c541cb31 100644
--- a/rtengine/pipettebuffer.h
+++ b/rtengine/pipettebuffer.h
@@ -58,7 +58,7 @@ public:
~PipetteBuffer();
/** @brief Getter to know if the pipette buffer is correctly filled */
- bool isReady()
+ bool isReady() const
{
return ready;
}
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index 863fbd6e2..0bb673f1e 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -1066,6 +1066,13 @@ enum ProcEventCode {
EvLocallabSpotavoidmun = 1040,
Evlocallabcontthres = 1041,
Evlocallabnorm = 1042,
+ Evlocallabreparw = 1043,
+ Evlocallabreparcol = 1044,
+ Evlocallabreparden = 1045,
+ Evlocallabreparsh = 1046,
+ Evlocallabreparexp = 1047,
+ Evlocallabrepartm = 1048,
+ Evlocallabchroml = 1049,
NUMOFEVENTS
};
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 9b371a1c8..870a9a71e 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -365,6 +365,10 @@ namespace rtengine
namespace procparams
{
+const short SpotParams::minRadius = 5;
+const short SpotParams::maxRadius = 100;
+
+
ToneCurveParams::ToneCurveParams() :
autoexp(false),
clip(0.02),
@@ -1691,6 +1695,47 @@ bool EPDParams::operator !=(const EPDParams& other) const
return !(*this == other);
}
+SpotEntry::SpotEntry() :
+ radius(25),
+ feather(1.f),
+ opacity(1.f)
+{
+}
+
+float SpotEntry::getFeatherRadius() const
+{
+ return radius * (1.f + feather);
+}
+
+bool SpotEntry::operator ==(const SpotEntry& other) const
+{
+ return other.sourcePos == sourcePos && other.targetPos == targetPos &&
+ other.radius == radius && other.feather == feather && other.opacity == opacity;
+}
+
+bool SpotEntry::operator !=(const SpotEntry& other) const
+{
+ return other.sourcePos != sourcePos || other.targetPos != targetPos ||
+ other.radius != radius || other.feather != feather || other.opacity != opacity;
+}
+
+SpotParams::SpotParams() :
+ enabled(false)
+{
+ entries.clear ();
+}
+
+bool SpotParams::operator ==(const SpotParams& other) const
+{
+ return enabled == other.enabled && entries == other.entries;
+}
+
+bool SpotParams::operator !=(const SpotParams& other) const
+{
+ return !(*this == other);
+}
+
+
FattalToneMappingParams::FattalToneMappingParams() :
enabled(false),
threshold(30),
@@ -2183,6 +2228,8 @@ ResizeParams::ResizeParams() :
dataspec(3),
width(900),
height(900),
+ longedge(900),
+ shortedge(900),
allowUpscaling(false)
{
}
@@ -2197,6 +2244,8 @@ bool ResizeParams::operator ==(const ResizeParams& other) const
&& dataspec == other.dataspec
&& width == other.width
&& height == other.height
+ && longedge == other.longedge
+ && shortedge == other.shortedge
&& allowUpscaling == other.allowUpscaling;
}
@@ -2206,6 +2255,7 @@ bool ResizeParams::operator !=(const ResizeParams& other) const
}
const Glib::ustring ColorManagementParams::NoICMString = Glib::ustring("No ICM: sRGB output");
+const Glib::ustring ColorManagementParams::NoProfileString = Glib::ustring("(none)");
ColorManagementParams::ColorManagementParams() :
inputProfile("(cameraICC)"),
@@ -2215,9 +2265,28 @@ ColorManagementParams::ColorManagementParams() :
applyHueSatMap(true),
dcpIlluminant(0),
workingProfile("ProPhoto"),
- workingTRC("none"),
- workingTRCGamma(2.4),
- workingTRCSlope(12.92310),
+ workingTRC(WorkingTrc::NONE),
+ will(Illuminant::DEFAULT),
+ wprim(Primaries::DEFAULT),
+ workingTRCGamma(2.4),//gamma sRGB
+ workingTRCSlope(12.92),
+ redx(0.7347),
+ redy(0.2653),
+ grex(0.1596),
+ grey(0.8404),
+ blux(0.0366),
+ bluy(0.0001),
+ preser(0.),
+ fbw(false),
+ labgridcieALow(0.51763),//Prophoto red = (0.7347+0.1) * 1.81818 - 1
+ labgridcieBLow(-0.33582),
+ labgridcieAHigh(-0.75163),//Prophoto blue
+ labgridcieBHigh(-0.8180),
+ labgridcieGx(-0.69164),//Prophoto green 0.1596
+ labgridcieGy(-0.70909),//0.84
+ labgridcieWx(-0.18964),//D50 0.3457, 0.3585,
+ labgridcieWy(-0.16636),//
+ aRendIntent(RI_RELATIVE),
outputProfile(options.rtSettings.srgb),
outputIntent(RI_RELATIVE),
outputBPC(true)
@@ -2235,8 +2304,27 @@ bool ColorManagementParams::operator ==(const ColorManagementParams& other) cons
&& dcpIlluminant == other.dcpIlluminant
&& workingProfile == other.workingProfile
&& workingTRC == other.workingTRC
+ && will == other.will
+ && wprim == other.wprim
&& workingTRCGamma == other.workingTRCGamma
&& workingTRCSlope == other.workingTRCSlope
+ && redx == other.redx
+ && redy == other.redy
+ && grex == other.grex
+ && grey == other.grey
+ && blux == other.blux
+ && bluy == other.bluy
+ && labgridcieALow == other.labgridcieALow
+ && labgridcieBLow == other.labgridcieBLow
+ && labgridcieAHigh == other.labgridcieAHigh
+ && labgridcieBHigh == other.labgridcieBHigh
+ && labgridcieGx == other.labgridcieGx
+ && labgridcieGy == other.labgridcieGy
+ && labgridcieWx == other.labgridcieWx
+ && labgridcieWy == other.labgridcieWy
+ && preser == other.preser
+ && fbw == other.fbw
+ && aRendIntent == other.aRendIntent
&& outputProfile == other.outputProfile
&& outputIntent == other.outputIntent
&& outputBPC == other.outputBPC;
@@ -2795,6 +2883,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
complexcolor(2),
curvactiv(false),
lightness(0),
+ reparcol(100.),
contrast(0),
chroma(0),
labgridALow(0.0),
@@ -3127,12 +3216,13 @@ LocallabParams::LocallabSpot::LocallabSpot() :
expMethod("std"),
exnoiseMethod("none"),
laplacexp(0.0),
+ reparexp(100.0),
balanexp(1.0),
linear(0.05),
gamm(0.4),
fatamount(1.0),
fatdetail(40.0),
- fatanchor(1.0),
+ fatanchor(50.0),
fatlevel(1.),
recothrese(1.),
lowthrese(12.),
@@ -3207,6 +3297,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
slomaskSH(0.0),
lapmaskSH(0.0),
detailSH(0),
+ reparsh(100.),
LmaskSHcurve{
static_cast(DCT_NURBS),
0.0,
@@ -3365,6 +3456,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
nlrad(5),
nlgam(3.),
sensiden(60),
+ reparden(100.),
detailthr(50),
locwavcurveden{
static_cast(FCT_MinMaxCPoints),
@@ -3494,6 +3586,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
gamma(1.0),
estop(1.4),
scaltm(1.0),
+ repartm(100.0),
rewei(0),
satur(0.),
sensitm(60),
@@ -3739,6 +3832,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
edgw(60.0),
basew(10.0),
sensilc(60),
+ reparw(100.),
fftwlc(false),
blurlc(true),
wavblur(false),
@@ -3972,6 +4066,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
// Log encoding
visilog(false),
explog(false),
+ complexlog(0),
autocompute(false),
sourceGray(10.),
sourceabs(2000.),
@@ -3979,6 +4074,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
targetGray(18.),
catad(0.),
saturl(0.),
+ chroml(0.),
lightl(0.),
lightq(0.),
contl(0.),
@@ -4219,6 +4315,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& complexcolor == other.complexcolor
&& curvactiv == other.curvactiv
&& lightness == other.lightness
+ && reparcol == other.reparcol
&& contrast == other.contrast
&& chroma == other.chroma
&& labgridALow == other.labgridALow
@@ -4318,6 +4415,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& expMethod == other.expMethod
&& exnoiseMethod == other.exnoiseMethod
&& laplacexp == other.laplacexp
+ && reparexp == other.reparexp
&& balanexp == other.balanexp
&& linear == other.linear
&& gamm == other.gamm
@@ -4364,6 +4462,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& slomaskSH == other.slomaskSH
&& lapmaskSH == other.lapmaskSH
&& detailSH == other.detailSH
+ && reparsh == other.reparsh
&& LmaskSHcurve == other.LmaskSHcurve
&& fatamountSH == other.fatamountSH
&& fatanchorSH == other.fatanchorSH
@@ -4466,6 +4565,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& nlrad == other.nlrad
&& nlgam == other.nlgam
&& sensiden == other.sensiden
+ && reparden == other.reparden
&& detailthr == other.detailthr
&& locwavcurveden == other.locwavcurveden
&& locwavcurvehue == other.locwavcurvehue
@@ -4497,6 +4597,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& gamma == other.gamma
&& estop == other.estop
&& scaltm == other.scaltm
+ && repartm == other.repartm
&& rewei == other.rewei
&& satur == other.satur
&& sensitm == other.sensitm
@@ -4618,6 +4719,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& edgw == other.edgw
&& basew == other.basew
&& sensilc == other.sensilc
+ && reparw == other.reparw
&& fftwlc == other.fftwlc
&& blurlc == other.blurlc
&& wavblur == other.wavblur
@@ -4695,6 +4797,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& targetGray == other.targetGray
&& catad == other.catad
&& saturl == other.saturl
+ && chroml == other.chroml
&& lightl == other.lightl
&& lightq == other.lightq
&& contl == other.contl
@@ -5864,6 +5967,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->complexcolor, "Locallab", "Complexcolor_" + index_str, spot.complexcolor, keyFile);
saveToKeyfile(!pedited || spot_edited->curvactiv, "Locallab", "Curvactiv_" + index_str, spot.curvactiv, keyFile);
saveToKeyfile(!pedited || spot_edited->lightness, "Locallab", "Lightness_" + index_str, spot.lightness, keyFile);
+ saveToKeyfile(!pedited || spot_edited->reparcol, "Locallab", "Reparcol_" + index_str, spot.reparcol, keyFile);
saveToKeyfile(!pedited || spot_edited->contrast, "Locallab", "Contrast_" + index_str, spot.contrast, keyFile);
saveToKeyfile(!pedited || spot_edited->chroma, "Locallab", "Chroma_" + index_str, spot.chroma, keyFile);
saveToKeyfile(!pedited || spot_edited->labgridALow, "Locallab", "labgridALow_" + index_str, spot.labgridALow, keyFile);
@@ -5964,6 +6068,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->expMethod, "Locallab", "ExpMethod_" + index_str, spot.expMethod, keyFile);
saveToKeyfile(!pedited || spot_edited->exnoiseMethod, "Locallab", "ExnoiseMethod_" + index_str, spot.exnoiseMethod, keyFile);
saveToKeyfile(!pedited || spot_edited->laplacexp, "Locallab", "Laplacexp_" + index_str, spot.laplacexp, keyFile);
+ saveToKeyfile(!pedited || spot_edited->reparexp, "Locallab", "Reparexp_" + index_str, spot.reparexp, keyFile);
saveToKeyfile(!pedited || spot_edited->balanexp, "Locallab", "Balanexp_" + index_str, spot.balanexp, keyFile);
saveToKeyfile(!pedited || spot_edited->linear, "Locallab", "Linearexp_" + index_str, spot.linear, keyFile);
saveToKeyfile(!pedited || spot_edited->gamm, "Locallab", "Gamm_" + index_str, spot.gamm, keyFile);
@@ -6006,6 +6111,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->gammaskSH, "Locallab", "GammaskSH_" + index_str, spot.gammaskSH, keyFile);
saveToKeyfile(!pedited || spot_edited->slomaskSH, "Locallab", "SlomaskSH_" + index_str, spot.slomaskSH, keyFile);
saveToKeyfile(!pedited || spot_edited->detailSH, "Locallab", "DetailSH_" + index_str, spot.detailSH, keyFile);
+ saveToKeyfile(!pedited || spot_edited->reparsh, "Locallab", "Reparsh_" + index_str, spot.reparsh, keyFile);
saveToKeyfile(!pedited || spot_edited->LmaskSHcurve, "Locallab", "LmaskSHCurve_" + index_str, spot.LmaskSHcurve, keyFile);
saveToKeyfile(!pedited || spot_edited->fatamountSH, "Locallab", "FatamountSH_" + index_str, spot.fatamountSH, keyFile);
saveToKeyfile(!pedited || spot_edited->fatanchorSH, "Locallab", "FatanchorSH_" + index_str, spot.fatanchorSH, keyFile);
@@ -6111,6 +6217,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->nlrad, "Locallab", "Nlrad_" + index_str, spot.nlrad, keyFile);
saveToKeyfile(!pedited || spot_edited->nlgam, "Locallab", "Nlgam_" + index_str, spot.nlgam, keyFile);
saveToKeyfile(!pedited || spot_edited->sensiden, "Locallab", "Sensiden_" + index_str, spot.sensiden, keyFile);
+ saveToKeyfile(!pedited || spot_edited->reparden, "Locallab", "Reparden_" + index_str, spot.reparden, keyFile);
saveToKeyfile(!pedited || spot_edited->detailthr, "Locallab", "Detailthr_" + index_str, spot.detailthr, keyFile);
saveToKeyfile(!pedited || spot_edited->locwavcurveden, "Locallab", "LocwavCurveden_" + index_str, spot.locwavcurveden, keyFile);
saveToKeyfile(!pedited || spot_edited->locwavcurvehue, "Locallab", "LocwavCurvehue_" + index_str, spot.locwavcurvehue, keyFile);
@@ -6143,6 +6250,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->gamma, "Locallab", "Gamma_" + index_str, spot.gamma, keyFile);
saveToKeyfile(!pedited || spot_edited->estop, "Locallab", "Estop_" + index_str, spot.estop, keyFile);
saveToKeyfile(!pedited || spot_edited->scaltm, "Locallab", "Scaltm_" + index_str, spot.scaltm, keyFile);
+ saveToKeyfile(!pedited || spot_edited->repartm, "Locallab", "Repartm_" + index_str, spot.repartm, keyFile);
saveToKeyfile(!pedited || spot_edited->rewei, "Locallab", "Rewei_" + index_str, spot.rewei, keyFile);
saveToKeyfile(!pedited || spot_edited->satur, "Locallab", "Satur_" + index_str, spot.satur, keyFile);
saveToKeyfile(!pedited || spot_edited->sensitm, "Locallab", "Sensitm_" + index_str, spot.sensitm, keyFile);
@@ -6267,6 +6375,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->edgw, "Locallab", "Edgw_" + index_str, spot.edgw, keyFile);
saveToKeyfile(!pedited || spot_edited->basew, "Locallab", "Basew_" + index_str, spot.basew, keyFile);
saveToKeyfile(!pedited || spot_edited->sensilc, "Locallab", "Sensilc_" + index_str, spot.sensilc, keyFile);
+ saveToKeyfile(!pedited || spot_edited->reparw, "Locallab", "Reparw_" + index_str, spot.reparw, keyFile);
saveToKeyfile(!pedited || spot_edited->fftwlc, "Locallab", "Fftwlc_" + index_str, spot.fftwlc, keyFile);
saveToKeyfile(!pedited || spot_edited->blurlc, "Locallab", "Blurlc_" + index_str, spot.blurlc, keyFile);
saveToKeyfile(!pedited || spot_edited->wavblur, "Locallab", "Wavblur_" + index_str, spot.wavblur, keyFile);
@@ -6342,6 +6451,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
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->saturl, "Locallab", "Chroml_" + index_str, spot.chroml, keyFile);
saveToKeyfile(!pedited || spot_edited->LcurveL, "Locallab", "LCurveL_" + index_str, spot.LcurveL, keyFile);
saveToKeyfile(!pedited || spot_edited->lightl, "Locallab", "Lightl_" + index_str, spot.lightl, keyFile);
saveToKeyfile(!pedited || spot_edited->lightq, "Locallab", "Brightq_" + index_str, spot.lightq, keyFile);
@@ -6434,6 +6544,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->resize.dataspec, "Resize", "DataSpecified", resize.dataspec, keyFile);
saveToKeyfile(!pedited || pedited->resize.width, "Resize", "Width", resize.width, keyFile);
saveToKeyfile(!pedited || pedited->resize.height, "Resize", "Height", resize.height, keyFile);
+ saveToKeyfile(!pedited || pedited->resize.longedge, "Resize", "LongEdge", resize.longedge, keyFile);
+ saveToKeyfile(!pedited || pedited->resize.shortedge, "Resize", "ShortEdge", resize.shortedge, keyFile);
saveToKeyfile(!pedited || pedited->resize.allowUpscaling, "Resize", "AllowUpscaling", resize.allowUpscaling, keyFile);
// Post demosaic sharpening
@@ -6471,10 +6583,97 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->icm.applyHueSatMap, "Color Management", "ApplyHueSatMap", icm.applyHueSatMap, keyFile);
saveToKeyfile(!pedited || pedited->icm.dcpIlluminant, "Color Management", "DCPIlluminant", icm.dcpIlluminant, keyFile);
saveToKeyfile(!pedited || pedited->icm.workingProfile, "Color Management", "WorkingProfile", icm.workingProfile, keyFile);
- saveToKeyfile(!pedited || pedited->icm.workingTRC, "Color Management", "WorkingTRC", icm.workingTRC, keyFile);
+ saveToKeyfile(
+ !pedited || pedited->icm.workingTRC,
+ "Color Management",
+ "WorkingTRC",
+ {
+ {ColorManagementParams::WorkingTrc::NONE, "none"},
+ {ColorManagementParams::WorkingTrc::CUSTOM, "Custom"},
+ {ColorManagementParams::WorkingTrc::BT709, "bt709"},
+ {ColorManagementParams::WorkingTrc::SRGB, "srgb"},
+ {ColorManagementParams::WorkingTrc::GAMMA_2_2, "22"},
+ {ColorManagementParams::WorkingTrc::GAMMA_1_8, "18"},
+ {ColorManagementParams::WorkingTrc::LINEAR, "lin"}
+ },
+ icm.workingTRC,
+ keyFile
+ );
+ saveToKeyfile(
+ !pedited || pedited->icm.will,
+ "Color Management",
+ "Will",
+ {
+ {ColorManagementParams::Illuminant::DEFAULT, "def"},
+ {ColorManagementParams::Illuminant::D41, "D41"},
+ {ColorManagementParams::Illuminant::D50, "D50"},
+ {ColorManagementParams::Illuminant::D55, "D55"},
+ {ColorManagementParams::Illuminant::D60, "D60"},
+ {ColorManagementParams::Illuminant::D65, "D65"},
+ {ColorManagementParams::Illuminant::D80, "D80"},
+ {ColorManagementParams::Illuminant::D120, "D120"},
+ {ColorManagementParams::Illuminant::STDA, "stda"},
+ {ColorManagementParams::Illuminant::TUNGSTEN_2000K, "2000"},
+ {ColorManagementParams::Illuminant::TUNGSTEN_1500K, "1500"}
+ },
+ icm.will,
+ keyFile
+ );
+ saveToKeyfile(
+ !pedited || pedited->icm.wprim,
+ "Color Management",
+ "Wprim",
+ {
+ {ColorManagementParams::Primaries::DEFAULT, "def"},
+ {ColorManagementParams::Primaries::SRGB, "srgb"},
+ {ColorManagementParams::Primaries::ADOBE_RGB, "adob"},
+ {ColorManagementParams::Primaries::PRO_PHOTO, "prop"},
+ {ColorManagementParams::Primaries::REC2020, "rec"},
+ {ColorManagementParams::Primaries::ACES_P1, "aces"},
+ {ColorManagementParams::Primaries::WIDE_GAMUT, "wid"},
+ {ColorManagementParams::Primaries::ACES_P0, "ac0"},
+ {ColorManagementParams::Primaries::BRUCE_RGB, "bru"},
+ {ColorManagementParams::Primaries::BETA_RGB, "bet"},
+ {ColorManagementParams::Primaries::BEST_RGB, "bst"},
+ {ColorManagementParams::Primaries::CUSTOM, "cus"},
+ {ColorManagementParams::Primaries::CUSTOM_GRID, "cusgr"}
+ },
+ icm.wprim,
+ keyFile
+ );
saveToKeyfile(!pedited || pedited->icm.workingTRCGamma, "Color Management", "WorkingTRCGamma", icm.workingTRCGamma, keyFile);
saveToKeyfile(!pedited || pedited->icm.workingTRCSlope, "Color Management", "WorkingTRCSlope", icm.workingTRCSlope, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.redx, "Color Management", "Redx", icm.redx, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.redy, "Color Management", "Redy", icm.redy, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.grex, "Color Management", "Grex", icm.grex, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.grey, "Color Management", "Grey", icm.grey, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.blux, "Color Management", "Blux", icm.blux, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.bluy, "Color Management", "Bluy", icm.bluy, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.labgridcieALow, "Color Management", "LabGridcieALow", icm.labgridcieALow, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.labgridcieBLow, "Color Management", "LabGridcieBLow", icm.labgridcieBLow, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.labgridcieAHigh, "Color Management", "LabGridcieAHigh", icm.labgridcieAHigh, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.labgridcieBHigh, "Color Management", "LabGridcieBHigh", icm.labgridcieBHigh, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.labgridcieGx, "Color Management", "LabGridcieGx", icm.labgridcieGx, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.labgridcieGy, "Color Management", "LabGridcieGy", icm.labgridcieGy, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.labgridcieWx, "Color Management", "LabGridcieWx", icm.labgridcieWx, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.labgridcieWy, "Color Management", "LabGridcieWy", icm.labgridcieWy, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.preser, "Color Management", "Preser", icm.preser, keyFile);
+ saveToKeyfile(!pedited || pedited->icm.fbw, "Color Management", "Fbw", icm.fbw, keyFile);
saveToKeyfile(!pedited || pedited->icm.outputProfile, "Color Management", "OutputProfile", icm.outputProfile, keyFile);
+ saveToKeyfile(
+ !pedited || pedited->icm.aRendIntent,
+ "Color Management",
+ "aIntent",
+ {
+ {RI_PERCEPTUAL, "Perceptual"},
+ {RI_RELATIVE, "Relative"},
+ {RI_SATURATION, "Saturation"},
+ {RI_ABSOLUTE, "Absolute"}
+ },
+ icm.aRendIntent,
+ keyFile
+ );
+
saveToKeyfile(
!pedited || pedited->icm.outputIntent,
"Color Management",
@@ -6484,7 +6683,6 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
{RI_RELATIVE, "Relative"},
{RI_SATURATION, "Saturation"},
{RI_ABSOLUTE, "Absolute"}
-
},
icm.outputIntent,
keyFile
@@ -6643,6 +6841,25 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.hueskin2, "Wavelet", "HueRange", wavelet.hueskin2.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.contrast, "Wavelet", "Contrast", wavelet.contrast, keyFile);
+//Spot removal
+ saveToKeyfile(!pedited || pedited->spot.enabled, "Spot removal", "Enabled", spot.enabled, keyFile);
+ for (size_t i = 0; i < spot.entries.size (); ++i) {
+ std::vector entry(7);
+
+ entry[0] = double (spot.entries.at (i).sourcePos.x);
+ entry[1] = double (spot.entries.at (i).sourcePos.y);
+ entry[2] = double (spot.entries.at (i).targetPos.x);
+ entry[3] = double (spot.entries.at (i).targetPos.y);
+ entry[4] = double (spot.entries.at (i).radius);
+ entry[5] = double (spot.entries.at (i).feather);
+ entry[6] = double (spot.entries.at (i).opacity);
+
+ std::stringstream ss;
+ ss << "Spot" << (i + 1);
+
+ saveToKeyfile(!pedited || pedited->spot.entries, "Spot removal", ss.str(), entry, keyFile);
+ }
+
// Directional pyramid equalizer
saveToKeyfile(!pedited || pedited->dirpyrequalizer.enabled, "Directional Pyramid Equalizer", "Enabled", dirpyrequalizer.enabled, keyFile);
saveToKeyfile(!pedited || pedited->dirpyrequalizer.gamutlab, "Directional Pyramid Equalizer", "Gamutlab", dirpyrequalizer.gamutlab, keyFile);
@@ -7688,6 +7905,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Complexcolor_" + index_str, pedited, spot.complexcolor, spotEdited.complexcolor);
assignFromKeyfile(keyFile, "Locallab", "Curvactiv_" + index_str, pedited, spot.curvactiv, spotEdited.curvactiv);
assignFromKeyfile(keyFile, "Locallab", "Lightness_" + index_str, pedited, spot.lightness, spotEdited.lightness);
+ assignFromKeyfile(keyFile, "Locallab", "Reparcol_" + index_str, pedited, spot.reparcol, spotEdited.reparcol);
assignFromKeyfile(keyFile, "Locallab", "Contrast_" + index_str, pedited, spot.contrast, spotEdited.contrast);
assignFromKeyfile(keyFile, "Locallab", "Chroma_" + index_str, pedited, spot.chroma, spotEdited.chroma);
assignFromKeyfile(keyFile, "Locallab", "labgridALow_" + index_str, pedited, spot.labgridALow, spotEdited.labgridALow);
@@ -7801,6 +8019,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "ExpMethod_" + index_str, pedited, spot.expMethod, spotEdited.expMethod);
assignFromKeyfile(keyFile, "Locallab", "ExnoiseMethod_" + index_str, pedited, spot.exnoiseMethod, spotEdited.exnoiseMethod);
assignFromKeyfile(keyFile, "Locallab", "Laplacexp_" + index_str, pedited, spot.laplacexp, spotEdited.laplacexp);
+ assignFromKeyfile(keyFile, "Locallab", "Reparexp_" + index_str, pedited, spot.reparexp, spotEdited.reparexp);
assignFromKeyfile(keyFile, "Locallab", "Balanexp_" + index_str, pedited, spot.balanexp, spotEdited.balanexp);
assignFromKeyfile(keyFile, "Locallab", "Linearexp_" + index_str, pedited, spot.linear, spotEdited.linear);
assignFromKeyfile(keyFile, "Locallab", "Gamm_" + index_str, pedited, spot.gamm, spotEdited.gamm);
@@ -7848,6 +8067,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "SlomaskSH_" + index_str, pedited, spot.slomaskSH, spotEdited.slomaskSH);
assignFromKeyfile(keyFile, "Locallab", "LapmaskSH_" + index_str, pedited, spot.lapmaskSH, spotEdited.lapmaskSH);
assignFromKeyfile(keyFile, "Locallab", "DetailSH_" + index_str, pedited, spot.detailSH, spotEdited.detailSH);
+ assignFromKeyfile(keyFile, "Locallab", "Reparsh_" + index_str, pedited, spot.reparsh, spotEdited.reparsh);
assignFromKeyfile(keyFile, "Locallab", "LmaskSHCurve_" + index_str, pedited, spot.LmaskSHcurve, spotEdited.LmaskSHcurve);
assignFromKeyfile(keyFile, "Locallab", "FatamountSH_" + index_str, pedited, spot.fatamountSH, spotEdited.fatamountSH);
assignFromKeyfile(keyFile, "Locallab", "FatanchorSH_" + index_str, pedited, spot.fatanchorSH, spotEdited.fatanchorSH);
@@ -7972,6 +8192,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Nlrad_" + index_str, pedited, spot.nlrad, spotEdited.nlrad);
assignFromKeyfile(keyFile, "Locallab", "Nlgam_" + index_str, pedited, spot.nlgam, spotEdited.nlgam);
assignFromKeyfile(keyFile, "Locallab", "Sensiden_" + index_str, pedited, spot.sensiden, spotEdited.sensiden);
+ assignFromKeyfile(keyFile, "Locallab", "Reparden_" + index_str, pedited, spot.reparden, spotEdited.reparden);
assignFromKeyfile(keyFile, "Locallab", "Detailthr_" + index_str, pedited, spot.detailthr, spotEdited.detailthr);
assignFromKeyfile(keyFile, "Locallab", "LocwavCurveden_" + index_str, pedited, spot.locwavcurveden, spotEdited.locwavcurveden);
assignFromKeyfile(keyFile, "Locallab", "LocwavCurvehue_" + index_str, pedited, spot.locwavcurvehue, spotEdited.locwavcurvehue);
@@ -8016,6 +8237,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Gamma_" + index_str, pedited, spot.gamma, spotEdited.gamma);
assignFromKeyfile(keyFile, "Locallab", "Estop_" + index_str, pedited, spot.estop, spotEdited.estop);
assignFromKeyfile(keyFile, "Locallab", "Scaltm_" + index_str, pedited, spot.scaltm, spotEdited.scaltm);
+ assignFromKeyfile(keyFile, "Locallab", "Repartm_" + index_str, pedited, spot.repartm, spotEdited.repartm);
assignFromKeyfile(keyFile, "Locallab", "Rewei_" + index_str, pedited, spot.rewei, spotEdited.rewei);
assignFromKeyfile(keyFile, "Locallab", "Satur_" + index_str, pedited, spot.satur, spotEdited.satur);
assignFromKeyfile(keyFile, "Locallab", "Sensitm_" + index_str, pedited, spot.sensitm, spotEdited.sensitm);
@@ -8149,6 +8371,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Edgw_" + index_str, pedited, spot.edgw, spotEdited.edgw);
assignFromKeyfile(keyFile, "Locallab", "Basew_" + index_str, pedited, spot.basew, spotEdited.basew);
assignFromKeyfile(keyFile, "Locallab", "Sensilc_" + index_str, pedited, spot.sensilc, spotEdited.sensilc);
+ assignFromKeyfile(keyFile, "Locallab", "Reparw_" + index_str, pedited, spot.reparw, spotEdited.reparw);
assignFromKeyfile(keyFile, "Locallab", "Fftwlc_" + index_str, pedited, spot.fftwlc, spotEdited.fftwlc);
assignFromKeyfile(keyFile, "Locallab", "Blurlc_" + index_str, pedited, spot.blurlc, spotEdited.blurlc);
assignFromKeyfile(keyFile, "Locallab", "Wavblur_" + index_str, pedited, spot.wavblur, spotEdited.wavblur);
@@ -8241,6 +8464,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
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", "Chroml_" + index_str, pedited, spot.chroml, spotEdited.chroml);
assignFromKeyfile(keyFile, "Locallab", "Lightl_" + index_str, pedited, spot.lightl, spotEdited.lightl);
assignFromKeyfile(keyFile, "Locallab", "Brightq_" + index_str, pedited, spot.lightq, spotEdited.lightq);
assignFromKeyfile(keyFile, "Locallab", "Contl_" + index_str, pedited, spot.contl, spotEdited.contl);
@@ -8356,6 +8580,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Resize", "DataSpecified", pedited, resize.dataspec, pedited->resize.dataspec);
assignFromKeyfile(keyFile, "Resize", "Width", pedited, resize.width, pedited->resize.width);
assignFromKeyfile(keyFile, "Resize", "Height", pedited, resize.height, pedited->resize.height);
+ assignFromKeyfile(keyFile, "Resize", "LongEdge", pedited, resize.longedge, pedited->resize.longedge);
+ assignFromKeyfile(keyFile, "Resize", "ShortEdge", pedited, resize.shortedge, pedited->resize.shortedge);
if (ppVersion >= 339) {
assignFromKeyfile(keyFile, "Resize", "AllowUpscaling", pedited, resize.allowUpscaling, pedited->resize.allowUpscaling);
} else {
@@ -8366,6 +8592,34 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
}
+ if (keyFile.has_group ("Spot removal")) {
+ assignFromKeyfile(keyFile, "Spot removal", "Enabled", pedited, spot.enabled, pedited->spot.enabled);
+ int i = 0;
+ do {
+ std::stringstream ss;
+ ss << "Spot" << (i++ + 1);
+
+ if (keyFile.has_key ("Spot removal", ss.str())) {
+ Glib::ArrayHandle entry = keyFile.get_double_list ("Spot removal", ss.str());
+ const double epsilon = 0.001; // to circumvent rounding of integer saved as double
+ SpotEntry se;
+
+ se.sourcePos.set(int(entry.data()[0] + epsilon), int(entry.data()[1] + epsilon));
+ se.targetPos.set(int(entry.data()[2] + epsilon), int(entry.data()[3] + epsilon));
+ se.radius = LIM(int (entry.data()[4] + epsilon), SpotParams::minRadius, SpotParams::maxRadius);
+ se.feather = float(entry.data()[5]);
+ se.opacity = float(entry.data()[6]);
+ spot.entries.push_back(se);
+
+ if (pedited) {
+ pedited->spot.entries = true;
+ }
+ } else {
+ break;
+ }
+ } while (1);
+ }
+
if (keyFile.has_group("PostDemosaicSharpening")) {
assignFromKeyfile(keyFile, "PostDemosaicSharpening", "Enabled", pedited, pdsharpening.enabled, pedited->pdsharpening.enabled);
assignFromKeyfile(keyFile, "PostDemosaicSharpening", "Contrast", pedited, pdsharpening.contrast, pedited->pdsharpening.contrast);
@@ -8427,10 +8681,125 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Color Management", "ApplyHueSatMap", pedited, icm.applyHueSatMap, pedited->icm.applyHueSatMap);
assignFromKeyfile(keyFile, "Color Management", "DCPIlluminant", pedited, icm.dcpIlluminant, pedited->icm.dcpIlluminant);
assignFromKeyfile(keyFile, "Color Management", "WorkingProfile", pedited, icm.workingProfile, pedited->icm.workingProfile);
- assignFromKeyfile(keyFile, "Color Management", "WorkingTRC", pedited, icm.workingTRC, pedited->icm.workingTRC);
+ if (
+ !assignFromKeyfile(
+ keyFile,
+ "Color Management",
+ "WorkingTRC",
+ pedited,
+ {
+ {"none", ColorManagementParams::WorkingTrc::NONE},
+ {"Custom", ColorManagementParams::WorkingTrc::CUSTOM},
+ {"bt709", ColorManagementParams::WorkingTrc::BT709},
+ {"srgb", ColorManagementParams::WorkingTrc::SRGB},
+ {"22", ColorManagementParams::WorkingTrc::GAMMA_2_2},
+ {"18", ColorManagementParams::WorkingTrc::GAMMA_1_8},
+ {"lin", ColorManagementParams::WorkingTrc::LINEAR}
+ },
+ icm.workingTRC,
+ pedited->icm.workingTRC
+ )
+ ) {
+ icm.workingTRC = ColorManagementParams::WorkingTrc::NONE;
+ if (pedited) {
+ pedited->icm.workingTRC = true;
+ }
+ }
+ if (
+ !assignFromKeyfile(
+ keyFile,
+ "Color Management",
+ "Will",
+ pedited,
+ {
+ {"def", ColorManagementParams::Illuminant::DEFAULT},
+ {"D41", ColorManagementParams::Illuminant::D41},
+ {"D50", ColorManagementParams::Illuminant::D50},
+ {"D55", ColorManagementParams::Illuminant::D55},
+ {"D60", ColorManagementParams::Illuminant::D60},
+ {"D65", ColorManagementParams::Illuminant::D65},
+ {"D80", ColorManagementParams::Illuminant::D80},
+ {"D120", ColorManagementParams::Illuminant::D120},
+ {"stda", ColorManagementParams::Illuminant::STDA},
+ {"2000", ColorManagementParams::Illuminant::TUNGSTEN_2000K},
+ {"1500", ColorManagementParams::Illuminant::TUNGSTEN_1500K}
+ },
+ icm.will,
+ pedited->icm.will
+ )
+ ) {
+ icm.will = ColorManagementParams::Illuminant::DEFAULT;
+ if (pedited) {
+ pedited->icm.will = true;
+ }
+ }
+ if (
+ !assignFromKeyfile(
+ keyFile,
+ "Color Management",
+ "Wprim",
+ pedited,
+ {
+ {"def", ColorManagementParams::Primaries::DEFAULT},
+ {"srgb", ColorManagementParams::Primaries::SRGB},
+ {"adob", ColorManagementParams::Primaries::ADOBE_RGB},
+ {"prop", ColorManagementParams::Primaries::PRO_PHOTO},
+ {"rec", ColorManagementParams::Primaries::REC2020},
+ {"aces", ColorManagementParams::Primaries::ACES_P1},
+ {"wid", ColorManagementParams::Primaries::WIDE_GAMUT},
+ {"ac0", ColorManagementParams::Primaries::ACES_P0},
+ {"bru", ColorManagementParams::Primaries::BRUCE_RGB},
+ {"bet", ColorManagementParams::Primaries::BETA_RGB},
+ {"bst", ColorManagementParams::Primaries::BEST_RGB},
+ {"cus", ColorManagementParams::Primaries::CUSTOM},
+ {"cusgr", ColorManagementParams::Primaries::CUSTOM_GRID}
+ },
+ icm.wprim,
+ pedited->icm.wprim
+ )
+ ) {
+ icm.wprim = ColorManagementParams::Primaries::DEFAULT;
+ if (pedited) {
+ pedited->icm.wprim = true;
+ }
+ }
assignFromKeyfile(keyFile, "Color Management", "WorkingTRCGamma", pedited, icm.workingTRCGamma, pedited->icm.workingTRCGamma);
assignFromKeyfile(keyFile, "Color Management", "WorkingTRCSlope", pedited, icm.workingTRCSlope, pedited->icm.workingTRCSlope);
+ assignFromKeyfile(keyFile, "Color Management", "Redx", pedited, icm.redx, pedited->icm.redx);
+ assignFromKeyfile(keyFile, "Color Management", "Redy", pedited, icm.redy, pedited->icm.redy);
+ assignFromKeyfile(keyFile, "Color Management", "Grex", pedited, icm.grex, pedited->icm.grex);
+ assignFromKeyfile(keyFile, "Color Management", "Grey", pedited, icm.grey, pedited->icm.grey);
+ assignFromKeyfile(keyFile, "Color Management", "Blux", pedited, icm.blux, pedited->icm.blux);
+ assignFromKeyfile(keyFile, "Color Management", "Bluy", pedited, icm.bluy, pedited->icm.bluy);
+ assignFromKeyfile(keyFile, "Color Management", "Preser", pedited, icm.preser, pedited->icm.preser);
+ assignFromKeyfile(keyFile, "Color Management", "Fbw", pedited, icm.fbw, pedited->icm.fbw);
+ assignFromKeyfile(keyFile, "Color Management", "LabGridcieALow", pedited, icm.labgridcieALow, pedited->icm.labgridcieALow);
+ assignFromKeyfile(keyFile, "Color Management", "LabGridcieBLow", pedited, icm.labgridcieBLow, pedited->icm.labgridcieBLow);
+ assignFromKeyfile(keyFile, "Color Management", "LabGridcieAHigh", pedited, icm.labgridcieAHigh, pedited->icm.labgridcieAHigh);
+ assignFromKeyfile(keyFile, "Color Management", "LabGridcieBHigh", pedited, icm.labgridcieBHigh, pedited->icm.labgridcieBHigh);
+ assignFromKeyfile(keyFile, "Color Management", "LabGridcieGx", pedited, icm.labgridcieGx, pedited->icm.labgridcieGx);
+ assignFromKeyfile(keyFile, "Color Management", "LabGridcieGy", pedited, icm.labgridcieGy, pedited->icm.labgridcieGy);
+ assignFromKeyfile(keyFile, "Color Management", "LabGridcieWx", pedited, icm.labgridcieWx, pedited->icm.labgridcieWx);
+ assignFromKeyfile(keyFile, "Color Management", "LabGridcieWy", pedited, icm.labgridcieWy, pedited->icm.labgridcieWy);
+ if (keyFile.has_key("Color Management", "aIntent")) {
+ Glib::ustring intent = keyFile.get_string("Color Management", "aIntent");
+
+ if (intent == "Perceptual") {
+ icm.aRendIntent = RI_PERCEPTUAL;
+ } else if (intent == "Relative") {
+ icm.aRendIntent = RI_RELATIVE;
+ } else if (intent == "Saturation") {
+ icm.aRendIntent = RI_SATURATION;
+ } else if (intent == "Absolute") {
+ icm.aRendIntent = RI_ABSOLUTE;
+ }
+
+ if (pedited) {
+ pedited->icm.aRendIntent = true;
+ }
+ }
+
assignFromKeyfile(keyFile, "Color Management", "OutputProfile", pedited, icm.outputProfile, pedited->icm.outputProfile);
if (ppVersion < 341) {
if (icm.outputProfile == "RT_Medium_gsRGB") {
@@ -9410,6 +9779,7 @@ bool ProcParams::operator ==(const ProcParams& other) const
&& chmixer == other.chmixer
&& blackwhite == other.blackwhite
&& resize == other.resize
+ && spot == other.spot
&& raw == other.raw
&& icm == other.icm
&& wavelet == other.wavelet
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 0df63b2fa..b0e7f9cd4 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -27,6 +27,7 @@
#include
#include
+#include "coord.h"
#include "noncopyable.h"
struct ParamsEdited;
@@ -1030,6 +1031,7 @@ struct LocallabParams {
int complexcolor;
bool curvactiv;
int lightness;
+ double reparcol;
int contrast;
int chroma;
double labgridALow;
@@ -1129,6 +1131,7 @@ struct LocallabParams {
Glib::ustring expMethod; // std, pde
Glib::ustring exnoiseMethod; // none, med, medhi
double laplacexp;
+ double reparexp;
double balanexp;
double linear;
double gamm;
@@ -1167,6 +1170,7 @@ struct LocallabParams {
double slomaskSH;
double lapmaskSH;
int detailSH;
+ double reparsh;
std::vector LmaskSHcurve;
double fatamountSH;
double fatanchorSH;
@@ -1269,6 +1273,7 @@ struct LocallabParams {
int nlrad;
double nlgam;
int sensiden;
+ double reparden;
int detailthr;
std::vector locwavcurveden;
std::vector locwavcurvehue;
@@ -1300,6 +1305,7 @@ struct LocallabParams {
double gamma;
double estop;
double scaltm;
+ double repartm;
int rewei;
double satur;
int sensitm;
@@ -1421,6 +1427,7 @@ struct LocallabParams {
double edgw;
double basew;
int sensilc;
+ double reparw;
bool fftwlc;
bool blurlc;
bool wavblur;
@@ -1490,6 +1497,7 @@ struct LocallabParams {
double targetGray;
double catad;
double saturl;
+ double chroml;
double lightl;
double lightq;
double contl;
@@ -1682,6 +1690,8 @@ struct ResizeParams {
int dataspec;
int width;
int height;
+ int longedge;
+ int shortedge;
bool allowUpscaling;
ResizeParams();
@@ -1690,10 +1700,85 @@ struct ResizeParams {
bool operator !=(const ResizeParams& other) const;
};
+/**
+ * Parameters entry
+ */
+struct SpotEntry {
+ Coord sourcePos;
+ Coord targetPos;
+ int radius;
+ float feather;
+ float opacity;
+
+ SpotEntry();
+ float getFeatherRadius() const;
+
+ bool operator ==(const SpotEntry& other) const;
+ bool operator !=(const SpotEntry& other) const;
+};
+
+/**
+ * Parameters of the dust removal tool
+ */
+struct SpotParams {
+ bool enabled;
+ std::vector entries;
+
+ // the following constant can be used for experimentation before the final merge
+ static const short minRadius;
+ static const short maxRadius;
+
+ SpotParams();
+
+ bool operator ==(const SpotParams& other) const;
+ bool operator !=(const SpotParams& other) const;
+};
+
+
/**
* Parameters of the color spaces used during the processing
*/
struct ColorManagementParams {
+ enum class WorkingTrc {
+ NONE,
+ CUSTOM,
+ BT709,
+ SRGB,
+ GAMMA_2_2,
+ GAMMA_1_8,
+ LINEAR
+ };
+
+ enum class Illuminant {
+ DEFAULT,
+ D41,
+ D50,
+ D55,
+ D60,
+ D65,
+ D80,
+ D120,
+ STDA,
+ TUNGSTEN_2000K,
+ TUNGSTEN_1500K
+ };
+
+ enum class Primaries {
+ DEFAULT,
+ SRGB,
+ ADOBE_RGB,
+ PRO_PHOTO,
+ REC2020,
+ ACES_P1,
+ WIDE_GAMUT,
+ ACES_P0,
+ BRUCE_RGB,
+ BETA_RGB,
+ BEST_RGB,
+ CUSTOM,
+ CUSTOM_GRID
+ };
+
Glib::ustring inputProfile;
bool toneCurve;
bool applyLookTable;
@@ -1702,15 +1787,35 @@ struct ColorManagementParams {
int dcpIlluminant;
Glib::ustring workingProfile;
- Glib::ustring workingTRC;
+ WorkingTrc workingTRC;
+ Illuminant will;
+ Primaries wprim;
double workingTRCGamma;
double workingTRCSlope;
+ double redx;
+ double redy;
+ double grex;
+ double grey;
+ double blux;
+ double bluy;
+ double preser;
+ bool fbw;
+ double labgridcieALow;
+ double labgridcieBLow;
+ double labgridcieAHigh;
+ double labgridcieBHigh;
+ double labgridcieGx;
+ double labgridcieGy;
+ double labgridcieWx;
+ double labgridcieWy;
+ RenderingIntent aRendIntent;
Glib::ustring outputProfile;
RenderingIntent outputIntent;
bool outputBPC;
static const Glib::ustring NoICMString;
+ static const Glib::ustring NoProfileString;
ColorManagementParams();
@@ -2319,6 +2424,7 @@ public:
ChannelMixerParams chmixer; ///< Channel mixer parameters
BlackWhiteParams blackwhite; ///< Black& White parameters
ResizeParams resize; ///< Resize parameters
+ SpotParams spot; ///< Spot removal tool
ColorManagementParams icm; ///< profiles/color spaces used during the image processing
RAWParams raw; ///< RAW parameters before demosaicing
WaveletParams wavelet; ///< Wavelet parameters
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index 7ae919e0a..6c4bfd8f9 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1325,7 +1325,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
if (ri->zeroIsBad()) { // mark all pixels with value zero as bad, has to be called before FF and DF. dcraw sets this flag only for some cameras (mainly Panasonic and Leica)
bitmapBads.reset(new PixelsMap(W, H));
- totBP = findZeroPixels(*(bitmapBads.get()));
+ totBP = findZeroPixels(*bitmapBads);
if (settings->verbose) {
printf("%d pixels with value zero marked as bad pixels\n", totBP);
@@ -1469,7 +1469,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
bitmapBads.reset(new PixelsMap(W, H));
}
- int nFound = findHotDeadPixels(*(bitmapBads.get()), raw.hotdeadpix_thresh, raw.hotPixelFilter, raw.deadPixelFilter);
+ int nFound = findHotDeadPixels(*bitmapBads, raw.hotdeadpix_thresh, raw.hotPixelFilter, raw.deadPixelFilter);
totBP += nFound;
if (settings->verbose && nFound > 0) {
@@ -1484,7 +1484,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
bitmapBads.reset(new PixelsMap(W, H));
}
- int n = f.mark(rawData, *(bitmapBads.get()));
+ int n = f.mark(rawData, *bitmapBads);
totBP += n;
if (n > 0) {
@@ -1548,15 +1548,15 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
if (ri->getSensorType() == ST_BAYER) {
if (numFrames == 4) {
for (int i = 0; i < 4; ++i) {
- interpolateBadPixelsBayer(*(bitmapBads.get()), *rawDataFrames[i]);
+ interpolateBadPixelsBayer(*bitmapBads, *rawDataFrames[i]);
}
} else {
- interpolateBadPixelsBayer(*(bitmapBads.get()), rawData);
+ interpolateBadPixelsBayer(*bitmapBads, rawData);
}
} else if (ri->getSensorType() == ST_FUJI_XTRANS) {
- interpolateBadPixelsXtrans(*(bitmapBads.get()));
+ interpolateBadPixelsXtrans(*bitmapBads);
} else {
- interpolateBadPixelsNColours(*(bitmapBads.get()), ri->get_colors());
+ interpolateBadPixelsNColours(*bitmapBads, ri->get_colors());
}
}
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index cb5353054..722898642 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -74,7 +74,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
0, // EvLDNEdgeTolerance: obsolete,
0, // EvCDNEnabled:obsolete,
0, // free entry
- RGBCURVE | M_AUTOEXP, // EvDCPToneCurve,
+ RGBCURVE | M_AUTOEXP, // EvDCPToneCurve,
ALLNORAW, // EvDCPIlluminant,
LUMINANCECURVE, // EvSHEnabled,
LUMINANCECURVE, // EvSHHighlights,
@@ -200,7 +200,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvLLCCurve
LUMINANCECURVE, // EvLLCredsk
ALLNORAW, // EvDPDNLdetail
- ALLNORAW, // EvCATEnabled
+ //ALLNORAW, // EvCATEnabled
+ LUMINANCECURVE, // EvCATEnabled
LUMINANCECURVE, // EvCATDegree
LUMINANCECURVE, // EvCATMethodsur
LUMINANCECURVE, // EvCATAdapscen
@@ -1069,7 +1070,14 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
AUTOEXP, // EvLocallabSpotavoidrad
AUTOEXP, // EvLocallabSpotavoidmun
AUTOEXP, // Evlocallabcontthres
- AUTOEXP // Evlocallabnorm
+ AUTOEXP, // Evlocallabnorm
+ AUTOEXP, // Evlocallabreparw
+ AUTOEXP, // Evlocallabreparcol
+ AUTOEXP, // Evlocallabreparden
+ AUTOEXP, // Evlocallabreparsh
+ AUTOEXP, // Evlocallabreparexp
+ AUTOEXP, // Evlocallabrepartm
+ AUTOEXP // Evlocallabchroml
};
diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h
index 0f3e5ee90..b53252796 100644
--- a/rtengine/refreshmap.h
+++ b/rtengine/refreshmap.h
@@ -32,6 +32,7 @@
// Elementary functions that can be done to
// the preview image when an event occurs
+#define M_SPOT (1<<19)
#define M_CSHARP (1<<18)
#define M_MONITOR (1<<14)
#define M_RETINEX (1<<13)
@@ -51,23 +52,24 @@
// Bitfield of functions to do to the preview image when an event occurs
// Use those or create new ones for your new events
-#define FIRST (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR|M_MONITOR) // without HIGHQUAL
-#define ALL (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
-#define DARKFRAME (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define DEMOSAIC (M_RAW|M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define ALLNORAW (M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define CAPTURESHARPEN (M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR|M_CSHARP)
-#define HDR (M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define TRANSFORM (M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define AUTOEXP (M_HDR|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define RGBCURVE (M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define LUMINANCECURVE (M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define SHARPENING (M_LUMINANCE|M_COLOR)
-#define IMPULSEDENOISE (M_LUMINANCE|M_COLOR)
-#define DEFRINGE (M_LUMINANCE|M_COLOR)
-#define DIRPYRDENOISE (M_LUMINANCE|M_COLOR)
-#define DIRPYREQUALIZER (M_LUMINANCE|M_COLOR)
+#define FIRST (M_PREPROC|M_RAW|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR|M_MONITOR) // without HIGHQUAL
+#define ALL (M_PREPROC|M_RAW|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
+#define DARKFRAME (M_PREPROC|M_RAW|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define DEMOSAIC (M_RAW|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define ALLNORAW (M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define CAPTURESHARPEN (M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR|M_CSHARP)
+#define HDR (M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define SPOTADJUST (M_SPOT|M_HDR|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define TRANSFORM (M_SPOT|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define AUTOEXP (M_SPOT|M_HDR|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define RGBCURVE (M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define LUMINANCECURVE (M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define SHARPENING (M_LUMINANCE|M_COLOR)
+#define IMPULSEDENOISE (M_LUMINANCE|M_COLOR)
+#define DEFRINGE (M_LUMINANCE|M_COLOR)
+#define DIRPYRDENOISE (M_LUMINANCE|M_COLOR)
+#define DIRPYREQUALIZER (M_LUMINANCE|M_COLOR)
#define GAMMA M_VOID //M_MONITOR
#define CROP M_CROP
#define RESIZE M_VOID
diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h
index c4ffb91f7..83d47fa96 100644
--- a/rtengine/rtengine.h
+++ b/rtengine/rtengine.h
@@ -81,6 +81,7 @@ class IImage8;
class IImage16;
class IImagefloat;
class ImageSource;
+class TweakOperator;
/**
* This class provides functions to obtain exif and IPTC metadata information
@@ -449,6 +450,15 @@ public:
virtual void autoColorTonChanged(int bwct, int satthres, int satprot) = 0;
};
+class AutoprimListener
+{
+public:
+ virtual ~AutoprimListener() = default;
+ virtual void primChanged(float rx, float ry, float bx, float by, float gx, float gy) = 0;
+ virtual void iprimChanged(float r_x, float r_y, float b_x, float b_y, float g_x, float g_y, float w_x, float w_y) = 0;
+};
+
+
class AutoBWListener
{
public:
@@ -544,9 +554,20 @@ public:
/** Returns the initial image corresponding to the image processor.
* @return the initial image corresponding to the image processor */
virtual InitialImage* getInitialImage () = 0;
+ /** Set the TweakOperator
+ * @param tOperator is a pointer to the object that will alter the ProcParams for the rendering */
+ virtual void setTweakOperator (TweakOperator *tOperator) = 0;
+ /** Unset the TweakOperator
+ * @param tOperator is a pointer to the object that were altering the ProcParams for the rendering
+ * It will only unset the tweak operator if tOperator is the same than the currently set operator.
+ * If it doesn't match, the currently set TweakOperator will remain set. */
+ virtual void unsetTweakOperator (TweakOperator *tOperator) = 0;
/** Returns the current processing parameters.
- * @param dst is the location where the image processing parameters are copied (it is assumed that the memory is allocated by the caller) */
- virtual void getParams (procparams::ProcParams* dst) = 0;
+ * Since the ProcParams can be tweaked by a GUI to operate on the image at a specific stage or with disabled tool,
+ * you'll have to specify if you want the tweaked version for the current special mode, or the untweaked one.
+ * @param dst is the location where the image processing parameters are copied (it is assumed that the memory is allocated by the caller)
+ * @param tweaked is used to chose betwen the tweaked ProcParams (if there is one) or the untweaked one */
+ virtual void getParams (procparams::ProcParams* dst, bool tweaked=false) = 0;
/** An essential member function. Call this when a setting has been changed. This function returns a pointer to the
* processing parameters, that you have to update to reflect the changed situation. When ready, call the paramsUpdateReady
* function to start the image update.
@@ -621,6 +642,8 @@ public:
virtual void setAutoBWListener (AutoBWListener* l) = 0;
virtual void setAutoWBListener (AutoWBListener* l) = 0;
virtual void setAutoColorTonListener (AutoColorTonListener* l) = 0;
+ virtual void setAutoprimListener (AutoprimListener* l) = 0;
+
virtual void setAutoChromaListener (AutoChromaListener* l) = 0;
virtual void setRetinexListener (RetinexListener* l) = 0;
virtual void setWaveletListener (WaveletListener* l) = 0;
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 1cc45aef6..8dc998862 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -1455,12 +1455,15 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
ipf.labColorCorrectionRegions(labView);
+
+
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || !params.colorappearance.enabled) {
ipf.EPDToneMap (labView, 5, 6);
}
ipf.softLight(labView, params.softlight);
+
if (params.colorappearance.enabled) {
CurveFactory::curveLightBrightColor (
params.colorappearance.curve,
@@ -1508,7 +1511,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
ipf.ciecam_02float (cieView, adap, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, sk, execsharp, d, dj, yb, rtt);
delete cieView;
}
-
+
+
// color processing
//ipf.colorCurve (labView, labView);
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index a1c1e6d44..f59140786 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -16,27 +16,31 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
*/
+
+#include
+#include
+
#include "cieimage.h"
-#include "dcp.h"
-#include "imagefloat.h"
-#include "labimage.h"
-#include "rtengine.h"
+#include "clutstore.h"
+#include "color.h"
#include "colortemp.h"
+#include "curves.h"
+#include "dcp.h"
+#include "guidedfilter.h"
+#include "iccstore.h"
+#include "imagefloat.h"
#include "imagesource.h"
#include "improcfun.h"
-#include "curves.h"
-#include "iccstore.h"
-#include "clutstore.h"
+#include "labimage.h"
+#include "mytime.h"
#include "processingjob.h"
#include "procparams.h"
-#include
-#include
-#include "../rtgui/options.h"
#include "rawimagesource.h"
+#include "rtengine.h"
+#include "utils.h"
+
#include "../rtgui/multilangmgr.h"
-#include "mytime.h"
-#include "guidedfilter.h"
-#include "color.h"
+#include "../rtgui/options.h"
#undef THREAD_PRIORITY_NORMAL
@@ -792,6 +796,11 @@ private:
params.toneCurve.black = 0;
}
+ // Spot Removal
+ if (params.spot.enabled && !params.spot.entries.empty ()) {
+ ipf.removeSpots (baseImg, imgsrc, params.spot.entries, pp, currWB, nullptr, tr);
+ }
+
// at this stage, we can flush the raw data to free up quite an important amount of memory
// commented out because it makes the application crash when batch processing...
// TODO: find a better place to flush rawData and rawRGB
@@ -924,21 +933,6 @@ private:
ipf.lab2rgb(labcbdl, *baseImg, params.icm.workingProfile);
}
-/* //gamma TRC working
- if (params.icm.workingTRC == "Custom") { //exec TRC IN free
- const Glib::ustring profile = params.icm.workingProfile;
-
- if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") {
- const int cw = baseImg->getWidth();
- const int ch = baseImg->getHeight();
- cmsHTRANSFORM dummyTransForm = nullptr;
- // put gamma TRC to 1
- ipf.workingtrc(baseImg, baseImg, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310, dummyTransForm, true, false, false);
- //adjust TRC
- ipf.workingtrc(baseImg, baseImg, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, dummyTransForm, false, true, false);
- }
- }
-*/
// RGB processing
labView = new LabImage(fw, fh);
@@ -1371,6 +1365,7 @@ private:
ipf.chromiLuminanceCurve(nullptr, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy);
+
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
ipf.EPDToneMap (labView, 0, 1);
}
@@ -1570,6 +1565,52 @@ private:
ipf.softLight(labView, params.softlight);
+
+ if (params.icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) {
+ const int GW = labView->W;
+ const int GH = labView->H;
+ std::unique_ptr provis;
+ const float pres = 0.01f * params.icm.preser;
+ if (pres > 0.f && params.icm.wprim != ColorManagementParams::Primaries::DEFAULT) {
+ provis.reset(new LabImage(GW, GH));
+ provis->CopyFrom(labView);
+ }
+
+ const std::unique_ptr tmpImage1(new Imagefloat(GW, GH));
+
+ ipf.lab2rgb(*labView, *tmpImage1, params.icm.workingProfile);
+
+ const float gamtone = params.icm.workingTRCGamma;
+ const float slotone = params.icm.workingTRCSlope;
+
+ int illum = toUnderlying(params.icm.will);
+ const int prim = toUnderlying(params.icm.wprim);
+
+ Glib::ustring prof = params.icm.workingProfile;
+
+ cmsHTRANSFORM dummy = nullptr;
+ int ill = 0;
+ ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false);
+ ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, dummy, false, true, true);
+
+ ipf.rgb2lab(*tmpImage1, *labView, params.icm.workingProfile);
+ // labView and provis
+ if(provis) {
+ ipf.preserv(labView, provis.get(), GW, GH);
+ }
+ if(params.icm.fbw) {
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+ for (int x = 0; x < GH; x++)
+ for (int y = 0; y < GW; y++) {
+ labView->a[x][y] = 0.f;
+ labView->b[x][y] = 0.f;
+ }
+ }
+
+ }
+
//Colorappearance and tone-mapping associated
int f_w = 1, f_h = 1;
diff --git a/rtengine/sleef.h b/rtengine/sleef.h
index fc23cbad9..e630d882d 100644
--- a/rtengine/sleef.h
+++ b/rtengine/sleef.h
@@ -3,6 +3,11 @@
// this code was taken from http://shibatch.sourceforge.net/
// Many thanks to the author of original version: Naoki Shibata
//
+// Copyright Naoki Shibata and contributors 2010 - 2021.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file sleef_LICENSE.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
// This version contains modifications made by Ingo Weyrich
//
////////////////////////////////////////////////////////////////
@@ -21,7 +26,6 @@
#define L2U .69314718055966295651160180568695068359375
#define L2L .28235290563031577122588448175013436025525412068e-12
#define R_LN2 1.442695040888963407359924681001892137426645954152985934135449406931
-#define pow_F(a,b) (xexpf(b*xlogf(a)))
__inline int64_t doubleToRawLongBits(double d) {
union {
diff --git a/rtengine/sleefsseavx.h b/rtengine/sleefsseavx.h
index c10f4a0c2..374823316 100644
--- a/rtengine/sleefsseavx.h
+++ b/rtengine/sleefsseavx.h
@@ -3,6 +3,11 @@
// this code was taken from http://shibatch.sourceforge.net/
// Many thanks to the author of original version: Naoki Shibata
//
+// Copyright Naoki Shibata and contributors 2010 - 2021.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file sleef_LICENSE.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
// This version contains modifications made by Ingo Weyrich
//
////////////////////////////////////////////////////////////////
diff --git a/rtengine/spot.cc b/rtengine/spot.cc
new file mode 100644
index 000000000..f43eaa909
--- /dev/null
+++ b/rtengine/spot.cc
@@ -0,0 +1,580 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 "improcfun.h"
+#include "alpha.h"
+#include "procparams.h"
+#include "imagesource.h"
+#include "imagefloat.h"
+#include "rt_math.h"
+#include
+#include
+#include
+
+namespace rtengine
+{
+
+class SpotBox;
+
+}
+
+namespace
+{
+
+using Boxes = std::vector>;
+
+/**
+ * Add the spot and its dependencies to a set of dependencies.
+ *
+ * @param spotNum The spot's index.
+ * @param dependencies A set to place the dependencies in. Spots that are
+ * already in the set must have all their dependencies included already.
+ * @param srcSpots Information on spot sources.
+ * @param dstSpots Information on spot destinations.
+ */
+void addSpotDependencies(int spotNum, std::unordered_set &dependencies, const Boxes &srcSpots, const Boxes &dstSpots);
+
+/**
+ * Returns the supplied spots and all their dependencies.
+ *
+ * @param visibleSpots The spots to get dependencies for.
+ * @param srcSpots Information on spot sources.
+ * @param dstSpots Information on spot destinations.
+ */
+std::unordered_set calcSpotDependencies(const std::set &visibleSpots, const Boxes &srcSpots, const Boxes &dstSpots);
+}
+
+namespace rtengine
+{
+
+class SpotBox {
+
+public:
+ enum class Type {
+ SOURCE,
+ TARGET,
+ FINAL
+ };
+
+ struct Rectangle {
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+
+ Rectangle() : Rectangle(0, 0, 0, 0) {}
+ Rectangle(int X1, int Y1, int X2, int Y2) : x1(X1), y1(Y1), x2(X2), y2(Y2) {}
+
+ int getWidth() {
+ return x2 - x1 + 1;
+ }
+
+ int getHeight() {
+ return y2 - y1 + 1;
+ }
+
+ bool intersects(const Rectangle &other) const {
+ return (other.x1 <= x2 && other.x2 >= x1)
+ && (other.y1 <= y2 && other.y2 >= y1);
+ }
+
+ bool getIntersection(const Rectangle &other, std::unique_ptr &intersection) const {
+ if (intersects(other)) {
+ std::unique_ptr intsec(
+ new Rectangle(
+ rtengine::max(x1, other.x1),
+ rtengine::max(y1, other.y1),
+ rtengine::min(x2, other.x2),
+ rtengine::min(y2, other.y2)
+ )
+ );
+
+ if (intsec->x1 > intsec->x2 || intsec->y1 > intsec->y2) {
+ return false;
+ }
+
+ intersection = std::move(intsec);
+ return true;
+ }
+ if (intersection) {
+ // There's no intersection, we delete the Rectangle structure
+ intersection.release();
+ }
+ return false;
+ }
+
+ Rectangle& operator+=(const Coord &v) {
+ x1 += v.x;
+ y1 += v.y;
+ x2 += v.x;
+ y2 += v.y;
+ return *this;
+ }
+
+ Rectangle& operator-=(const Coord &v) {
+ x1 -= v.x;
+ y1 -= v.y;
+ x2 -= v.x;
+ y2 -= v.y;
+ return *this;
+ }
+
+ Rectangle& operator/=(int v) {
+ if (v == 1) {
+ return *this;
+ }
+
+ int w = x2 - x1 + 1;
+ int h = y2 - y1 + 1;
+ w = w / v + static_cast(w % v);
+ h = h / v + static_cast(h % v);
+ x1 /= v;
+ y1 /= v;
+ x2 = x1 + w - 1;
+ y2 = y1 + h - 1;
+
+ return *this;
+ }
+ };
+
+private:
+ Type type;
+ Imagefloat* image;
+
+public:
+ // top/left and bottom/right coordinates of the spot in image space (at some point divided by scale factor)
+ Rectangle spotArea;
+ // top/left and bottom/right coordinates of the spot in scaled image space (on borders, imgArea won't cover spotArea)
+ Rectangle imgArea;
+ // top/left and bottom/right coordinates of useful part of the image in scaled image space (rounding error workaround)
+ Rectangle intersectionArea;
+ float radius;
+ float featherRadius;
+
+ SpotBox (int tl_x, int tl_y, int br_x, int br_y, int radius, int feather_radius, Imagefloat* image, Type type) :
+ type(type),
+ image(image),
+ spotArea(tl_x, tl_y, br_x, br_y),
+ imgArea(spotArea),
+ intersectionArea(),
+ radius(radius),
+ featherRadius(feather_radius)
+ {}
+
+ SpotBox (int tl_x, int tl_y, int radius, int feather_radius, Imagefloat* image, Type type) :
+ type(type),
+ image(image),
+ spotArea(tl_x, tl_y, image ? tl_x + image->getWidth() - 1 : 0, image ? tl_y + image->getHeight() - 1 : 0),
+ imgArea(spotArea),
+ intersectionArea(),
+ radius(radius),
+ featherRadius(feather_radius)
+ {}
+
+ SpotBox (SpotEntry &spot, Type type) :
+ type(type),
+ image(nullptr),
+ intersectionArea(),
+ radius(spot.radius),
+ featherRadius(int(spot.getFeatherRadius() + 0.5f)) // rounding to int before resizing
+ {
+ spotArea.x1 = int ((type == Type::SOURCE ? spot.sourcePos.x : spot.targetPos.x) - featherRadius);
+ spotArea.x2 = int ((type == Type::SOURCE ? spot.sourcePos.x : spot.targetPos.x) + featherRadius);
+ spotArea.y1 = int ((type == Type::SOURCE ? spot.sourcePos.y : spot.targetPos.y) - featherRadius);
+ spotArea.y2 = int ((type == Type::SOURCE ? spot.sourcePos.y : spot.targetPos.y) + featherRadius);
+ imgArea = spotArea;
+ }
+
+ ~SpotBox() {
+ if (image && type != Type::FINAL) {
+ delete image;
+ }
+ }
+
+ SpotBox& operator /=(int v) {
+ if (v == 1) {
+ return *this;
+ }
+ spotArea /= v;
+ imgArea /= v;
+ radius /= float(v);
+ featherRadius = getWidth() / 2.f;
+ // intersectionArea doesn't need resize, because it's set after resizing
+ return *this;
+ }
+
+ int getWidth() {
+ return spotArea.getWidth();
+ }
+
+ int getHeight() {
+ return spotArea.getHeight();
+ }
+
+ int getImageWidth() {
+ return imgArea.getWidth();
+ }
+
+ int getImageHeight() {
+ return imgArea.getHeight();
+ }
+
+ int getIntersectionWidth() {
+ return intersectionArea.getWidth();
+ }
+
+ int getIntersectionHeight() {
+ return intersectionArea.getHeight();
+ }
+
+ bool checkImageSize() {
+ if (!image || getImageWidth() != image->getWidth() || getImageHeight() != image->getHeight()) {
+ return false;
+ }
+ return true;
+ }
+
+ void tuneImageSize() {
+ if (!image) {
+ return;
+ }
+ if (getImageWidth() > image->getWidth()) {
+ imgArea.x2 = imgArea.x1 + image->getWidth() - 1;
+ }
+ if (getImageHeight() > image->getHeight()) {
+ imgArea.y2 = imgArea.y1 + image->getHeight() - 1;
+ }
+ }
+
+ Imagefloat *getImage() { // TODO: this should send back a const value, but getImage don't want it to be const...
+ return image;
+ }
+
+ void allocImage() {
+ int newW = imgArea.x2 - imgArea.x1 + 1;
+ int newH = imgArea.y2 - imgArea.y1 + 1;
+
+ if (image && type != Type::FINAL && (image->getWidth() != newW || image->getHeight() != newH)) {
+ delete image;
+ image = nullptr;
+ }
+ if (image == nullptr) {
+ image = new Imagefloat(newW, newH);
+ }
+ }
+
+ bool spotIntersects(const SpotBox &other) const {
+ return spotArea.intersects(other.spotArea);
+ }
+
+ bool getSpotIntersection(const SpotBox &other, std::unique_ptr &intersection) const {
+ return spotArea.getIntersection(other.spotArea, intersection);
+ }
+
+ bool imageIntersects(const SpotBox &other, bool atDestLocation=false) const {
+ if (atDestLocation) {
+ Coord v(other.spotArea.x1 - spotArea.x1, other.spotArea.y1 - spotArea.y1);
+ Rectangle imgArea2(imgArea.x1, imgArea.y1, imgArea.x2, imgArea.y2);
+ imgArea2 += v;
+ return imgArea2.intersects(other.imgArea);
+ }
+ return imgArea.intersects(other.imgArea);
+ }
+
+ bool mutuallyClipImageArea(SpotBox &other) {
+ Coord v(other.spotArea.x1 - spotArea.x1, other.spotArea.y1 - spotArea.y1);
+ Rectangle imgArea2 = imgArea;
+ imgArea2 += v;
+ std::unique_ptr intersection;
+ if (!imgArea2.getIntersection(other.imgArea, intersection)) {
+ return false;
+ }
+ other.intersectionArea = *intersection;
+ Coord v2(-v.x, -v.y);
+ *intersection -= v;
+ intersectionArea = *intersection;
+ return true;
+ }
+
+ bool setIntersectionWith(const SpotBox &other) {
+ if (!spotIntersects(other)) {
+ return false;
+ }
+ imgArea.x1 = rtengine::max(spotArea.x1, other.spotArea.x1);
+ imgArea.x2 = rtengine::min(spotArea.x2, other.spotArea.x2);
+ imgArea.y1 = rtengine::max(spotArea.y1, other.spotArea.y1);
+ imgArea.y2 = rtengine::min(spotArea.y2, other.spotArea.y2);
+ if (imgArea.x1 > imgArea.x2 || imgArea.y1 > imgArea.y2) {
+ return false;
+ }
+ return true;
+ }
+
+ bool processIntersectionWith(SpotBox &destBox) {
+ Imagefloat *dstImg = destBox.image;
+
+ if (image == nullptr || dstImg == nullptr) {
+ std::cerr << "One of the source or destination SpotBox image is missing !" << std::endl;
+ return false;
+ }
+
+ int srcImgY = intersectionArea.y1 - imgArea.y1;
+ int dstImgY = destBox.intersectionArea.y1 - destBox.imgArea.y1;
+ for (int y = intersectionArea.y1; y <= intersectionArea.y2; ++y) {
+ float dy = float(y - spotArea.y1) - featherRadius;
+
+ int srcImgX = intersectionArea.x1 - imgArea.x1;
+ int dstImgX = destBox.intersectionArea.x1 - destBox.imgArea.x1;
+ for (int x = intersectionArea.x1; x <= intersectionArea.x2; ++x) {
+ float dx = float(x - spotArea.x1) - featherRadius;
+ float r = sqrt(dx * dx + dy * dy);
+
+ if (r >= featherRadius) {
+ ++srcImgX;
+ ++dstImgX;
+ continue;
+ }
+ if (r <= radius) {
+ dstImg->r(dstImgY, dstImgX) = image->r(srcImgY, srcImgX);
+ dstImg->g(dstImgY, dstImgX) = image->g(srcImgY, srcImgX);
+ dstImg->b(dstImgY, dstImgX) = image->b(srcImgY, srcImgX);
+ } else {
+ float opacity = (featherRadius - r) / (featherRadius - radius);
+ dstImg->r(dstImgY, dstImgX) = (image->r(srcImgY, srcImgX) - dstImg->r(dstImgY, dstImgX)) * opacity + dstImg->r(dstImgY,dstImgX);
+ dstImg->g(dstImgY, dstImgX) = (image->g(srcImgY, srcImgX) - dstImg->g(dstImgY, dstImgX)) * opacity + dstImg->g(dstImgY,dstImgX);
+ dstImg->b(dstImgY, dstImgX) = (image->b(srcImgY, srcImgX) - dstImg->b(dstImgY, dstImgX)) * opacity + dstImg->b(dstImgY,dstImgX);
+ }
+ ++srcImgX;
+ ++dstImgX;
+ }
+ ++srcImgY;
+ ++dstImgY;
+ }
+
+ return true;
+ }
+
+ // Copy the intersecting part
+ bool copyImgTo(SpotBox &destBox) {
+ Imagefloat *destImg = destBox.image;
+
+ if (image == nullptr || destImg == nullptr) {
+ std::cerr << "One of the source or destination SpotBox image is missing !" << std::endl;
+ return false;
+ }
+
+ std::unique_ptr intersection;
+
+ if (!intersectionArea.getIntersection(destBox.intersectionArea, intersection)) {
+ return false;
+ }
+
+ Imagefloat *srcImg = image;
+ Imagefloat *dstImg = destBox.image;
+
+ int srcImgY = intersection->y1 - imgArea.y1;
+ int dstImgY = intersection->y1 - destBox.imgArea.y1;
+ for (int y = intersection->y1; y <= intersection->y2; ++y) {
+ int srcImgX = intersection->x1 - imgArea.x1;
+ int dstImgX = intersection->x1 - destBox.imgArea.x1;
+
+ for (int x = intersection->x1; x <= intersection->x2; ++x) {
+ dstImg->r(dstImgY, dstImgX) = srcImg->r(srcImgY, srcImgX);
+ dstImg->g(dstImgY, dstImgX) = srcImg->g(srcImgY, srcImgX);
+ dstImg->b(dstImgY, dstImgX) = srcImg->b(srcImgY, srcImgX);
+ ++srcImgX;
+ ++dstImgX;
+ }
+ ++srcImgY;
+ ++dstImgY;
+ }
+
+ return true;
+ }
+};
+
+void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const std::vector &entries, const PreviewProps &pp, const ColorTemp &currWB, const ColorManagementParams *cmp, int tr)
+{
+ //Get the clipped image areas (src & dst) from the source image
+
+ std::vector< std::shared_ptr > srcSpotBoxs;
+ std::vector< std::shared_ptr > dstSpotBoxs;
+ int fullImgWidth = 0;
+ int fullImgHeight = 0;
+ imgsrc->getFullSize(fullImgWidth, fullImgHeight, tr);
+ SpotBox fullImageBox(0, 0, fullImgWidth - 1, fullImgHeight - 1, 0, 0, nullptr, SpotBox::Type::FINAL);
+ SpotBox cropBox(pp.getX(), pp.getY(),
+ pp.getX() + pp.getWidth() - 1, pp.getY() + pp.getHeight() - 1,
+ 0, 0, img, SpotBox::Type::FINAL);
+
+ std::set visibleSpots; // list of dest spots intersecting the preview's crop
+ int i = 0;
+
+ for (auto entry : params->spot.entries) {
+ std::shared_ptr srcSpotBox(new SpotBox(entry, SpotBox::Type::SOURCE));
+ std::shared_ptr dstSpotBox(new SpotBox(entry, SpotBox::Type::TARGET));
+ if ( !srcSpotBox->setIntersectionWith(fullImageBox)
+ || !dstSpotBox->setIntersectionWith(fullImageBox)
+ || !srcSpotBox->imageIntersects(*dstSpotBox, true))
+ {
+ continue;
+ }
+
+ // If spot intersect the preview image, add it to the visible spots
+ if (dstSpotBox->spotIntersects(cropBox)) {
+ visibleSpots.insert(i);
+ }
+ ++i;
+
+ // Source area
+ PreviewProps spp(srcSpotBox->imgArea.x1, srcSpotBox->imgArea.y1,
+ srcSpotBox->getImageWidth(), srcSpotBox->getImageHeight(), pp.getSkip());
+ int w = 0;
+ int h = 0;
+ imgsrc->getSize(spp, w, h);
+ *srcSpotBox /= pp.getSkip();
+ srcSpotBox->allocImage();
+ Imagefloat *srcImage = srcSpotBox->getImage();
+ for (int y = 0; y < (int)srcImage->getHeight(); ++y) {
+ for (int x = 0; x < (int)srcImage->getWidth(); ++x) {
+ srcImage->r(y, x) = 60000.f;
+ srcImage->g(y, x) = 500.f;
+ srcImage->b(y, x) = 500.f;
+ }
+ }
+
+ imgsrc->getImage(currWB, tr, srcSpotBox->getImage(), spp, params->toneCurve, params->raw);
+ if (cmp) {
+ imgsrc->convertColorSpace(srcImage, *cmp, currWB);
+ }
+ assert(srcSpotBox->checkImageSize());
+
+
+ // Destination area
+ spp.set(dstSpotBox->imgArea.x1, dstSpotBox->imgArea.y1, dstSpotBox->getImageWidth(),
+ dstSpotBox->getImageHeight(), pp.getSkip());
+ *dstSpotBox /= pp.getSkip();
+ dstSpotBox->allocImage();
+ Imagefloat *dstImage = dstSpotBox->getImage();
+ for (int y = 0; y < (int)dstImage->getHeight(); ++y) {
+ for (int x = 0; x < (int)dstImage->getWidth(); ++x) {
+ dstImage->r(y, x) = 500.f;
+ dstImage->g(y, x) = 500.f;
+ dstImage->b(y, x) = 60000.f;
+ }
+ }
+ imgsrc->getImage(currWB, tr, dstSpotBox->getImage(), spp, params->toneCurve, params->raw);
+ if (cmp) {
+ imgsrc->convertColorSpace(dstImage, *cmp, currWB);
+ }
+ assert(dstSpotBox->checkImageSize());
+
+ // Update the intersectionArea between src and dest
+ if (srcSpotBox->mutuallyClipImageArea(*dstSpotBox)) {
+ srcSpotBoxs.push_back(srcSpotBox);
+ dstSpotBoxs.push_back(dstSpotBox);
+ }
+
+ }
+
+ // Construct list of upstream dependancies
+
+ std::unordered_set requiredSpotsSet = calcSpotDependencies(visibleSpots, srcSpotBoxs, dstSpotBoxs);
+ std::vector requiredSpots(requiredSpotsSet.size());
+ std::copy(requiredSpotsSet.begin(), requiredSpotsSet.end(), requiredSpots.begin());
+ std::sort(requiredSpots.begin(), requiredSpots.end());
+
+ // Process spots and copy them downstream
+
+ for (auto i = requiredSpots.begin(); i != requiredSpots.end(); i++) {
+ // Process
+ srcSpotBoxs.at(*i)->processIntersectionWith(*dstSpotBoxs.at(*i));
+
+ // Propagate
+ std::set positiveSpots; // For DEBUG purpose only !
+ auto j = i;
+ ++j;
+ while (j != requiredSpots.end()) {
+ bool intersectionFound = false;
+ int i_ = *i;
+ int j_ = *j;
+ intersectionFound |= dstSpotBoxs.at(i_)->copyImgTo(*srcSpotBoxs.at(j_));
+ intersectionFound |= dstSpotBoxs.at(i_)->copyImgTo(*dstSpotBoxs.at(j_));
+ if (intersectionFound) {
+ positiveSpots.insert(j_);
+ }
+ ++j;
+ }
+ }
+
+ // Copy the dest spot to the preview image
+ cropBox /= pp.getSkip();
+ cropBox.tuneImageSize();
+ cropBox.intersectionArea = cropBox.imgArea;
+
+ int f = 0;
+ for (auto i : visibleSpots) {
+ f += dstSpotBoxs.at(i)->copyImgTo(cropBox) ? 1 : 0;
+ }
+}
+
+}
+
+namespace
+{
+
+void addSpotDependencies(int spotNum, std::unordered_set &dependencies, const Boxes &srcSpots, const Boxes &dstSpots)
+{
+ dependencies.insert(spotNum);
+
+ // Our spot can depend on previous spots.
+ for (int i = spotNum - 1; i >= 0; --i) {
+ if (dependencies.find(i) != dependencies.end()) {
+ continue; // Spot already has its dependencies added.
+ }
+
+ // Check if our spot depends on this previous spot.
+ if (srcSpots.at(spotNum)->imageIntersects(*dstSpots.at(i))) {
+ // If so, add it and its dependencies.
+ addSpotDependencies(i, dependencies, srcSpots, dstSpots);
+ }
+ }
+}
+
+std::unordered_set calcSpotDependencies(const std::set &visibleSpots, const Boxes &srcSpots, const Boxes &dstSpots)
+{
+ std::unordered_set dependencies;
+ std::vector visibleSpotsOrdered(visibleSpots.size());
+
+ std::copy(visibleSpots.begin(), visibleSpots.end(), visibleSpotsOrdered.begin());
+ std::sort(visibleSpotsOrdered.begin(), visibleSpotsOrdered.end());
+
+ // Add dependencies, starting with the last spot.
+ for (auto i = visibleSpotsOrdered.crbegin(); i != visibleSpotsOrdered.crend(); ++i) {
+ if (dependencies.find(*i) != dependencies.end()) {
+ continue; // Spot already has its dependencies added.
+ }
+ addSpotDependencies(*i, dependencies, srcSpots, dstSpots);
+ }
+
+ return dependencies;
+}
+
+}
+
diff --git a/rtengine/tweakoperator.h b/rtengine/tweakoperator.h
new file mode 100644
index 000000000..e75ea89f2
--- /dev/null
+++ b/rtengine/tweakoperator.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2019 Jean-Christophe FRISCH
+ *
+ * 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
+
+namespace rtengine
+{
+
+namespace procparams
+{
+
+class ProcParams;
+
+}
+
+/** This class can let objects alter the collected values of the ProcParams for a specific
+ * purpose, e.g. displaying a preview image at a specific point in the pipeline or with
+ * disabled tools. Before starting the rendering, the engine will call the TweakOperator
+ * (if set) to modify the ProcParams. The untweaked one will still exist as a backup, and
+ * can be sent back if necessary. */
+class TweakOperator
+{
+public:
+ virtual ~TweakOperator() {}
+
+ /** Callback that will alter the ProcParams before hte image is computed. */
+ virtual void tweakParams(procparams::ProcParams& pparams) = 0;
+};
+
+}
diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc
index b3d31b950..a7125fb9a 100644
--- a/rtexif/rtexif.cc
+++ b/rtexif/rtexif.cc
@@ -139,7 +139,7 @@ TagDirectory* TagDirectory::getRoot()
}
}
-const TagAttrib* TagDirectory::getAttrib (int id)
+const TagAttrib* TagDirectory::getAttrib (int id) const
{
if (attribs)
diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h
index dd89b70ce..7b2f8ad23 100644
--- a/rtexif/rtexif.h
+++ b/rtexif/rtexif.h
@@ -145,12 +145,12 @@ public:
{
return tags.size ();
}
- const TagAttrib* getAttrib (int id);
+ const TagAttrib* getAttrib (int id) const;
// Find a Tag by scanning the whole tag tree and stopping at the first occurrence
const TagAttrib* getAttrib (const char* name);
// Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength")
const TagAttrib* getAttribP (const char* name);
- const TagAttrib* getAttribTable()
+ const TagAttrib* getAttribTable() const
{
return attribs;
}
@@ -321,7 +321,7 @@ public:
Tag* clone (TagDirectory* parent) const;
// to control if the tag shall be written
- bool getKeep ()
+ bool getKeep () const
{
return keep;
}
@@ -331,7 +331,7 @@ public:
}
// get subdirectory (there can be several, the last is NULL)
- bool isDirectory ()
+ bool isDirectory () const
{
return directory != nullptr;
}
@@ -340,7 +340,7 @@ public:
return (directory) ? directory[i] : nullptr;
}
- MNKind getMakerNoteFormat ()
+ MNKind getMakerNoteFormat () const
{
return makerNoteKind;
}
diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt
index 1d4b57553..ed6a0b364 100644
--- a/rtgui/CMakeLists.txt
+++ b/rtgui/CMakeLists.txt
@@ -151,6 +151,7 @@ set(NONCLISOURCEFILES
softlight.cc
soundman.cc
splash.cc
+ spot.cc
threadutils.cc
thresholdadjuster.cc
thresholdselector.cc
diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc
index 4d7a08b5f..9e74ddb90 100644
--- a/rtgui/batchtoolpanelcoord.cc
+++ b/rtgui/batchtoolpanelcoord.cc
@@ -578,6 +578,14 @@ void BatchToolPanelCoordinator::panelChanged(const rtengine::ProcEvent& event, c
}
}
+void BatchToolPanelCoordinator::setTweakOperator (rtengine::TweakOperator *tOperator)
+{
+}
+
+void BatchToolPanelCoordinator::unsetTweakOperator (rtengine::TweakOperator *tOperator)
+{
+}
+
void BatchToolPanelCoordinator::getAutoWB (double& temp, double& green, double equal, double tempBias)
{
diff --git a/rtgui/batchtoolpanelcoord.h b/rtgui/batchtoolpanelcoord.h
index ea11f97c8..0009724e8 100644
--- a/rtgui/batchtoolpanelcoord.h
+++ b/rtgui/batchtoolpanelcoord.h
@@ -56,6 +56,8 @@ public:
// toolpanellistener interface
void panelChanged(const rtengine::ProcEvent& event, const Glib::ustring& descr) override;
+ void setTweakOperator (rtengine::TweakOperator *tOperator) override;
+ void unsetTweakOperator (rtengine::TweakOperator *tOperator) override;
// profilechangelistener interface
void profileChange(
diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc
index 51ca3a4bc..0140c5b62 100644
--- a/rtgui/colortoning.cc
+++ b/rtgui/colortoning.cc
@@ -646,7 +646,7 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited)
lastLumamode = pp->colorToning.lumamode;
- labgrid->setParams(pp->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX, false);
+ labgrid->setParams(pp->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX, 0, 0, 0, 0,false);
if (pedited && !pedited->colorToning.method) {
method->set_active (7);
@@ -715,8 +715,10 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited)
pp->colorToning.satProtectionThreshold = satProtectionThreshold->getIntValue();
pp->colorToning.saturatedOpacity = saturatedOpacity->getIntValue();
pp->colorToning.strength = strength->getIntValue();
-
- labgrid->getParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh);
+ double zerox = 0.;
+ double zeroy = 0.;
+
+ labgrid->getParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh, zerox, zeroy, zerox, zeroy);
pp->colorToning.labgridALow *= ColorToningParams::LABGRID_CORR_MAX;
pp->colorToning.labgridAHigh *= ColorToningParams::LABGRID_CORR_MAX;
pp->colorToning.labgridBLow *= ColorToningParams::LABGRID_CORR_MAX;
@@ -832,7 +834,7 @@ void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited*
hlColSat->setDefault (defParams->colorToning.hlColSat);
shadowsColSat->setDefault (defParams->colorToning.shadowsColSat);
strength->setDefault (defParams->colorToning.strength);
- labgrid->setDefault(defParams->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX);
+ labgrid->setDefault(defParams->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX, 0, 0, 0, 0);
if (pedited) {
@@ -1430,7 +1432,9 @@ void ColorToning::labRegionGet(int idx)
auto &r = labRegionData[idx];
double la, lb;
- labRegionAB->getParams(la, lb, r.a, r.b);
+ double zerox = 0.;
+ double zeroy = 0.;
+ labRegionAB->getParams(la, lb, r.a, r.b, zerox, zeroy, zerox, zeroy);
r.saturation = labRegionSaturation->getValue();
r.slope = labRegionSlope->getValue();
r.offset = labRegionOffset->getValue();
@@ -1566,9 +1570,9 @@ void ColorToning::labRegionShow(int idx, bool list_only)
disableListener();
}
rtengine::procparams::ColorToningParams::LabCorrectionRegion dflt;
- auto &r = labRegionData[idx];
+ auto &r = labRegionData[idx];
if (!list_only) {
- labRegionAB->setParams(0, 0, r.a, r.b, false);
+ labRegionAB->setParams(0, 0, r.a, r.b,0, 0, 0, 0, false);
labRegionSaturation->setValue(r.saturation);
labRegionSlope->setValue(r.slope);
labRegionOffset->setValue(r.offset);
diff --git a/rtgui/controllines.cc b/rtgui/controllines.cc
index 573b3263f..65106f375 100644
--- a/rtgui/controllines.cc
+++ b/rtgui/controllines.cc
@@ -16,6 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
*/
+#include
#include
#include "controllines.h"
@@ -27,6 +28,53 @@
using namespace rtengine;
+enum GeometryIndex {
+ MO_CANVAS,
+ MO_OBJECT_COUNT,
+
+ VISIBLE_OBJECT_COUNT = 0
+};
+
+/**
+ * Offsets for mouse-over geometry that can be compared to the mouse-over object
+ * ID modded with the control line object count.
+ */
+enum GeometryOffset {
+ OFFSET_LINE = (MO_OBJECT_COUNT + ::ControlLine::LINE) % ::ControlLine::OBJECT_COUNT,
+ OFFSET_ICON = (MO_OBJECT_COUNT + ::ControlLine::ICON) % ::ControlLine::OBJECT_COUNT,
+ OFFSET_BEGIN = (MO_OBJECT_COUNT + ::ControlLine::BEGIN) % ::ControlLine::OBJECT_COUNT,
+ OFFSET_END = (MO_OBJECT_COUNT + ::ControlLine::END) % ::ControlLine::OBJECT_COUNT,
+};
+
+namespace
+{
+
+/**
+ * Returns true if the object matches the offset.
+ */
+constexpr bool checkOffset(int object_id, enum GeometryOffset offset)
+{
+ return object_id % ::ControlLine::OBJECT_COUNT == offset;
+}
+
+/**
+ * Converts a control line mouse-over geometry ID to the visible geometry ID.
+ */
+constexpr int mouseOverIdToVisibleId(int mouse_over_id)
+{
+ return mouse_over_id - MO_OBJECT_COUNT + VISIBLE_OBJECT_COUNT;
+}
+
+/**
+ * Converts a control line mouse-over geometry ID to the control line ID.
+ */
+constexpr int mouseOverIdToLineId(int mouse_over_id)
+{
+ return (mouse_over_id - MO_OBJECT_COUNT) / ::ControlLine::OBJECT_COUNT;
+}
+
+}
+
::ControlLine::~ControlLine() = default;
ControlLineManager::ControlLineManager():
@@ -36,6 +84,7 @@ ControlLineManager::ControlLineManager():
draw_mode(false),
drawing_line(false),
edited(false),
+ horizontalCount(0), verticalCount(0),
prev_obj(-1),
selected_object(-1)
{
@@ -79,11 +128,21 @@ void ControlLineManager::setDrawMode(bool draw)
draw_mode = draw;
}
-size_t ControlLineManager::size(void) const
+std::size_t ControlLineManager::size() const
{
return control_lines.size();
}
+std::size_t ControlLineManager::getHorizontalCount() const
+{
+ return horizontalCount;
+}
+
+std::size_t ControlLineManager::getVerticalCount() const
+{
+ return verticalCount;
+}
+
bool ControlLineManager::button1Pressed(int modifierKey)
{
EditDataProvider* dataProvider = getEditProvider();
@@ -96,17 +155,20 @@ bool ControlLineManager::button1Pressed(int modifierKey)
const int object = dataProvider->getObject();
- if (object > 0) { // A control line.
- if (object % ::ControlLine::OBJ_COUNT == 2) { // Icon.
+ if (object >= MO_OBJECT_COUNT) { // A control line.
+ if (checkOffset(object, OFFSET_ICON)) { // Icon.
action = Action::PICKING;
} else {
selected_object = object;
action = Action::DRAGGING;
}
} else if (draw_mode && (modifierKey & GDK_CONTROL_MASK)) { // Add new line.
+ if (object < 0) {
+ return false;
+ }
addLine(dataProvider->posImage, dataProvider->posImage);
drawing_line = true;
- selected_object = mouseOverGeometry.size() - 1; // Select endpoint.
+ selected_object = mouseOverGeometry.size() - ::ControlLine::OBJECT_COUNT + ::ControlLine::END; // Select endpoint.
action = Action::DRAGGING;
}
@@ -117,7 +179,7 @@ bool ControlLineManager::button1Released(void)
{
action = Action::NONE;
- if (selected_object > 0) {
+ if (selected_object >= MO_OBJECT_COUNT) {
mouseOverGeometry[selected_object]->state = Geometry::NORMAL;
}
@@ -125,7 +187,7 @@ bool ControlLineManager::button1Released(void)
callbacks->lineChanged();
drawing_line = false;
selected_object = -1;
- return false;
+ return true;
}
bool ControlLineManager::button3Pressed(int modifierKey)
@@ -134,12 +196,12 @@ bool ControlLineManager::button3Pressed(int modifierKey)
action = Action::NONE;
- if (!provider || provider->getObject() < 1) {
+ if (!provider || provider->getObject() < MO_OBJECT_COUNT) {
return false;
}
action = Action::PICKING;
- return false;
+ return true;
}
bool ControlLineManager::pick1(bool picked)
@@ -152,24 +214,27 @@ bool ControlLineManager::pick1(bool picked)
EditDataProvider* provider = getEditProvider();
- if (!provider || provider->getObject() % ::ControlLine::OBJ_COUNT != 2) {
+ if (!provider || !checkOffset(provider->getObject(), OFFSET_ICON)) {
return false;
}
// Change line type.
int object_id = provider->getObject();
- ::ControlLine& line =
- *control_lines[(object_id - 1) / ::ControlLine::OBJ_COUNT];
+ ::ControlLine& line = *control_lines[mouseOverIdToLineId(object_id)];
if (line.type == rtengine::ControlLine::HORIZONTAL) {
line.icon = line.icon_v;
line.type = rtengine::ControlLine::VERTICAL;
+ horizontalCount--;
+ verticalCount++;
} else if (line.type == rtengine::ControlLine::VERTICAL) {
line.icon = line.icon_h;
line.type = rtengine::ControlLine::HORIZONTAL;
+ horizontalCount++;
+ verticalCount--;
}
- visibleGeometry[object_id - 1] = line.icon.get();
+ visibleGeometry[mouseOverIdToVisibleId(object_id)] = line.icon.get();
edited = true;
callbacks->lineChanged();
@@ -191,38 +256,42 @@ bool ControlLineManager::pick3(bool picked)
return false;
}
- removeLine((provider->getObject() - 1) / ::ControlLine::OBJ_COUNT);
+ removeLine(mouseOverIdToLineId(provider->getObject()));
prev_obj = -1;
selected_object = -1;
- return false;
+ return true;
}
bool ControlLineManager::drag1(int modifierKey)
{
+ if (action != Action::DRAGGING) {
+ return false;
+ }
+
EditDataProvider* provider = getEditProvider();
- if (!provider || selected_object < 1) {
+ if (!provider || selected_object < MO_OBJECT_COUNT) {
return false;
}
::ControlLine& control_line =
- *control_lines[(selected_object - 1) / ::ControlLine::OBJ_COUNT];
+ *control_lines[mouseOverIdToLineId(selected_object)];
// 0 == end, 1 == line, 2 == icon, 3 == begin
- int component = selected_object % ::ControlLine::OBJ_COUNT;
+ int component = selected_object % ::ControlLine::OBJECT_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
+ case (OFFSET_END): // 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
+ case (OFFSET_LINE): { // line
// Constrain delta so the end stays above the image.
Coord new_delta = control_line.end->center + delta;
new_delta.clip(iw, ih);
@@ -241,7 +310,7 @@ bool ControlLineManager::drag1(int modifierKey)
break;
}
- case (3): // begin
+ case (OFFSET_BEGIN): // begin
control_line.begin->center = mouse;
control_line.begin->center.clip(iw, ih);
control_line.line->begin = control_line.begin->center;
@@ -260,7 +329,24 @@ bool ControlLineManager::drag1(int modifierKey)
autoSetLineType(selected_object);
}
- return false;
+ return true;
+}
+
+void ControlLineManager::releaseEdit(void)
+{
+ action = Action::NONE;
+
+ if (selected_object >= MO_OBJECT_COUNT) {
+ mouseOverGeometry[selected_object]->state = Geometry::NORMAL;
+ }
+ if (prev_obj >= MO_OBJECT_COUNT) {
+ visibleGeometry[mouseOverIdToVisibleId(prev_obj)]->state = Geometry::NORMAL;
+ }
+
+ edited = true;
+ callbacks->lineChanged();
+ drawing_line = false;
+ selected_object = -1;
}
bool ControlLineManager::getEdited(void) const
@@ -268,7 +354,7 @@ bool ControlLineManager::getEdited(void) const
return edited;
}
-CursorShape ControlLineManager::getCursor(int objectID) const
+CursorShape ControlLineManager::getCursor(int objectID, int xPos, int yPos) const
{
return cursor;
}
@@ -283,7 +369,7 @@ bool ControlLineManager::mouseOver(int modifierKey)
int cur_obj = provider->getObject();
- if (cur_obj == 0) { // Canvas
+ if (cur_obj == MO_CANVAS) { // Canvas
if (draw_mode && modifierKey & GDK_CONTROL_MASK) {
cursor = CSCrosshair;
} else {
@@ -291,16 +377,16 @@ bool ControlLineManager::mouseOver(int modifierKey)
}
} else if (cur_obj < 0) { // Nothing
cursor = CSArrow;
- } else if (cur_obj % ::ControlLine::OBJ_COUNT == 2) { // Icon
- visibleGeometry[cur_obj - 1]->state = Geometry::PRELIGHT;
+ } else if (checkOffset(cur_obj, OFFSET_ICON)) { // Icon
+ visibleGeometry[mouseOverIdToVisibleId(cur_obj)]->state = Geometry::PRELIGHT;
cursor = CSArrow;
} else { // Object
- visibleGeometry[cur_obj - 1]->state = Geometry::PRELIGHT;
+ visibleGeometry[mouseOverIdToVisibleId(cur_obj)]->state = Geometry::PRELIGHT;
cursor = CSMove2D;
}
- if (prev_obj != cur_obj && prev_obj > 0) {
- visibleGeometry[prev_obj - 1]->state = Geometry::NORMAL;
+ if (prev_obj != cur_obj && prev_obj >= MO_OBJECT_COUNT) {
+ visibleGeometry[mouseOverIdToVisibleId(prev_obj)]->state = Geometry::NORMAL;
}
prev_obj = cur_obj;
@@ -394,22 +480,42 @@ void ControlLineManager::addLine(Coord begin, Coord end,
control_line->line = std::move(line);
control_line->type = type;
+ auto assertEqual = [](size_t a, int b) {
+ assert(b >= 0);
+ assert(a == static_cast(b));
+ };
+
+ const int base_visible_offset = VISIBLE_OBJECT_COUNT + ::ControlLine::OBJECT_COUNT * control_lines.size();
+ assertEqual(visibleGeometry.size(), base_visible_offset + ::ControlLine::LINE);
EditSubscriber::visibleGeometry.push_back(control_line->line.get());
+ assertEqual(visibleGeometry.size(), base_visible_offset + ::ControlLine::ICON);
EditSubscriber::visibleGeometry.push_back(control_line->icon.get());
+ assertEqual(visibleGeometry.size(), base_visible_offset + ::ControlLine::BEGIN);
EditSubscriber::visibleGeometry.push_back(control_line->begin.get());
+ assertEqual(visibleGeometry.size(), base_visible_offset + ::ControlLine::END);
EditSubscriber::visibleGeometry.push_back(control_line->end.get());
+ const int base_mo_count = MO_OBJECT_COUNT + ::ControlLine::OBJECT_COUNT * control_lines.size();
+ assertEqual(mouseOverGeometry.size(), base_mo_count + ::ControlLine::LINE);
EditSubscriber::mouseOverGeometry.push_back(control_line->line.get());
+ assertEqual(mouseOverGeometry.size(), base_mo_count + ::ControlLine::ICON);
EditSubscriber::mouseOverGeometry.push_back(control_line->icon.get());
+ assertEqual(mouseOverGeometry.size(), base_mo_count + ::ControlLine::BEGIN);
EditSubscriber::mouseOverGeometry.push_back(control_line->begin.get());
+ assertEqual(mouseOverGeometry.size(), base_mo_count + ::ControlLine::END);
EditSubscriber::mouseOverGeometry.push_back(control_line->end.get());
control_lines.push_back(std::move(control_line));
+ if (type == rtengine::ControlLine::HORIZONTAL) {
+ horizontalCount++;
+ } else {
+ verticalCount++;
+ }
}
void ControlLineManager::autoSetLineType(int object_id)
{
- int line_id = (object_id - 1) / ::ControlLine::OBJ_COUNT;
+ int line_id = mouseOverIdToLineId(object_id);
::ControlLine& line = *control_lines[line_id];
int dx = line.begin->center.x - line.end->center.x;
@@ -437,7 +543,15 @@ void ControlLineManager::autoSetLineType(int object_id)
if (type != line.type) { // Need to update line type.
line.type = type;
line.icon = icon;
- visibleGeometry[line_id * ::ControlLine::OBJ_COUNT + 1] =
+ if (type == rtengine::ControlLine::HORIZONTAL) {
+ horizontalCount++;
+ verticalCount--;
+ } else {
+ horizontalCount--;
+ verticalCount++;
+ }
+ visibleGeometry[line_id * ::ControlLine::OBJECT_COUNT
++ VISIBLE_OBJECT_COUNT + ::ControlLine::ICON] =
line.icon.get();
}
}
@@ -445,31 +559,36 @@ void ControlLineManager::autoSetLineType(int object_id)
void ControlLineManager::removeAll(void)
{
visibleGeometry.clear();
- mouseOverGeometry.erase(mouseOverGeometry.begin() + 1,
+ mouseOverGeometry.erase(mouseOverGeometry.begin() + MO_OBJECT_COUNT,
mouseOverGeometry.end());
control_lines.clear();
+ horizontalCount = verticalCount = 0;
prev_obj = -1;
selected_object = -1;
edited = true;
callbacks->lineChanged();
}
-void ControlLineManager::removeLine(size_t line_id)
+void ControlLineManager::removeLine(std::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
+ visibleGeometry.begin() + ::ControlLine::OBJECT_COUNT * line_id + VISIBLE_OBJECT_COUNT,
+ visibleGeometry.begin() + ::ControlLine::OBJECT_COUNT * line_id + VISIBLE_OBJECT_COUNT
+ + ::ControlLine::OBJECT_COUNT
);
mouseOverGeometry.erase(
- mouseOverGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id + 1,
- mouseOverGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id
- + ::ControlLine::OBJ_COUNT + 1
+ mouseOverGeometry.begin() + ::ControlLine::OBJECT_COUNT * line_id + MO_OBJECT_COUNT,
+ mouseOverGeometry.begin() + ::ControlLine::OBJECT_COUNT * line_id + MO_OBJECT_COUNT + ::ControlLine::OBJECT_COUNT
);
+ if (control_lines[line_id]->type == rtengine::ControlLine::HORIZONTAL) {
+ horizontalCount--;
+ } else {
+ verticalCount--;
+ }
control_lines.erase(control_lines.begin() + line_id);
edited = true;
diff --git a/rtgui/controllines.h b/rtgui/controllines.h
index 0ff449092..9e850da1c 100644
--- a/rtgui/controllines.h
+++ b/rtgui/controllines.h
@@ -30,7 +30,14 @@ class Rectangle;
class RTSurface;
struct ControlLine {
- static constexpr int OBJ_COUNT = 4;
+ enum ObjectIndex {
+ LINE,
+ ICON,
+ BEGIN,
+ END,
+ OBJECT_COUNT
+ };
+
std::unique_ptr line;
std::shared_ptr icon;
std::shared_ptr icon_h, icon_v;
@@ -52,6 +59,7 @@ protected:
bool draw_mode;
bool drawing_line;
bool edited;
+ std::size_t horizontalCount, verticalCount;
Cairo::RefPtr line_icon_h, line_icon_v;
Cairo::RefPtr line_icon_h_prelight, line_icon_v_prelight;
int prev_obj;
@@ -67,7 +75,7 @@ protected:
* line, inclusive, the line type is set to vertical. Otherwise, horizontal.
*/
void autoSetLineType(int object_id);
- void removeLine(size_t line_id);
+ void removeLine(std::size_t line_id);
public:
class Callbacks
@@ -87,6 +95,12 @@ public:
~ControlLineManager();
bool getEdited(void) const;
+ /** Returns the number of horizontal control lines. */
+ std::size_t getHorizontalCount() const;
+ /** Returns the number of vertical control lines. */
+ std::size_t getVerticalCount() const;
+ /** Release anything that is currently being dragged. */
+ void releaseEdit(void);
void removeAll(void);
/** Sets whether or not the lines are visible and interact-able. */
void setActive(bool active);
@@ -96,7 +110,7 @@ public:
void setEditProvider(EditDataProvider* provider);
void setLines(const std::vector& lines);
/** Returns the number of lines. */
- size_t size(void) const;
+ std::size_t size() const;
/**
* Allocates a new array and populates it with copies of the control lines.
*/
@@ -109,7 +123,7 @@ public:
bool pick1(bool picked) override;
bool pick3(bool picked) override;
bool drag1(int modifierKey) override;
- CursorShape getCursor(int objectID) const override;
+ CursorShape getCursor(int objectID, int xPos, int yPos) const override;
bool mouseOver(int modifierKey) override;
void switchOffEditMode(void) override;
};
diff --git a/rtgui/controlspotpanel.cc b/rtgui/controlspotpanel.cc
index 48aa6dab1..bdf723992 100644
--- a/rtgui/controlspotpanel.cc
+++ b/rtgui/controlspotpanel.cc
@@ -2197,7 +2197,7 @@ void ControlSpotPanel::updateCurveOpacity(const Gtk::TreeModel::Row& selectedRow
}
}
-CursorShape ControlSpotPanel::getCursor(int objectID) const
+CursorShape ControlSpotPanel::getCursor(int objectID, int xPos, int yPos) const
{
// printf("Object ID: %d\n", objectID);
diff --git a/rtgui/controlspotpanel.h b/rtgui/controlspotpanel.h
index 2f92b9a77..b748df544 100644
--- a/rtgui/controlspotpanel.h
+++ b/rtgui/controlspotpanel.h
@@ -267,7 +267,7 @@ private:
void updateControlSpotCurve(const Gtk::TreeModel::Row& row);
void deleteControlSpotCurve(Gtk::TreeModel::Row& row);
void updateCurveOpacity(const Gtk::TreeModel::Row& selectedRow);
- CursorShape getCursor(int objectID) const override;
+ CursorShape getCursor(int objectID, int xPos, int yPos) const override;
bool mouseOver(int modifierKey) override;
bool button1Pressed(int modifierKey) override;
bool button1Released() override;
diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc
index 1ed9211a1..2927cdf32 100644
--- a/rtgui/cropwindow.cc
+++ b/rtgui/cropwindow.cc
@@ -510,7 +510,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y)
cropgl->cropInit (cropHandler.cropParams->x, cropHandler.cropParams->y, cropHandler.cropParams->w, cropHandler.cropParams->h);
} else if (iarea->getToolMode () == TMHand) {
if (editSubscriber) {
- if ((cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK))) {
+ if ((cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK))) || editSubscriber->getEditingType() == ET_OBJECTS) {
needRedraw = editSubscriber->button1Pressed(bstate);
if (editSubscriber->isDragging()) {
state = SEditDrag1;
@@ -540,7 +540,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y)
action_y = 0;
}
- } else if (iarea->getToolMode () == TMHand) { // events outside of the image domain
+ } else if (iarea->getToolMode () == TMHand || iarea->getToolMode() == TMPerspective) { // events outside of the image domain
EditSubscriber *editSubscriber = iarea->getCurrSubscriber();
if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) {
@@ -705,15 +705,15 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y)
state = SNormal;
needRedraw = true;
} else if (state == SEditDrag1 || state == SEditDrag2 || state == SEditDrag3) {
- if (state == SEditDrag1) {
- needRedraw = editSubscriber->button1Released();
- } else if (state == SEditDrag2) {
- needRedraw = editSubscriber->button2Released();
- } else if (state == SEditDrag3) {
- needRedraw = editSubscriber->button3Released();
- }
-
if (editSubscriber) {
+ if (state == SEditDrag1) {
+ needRedraw = editSubscriber->button1Released();
+ } else if (state == SEditDrag2) {
+ needRedraw = editSubscriber->button2Released();
+ } else if (state == SEditDrag3) {
+ needRedraw = editSubscriber->button3Released();
+ }
+
rtengine::Crop* crop = static_cast(cropHandler.getCrop());
Coord imgPos;
action_x = x;
@@ -794,6 +794,13 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y)
iarea->setToolHand ();
}
+ if (state != SEditDrag1 && state != SEditDrag2 && state != SEditDrag3) {
+ iarea->deltaImage.set(0, 0);
+ iarea->deltaScreen.set(0, 0);
+ iarea->deltaPrevImage.set(0, 0);
+ iarea->deltaPrevScreen.set(0, 0);
+ }
+
if (cropgl && (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove)) {
cropgl->cropManipReady ();
iarea->setToolHand ();
@@ -1128,7 +1135,7 @@ void CropWindow::pointerMoved (int bstate, int x, int y)
rtengine::StagedImageProcessor* ipc = iarea->getImProcCoordinator();
if(ipc) {
procparams::ProcParams params;
- ipc->getParams(¶ms);
+ ipc->getParams(¶ms, true);
isRaw = params.raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::NONE) || params.raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::NONE);
if(isRaw) {
ImageSource *isrc = static_cast(ipc->getInitialImage());
@@ -1293,7 +1300,10 @@ void CropWindow::updateCursor (int x, int y)
} else if (onArea (CropToolBar, x, y)) {
newType = CSMove;
} else if (iarea->getObject() > -1 && editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) {
- newType = editSubscriber->getCursor(iarea->getObject());
+ int cursorX;
+ int cursorY;
+ screenCoordToImage (x, y, cursorX, cursorY);
+ newType = editSubscriber->getCursor(iarea->getObject(), cursorX, cursorY);
} else if (onArea (CropResize, x, y)) {
newType = CSResizeDiagonal;
} else if (tm == TMColorPicker && hoveredPicker) {
@@ -1320,7 +1330,10 @@ void CropWindow::updateCursor (int x, int y)
}
if (objectID > -1) {
- newType = editSubscriber->getCursor(objectID);
+ int cursorX;
+ int cursorY;
+ screenCoordToImage (x, y, cursorX, cursorY);
+ newType = editSubscriber->getCursor(objectID, cursorX, cursorY);
} else if (tm == TMHand) {
if (onArea (CropObserved, x, y)) {
newType = CSMove;
@@ -1346,7 +1359,10 @@ void CropWindow::updateCursor (int x, int y)
}
if (objectID > -1) {
- newType = editSubscriber->getCursor(objectID);
+ int cursorX;
+ int cursorY;
+ screenCoordToImage (x, y, cursorX, cursorY);
+ newType = editSubscriber->getCursor(objectID, cursorX, cursorY);
} else {
newType = CSArrow;
}
@@ -1375,6 +1391,16 @@ void CropWindow::updateCursor (int x, int y)
newType = CSResizeDiagonal;
} else if (state == SDragPicker) {
newType = CSMove2D;
+ } else if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) {
+ int objectID = iarea->getObject();
+ if (objectID > -1) {
+ int cursorX;
+ int cursorY;
+ screenCoordToImage (x, y, cursorX, cursorY);
+ newType = editSubscriber->getCursor(objectID, cursorX, cursorY);
+ } else {
+ newType = CSArrow;
+ }
}
if (newType != cursor_type) {
diff --git a/rtgui/curveeditor.cc b/rtgui/curveeditor.cc
index e38f3a947..67cea5174 100644
--- a/rtgui/curveeditor.cc
+++ b/rtgui/curveeditor.cc
@@ -504,7 +504,7 @@ bool CurveEditor::drag1(int modifierKey)
return false;
}
-CursorShape CurveEditor::getCursor(int objectID) const
+CursorShape CurveEditor::getCursor(int objectID, int xPos, int yPos) const
{
if (remoteDrag) {
return CSResizeHeight;
diff --git a/rtgui/curveeditor.h b/rtgui/curveeditor.h
index d5ec49559..398c63603 100644
--- a/rtgui/curveeditor.h
+++ b/rtgui/curveeditor.h
@@ -133,7 +133,7 @@ public:
bool button1Pressed(int modifierKey) override;
bool button1Released() override;
bool drag1(int modifierKey) override;
- CursorShape getCursor(int objectID) const override;
+ CursorShape getCursor(int objectID, int xPos, int yPos) const override;
};
diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc
index 5c120f7e4..d099e1a99 100644
--- a/rtgui/curveeditorgroup.cc
+++ b/rtgui/curveeditorgroup.cc
@@ -29,12 +29,17 @@
#include "options.h"
#include "pathutils.h"
-CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, Glib::ustring groupLabel) : curveDir(curveDir), line(0), curve_reset(nullptr),
+CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, Glib::ustring groupLabel, int blank) : curveDir(curveDir), line(0), curve_reset(nullptr),
displayedCurve(nullptr), flatSubGroup(nullptr), diagonalSubGroup(nullptr), cl(nullptr), numberOfPackedCurve(0)
{
// We set the label to the one provided as parameter, even if it's an empty string
- curveGroupLabel = Gtk::manage (new Gtk::Label (groupLabel + ":", Gtk::ALIGN_START));
+ if(blank == 0) {
+ curveGroupLabel = Gtk::manage (new Gtk::Label (groupLabel + ":", Gtk::ALIGN_START));
+ } else if(blank == 1){
+ curveGroupLabel = Gtk::manage (new Gtk::Label (groupLabel, Gtk::ALIGN_START));
+ }
+
setExpandAlignProperties(curveGroupLabel, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
set_row_spacing(RTScalable::getScale());
}
diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h
index 0f7c01a32..55d438b2d 100644
--- a/rtgui/curveeditorgroup.h
+++ b/rtgui/curveeditorgroup.h
@@ -71,7 +71,7 @@ public:
* dialogs.
*/
- explicit CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = "");
+ explicit CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = "", int blank = 0);
~CurveEditorGroup() override;
void newLine();
void curveListComplete();
diff --git a/rtgui/editcallbacks.cc b/rtgui/editcallbacks.cc
index 5404b0bc9..71c342874 100644
--- a/rtgui/editcallbacks.cc
+++ b/rtgui/editcallbacks.cc
@@ -173,10 +173,10 @@ void EditDataProvider::setPipetteVal3(float newVal)
pipetteVal3 = newVal;
}
-CursorShape EditDataProvider::getCursor(int objectID) const
+CursorShape EditDataProvider::getCursor(int objectID, int xPos, int yPos) const
{
if (currSubscriber) {
- currSubscriber->getCursor(objectID);
+ currSubscriber->getCursor(objectID, xPos, yPos);
}
return CSHandOpen;
@@ -187,12 +187,12 @@ EditSubscriber* EditDataProvider::getCurrSubscriber() const
return currSubscriber;
}
-EditDataProvider* EditSubscriber::getEditProvider()
+EditDataProvider* EditSubscriber::getEditProvider() const
{
return provider;
}
-CursorShape EditSubscriber::getCursor(int objectID) const
+CursorShape EditSubscriber::getCursor(int objectID, int xPos, int yPos) const
{
return CSHandOpen;
}
diff --git a/rtgui/editcallbacks.h b/rtgui/editcallbacks.h
index d81e84806..134ea6477 100644
--- a/rtgui/editcallbacks.h
+++ b/rtgui/editcallbacks.h
@@ -57,7 +57,7 @@ public:
virtual ~EditSubscriber () = default;
void setEditProvider(EditDataProvider *provider);
- EditDataProvider* getEditProvider ();
+ EditDataProvider* getEditProvider () const;
void setEditID(EditUniqueID ID, BufferType buffType);
bool isCurrentSubscriber() const;
virtual void subscribe();
@@ -70,8 +70,10 @@ public:
bool isPicking() const; /// Returns true if something is being picked
/** @brief Get the cursor to be displayed when above handles
- @param objectID object currently "hovered" */
- virtual CursorShape getCursor (int objectID) const;
+ @param objectID object currently "hovered"
+ @param xPos X cursor position in image space
+ @param yPos Y cursor position in image space */
+ virtual CursorShape getCursor (int objectID, int xPos, int yPos) const;
/** @brief Triggered when the mouse is moving over an object
This method is also triggered when the cursor is moving over the image in ET_PIPETTE mode
@@ -189,7 +191,7 @@ public:
void setPipetteVal1(float newVal);
void setPipetteVal2(float newVal);
void setPipetteVal3(float newVal);
- virtual CursorShape getCursor(int objectID) const;
+ virtual CursorShape getCursor(int objectID, int xPos, int yPos) const;
int getPipetteRectSize () const;
EditSubscriber* getCurrSubscriber() const;
virtual void getImageSize (int &w, int&h) = 0;
diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc
index 021333503..5c61e672e 100644
--- a/rtgui/editorpanel.cc
+++ b/rtgui/editorpanel.cc
@@ -637,6 +637,8 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
vboxright = new Gtk::Paned (Gtk::ORIENTATION_VERTICAL);
vsubboxright = new Gtk::Box (Gtk::ORIENTATION_VERTICAL, 0);
+// int rightsize = options.fontSize * 44;
+// vsubboxright->set_size_request (rightsize, rightsize - 50);
vsubboxright->set_size_request (300, 250);
vsubboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 2);
@@ -1759,7 +1761,7 @@ void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt)
PartialProfile pp (true);
pp.set (true);
* (pp.pparams) = openThm->getProcParams();
- pp.pedited->locallab.spots.resize(pp.pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true));
+ pp.pedited->locallab.spots.resize(pp.pparams->locallab.spots.size(), LocallabParamsEdited::LocallabSpotEdited(true));
tpc->profileChange (&pp, rtengine::EvProfileChangeNotification, M ("PROGRESSDLG_PROFILECHANGEDINBROWSER"));
pp.deleteInstance();
}
@@ -1974,6 +1976,9 @@ void EditorPanel::sendToExternal()
// develop image
rtengine::procparams::ProcParams pparams;
ipc->getParams (&pparams);
+ if (options.editor_bypass_output_profile) {
+ pparams.icm.outputProfile = rtengine::procparams::ColorManagementParams::NoProfileString;
+ }
if (!cached_exported_filename.empty() && pparams == cached_exported_pparams && Glib::file_test(cached_exported_filename, Glib::FILE_TEST_IS_REGULAR)) {
idle_sentToGimp(nullptr, nullptr, cached_exported_filename);
@@ -2077,24 +2082,40 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *p
if (img) {
// get file name base
- const Glib::ustring shortname = removeExtension (Glib::path_get_basename (fname));
- const Glib::ustring dirname = Glib::get_tmp_dir ();
- const Glib::ustring lfname = Glib::build_filename (dirname, shortname);
+ Glib::ustring shortname = removeExtension(Glib::path_get_basename(fname));
+ Glib::ustring dirname;
+ switch (options.editor_out_dir) {
+ case Options::EDITOR_OUT_DIR_CURRENT:
+ dirname = Glib::path_get_dirname(fname);
+ break;
+ case Options::EDITOR_OUT_DIR_CUSTOM:
+ dirname = options.editor_custom_out_dir;
+ break;
+ default: // Options::EDITOR_OUT_DIR_TEMP
+ dirname = Glib::get_tmp_dir();
+ break;
+ }
+ Glib::ustring fullFileName = Glib::build_filename(dirname, shortname);
SaveFormat sf;
sf.format = "tif";
- sf.tiffBits = 16;
- sf.tiffFloat = false;
+ if (options.editor_float32) {
+ sf.tiffBits = 32;
+ sf.tiffFloat = true;
+ } else {
+ sf.tiffBits = 16;
+ sf.tiffFloat = false;
+ }
+
sf.tiffUncompressed = true;
sf.saveParams = true;
- Glib::ustring fileName = Glib::ustring::compose ("%1.%2", lfname, sf.format);
+ Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fullFileName, sf.format);
// TODO: Just list all file with a suitable name instead of brute force...
int tries = 1;
-
while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries < 1000) {
- fileName = Glib::ustring::compose ("%1-%2.%3", lfname, tries, sf.format);
+ fileName = Glib::ustring::compose ("%1-%2.%3", fullFileName, tries, sf.format);
tries++;
}
diff --git a/rtgui/editwidgets.cc b/rtgui/editwidgets.cc
index fccdb874a..f9c9b3781 100644
--- a/rtgui/editwidgets.cc
+++ b/rtgui/editwidgets.cc
@@ -22,7 +22,11 @@
#include "editbuffer.h"
#include "editcallbacks.h"
#include "rtsurface.h"
-#include "../rtengine/rt_math.h"
+
+const std::vector Geometry::dash = {3., 1.5};
+
+#define INNERGEOM_OPACITY 1.
+#define OUTERGEOM_OPACITY 0.7
RGBColor Geometry::getInnerLineColor ()
{
@@ -67,7 +71,8 @@ RGBColor Geometry::getOuterLineColor ()
void Circle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
{
- if ((flags & F_VISIBLE) && state != INSENSITIVE) {
+ double lineWidth = getOuterLineWidth();
+ if ((flags & F_VISIBLE) && state != INSENSITIVE && lineWidth > 0. && innerLineWidth > 0.) {
RGBColor color;
if (flags & F_AUTO_COLOR) {
@@ -76,8 +81,9 @@ void Circle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer
color = outerLineColor;
}
- cr->set_source_rgba (color.getR(), color.getG(), color.getB(), opacity / 100.);
- cr->set_line_width( getOuterLineWidth() );
+ cr->set_source_rgba (color.getR(), color.getG(), color.getB(), OUTERGEOM_OPACITY * rtengine::min(innerLineWidth / 2.f, 1.f));
+ cr->set_line_width (lineWidth);
+ cr->set_line_cap(Cairo::LINE_CAP_ROUND);
rtengine::Coord center_ = center;
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius);
@@ -107,10 +113,11 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer
color = innerLineColor;
}
- cr->set_source_rgba(color.getR(), color.getG(), color.getB(), opacity / 100.);
+ cr->set_source_rgba (color.getR(), color.getG(), color.getB(), INNERGEOM_OPACITY);
}
- cr->set_line_width( innerLineWidth );
+ cr->set_line_width(innerLineWidth);
+ cr->set_line_cap(flags & F_DASHED ? Cairo::LINE_CAP_BUTT : Cairo::LINE_CAP_ROUND);
rtengine::Coord center_ = center;
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius);
@@ -123,9 +130,12 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer
center_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen;
}
- if (filled && state != INSENSITIVE) {
- cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*rtengine::RT_PI);
+ if (flags & F_DASHED) {
+ cr->set_dash(dash, 0.);
+ }
+ if (filled) {
+ cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*rtengine::RT_PI);
if (innerLineWidth > 0.f) {
cr->fill_preserve();
cr->stroke();
@@ -134,28 +144,20 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer
}
} else if (innerLineWidth > 0.f) {
cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*rtengine::RT_PI);
-
- if (state == INSENSITIVE) {
- std::valarray ds(1);
- ds[0] = 4;
- cr->set_source_rgba(1.0, 1.0, 1.0, 0.618);
- cr->stroke_preserve();
- cr->set_source_rgba(0.0, 0.0, 0.0, 0.618);
- cr->set_dash(ds, 0);
- cr->stroke();
- ds.resize(0);
- cr->set_dash(ds, 0);
- } else {
- cr->stroke();
- }
+ cr->stroke();
}
- }
+
+ if (flags & F_DASHED) {
+ cr->unset_dash();
+ }
+}
}
void Circle::drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
{
if (flags & F_HOVERABLE) {
cr->set_line_width( getMouseOverLineWidth() );
+ cr->set_line_cap(Cairo::LINE_CAP_ROUND);
rtengine::Coord center_ = center;
double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius);
@@ -190,7 +192,8 @@ void Circle::drawToMOChannel (Cairo::RefPtr &cr, unsigned short
void Line::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
{
- if ((flags & F_VISIBLE) && state != INSENSITIVE) {
+ double lineWidth = getOuterLineWidth();
+ if ((flags & F_VISIBLE) && state != INSENSITIVE && lineWidth > 0. && innerLineWidth > 0.) {
RGBColor color;
if (flags & F_AUTO_COLOR) {
@@ -199,8 +202,9 @@ void Line::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *
color = outerLineColor;
}
- cr->set_source_rgba (color.getR(), color.getG(), color.getB(), opacity / 100.0);
- cr->set_line_width( getOuterLineWidth() );
+ cr->set_source_rgba (color.getR(), color.getG(), color.getB(), OUTERGEOM_OPACITY * rtengine::min(innerLineWidth / 2.f, 1.f));
+ cr->set_line_width (lineWidth);
+ cr->set_line_cap(Cairo::LINE_CAP_ROUND);
rtengine::Coord begin_ = begin;
rtengine::Coord end_ = end;
@@ -234,10 +238,11 @@ void Line::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *
color = innerLineColor;
}
- cr->set_source_rgba (color.getR(), color.getG(), color.getB(), opacity / 100.);
+ cr->set_source_rgba (color.getR(), color.getG(), color.getB(), INNERGEOM_OPACITY);
}
cr->set_line_width(innerLineWidth);
+ cr->set_line_cap(flags & F_DASHED ? Cairo::LINE_CAP_BUTT : Cairo::LINE_CAP_ROUND);
rtengine::Coord begin_ = begin;
rtengine::Coord end_ = end;
@@ -253,21 +258,16 @@ void Line::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *
end_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen;
}
+ if (flags & F_DASHED) {
+ cr->set_dash(dash, 0.);
+ }
+
cr->move_to(begin_.x + 0.5, begin_.y + 0.5);
cr->line_to(end_.x + 0.5, end_.y + 0.5);
+ cr->stroke();
- if (state == INSENSITIVE) {
- std::valarray ds(1);
- ds[0] = 4;
- cr->set_source_rgba(1.0, 1.0, 1.0, 0.618);
- cr->stroke_preserve();
- cr->set_source_rgba(0.0, 0.0, 0.0, 0.618);
- cr->set_dash(ds, 0);
- cr->stroke();
- ds.resize(0);
- cr->set_dash(ds, 0);
- } else {
- cr->stroke();
+ if (flags & F_DASHED) {
+ cr->unset_dash();
}
}
}
@@ -276,6 +276,7 @@ void Line::drawToMOChannel(Cairo::RefPtr &cr, unsigned short id,
{
if (flags & F_HOVERABLE) {
cr->set_line_width( getMouseOverLineWidth() );
+ cr->set_line_cap(Cairo::LINE_CAP_ROUND);
rtengine::Coord begin_ = begin;
rtengine::Coord end_ = end;
@@ -304,7 +305,8 @@ void Line::drawToMOChannel(Cairo::RefPtr &cr, unsigned short id,
void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
{
- if ((flags & F_VISIBLE) && state != INSENSITIVE && points.size() > 1) {
+ double lineWidth = getOuterLineWidth();
+ if ((flags & F_VISIBLE) && state != INSENSITIVE && points.size() > 1 && lineWidth > 0.) {
RGBColor color;
if (flags & F_AUTO_COLOR) {
@@ -313,8 +315,10 @@ void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuff
color = outerLineColor;
}
- cr->set_source_rgba (color.getR(), color.getG(), color.getB(), opacity / 100.);
- cr->set_line_width( getOuterLineWidth() );
+ cr->set_source_rgba (color.getR(), color.getG(), color.getB(), OUTERGEOM_OPACITY * rtengine::min(innerLineWidth / 2.f, 1.f));
+ cr->set_line_width (lineWidth);
+ cr->set_line_cap(Cairo::LINE_CAP_ROUND);
+ cr->set_line_join(Cairo::LINE_JOIN_ROUND);
rtengine::Coord currPos;
@@ -357,10 +361,16 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuff
color = innerLineColor;
}
- cr->set_source_rgba (color.getR(), color.getG(), color.getB(), opacity / 100.);
+ cr->set_source_rgba (color.getR(), color.getG(), color.getB(), INNERGEOM_OPACITY);
}
- cr->set_line_width( innerLineWidth );
+ cr->set_line_width(innerLineWidth);
+ cr->set_line_cap(flags & F_DASHED ? Cairo::LINE_CAP_BUTT : Cairo::LINE_CAP_ROUND);
+ cr->set_line_join(Cairo::LINE_JOIN_ROUND);
+
+ if (flags & F_DASHED) {
+ cr->set_dash(dash, 0.);
+ }
if (filled && state != INSENSITIVE) {
rtengine::Coord currPos;
@@ -409,20 +419,11 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuff
cr->line_to(currPos.x + 0.5, currPos.y + 0.5);
}
}
+ cr->stroke();
+ }
- if (state == INSENSITIVE) {
- std::valarray ds(1);
- ds[0] = 4;
- cr->set_source_rgba(1.0, 1.0, 1.0, 0.618);
- cr->stroke_preserve();
- cr->set_source_rgba(0.0, 0.0, 0.0, 0.618);
- cr->set_dash(ds, 0);
- cr->stroke();
- ds.resize(0);
- cr->set_dash(ds, 0);
- } else {
- cr->stroke();
- }
+ if (flags & F_DASHED) {
+ cr->unset_dash();
}
}
}
@@ -439,8 +440,11 @@ void Polyline::drawToMOChannel (Cairo::RefPtr &cr, unsigned shor
cr->set_source_rgba (0., 0., 0., (id + 1) / 65535.);
}
+ cr->set_line_width( getMouseOverLineWidth() );
+ cr->set_line_cap(Cairo::LINE_CAP_ROUND);
+ cr->set_line_join(Cairo::LINE_JOIN_ROUND);
+
for (unsigned int i = 0; i < points.size(); ++i) {
- cr->set_line_width( getMouseOverLineWidth() );
currPos = points.at(i);
if (datum == IMAGE) {
@@ -497,7 +501,8 @@ void Rectangle::setXYXY(rtengine::Coord topLeft, rtengine::Coord bottomRight)
void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
{
- if ((flags & F_VISIBLE) && state != INSENSITIVE) {
+ double lineWidth = getOuterLineWidth();
+ if ((flags & F_VISIBLE) && state != INSENSITIVE && lineWidth > 0. && innerLineWidth > 0.) {
RGBColor color;
if (flags & F_AUTO_COLOR) {
@@ -506,8 +511,9 @@ void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuf
color = outerLineColor;
}
- cr->set_source_rgba (color.getR(), color.getG(), color.getB(), opacity / 100.);
- cr->set_line_width( getOuterLineWidth() );
+ cr->set_source_rgba (color.getR(), color.getG(), color.getB(), OUTERGEOM_OPACITY * rtengine::min(innerLineWidth / 2.f, 1.f));
+ cr->set_line_width (lineWidth);
+ cr->set_line_join(Cairo::LINE_JOIN_BEVEL);
rtengine::Coord tl, br;
@@ -550,10 +556,11 @@ void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuf
color = innerLineColor;
}
- cr->set_source_rgba (color.getR(), color.getG(), color.getB(), opacity / 100.);
+ cr->set_source_rgba (color.getR(), color.getG(), color.getB(), INNERGEOM_OPACITY);
}
- cr->set_line_width( innerLineWidth );
+ cr->set_line_width(innerLineWidth);
+ cr->set_line_join(Cairo::LINE_JOIN_BEVEL);
rtengine::Coord tl, br;
@@ -573,7 +580,11 @@ void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuf
br = bottomRight + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen;
}
- if (filled && state != INSENSITIVE) {
+ if (flags & F_DASHED) {
+ cr->set_dash(dash, 0.);
+ }
+
+ if (filled) {
cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y);
if (innerLineWidth > 0.f) {
@@ -584,20 +595,11 @@ void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuf
}
} else if (innerLineWidth > 0.f) {
cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y);
+ cr->stroke();
+ }
- if (state == INSENSITIVE) {
- std::valarray ds(1);
- ds[0] = 4;
- cr->set_source_rgba(1.0, 1.0, 1.0, 0.618);
- cr->stroke_preserve();
- cr->set_source_rgba(0.0, 0.0, 0.0, 0.618);
- cr->set_dash(ds, 0);
- cr->stroke();
- ds.resize(0);
- cr->set_dash(ds, 0);
- } else {
- cr->stroke();
- }
+ if (flags & F_DASHED) {
+ cr->unset_dash();
}
}
}
@@ -606,6 +608,7 @@ void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, unsigned shor
{
if (flags & F_HOVERABLE) {
cr->set_line_width( getMouseOverLineWidth() );
+ cr->set_line_join(Cairo::LINE_JOIN_ROUND);
rtengine::Coord tl, br;
diff --git a/rtgui/editwidgets.h b/rtgui/editwidgets.h
index c86949cb4..fd539c355 100644
--- a/rtgui/editwidgets.h
+++ b/rtgui/editwidgets.h
@@ -24,10 +24,11 @@
#include
#include "editcoordsys.h"
+#include "rtsurface.h"
#include "../rtengine/coord.h"
+#include "../rtengine/rt_math.h"
class ObjectMOBuffer;
-class RTSurface;
/** @file
*
@@ -210,6 +211,8 @@ public:
F_VISIBLE = 1 << 0, /// true if the geometry have to be drawn on the visible layer
F_HOVERABLE = 1 << 1, /// true if the geometry have to be drawn on the "mouse over" layer
F_AUTO_COLOR = 1 << 2, /// true if the color depend on the state value, not the color field above
+ F_DASHED = 1 << 3, /// true if the geometry have to be drawn as a dash line
+ // (TODO: add a F_LARGE_DASH to have two different dash size ?)
};
/// @brief Key point of the image's rectangle that is used to locate the icon copy to the target point:
@@ -226,6 +229,7 @@ public:
};
protected:
+ static const std::vector dash;
RGBColor innerLineColor;
RGBColor outerLineColor;
short flags;
@@ -252,6 +256,8 @@ public:
void setVisible (bool visible);
bool isHoverable ();
void setHoverable (bool visible);
+ bool isDashed ();
+ void setDashed (bool dashed);
// setActive will enable/disable the visible and hoverable flags in one shot!
@@ -449,7 +455,7 @@ inline void Geometry::setOuterLineColor (char r, char g, char b) {
}
inline double Geometry::getMouseOverLineWidth () {
- return getOuterLineWidth () + 2.;
+ return rtengine::max(double(innerLineWidth), 1.) + 2.;
}
inline void Geometry::setAutoColor (bool aColor) {
@@ -484,6 +490,18 @@ inline void Geometry::setHoverable (bool hoverable) {
}
}
+inline bool Geometry::isDashed () {
+ return flags & F_DASHED;
+}
+
+inline void Geometry::setDashed (bool dashed) {
+ if (dashed) {
+ flags |= F_DASHED;
+ } else {
+ flags &= ~F_DASHED;
+ }
+}
+
inline void Geometry::setActive (bool active) {
if (active) {
flags |= (F_VISIBLE | F_HOVERABLE);
diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc
index 3ae3e47fa..d0e53d730 100644
--- a/rtgui/editwindow.cc
+++ b/rtgui/editwindow.cc
@@ -31,11 +31,17 @@ extern Glib::ustring argv0;
// Check if the system has more than one display and option is set
bool EditWindow::isMultiDisplayEnabled()
{
- return options.multiDisplayMode > 0 && Gdk::Screen::get_default()->get_n_monitors() > 1;
+ const auto screen = Gdk::Screen::get_default();
+
+ if (screen) {
+ return options.multiDisplayMode > 0 && screen->get_display()->get_n_monitors() > 1;
+ } else {
+ return false; // There is no default screen
+ }
}
-// Should only be created once, auto-creates window on correct display
-EditWindow* EditWindow::getInstance(RTWindow* p, bool restore)
+// Should only be created once
+EditWindow* EditWindow::getInstance(RTWindow* p)
{
struct EditWindowInstance
{
@@ -47,13 +53,15 @@ EditWindow* EditWindow::getInstance(RTWindow* p, bool restore)
};
static EditWindowInstance instance_(p);
- if(restore) {
- instance_.editWnd.restoreWindow();
- }
return &instance_.editWnd;
}
-EditWindow::EditWindow (RTWindow* p) : resolution(RTScalable::baseDPI), parent(p) , isFullscreen(false), isClosed(true)
+EditWindow::EditWindow (RTWindow* p)
+ : resolution(RTScalable::baseDPI)
+ , parent(p)
+ , isFullscreen(false)
+ , isClosed(true)
+ , isMinimized(false)
{
updateResolution();
@@ -70,6 +78,8 @@ EditWindow::EditWindow (RTWindow* p) : resolution(RTScalable::baseDPI), parent(p
mainNB->signal_switch_page().connect_notify(sigc::mem_fun(*this, &EditWindow::on_mainNB_switch_page));
signal_key_press_event().connect(sigc::mem_fun(*this, &EditWindow::keyPressed));
+ signal_window_state_event().connect(sigc::mem_fun(*this, &EditWindow::on_window_state_event));
+ onConfEventConn = signal_configure_event().connect(sigc::mem_fun(*this, &EditWindow::on_configure_event));
Gtk::Box* mainBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
mainBox->pack_start(*mainNB);
@@ -78,43 +88,74 @@ EditWindow::EditWindow (RTWindow* p) : resolution(RTScalable::baseDPI), parent(p
}
-void EditWindow::restoreWindow() {
+void EditWindow::restoreWindow()
+{
+ if (isClosed) {
+ onConfEventConn.block(true); // Avoid getting size and position while window is being moved, maximized, ...
- if(isClosed) {
- int meowMonitor = 0;
- if(isMultiDisplayEnabled()) {
- if(options.meowMonitor >= 0) { // use display from last session if available
- meowMonitor = std::min(options.meowMonitor, Gdk::Screen::get_default()->get_n_monitors() - 1);
- } else { // Determine the other display
- const Glib::RefPtr< Gdk::Window >& wnd = parent->get_window();
- meowMonitor = parent->get_screen()->get_monitor_at_window(wnd) == 0 ? 1 : 0;
+ int meowMonitor = 0; // By default, set to main monitor
+ const auto display = get_screen()->get_display();
+
+ if (isMultiDisplayEnabled()) {
+ if (options.meowMonitor >= 0) { // Use display from last session if available
+ meowMonitor = std::max(0, std::min(options.meowMonitor, display->get_n_monitors() - 1));
+ } else { // Determine the main RT window display
+ const Glib::RefPtr &wnd = parent->get_window();
+
+ // Retrieve window monitor ID
+ const int monitor_nb = display->get_n_monitors();
+
+ for (int id = 0; id < monitor_nb; id++) {
+ if (display->get_monitor_at_window(wnd) == display->get_monitor(id)) {
+ meowMonitor = id;
+ break;
+ }
+ }
}
}
Gdk::Rectangle lMonitorRect;
- get_screen()->get_monitor_geometry(meowMonitor, lMonitorRect);
- if(options.meowMaximized) {
+ display->get_monitor(meowMonitor)->get_geometry(lMonitorRect);
+
+#ifdef __APPLE__
+ // Get macOS menu bar height
+ Gdk::Rectangle lWorkAreaRect;
+ display->get_monitor(std::min(meowMonitor, display->get_n_monitors() - 1))->get_workarea(lWorkAreaRect);
+ const int macMenuBarHeight = lWorkAreaRect.get_y();
+
+ // Place RT window to saved one in options file
+ if (options.meowX <= lMonitorRect.get_x() + lMonitorRect.get_width()
+ && options.meowX >= 0
+ && options.meowY <= lMonitorRect.get_y() + lMonitorRect.get_height() - macMenuBarHeight
+ && options.meowY >= 0) {
+ move(options.meowX, options.meowY + macMenuBarHeight);
+ } else {
+ move(lMonitorRect.get_x(), lMonitorRect.get_y() + macMenuBarHeight);
+ }
+#else
+ // Place RT window to saved one in options file
+ if (options.meowX <= lMonitorRect.get_x() + lMonitorRect.get_width()
+ && options.meowX >= 0
+ && options.meowY <= lMonitorRect.get_y() + lMonitorRect.get_height()
+ && options.meowY >= 0) {
+ move(options.meowX, options.meowY);
+ } else {
move(lMonitorRect.get_x(), lMonitorRect.get_y());
+ }
+#endif
+
+ // Maximize RT window according to options file
+ if (options.meowMaximized) {
maximize();
} else {
+ unmaximize();
resize(options.meowWidth, options.meowHeight);
- if(options.meowX <= lMonitorRect.get_x() + lMonitorRect.get_width() && options.meowY <= lMonitorRect.get_y() + lMonitorRect.get_height()) {
- move(options.meowX, options.meowY);
- } else {
- move(lMonitorRect.get_x(), lMonitorRect.get_y());
- }
- }
- show_all();
-
- isFullscreen = options.meowFullScreen;
-
- if(isFullscreen) {
- fullscreen();
}
isClosed = false;
- }
+ onConfEventConn.block(false);
+ }
}
void EditWindow::on_realize ()
@@ -174,27 +215,23 @@ bool EditWindow::on_configure_event(GdkEventConfigure* event)
setAppIcon();
}
- if (get_realized() && is_visible()) {
- if(!is_maximized()) {
- get_position(options.meowX, options.meowY);
- get_size(options.meowWidth, options.meowHeight);
- }
- options.meowMaximized = is_maximized();
+ if (!options.meowMaximized && !isFullscreen && !isMinimized) {
+ get_position(options.meowX, options.meowY);
+ get_size(options.meowWidth, options.meowHeight);
}
return Gtk::Widget::on_configure_event(event);
}
-/* HOMBRE: Disabling this since it's maximized when opened anyway.
- * Someday, the EditorWindow might save its own position and state, so it'll have to be uncommented
bool EditWindow::on_window_state_event(GdkEventWindowState* event)
{
- if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
- options.windowMaximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
- }
+ // Retrieve RT window states
+ options.meowMaximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
+ isMinimized = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED;
+ isFullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
return Gtk::Widget::on_window_state_event(event);
-}*/
+}
void EditWindow::on_mainNB_switch_page(Gtk::Widget* widget, guint page_num)
{
@@ -241,7 +278,8 @@ void EditWindow::addEditorPanel (EditorPanel* ep, const std::string &name)
epanels[ name ] = ep;
filesEdited.insert ( name );
parent->fpanel->refreshEditedState (filesEdited);
- ep->setAspect();
+
+ show_all();
}
void EditWindow::remEditorPanel (EditorPanel* ep)
@@ -281,10 +319,20 @@ bool EditWindow::selectEditorPanel(const std::string &name)
void EditWindow::toFront ()
{
- // when using the secondary window on the same monitor as the primary window we need to present the secondary window.
+ // When using the secondary window on the same monitor as the primary window we need to present the secondary window.
// If we don't, it will stay in background when opening 2nd, 3rd... editor, which is annoying
// It will also deiconify the window
- present();
+ // To avoid unexpected behavior while window is being updated, present() function is called after at idle
+ idle_register.add(
+ [this]()-> bool
+ {
+ onConfEventConn.block(true); // Avoid getting size and position while window is being moved, maximized, ...
+ present();
+ onConfEventConn.block(false);
+
+ return false;
+ }
+ );
}
bool EditWindow::keyPressed (GdkEventKey* event)
@@ -308,27 +356,63 @@ bool EditWindow::keyPressed (GdkEventKey* event)
return false;
}
-
}
-void EditWindow::toggleFullscreen ()
+void EditWindow::toggleFullscreen()
{
+ onConfEventConn.block(true); // Avoid getting size and position while window is getting fullscreen
+
isFullscreen ? unfullscreen() : fullscreen();
- options.meowFullScreen = isFullscreen = !isFullscreen;
+
+ onConfEventConn.block(false);
}
-void EditWindow::writeOptions() {
+void EditWindow::get_position(int& x, int& y) const
+{
+ // Call native function
+ Gtk::Window::get_position(x, y);
- if(is_visible()) {
- if(isMultiDisplayEnabled()) {
- options.meowMonitor = get_screen()->get_monitor_at_window(get_window());
+ // Retrieve display (concatenation of all monitors) size
+ int width = 0, height = 0;
+ const auto display = get_screen()->get_display();
+ const int nbMonitors = display->get_n_monitors();
+
+ for (int i = 0; i < nbMonitors; i++) {
+ Gdk::Rectangle lMonitorRect;
+ display->get_monitor(i)->get_geometry(lMonitorRect);
+ width = std::max(width, lMonitorRect.get_x() + lMonitorRect.get_width());
+ height = std::max(height, lMonitorRect.get_y() + lMonitorRect.get_height());
+ }
+
+ // Saturate position at monitor limits to avoid unexpected behavior (fixes #6233)
+ x = std::min(width, std::max(0, x));
+ y = std::min(height, std::max(0, y));
+}
+
+void EditWindow::writeOptions()
+{
+ if (is_visible()) {
+ if (isMultiDisplayEnabled()) {
+ // Retrieve window monitor ID
+ options.meowMonitor = 0;
+ const auto display = get_screen()->get_display();
+ const int monitor_nb = display->get_n_monitors();
+
+ for (int id = 0; id < monitor_nb; id++) {
+ if (display->get_monitor_at_window(get_window()) == display->get_monitor(id)) {
+ options.windowMonitor = id;
+ break;
+ }
+ }
}
- options.meowMaximized = is_maximized();
- get_position(options.meowX, options.meowY);
- get_size(options.meowWidth,options.meowHeight);
+ if (!options.meowMaximized && !isFullscreen && !isMinimized) {
+ get_position(options.meowX, options.meowY);
+ get_size(options.meowWidth, options.meowHeight);
+ }
}
}
+
bool EditWindow::on_delete_event(GdkEventAny* event)
{
diff --git a/rtgui/editwindow.h b/rtgui/editwindow.h
index f4ada571d..b8eeaee82 100644
--- a/rtgui/editwindow.h
+++ b/rtgui/editwindow.h
@@ -21,6 +21,7 @@
#include
#include "rtimage.h"
+#include "guiutils.h"
class EditorPanel;
class RTWindow;
@@ -40,17 +41,20 @@ private:
bool isFullscreen;
bool isClosed;
+ bool isMinimized;
+ sigc::connection onConfEventConn;
void toggleFullscreen ();
- void restoreWindow();
bool updateResolution();
void setAppIcon();
+ IdleRegister idle_register;
+
public:
// Check if the system has more than one display and option is set
static bool isMultiDisplayEnabled();
- // Should only be created once, auto-creates window on correct display
- static EditWindow* getInstance(RTWindow* p, bool restore = true);
+ // Should only be created once
+ static EditWindow* getInstance(RTWindow* p);
explicit EditWindow (RTWindow* p);
@@ -65,8 +69,10 @@ public:
bool keyPressed (GdkEventKey* event);
bool on_configure_event(GdkEventConfigure* event) override;
bool on_delete_event(GdkEventAny* event) override;
- //bool on_window_state_event(GdkEventWindowState* event);
+ bool on_window_state_event(GdkEventWindowState* event) override;
void on_mainNB_switch_page(Gtk::Widget* page, guint page_num);
void set_title_decorated(Glib::ustring fname);
void on_realize () override;
+ void get_position(int& x, int& y) const;
+ void restoreWindow();
};
diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc
index 939ead608..148eee944 100644
--- a/rtgui/extprog.cc
+++ b/rtgui/extprog.cc
@@ -276,8 +276,8 @@ bool ExtProgStore::openInGimp (const Glib::ustring& fileName)
for (auto ver = 12; ver >= 0; --ver) {
executable = Glib::build_filename (options.gimpDir, "bin", Glib::ustring::compose (Glib::ustring("gimp-2.%1.exe"), ver));
- auto lsuccess = ShellExecute( NULL, "open", executable.c_str(), fileName.c_str(), NULL, SW_SHOWNORMAL );
-
+ Glib::ustring escapedFileName = Glib::ustring::compose ("\"%1\"", fileName);
+ auto lsuccess = ShellExecute( NULL, "open", executable.c_str(), escapedFileName.c_str(), NULL, SW_SHOWNORMAL );
if (reinterpret_cast(lsuccess) > 32) {
return true;
}
diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc
index 0d2451b59..b96a5ecd1 100644
--- a/rtgui/filebrowser.cc
+++ b/rtgui/filebrowser.cc
@@ -411,7 +411,7 @@ FileBrowser::FileBrowser () :
untrash->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_Delete, Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
open->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_Return, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
if (options.inspectorWindow)
- inspect->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_F, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
+ inspect->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_f, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
develop->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_B, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
developfast->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_B, Gdk::CONTROL_MASK | Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
copyprof->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_C, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
@@ -1374,6 +1374,19 @@ int FileBrowser::getThumbnailHeight ()
}
}
+void FileBrowser::enableTabMode(bool enable)
+{
+ ThumbBrowserBase::enableTabMode(enable);
+ if (options.inspectorWindow) {
+ if (enable) {
+ inspect->remove_accelerator(pmenu->get_accel_group(), GDK_KEY_f, (Gdk::ModifierType)0);
+ }
+ else {
+ inspect->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_f, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
+ }
+ }
+}
+
void FileBrowser::applyMenuItemActivated (ProfileStoreLabel *label)
{
MYREADERLOCK(l, entryRW);
@@ -1431,7 +1444,7 @@ void FileBrowser::applyPartialMenuItemActivated (ProfileStoreLabel *label)
rtengine::procparams::PartialProfile dstProfile(true);
*dstProfile.pparams = (static_cast(selected[i]))->thumbnail->getProcParams ();
dstProfile.set(true);
- dstProfile.pedited->locallab.spots.resize(dstProfile.pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true));
+ dstProfile.pedited->locallab.spots.resize(dstProfile.pparams->locallab.spots.size(), LocallabParamsEdited::LocallabSpotEdited(true));
partialPasteDlg.applyPaste (dstProfile.pparams, dstProfile.pedited, srcProfiles->pparams, srcProfiles->pedited);
(static_cast(selected[i]))->thumbnail->setProcParams (*dstProfile.pparams, dstProfile.pedited, FILEBROWSER);
dstProfile.deleteInstance();
@@ -2100,5 +2113,5 @@ void FileBrowser::openRequested( std::vector mselected)
void FileBrowser::inspectRequested(std::vector mselected)
{
- getInspector()->showWindow(false, false);
+ getInspector()->showWindow(true);
}
diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h
index 03a8636e5..4602ba9bb 100644
--- a/rtgui/filebrowser.h
+++ b/rtgui/filebrowser.h
@@ -182,6 +182,8 @@ public:
void saveThumbnailHeight (int height) override;
int getThumbnailHeight () override;
+
+ void enableTabMode(bool enable);
bool isInTabMode() override
{
return tbl ? tbl->isInTabMode() : false;
diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc
index 432296f38..5e8c730aa 100644
--- a/rtgui/filebrowserentry.cc
+++ b/rtgui/filebrowserentry.cc
@@ -294,7 +294,7 @@ bool FileBrowserEntry::motionNotify (int x, int y)
Inspector* inspector = parent->getInspector();
- if (inspector && inspector->isActive() && !parent->isInTabMode()) {
+ if (inspector && inspector->isActive() && (!parent->isInTabMode() || options.inspectorWindow)) {
const rtengine::Coord2D coord(getPosInImgSpace(x, y));
if (coord.x != -1.) {
diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc
index dbea4ade9..58c1bbc1b 100644
--- a/rtgui/filecatalog.cc
+++ b/rtgui/filecatalog.cc
@@ -1215,9 +1215,13 @@ void FileCatalog::developRequested(const std::vector& tbe, bo
if (params.resize.enabled) {
params.resize.width = rtengine::min(params.resize.width, options.fastexport_resize_width);
params.resize.height = rtengine::min(params.resize.height, options.fastexport_resize_height);
+ params.resize.longedge = rtengine::min(params.resize.longedge, options.fastexport_resize_longedge);
+ params.resize.shortedge = rtengine::min(params.resize.shortedge, options.fastexport_resize_shortedge);
} else {
params.resize.width = options.fastexport_resize_width;
params.resize.height = options.fastexport_resize_height;
+ params.resize.longedge = options.fastexport_resize_longedge;
+ params.resize.shortedge = options.fastexport_resize_shortedge;
}
params.resize.enabled = options.fastexport_resize_enabled;
@@ -2515,8 +2519,10 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event)
if (!ctrl && !alt) {
switch (event->keyval) {
case GDK_KEY_f:
+ fileBrowser->getInspector()->showWindow(false, true);
+ return true;
case GDK_KEY_F:
- fileBrowser->getInspector()->showWindow(!shift);
+ fileBrowser->getInspector()->showWindow(false, false);
return true;
}
}
@@ -2524,6 +2530,23 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event)
return fileBrowser->keyPressed(event);
}
+bool FileCatalog::handleShortcutKeyRelease(GdkEventKey* event)
+{
+ bool ctrl = event->state & GDK_CONTROL_MASK;
+ bool alt = event->state & GDK_MOD1_MASK;
+
+ if (!ctrl && !alt) {
+ switch (event->keyval) {
+ case GDK_KEY_f:
+ case GDK_KEY_F:
+ fileBrowser->getInspector()->hideWindow();
+ return true;
+ }
+ }
+
+ return false;
+}
+
void FileCatalog::showToolBar()
{
if (hbToolBar1STB) {
diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h
index c7c4f3155..23d56af73 100644
--- a/rtgui/filecatalog.h
+++ b/rtgui/filecatalog.h
@@ -276,6 +276,7 @@ public:
void openNextPreviousEditorImage (Glib::ustring fname, bool clearFilters, eRTNav nextPrevious);
bool handleShortcutKey (GdkEventKey* event);
+ bool handleShortcutKeyRelease(GdkEventKey *event);
bool CheckSidePanelsVisibility();
void toggleSidePanels();
diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc
index a09a82597..974482f41 100644
--- a/rtgui/filepanel.cc
+++ b/rtgui/filepanel.cc
@@ -412,6 +412,15 @@ bool FilePanel::handleShortcutKey (GdkEventKey* event)
return false;
}
+bool FilePanel::handleShortcutKeyRelease(GdkEventKey *event)
+{
+ if(fileCatalog->handleShortcutKeyRelease(event)) {
+ return true;
+ }
+
+ return false;
+}
+
void FilePanel::loadingThumbs(Glib::ustring str, double rate)
{
GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected
diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h
index 65e1ea548..ba5dfa7c9 100644
--- a/rtgui/filepanel.h
+++ b/rtgui/filepanel.h
@@ -81,6 +81,7 @@ public:
bool imageLoaded( Thumbnail* thm, ProgressConnector * );
bool handleShortcutKey (GdkEventKey* event);
+ bool handleShortcutKeyRelease(GdkEventKey *event);
void updateTPVScrollbar (bool hide);
private:
diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc
index 5fc15b5ba..068575a96 100644
--- a/rtgui/filmnegative.cc
+++ b/rtgui/filmnegative.cc
@@ -194,6 +194,7 @@ FilmNegative::FilmNegative() :
evFilmNegativeColorSpace(ProcEventMapper::getInstance()->newEvent(ALLNORAW, "HISTORY_MSG_FILMNEGATIVE_COLORSPACE")),
refInputValues({0.f, 0.f, 0.f}),
paramsUpgraded(false),
+ refLuminance({{0.f, 0.f, 0.f}, 0.f}),
fnp(nullptr),
colorSpace(Gtk::manage(new MyComboBoxText())),
greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 0.01, 1.5)), // master exponent (green channel)
@@ -343,6 +344,9 @@ void FilmNegative::read(const rtengine::procparams::ProcParams* pp, const Params
setEnabled(pp->filmNegative.enabled);
+ // Reset luminance reference each time params are read
+ refLuminance.lum = 0.f;
+
colorSpace->set_active(CLAMP((int)pp->filmNegative.colorSpace, 0, 1));
redRatio->setValue(pp->filmNegative.redRatio);
greenExp->setValue(pp->filmNegative.greenExp);
@@ -471,6 +475,9 @@ void FilmNegative::adjusterChanged(Adjuster* a, double newval)
);
} else if (a == outputLevel || a == greenBalance || a == blueBalance) {
+ // Reset luminance reference when output level/color sliders are changed
+ refLuminance.lum = 0.f;
+
listener->panelChanged(
evFilmNegativeBalance,
Glib::ustring::compose(
@@ -540,7 +547,7 @@ void FilmNegative::setEditProvider(EditDataProvider* provider)
EditSubscriber::setEditProvider(provider);
}
-CursorShape FilmNegative::getCursor(int objectID) const
+CursorShape FilmNegative::getCursor(int objectID, int xPos, int yPos) const
{
return CSSpotWB;
}
@@ -606,12 +613,44 @@ bool FilmNegative::button1Pressed(int modifierKey)
} else if (refSpotButton->get_active()) {
+ disableListener();
+
+ // If the luminance reference is not set, copy the current reference input
+ // values, and the corresponding output luminance
+ if(refLuminance.lum <= 0.f) {
+ RGB out;
+ readOutputSliders(out);
+ refLuminance.input = refInputValues;
+ refLuminance.lum = rtengine::Color::rgbLuminance(out.r, out.g, out.b);
+ }
+
RGB refOut;
fnp->getFilmNegativeSpot(provider->posImage, 32, refInputValues, refOut);
- disableListener();
+ // Output luminance of the sampled spot
+ float spotLum = rtengine::Color::rgbLuminance(refOut.r, refOut.g, refOut.b);
+
+ float rexp = -(greenExp->getValue() * redRatio->getValue());
+ float gexp = -greenExp->getValue();
+ float bexp = -(greenExp->getValue() * blueRatio->getValue());
+
+ RGB mult = {
+ spotLum / pow_F(rtengine::max(refInputValues.r, 1.f), rexp),
+ spotLum / pow_F(rtengine::max(refInputValues.g, 1.f), gexp),
+ spotLum / pow_F(rtengine::max(refInputValues.b, 1.f), bexp)
+ };
+
+ // Calculate the new luminance of the initial luminance reference spot, by
+ // applying current multipliers
+ float newRefLum = rtengine::Color::rgbLuminance(
+ mult.r * pow_F(rtengine::max(refLuminance.input.r, 1.f), rexp),
+ mult.g * pow_F(rtengine::max(refLuminance.input.g, 1.f), gexp),
+ mult.b * pow_F(rtengine::max(refLuminance.input.b, 1.f), bexp));
+
+ // Choose a suitable gray value for the sampled spot, so that luminance
+ // of the initial reference spot is preserved.
+ float gray = spotLum * (refLuminance.lum / newRefLum);
- float gray = rtengine::Color::rgbLuminance(refOut.r, refOut.g, refOut.b);
writeOutputSliders({gray, gray, gray});
refInputLabel->set_text(
diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h
index e27a38e09..21a7dce5c 100644
--- a/rtgui/filmnegative.h
+++ b/rtgui/filmnegative.h
@@ -71,7 +71,7 @@ public:
void setEditProvider(EditDataProvider* provider) override;
// EditSubscriber interface
- CursorShape getCursor(int objectID) const override;
+ CursorShape getCursor(int objectID, int xPos, int yPos) const override;
bool mouseOver(int modifierKey) override;
bool button1Pressed(int modifierKey) override;
bool button1Released() override;
@@ -99,6 +99,17 @@ private:
RGB refInputValues;
bool paramsUpgraded;
+ /**
+ * Luminance reference: these input RGB values must produce this output luminance.
+ * This allows keeping constant luminance when picking several white balance spot
+ * samples in sequence; values are set on the initial white balance spot sampling,
+ * and reset every time params are read, or the output sliders are changed.
+ */
+ struct {
+ RGB input;
+ float lum;
+ } refLuminance;
+
FilmNegProvider* fnp;
MyComboBoxText* const colorSpace;
diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc
index b0c6000be..af6503b45 100644
--- a/rtgui/gradient.cc
+++ b/rtgui/gradient.cc
@@ -12,6 +12,14 @@
using namespace rtengine;
using namespace rtengine::procparams;
+enum GeometryIndex {
+ H_LINE,
+ V_LINE,
+ FEATHER_LINE_1,
+ FEATHER_LINE_2,
+ CENTER_CIRCLE,
+};
+
Gradient::Gradient () : FoldableToolPanel(this, "gradient", M("TP_GRADIENT_LABEL"), false, true), EditSubscriber(ET_OBJECTS), lastObject(-1), draggedPointOldAngle(-1000.)
{
@@ -191,24 +199,24 @@ void Gradient::updateGeometry(const int centerX, const int centerY, const double
};
// update horizontal line
- updateLine (visibleGeometry.at(0), 1500., 0., 180.);
- updateLine (mouseOverGeometry.at(0), 1500., 0., 180.);
+ updateLine (visibleGeometry.at(H_LINE), 1500., 0., 180.);
+ updateLine (mouseOverGeometry.at(H_LINE), 1500., 0., 180.);
// update vertical line
- updateLine (visibleGeometry.at(1), 700., 90., 270.);
- updateLine (mouseOverGeometry.at(1), 700., 90., 270.);
+ updateLine (visibleGeometry.at(V_LINE), 700., 90., 270.);
+ updateLine (mouseOverGeometry.at(V_LINE), 700., 90., 270.);
// update upper feather line
- updateLineWithDecay (visibleGeometry.at(2), 350., 270.);
- updateLineWithDecay (mouseOverGeometry.at(2), 350., 270.);
+ updateLineWithDecay (visibleGeometry.at(FEATHER_LINE_1), 350., 270.);
+ updateLineWithDecay (mouseOverGeometry.at(FEATHER_LINE_1), 350., 270.);
// update lower feather line
- updateLineWithDecay (visibleGeometry.at(3), 350., 90.);
- updateLineWithDecay (mouseOverGeometry.at(3), 350., 90.);
+ updateLineWithDecay (visibleGeometry.at(FEATHER_LINE_2), 350., 90.);
+ updateLineWithDecay (mouseOverGeometry.at(FEATHER_LINE_2), 350., 90.);
// update circle's position
- updateCircle (visibleGeometry.at(4));
- updateCircle (mouseOverGeometry.at(4));
+ updateCircle (visibleGeometry.at(CENTER_CIRCLE));
+ updateCircle (mouseOverGeometry.at(CENTER_CIRCLE));
}
void Gradient::write (ProcParams* pp, ParamsEdited* pedited)
@@ -325,19 +333,20 @@ void Gradient::editToggled ()
if (edit->get_active()) {
subscribe();
} else {
+ releaseEdit();
unsubscribe();
}
}
-CursorShape Gradient::getCursor(int objectID) const
+CursorShape Gradient::getCursor(int objectID, int xPos, int yPos) const
{
switch (objectID) {
- case (0):
- case (1):
+ case (H_LINE):
+ case (V_LINE):
return CSMoveRotate;
- case (2):
- case (3): {
+ case (FEATHER_LINE_1):
+ case (FEATHER_LINE_2): {
int angle = degree->getIntValue();
if (angle < -135 || (angle >= -45 && angle <= 45) || angle > 135) {
@@ -347,7 +356,7 @@ CursorShape Gradient::getCursor(int objectID) const
return CSMove1DH;
}
- case (4):
+ case (CENTER_CIRCLE):
return CSMove2D;
default:
@@ -361,18 +370,18 @@ bool Gradient::mouseOver(int modifierKey)
if (editProvider && editProvider->getObject() != lastObject) {
if (lastObject > -1) {
- if (lastObject == 2 || lastObject == 3) {
- EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL;
- EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL;
+ if (lastObject == FEATHER_LINE_1 || lastObject == FEATHER_LINE_2) {
+ EditSubscriber::visibleGeometry.at(FEATHER_LINE_1)->state = Geometry::NORMAL;
+ EditSubscriber::visibleGeometry.at(FEATHER_LINE_2)->state = Geometry::NORMAL;
} else {
EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL;
}
}
if (editProvider->getObject() > -1) {
- if (editProvider->getObject() == 2 || editProvider->getObject() == 3) {
- EditSubscriber::visibleGeometry.at(2)->state = Geometry::PRELIGHT;
- EditSubscriber::visibleGeometry.at(3)->state = Geometry::PRELIGHT;
+ if (editProvider->getObject() == FEATHER_LINE_1 || editProvider->getObject() == FEATHER_LINE_2) {
+ EditSubscriber::visibleGeometry.at(FEATHER_LINE_1)->state = Geometry::PRELIGHT;
+ EditSubscriber::visibleGeometry.at(FEATHER_LINE_2)->state = Geometry::PRELIGHT;
} else {
EditSubscriber::visibleGeometry.at(editProvider->getObject())->state = Geometry::PRELIGHT;
}
@@ -414,7 +423,7 @@ bool Gradient::button1Pressed(int modifierKey)
//printf("\ndraggedPointOldAngle=%.3f\n\n", draggedPointOldAngle);
draggedPointAdjusterAngle = degree->getValue();
- if (lastObject == 2 || lastObject == 3) {
+ if (lastObject == FEATHER_LINE_1 || lastObject == FEATHER_LINE_2) {
// Dragging a line to change the angle
PolarCoord draggedPoint;
rtengine::Coord currPos;
@@ -430,7 +439,7 @@ bool Gradient::button1Pressed(int modifierKey)
// compute the projected value of the dragged point
draggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*rtengine::RT_PI);
- if (lastObject == 3) {
+ if (lastObject == FEATHER_LINE_2) {
draggedFeatherOffset = -draggedFeatherOffset;
}
@@ -441,9 +450,9 @@ bool Gradient::button1Pressed(int modifierKey)
return false;
} else { // should theoretically always be true
// this will let this class ignore further drag events
- if (lastObject == 2 || lastObject == 3) {
- EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL;
- EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL;
+ if (lastObject == FEATHER_LINE_1 || lastObject == FEATHER_LINE_2) {
+ EditSubscriber::visibleGeometry.at(FEATHER_LINE_1)->state = Geometry::NORMAL;
+ EditSubscriber::visibleGeometry.at(FEATHER_LINE_2)->state = Geometry::NORMAL;
} else {
EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL;
}
@@ -471,7 +480,7 @@ bool Gradient::drag1(int modifierKey)
double halfSizeW = imW / 2.;
double halfSizeH = imH / 2.;
- if (lastObject == 0 || lastObject == 1) {
+ if (lastObject == H_LINE || lastObject == V_LINE) {
// Dragging a line to change the angle
PolarCoord draggedPoint;
@@ -515,7 +524,7 @@ bool Gradient::drag1(int modifierKey)
return true;
}
- } else if (lastObject == 2 || lastObject == 3) {
+ } else if (lastObject == FEATHER_LINE_1 || lastObject == FEATHER_LINE_2) {
// Dragging the upper or lower feather bar
PolarCoord draggedPoint;
rtengine::Coord currPos;
@@ -532,11 +541,11 @@ bool Gradient::drag1(int modifierKey)
draggedPoint = currPos - centerPos;
double currDraggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*rtengine::RT_PI);
- if (lastObject == 2)
+ if (lastObject == FEATHER_LINE_1)
// Dragging the upper feather bar
{
currDraggedFeatherOffset -= draggedFeatherOffset;
- } else if (lastObject == 3)
+ } else if (lastObject == FEATHER_LINE_2)
// Dragging the lower feather bar
{
currDraggedFeatherOffset = -currDraggedFeatherOffset + draggedFeatherOffset;
@@ -554,7 +563,7 @@ bool Gradient::drag1(int modifierKey)
return true;
}
- } else if (lastObject == 4) {
+ } else if (lastObject == CENTER_CIRCLE) {
// Dragging the circle to change the center
rtengine::Coord currPos;
draggedCenter += provider->deltaPrevImage;
@@ -579,6 +588,19 @@ bool Gradient::drag1(int modifierKey)
return false;
}
+void Gradient::releaseEdit()
+{
+ if (lastObject >= 0) {
+ if (lastObject == FEATHER_LINE_1 || lastObject == FEATHER_LINE_2) {
+ EditSubscriber::visibleGeometry.at(FEATHER_LINE_1)->state = Geometry::NORMAL;
+ EditSubscriber::visibleGeometry.at(FEATHER_LINE_2)->state = Geometry::NORMAL;
+ } else {
+ EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL;
+ }
+ }
+ action = Action::NONE;
+}
+
void Gradient::switchOffEditMode ()
{
if (edit->get_active()) {
diff --git a/rtgui/gradient.h b/rtgui/gradient.h
index 64eabefae..dc0371932 100644
--- a/rtgui/gradient.h
+++ b/rtgui/gradient.h
@@ -35,6 +35,7 @@ protected:
sigc::connection editConn;
void editToggled ();
+ void releaseEdit();
public:
@@ -55,7 +56,7 @@ public:
void setEditProvider (EditDataProvider* provider) override;
// EditSubscriber interface
- CursorShape getCursor(int objectID) const override;
+ CursorShape getCursor(int objectID, int xPos, int yPos) const override;
bool mouseOver(int modifierKey) override;
bool button1Pressed(int modifierKey) override;
bool button1Released() override;
diff --git a/rtgui/history.cc b/rtgui/history.cc
index dfc74af24..4d6940e9b 100644
--- a/rtgui/history.cc
+++ b/rtgui/history.cc
@@ -180,7 +180,7 @@ void History::historySelectionChanged ()
if (row && tpc) {
ProcParams pparams = row[historyColumns.params];
ParamsEdited pe (true);
- pe.locallab.spots.resize(pparams.locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true));
+ pe.locallab.spots.resize(pparams.locallab.spots.size(), LocallabParamsEdited::LocallabSpotEdited(true));
PartialProfile pp (&pparams, &pe);
ParamsEdited paramsEdited = row[historyColumns.paramsEdited];
@@ -215,7 +215,7 @@ void History::bookmarkSelectionChanged ()
if (row && tpc) {
ProcParams pparams = row[bookmarkColumns.params];
ParamsEdited pe (true);
- pe.locallab.spots.resize(pparams.locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true));
+ pe.locallab.spots.resize(pparams.locallab.spots.size(), LocallabParamsEdited::LocallabSpotEdited(true));
PartialProfile pp (&pparams, &pe);
ParamsEdited paramsEdited = row[bookmarkColumns.paramsEdited];
tpc->profileChange (&pp, EvBookmarkSelected, row[bookmarkColumns.text], ¶msEdited);
diff --git a/rtgui/iccprofilecreator.cc b/rtgui/iccprofilecreator.cc
index 3f1ed4089..b7e6bc20e 100644
--- a/rtgui/iccprofilecreator.cc
+++ b/rtgui/iccprofilecreator.cc
@@ -101,17 +101,17 @@ ICCProfileCreator::ICCProfileCreator(RTWindow *rtwindow)
Gtk::Image* gamutl5 = Gtk::manage(new RTImage("rt-logo-small.png"));
*/
- aPrimariesRedX = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_REDX"), 0.6300, 0.7350, 0.0001, 0.6400/*, gamuts0, gamutl0*/));
+ aPrimariesRedX = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_REDX"), 0.4100, 0.9000, 0.0001, 0.6400/*, gamuts0, gamutl0*/));
setExpandAlignProperties(aPrimariesRedX, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
- aPrimariesRedY = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_REDY"), 0.2650, 0.3350, 0.0001, 0.3300/*, gamutl1, gamuts1*/));
+ aPrimariesRedY = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_REDY"), 0.1000, 0.6000, 0.0001, 0.3300/*, gamutl1, gamuts1*/));
setExpandAlignProperties(aPrimariesRedY, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
- aPrimariesGreenX = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_GREX"), 0.0000, 0.3100, 0.0001, 0.3000/*, gamutl2, gamuts2*/));
+ aPrimariesGreenX = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_GREX"), -0.100, 0.4000, 0.0001, 0.3000/*, gamutl2, gamuts2*/));
setExpandAlignProperties(aPrimariesGreenX, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
- aPrimariesGreenY = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_GREY"), 0.5900, 1.0000, 0.0001, 0.6000/*, gamuts3, gamutl3*/));
+ aPrimariesGreenY = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_GREY"), 0.50, 1.0000, 0.0001, 0.6000/*, gamuts3, gamutl3*/));
setExpandAlignProperties(aPrimariesGreenY, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
- aPrimariesBlueX = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_BLUX"), 0.0001, 0.1600, 0.0001, 0.1500/*, gamutl4, gamuts4*/));
+ aPrimariesBlueX = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_BLUX"), -0.1, 0.3000, 0.0001, 0.1500/*, gamutl4, gamuts4*/));
setExpandAlignProperties(aPrimariesBlueX, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
- aPrimariesBlueY = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_BLUY"), -0.0800, 0.0700, 0.0001, 0.060/*, gamutl5, gamuts5*/));
+ aPrimariesBlueY = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_PRIM_BLUY"), -0.100, 0.4000, 0.0001, 0.060/*, gamutl5, gamuts5*/));
setExpandAlignProperties(aPrimariesBlueY, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
primariesGrid->attach(*aPrimariesRedX, 0, 0, 1, 1);
diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc
index e0fd7cd96..c52807497 100644
--- a/rtgui/icmpanel.cc
+++ b/rtgui/icmpanel.cc
@@ -22,6 +22,7 @@
#include "eventmapper.h"
#include "guiutils.h"
+#include "labgrid.h"
#include "options.h"
#include "pathutils.h"
#include "rtimage.h"
@@ -29,6 +30,7 @@
#include "../rtengine/dcp.h"
#include "../rtengine/iccstore.h"
#include "../rtengine/procparams.h"
+#include "../rtengine/utils.h"
using namespace rtengine;
using namespace rtengine::procparams;
@@ -45,15 +47,27 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha
EvICMpgrey = m->newEvent(GAMMA, "HISTORY_MSG_ICMPGREY");
EvICMpblux = m->newEvent(GAMMA, "HISTORY_MSG_ICMPBLUX");
EvICMpbluy = m->newEvent(GAMMA, "HISTORY_MSG_ICMPBLUY");
- EvICMgamm = m->newEvent(AUTOEXP, "HISTORY_MSG_ICM_WORKING_GAMMA");
- EvICMslop = m->newEvent(AUTOEXP, "HISTORY_MSG_ICM_WORKING_SLOPE");
- EvICMtrcinMethod = m->newEvent(AUTOEXP, "HISTORY_MSG_ICM_WORKING_TRC_METHOD");
-
+ EvICMgamm = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_GAMMA");
+ EvICMslop = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_SLOPE");
+ EvICMtrcinMethod = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_TRC_METHOD");
+ EvICMwillMethod = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_ILLUM_METHOD");
+ EvICMwprimMethod = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WORKING_PRIM_METHOD");
+ EvICMredx = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_REDX");
+ EvICMredy = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_REDY");
+ EvICMgrex = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_GREX");
+ EvICMgrey = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_GREY");
+ EvICMblux = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_BLUX");
+ EvICMbluy = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_BLUY");
+ EvaIntent = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_AINTENT");
+ EvICMpreser = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_PRESER");
+ EvICMLabGridciexy = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICL_LABGRIDCIEXY");
+ EvICMfbw = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_FBW");
isBatchMode = lastToneCurve = lastApplyLookTable = lastApplyBaselineExposureOffset = lastApplyHueSatMap = false;
ipDialog = Gtk::manage(new MyFileChooserButton(M("TP_ICM_INPUTDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN));
ipDialog->set_tooltip_text(M("TP_ICM_INPUTCUSTOM_TOOLTIP"));
bindCurrentFolder(*ipDialog, options.lastIccDir);
+ labgridcie = Gtk::manage(new LabGrid(EvICMLabGridciexy, M("TP_ICM_LABGRID_CIEXY"), true, true));
// ------------------------------- Input profile
@@ -184,44 +198,195 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha
wProfNames->set_active(0);
- // wFrame->add(*wVBox);
+ wFrame->add(*wProfVBox);
//-----------------gamma TRC working
+ Gtk::Frame *trcFrame = Gtk::manage(new Gtk::Frame(M("TP_ICM_TRCFRAME")));
+ trcFrame->set_label_align(0.025, 0.5);
+ Gtk::Box *trcProfVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+ trcFrame->set_tooltip_text(M("TP_ICM_TRCFRAME_TOOLTIP"));
- wTRCHBox = Gtk::manage(new Gtk::Box());
+ wTRCBox = Gtk::manage(new Gtk::Box());
- Gtk::Label* wtrclab = Gtk::manage(new Gtk::Label(M("TP_ICM_WORKING_TRC")));
-
- 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);
+ wTRCBox->pack_start(*wTRC, Gtk::PACK_EXPAND_WIDGET);
+ trcProfVBox->pack_start(*wTRCBox, Gtk::PACK_EXPAND_WIDGET);
wTRC->append(M("TP_ICM_WORKING_TRC_NONE"));
wTRC->append(M("TP_ICM_WORKING_TRC_CUSTOM"));
+ wTRC->append(M("TP_ICM_WORKING_TRC_BT709"));
+ wTRC->append(M("TP_ICM_WORKING_TRC_SRGB"));
+ wTRC->append(M("TP_ICM_WORKING_TRC_22"));
+ wTRC->append(M("TP_ICM_WORKING_TRC_18"));
+ wTRC->append(M("TP_ICM_WORKING_TRC_LIN"));
-// 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_TRC_TOOLTIP"));
+
+ wFrame->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();
+ wGamma = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_TRC_GAMMA"), 0.40, 15.0, 0.001, 2.222));
+ wSlope = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_TRC_SLOPE"), 0., 300., 0.01, 4.5));
+ trcProfVBox->pack_start(*wGamma, Gtk::PACK_SHRINK);
+ wGamma->show();
-// wProfVBox->pack_start(*wSlope, Gtk::PACK_SHRINK);
-// wSlope->show();
+ trcProfVBox->pack_start(*wSlope, Gtk::PACK_SHRINK);
+ wSlope->show();
+ willuBox = Gtk::manage(new Gtk::Box());
+ willulab = Gtk::manage(new Gtk::Label(M("TP_ICM_WORKING_ILLU") + ":"));
+
+ willuBox->pack_start(*willulab, Gtk::PACK_SHRINK);
+ will = Gtk::manage(new MyComboBoxText());
+ willuBox->pack_start(*will, Gtk::PACK_EXPAND_WIDGET);
+ trcProfVBox->pack_start(*willuBox, Gtk::PACK_EXPAND_WIDGET);
+ will->append(M("TP_ICM_WORKING_ILLU_NONE"));
+ will->append(M("TP_ICM_WORKING_ILLU_D41"));
+ will->append(M("TP_ICM_WORKING_ILLU_D50"));
+ will->append(M("TP_ICM_WORKING_ILLU_D55"));
+ will->append(M("TP_ICM_WORKING_ILLU_D60"));
+ will->append(M("TP_ICM_WORKING_ILLU_D65"));
+ will->append(M("TP_ICM_WORKING_ILLU_D80"));
+ will->append(M("TP_ICM_WORKING_ILLU_D120"));
+ will->append(M("TP_ICM_WORKING_ILLU_STDA"));
+ will->append(M("TP_ICM_WORKING_ILLU_2000"));
+ will->append(M("TP_ICM_WORKING_ILLU_1500"));
+ will->set_active(0);
+ will->set_tooltip_text(M("TP_ICM_ILLUMPRIM_TOOLTIP"));
+
+
+ wprimBox = Gtk::manage(new Gtk::Box());
+ wprimlab = Gtk::manage(new Gtk::Label(M("TP_ICM_WORKING_PRIM") + ":"));
+
+ wprimBox->pack_start(*wprimlab, Gtk::PACK_SHRINK);
+ wprim = Gtk::manage(new MyComboBoxText());
+ wprimBox->pack_start(*wprim, Gtk::PACK_EXPAND_WIDGET);
+ fbw = Gtk::manage(new Gtk::CheckButton((M("TP_ICM_FBW"))));
+ fbw->set_active(true);
+ trcProfVBox->pack_start(*wprimBox, Gtk::PACK_EXPAND_WIDGET);
+ trcProfVBox->pack_start(*fbw, Gtk::PACK_EXPAND_WIDGET);
+
+ neutral = Gtk::manage (new Gtk::Button (M ("TP_ICM_NEUTRAL")));
+ setExpandAlignProperties (neutral, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
+ RTImage *resetImg = Gtk::manage (new RTImage ("undo-small.png", "redo-small.png"));
+ setExpandAlignProperties (resetImg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
+ neutral->set_image (*resetImg);
+ neutralconn = neutral->signal_pressed().connect ( sigc::mem_fun (*this, &ICMPanel::neutral_pressed) );
+ neutral->show();
+
+ trcProfVBox->pack_start (*neutral);
+
+
+ wprim->append(M("TP_ICM_WORKING_PRIM_NONE"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_SRGB"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_ADOB"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_PROP"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_REC"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_ACE"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_WID"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_AC0"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_BRU"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_BET"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_BST"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_CUS"));
+ wprim->append(M("TP_ICM_WORKING_PRIM_CUSGR"));
+ wprim->set_active(0);
+
+ wprim->set_tooltip_text(M("TP_ICM_PRIMILLUM_TOOLTIP"));
+
+
+ redx = Gtk::manage(new Adjuster(M("TC_PRIM_REDX"), 0.41, 1.0, 0.0001, 0.7347));
+ setExpandAlignProperties(redx, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
+ redy = Gtk::manage(new Adjuster(M("TC_PRIM_REDY"), 0.0, 0.70, 0.0001, 0.2653));
+ setExpandAlignProperties(redy, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
+ grex = Gtk::manage(new Adjuster(M("TC_PRIM_GREX"), -0.1, 0.4, 0.0001, 0.1596));
+ setExpandAlignProperties(grex, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
+ grey = Gtk::manage(new Adjuster(M("TC_PRIM_GREY"), 0.50, 1.0, 0.0001, 0.8404));
+ setExpandAlignProperties(grey, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
+ blux = Gtk::manage(new Adjuster(M("TC_PRIM_BLUX"), -0.1, 0.4, 0.0001, 0.0366));
+ setExpandAlignProperties(blux, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
+ bluy = Gtk::manage(new Adjuster(M("TC_PRIM_BLUY"), -0.1, 0.5, 0.0001, 0.0001));
+ setExpandAlignProperties(bluy, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
+
+ redx->set_tooltip_text(M("TP_ICM_PRIMRED_TOOLTIP"));
+ grex->set_tooltip_text(M("TP_ICM_PRIMGRE_TOOLTIP"));
+ blux->set_tooltip_text(M("TP_ICM_PRIMBLU_TOOLTIP"));
+ blr = Gtk::manage(new Gtk::Label(M(" ")));
+ blg = Gtk::manage(new Gtk::Label(M(" ")));
+ blb = Gtk::manage(new Gtk::Label(M(" ")));
+
+ redBox = Gtk::manage(new Gtk::Box());
+ redBox->pack_start(*redx);//, Gtk::PACK_SHRINK);
+ redBox->pack_start(*blr, Gtk::PACK_SHRINK);
+ redBox->pack_start(*redy);//, Gtk::PACK_SHRINK);
+ redFrame = Gtk::manage(new Gtk::Frame(M("TP_ICM_REDFRAME")));
+ redFrame->set_label_align(0.025, 0.5);
+ Gtk::Box *redVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+ redVBox->pack_start(*redBox, Gtk::PACK_EXPAND_WIDGET);
+ redFrame->set_tooltip_text(M("TP_ICM_WORKING_PRIMFRAME_TOOLTIP"));
+
+ greBox = Gtk::manage(new Gtk::Box());
+ greBox->pack_start(*grex);//, Gtk::PACK_SHRINK, 2);
+ greBox->pack_start(*blg, Gtk::PACK_SHRINK);
+ greBox->pack_start(*grey);//, Gtk::PACK_SHRINK, 2);
+ redVBox->pack_start(*greBox, Gtk::PACK_EXPAND_WIDGET);
+ Gtk::Separator* const separator1 = Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL));
+ Gtk::Separator* const separator2 = Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL));
+
+ bluBox = Gtk::manage(new Gtk::Box());
+ bluBox->pack_start(*blux);//, Gtk::PACK_SHRINK);
+ bluBox->pack_start(*blb, Gtk::PACK_SHRINK);
+ bluBox->pack_start(*bluy);//, Gtk::PACK_SHRINK);
+ redVBox->pack_start(*bluBox, Gtk::PACK_EXPAND_WIDGET);
+ preser = Gtk::manage(new Adjuster(M("TP_ICM_WORKING_PRESER"), 0., 100., 0.5, 0.));
+ preser->setAdjusterListener(this);
+
+ preBox = Gtk::manage(new Gtk::Box());
+ preBox->pack_start(*preser, Gtk::PACK_SHRINK);
+ redVBox->pack_start(*separator1, Gtk::PACK_SHRINK);
+ redVBox->pack_start(*preBox, Gtk::PACK_EXPAND_WIDGET);
+ redVBox->pack_start(*separator2, Gtk::PACK_SHRINK);
+
+ cielab = Gtk::manage(new Gtk::Label(M("TP_ICM_WORKING_CIEDIAG") + ":"));
+
+ redVBox->pack_start(*cielab, Gtk::PACK_SHRINK);
+
+ redVBox->pack_start(*labgridcie, Gtk::PACK_EXPAND_WIDGET, 4);
+
+ redFrame->add(*redVBox);
wGamma->setAdjusterListener(this);
+ wSlope->setLogScale(16, 0);
wSlope->setAdjusterListener(this);
+ redx->setAdjusterListener(this);
+ redy->setAdjusterListener(this);
+ grex->setAdjusterListener(this);
+ grey->setAdjusterListener(this);
+ blux->setAdjusterListener(this);
+ bluy->setAdjusterListener(this);
wGamma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
wSlope->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay));
- wFrame->add(*wProfVBox);
+ // Rendering intent
+ riaHBox = Gtk::manage(new Gtk::Box());
+ Gtk::Label* abIntentLbl = Gtk::manage(new Gtk::Label(M("TP_ICM_PROFILEINTENT")));
+ riaHBox->pack_start(*abIntentLbl, Gtk::PACK_SHRINK);
+ aRendIntent.reset(new PopUpButton());
+ aRendIntent->addEntry("intent-perceptual.png", M("PREFERENCES_INTENT_PERCEPTUAL"));
+ aRendIntent->addEntry("intent-relative.png", M("PREFERENCES_INTENT_RELATIVE"));
+ aRendIntent->addEntry("intent-saturation.png", M("PREFERENCES_INTENT_SATURATION"));
+ aRendIntent->addEntry("intent-absolute.png", M("PREFERENCES_INTENT_ABSOLUTE"));
+ aRendIntent->setSelected(1);
+ aRendIntent->show();
+ riaHBox->pack_start(*aRendIntent->buttonGroup, Gtk::PACK_EXPAND_PADDING);
+
+ trcFrame->add(*trcProfVBox);
pack_start(*wFrame, Gtk::PACK_EXPAND_WIDGET);
+ pack_start(*trcFrame, Gtk::PACK_EXPAND_WIDGET);
+ pack_start(*redFrame, Gtk::PACK_EXPAND_WIDGET);
// ---------------------------- Output profile
@@ -229,6 +394,7 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha
Gtk::Frame *oFrame = Gtk::manage(new Gtk::Frame(M("TP_ICM_OUTPUTPROFILE")));
oFrame->set_label_align(0.025, 0.5);
+ oFrame->set_tooltip_text(M("TP_ICM_OUTPUTPROFILE_TOOLTIP"));
Gtk::Box* oProfVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
@@ -303,9 +469,13 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha
wprofnamesconn = wProfNames->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::wpChanged));
oprofnamesconn = oProfNames->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::opChanged));
orendintentconn = oRendIntent->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::oiChanged));
+ arendintentconn = aRendIntent->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::aiChanged));
dcpillconn = dcpIll->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::dcpIlluminantChanged));
wtrcconn = wTRC->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::wtrcinChanged));
+ willconn = will->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::willChanged));
+ wprimconn = wprim->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::wprimChanged));
+ fbwconn = fbw->signal_toggled().connect(sigc::mem_fun(*this, &ICMPanel::fbwChanged));
obpcconn = obpc->signal_toggled().connect(sigc::mem_fun(*this, &ICMPanel::oBPCChanged));
tcurveconn = ckbToneCurve->signal_toggled().connect(sigc::mem_fun(*this, &ICMPanel::toneCurveChanged));
ltableconn = ckbApplyLookTable->signal_toggled().connect(sigc::mem_fun(*this, &ICMPanel::applyLookTableChanged));
@@ -323,6 +493,38 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha
show_all();
}
+void ICMPanel::neutral_pressed ()
+{ //find working profile and set the same destination proile
+ if (wProfNames->get_active_text() == "Rec2020") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::REC2020));
+ } else if (wProfNames->get_active_text() == "sRGB") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::SRGB));
+ } else if (wProfNames->get_active_text() == "Adobe RGB") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::ADOBE_RGB));
+ } else if (wProfNames->get_active_text() == "ProPhoto") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::PRO_PHOTO));
+ } else if (wProfNames->get_active_text() == "ACESp1") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::ACES_P1));
+ } else if (wProfNames->get_active_text() == "WideGamut") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::WIDE_GAMUT));
+ } else if (wProfNames->get_active_text() == "ACESp0") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::ACES_P0));
+ } else if (wProfNames->get_active_text() == "BruceRGB") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::BRUCE_RGB));
+ } else if (wProfNames->get_active_text() == "Beta RGB") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::BETA_RGB));
+ } else if (wProfNames->get_active_text() == "BestRGB") {
+ wprim->set_active(toUnderlying(ColorManagementParams::Primaries::BEST_RGB));
+ }
+ const ColorManagementParams defPar;
+ wGamma->setValue(defPar.workingTRCGamma);//2.4
+ wSlope->setValue(defPar.workingTRCSlope);//12.92
+ preser->setValue(defPar.preser);
+ fbw->set_active(defPar.fbw);
+ wTRC->set_active(toUnderlying(ColorManagementParams::WorkingTrc::NONE));//reset to none
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::DEFAULT));//reset to default - after wprim
+}
+
void ICMPanel::updateRenderingIntent(const Glib::ustring &profile)
{
const uint8_t supportedIntents = rtengine::ICCStore::getInstance()->getOutputIntents(profile);
@@ -339,6 +541,13 @@ void ICMPanel::updateRenderingIntent(const Glib::ustring &profile)
oRendIntent->setItemSensitivity(1, supportsRelative);
oRendIntent->setItemSensitivity(2, supportsSaturation);
oRendIntent->setItemSensitivity(3, supportsAbsolute);
+
+ aRendIntent->set_sensitive(true);
+ aRendIntent->setItemSensitivity(0, supportsPerceptual);
+ aRendIntent->setItemSensitivity(1, supportsRelative);
+ aRendIntent->setItemSensitivity(2, supportsSaturation);
+ aRendIntent->setItemSensitivity(3, supportsAbsolute);
+
} else {
oRendIntent->setItemSensitivity(0, true);
oRendIntent->setItemSensitivity(1, true);
@@ -346,9 +555,91 @@ void ICMPanel::updateRenderingIntent(const Glib::ustring &profile)
oRendIntent->setItemSensitivity(3, true);
oRendIntent->set_sensitive(false);
oRendIntent->setSelected(1);
+
+ aRendIntent->setItemSensitivity(0, true);
+ aRendIntent->setItemSensitivity(1, true);
+ aRendIntent->setItemSensitivity(2, true);
+ aRendIntent->setItemSensitivity(3, true);
+ aRendIntent->set_sensitive(false);
+ aRendIntent->setSelected(1);
+
}
}
+ICMPanel::~ICMPanel()
+{
+ idle_register.destroy();
+}
+
+void ICMPanel::primChanged (float rx, float ry, float bx, float by, float gx, float gy)
+{ //update sliders R G B Ciexy
+ nextrx = rx;
+ nextry = ry;
+ nextbx = bx;
+ nextby = by;
+ nextgx = gx;
+ nextgy = gy;
+
+ idle_register.add(
+ [this]() -> bool
+ {
+ disableListener();
+ redx->setValue(nextrx);
+ redy->setValue(nextry);
+ blux->setValue(nextbx);
+ bluy->setValue(nextby);
+ grex->setValue(nextgx);
+ grey->setValue(nextgy);
+
+ enableListener();
+ return false;
+ }
+ );
+}
+
+void ICMPanel::iprimChanged (float r_x, float r_y, float b_x, float b_y, float g_x, float g_y, float w_x, float w_y)
+{//update CIE xy graph
+ nextrx = r_x;
+ nextry = r_y;
+ nextbx = b_x;
+ nextby = b_y;
+ nextgx = g_x;
+ nextgy = g_y;
+ nextwx = w_x;
+ nextwy = w_y;
+ //convert xy datas in datas for labgrid areas
+ nextrx = 1.81818f * (nextrx + 0.1f) - 1.f;
+ nextry = 1.81818f * (nextry + 0.1f) - 1.f;
+ nextbx = 1.81818f * (nextbx + 0.1f) - 1.f;
+ nextby = 1.81818f * (nextby + 0.1f) - 1.f;
+ nextgx = 1.81818f * (nextgx + 0.1f) - 1.f;
+ nextgy = 1.81818f * (nextgy + 0.1f) - 1.f;
+ nextwx = 1.81818f * (nextwx + 0.1f) - 1.f;
+ nextwy = 1.81818f * (nextwy + 0.1f) - 1.f;
+
+ idle_register.add(
+ [this]() -> bool
+ {
+ disableListener();
+ labgridcie->setParams(nextrx, nextry, nextbx, nextby, nextgx, nextgy, nextwx, nextwy, false);
+ enableListener();
+ return false;
+ }
+ );
+}
+
+
+void ICMPanel::setEditProvider(EditDataProvider *provider)
+{
+ //in case of
+}
+
+void ICMPanel::setListener(ToolPanelListener *tpl)
+{//enable listener Toolpanel and Labgridcie
+ ToolPanel::setListener(tpl);
+ labgridcie->setListener(tpl);
+}
+
void ICMPanel::updateDCP(int dcpIlluminant, Glib::ustring dcp_name)
{
ConnectionBlocker dcpillconn_(dcpillconn);
@@ -481,6 +772,7 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited)
disableListener();
ConnectionBlocker obpcconn_(obpcconn);
+ ConnectionBlocker fbwconn_(fbwconn);
ConnectionBlocker ipc_(ipc);
ConnectionBlocker tcurveconn_(tcurveconn);
ConnectionBlocker ltableconn_(ltableconn);
@@ -489,7 +781,11 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited)
ConnectionBlocker wprofnamesconn_(wprofnamesconn);
ConnectionBlocker oprofnamesconn_(oprofnamesconn);
ConnectionBlocker orendintentconn_(orendintentconn);
+ ConnectionBlocker arendintentconn_(arendintentconn);
ConnectionBlocker dcpillconn_(dcpillconn);
+ ConnectionBlocker wtrcconn_(wtrcconn);
+ ConnectionBlocker willconn_(willconn);
+ ConnectionBlocker wprimconn_(wprimconn);
if (pp->icm.inputProfile.substr(0, 5) != "file:" && !ipDialog->get_filename().empty()) {
ipDialog->set_filename(pp->icm.inputProfile);
@@ -525,13 +821,15 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited)
wProfNames->set_active_text(pp->icm.workingProfile);
- if (pp->icm.workingTRC == "none") {
- wTRC->set_active(0);
- } else if (pp->icm.workingTRC == "Custom") {
- wTRC->set_active(1);
- }
+ wTRC->set_active(rtengine::toUnderlying(pp->icm.workingTRC));
+
+ will->set_active(rtengine::toUnderlying(pp->icm.will));
+
+ wprim->set_active(rtengine::toUnderlying(pp->icm.wprim));
wtrcinChanged();
+ willChanged();
+ wprimChanged();
if (pp->icm.outputProfile == ColorManagementParams::NoICMString) {
oProfNames->set_active_text(M("TP_ICM_NOICM"));
@@ -544,8 +842,10 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited)
}
oRendIntent->setSelected(pp->icm.outputIntent);
+ aRendIntent->setSelected(pp->icm.aRendIntent);
obpc->set_active(pp->icm.outputBPC);
+ fbw->set_active(pp->icm.fbw);
ckbToneCurve->set_active(pp->icm.toneCurve);
lastToneCurve = pp->icm.toneCurve;
ckbApplyLookTable->set_active(pp->icm.applyLookTable);
@@ -557,10 +857,19 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited)
wGamma->setValue(pp->icm.workingTRCGamma);
wSlope->setValue(pp->icm.workingTRCSlope);
+ redx->setValue(pp->icm.redx);
+ redy->setValue(pp->icm.redy);
+ grex->setValue(pp->icm.grex);
+ grey->setValue(pp->icm.grey);
+ blux->setValue(pp->icm.blux);
+ bluy->setValue(pp->icm.bluy);
+ preser->setValue(pp->icm.preser);
+ labgridcie->setParams(pp->icm.labgridcieALow, pp->icm.labgridcieBLow, pp->icm.labgridcieAHigh, pp->icm.labgridcieBHigh, pp->icm.labgridcieGx, pp->icm.labgridcieGy, pp->icm.labgridcieWx, pp->icm.labgridcieWy, false);
if (pedited) {
iunchanged->set_active(!pedited->icm.inputProfile);
obpc->set_inconsistent(!pedited->icm.outputBPC);
+ fbw->set_inconsistent(!pedited->icm.fbw);
ckbToneCurve->set_inconsistent(!pedited->icm.toneCurve);
ckbApplyLookTable->set_inconsistent(!pedited->icm.applyLookTable);
ckbApplyBaselineExposureOffset->set_inconsistent(!pedited->icm.applyBaselineExposureOffset);
@@ -578,6 +887,10 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited)
oRendIntent->setSelected(4);
}
+ if (!pedited->icm.aRendIntent) {
+ aRendIntent->setSelected(4);
+ }
+
if (!pedited->icm.dcpIlluminant) {
dcpIll->set_active_text(M("GENERAL_UNCHANGED"));
}
@@ -586,11 +899,206 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited)
wTRC->set_active_text(M("GENERAL_UNCHANGED"));
}
+ if (!pedited->icm.will) {
+ will->set_active_text(M("GENERAL_UNCHANGED"));
+ }
+
+ if (!pedited->icm.wprim) {
+ wprim->set_active_text(M("GENERAL_UNCHANGED"));
+ }
+ labgridcie->setEdited(pedited->icm.labgridcieALow || pedited->icm.labgridcieBLow || pedited->icm.labgridcieAHigh || pedited->icm.labgridcieBHigh || pedited->icm.labgridcieGx || pedited->icm.labgridcieGy || pedited->icm.labgridcieWx || pedited->icm.labgridcieWy);
+
wGamma->setEditedState(pedited->icm.workingTRCGamma ? Edited : UnEdited);
wSlope->setEditedState(pedited->icm.workingTRCSlope ? Edited : UnEdited);
+ redx->setEditedState(pedited->icm.redx ? Edited : UnEdited);
+ redy->setEditedState(pedited->icm.redy ? Edited : UnEdited);
+ grex->setEditedState(pedited->icm.grex ? Edited : UnEdited);
+ grey->setEditedState(pedited->icm.grey ? Edited : UnEdited);
+ blux->setEditedState(pedited->icm.blux ? Edited : UnEdited);
+ bluy->setEditedState(pedited->icm.bluy ? Edited : UnEdited);
+ preser->setEditedState(pedited->icm.preser ? Edited : UnEdited);
}
+ switch (ColorManagementParams::WorkingTrc(wTRC->get_active_row_number())) {
+ case ColorManagementParams::WorkingTrc::NONE: {
+ wSlope->set_sensitive(false);
+ wGamma->set_sensitive(false);
+ will->set_sensitive(false);
+ willulab->set_sensitive(false);
+ wprim->set_sensitive(false);
+ fbw->set_sensitive(false);
+ wprimlab->set_sensitive(false);
+ riaHBox->set_sensitive(false);
+ redFrame->hide();
+ break;
+ }
+
+ case ColorManagementParams::WorkingTrc::CUSTOM: {
+ will->set_sensitive(false);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ if (
+ ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM
+ && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID
+ ) {
+ will->set_sensitive(false);
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ labgridcie->set_sensitive(false);
+
+ } else {
+ will->set_sensitive(false);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::CUSTOM) {
+ will->set_sensitive(true);
+ }
+ redBox->set_sensitive(true);
+ greBox->set_sensitive(true);
+ bluBox->set_sensitive(true);
+ labgridcie->set_sensitive(true);
+ }
+
+ }
+ riaHBox->set_sensitive(true);
+
+ if (pp->icm.workingTRCGamma <= 1.) {
+ wGamma->set_sensitive(true);
+ wSlope->set_sensitive(false);
+ } else {
+ wGamma->set_sensitive(true);
+ wSlope->set_sensitive(true);
+ }
+ break;
+ }
+
+ case ColorManagementParams::WorkingTrc::BT709:
+ wGamma->setValue(2.222);
+ wSlope->setValue(4.5);
+ will->set_sensitive(true);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ }
+ riaHBox->set_sensitive(true);
+ break;
+ case ColorManagementParams::WorkingTrc::SRGB:
+ wGamma->setValue(2.4);
+ wSlope->setValue(12.92);
+ will->set_sensitive(true);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ riaHBox->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ }
+ break;
+ case ColorManagementParams::WorkingTrc::GAMMA_2_2:
+ wGamma->setValue(2.2);
+ wSlope->setValue(0.);
+ will->set_sensitive(true);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ redFrame->show();
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ riaHBox->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ }
+ break;
+ case ColorManagementParams::WorkingTrc::GAMMA_1_8:
+ wGamma->setValue(1.8);
+ wSlope->setValue(0.);
+ will->set_sensitive(true);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ riaHBox->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ }
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ break;
+ case ColorManagementParams::WorkingTrc::LINEAR:
+ wGamma->setValue(1.);
+ wSlope->setValue(1.);
+ will->set_sensitive(true);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ riaHBox->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ }
+ break;
+ }
+
+ switch (ColorManagementParams::Primaries(wprim->get_active_row_number())) {
+ case ColorManagementParams::Primaries::DEFAULT:
+ case ColorManagementParams::Primaries::SRGB:
+ case ColorManagementParams::Primaries::ADOBE_RGB:
+ case ColorManagementParams::Primaries::PRO_PHOTO:
+ case ColorManagementParams::Primaries::REC2020:
+ case ColorManagementParams::Primaries::ACES_P1:
+ case ColorManagementParams::Primaries::WIDE_GAMUT:
+ case ColorManagementParams::Primaries::ACES_P0:
+ case ColorManagementParams::Primaries::BRUCE_RGB:
+ case ColorManagementParams::Primaries::BETA_RGB:
+ case ColorManagementParams::Primaries::BEST_RGB: {
+ labgridcie->set_sensitive(false);
+ will->set_sensitive(false);
+ break;
+ }
+
+ case ColorManagementParams::Primaries::CUSTOM: {
+ will->set_sensitive(true);
+ labgridcie->set_sensitive(false);
+ break;
+ }
+
+ case ColorManagementParams::Primaries::CUSTOM_GRID: {
+ labgridcie->set_sensitive(true);
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ will->set_sensitive(false);
+ break;
+ }
+ }
+
enableListener();
}
@@ -615,7 +1123,7 @@ void ICMPanel::write(ProcParams* pp, ParamsEdited* pedited)
pp->icm.workingProfile = wProfNames->get_active_text();
pp->icm.dcpIlluminant = rtengine::max(dcpIll->get_active_row_number(), 0);
- pp->icm.workingTRC = wTRC->get_active_text();
+ labgridcie->getParams(pp->icm.labgridcieALow, pp->icm.labgridcieBLow, pp->icm.labgridcieAHigh, pp->icm.labgridcieBHigh, pp->icm.labgridcieGx, pp->icm.labgridcieGy, pp->icm.labgridcieWx, pp->icm.labgridcieWy);
if (oProfNames->get_active_text() == M("TP_ICM_NOICM")) {
pp->icm.outputProfile = ColorManagementParams::NoICMString;
@@ -631,27 +1139,43 @@ void ICMPanel::write(ProcParams* pp, ParamsEdited* pedited)
pp->icm.outputIntent = rtengine::RI_RELATIVE;
}
- if (wTRC->get_active_row_number() == 0) {
- pp->icm.workingTRC = "none";
- } else if (wTRC->get_active_row_number() == 1) {
- pp->icm.workingTRC = "Custom";
+ int aintentVal = aRendIntent->getSelected();
+
+ if (aintentVal >= 0 && aintentVal < RI__COUNT) {
+ pp->icm.aRendIntent = static_cast(aintentVal);
+ } else {
+ pp->icm.aRendIntent = rtengine::RI_RELATIVE;
}
+ pp->icm.workingTRC = ColorManagementParams::WorkingTrc(wTRC->get_active_row_number());
+ pp->icm.will = ColorManagementParams::Illuminant(will->get_active_row_number());
+ pp->icm.wprim = ColorManagementParams::Primaries(wprim->get_active_row_number());
+
pp->icm.toneCurve = ckbToneCurve->get_active();
pp->icm.applyLookTable = ckbApplyLookTable->get_active();
pp->icm.applyBaselineExposureOffset = ckbApplyBaselineExposureOffset->get_active();
pp->icm.applyHueSatMap = ckbApplyHueSatMap->get_active();
pp->icm.outputBPC = obpc->get_active();
- pp->icm.workingTRCGamma = (double) wGamma->getValue();
- pp->icm.workingTRCSlope = (double) wSlope->getValue();
+ pp->icm.fbw = fbw->get_active();
+ pp->icm.workingTRCGamma = wGamma->getValue();
+ pp->icm.workingTRCSlope = wSlope->getValue();
+ pp->icm.redx = redx->getValue();
+ pp->icm.redy = redy->getValue();
+ pp->icm.grex = grex->getValue();
+ pp->icm.grey = grey->getValue();
+ pp->icm.blux = blux->getValue();
+ pp->icm.bluy = bluy->getValue();
pp->toneCurve.fromHistMatching = false;
+ pp->icm.preser = preser->getValue();
if (pedited) {
pedited->icm.inputProfile = !iunchanged->get_active();
pedited->icm.workingProfile = wProfNames->get_active_text() != M("GENERAL_UNCHANGED");
pedited->icm.outputProfile = oProfNames->get_active_text() != M("GENERAL_UNCHANGED");
pedited->icm.outputIntent = oRendIntent->getSelected() < 4;
+ pedited->icm.aRendIntent = aRendIntent->getSelected() < 4;
pedited->icm.outputBPC = !obpc->get_inconsistent();
+ pedited->icm.fbw = !fbw->get_inconsistent();
pedited->icm.dcpIlluminant = dcpIll->get_active_text() != M("GENERAL_UNCHANGED");
pedited->icm.toneCurve = !ckbToneCurve->get_inconsistent();
pedited->icm.applyLookTable = !ckbApplyLookTable->get_inconsistent();
@@ -660,21 +1184,50 @@ void ICMPanel::write(ProcParams* pp, ParamsEdited* pedited)
pedited->icm.workingTRCGamma = wGamma->getEditedState();
pedited->icm.workingTRCSlope = wSlope->getEditedState();
pedited->icm.workingTRC = wTRC->get_active_text() != M("GENERAL_UNCHANGED");
- }
+ pedited->icm.will = will->get_active_text() != M("GENERAL_UNCHANGED");
+ pedited->icm.wprim = wprim->get_active_text() != M("GENERAL_UNCHANGED");
+ pedited->icm.redx = redx->getEditedState();
+ pedited->icm.redy = redy->getEditedState();
+ pedited->icm.labgridcieALow = pedited->icm.labgridcieBLow = pedited->icm.labgridcieAHigh = pedited->icm.labgridcieBHigh = pedited->icm.labgridcieGx = pedited->icm.labgridcieGy = pedited->icm.labgridcieWx = pedited->icm.labgridcieWy = labgridcie->getEdited();
+ }
}
void ICMPanel::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited)
{
wGamma->setDefault(defParams->icm.workingTRCGamma);
wSlope->setDefault(defParams->icm.workingTRCSlope);
+ redx->setDefault(defParams->icm.redx);
+ redy->setDefault(defParams->icm.redy);
+ grex->setDefault(defParams->icm.grex);
+ grey->setDefault(defParams->icm.grey);
+ blux->setDefault(defParams->icm.blux);
+ bluy->setDefault(defParams->icm.bluy);
+ preser->setDefault(defParams->icm.preser);
+ labgridcie->setDefault(defParams->icm.labgridcieALow, defParams->icm.labgridcieBLow , defParams->icm.labgridcieAHigh, defParams->icm.labgridcieBHigh, defParams->icm.labgridcieGx, defParams->icm.labgridcieGy, defParams->icm.labgridcieWx, defParams->icm.labgridcieWy);
if (pedited) {
wGamma->setDefaultEditedState(pedited->icm.workingTRCGamma ? Edited : UnEdited);
wSlope->setDefaultEditedState(pedited->icm.workingTRCSlope ? Edited : UnEdited);
+ redx->setDefaultEditedState(pedited->icm.redx ? Edited : UnEdited);
+ redy->setDefaultEditedState(pedited->icm.redy ? Edited : UnEdited);
+ grex->setDefaultEditedState(pedited->icm.grex ? Edited : UnEdited);
+ grey->setDefaultEditedState(pedited->icm.grey ? Edited : UnEdited);
+ blux->setDefaultEditedState(pedited->icm.blux ? Edited : UnEdited);
+ bluy->setDefaultEditedState(pedited->icm.bluy ? Edited : UnEdited);
+ labgridcie->setEdited((pedited->icm.labgridcieALow || pedited->icm.labgridcieBLow || pedited->icm.labgridcieAHigh || pedited->icm.labgridcieBHigh || pedited->icm.labgridcieGx || pedited->icm.labgridcieGy || pedited->icm.labgridcieWx || pedited->icm.labgridcieWy) ? Edited : UnEdited);
+ preser->setDefaultEditedState(pedited->icm.preser ? Edited : UnEdited);
} else {
wGamma->setDefaultEditedState(Irrelevant);
wSlope->setDefaultEditedState(Irrelevant);
+ redx->setDefaultEditedState(Irrelevant);
+ redy->setDefaultEditedState(Irrelevant);
+ grex->setDefaultEditedState(Irrelevant);
+ grey->setDefaultEditedState(Irrelevant);
+ blux->setDefaultEditedState(Irrelevant);
+ bluy->setDefaultEditedState(Irrelevant);
+ preser->setDefaultEditedState(Irrelevant);
+ labgridcie->setEdited(Edited);
}
}
@@ -685,9 +1238,28 @@ void ICMPanel::adjusterChanged(Adjuster* a, double newval)
Glib::ustring costr2 = Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), newval);
if (a == wGamma) {
+ if (wGamma->getValue() <= 1.) {
+ wSlope->set_sensitive(false);
+ } else {
+ wSlope->set_sensitive(true);
+ }
listener->panelChanged(EvICMgamm, costr2);
} else if (a == wSlope) {
listener->panelChanged(EvICMslop, costr2);
+ } else if (a == redx) {
+ listener->panelChanged(EvICMredx, costr2);
+ } else if (a == redy) {
+ listener->panelChanged(EvICMredy, costr2);
+ } else if (a == grex) {
+ listener->panelChanged(EvICMgrex, costr2);
+ } else if (a == grey) {
+ listener->panelChanged(EvICMgrey, costr2);
+ } else if (a == blux) {
+ listener->panelChanged(EvICMblux, costr2);
+ } else if (a == bluy) {
+ listener->panelChanged(EvICMbluy, costr2);
+ } else if (a == preser) {
+ listener->panelChanged(EvICMpreser, costr2);
}
}
@@ -702,13 +1274,238 @@ void ICMPanel::wpChanged()
void ICMPanel::wtrcinChanged()
{
- if (wTRC->get_active_row_number() == 0) {
- wGamma->set_sensitive(false);
- wSlope->set_sensitive(false);
+ switch (ColorManagementParams::WorkingTrc(wTRC->get_active_row_number())) {
+ case ColorManagementParams::WorkingTrc::NONE: {
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ will->set_sensitive(false);
+ willulab->set_sensitive(false);
+ wprim->set_sensitive(false);
+ fbw->set_sensitive(false);
+ wprimlab->set_sensitive(false);
+ redFrame->hide();
+ riaHBox->set_sensitive(false);
+ break;
+ }
- } else {
- wGamma->set_sensitive(true);
- wSlope->set_sensitive(true);
+ case ColorManagementParams::WorkingTrc::CUSTOM: {
+ will->set_sensitive(false);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ willulab->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ if (
+ ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM
+ && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID
+ ) {
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ } else {
+ redBox->set_sensitive(true);
+ greBox->set_sensitive(true);
+ bluBox->set_sensitive(true);
+ }
+ }
+ riaHBox->set_sensitive(true);
+ if (wGamma->getValue() <= 1.) {
+ wGamma->set_sensitive(true);
+ wSlope->set_sensitive(false);
+ } else {
+ wGamma->set_sensitive(true);
+ wSlope->set_sensitive(true);
+ }
+ break;
+ }
+
+ case ColorManagementParams::WorkingTrc::BT709: {
+ wGamma->setValue(2.222);
+ wSlope->setValue(4.5);
+ will->set_sensitive(false);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ if (
+ ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM
+ && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID
+ ) {
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ }
+ }
+ riaHBox->set_sensitive(true);
+ break;
+ }
+
+ case ColorManagementParams::WorkingTrc::SRGB: {
+ wGamma->setValue(2.4);
+ wSlope->setValue(12.92);
+ will->set_sensitive(false);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ riaHBox->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ if (
+ ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM
+ && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID
+ ) {
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ } else {
+ redBox->set_sensitive(true);
+ greBox->set_sensitive(true);
+ bluBox->set_sensitive(true);
+ }
+ }
+ break;
+ }
+
+ case ColorManagementParams::WorkingTrc::GAMMA_2_2: {
+ wGamma->setValue(2.2);
+ wSlope->setValue(0.);
+ will->set_sensitive(false);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ riaHBox->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ if (
+ ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM
+ && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID
+ ) {
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ } else {
+ redBox->set_sensitive(true);
+ greBox->set_sensitive(true);
+ bluBox->set_sensitive(true);
+ }
+ }
+ break;
+ }
+
+ case ColorManagementParams::WorkingTrc::GAMMA_1_8: {
+ wGamma->setValue(1.8);
+ wSlope->setValue(0.);
+ will->set_sensitive(false);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ riaHBox->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ if (
+ ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM
+ && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID
+ ) {
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ } else {
+ redBox->set_sensitive(true);
+ greBox->set_sensitive(true);
+ bluBox->set_sensitive(true);
+ }
+ }
+ break;
+ }
+
+ case ColorManagementParams::WorkingTrc::LINEAR: {
+ wGamma->setValue(1.0);
+ wSlope->setValue(1.);
+ will->set_sensitive(false);
+ willulab->set_sensitive(true);
+ wprim->set_sensitive(true);
+ fbw->set_sensitive(true);
+ wprimlab->set_sensitive(true);
+ wGamma->set_sensitive(false);
+ wSlope->set_sensitive(false);
+ riaHBox->set_sensitive(true);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ redFrame->hide();
+ } else {
+ redFrame->show();
+ if (
+ ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM
+ && ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM_GRID
+ ) {
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ } else {
+ redBox->set_sensitive(true);
+ greBox->set_sensitive(true);
+ bluBox->set_sensitive(true);
+ }
+ }
+ break;
+ }
+ }
+ wprimChanged();
+
+ switch (ColorManagementParams::Primaries(wprim->get_active_row_number())) {
+ case ColorManagementParams::Primaries::DEFAULT:
+ case ColorManagementParams::Primaries::SRGB:
+ case ColorManagementParams::Primaries::ADOBE_RGB:
+ case ColorManagementParams::Primaries::PRO_PHOTO:
+ case ColorManagementParams::Primaries::REC2020:
+ case ColorManagementParams::Primaries::ACES_P1:
+ case ColorManagementParams::Primaries::WIDE_GAMUT:
+ case ColorManagementParams::Primaries::ACES_P0:
+ case ColorManagementParams::Primaries::BRUCE_RGB:
+ case ColorManagementParams::Primaries::BETA_RGB:
+ case ColorManagementParams::Primaries::BEST_RGB: {
+ labgridcie->set_sensitive(false);
+ will->set_sensitive(false);
+ break;
+ }
+
+ case ColorManagementParams::Primaries::CUSTOM: {
+ will->set_sensitive(true);
+ labgridcie->set_sensitive(false);
+ break;
+ }
+
+ case ColorManagementParams::Primaries::CUSTOM_GRID: {
+ labgridcie->set_sensitive(true);
+ will->set_sensitive(false);
+ break;
+ }
+ }
+
+ if (ColorManagementParams::WorkingTrc(wTRC->get_active_row_number()) == ColorManagementParams::WorkingTrc::NONE) {
+ redFrame->hide();
}
if (listener) {
@@ -716,6 +1513,284 @@ void ICMPanel::wtrcinChanged()
}
}
+void ICMPanel::willChanged()
+{
+ switch (ColorManagementParams::Primaries(wprim->get_active_row_number())) {
+ case ColorManagementParams::Primaries::DEFAULT:
+ case ColorManagementParams::Primaries::SRGB:
+ case ColorManagementParams::Primaries::ADOBE_RGB:
+ case ColorManagementParams::Primaries::PRO_PHOTO:
+ case ColorManagementParams::Primaries::REC2020:
+ case ColorManagementParams::Primaries::ACES_P1:
+ case ColorManagementParams::Primaries::WIDE_GAMUT:
+ case ColorManagementParams::Primaries::ACES_P0:
+ case ColorManagementParams::Primaries::BRUCE_RGB:
+ case ColorManagementParams::Primaries::BETA_RGB:
+ case ColorManagementParams::Primaries::BEST_RGB: {
+ labgridcie->set_sensitive(false);
+ will->set_sensitive(false);
+ break;
+ }
+
+ case ColorManagementParams::Primaries::CUSTOM: {
+ will->set_sensitive(true);
+ labgridcie->set_sensitive(false);
+ break;
+ }
+
+ case ColorManagementParams::Primaries::CUSTOM_GRID: {
+ labgridcie->set_sensitive(true);
+ will->set_sensitive(false);
+ break;
+ }
+ }
+
+ if (listener) {
+ listener->panelChanged(EvICMwillMethod, will->get_active_text());
+ }
+}
+
+
+
+void ICMPanel::wprimChanged()
+{
+ switch (ColorManagementParams::Primaries(wprim->get_active_row_number())) {
+ case ColorManagementParams::Primaries::DEFAULT:
+ case ColorManagementParams::Primaries::CUSTOM:
+ case ColorManagementParams::Primaries::CUSTOM_GRID: {
+ break;
+ }
+
+ case ColorManagementParams::Primaries::SRGB: {
+ redx->setValue(0.64);
+ redy->setValue(0.33);
+ grex->setValue(0.30);
+ grey->setValue(0.60);
+ blux->setValue(0.15);
+ bluy->setValue(0.06);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::ADOBE_RGB: {
+ redx->setValue(0.64);
+ redy->setValue(0.33);
+ grex->setValue(0.21);
+ grey->setValue(0.71);
+ blux->setValue(0.15);
+ bluy->setValue(0.06);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::PRO_PHOTO: {
+ redx->setValue(0.7347);
+ redy->setValue(0.2653);
+ grex->setValue(0.1596);
+ grey->setValue(0.8404);
+ blux->setValue(0.0366);
+ bluy->setValue(0.0001);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::REC2020: {
+ redx->setValue(0.708);
+ redy->setValue(0.292);
+ grex->setValue(0.17);
+ grey->setValue(0.797);
+ blux->setValue(0.131);
+ bluy->setValue(0.046);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::ACES_P1: {
+ redx->setValue(0.713);
+ redy->setValue(0.293);
+ grex->setValue(0.165);
+ grey->setValue(0.830);
+ blux->setValue(0.128);
+ bluy->setValue(0.044);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D60));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::WIDE_GAMUT: {
+ redx->setValue(0.735);
+ redy->setValue(0.265);
+ grex->setValue(0.115);
+ grey->setValue(0.826);
+ blux->setValue(0.1570);
+ bluy->setValue(0.018);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::ACES_P0: {
+ redx->setValue(0.7347);
+ redy->setValue(0.2653);
+ grex->setValue(0.);
+ grey->setValue(1.0);
+ blux->setValue(0.0001);
+ bluy->setValue(-0.077);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D60));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::BRUCE_RGB: {
+ redx->setValue(0.64);
+ redy->setValue(0.33);
+ grex->setValue(0.28);
+ grey->setValue(0.65);
+ blux->setValue(0.15);
+ bluy->setValue(0.06);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::BETA_RGB: {
+ redx->setValue(0.6888);
+ redy->setValue(0.3112);
+ grex->setValue(0.1986);
+ grey->setValue(0.7551);
+ blux->setValue(0.1265);
+ bluy->setValue(0.0352);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50));
+ break;
+ }
+
+ case ColorManagementParams::Primaries::BEST_RGB: {
+ redx->setValue(0.7347);
+ redy->setValue(0.2653);
+ grex->setValue(0.2150);
+ grey->setValue(0.7750);
+ blux->setValue(0.130);
+ bluy->setValue(0.035);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50));
+ break;
+ }
+ }
+
+
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::DEFAULT) {
+ if (wProfNames->get_active_text() == "Rec2020") {
+ redx->setValue(0.708);
+ redy->setValue(0.292);
+ grex->setValue(0.17);
+ grey->setValue(0.797);
+ blux->setValue(0.131);
+ bluy->setValue(0.046);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65));
+ } else if (wProfNames->get_active_text() == "sRGB") {
+ redx->setValue(0.64);
+ redy->setValue(0.33);
+ grex->setValue(0.30);
+ grey->setValue(0.60);
+ blux->setValue(0.15);
+ bluy->setValue(0.06);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65));
+ } else if (wProfNames->get_active_text() == "Adobe RGB") {
+ redx->setValue(0.64);
+ redy->setValue(0.33);
+ grex->setValue(0.21);
+ grey->setValue(0.71);
+ blux->setValue(0.15);
+ bluy->setValue(0.06);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65));
+ } else if (wProfNames->get_active_text() == "ProPhoto") {
+ redx->setValue(0.7347);
+ redy->setValue(0.2653);
+ grex->setValue(0.1596);
+ grey->setValue(0.8404);
+ blux->setValue(0.0366);
+ bluy->setValue(0.0001);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50));
+ } else if (wProfNames->get_active_text() == "ACESp1") {
+ redx->setValue(0.713);
+ redy->setValue(0.293);
+ grex->setValue(0.165);
+ grey->setValue(0.830);
+ blux->setValue(0.128);
+ bluy->setValue(0.044);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D60));
+ } else if (wProfNames->get_active_text() == "WideGamut") {
+ redx->setValue(0.735);
+ redy->setValue(0.265);
+ grex->setValue(0.115);
+ grey->setValue(0.826);
+ blux->setValue(0.1570);
+ bluy->setValue(0.018);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50));
+ } else if (wProfNames->get_active_text() == "ACESp0") {
+ redx->setValue(0.7347);
+ redy->setValue(0.2653);
+ grex->setValue(0.);
+ grey->setValue(1.0);
+ blux->setValue(0.0001);
+ bluy->setValue(-0.077);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D60));
+ } else if (wProfNames->get_active_text() == "BruceRGB") {
+ redx->setValue(0.64);
+ redy->setValue(0.33);
+ grex->setValue(0.28);
+ grey->setValue(0.65);
+ blux->setValue(0.15);
+ bluy->setValue(0.06);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D65));
+ } else if (wProfNames->get_active_text() == "Beta RGB") {
+ redx->setValue(0.6888);
+ redy->setValue(0.3112);
+ grex->setValue(0.1986);
+ grey->setValue(0.7551);
+ blux->setValue(0.1265);
+ bluy->setValue(0.0352);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50));
+ } else if (wProfNames->get_active_text() == "BestRGB") {
+ redx->setValue(0.7347);
+ redy->setValue(0.2653);
+ grex->setValue(0.2150);
+ grey->setValue(0.7750);
+ blux->setValue(0.130);
+ bluy->setValue(0.035);
+ will->set_active(toUnderlying(ColorManagementParams::Illuminant::D50));
+ }
+
+ redFrame->hide();
+ } else {
+ redFrame->show();
+
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) != ColorManagementParams::Primaries::CUSTOM) {
+ redBox->set_sensitive(false);
+ greBox->set_sensitive(false);
+ bluBox->set_sensitive(false);
+ labgridcie->set_sensitive(false);
+ will->set_sensitive(false);
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::CUSTOM_GRID) {
+ labgridcie->set_sensitive(true);
+ }
+ } else {
+ redBox->set_sensitive(true);
+ greBox->set_sensitive(true);
+ bluBox->set_sensitive(true);
+ labgridcie->set_sensitive(false);
+ will->set_sensitive(true);
+ }
+
+ }
+ willChanged ();
+
+ if (ColorManagementParams::Primaries(wprim->get_active_row_number()) == ColorManagementParams::Primaries::CUSTOM_GRID) {
+ labgridcie->set_sensitive(true);
+ } else {
+ labgridcie->set_sensitive(false);
+ }
+
+ if (listener) {
+ listener->panelChanged(EvICMwprimMethod, wprim->get_active_text());
+ }
+}
+
void ICMPanel::dcpIlluminantChanged()
{
if (listener) {
@@ -897,6 +1972,39 @@ void ICMPanel::oiChanged(int n)
}
}
+void ICMPanel::aiChanged(int n)
+{
+
+ if (listener) {
+ Glib::ustring str;
+
+ switch (n) {
+ case 0:
+ str = M("PREFERENCES_INTENT_PERCEPTUAL");
+ break;
+
+ case 1:
+ str = M("PREFERENCES_INTENT_RELATIVE");
+ break;
+
+ case 2:
+ str = M("PREFERENCES_INTENT_SATURATION");
+ break;
+
+ case 3:
+ str = M("PREFERENCES_INTENT_ABSOLUTE");
+ break;
+
+ case 4:
+ default:
+ str = M("GENERAL_UNCHANGED");
+ break;
+ }
+
+ listener->panelChanged(EvaIntent, str);
+ }
+}
+
void ICMPanel::oBPCChanged()
{
if (multiImage) {
@@ -923,6 +2031,32 @@ void ICMPanel::oBPCChanged()
}
}
+void ICMPanel::fbwChanged()
+{
+ if (multiImage) {
+ if (fbw->get_inconsistent()) {
+ fbw->set_inconsistent(false);
+ fbwconn.block(true);
+ fbw->set_active(false);
+ fbwconn.block(false);
+ } else if (lastfbw) {
+ fbw->set_inconsistent(true);
+ }
+
+ lastfbw = fbw->get_active();
+ }
+
+ if (listener) {
+ if (fbw->get_inconsistent()) {
+ listener->panelChanged(EvICMfbw, M("GENERAL_UNCHANGED"));
+ } else if (fbw->get_active()) {
+ listener->panelChanged(EvICMfbw, M("GENERAL_ENABLED"));
+ } else {
+ listener->panelChanged(EvICMfbw, M("GENERAL_DISABLED"));
+ }
+ }
+}
+
void ICMPanel::setRawMeta(bool raw, const rtengine::FramesData* pMeta)
{
@@ -948,6 +2082,8 @@ void ICMPanel::ipSelectionChanged()
ipChanged();
}
+
+
void ICMPanel::saveReferencePressed()
{
@@ -1022,10 +2158,21 @@ void ICMPanel::setBatchMode(bool batchMode)
oProfNames->append(M("GENERAL_UNCHANGED"));
oRendIntent->addEntry("template-24.png", M("GENERAL_UNCHANGED"));
oRendIntent->show();
+ aRendIntent->addEntry("template-24.png", M("GENERAL_UNCHANGED"));
+ aRendIntent->show();
wProfNames->append(M("GENERAL_UNCHANGED"));
wTRC->append(M("GENERAL_UNCHANGED"));
+ will->append(M("GENERAL_UNCHANGED"));
+ wprim->append(M("GENERAL_UNCHANGED"));
dcpIll->append(M("GENERAL_UNCHANGED"));
wGamma->showEditedCB();
wSlope->showEditedCB();
+ redx->showEditedCB();
+ redy->showEditedCB();
+ grex->showEditedCB();
+ grey->showEditedCB();
+ blux->showEditedCB();
+ bluy->showEditedCB();
+ preser->showEditedCB();
}
diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h
index 81a011c59..063da28d1 100644
--- a/rtgui/icmpanel.h
+++ b/rtgui/icmpanel.h
@@ -36,24 +36,38 @@ public:
virtual void saveInputICCReference(const Glib::ustring& fname, bool apply_wb) = 0;
};
+class LabGrid;
+
class ICMPanel final :
public ToolParamBlock,
- public AdjusterListener,
- public FoldableToolPanel
+ public FoldableToolPanel,
+ public rtengine::AutoprimListener,
+ public AdjusterListener
{
protected:
Gtk::Frame* dcpFrame;
Gtk::Frame* coipFrame;
+ Gtk::Frame* redFrame;
Adjuster* wGamma;
Adjuster* wSlope;
+ Adjuster* redx;
+ Adjuster* redy;
+ Adjuster* grex;
+ Adjuster* grey;
+ Adjuster* blux;
+ Adjuster* bluy;
+ Adjuster* preser;
Gtk::Label* labmga;
Gtk::Box* gabox;
+ Gtk::Label* blr;
+ Gtk::Label* blg;
+ Gtk::Label* blb;
+ Gtk::Button* neutral;
-
- //bool freegamma;
+ sigc::connection neutralconn;
bool lastToneCurve;
sigc::connection tcurveconn;
bool lastApplyLookTable;
@@ -64,6 +78,8 @@ protected:
sigc::connection hsmconn;
bool lastobpc;
sigc::connection obpcconn;
+ bool lastfbw;
+ sigc::connection fbwconn;
bool isBatchMode;
private:
@@ -79,9 +95,34 @@ private:
rtengine::ProcEvent EvICMgamm;
rtengine::ProcEvent EvICMslop;
rtengine::ProcEvent EvICMtrcinMethod;
+ rtengine::ProcEvent EvICMwillMethod;
+ rtengine::ProcEvent EvICMwprimMethod;
+ rtengine::ProcEvent EvICMredx;
+ rtengine::ProcEvent EvICMredy;
+ rtengine::ProcEvent EvICMgrex;
+ rtengine::ProcEvent EvICMgrey;
+ rtengine::ProcEvent EvICMblux;
+ rtengine::ProcEvent EvICMbluy;
+ rtengine::ProcEvent EvaIntent;
+ rtengine::ProcEvent EvICMpreser;
+ rtengine::ProcEvent EvICMLabGridciexy;
+ rtengine::ProcEvent EvICMfbw;
+ LabGrid *labgridcie;
+ IdleRegister idle_register;
+ Gtk::Box* willuBox;
+ Gtk::Label* willulab;
+ Gtk::Box* wprimBox;
+ Gtk::Label* wprimlab;
+ Gtk::Label* cielab;
+ Gtk::Box* redBox;
+ Gtk::Box* greBox;
+ Gtk::Box* bluBox;
+ Gtk::Box* riaHBox;
+ Gtk::Box* preBox;
Gtk::Box* iVBox;
- Gtk::Box* wTRCHBox;
+ Gtk::Box* wTRCBox;
+ Gtk::CheckButton* fbw;
Gtk::CheckButton* obpc;
Gtk::RadioButton* inone;
@@ -101,6 +142,12 @@ private:
sigc::connection wprofnamesconn;
MyComboBoxText* wTRC;
sigc::connection wtrcconn;
+ MyComboBoxText* will;
+ sigc::connection willconn;
+ MyComboBoxText* wprim;
+ sigc::connection wprimconn;
+ std::unique_ptr aRendIntent;
+ sigc::connection arendintentconn;
MyComboBoxText* oProfNames;
sigc::connection oprofnamesconn;
@@ -113,26 +160,44 @@ private:
sigc::connection ipc;
Glib::ustring oldip;
ICMPanelListener* icmplistener;
-
+
double dcpTemperatures[2];
Glib::ustring lastRefFilename;
Glib::ustring camName;
void updateDCP(int dcpIlluminant, Glib::ustring dcp_name);
void updateRenderingIntent(const Glib::ustring &profile);
+
+ float nextrx;
+ float nextry;
+ float nextbx;
+ float nextby;
+ float nextgx;
+ float nextgy;
+ float nextwx;
+ float nextwy;
+
public:
ICMPanel();
+ ~ICMPanel() override;
void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override;
void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override;
void setBatchMode(bool batchMode) override;
void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override;
void adjusterChanged(Adjuster* a, double newval) override;
+ void primChanged (float rx, float ry, float bx, float by, float gx, float gy) override;
+ void iprimChanged (float r_x, float r_y, float b_x, float b_y, float g_x, float g_y, float w_x, float w_y) override;
+ void neutral_pressed();
void wpChanged();
void wtrcinChanged();
+ void willChanged();
+ void wprimChanged();
void opChanged();
void oiChanged(int n);
+ void aiChanged(int n);
void oBPCChanged();
+ void fbwChanged();
void ipChanged();
void ipSelectionChanged();
void dcpIlluminantChanged();
@@ -143,9 +208,13 @@ public:
void setRawMeta(bool raw, const rtengine::FramesData* pMeta);
void saveReferencePressed();
+ void setListener(ToolPanelListener* tpl) override;
+ void setEditProvider(EditDataProvider *provider) override;
void setICMPanelListener(ICMPanelListener* ipl)
{
icmplistener = ipl;
}
+
};
+
diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc
index 37ed20207..675da51c6 100644
--- a/rtgui/inspector.cc
+++ b/rtgui/inspector.cc
@@ -21,6 +21,7 @@
#include
#include "cursormanager.h"
#include "guiutils.h"
+#include "multilangmgr.h"
#include "options.h"
#include "pathutils.h"
#include "rtscalable.h"
@@ -82,7 +83,7 @@ InspectorBuffer::~InspectorBuffer() {
// return deg;
//}
-Inspector::Inspector () : currImage(nullptr), scaled(false), scale(1.0), zoomScale(1.0), zoomScaleBegin(1.0), active(false), pinned(false), dirty(false)
+Inspector::Inspector () : currImage(nullptr), scaled(false), scale(1.0), zoomScale(1.0), zoomScaleBegin(1.0), active(false), pinned(false), dirty(false), fullscreen(true), keyDown(false), windowShowing(false)
{
set_name("Inspector");
@@ -91,11 +92,14 @@ Inspector::Inspector () : currImage(nullptr), scaled(false), scale(1.0), zoomSca
}
else {
window = new Gtk::Window();
- window->set_title("RawTherapee Inspector");
+ window->set_name("InspectorWindow");
+ window->set_title("RawTherapee " + M("INSPECTOR_WINDOW_TITLE"));
window->set_visible(false);
window->add_events(Gdk::KEY_PRESS_MASK);
window->signal_key_release_event().connect(sigc::mem_fun(*this, &Inspector::on_key_release));
window->signal_key_press_event().connect(sigc::mem_fun(*this, &Inspector::on_key_press));
+ window->signal_hide().connect(sigc::mem_fun(*this, &Inspector::on_window_hide));
+ window->signal_window_state_event().connect(sigc::mem_fun(*this, &Inspector::on_inspector_window_state_event));
add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
gestureZoom = Gtk::GestureZoom::create(*this);
@@ -104,6 +108,7 @@ Inspector::Inspector () : currImage(nullptr), scaled(false), scale(1.0), zoomSca
window->add(*this);
window->set_size_request(500, 500);
+ window->fullscreen();
initialized = false; // delay init to avoid flickering on some systems
active = true; // always track inspected thumbnails
}
@@ -116,35 +121,40 @@ Inspector::~Inspector()
delete window;
}
-void Inspector::showWindow(bool scaled, bool fullscreen)
+void Inspector::showWindow(bool pinned, bool scaled)
{
- if (!window)
+ if (!window || windowShowing)
return;
// initialize when shown first
if (!initialized) {
window->show_all();
- window->set_visible(false);
initialized = true;
}
// show inspector window
this->scaled = scaled;
- if (fullscreen)
- window->fullscreen();
- else
- window->unfullscreen();
- this->fullscreen = fullscreen;
window->set_visible(true);
- pinned = false;
+ this->pinned = pinned;
+ windowShowing = true;
// update content when becoming visible
switchImage(next_image_path);
mouseMove(next_image_pos, 0);
}
+void Inspector::hideWindow()
+{
+ if (!window) {
+ return;
+ }
+ window->set_visible(false);
+}
+
bool Inspector::on_key_release(GdkEventKey *event)
{
+ keyDown = false;
+
if (!window)
return false;
@@ -165,6 +175,12 @@ bool Inspector::on_key_press(GdkEventKey *event)
if (!window)
return false;
+ if (keyDown) {
+ return true;
+ }
+
+ keyDown = true;
+
switch (event->keyval) {
case GDK_KEY_z:
case GDK_KEY_F:
@@ -196,9 +212,27 @@ bool Inspector::on_key_press(GdkEventKey *event)
return true;
}
+ keyDown = false;
+
return false;
}
+void Inspector::on_window_hide()
+{
+ windowShowing = false;
+}
+
+bool Inspector::on_inspector_window_state_event(GdkEventWindowState *event)
+{
+ if (!window->get_window() || window->get_window()->gobj() != event->window) {
+ return false;
+ }
+
+ fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
+
+ return true;
+}
+
bool Inspector::on_button_press_event(GdkEventButton *event)
{
if (!window)
@@ -220,13 +254,15 @@ bool Inspector::on_motion_notify_event(GdkEventMotion *event)
return false;
int deviceScale = get_scale_factor();
- int delta_x = (button_pos.x - event->x)*deviceScale;
- int delta_y = (button_pos.y - event->y)*deviceScale;
+ int event_x = round(event->x);
+ int event_y = round(event->y);
+ int delta_x = (button_pos.x - event_x) * deviceScale;
+ int delta_y = (button_pos.y - event_y) * deviceScale;
int imW = currImage->imgBuffer.getWidth();
int imH = currImage->imgBuffer.getHeight();
moveCenter(delta_x, delta_y, imW, imH, deviceScale);
- button_pos.set(event->x, event->y);
+ button_pos.set(event_x, event_y);
if (!dirty) {
dirty = true;
@@ -241,6 +277,8 @@ bool Inspector::on_scroll_event(GdkEventScroll *event)
if (!currImage || !window)
return false;
+ pinned = true;
+
bool alt = event->state & GDK_MOD1_MASK;
int deviceScale = get_scale_factor();
int imW = currImage->imgBuffer.getWidth();
@@ -309,8 +347,8 @@ void Inspector::moveCenter(int delta_x, int delta_y, int imW, int imH, int devic
rtengine::Coord margin; // limit to image size
margin.x = rtengine::min(window->get_width() * deviceScale / scale, imW) / 2;
margin.y = rtengine::min(window->get_height() * deviceScale / scale, imH) / 2;
- center.set(rtengine::LIM(center.x + delta_x, margin.x, imW - margin.x),
- rtengine::LIM(center.y + delta_y, margin.y, imH - margin.y));
+ center.set(rtengine::LIM(center.x + delta_x / scale, margin.x, imW - margin.x),
+ rtengine::LIM(center.y + delta_y / scale, margin.y, imH - margin.y));
}
void Inspector::beginZoom(double x, double y)
@@ -326,8 +364,17 @@ void Inspector::beginZoom(double x, double y)
moveCenter(0, 0, imW, imH, deviceScale);
// store center and current position for zooming
- dcenterBegin.x = (x - window->get_width()/2) / scale * deviceScale;
- dcenterBegin.y = (y - window->get_height()/2) / scale * deviceScale;
+ double cur_scale = zoomScale;
+ if (scaled) {
+ Glib::RefPtr win = get_window();
+ double winW = win->get_width() * deviceScale;
+ double winH = win->get_height() * deviceScale;
+ int imW = rtengine::max(currImage->imgBuffer.getWidth(), 1);
+ int imH = rtengine::max(currImage->imgBuffer.getHeight(), 1);
+ cur_scale *= rtengine::min(winW / imW, winH / imH);
+ }
+ dcenterBegin.x = (x - window->get_width() / 2.) / cur_scale * deviceScale;
+ dcenterBegin.y = (y - window->get_height() / 2.) / cur_scale * deviceScale;
centerBegin = center;
zoomScaleBegin = zoomScale;
@@ -336,6 +383,7 @@ void Inspector::beginZoom(double x, double y)
void Inspector::on_zoom_begin(GdkEventSequence *s)
{
double x, y;
+ pinned = true;
if (gestureZoom->get_point(s, x, y))
beginZoom(x, y);
}
@@ -378,15 +426,16 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
// this will eventually create/update the off-screen pixmap
// compute the displayed area
- rtengine::Coord availableSize;
- rtengine::Coord topLeft;
- rtengine::Coord dest(0, 0);
+ rtengine::Coord2D availableSize;
+ rtengine::Coord2D topLeft;
+ rtengine::Coord topLeftInt;
+ rtengine::Coord2D dest(0, 0);
int deviceScale = window? get_scale_factor(): 1;
availableSize.x = win->get_width() * deviceScale;
availableSize.y = win->get_height() * deviceScale;
int imW = rtengine::max(currImage->imgBuffer.getWidth(), 1);
int imH = rtengine::max(currImage->imgBuffer.getHeight(), 1);
- scale = rtengine::min((double)availableSize.x / imW, (double)availableSize.y / imH);
+ scale = rtengine::min(1., rtengine::min(availableSize.x / imW, availableSize.y / imH));
if (scaled) {
// reduce size of image to fit into window, no further zoom down
zoomScale = rtengine::max(zoomScale, 1.0);
@@ -403,33 +452,36 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
if (imW < availableSize.x) {
// center the image in the available space along X
topLeft.x = 0;
- dest.x = (availableSize.x - imW) / 2;
+ dest.x = (availableSize.x - imW) / 2.;
} else {
// partial image display
// double clamp
- topLeft.x = center.x + availableSize.x / 2;
- topLeft.x = rtengine::min(topLeft.x, imW);
+ topLeft.x = center.x + availableSize.x / 2.;
+ topLeft.x = rtengine::min(topLeft.x, imW);
topLeft.x -= availableSize.x;
- topLeft.x = rtengine::max(topLeft.x, 0);
+ topLeft.x = rtengine::max(topLeft.x, 0);
}
if (imH < availableSize.y) {
// center the image in the available space along Y
topLeft.y = 0;
- dest.y = (availableSize.y - imH) / 2;
+ dest.y = (availableSize.y - imH) / 2.;
} else {
// partial image display
// double clamp
- topLeft.y = center.y + availableSize.y / 2;
- topLeft.y = rtengine::min(topLeft.y, imH);
+ topLeft.y = center.y + availableSize.y / 2.;
+ topLeft.y = rtengine::min(topLeft.y, imH);
topLeft.y -= availableSize.y;
- topLeft.y = rtengine::max(topLeft.y, 0);
+ topLeft.y = rtengine::max(topLeft.y, 0);
}
//printf("center: %d, %d (img: %d, %d) (availableSize: %d, %d) (topLeft: %d, %d)\n", center.x, center.y, imW, imH, availableSize.x, availableSize.y, topLeft.x, topLeft.y);
+ topLeftInt.x = floor(topLeft.x);
+ topLeftInt.y = floor(topLeft.y);
+
// define the destination area
- currImage->imgBuffer.setDrawRectangle(win, dest.x, dest.y, rtengine::min(availableSize.x - dest.x, imW), rtengine::min(availableSize.y - dest.y, imH), false);
- currImage->imgBuffer.setSrcOffset(topLeft.x, topLeft.y);
+ currImage->imgBuffer.setDrawRectangle(win, dest.x, dest.y, rtengine::min(ceil(availableSize.x + (topLeft.x - topLeftInt.x) - 2 * dest.x), imW), rtengine::min(ceil(availableSize.y + (topLeft.y - topLeftInt.y) - 2 * dest.y), imH), false);
+ currImage->imgBuffer.setSrcOffset(topLeftInt.x, topLeftInt.y);
if (!currImage->imgBuffer.surfaceCreated()) {
return false;
@@ -444,15 +496,6 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
// draw the background
style->render_background(cr, 0, 0, get_width(), get_height());
}
- else {
- ///* --- old method (the new method does not seem to work)
- c = style->get_background_color (Gtk::STATE_FLAG_NORMAL);
- cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue());
- cr->set_line_width (0);
- cr->rectangle (0, 0, availableSize.x, availableSize.y);
- cr->fill ();
- //*/
- }
bool scaledImage = scale != 1.0;
if (!window || (deviceScale == 1 && !scaledImage)) {
@@ -462,20 +505,26 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
else {
// consider device scale and image scale
if (deviceScale > 1) {
+#ifdef __APPLE__
// use full device resolution and let it scale the image (macOS)
cairo_surface_set_device_scale(cr->get_target()->cobj(), scale, scale);
scaledImage = false;
+#else
+ cr->scale(1. / deviceScale, 1. / deviceScale);
+#endif
}
- int viewW = rtengine::min(imW, availableSize.x);
- int viewH = rtengine::min(imH, availableSize.y);
- Glib::RefPtr crop = Gdk::Pixbuf::create(currImage->imgBuffer.getSurface(), topLeft.x, topLeft.y, viewW, viewH);
+ int viewW = rtengine::min(imW, ceil(availableSize.x + (topLeft.x - topLeftInt.x)));
+ int viewH = rtengine::min(imH, ceil(availableSize.y + (topLeft.y - topLeftInt.y)));
+ Glib::RefPtr crop = Gdk::Pixbuf::create(currImage->imgBuffer.getSurface(), topLeftInt.x, topLeftInt.y, viewW, viewH);
if (!scaledImage) {
Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x, dest.y);
}
else {
+ double dx = scale * (dest.x + topLeftInt.x - topLeft.x);
+ double dy = scale * (dest.y + topLeftInt.y - topLeft.y);
// scale crop as the device does not seem to support it (Linux)
- crop = crop->scale_simple(viewW*scale, viewH*scale, Gdk::INTERP_BILINEAR);
- Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x*scale, dest.y*scale);
+ crop = crop->scale_simple(round(viewW*scale), round(viewH*scale), Gdk::INTERP_BILINEAR);
+ Gdk::Cairo::set_source_pixbuf(cr, crop, dx, dy);
}
cr->paint();
}
@@ -506,7 +555,7 @@ void Inspector::mouseMove (rtengine::Coord2D pos, int transform)
return;
if (currImage) {
- center.set(int(rtengine::LIM01(pos.x)*double(currImage->imgBuffer.getWidth())), int(rtengine::LIM01(pos.y)*double(currImage->imgBuffer.getHeight())));
+ center.set(rtengine::LIM01(pos.x)*double(currImage->imgBuffer.getWidth()), rtengine::LIM01(pos.y)*double(currImage->imgBuffer.getHeight()));
} else {
center.set(0, 0);
}
diff --git a/rtgui/inspector.h b/rtgui/inspector.h
index 726bc947c..5577bfb45 100644
--- a/rtgui/inspector.h
+++ b/rtgui/inspector.h
@@ -22,7 +22,6 @@
#include "guiutils.h"
-#include "../rtengine/coord.h"
#include "../rtengine/coord2d.h"
class InspectorBuffer
@@ -44,18 +43,20 @@ class Inspector final : public Gtk::DrawingArea
{
private:
- rtengine::Coord center;
+ rtengine::Coord2D center;
std::vector images;
InspectorBuffer* currImage;
bool scaled; // fit image into window
double scale; // current scale
double zoomScale, zoomScaleBegin; // scale during zoom
- rtengine::Coord centerBegin, dcenterBegin; // center during zoom
+ rtengine::Coord2D centerBegin, dcenterBegin; // center during zoom
bool active;
bool pinned;
bool dirty;
bool initialized;
bool fullscreen; // window is shown in fullscreen mode
+ bool keyDown;
+ bool windowShowing;
sigc::connection delayconn;
Glib::ustring next_image_path;
@@ -65,6 +66,9 @@ private:
bool on_key_release(GdkEventKey *event);
bool on_key_press(GdkEventKey *event);
+ void on_window_hide();
+ bool on_inspector_window_state_event(GdkEventWindowState *event);
+
rtengine::Coord button_pos;
bool on_button_press_event(GdkEventButton *event) override;
bool on_motion_notify_event(GdkEventMotion *event) override;
@@ -87,9 +91,15 @@ public:
~Inspector() override;
/** @brief Show or hide window
+ * @param pinned pin window
* @param scaled fit image into window
*/
- void showWindow(bool scaled, bool fullscreen = true);
+ void showWindow(bool pinned, bool scaled = true);
+
+ /**
+ * Hide the window.
+ */
+ void hideWindow();
/** @brief Mouse movement to a new position
* @param pos Location of the mouse, in percentage (i.e. [0;1] range) relative to the full size image ; -1,-1 == out of the image
diff --git a/rtgui/labgrid.cc b/rtgui/labgrid.cc
index d8a22b1d9..d0443d58d 100644
--- a/rtgui/labgrid.cc
+++ b/rtgui/labgrid.cc
@@ -4,6 +4,8 @@
*
* Copyright (c) 2017 Alberto Griggio
*
+ * Copyright (c) 2021 Jacques Desmis for CIE xy graph
+ *
* 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
@@ -57,22 +59,34 @@ bool LabGridArea::notifyListener()
{
return int(v * 1000) / 1000.f;
};
- listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(high_a), round(high_b), round(low_a), round(low_b)));
+ if (! ciexy_enabled){
+ listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(high_a), round(high_b), round(low_a), round(low_b)));
+ } else {
+ float high_a1 = 0.55f * (high_a + 1.f) - 0.1f;
+ float high_b1 = 0.55f * (high_b + 1.f) - 0.1f;
+ float low_a1 = 0.55f * (low_a + 1.f) - 0.1f;
+ float low_b1 = 0.55f * (low_b + 1.f) - 0.1f;
+ float gre_x1 = 0.55f * (gre_x + 1.f) - 0.1f;
+ float gre_y1 = 0.55f * (gre_y + 1.f) - 0.1f;
+ listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(low_a1), round(low_b1), round(gre_x1), round(gre_y1), round(high_a1), round(high_b1)));
+ }
}
return false;
}
-LabGridArea::LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low):
+LabGridArea::LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low, bool ciexy):
Gtk::DrawingArea(),
evt(evt), evtMsg(msg),
litPoint(NONE),
- low_a(0.f), high_a(0.f), low_b(0.f), high_b(0.f),
- defaultLow_a(0.f), defaultHigh_a(0.f), defaultLow_b(0.f), defaultHigh_b(0.f),
+ low_a(0.f), high_a(0.f), low_b(0.f), high_b(0.f), gre_x(0.f), gre_y(0.f), whi_x(0.f), whi_y(0.f),//these variables are used as xy in Ciexy - no change labels
+ defaultLow_a(0.f), defaultHigh_a(0.f), defaultLow_b(0.f), defaultHigh_b(0.f), defaultgre_x(0.f), defaultgre_y(0.f), defaultwhi_x(0.f), defaultwhi_y(0.f),
listener(nullptr),
edited(false),
isDragged(false),
- low_enabled(enable_low)
+ low_enabled(enable_low),
+ ciexy_enabled(ciexy)
+
{
set_can_focus(false); // prevent moving the grid while you're moving a point
add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK);
@@ -80,16 +94,21 @@ LabGridArea::LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool
get_style_context()->add_class("drawingarea");
}
-void LabGridArea::getParams(double &la, double &lb, double &ha, double &hb) const
+void LabGridArea::getParams(double &la, double &lb, double &ha, double &hb, double &gx, double &gy, double &wx, double &wy) const
{
la = low_a;
ha = high_a;
lb = low_b;
hb = high_b;
+ gx = gre_x;
+ gy = gre_y;
+ wx = whi_x;
+ wy = whi_y;
+ // printf("la=%f ha=%f lb=%f hb=%f gx=%f gy=%f\n", la, ha, lb, hb, gx, gy);
}
-void LabGridArea::setParams(double la, double lb, double ha, double hb, bool notify)
+void LabGridArea::setParams(double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy, bool notify)
{
const double lo = -1.0;
const double hi = 1.0;
@@ -97,27 +116,37 @@ void LabGridArea::setParams(double la, double lb, double ha, double hb, bool not
low_b = rtengine::LIM(lb, lo, hi);
high_a = rtengine::LIM(ha, lo, hi);
high_b = rtengine::LIM(hb, lo, hi);
+ gre_x = rtengine::LIM(gx, lo, hi);
+ gre_y = rtengine::LIM(gy, lo, hi);
+ whi_x = rtengine::LIM(wx, lo, hi);
+ whi_y = rtengine::LIM(wy, lo, hi);
+
queue_draw();
if (notify) {
notifyListener();
}
}
-void LabGridArea::setDefault (double la, double lb, double ha, double hb)
+void LabGridArea::setDefault (double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy)
{
defaultLow_a = la;
defaultLow_b = lb;
defaultHigh_a = ha;
defaultHigh_b = hb;
+ defaultgre_x = gx;
+ defaultgre_y = gy;
+ defaultwhi_x = wx;
+ defaultwhi_y = wy;
}
void LabGridArea::reset(bool toInitial)
{
if (toInitial) {
- setParams(defaultLow_a, defaultLow_b, defaultHigh_a, defaultHigh_b, true);
+ setParams(defaultLow_a, defaultLow_b, defaultHigh_a, defaultHigh_b, defaultgre_x, defaultgre_y, defaultwhi_x, defaultwhi_y, true);
} else {
- setParams(0., 0., 0., 0., true);
+ // printf("RESET \n");
+ setParams(0., 0., 0., 0., 0., 0., 0., 0., true);
}
}
@@ -166,6 +195,7 @@ bool LabGridArea::on_draw(const ::Cairo::RefPtr &crf)
Gtk::Border padding = getPadding(style); // already scaled
Cairo::RefPtr cr = getContext();
+
if (isDirty()) {
int width = allocation.get_width();
int height = allocation.get_height();
@@ -195,55 +225,208 @@ bool LabGridArea::on_draw(const ::Cairo::RefPtr &crf)
// flip y:
cr->translate(0, height);
cr->scale(1., -1.);
- const int cells = 8;
- float step = 12000.f / float(cells/2);
- double cellW = double(width) / double(cells);
- double cellH = double(height) / double(cells);
- double cellYMin = 0.;
- double cellYMax = std::floor(cellH);
- for (int j = 0; j < cells; j++) {
- double cellXMin = 0.;
- double cellXMax = std::floor(cellW);
- for (int i = 0; i < cells; i++) {
- float R, G, B;
- float x, y, z;
- int ii = i - cells/2;
- int jj = j - cells/2;
- float a = step * (ii + 0.5f);
- float b = step * (jj + 0.5f);
- Color::Lab2XYZ(25000.f, a, b, x, y, z);
- Color::xyz2srgb(x, y, z, R, G, B);
- cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f);
- cr->rectangle(
- cellXMin,
- cellYMin,
- cellXMax - cellXMin - (i == cells-1 ? 0. : double(s)),
- cellYMax - cellYMin - (j == cells-1 ? 0. : double(s))
- );
- cellXMin = cellXMax;
- cellXMax = std::floor(cellW * double(i+2) + 0.01);
- cr->fill();
- }
- cellYMin = cellYMax;
- cellYMax = std::floor(cellH * double(j+2) + 0.01);
- }
+ if (! ciexy_enabled) {//draw cells for Labgrid
+ int cells = 8;
+ float step = 12000.f / float(cells/2);
+ double cellW = double(width) / double(cells);
+ double cellH = double(height) / double(cells);
+ double cellYMin = 0.;
+ double cellYMax = std::floor(cellH);
+ for (int j = 0; j < cells; j++) {
+ double cellXMin = 0.;
+ double cellXMax = std::floor(cellW);
+ for (int i = 0; i < cells; i++) {
+ float R, G, B;
+ float x, y, z;
+ int ii = i - cells/2;
+ int jj = j - cells/2;
+ float a = step * (ii + 0.5f);
+ float b = step * (jj + 0.5f);
+ Color::Lab2XYZ(25000.f, a, b, x, y, z);
+ Color::xyz2srgb(x, y, z, R, G, B);
+ cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f);
+ cr->rectangle(
+ cellXMin,
+ cellYMin,
+ cellXMax - cellXMin - (i == cells-1 ? 0. : double(s)),
+ cellYMax - cellYMin - (j == cells-1 ? 0. : double(s))
+ );
+ cellXMin = cellXMax;
+ cellXMax = std::floor(cellW * double(i+2) + 0.01);
+ cr->fill();
+ }
+ cellYMin = cellYMax;
+ cellYMax = std::floor(cellH * double(j+2) + 0.01);
+ }
+ } else {//cells for CIE xy
+ int cells = 600;
+ float step = 1.f / float(cells);
+ double cellW = double(width) / double(cells);
+ double cellH = double(height) / double(cells);
+ double cellYMin = 0.;
+ double cellYMax = std::floor(cellH);
+ //various approximations to simulate Ciexy curves graph
+ // this graph is not accurate...I replace curve by polygon or parabolic
+ float xa = 0.2653f / (0.7347f - 0.17f);
+ float xb = -0.17f * xa;
+ //linaer values
+ // float ax = (0.1f - 0.6f) / 0.08f;
+ // float bx = 0.6f;
+ // float ax0 = -0.1f / (0.17f - 0.08f);
+ // float bx0 = -0.17f* ax0;
+ float axs = (0.2653f - 0.65f) / (0.7347f - 0.35f);
+ float bxs = 0.65f - axs * 0.35f;
+ // float axss = (0.7f - 0.83f) / (0.3f - 0.1f);
+ // float bxss = 0.7f - 0.3f * axss;
+ //float bxsss = 0.65f;
+ //float axsss = (0.83f - bxsss) / 0.05f;
+ //float bx4s = 0.83f;
+ float ay = 0.4f;
+ float by = 0.4f;
+ for (int j = 0; j < cells; j++) {
+ double cellXMin = 0.;
+ double cellXMax = std::floor(cellW);
+ for (int i = 0; i < cells; i++) {
+ float R, G, B;
+ float XX, YY, ZZ;
+ float x = 1.1f * step * i - 0.1f;//Graph CIExy with -0.1 to 1 - must be enough
+ float y = 1.1f * step * j - 0.1;//Graph CIExy with -0.1 to 1 - must be enough
+ if(y > 0.5f) {
+ YY = 0.6f;
+ } else {
+ YY = ay * y + by;
+ }
+ XX = (x * YY) / y;
+ ZZ = ((1.f - x - y)* YY) / y;
+ float yr = xa * x + xb;
+ // float y0 = ax0 * x + bx0;
+ // float y1 = ax * x + bx;
+ float y2 = axs * x + bxs;
+ // float y3 = axss * x + bxss;
+ // float y4 = axsss * x + bxsss;
+ // float y5 = bx4s;
+ float y6 = 22.52f * x * x - 7.652f * x + 0.65f;//parabolic passing in x=0.17 y=0 - x=0.1 y =0.11 - x=0 y= 0.65
+ float y3 = -1.266666f * x * x -0.170002f * x + 0.859686f;//other parabolic for green passing in x=0.35 y=0.65 - x=0.20 y=0.775 - x=0.1 y=0.83
+ float y4 = -60.71428f * x * x + 6.821428f * x + 0.65f;//other parabolic x=0 y=0.65 - x=0.03 y=0.8 - x=0.07 y=0.83
+ //small difference in the connection of the 2 last parabolic
+
+ Color::xyz2srgb(XX, YY, ZZ, R, G, B);
+ //replace color by gray
+ if(y < yr && x > 0.17f) {
+ R = 0.7f; G = 0.7f; B = 0.7f;
+ }
+ /*
+ if(y < y0 && x <= 0.17f && x >= 0.08f) {
+ R = 0.7f; G = 0.7f; B = 0.7f;
+ }
+ if(y < y1 && x < 0.08f) {
+ R = 0.7f; G = 0.7f; B = 0.7f;
+ }
+ */
+ if(y < y6 && y < 0.65f && x < 0.17f) {
+ R = 0.7f; G = 0.7f; B = 0.7f;
+ }
+
+ if(y > y2 && x > 0.35f) {//0.35
+ R = 0.7f; G = 0.7f; B = 0.7f;
+ }
+ if(y > y3 && x <= 0.35f && x > 0.06f) {//0.35
+ R = 0.7f; G = 0.7f; B = 0.7f;
+ }
+ if(y > y4 && x <= 0.06f) {
+ R = 0.7f; G = 0.7f; B = 0.7f;
+ }
+ // if(y > y5 && x >= 0.07f && x <= 0.1f) {
+ // R = 0.7f; G = 0.7f; B = 0.7f;
+ // }
+
+ cr->set_source_rgb(R , G , B);
+
+ cr->rectangle(
+ cellXMin,
+ cellYMin,
+ cellXMax - cellXMin - (i == cells-1 ? 0. : 0.f * double(s)),
+ cellYMax - cellYMin - (j == cells-1 ? 0. : 0.f * double(s))
+ );
+ cellXMin = cellXMax;
+ cellXMax = std::floor(cellW * double(i+2) + 0.001);
+ cr->fill();
+ }
+ cellYMin = cellYMax;
+ cellYMax = std::floor(cellH * double(j+2) + 0.001);
+ }
+ }
// drawing the connection line
cr->set_antialias(Cairo::ANTIALIAS_DEFAULT);
- float loa, hia, lob, hib;
+ float loa, hia, lob, hib, grx, gry, whx, why;
loa = .5 * (width + width * low_a);
hia = .5 * (width + width * high_a);
lob = .5 * (height + height * low_b);
hib = .5 * (height + height * high_b);
- cr->set_line_width(2. * double(s));
+ grx = .5 * (width + width * gre_x);
+ gry = .5 * (height + height * gre_y);
+ whx = .5 * (width + width * whi_x);
+ why = .5 * (height + height * whi_y);
+ cr->set_line_width(1.5f * double(s));
cr->set_source_rgb(0.6, 0.6, 0.6);
cr->move_to(loa, lob);
cr->line_to(hia, hib);
+ if (ciexy_enabled) {
+ cr->move_to(loa, lob);
+ cr->line_to(grx, gry);
+ cr->move_to(grx, gry);
+ cr->line_to(hia, hib);
+ }
cr->stroke();
+ if (ciexy_enabled) {
+ //to convert from / to Ciexy <=> area
+ // pos_area = 1.81818 * (x + 0.1) - 1
+ // x = 0.55 * (pos_area + 1) - 0.1
+ cr->set_line_width(0.2f * double(s));
+ cr->set_source_rgb(0.1, 0.1, 0.1);
+ //draw horiz and vertical lines
+ for(int i = 0; i < 22; i++) {
+ cr->move_to(0.04545 * i * width, 0.);
+ cr->line_to(0.04545 * i * width, height);
+ }
+ for(int i = 0; i < 22; i++) {
+ cr->move_to(0., 0.04545 * i * height );
+ cr->line_to(width, 0.04545 * i * height);
+ }
+
+ cr->stroke();
+ //draw abciss and ordonate
+ cr->set_line_width(1.f * double(s));
+ cr->set_source_rgb(0.4, 0., 0.);
+ cr->move_to(0.04545 * 2 * width, 0.);
+ cr->line_to(0.04545 * 2 * width, height);
+ cr->move_to(0., 0.04545 * 2 * height );
+ cr->line_to(width, 0.04545 * 2 * height);
+ cr->stroke();
+
+ //draw 0 and 1 with circle and lines
+ cr->set_line_width(1.2f * double(s));
+ cr->set_source_rgb(0.4, 0., 0.);
+ cr->arc(0.06 * width, 0.06 * height, 0.016 * width, 0, 2. * rtengine::RT_PI);
+ cr->stroke();
+ cr->set_line_width(1.5f * double(s));
+ cr->set_source_rgb(0.4, 0., 0.);
+ cr->move_to(0.985 * width, 0.08 * height);
+ cr->line_to(0.985 * width, 0.055 * height);
+
+ cr->move_to(0.07 * width, 0.99 * height);
+ cr->line_to(0.07 * width, 0.965 * height);
+
+ cr->stroke();
+
+ }
+
+
// drawing points
if (low_enabled) {
- cr->set_source_rgb(0.1, 0.1, 0.1);
+ cr->set_source_rgb(0.1, 0.1, 0.1);//black for red in Ciexy
if (litPoint == LOW) {
cr->arc(loa, lob, 5 * s, 0, 2. * rtengine::RT_PI);
} else {
@@ -252,7 +435,23 @@ bool LabGridArea::on_draw(const ::Cairo::RefPtr &crf)
cr->fill();
}
- cr->set_source_rgb(0.9, 0.9, 0.9);
+ if (ciexy_enabled) {
+ cr->set_source_rgb(0.5, 0.5, 0.5);//gray for green
+ if (litPoint == GRE) {
+ cr->arc(grx, gry, 5 * s, 0, 2. * rtengine::RT_PI);
+ } else {
+ cr->arc(grx, gry, 3 * s, 0, 2. * rtengine::RT_PI);
+ }
+ cr->fill();
+ }
+
+ if (ciexy_enabled) {//White Point
+ cr->set_source_rgb(1., 1., 1.);//White
+ cr->arc(whx, why, 3 * s, 0, 2. * rtengine::RT_PI);
+ cr->fill();
+ }
+
+ cr->set_source_rgb(0.9, 0.9, 0.9);//white for blue en Ciexy
if (litPoint == HIGH) {
cr->arc(hia, hib, 5 * s, 0, 2. * rtengine::RT_PI);
} else {
@@ -269,10 +468,11 @@ bool LabGridArea::on_draw(const ::Cairo::RefPtr &crf)
bool LabGridArea::on_button_press_event(GdkEventButton *event)
{
if (event->button == 1) {
+ if (!ciexy_enabled) {
if (event->type == GDK_2BUTTON_PRESS) {
switch (litPoint) {
case NONE:
- low_a = low_b = high_a = high_b = 0.f;
+ low_a = low_b = high_a = high_b = gre_x = gre_y = 0.f;
break;
case LOW:
low_a = low_b = 0.f;
@@ -280,6 +480,9 @@ bool LabGridArea::on_button_press_event(GdkEventButton *event)
case HIGH:
high_a = high_b = 0.f;
break;
+ case GRE:
+ gre_x = gre_y = 0.f;
+ break;
}
edited = true;
notifyListener();
@@ -287,6 +490,16 @@ bool LabGridArea::on_button_press_event(GdkEventButton *event)
} else if (event->type == GDK_BUTTON_PRESS && litPoint != NONE) {
isDragged = true;
}
+ } else {
+ if (event->type == GDK_2BUTTON_PRESS) {
+ edited = true;
+ notifyListener();
+ queue_draw();
+ } else if (event->type == GDK_BUTTON_PRESS && litPoint != NONE) {
+ isDragged = true;
+ }
+
+ }
return false;
}
return true;
@@ -328,6 +541,9 @@ bool LabGridArea::on_motion_notify_event(GdkEventMotion *event)
} else if (litPoint == HIGH) {
high_a = ma;
high_b = mb;
+ } else if (litPoint == GRE) {
+ gre_x = ma;
+ gre_y = mb;
}
edited = true;
grab_focus();
@@ -343,13 +559,18 @@ bool LabGridArea::on_motion_notify_event(GdkEventMotion *event)
float lb = low_b;
float ha = high_a;
float hb = high_b;
+ float gx = gre_x;
+ float gy = gre_y;
const float thrs = 0.05f;
const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb);
const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb);
+ const float distgxy = (gx - ma) * (gx - ma) + (gy - mb) * (gy - mb);
if (low_enabled && distlo < thrs * thrs && distlo < disthi) {
litPoint = LOW;
} else if (disthi < thrs * thrs && disthi <= distlo) {
litPoint = HIGH;
+ } else if (ciexy_enabled && distgxy < thrs * thrs && distgxy <= distlo) {
+ litPoint = GRE;
}
if ((oldLitPoint == NONE && litPoint != NONE) || (oldLitPoint != NONE && litPoint == NONE)) {
queue_draw();
@@ -391,6 +612,10 @@ bool LabGridArea::lowEnabled() const
return low_enabled;
}
+bool LabGridArea::ciexyEnabled() const
+{
+ return ciexy_enabled;
+}
void LabGridArea::setLowEnabled(bool yes)
{
@@ -400,17 +625,26 @@ void LabGridArea::setLowEnabled(bool yes)
}
}
+void LabGridArea::setciexyEnabled(bool yes)
+{
+ if (ciexy_enabled != yes) {
+ ciexy_enabled = yes;
+ queue_draw();
+ }
+}
//-----------------------------------------------------------------------------
// LabGrid
//-----------------------------------------------------------------------------
-LabGrid::LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low):
- grid(evt, msg, enable_low)
+LabGrid::LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low, bool ciexy):
+ grid(evt, msg, enable_low, ciexy)
{
Gtk::Button *reset = Gtk::manage(new Gtk::Button());
reset->set_tooltip_markup(M("ADJUSTER_RESET_TO_DEFAULT"));
- reset->add(*Gtk::manage(new RTImage("undo-small.png", "redo-small.png")));
+ if(!ciexy) {//disabled for Cie xy
+ reset->add(*Gtk::manage(new RTImage("undo-small.png", "redo-small.png")));
+ }
reset->signal_button_release_event().connect(sigc::mem_fun(*this, &LabGrid::resetPressed));
setExpandAlignProperties(reset, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START);
diff --git a/rtgui/labgrid.h b/rtgui/labgrid.h
index 78179210c..0ed4cdf98 100644
--- a/rtgui/labgrid.h
+++ b/rtgui/labgrid.h
@@ -48,17 +48,25 @@ private:
rtengine::ProcEvent evt;
Glib::ustring evtMsg;
- enum State { NONE, HIGH, LOW };
+ enum State { NONE, HIGH, LOW, GRE};
State litPoint;
double low_a;
double high_a;
double low_b;
double high_b;
-
+ double gre_x;
+ double gre_y;
+ double whi_x;
+ double whi_y;
+
double defaultLow_a;
double defaultHigh_a;
double defaultLow_b;
double defaultHigh_b;
+ double defaultgre_x;
+ double defaultgre_y;
+ double defaultwhi_x;
+ double defaultwhi_y;
ToolPanelListener *listener;
bool edited;
@@ -67,16 +75,17 @@ private:
static const int inset = 5;
bool low_enabled;
+ bool ciexy_enabled;
bool notifyListener();
void getLitPoint();
public:
- LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true);
+ LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true, bool ciexy=false);
- void getParams(double &la, double &lb, double &ha, double &hb) const;
- void setParams(double la, double lb, double ha, double hb, bool notify);
- void setDefault (double la, double lb, double ha, double hb);
+ void getParams(double &la, double &lb, double &ha, double &hb, double &gx, double &gy, double &wx, double &wy) const;
+ void setParams(double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy, bool notify);
+ void setDefault (double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy);
void setEdited(bool yes);
bool getEdited() const;
void reset(bool toInitial);
@@ -84,6 +93,8 @@ public:
bool lowEnabled() const;
void setLowEnabled(bool yes);
+ bool ciexyEnabled() const;
+ void setciexyEnabled(bool yes);
bool on_draw(const ::Cairo::RefPtr &crf) override;
void on_style_updated () override;
@@ -103,16 +114,18 @@ private:
bool resetPressed(GdkEventButton *event);
public:
- LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true);
+ LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true, bool ciexy=false);
- void getParams(double &la, double &lb, double &ha, double &hb) const { return grid.getParams(la, lb, ha, hb); }
- void setParams(double la, double lb, double ha, double hb, bool notify) { grid.setParams(la, lb, ha, hb, notify); }
- void setDefault (double la, double lb, double ha, double hb) { grid.setDefault(la, lb, ha, hb); }
+ void getParams(double &la, double &lb, double &ha, double &hb, double &gx, double &gy, double &wx, double &wy) const { return grid.getParams(la, lb, ha, hb, gx, gy, wx, wy); }
+ void setParams(double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy, bool notify) { grid.setParams(la, lb, ha, hb, gx, gy, wx, wy, notify); }
+ void setDefault (double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy) { grid.setDefault(la, lb, ha, hb, gx, gy, wx, wy); }
void setEdited(bool yes) { grid.setEdited(yes); }
bool getEdited() const { return grid.getEdited(); }
void reset(bool toInitial) { grid.reset(toInitial); }
void setListener(ToolPanelListener *l) { grid.setListener(l); }
bool lowEnabled() const { return grid.lowEnabled(); }
void setLowEnabled(bool yes) { grid.setLowEnabled(yes); }
+ bool ciexyEnabled() const { return grid.ciexyEnabled(); }
+ void setciexyEnabled(bool yes) { grid.setciexyEnabled(yes); }
};
diff --git a/rtgui/lensgeomlistener.h b/rtgui/lensgeomlistener.h
index b9979f9a2..7f437c170 100644
--- a/rtgui/lensgeomlistener.h
+++ b/rtgui/lensgeomlistener.h
@@ -35,5 +35,4 @@ public:
virtual void autoCropRequested () = 0;
virtual double autoDistorRequested () = 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 e1eca81c5..6f59d3b0f 100644
--- a/rtgui/locallab.cc
+++ b/rtgui/locallab.cc
@@ -740,6 +740,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited
} else {
r->shapeMethod = 3;
}
+ //printf("n0=%f n1=%f n2=%f n3=%f\n", (double) newSpot->loc.at(0), (double) newSpot->loc.at(1), (double) newSpot->loc.at(2), (double) newSpot->loc.at(3));
// Calculate spot size and center position according to preview area
if (provider && !batchMode) {
@@ -752,17 +753,27 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited
newSpot->centerX = rtengine::LIM(int(int((double)prX - (double)imW / 2.) * 2000. / (double)imW), -1000, 1000);
newSpot->centerY = rtengine::LIM(int(int((double)prY - (double)imH / 2.) * 2000. / (double)imH), -1000, 1000);
// Ellipse/rectangle size computation
+ /*
newSpot->loc.at(0) = rtengine::LIM(int(((double)prW / 2. - 5.) * 2000. / (double)imW), 2, newSpot->loc.at(0));
newSpot->loc.at(1) = rtengine::LIM(int(((double)prW / 2. - 5.) * 2000. / (double)imW), 2, newSpot->loc.at(1));
newSpot->loc.at(2) = rtengine::LIM(int(((double)prH / 2. - 5.) * 2000. / (double)imH), 2, newSpot->loc.at(2));
newSpot->loc.at(3) = rtengine::LIM(int(((double)prH / 2. - 5.) * 2000. / (double)imH), 2, newSpot->loc.at(3));
+ */
}
}
- r->locX = newSpot->loc.at(0);
- r->locXL = newSpot->loc.at(1);
- r->locY = newSpot->loc.at(2);
- r->locYT = newSpot->loc.at(3);
+ if(r->spotMethod != 2) {
+ r->locX = newSpot->loc.at(0);
+ r->locXL = newSpot->loc.at(1);
+ r->locY = newSpot->loc.at(2);
+ r->locYT = newSpot->loc.at(3);
+ } else {
+ r->locX = 3000.;
+ r->locXL = 3000.;
+ r->locY = 3000.;
+ r->locYT = 3000.;
+ }
+
r->centerX = newSpot->centerX;
r->centerY = newSpot->centerY;
diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc
index c0988ca37..14a3a43c4 100644
--- a/rtgui/locallabtools.cc
+++ b/rtgui/locallabtools.cc
@@ -132,28 +132,29 @@ LocallabTool::LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustr
complexity(Gtk::manage(new MyComboBoxText()))
{
// Create expander title bar
+ Gtk::Box *titVBox;
+ titVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+ titVBox->set_spacing(2);
+
Gtk::Box* const titleBox = Gtk::manage(new Gtk::Box());
Gtk::Label* const titleLabel = Gtk::manage(new Gtk::Label());
titleLabel->set_markup(Glib::ustring("") + escapeHtmlChars(UILabel) + Glib::ustring(""));
titleLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
titleBox->pack_start(*titleLabel, Gtk::PACK_EXPAND_WIDGET, 0);
-
+
Gtk::EventBox* const removeEvBox = Gtk::manage(new Gtk::EventBox()); // Glue to manage mouse clicking event on remove image
removeEvBox->set_can_focus(false);
removeEvBox->set_above_child(false); // To have priority over expander title bar when mouse clicking on remove image
removeEvBox->signal_button_release_event().connect(sigc::mem_fun(this, &LocallabTool::on_remove_change));
RTImage* const removeImage = Gtk::manage(new RTImage("cancel-small.png"));
removeEvBox->add(*removeImage);
- titleBox->pack_end(*removeEvBox, Gtk::PACK_SHRINK, 4);
-
+ titleBox->pack_end(*removeEvBox, Gtk::PACK_SHRINK, 1);
if (needMode) {
complexity->append(M("TP_LOCALLAB_MODE_EXPERT"));
complexity->append(M("TP_LOCALLAB_MODE_NORMAL"));
complexity->append(M("TP_LOCALLAB_MODE_SIMPLE"));
complexity->set_active(2);
- complexity->setPreferredWidth(100, -1);
complexityConn = complexity->signal_changed().connect(sigc::mem_fun(*this, &LocallabTool::complexityModeChanged));
- titleBox->pack_end(*complexity, Gtk::PACK_SHRINK, 2);
}
Gtk::Separator* const separator = Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL));
@@ -164,8 +165,10 @@ LocallabTool::LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustr
titleImage->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP"));
titleBox->pack_end(*titleImage, Gtk::PACK_SHRINK, 0);
}
+ titVBox->pack_start(*titleBox, Gtk::PACK_SHRINK, 1);
+ titVBox->pack_start(*complexity, Gtk::PACK_SHRINK, 1);
- exp = Gtk::manage(new MyExpander(true, titleBox));
+ exp = Gtk::manage(new MyExpander(true, titVBox));
exp->signal_button_release_event().connect_notify(sigc::mem_fun(this, &LocallabTool::foldThemAll));
enaExpConn = exp->signal_enabled_toggled().connect(sigc::mem_fun(*this, &LocallabTool::enabledChanged));
@@ -413,12 +416,13 @@ LocallabColor::LocallabColor():
// Color & Light specific widgets
lumFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LUMFRA")))),
+ reparcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LOGREPART"), 1.0, 100.0, 1., 100.0))),
lightness(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LIGHTNESS"), -100, 500, 1, 0))),
contrast(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTRAST"), -100, 100, 1, 0))),
chroma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMA"), -100, 150, 1, 0))),
curvactiv(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_CURV")))),
gridFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABGRID")))),
- labgrid(Gtk::manage(new LabGrid(EvLocallabLabGridValue, M("TP_LOCALLAB_LABGRID_VALUES")))),
+ labgrid(Gtk::manage(new LabGrid(EvLocallabLabGridValue, M("TP_LOCALLAB_LABGRID_VALUES"), true, false))),
gridMethod(Gtk::manage(new MyComboBoxText())),
strengthgrid(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRGRID"), 0, 100, 1, 30))),
sensi(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))),
@@ -448,11 +452,11 @@ LocallabColor::LocallabColor():
clshape(static_cast(clCurveEditorG->addCurve(CT_Diagonal, "C(L)"))),
lcshape(static_cast(clCurveEditorG->addCurve(CT_Diagonal, "L(C)"))),
HCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))),
- LHshape(static_cast(HCurveEditorG->addCurve(CT_Flat, "L(H)", nullptr, false, true))),
+ LHshape(static_cast(HCurveEditorG->addCurve(CT_Flat, "L(h)", nullptr, false, true))),
H3CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))),
- CHshape(static_cast(H3CurveEditorG->addCurve(CT_Flat, "C(H)", nullptr, false, true))),
+ CHshape(static_cast(H3CurveEditorG->addCurve(CT_Flat, "C(h)", nullptr, false, true))),
H2CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))),
- HHshape(static_cast(H2CurveEditorG->addCurve(CT_Flat, "H(H)", nullptr, false, true))),
+ HHshape(static_cast(H2CurveEditorG->addCurve(CT_Flat, "h(h)", nullptr, false, true))),
rgbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_RGB"))),
toneMethod(Gtk::manage(new MyComboBoxText())),
rgbshape(static_cast(rgbCurveEditorG->addCurve(CT_Diagonal, "", toneMethod))),
@@ -472,10 +476,11 @@ LocallabColor::LocallabColor():
showmaskcolMethod(Gtk::manage(new MyComboBoxText())),
showmaskcolMethodinv(Gtk::manage(new MyComboBoxText())),
enaColorMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))),
- maskCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))),
- CCmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))),
- LLmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))),
- HHmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))),
+// maskCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))),
+ maskCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir,"", 1)),
+ CCmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
+ LLmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
+ HHmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))),
struFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABSTRUM")))),
strumaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUMASKCOL"), 0., 200., 0.1, 0.))),
toolcol(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_TOOLCOL")))),
@@ -485,14 +490,16 @@ LocallabColor::LocallabColor():
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")))),
+ toolcolFrame2(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK_2")))),
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.))),
gammaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))),
slomaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))),
shadmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHAMASKCOL"), 0, 100, 1, 0))),
- maskHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKH"))),
- HHhmaskshape(static_cast(maskHCurveEditorG->addCurve(CT_Flat, "H(H)", nullptr, false, true))),
+ // maskHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKH"))),
+ maskHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "")),
+ HHhmaskshape(static_cast(maskHCurveEditorG->addCurve(CT_Flat, "h(h)", nullptr, false, true))),
mask2CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))),
Lmaskshape(static_cast(mask2CurveEditorG->addCurve(CT_Diagonal, "L(L)"))),
mask2CurveEditorGwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))),
@@ -519,6 +526,8 @@ LocallabColor::LocallabColor():
lightness->setAdjusterListener(this);
+ reparcol->setAdjusterListener(this);
+
contrast->setAdjusterListener(this);
chroma->setAdjusterListener(this);
@@ -781,6 +790,8 @@ LocallabColor::LocallabColor():
csThresholdcol->setAdjusterListener(this);
// Add Color & Light specific widgets to GUI
+ pack_start(*reparcol);
+ pack_start(*invers);
ToolParamBlock* const lumBox = Gtk::manage(new ToolParamBlock());
lumBox->pack_start(*lightness);
lumBox->pack_start(*contrast);
@@ -803,7 +814,7 @@ LocallabColor::LocallabColor():
pack_start(*structcol);
pack_start(*blurcolde);
pack_start(*softradiuscol);
- pack_start(*invers);
+// pack_start(*invers);
ToolParamBlock* const colBox3 = Gtk::manage(new ToolParamBlock());
colBox3->pack_start(*maskusablec, Gtk::PACK_SHRINK, 0);
colBox3->pack_start(*maskunusablec, Gtk::PACK_SHRINK, 0);
@@ -879,6 +890,7 @@ LocallabColor::LocallabColor():
maskcolBox->pack_start(*blendmaskcol, Gtk::PACK_SHRINK, 0);
// Gtk::Frame* const toolcolFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK")));
toolcolFrame->set_label_align(0.025, 0.5);
+ toolcolFrame2->set_label_align(0.025, 0.5);
ToolParamBlock* const toolcolBox = Gtk::manage(new ToolParamBlock());
toolcolBox->pack_start(*radmaskcol, Gtk::PACK_SHRINK, 0);
toolcolBox->pack_start(*lapmaskcol, Gtk::PACK_SHRINK, 0);
@@ -888,8 +900,11 @@ LocallabColor::LocallabColor():
toolcolBox->pack_start(*shadmaskcol, Gtk::PACK_SHRINK, 0);
toolcolBox->pack_start(*maskHCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor
toolcolBox->pack_start(*mask2CurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor
- toolcolBox->pack_start(*mask2CurveEditorGwav, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor
- toolcolBox->pack_start(*csThresholdcol, Gtk::PACK_SHRINK, 0);
+ ToolParamBlock* const toolcolBox2 = Gtk::manage(new ToolParamBlock());
+ toolcolBox2->pack_start(*mask2CurveEditorGwav, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor
+ toolcolBox2->pack_start(*csThresholdcol, Gtk::PACK_SHRINK, 0);
+ toolcolFrame2->add(*toolcolBox2);
+ toolcolBox->pack_start(*toolcolFrame2);
toolcolFrame->add(*toolcolBox);
maskcolBox->pack_start(*toolcolFrame);
mergecolFrame->add(*maskcolBox);
@@ -947,6 +962,7 @@ 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"));
+ reparcol->set_tooltip_text(M("TP_LOCALLAB_REPARCOL_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"));
@@ -998,6 +1014,7 @@ void LocallabColor::updateAdviceTooltips(const bool showTooltips)
} else {
lumFrame->set_tooltip_text("");
lightness->set_tooltip_text("");
+ reparcol->set_tooltip_text("");
gridMethod->set_tooltip_text("");
strengthgrid->set_tooltip_text("");
blurcolde->set_tooltip_text("");
@@ -1114,6 +1131,7 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param
complexity->set_active(spot.complexcolor);
lightness->setValue(spot.lightness);
+ reparcol->setValue(spot.reparcol);
contrast->setValue(spot.contrast);
chroma->setValue(spot.chroma);
curvactiv->set_active(spot.curvactiv);
@@ -1121,8 +1139,8 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param
spot.labgridBLow / LocallabParams::LABGRIDL_CORR_MAX,
spot.labgridAHigh / LocallabParams::LABGRIDL_CORR_MAX,
spot.labgridBHigh / LocallabParams::LABGRIDL_CORR_MAX,
- false);
-
+ 0, 0, 0, 0, false);
+ // printf("labgridlow=%f \n", spot.labgridALow);
if (spot.gridMethod == "one") {
gridMethod->set_active(0);
} else if (spot.gridMethod == "two") {
@@ -1234,7 +1252,7 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param
labgridmerg->setParams(0, 0,
spot.labgridAHighmerg / LocallabParams::LABGRIDL_CORR_MAX,
spot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX,
- false);
+ 0, 0, 0, 0, false);
merlucol->setValue(spot.merlucol);
enaColorMask->set_active(spot.enaColorMask);
CCmaskshape->setCurve(spot.CCmaskcurve);
@@ -1288,13 +1306,16 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe
spot.complexcolor = complexity->get_active_row_number();
spot.lightness = lightness->getIntValue();
+ spot.reparcol = reparcol->getValue();
spot.contrast = contrast->getIntValue();
spot.chroma = chroma->getIntValue();
spot.curvactiv = curvactiv->get_active();
+ double zerox = 0.;
+ double zeroy = 0.;
labgrid->getParams(spot.labgridALow,
spot.labgridBLow,
spot.labgridAHigh,
- spot.labgridBHigh);
+ spot.labgridBHigh, zerox, zeroy, zerox, zeroy);
spot.labgridALow *= LocallabParams::LABGRIDL_CORR_MAX;
spot.labgridAHigh *= LocallabParams::LABGRIDL_CORR_MAX;
spot.labgridBLow *= LocallabParams::LABGRIDL_CORR_MAX;
@@ -1408,10 +1429,12 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe
spot.mercol = mercol->getValue();
spot.opacol = opacol->getValue();
spot.conthrcol = conthrcol->getValue();
+ double zerox1 = 0.;
+ double zeroy1 = 0.;
labgridmerg->getParams(spot.labgridALowmerg,
spot.labgridBLowmerg,
spot.labgridAHighmerg,
- spot.labgridBHighmerg);
+ spot.labgridBHighmerg, zerox1, zeroy1, zerox1, zeroy1);
spot.labgridALowmerg *= LocallabParams::LABGRIDL_CORR_MAX;
spot.labgridAHighmerg *= LocallabParams::LABGRIDL_CORR_MAX;
spot.labgridBLowmerg *= LocallabParams::LABGRIDL_CORR_MAX;
@@ -1451,12 +1474,13 @@ void LocallabColor::setDefaults(const rtengine::procparams::ProcParams* defParam
// Set default value for adjuster, labgrid and threshold adjuster widgets
lightness->setDefault((double)defSpot.lightness);
+ reparcol->setDefault(defSpot.reparcol);
contrast->setDefault((double)defSpot.contrast);
chroma->setDefault((double)defSpot.chroma);
labgrid->setDefault(defSpot.labgridALow / LocallabParams::LABGRIDL_CORR_MAX,
defSpot.labgridBLow / LocallabParams::LABGRIDL_CORR_MAX,
defSpot.labgridAHigh / LocallabParams::LABGRIDL_CORR_MAX,
- defSpot.labgridBHigh / LocallabParams::LABGRIDL_CORR_MAX);
+ defSpot.labgridBHigh / LocallabParams::LABGRIDL_CORR_MAX, 0, 0, 0, 0);
strengthgrid->setDefault((double) defSpot.strengthgrid);
sensi->setDefault((double)defSpot.sensi);
structcol->setDefault((double)defSpot.structcol);
@@ -1472,7 +1496,7 @@ void LocallabColor::setDefaults(const rtengine::procparams::ProcParams* defParam
labgridmerg->setDefault(defSpot.labgridALowmerg / LocallabParams::LABGRIDL_CORR_MAX,
defSpot.labgridBLowmerg / LocallabParams::LABGRIDL_CORR_MAX,
defSpot.labgridAHighmerg / LocallabParams::LABGRIDL_CORR_MAX,
- defSpot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX);
+ defSpot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX, 0, 0, 0, 0);
merlucol->setDefault(defSpot.merlucol);
strumaskcol->setDefault(defSpot.strumaskcol);
contcol->setDefault(defSpot.contcol);
@@ -1505,6 +1529,13 @@ void LocallabColor::adjusterChanged(Adjuster* a, double newval)
}
}
+ if (a == reparcol) {
+ if (listener) {
+ listener->panelChanged(Evlocallabreparcol,
+ reparcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")");
+ }
+ }
+
if (a == contrast) {
if (listener) {
listener->panelChanged(Evlocallabcontrast,
@@ -1935,7 +1966,7 @@ void LocallabColor::convertParamToNormal()
labgridmerg->setParams(0, 0,
defSpot.labgridAHighmerg / LocallabParams::LABGRIDL_CORR_MAX,
defSpot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX,
- false);
+ 0, 0, 0, 0, false);
merlucol->setValue(defSpot.merlucol);
strumaskcol->setValue(defSpot.strumaskcol);
toolcol->set_active(defSpot.toolcol);
@@ -2041,6 +2072,7 @@ void LocallabColor::updateGUIToMode(const modeType new_type)
maskHCurveEditorG->hide();
mask2CurveEditorGwav->hide();
csThresholdcol->hide();
+ toolcolFrame2->hide();
// Specific Simple mode widgets are shown in Normal mode
softradiuscol->show();
if (enaColorMask->get_active()) {
@@ -2113,6 +2145,7 @@ void LocallabColor::updateGUIToMode(const modeType new_type)
maskHCurveEditorG->show();
mask2CurveEditorGwav->show();
csThresholdcol->show();
+ toolcolFrame2->show();
}
}
@@ -2261,9 +2294,10 @@ void LocallabColor::showmaskcolMethodChanged()
if (locToolListener) {
locToolListener->resetOtherMaskView(this);
}
-
- if (listener) {
- listener->panelChanged(EvlocallabshowmaskMethod, "");
+ if(exp->getEnabled()) {
+ if (listener) {
+ listener->panelChanged(EvlocallabshowmaskMethod, "");
+ }
}
}
@@ -2278,9 +2312,10 @@ void LocallabColor::showmaskcolMethodChangedinv()
if (locToolListener) {
locToolListener->resetOtherMaskView(this);
}
-
- if (listener) {
- listener->panelChanged(EvlocallabshowmaskMethod, "");
+ if(exp->getEnabled()) {
+ if (listener) {
+ listener->panelChanged(EvlocallabshowmaskMethod, "");
+ }
}
}
@@ -2364,6 +2399,7 @@ void LocallabColor::updateColorGUI1()
showmaskcolMethodinv->show();
contcol->hide();
blurcol->hide();
+ reparcol->hide();
} else {
gridFrame->show();
@@ -2395,6 +2431,7 @@ void LocallabColor::updateColorGUI1()
showmaskcolMethodConninv.block(false);
contcol->show();
blurcol->show();
+ reparcol->show();
}
}
@@ -2476,6 +2513,7 @@ LocallabExposure::LocallabExposure():
// 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.))),
+ reparexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LOGREPART"), 1.0, 100.0, 1., 100.0))),
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))),
@@ -2487,7 +2525,7 @@ LocallabExposure::LocallabExposure():
fatdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATDETAIL"), -100., 300., 1., 0.))),
norm(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EQUIL")))),
fatlevel(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATLEVEL"), 0.5, 2.0, 0.01, 1.))),
- fatanchor(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATANCHORA"), 0.5, 2.0, 0.01, 1.))),
+ fatanchor(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATANCHOR"), 0.1, 100.0, 0.01, 50., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))),
sensiex(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 60))),
structexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUCCOL"), 0, 100, 1, 0))),
blurexpde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))),
@@ -2518,10 +2556,11 @@ LocallabExposure::LocallabExposure():
showmaskexpMethodinv(Gtk::manage(new MyComboBoxText())),
enaExpMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))),
enaExpMaskaft(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASKAFT")))),
- maskexpCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))),
- CCmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))),
- LLmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))),
- HHmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))),
+ // maskexpCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))),
+ maskexpCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)),
+ CCmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
+ LLmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
+ HHmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))),
blendmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))),
radmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), 0.0, 100.0, 0.1, 0.))),
lapmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))),
@@ -2549,6 +2588,7 @@ LocallabExposure::LocallabExposure():
setExpandAlignProperties(expfat, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
laplacexp->setAdjusterListener(this);
+ reparexp->setAdjusterListener(this);
linear->setAdjusterListener(this);
@@ -2688,7 +2728,9 @@ LocallabExposure::LocallabExposure():
mask2expCurveEditorG->curveListComplete();
// Add Color & Light specific widgets to GUI
-// pack_start(*expMethod);
+ pack_start(*sensiex);
+ pack_start(*reparexp);
+ pack_start(*inversex);
ToolParamBlock* const pdeBox = Gtk::manage(new ToolParamBlock());
pdeBox->pack_start(*laplacexp);
pdeBox->pack_start(*linear);
@@ -2708,13 +2750,12 @@ LocallabExposure::LocallabExposure():
fatBox->pack_start(*fatdetail);
// fatBox->pack_start(*norm);
// fatBox->pack_start(*fatlevel);
-// fatBox->pack_start(*fatanchor);
+ fatBox->pack_start(*fatanchor);
// fatFrame->add(*fatBox);
expfat->add(*fatBox, false);
// pack_start(*fatFrame);
pack_start(*expfat);
pack_start(*expcomp);
- pack_start(*sensiex);
pack_start(*structexp);
pack_start(*blurexpde);
ToolParamBlock* const toolBox = Gtk::manage(new ToolParamBlock());
@@ -2743,7 +2784,7 @@ LocallabExposure::LocallabExposure():
expgradexp->add(*gradBox, false);
pack_start(*expgradexp);
pack_start(*softradiusexp);
- pack_start(*inversex);
+ // pack_start(*inversex);
ToolParamBlock* const maskexpBox = Gtk::manage(new ToolParamBlock());
maskexpBox->pack_start(*showmaskexpMethod, Gtk::PACK_SHRINK, 4);
maskexpBox->pack_start(*showmaskexpMethodinv, Gtk::PACK_SHRINK, 4);
@@ -2809,6 +2850,7 @@ void LocallabExposure::updateAdviceTooltips(const bool showTooltips)
higthrese->set_tooltip_text(M("TP_LOCALLAB_MASKHIGTHRESE_TOOLTIP"));
blurexpde->set_tooltip_text(M("TP_LOCALLAB_BLURCOLDE_TOOLTIP"));
laplacexp->set_tooltip_text(M("TP_LOCALLAB_EXPLAP_TOOLTIP"));
+ reparexp->set_tooltip_text(M("TP_LOCALLAB_REPAREXP_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"));
@@ -2843,6 +2885,7 @@ void LocallabExposure::updateAdviceTooltips(const bool showTooltips)
blurexpde->set_tooltip_text("");
exprecove->set_tooltip_markup("");
laplacexp->set_tooltip_text("");
+ reparexp->set_tooltip_text("");
linear->set_tooltip_text("");
balanexp->set_tooltip_text("");
gamm->set_tooltip_text("");
@@ -2933,6 +2976,7 @@ void LocallabExposure::read(const rtengine::procparams::ProcParams* pp, const Pa
}
*/
laplacexp->setValue(spot.laplacexp);
+ reparexp->setValue(spot.reparexp);
linear->setValue(spot.linear);
balanexp->setValue(spot.balanexp);
gamm->setValue(spot.gamm);
@@ -3024,6 +3068,7 @@ void LocallabExposure::write(rtengine::procparams::ProcParams* pp, ParamsEdited*
}
*/
spot.laplacexp = laplacexp->getValue();
+ spot.reparexp = reparexp->getValue();
spot.linear = linear->getValue();
spot.balanexp = balanexp->getValue();
spot.gamm = gamm->getValue();
@@ -3088,6 +3133,7 @@ void LocallabExposure::setDefaults(const rtengine::procparams::ProcParams* defPa
// Set default values for adjuster widgets
laplacexp->setDefault(defSpot.laplacexp);
+ reparexp->setDefault(defSpot.reparexp);
linear->setDefault(defSpot.linear);
balanexp->setDefault(defSpot.balanexp);
gamm->setDefault(defSpot.gamm);
@@ -3140,6 +3186,13 @@ void LocallabExposure::adjusterChanged(Adjuster* a, double newval)
}
}
+ if (a == reparexp) {
+ if (listener) {
+ listener->panelChanged(Evlocallabreparexp,
+ reparexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")");
+ }
+ }
+
if (a == linear) {
if (listener) {
listener->panelChanged(Evlocallablinear,
@@ -3436,12 +3489,9 @@ void LocallabExposure::convertParamToNormal()
slomaskexp->setValue(defSpot.slomaskexp);
strmaskexp->setValue(defSpot.strmaskexp);
angmaskexp->setValue(defSpot.angmaskexp);
-// fatlevel->setValue(defSpot.fatlevel);
-// fatanchor->setValue(defSpot.fatanchor);
decaye->setValue(defSpot.decaye);
// norm->set_active(defSpot.enaExpMask);
fatlevel->setValue(defSpot.fatlevel);
- fatanchor->setValue(defSpot.fatanchor);
// Enable all listeners
enableListener();
@@ -3517,13 +3567,17 @@ void LocallabExposure::updateGUIToMode(const modeType new_type)
}
norm->show();
fatlevel->hide();
- fatanchor->hide();
+ fatanchor->show();
// Specific Simple mode widgets are shown in Normal mode
+ softradiusexp->hide();
+ blurexpde->hide();
+
if (!inversex->get_active()) { // Keep widget hidden when invers is toggled
expgradexp->show();
softradiusexp->show();
exprecove->show();
+ blurexpde->show();
}
expmaskexp->show();
@@ -3533,7 +3587,8 @@ void LocallabExposure::updateGUIToMode(const modeType new_type)
case Expert:
// Show widgets hidden in Normal and Simple mode
- if (!inversex->get_active()) { // Keep widget hidden when invers is toggled
+ structexp->hide();
+ if (!inversex->get_active()) { // Keep widget hidden when invers is toggled
structexp->show();
}
@@ -3541,11 +3596,15 @@ void LocallabExposure::updateGUIToMode(const modeType new_type)
norm->show();
fatlevel->show();
fatanchor->show();
+ softradiusexp->hide();
+ blurexpde->hide();
if (!inversex->get_active()) { // Keep widget hidden when invers is toggled
expgradexp->show();
softradiusexp->show();
exprecove->show();
+ blurexpde->show();
+
}
if (enaExpMask->get_active()) {
maskusablee->show();
@@ -3661,8 +3720,10 @@ void LocallabExposure::showmaskexpMethodChanged()
locToolListener->resetOtherMaskView(this);
}
- if (listener) {
- listener->panelChanged(EvlocallabshowmaskMethod, "");
+ if(exp->getEnabled()) {
+ if (listener) {
+ listener->panelChanged(EvlocallabshowmaskMethod, "");
+ }
}
}
@@ -3678,8 +3739,10 @@ void LocallabExposure::showmaskexpMethodChangedinv()
locToolListener->resetOtherMaskView(this);
}
- if (listener) {
- listener->panelChanged(EvlocallabshowmaskMethod, "");
+ if(exp->getEnabled()) {
+ if (listener) {
+ listener->panelChanged(EvlocallabshowmaskMethod, "");
+ }
}
}
@@ -3761,6 +3824,11 @@ void LocallabExposure::updateExposureGUI3()
expMethod->hide();
expcomp->setLabel(M("TP_LOCALLAB_EXPCOMPINV"));
exprecove->hide();
+ reparexp->hide();
+ expfat->hide();
+ exppde->hide();
+ structexp->hide();
+ blurexpde->hide();
// Manage specific case where expMethod is different from 0
if (expMethod->get_active_row_number() > 0) {
@@ -3783,12 +3851,24 @@ void LocallabExposure::updateExposureGUI3()
} else {
expMethod->show();
expcomp->setLabel(M("TP_LOCALLAB_EXPCOMP"));
+ expfat->show();
+ exppde->show();
- if (mode == Expert || mode == Normal) { // Keep widgets hidden in Simple mode
+ if (mode == Normal) { // Keep widgets hidden in Simple mode
softradiusexp->show();
expgradexp->show();
exprecove->show();
+ blurexpde->show();
}
+ if (mode == Expert) { // Keep widgets hidden in Simple mode
+ softradiusexp->show();
+ expgradexp->show();
+ exprecove->show();
+ structexp->show();
+ blurexpde->show();
+ }
+
+ reparexp->show();
showmaskexpMethodinv->hide();
// Reset hidden mask combobox
@@ -3805,6 +3885,7 @@ LocallabShadow::LocallabShadow():
// Shadow highlight specific widgets
shMethod(Gtk::manage(new MyComboBoxText())),
+ reparsh(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LOGREPART"), 1.0, 100.0, 1., 100.0))),
multipliersh([]() -> std::array
{
std::array res = {};
@@ -3850,10 +3931,11 @@ LocallabShadow::LocallabShadow():
showmaskSHMethod(Gtk::manage(new MyComboBoxText())),
showmaskSHMethodinv(Gtk::manage(new MyComboBoxText())),
enaSHMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))),
- maskSHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))),
- CCmaskSHshape(static_cast