diff --git a/rtdata/images/Chanmixer-BY.png b/rtdata/images/Chanmixer-BY.png new file mode 100644 index 000000000..c630ffb29 Binary files /dev/null and b/rtdata/images/Chanmixer-BY.png differ diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index b5c8c56a1..a1401fb2a 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -468,6 +468,36 @@ HISTORY_MSG_247;Courbe 'LT' HISTORY_MSG_248;Courbe 'TT' HISTORY_MSG_249;Seuil Contraste par niv. de détail HISTORY_MSG_250;Réd. de bruit - Amélioré +HISTORY_MSG_251;N&B - Algorithme +HISTORY_MSG_252;CpND - Tons chair +HISTORY_MSG_253;CpND - Réduction des artéfactes +HISTORY_MSG_254;CpND - Teinte chair +HISTORY_MSG_255;Virage Partiel +HISTORY_MSG_256;Virage Partiel - Couleur +HISTORY_MSG_257;Virage Partiel - Opacité +HISTORY_MSG_258;Virage Partiel - Opacité ab +HISTORY_MSG_259;Virage Partiel - Méthode +HISTORY_MSG_260;Virage Partiel - 2 couleurs +HISTORY_MSG_261;Virage Partiel - Luminance +HISTORY_MSG_262;Virage Partiel - Ombres - Rouge +HISTORY_MSG_263;Virage Partiel - Ombres - Vert +HISTORY_MSG_264;Virage Partiel - Ombres - Bleu +HISTORY_MSG_265;Virage Partiel - Moyen - Rouge +HISTORY_MSG_266;Virage Partiel - Moyen - Vert +HISTORY_MSG_267;Virage Partiel - Moyen - Bleu +HISTORY_MSG_268;Virage Partiel - HL - Rouge +HISTORY_MSG_269;Virage Partiel - HL - Vert +HISTORY_MSG_270;Virage Partiel - HL - Bleu +HISTORY_MSG_271;Virage Partiel - Balance +HISTORY_MSG_272;Virage Partiel - Réinit. +HISTORY_MSG_273;Virage Partiel - Saturation Shadows +HISTORY_MSG_274;Virage Partiel - Saturation Highlights +HISTORY_MSG_275;Virage Partiel - Réinit. Courbes +HISTORY_MSG_276;Virage Partiel - Préserver Luminance +HISTORY_MSG_277;Virage partiel - Ombres +HISTORY_MSG_278;Virage partiel - Hautes Lumières +HISTORY_MSG_279;Virage partiel - Protect. Saturé +HISTORY_MSG_280;Virage partiel - Seuil de Protection HISTORY_NEWSNAPSHOT;Ajouter HISTORY_NEWSNAPSHOT_TOOLTIP;Raccourci: Alt-s HISTORY_SNAPSHOTS;Captures @@ -611,6 +641,7 @@ PARTIALPASTE_CHANNELMIXER;Mixage des canaux PARTIALPASTE_COARSETRANS;Rotation de 90° / symétrisation PARTIALPASTE_COLORAPP;CIE Modèle apparence de la couleur 2002 PARTIALPASTE_COLORGROUP;Réglages couleurs +PARTIALPASTE_COLORTONING;Virage Partiel PARTIALPASTE_COMMONTRANSFORMPARAMS;Remplir PARTIALPASTE_COMPOSITIONGROUP;Réglages de la composition PARTIALPASTE_CROP;Recadrage @@ -1034,6 +1065,53 @@ TP_COLORAPP_TONECIE;Compression Tonale utilisant CIECAM02 TP_COLORAPP_TONECIE_TOOLTIP;Si cette option est désactivée, la compression tonale est faite dans l'espace Lab.\nSi cette options est activée, la compression tonale est faite en utilisant CIECAM02.\nL'outil Compression Tonale doit être activé pour que ce réglage prenne effet TP_COLORAPP_WBCAM;BB [RT+CAT02] + [sortie] TP_COLORAPP_WBRT;BB [RT] + [sortie] +TP_COLORTONING_LABEL;Virage Partiel +TP_COLORTONING_OPACITY;Opacité +TP_COLORTONING_LUMAMODE;Préserver la luminance +TP_COLORTONING_LUMAMODE_TOOLTIP;Si activé, lorsque vous changez la couleur (rouge, vert, cyan, bleu, etc.), la luminance de chaque pixel est préservé +TP_COLORTONING_COLOR;Couleur +TP_COLORTONING_LABCOL;Couleurs direct +TP_COLORTONING_LABCOL_TOOLTIP;Lorsque vous déplacez un curseur de saturation, ces couleurs 'direct' sont augmentés +TP_COLORTONING_LABINT;Couleurs interpolés - Mixage +TP_COLORTONING_LABINT_TOOLTIP;Lorsque l'image est bleue et que la mixage de la couleur interpolé est rouge, cela résulte en un magenta en fonction du pourcentage d'opacité\nLorsque l'image est rouge et que la mixage de la couleur interpolé est jaune, cela résulte en un orange en fonction du pourcentage d'opacité\nEtc... +TP_COLORTONING_CHROMA;Opacité 'ab' ou 'a' +TP_COLORTONING_CHROMA2;Opacité 'b' +TP_COLORTONING_AB;ab L +TP_COLORTONING_BY;b L +TP_COLORTONING_LUMA;Luminance +TP_COLORTONING_CURVEEDITOR_LL;L +TP_COLORTONING_METHOD;Méthode +TP_COLORTONING_TWOSTD;Opacité standard 'ab' +TP_COLORTONING_TWOALL;Opacité spécial 'ab' +TP_COLORTONING_TWOBY;Opacité spécial 'a' and 'b' +TP_COLORTONING_TWO2;Opacité spécial 'ab' 2 couleurs +TP_COLORTONING_TWOCOLOR_TOOLTIP;Standard: réponse linéaire identique pour 'a' et 'b'\nSpécial 'ab': même réponse pour 'a' and 'b', mais sans limites - essayez en dessous de la diagonale\nSpécial 'a' et 'b': comme Spécial + courbes 'a' et 'b' séparé: dédié aux effets spéciaux\nSpécial 2 couleurs - plus prévisible +TP_COLORTONING_HUE;Mixage de la teinte +TP_COLORTONING_LAB;Mixage Lab +TP_COLORTONING_LCH;Mixage Lch +TP_COLORTONING_LCH_1;Teinte + XYZ +TP_COLORTONING_LCH_2;Mixage XYZ +TP_COLORTONING_NEUTRALCUR;Réinit. courbes +TP_COLORTONING_NEUTRALCUR_TIP;Réinitialise toutes les courbes à leurs valeur par défaut. +TP_COLORTONING_NEUTRAL;Réinit. curseurs +TP_COLORTONING_NEUTRAL_TIP;Réinitialise toutes les valeurs (Ombres, Tons moyens, Hautes lumières) à leur valeur par défaut. +TP_COLORTONING_SPLITCO;Virage couleur O-TM-HL +TP_COLORTONING_SPLITBAL;Virage couleur O-HL + balance +TP_COLORTONING_SPLITLR;Virage couleur - Saturation 2 couleurs +TP_COLORTONING_SATL;Saturation des Ombres +TP_COLORTONING_SATH;Saturation des Hautes lumière +TP_COLORTONING_BALANCE;Balance +TP_COLORTONING_METHOD_TOOLTIP;Lab blending use interpolation colour blending\nSplit Toning Colour SMH (Shadows Midtones Highlights)\nSplit Toning Colour SH+balance (Shadows Highlights + balance shadows/highlights) use direct colors\nIn all methods you can enabled Black and White +TP_COLORTONING_BALANCE_TOOLTIP;Équilibre entre la couleur des ombres et celle des hautes lumières +TP_COLORTONING_RGBSLIDERS;RVB - Curseurs +TP_COLORTONING_RGBCURVES;RVB - Courbes +TP_COLORTONING_SATURATIONTHRESHOLD;Seuil des couleurs saturés +TP_COLORTONING_SATURATEDOPACITY;Protection des couleurs saturées +TP_COLORTONING_SHADOWS;Ombres +TP_COLORTONING_MIDTONES;Tons Moyens +TP_COLORTONING_HIGHLIGHT;Hautes lumières +TP_COLORTONING_STRENGTH;Force +TP_COLORTONING_HUE;Teinte TP_CROP_FIXRATIO;Ratio fixe: TP_CROP_GTDIAGONALS;Règle des diagonales TP_CROP_GTEPASSPORT;Passeport biométrique diff --git a/rtdata/languages/default b/rtdata/languages/default index e7c661817..4d8ede071 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -476,6 +476,35 @@ HISTORY_MSG_253;CbDL Reduce artifacts HISTORY_MSG_254;CbDL - Hueskin HISTORY_MSG_255;NR - median HISTORY_MSG_256;NR - median method +HISTORY_MSG_257;Color Toning +HISTORY_MSG_258;Color Toning - Color +HISTORY_MSG_259;Color Toning - Opacity +HISTORY_MSG_260;Color Toning - Opacity ab +HISTORY_MSG_261;Color Toning - Method +HISTORY_MSG_262;Color Toning - 2 colours +HISTORY_MSG_263;Color Toning - Luminance +HISTORY_MSG_263;Color Toning - Shadows Red +HISTORY_MSG_264;Color Toning - Shadows Green +HISTORY_MSG_265;Color Toning - Shadows Blue +HISTORY_MSG_266;Color Toning - Middle Red +HISTORY_MSG_267;Color Toning - Middle Green +HISTORY_MSG_268;Color Toning - Middle Blue +HISTORY_MSG_269;Color Toning - High Red +HISTORY_MSG_270;Color Toning - High Green +HISTORY_MSG_271;Color Toning - High Blue +HISTORY_MSG_272;Color Toning - Balance +HISTORY_MSG_273;Color Toning - Reset +HISTORY_MSG_274;Color Toning - Saturation Shadows +HISTORY_MSG_275;Color Toning - Saturation Highlights +HISTORY_MSG_276;Color Toning - Method +HISTORY_MSG_277;Color Toning - Reset Curves +HISTORY_MSG_278;Color Toning - Preserve Luminance +HISTORY_MSG_279;Color Toning - Shadows +HISTORY_MSG_280;Color Toning - Highlights +HISTORY_MSG_281;Color Toning - Sat. Protection +HISTORY_MSG_282;Color Toning - Sat. Threshold +HISTORY_MSG_283;Color Toning - Str. Protection +HISTORY_MSG_284;Color Toning - Auto saturation HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOTS;Snapshots @@ -611,6 +640,7 @@ PARTIALPASTE_CHANNELMIXER;Channel mixer PARTIALPASTE_COARSETRANS;90° rotation / flipping PARTIALPASTE_COLORAPP;CIE Color Appearance Model 2002 PARTIALPASTE_COLORGROUP;Color Related Settings +PARTIALPASTE_COLORTONING;Color Toning PARTIALPASTE_COMMONTRANSFORMPARAMS;Auto-fill PARTIALPASTE_COMPOSITIONGROUP;Composition Settings PARTIALPASTE_CROP;Crop @@ -1041,6 +1071,58 @@ TP_COLORAPP_TONECIE;Tone mapping using CIECAM02 TP_COLORAPP_TONECIE_TOOLTIP;If this option is disabled, tone mapping is done in Lab space.\nIf this option is enabled, tone mapping is done using CIECAM02.\nThe Tone Mapping tool must be enabled for this setting to take effect. TP_COLORAPP_WBCAM;WB [RT+CAT02] + [output] TP_COLORAPP_WBRT;WB [RT] + [output] +TP_COLORTONING_LABEL;Color Toning +TP_COLORTONING_OPACITY;Opacity +TP_COLORTONING_LUMAMODE;Preserve luminance +TP_COLORTONING_LUMAMODE_TOOLTIP;if enabled when you change color (red, green, cyan, blue, etc.) the luminance of each pixel is preserved +TP_COLORTONING_COLOR;Color +TP_COLORTONING_LABCOL;Direct Colors +TP_COLORTONING_LABCOL_TOOLTIP;When you move a saturation slider, these 'direct' colors are increased +TP_COLORTONING_LABINT;Interpolates Colors - Blending +TP_COLORTONING_LABINT_TOOLTIP;When image color is blue and interpolate color blending is red - it result a magenta in function of % opacity\nWhen image color is red and interpolate color blending is yellow - it result a orange in function of % opacity\n etc. +TP_COLORTONING_CHROMA;Opacity 'ab' or 'a' +TP_COLORTONING_CHROMA1;Opacity 'a' +TP_COLORTONING_CHROMA2;Opacity 'b' +TP_COLORTONING_CHROMAC;Opacity chroma +TP_COLORTONING_AB;o C/L +TP_COLORTONING_BY;o C/L +TP_COLORTONING_LUMA;Luminance +TP_COLORTONING_CURVEEDITOR_LL;L +TP_COLORTONING_METHOD;Method +TP_COLORTONING_TWOSTD;Opacity standard chroma +TP_COLORTONING_TWOALL;Opacity special chroma +TP_COLORTONING_TWOBY;Opacity special 'a' and 'b' +TP_COLORTONING_TWO2;Opacity special chroma 2 colors +TP_COLORTONING_TWOCOLOR_TOOLTIP;Standard - linear response same for 'a' and 'b'\nSpecial chroma same response for 'a' and 'b', but without bound - try under the diagonal\nSpecial 'a' and 'b': as Special + first curve 'a' only - second curve 'b' only : dedicate for special effects\nSpecial 2 colors - more predictable +TP_COLORTONING_HUE;Hue blending only +TP_COLORTONING_LAB;Lab blending +TP_COLORTONING_LCH;Lch blending +TP_COLORTONING_LCH_1;Hue + XYZ +TP_COLORTONING_LCH_2;XYZ blending +TP_COLORTONING_NEUTRALCUR;Reset curves +TP_COLORTONING_NEUTRALCUR_TIP;Reset all curves to default. +TP_COLORTONING_NEUTRAL;Reset sliders +TP_COLORTONING_NEUTRAL_TIP;Reset all values (Shadows Midtones Highlights) to default. +TP_COLORTONING_SPLITCO;Split Toning Colour SMH +TP_COLORTONING_SPLITCOCO;Color Balance SMH +TP_COLORTONING_SPLITBAL;Split Toning Colour SH + balance +TP_COLORTONING_SPLITLR;Split Toning Saturation 2 colors +TP_COLORTONING_SATL;Saturation shadows +TP_COLORTONING_SATH;Saturation highlights +TP_COLORTONING_BALANCE;Balance +TP_COLORTONING_STRPROTECT;Strength protection +TP_COLORTONING_METHOD_TOOLTIP;Lab blending use interpolation colour blending\nColor balance (Shadows Midtones Highlights)\nSplit Toning Colour SH+balance (Shadows Highlights + balance shadows/highlights) use direct colors\nIn all methods you can enabled Black and White +TP_COLORTONING_BALANCE_TOOLTIP;Equilibrate tones between shadows and highlights +TP_COLORTONING_RGBSLIDERS;RGB - Sliders +TP_COLORTONING_RGBCURVES;RGB - Curves +TP_COLORTONING_AUTOSAT;Auto saturation +TP_COLORTONING_SATURATIONTHRESHOLD;Saturation protection threshold +TP_COLORTONING_SATURATEDOPACITY;Saturation protection +TP_COLORTONING_SHADOWS;Shadows +TP_COLORTONING_MIDTONES;Mid Tones +TP_COLORTONING_HIGHLIGHT;Highlights +TP_COLORTONING_STRENGTH;Strength +TP_COLORTONING_HUE;Hue TP_CROP_FIXRATIO;Fix ratio: TP_CROP_GTDIAGONALS;Rule of Diagonals TP_CROP_GTEPASSPORT;Biometric Passport diff --git a/rtdata/profiles/BW/BW 1.pp3 b/rtdata/profiles/BW/BW 1.pp3 index 2cabb35bf..22ec48fd5 100644 --- a/rtdata/profiles/BW/BW 1.pp3 +++ b/rtdata/profiles/BW/BW 1.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=-100 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/BW/BW 2.pp3 b/rtdata/profiles/BW/BW 2.pp3 index 27fb098fd..1e9400898 100644 --- a/rtdata/profiles/BW/BW 2.pp3 +++ b/rtdata/profiles/BW/BW 2.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=-100 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.84892086330935235;0.69064748201438808;1;1; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/BW/BW 3.pp3 b/rtdata/profiles/BW/BW 3.pp3 index 445dd7ad8..56f8e68ff 100644 --- a/rtdata/profiles/BW/BW 3.pp3 +++ b/rtdata/profiles/BW/BW 3.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=-25 Chromaticity=-100 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=2;0.25;0.5;0.75;50;12;-12;-50; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/BW/BW 4.pp3 b/rtdata/profiles/BW/BW 4.pp3 index 93b15b27b..c3cf60b09 100644 --- a/rtdata/profiles/BW/BW 4.pp3 +++ b/rtdata/profiles/BW/BW 4.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=-35 Chromaticity=-100 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.18623481781376497;0.028340080971659902;0.50607287449392713;0.50607287449392713;0.77732793522267185;0.97975708502024295;1;1; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Default ISO High.pp3 b/rtdata/profiles/Default ISO High.pp3 index 55375af34..dd35a50e6 100644 --- a/rtdata/profiles/Default ISO High.pp3 +++ b/rtdata/profiles/Default ISO High.pp3 @@ -48,7 +48,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=5 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -83,7 +83,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Default ISO Medium.pp3 b/rtdata/profiles/Default ISO Medium.pp3 index fb9b67a41..d35745762 100644 --- a/rtdata/profiles/Default ISO Medium.pp3 +++ b/rtdata/profiles/Default ISO Medium.pp3 @@ -48,7 +48,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=5 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -83,7 +83,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Default.pp3 b/rtdata/profiles/Default.pp3 index 123860247..6dbc7a6f7 100644 --- a/rtdata/profiles/Default.pp3 +++ b/rtdata/profiles/Default.pp3 @@ -48,7 +48,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -83,7 +83,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Amber 1 TM Bright.pp3 b/rtdata/profiles/Faded/Faded Amber 1 TM Bright.pp3 index 78f681063..25a3553a6 100644 --- a/rtdata/profiles/Faded/Faded Amber 1 TM Bright.pp3 +++ b/rtdata/profiles/Faded/Faded Amber 1 TM Bright.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Amber 1 TM.pp3 b/rtdata/profiles/Faded/Faded Amber 1 TM.pp3 index 216339b4e..7ed6b967a 100644 --- a/rtdata/profiles/Faded/Faded Amber 1 TM.pp3 +++ b/rtdata/profiles/Faded/Faded Amber 1 TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Amber 1.pp3 b/rtdata/profiles/Faded/Faded Amber 1.pp3 index 9c696db84..d90098dd9 100644 --- a/rtdata/profiles/Faded/Faded Amber 1.pp3 +++ b/rtdata/profiles/Faded/Faded Amber 1.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Blue 1 TM Bright.pp3 b/rtdata/profiles/Faded/Faded Blue 1 TM Bright.pp3 index 38ae1c1e6..8cd869961 100644 --- a/rtdata/profiles/Faded/Faded Blue 1 TM Bright.pp3 +++ b/rtdata/profiles/Faded/Faded Blue 1 TM Bright.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Blue 1 TM.pp3 b/rtdata/profiles/Faded/Faded Blue 1 TM.pp3 index 4cc197dc9..69e65028e 100644 --- a/rtdata/profiles/Faded/Faded Blue 1 TM.pp3 +++ b/rtdata/profiles/Faded/Faded Blue 1 TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Blue 1.pp3 b/rtdata/profiles/Faded/Faded Blue 1.pp3 index 3359c1c50..ec36fb7e3 100644 --- a/rtdata/profiles/Faded/Faded Blue 1.pp3 +++ b/rtdata/profiles/Faded/Faded Blue 1.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Blue Pink TM.pp3 b/rtdata/profiles/Faded/Faded Blue Pink TM.pp3 index 93c6eb447..df0653315 100644 --- a/rtdata/profiles/Faded/Faded Blue Pink TM.pp3 +++ b/rtdata/profiles/Faded/Faded Blue Pink TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Blue Pink.pp3 b/rtdata/profiles/Faded/Faded Blue Pink.pp3 index c87a75f83..f61733589 100644 --- a/rtdata/profiles/Faded/Faded Blue Pink.pp3 +++ b/rtdata/profiles/Faded/Faded Blue Pink.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Chocolate 1 TM Bright.pp3 b/rtdata/profiles/Faded/Faded Chocolate 1 TM Bright.pp3 index a6378877f..11175d3fb 100644 --- a/rtdata/profiles/Faded/Faded Chocolate 1 TM Bright.pp3 +++ b/rtdata/profiles/Faded/Faded Chocolate 1 TM Bright.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Chocolate 2 TM Bright.pp3 b/rtdata/profiles/Faded/Faded Chocolate 2 TM Bright.pp3 index 71af0eaf5..b71f344c8 100644 --- a/rtdata/profiles/Faded/Faded Chocolate 2 TM Bright.pp3 +++ b/rtdata/profiles/Faded/Faded Chocolate 2 TM Bright.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Golden 1.pp3 b/rtdata/profiles/Faded/Faded Golden 1.pp3 index a03b19077..699e1fb61 100644 --- a/rtdata/profiles/Faded/Faded Golden 1.pp3 +++ b/rtdata/profiles/Faded/Faded Golden 1.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=56 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Golden 2.pp3 b/rtdata/profiles/Faded/Faded Golden 2.pp3 index 790348d73..78619557e 100644 --- a/rtdata/profiles/Faded/Faded Golden 2.pp3 +++ b/rtdata/profiles/Faded/Faded Golden 2.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=56 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Green 1 TM Bright.pp3 b/rtdata/profiles/Faded/Faded Green 1 TM Bright.pp3 index 490d38410..3633783a9 100644 --- a/rtdata/profiles/Faded/Faded Green 1 TM Bright.pp3 +++ b/rtdata/profiles/Faded/Faded Green 1 TM Bright.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Green 1 TM.pp3 b/rtdata/profiles/Faded/Faded Green 1 TM.pp3 index 1ad37389c..b7c24ef44 100644 --- a/rtdata/profiles/Faded/Faded Green 1 TM.pp3 +++ b/rtdata/profiles/Faded/Faded Green 1 TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Green 1.pp3 b/rtdata/profiles/Faded/Faded Green 1.pp3 index 776996fd7..88e95ccfd 100644 --- a/rtdata/profiles/Faded/Faded Green 1.pp3 +++ b/rtdata/profiles/Faded/Faded Green 1.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Green 2.pp3 b/rtdata/profiles/Faded/Faded Green 2.pp3 index 916a89b76..d974b003e 100644 --- a/rtdata/profiles/Faded/Faded Green 2.pp3 +++ b/rtdata/profiles/Faded/Faded Green 2.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Green 3.pp3 b/rtdata/profiles/Faded/Faded Green 3.pp3 index 868a646e3..b4e4c792c 100644 --- a/rtdata/profiles/Faded/Faded Green 3.pp3 +++ b/rtdata/profiles/Faded/Faded Green 3.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Neutral TM.pp3 b/rtdata/profiles/Faded/Faded Neutral TM.pp3 index 54d2d04bd..e39a6502a 100644 --- a/rtdata/profiles/Faded/Faded Neutral TM.pp3 +++ b/rtdata/profiles/Faded/Faded Neutral TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Neutral.pp3 b/rtdata/profiles/Faded/Faded Neutral.pp3 index 91309a946..08d70126f 100644 --- a/rtdata/profiles/Faded/Faded Neutral.pp3 +++ b/rtdata/profiles/Faded/Faded Neutral.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Purple 1 TM Bright.pp3 b/rtdata/profiles/Faded/Faded Purple 1 TM Bright.pp3 index cb96611ac..7829a6ee1 100644 --- a/rtdata/profiles/Faded/Faded Purple 1 TM Bright.pp3 +++ b/rtdata/profiles/Faded/Faded Purple 1 TM Bright.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Purple 1 TM.pp3 b/rtdata/profiles/Faded/Faded Purple 1 TM.pp3 index a9eb8d476..8906bbe4a 100644 --- a/rtdata/profiles/Faded/Faded Purple 1 TM.pp3 +++ b/rtdata/profiles/Faded/Faded Purple 1 TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Purple 1.pp3 b/rtdata/profiles/Faded/Faded Purple 1.pp3 index c63e6ab80..f496cd4ee 100644 --- a/rtdata/profiles/Faded/Faded Purple 1.pp3 +++ b/rtdata/profiles/Faded/Faded Purple 1.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Purple 2 TM.pp3 b/rtdata/profiles/Faded/Faded Purple 2 TM.pp3 index 4e50aebde..d49edb003 100644 --- a/rtdata/profiles/Faded/Faded Purple 2 TM.pp3 +++ b/rtdata/profiles/Faded/Faded Purple 2 TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Purple 2.pp3 b/rtdata/profiles/Faded/Faded Purple 2.pp3 index a18353b85..e164e0671 100644 --- a/rtdata/profiles/Faded/Faded Purple 2.pp3 +++ b/rtdata/profiles/Faded/Faded Purple 2.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Teal Orange TM Bright.pp3 b/rtdata/profiles/Faded/Faded Teal Orange TM Bright.pp3 index 1f44d5019..27cdf8efc 100644 --- a/rtdata/profiles/Faded/Faded Teal Orange TM Bright.pp3 +++ b/rtdata/profiles/Faded/Faded Teal Orange TM Bright.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.094310344827586101;0.09189655172413784;0.9956896551724137;0.92051724137931046;1;1; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Teal Orange TM.pp3 b/rtdata/profiles/Faded/Faded Teal Orange TM.pp3 index c695aba73..1eb84fc5e 100644 --- a/rtdata/profiles/Faded/Faded Teal Orange TM.pp3 +++ b/rtdata/profiles/Faded/Faded Teal Orange TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.094310344827586101;0.09189655172413784;0.89568965517241339;0.9032758620689656;1;1; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Teal Orange.pp3 b/rtdata/profiles/Faded/Faded Teal Orange.pp3 index be2fcb653..0e9ccca66 100644 --- a/rtdata/profiles/Faded/Faded Teal Orange.pp3 +++ b/rtdata/profiles/Faded/Faded Teal Orange.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.094310344827586101;0.09189655172413784;0.89568965517241339;0.9032758620689656;1;1; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Warm 1 TM Bright.pp3 b/rtdata/profiles/Faded/Faded Warm 1 TM Bright.pp3 index 37403818a..b351dae0f 100644 --- a/rtdata/profiles/Faded/Faded Warm 1 TM Bright.pp3 +++ b/rtdata/profiles/Faded/Faded Warm 1 TM Bright.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Warm 1 TM.pp3 b/rtdata/profiles/Faded/Faded Warm 1 TM.pp3 index 9e4aa4507..01febd92d 100644 --- a/rtdata/profiles/Faded/Faded Warm 1 TM.pp3 +++ b/rtdata/profiles/Faded/Faded Warm 1 TM.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Warm 1.pp3 b/rtdata/profiles/Faded/Faded Warm 1.pp3 index ea42493a7..6b8210ae1 100644 --- a/rtdata/profiles/Faded/Faded Warm 1.pp3 +++ b/rtdata/profiles/Faded/Faded Warm 1.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=-25 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Warm 2.pp3 b/rtdata/profiles/Faded/Faded Warm 2.pp3 index b62355b51..1f8194182 100644 --- a/rtdata/profiles/Faded/Faded Warm 2.pp3 +++ b/rtdata/profiles/Faded/Faded Warm 2.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Faded/Faded Warm 3.pp3 b/rtdata/profiles/Faded/Faded Warm 3.pp3 index 063eb8be6..ab787676c 100644 --- a/rtdata/profiles/Faded/Faded Warm 3.pp3 +++ b/rtdata/profiles/Faded/Faded Warm 3.pp3 @@ -29,7 +29,7 @@ Enabled=false Brightness=0 Contrast=0 Chromaticity=-29 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -48,7 +48,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Generic/Deep Shadows.pp3 b/rtdata/profiles/Generic/Deep Shadows.pp3 index 416cead89..e7aba345d 100644 --- a/rtdata/profiles/Generic/Deep Shadows.pp3 +++ b/rtdata/profiles/Generic/Deep Shadows.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=20 Saturated=20 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Generic/Equilibrated.pp3 b/rtdata/profiles/Generic/Equilibrated.pp3 index 8c8e787a9..b42576962 100644 --- a/rtdata/profiles/Generic/Equilibrated.pp3 +++ b/rtdata/profiles/Generic/Equilibrated.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Generic/High-Key.pp3 b/rtdata/profiles/Generic/High-Key.pp3 index c8351a292..169ce7226 100644 --- a/rtdata/profiles/Generic/High-Key.pp3 +++ b/rtdata/profiles/Generic/High-Key.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=5 Chromaticity=-10 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Generic/Natural 1.pp3 b/rtdata/profiles/Generic/Natural 1.pp3 index 5f90d9fe7..5c4a399a2 100644 --- a/rtdata/profiles/Generic/Natural 1.pp3 +++ b/rtdata/profiles/Generic/Natural 1.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Generic/Natural 2.pp3 b/rtdata/profiles/Generic/Natural 2.pp3 index b621535f9..6bb41b2b5 100644 --- a/rtdata/profiles/Generic/Natural 2.pp3 +++ b/rtdata/profiles/Generic/Natural 2.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=5 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.84892086330935235;0.69064748201438808;1;1; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Generic/Punchy 1.pp3 b/rtdata/profiles/Generic/Punchy 1.pp3 index e7bd9df08..1940202b7 100644 --- a/rtdata/profiles/Generic/Punchy 1.pp3 +++ b/rtdata/profiles/Generic/Punchy 1.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=10 Chromaticity=5 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Generic/Punchy 2.pp3 b/rtdata/profiles/Generic/Punchy 2.pp3 index a14e0e7f5..0415c5fb9 100644 --- a/rtdata/profiles/Generic/Punchy 2.pp3 +++ b/rtdata/profiles/Generic/Punchy 2.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=10 Chromaticity=5 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Pop/Pop 1.pp3 b/rtdata/profiles/Pop/Pop 1.pp3 index de7977994..cd27dd686 100644 --- a/rtdata/profiles/Pop/Pop 1.pp3 +++ b/rtdata/profiles/Pop/Pop 1.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.5;0.40000000000000002;1;1; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Pop/Pop 2 L.pp3 b/rtdata/profiles/Pop/Pop 2 L.pp3 index a838af63b..501f97a9f 100644 --- a/rtdata/profiles/Pop/Pop 2 L.pp3 +++ b/rtdata/profiles/Pop/Pop 2 L.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.12;0.29999999999999999;0.5;0.46000000000000002;1;1; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Pop/Pop 3 Skin.pp3 b/rtdata/profiles/Pop/Pop 3 Skin.pp3 index 539cbacab..9ca9bf43a 100644 --- a/rtdata/profiles/Pop/Pop 3 Skin.pp3 +++ b/rtdata/profiles/Pop/Pop 3 Skin.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.5;0.40000000000000002;1;1; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Pop/Pop 4 BW.pp3 b/rtdata/profiles/Pop/Pop 4 BW.pp3 index 3796d8880..00029081c 100644 --- a/rtdata/profiles/Pop/Pop 4 BW.pp3 +++ b/rtdata/profiles/Pop/Pop 4 BW.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.21199999999999999;0.11899999999999999;0.67400000000000004;0.77300000000000002;1;1; @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Portrait/Portrait Lejto.pp3 b/rtdata/profiles/Portrait/Portrait Lejto.pp3 index e923734e9..5460fe5c5 100644 --- a/rtdata/profiles/Portrait/Portrait Lejto.pp3 +++ b/rtdata/profiles/Portrait/Portrait Lejto.pp3 @@ -15,8 +15,8 @@ HighlightComprThreshold=0 ShadowCompr=50 CurveMode=Standard CurveMode2=SatAndValueBlending -Curve=1;0;0;0.079285714285714293;0.029999999999999999;0.18041642857142856;0.21375157142857143;0.70232600000000001;0.74883699999999997;1;1; -Curve2=1;0;0;0.075000000000000691;0.13571428571428609;0.29999999999999999;0.42857142857142855;0.7214285714285712;0.74642857142857144;1;1; +Curve=1;0;0;0.079285714285714293;0.03;0.18041642857142856;0.21375157142857143;0.702326;0.748837;1;1; +Curve2=1;0;0;0.075;0.13571428571428609;0.3;0.42857142857142855;0.7214285714285712;0.74642857142857144;1;1; [HLRecovery] Enabled=false @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Portrait/Portrait Smooth.pp3 b/rtdata/profiles/Portrait/Portrait Smooth.pp3 index 2392d5a54..e23693302 100644 --- a/rtdata/profiles/Portrait/Portrait Smooth.pp3 +++ b/rtdata/profiles/Portrait/Portrait Smooth.pp3 @@ -15,7 +15,7 @@ HighlightComprThreshold=0 ShadowCompr=50 CurveMode=FilmLike CurveMode2=Standard -Curve=1;0;0;0.443;0.57399999999999995;1;1; +Curve=1;0;0;0.443;0.574;1;1; Curve2=0; [HLRecovery] @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=-20 Contrast=-20 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=50 LCredsk=true LCurve=3;0;0;0.042700000000000002;0.014;0.16200000000000001;0.16200000000000001;0.54700000000000004;0.93300000000000005;1;1; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=75;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Natural TM.pp3 b/rtdata/profiles/Skintones/Skintones - Natural TM.pp3 index 13ff341a4..f692db268 100644 --- a/rtdata/profiles/Skintones/Skintones - Natural TM.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Natural TM.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.063241106719367585;6.9388939039072284e-18;0.49407114624505927;0.50197628458498023;0.92885375494071132;0.99604743083003922;1;1; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Natural.pp3 b/rtdata/profiles/Skintones/Skintones - Natural.pp3 index 7419c29d5..f6c2769a5 100644 --- a/rtdata/profiles/Skintones/Skintones - Natural.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Natural.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.063241106719367585;6.9388939039072284e-18;0.49407114624505927;0.50197628458498023;0.92885375494071132;0.99604743083003922;1;1; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Pale TM Bright.pp3 b/rtdata/profiles/Skintones/Skintones - Pale TM Bright.pp3 index 791b429aa..28a1db08c 100644 --- a/rtdata/profiles/Skintones/Skintones - Pale TM Bright.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Pale TM Bright.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.063241106719367585;6.9388939039072284e-18;0.49407114624505927;0.50197628458498023;0.92885375494071132;0.99604743083003922;1;1; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Pale TM.pp3 b/rtdata/profiles/Skintones/Skintones - Pale TM.pp3 index bd9fd36a9..825c177b5 100644 --- a/rtdata/profiles/Skintones/Skintones - Pale TM.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Pale TM.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.063241106719367585;6.9388939039072284e-18;0.49407114624505927;0.50197628458498023;0.92885375494071132;0.99604743083003922;1;1; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Pale.pp3 b/rtdata/profiles/Skintones/Skintones - Pale.pp3 index a95b5cb64..3387ec173 100644 --- a/rtdata/profiles/Skintones/Skintones - Pale.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Pale.pp3 @@ -74,7 +74,7 @@ Pastels=50 Saturated=50 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Soft Texture.pp3 b/rtdata/profiles/Skintones/Skintones - Soft Texture.pp3 index 7195fba6c..21841dce3 100644 --- a/rtdata/profiles/Skintones/Skintones - Soft Texture.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Soft Texture.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Strong Texture.pp3 b/rtdata/profiles/Skintones/Skintones - Strong Texture.pp3 index a663bdc0b..86e0fdc73 100644 --- a/rtdata/profiles/Skintones/Skintones - Strong Texture.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Strong Texture.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Studio TM.pp3 b/rtdata/profiles/Skintones/Skintones - Studio TM.pp3 index c4944c06a..870b84f4b 100644 --- a/rtdata/profiles/Skintones/Skintones - Studio TM.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Studio TM.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.15019762845849804;0.02766798418972332;0.31620553359683784;0.23715415019762845;0.49407114624505927;0.50197628458498023;0.92885375494071132;0.99604743083003922;1;1; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - Studio.pp3 b/rtdata/profiles/Skintones/Skintones - Studio.pp3 index 489a81419..7ee7ca690 100644 --- a/rtdata/profiles/Skintones/Skintones - Studio.pp3 +++ b/rtdata/profiles/Skintones/Skintones - Studio.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=3;0;0;0.15019762845849804;0.02766798418972332;0.31620553359683784;0.23715415019762845;0.49407114624505927;0.50197628458498023;0.92885375494071132;0.99604743083003922;1;1; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - StudioBase 1 TM.pp3 b/rtdata/profiles/Skintones/Skintones - StudioBase 1 TM.pp3 index 48423a585..3d45cedde 100644 --- a/rtdata/profiles/Skintones/Skintones - StudioBase 1 TM.pp3 +++ b/rtdata/profiles/Skintones/Skintones - StudioBase 1 TM.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtdata/profiles/Skintones/Skintones - StudioBase 1.pp3 b/rtdata/profiles/Skintones/Skintones - StudioBase 1.pp3 index d8b947a15..38740fd61 100644 --- a/rtdata/profiles/Skintones/Skintones - StudioBase 1.pp3 +++ b/rtdata/profiles/Skintones/Skintones - StudioBase 1.pp3 @@ -55,7 +55,7 @@ AfterCurve=0; Brightness=0 Contrast=0 Chromaticity=0 -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; @@ -74,7 +74,7 @@ Pastels=0 Saturated=0 PSThreshold=0;75; ProtectSkins=false -AvoidColorShift=true +AvoidColorShift=false PastSatTog=true SkinTonesCurve=0; diff --git a/rtengine/LUT.h b/rtengine/LUT.h index 8dfb0ba6f..83a85fb65 100644 --- a/rtengine/LUT.h +++ b/rtengine/LUT.h @@ -79,11 +79,13 @@ template class LUT { -private: +protected: // list of variables ordered to improve cache speed unsigned int maxs; T * data; - unsigned int clip, size, owner; + unsigned int clip, size; +private: + unsigned int owner; #if defined( __SSE2__ ) && defined( __x86_64__ ) __m128 maxsv __attribute__ ((aligned (16))); __m128 sizev __attribute__ ((aligned (16))); @@ -180,6 +182,22 @@ public: clip = flags; } + /** @brief Get the number of element in the LUT (i.e. dimension of the array) + * For a LUT(500), it will return 500 + * @return number of element in the array + */ + int getSize() { + return size; + } + + /** @brief Get the highest value possible (i.e. dimension of the array) + * For a LUT(500), it will return 499, because 500 elements, starting from 0, goes up to 499 + * @return number of element in the array + */ + int getUpperBound() { + return size>0 ? size-1 : 0; + } + LUT & operator=(LUT &rhs) { if (this != &rhs) { if (rhs.size>this->size) @@ -374,4 +392,57 @@ public: } }; +/** @brief LUT subclass handling hue values specifically. + The array has a fixed size of float values and have to be in the [0.; 1.] range in both axis (no error checking implemented) */ +class HueLUT : public LUTf { + public: + HueLUT() : LUTf() {} + HueLUT(bool createArray) : LUTf() { + if (createArray) + this->operator () (501, LUT_CLIP_BELOW|LUT_CLIP_ABOVE); + } + + void create() { + this->operator () (501, LUT_CLIP_BELOW|LUT_CLIP_ABOVE); + } + + // use with integer indices + float& operator[](int index) const { + return data[ rtengine::LIM(index, 0, size-1) ]; + } + + // use with float indices in the [0.;1.] range + float operator[](float index) const { + int idx = int(index*500.f); // don't use floor! The difference in negative space is no problems here + if (index<0.f) + return data[0]; + else if (index > 1.f) + return data[size - 1]; + + float balance = index - float(idx/500.f); + float h1 = data[idx]; + float h2 = data[idx + 1]; + + if (h1==h2) + return h1; + if ((h1 > h2) && (h1-h2 > 0.5f)){ + h1 -= 1.f; + float value = h1 + balance * (h2-h1); + if (value < 0.f) + value += 1.f; + return value; + } + else if (h2-h1 > 0.5f) { + h2 -= 1.f; + float value = h1 + balance * (h2-h1); + if (value < 0.f) + value += 1.f; + return value; + } + else + return h1 + balance * (h2-h1); + } +}; + + #endif /* LUT_H_ */ diff --git a/rtengine/color.cc b/rtengine/color.cc index ad6effc80..38d0d96fa 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -47,6 +47,7 @@ namespace rtengine { LUTf Color::gammatab_26_11; LUTf Color::igammatab_24_17; LUTf Color::gammatab_24_17a; + LUTf Color::gammatab_13_2; // Wikipedia sRGB: Unlike most other RGB color spaces, the sRGB gamma cannot be expressed as a single numerical value. // The overall gamma is approximately 2.2, consisting of a linear (gamma 1.0) section near black, and a non-linear section elsewhere involving a 2.4 exponent @@ -54,7 +55,8 @@ namespace rtengine { const double Color::sRGBGamma = 2.2; const double Color::sRGBGammaCurve = 2.4; - const double Color::eps_max=580.40756; //(MAXVALF* 216.0f/24389.0); + const double Color::eps_max=580.40756; //(MAXVALF* 216.0f/24389.0); + const double Color::eps=216.0f/24389.0;//0.008856 const double Color::kappa=24389.0/27.0;//903.29630; const float Color::D50x=0.9642f; //0.96422; @@ -155,6 +157,7 @@ namespace rtengine { gammatab_26_11(65536,0); igammatab_24_17(65536,0); gammatab_24_17a(65536,0); + gammatab_13_2(65536,0); for (int i=0; i<65536; i++) gammatab_srgb[i] = (65535.0 * gamma2 (i/65535.0)); @@ -176,6 +179,8 @@ namespace rtengine { gammatab_4[i] = (65535.0 * gamma4 (i/65535.0)); for (int i=0; i<65536; i++) igammatab_4[i] = (65535.0 * igamma4 (i/65535.0)); + for (int i=0; i<65536; i++) + gammatab_13_2[i] = (65535.0 * gamma13_2 (i/65535.0)); for (int i=0; i<65536; i++) gammatab_26_11[i] = (65535.0 * gamma26_11 (i/65535.0)); @@ -270,6 +275,29 @@ namespace rtengine { } } + void Color::hsl2rgb01 (float h, float s, float l, float &r, float &g, float &b) { + + if (s == 0) + r = g = b = l; // achromatic + else { + double m2; + double h_ = double(h); + double s_ = double(s); + double l_ = double(l); + + if (l <= 0.5f) + m2 = l_ * (1.0 + s_); + else { + m2 = l_ + s_ - l_ * s_; + } + + double m1 = 2.0 * l_ - m2; + + r = float(hue2rgb (m1, m2, h_ * 6.0 + 2.0)); + g = float(hue2rgb (m1, m2, h_ * 6.0)); + b = float(hue2rgb (m1, m2, h_ * 6.0 - 2.0)); + } + } void Color::rgb2hsv(float r, float g, float b, float &h, float &s, float &v) { double var_R = r / 65535.0; @@ -299,13 +327,13 @@ namespace rtengine { void Color::hsv2rgb (float h, float s, float v, float &r, float &g, float &b) { - float h1 = h*6; // sector 0 to 5 + float h1 = h*6.f; // sector 0 to 5 int i = (int)h1; // floor() is very slow, and h1 is always >0 float f = h1 - i; // fractional part of h - float p = v * ( 1 - s ); - float q = v * ( 1 - s * f ); - float t = v * ( 1 - s * ( 1 - f ) ); + float p = v * ( 1.f - s ); + float q = v * ( 1.f - s * f ); + float t = v * ( 1.f - s * ( 1.f - f ) ); float r1,g1,b1; @@ -316,9 +344,9 @@ namespace rtengine { else if (i==5) {r1 = v; g1 = p; b1 = q;} else /*i==(0|6)*/ {r1 = v; g1 = t; b1 = p;} - r = ((r1)*65535.0); - g = ((g1)*65535.0); - b = ((b1)*65535.0); + r = ((r1)*65535.0f); + g = ((g1)*65535.0f); + b = ((b1)*65535.0f); } // Function copied for speed concerns @@ -399,14 +427,13 @@ namespace rtengine { z = ((xyz_prophoto[2][0]*r + xyz_prophoto[2][1]*g + xyz_prophoto[2][2]*b)) ; } - void Color::rgbxyz (float r, float g, float b, float &x, float &y, float &z, double xyz_rgb[3][3]) { + void Color::rgbxyz (float r, float g, float b, float &x, float &y, float &z, const double xyz_rgb[3][3]) { x = ((xyz_rgb[0][0]*r + xyz_rgb[0][1]*g + xyz_rgb[0][2]*b)) ; y = ((xyz_rgb[1][0]*r + xyz_rgb[1][1]*g + xyz_rgb[1][2]*b)) ; z = ((xyz_rgb[2][0]*r + xyz_rgb[2][1]*g + xyz_rgb[2][2]*b)) ; } - - void Color::xyz2rgb (float x, float y, float z, float &r, float &g, float &b, double rgb_xyz[3][3]) { + void Color::xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const double rgb_xyz[3][3]) { //Transform to output color. Standard sRGB is D65, but internal representation is D50 //Note that it is only at this point that we should have need of clipping color data @@ -608,6 +635,183 @@ namespace rtengine { } + void Color::interpolateRGBColor (const float balance, const float r1, const float g1, const float b1, const float r2, const float g2, const float b2, int toDo, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo) { + float X1, Y1, Z1, X2, Y2, Z2, X, Y, Z; + float L1, L2, a_1, b_1, a_2, b_2, a, b; + float c1, c2, h1, h2; + float RR,GG,BB; + float Lr; + + // converting color 1 to Lch + Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); + Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1); + Color::Lab2Lch(a_1, b_1, c1, h1); + Lr=L1/327.68f;//for gamutlch + //gamut control on r1 g1 b1 + #ifndef NDEBUG + bool neg=false; + bool more_rgb=false; + + //gamut control : Lab values are in gamut + Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); + #else + Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); + #endif + + L1=Lr*327.68f; + + // converting color 2 to Lch + Color::rgbxyz(r2, g2, b2, X2, Y2, Z2, xyz_rgb); + Color::XYZ2Lab(X2, Y2, Z2, L2, a_2, b_2); + Color::Lab2Lch(a_2, b_2, c2, h2); + + Lr=L2/327.68f;//for gamutlch + //gamut control on r2 g2 b2 + #ifndef NDEBUG + neg=false; + more_rgb=false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(h2,Lr,c2, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); + #else + Color::gamutLchonly(h2,Lr,c2, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); + #endif + L2=Lr*327.68f; + + // interpolating Lch values + if (toDo & CHANNEL_LIGHTNESS) { L1 = L1 + (L2-L1)*balance;if(L1<0.f) L1=0.f;}//do not allow negative L + if (toDo & CHANNEL_CHROMATICITY) {c1 = c1 + (c2-c1)*balance;if(c1<0.f) c1=0.f; if(c1>180.f) c1=180.f;}//limit C to reasonable value + if (toDo & CHANNEL_HUE) h1 = interpolatePolarHue_PI(h1, h2, balance); + + // here I have put gamut control with gamutlchonly on final process + Lr=L1/327.68f;//for gamutlch + #ifndef NDEBUG + neg=false; + more_rgb=false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); + #else + //gamut control : Lab values are in gamut + Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); + #endif + //convert CH ==> ab + L1=Lr*327.68f; + + // converting back to rgb + Color::Lch2Lab(c1, h1, a, b); + Color::Lab2XYZ(L1, a, b, X, Y, Z); + Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz); + } + + + void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int algm, const float balance, int twoc, int metchrom, + bool chr, bool lum, float chromat, float luma, const float r1, const float g1, const float b1, + const float xl, const float yl, const float zl, const float x2, const float y2, const float z2, + int toDo, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo) + { + float X1, Y1, Z1, X2, Y2, Z2, X, Y, Z,XL,YL,ZL; + float L1, L2, LL, a_1, b_1, a_2, b_2, a, b,a_L,b_L; + float c1, c2, h1, h2,cL,hL; + float RR,GG,BB; + float Lr; + float slc=0.f; + float hh=0.f; + float ll=0.f; + float sh=0.f; + bool LCH=false; + + float ha,hb,hc,ba; + float c_1,h_1; + // converting color 1 to Lab (image) + Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); + if(algm == 1) {//use H interpolate + Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1); + //Color::Lab2Lch(a_1, b_1, c_1, h_1) ; + } + // converting color l lab(low) first color + if(twoc==0) { // 2 colours + //Color::rgbxyz(rl, gl, bl, XL, YL, ZL, xyz_rgb); + XL=xl; + YL=yl; + ZL=zl; + if(algm <= 1) {//use H interpolate + Color::XYZ2Lab(XL, YL, ZL, LL, a_L, b_L); + } + } + + // converting color 2 to lab (universal or high) + X2=x2; + Y2=y2; + Z2=z2; + float c_2,h_2; + if(algm == 1 ) { + Color::XYZ2Lab(X2, Y2, Z2, L2, a_2, b_2); + //Color::Lab2Lch(a_2, b_2, c_2, h_2) ; + } + float bal,balH,cal,calH,calm; + bal=balH=balance; + cal=calH=calm=1.f-chromat; + float med=(iphigh+iplow)/2.f; + float medH=(iphigh+iplow)/2.f; + float medL=(iphigh+iplow)/2.f; + + med=1.f;medH=0.f;//new algo for 2 colors + float calan; + calan=chromat; + + float calby; + calby=luma; + + if(twoc==0) { // 2 colours + calan=chromat; + + //calculate new balance in function of (arbitrary) "med".. I hope no error !! + if (realL > iplow && realL<=med) bal = realL*balance/(iplow-med) - med*balance/(iplow-med); + else if (realL <= iplow) bal = realL*balance/iplow; + + if (realL > medH && realL <= iphigh) balH = realL*balance/(iphigh-medH) - medH*balance/(iphigh-medH); + else if (realL > iphigh) balH = realL*balance*(iphigh-1.f) - balance*(iphigh-1.f); + + //calculate new balance chroma + if (realL > iplow && realL<=med) cal = realL*calan/(iplow-med) - med*calan/(iplow-med); + else if (realL <= iplow) cal = realL*calan/iplow; + + if (realL > medH && realL <= iphigh) calH = realL*calan/(iphigh-medH) - medH*calan/(iphigh-medH); + else if (realL > iphigh) calH = realL*calan;//*(iphigh-1.f) - calan*(iphigh-1.f);//it is better without transition in highlight + } + + float hX=0.f; + float hLL,hH,ccL,ccH,llH,aaH,bbH; + + if(algm <=1){ + if(twoc==0 && metchrom==3) { // 2 colours only with special "ab" + if(algm==1) { + aaH=a_1 + (a_2-a_1)*calH;bbH=b_1 + (b_2-b_1)*calH;//pass to line after + a_1=aaH + (a_L-aaH)*cal*balance;b_1=bbH + (b_L-bbH)*cal*balance; + } + } + else if(twoc==1) { + if(metchrom==0) { + a_1=a_1 + (a_2-a_1)*balance; + b_1=b_1 + (b_2-b_1)*balance; + } + else if(metchrom==1){ + a_1=a_1 + (a_2-a_1)*calan*balance; + b_1=b_1 + (b_2-b_1)*calan*balance; + } + else if(metchrom==2) { + a_1=a_1 + (a_2-a_1)*calan*balance; + b_1=b_1 + (b_2-b_1)*calby*balance; + } + } + } + else + h1=hX; + + Color::Lab2XYZ(L1, a_1, b_1, X, Y, Z); + + Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz);// ro go bo in gamut + } + void Color::calcGamma (double pwr, double ts, int mode, int imax, double &gamma0, double &gamma1, double &gamma2, double &gamma3, double &gamma4, double &gamma5) { //from Dcraw (D.Coffin) int i; @@ -657,9 +861,9 @@ namespace rtengine { float y= Y; float fx,fy,fz; - fx = (x<65535.0f ? cachef[std::max(x,0.f)] : (327.68f*exp(log(x/MAXVALF)/3.0f ))); - fy = (y<65535.0f ? cachef[std::max(y,0.f)] : (327.68f*exp(log(y/MAXVALF)/3.0f ))); - fz = (z<65535.0f ? cachef[std::max(z,0.f)] : (327.68f*exp(log(z/MAXVALF)/3.0f ))); + fx = (x<=65535.0f ? cachef[std::max(x,0.f)] : (327.68f*exp(log(x/MAXVALF)/3.0f ))); + fy = (y<=65535.0f ? cachef[std::max(y,0.f)] : (327.68f*exp(log(y/MAXVALF)/3.0f ))); + fz = (z<=65535.0f ? cachef[std::max(z,0.f)] : (327.68f*exp(log(z/MAXVALF)/3.0f ))); L = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; a = (500.0f * (fx - fy) ); @@ -691,15 +895,75 @@ namespace rtengine { gamutmap(X,Y,Z,wp); - float fx = (X<65535.0 ? cachef[X] : (327.68*exp(log(X/MAXVALF)/3.0 ))); - float fy = (Y<65535.0 ? cachef[Y] : (327.68*exp(log(Y/MAXVALF)/3.0 ))); - float fz = (Z<65535.0 ? cachef[Z] : (327.68*exp(log(Z/MAXVALF)/3.0 ))); + float fx = (X<=65535.0 ? cachef[X] : (327.68*exp(log(X/MAXVALF)/3.0 ))); + float fy = (Y<=65535.0 ? cachef[Y] : (327.68*exp(log(Y/MAXVALF)/3.0 ))); + float fz = (Z<=65535.0 ? cachef[Z] : (327.68*exp(log(Z/MAXVALF)/3.0 ))); L = (116.0 * fy - 5242.88); //5242.88=16.0*327.68; a = (500.0 * (fx - fy) ); b = (200.0 * (fy - fz) ); } + void Color::Lab2Lch(float a, float b, float &c, float &h) { + c = (sqrtf(a*a+b*b))/327.68f; + h = xatan2f(b, a); + } + + void Color::Lch2Lab(float c, float h, float &a, float &b) { + float2 sincosval = xsincosf(h); + a = 327.68f * c * sincosval.y; + b = 327.68f * c * sincosval.x; + } + + void Color::Luv2Lch(float u, float v, float &c, float &h) { + c = sqrtf(u*u+v*v); + h = xatan2f(v, u); //WARNING: should we care of division by zero here? + if (h < 0.f) + h += 1.f; + } + + void Color::Lch2Luv(float c, float h, float &u, float &v) { + float2 sincosval = xsincosf(h); + u = c * sincosval.x; + v = c * sincosval.y; + } + + // NOT TESTED + void Color::XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v) { + + X /= 65535.f; + Y /= 65535.f; + Z /= 65535.f; + + if (Y > float(eps)) + L = 116.f * pow(Y, 1.f/3.f) -16.f; + else + L = float(kappa) * Y; + u = 13.f * L * float(u0); + v = 13.f * L * float(v0); + } + + // NOT TESTED + void Color::Luv2XYZ (float L, float u, float v, float &X, float &Y, float &Z) { + if (L > float(epskap)) { + float t = (L+16.f) / 116.f; + Y = t*t*t; + } + else + Y = L/float(kappa); + + float a = ((52.f*L) / (u+13.f*L*float(u0)) -1.f) / 3.f; + float d = Y * (((39*L) / (v+13*float(v0))) -5.f); + float b = -5.f*Y; + X = (d-b) / (a+1.f/3.f); + + Z = X*a+b; + + X *= 65535.f; + Y *= 65535.f; + Z *= 65535.f; + } + /* * Gamut mapping algorithm * Copyright (c) 2010-2011 Emil Martinec @@ -1055,9 +1319,9 @@ munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); * bool neg and moreRGB : only in DEBUG mode to calculate iterations for negatives values and > 65535 */ #ifdef _DEBUG - void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb) + void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb) #else - void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) + void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) #endif { const float ClipLevel = 65535.0f; @@ -1090,8 +1354,17 @@ munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); #ifdef _DEBUG neg=true; #endif - if (Lprov1 < 0.01f) - Lprov1 = 0.01f; + if (Lprov1 < 0.1f) Lprov1 = 0.1f; + //gamut for L with ultra blue : we can improve the algorithm ... thinner, and other color ??? + if(HH < -0.9f && HH > -1.55f ) {//ultra blue + if(Chprov1 > 160.f) if (Lprov1 < 5.f) Lprov1 = 5.f;//very very very very high chroma + if(Chprov1 > 140.f) if (Lprov1 < 3.5f) Lprov1 = 3.5f; + if(Chprov1 > 120.f) if (Lprov1 < 2.f) Lprov1 = 2.f; + if(Chprov1 > 105.f) if (Lprov1 < 1.f) Lprov1 = 1.f; + if(Chprov1 > 90.f) if (Lprov1 < 0.7f) Lprov1 = 0.7f; + if(Chprov1 > 50.f) if (Lprov1 < 0.5f) Lprov1 = 0.5f; + if(Chprov1 > 20.f) if (Lprov1 < 0.4f) Lprov1 = 0.4f; + } Chprov1 *= higherCoef; // decrease the chromaticity value if (Chprov1 <= 3.0f) Lprov1 += lowerCoef; diff --git a/rtengine/color.h b/rtengine/color.h index a269bb36a..f2269e50e 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -26,6 +26,8 @@ #include "iccstore.h" #include "iccmatrices.h" #include "sleef.c" +#define SAT(a,b,c) ((float)max(a,b,c)-(float)min(a,b,c))/(float)max(a,b,c) + namespace rtengine { #ifdef _DEBUG @@ -83,12 +85,34 @@ private: // Separated from init() to keep the code clear static void initMunsell (); - static double hue2rgb(double p, double q, double t); + static double hue2rgb(double p, double q, double t); public: + + typedef enum Channel { + CHANNEL_RED = 1<<0, + CHANNEL_GREEN = 1<<1, + CHANNEL_BLUE = 1<<2, + CHANNEL_HUE = 1<<3, + CHANNEL_SATURATION = 1<<4, + CHANNEL_VALUE = 1<<5, + CHANNEL_LIGHTNESS = 1<<6, + CHANNEL_CHROMATICITY = 1<<7 + } eChannel; + + typedef enum InterpolationPath { + IP_SHORTEST, /// Interpolate color using the shortest path between 2 hues + IP_LONGEST, /// Interpolate color using the longest path between 2 hues + } eInterpolationPath; + + typedef enum InterpolationDirection { + ID_UP, /// Interpolate color by increasing the hue value, crossing the upper limit + ID_DOWN /// Interpolate color by decreasing the hue value, crossing the lower limit + } eInterpolationDirection; + const static double sRGBGamma; // standard average gamma const static double sRGBGammaCurve; // 2.4 in the curve - const static double eps_max, kappa, epskap; + const static double eps, eps_max, kappa, epskap; const static float D50x, D50z; const static double u0, v0; @@ -111,6 +135,7 @@ public: static LUTf gammatab_26_11; static LUTf igammatab_24_17; static LUTf gammatab_24_17a; + static LUTf gammatab_13_2; // look-up tables for the simple exponential gamma static LUTf gammatab; @@ -156,6 +181,17 @@ public: */ static void hsl2rgb (float h, float s, float l, float &r, float &g, float &b); + /** + * @brief Convert hue/saturation/luminance in red/green/blue + * @param h hue channel [0 ; 1] + * @param s saturation channel [0 ; 1] + * @param l luminance channel [0 ; 1] + * @param r red channel [0 ; 1] (return value) + * @param g green channel [0 ; 1] (return value) + * @param b blue channel [0 ; 1] (return value) + */ + static void hsl2rgb01 (float h, float s, float l, float &r, float &g, float &b); + /** * @brief Convert red green blue to hue saturation value @@ -244,13 +280,13 @@ public: * @param b blue channel [same range than xyz channel] (return value) * @param rgb_xyz[3][3] transformation matrix to use for the conversion */ - static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, double rgb_xyz[3][3]); + static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const double rgb_xyz[3][3]); static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const float rgb_xyz[3][3]); /** * @brief Convert rgb in xyz - * Color space : undefined - use matrix adhoc : xyz_rgb[3][3] (iccmatrice.h) in function of working space + * Color space : undefined - use adhoc matrix : xyz_rgb[3][3] (iccmatrice.h) in function of working space * @param r red channel [0 ; 1] or [0 ; 65535] * @param g green channel [0 ; 1] or [0 ; 65535] * @param b blue channel [0 ; 1] or [0 ; 65535] @@ -259,7 +295,7 @@ public: * @param z Z coordinate [same range than rgb channel] (return value) * @param xyz_rgb[3][3] transformation matrix to use for the conversion */ - static void rgbxyz (float r, float g, float b, float &x, float &y, float &z, double xyz_rgb[3][3]); + static void rgbxyz (float r, float g, float b, float &x, float &y, float &z, const double xyz_rgb[3][3]); /** @@ -283,7 +319,7 @@ public: * @param a channel [-42000 ; +42000] ; can be more than 42000 (return value) * @param b channel [-42000 ; +42000] ; can be more than 42000 (return value) */ - static void XYZ2Lab(float X, float Y, float Z, float &L, float &a, float &b); + static void XYZ2Lab(float x, float y, float z, float &L, float &a, float &b); /** @@ -310,6 +346,72 @@ public: static void Yuv2Lab(float Y, float u, float v, float &L, float &a, float &b, double wp[3][3]); + /** + * @brief Convert the 'a' and 'b' channels of the L*a*b color space to 'c' and 'h' channels of the Lch color space (channel 'L' is identical [0 ; 32768]) + * @param a 'a' channel [-42000 ; +42000] ; can be more than 42000 + * @param b 'b' channel [-42000 ; +42000] ; can be more than 42000 + * @param c 'c' channel return value, in [0 ; 42000] ; can be more than 42000 (return value) + * @param h 'h' channel return value, in [-PI ; +PI] (return value) + */ + static void Lab2Lch(float a, float b, float &c, float &h); + + + /** + * @brief Convert 'c' and 'h' channels of the Lch color space to the 'a' and 'b' channels of the L*a*b color space (channel 'L' is identical [0 ; 32768]) + * @param c 'c' channel value, in [0 ; 42000] + * @param h 'h' channel value, in [-PI ; +PI] + * @param a 'a' channel [-42000 ; +42000] ; can be more than 42000 (return value) + * @param b 'b' channel [-42000 ; +42000] ; can be more than 42000 (return value) + */ + static void Lch2Lab(float c, float h, float &a, float &b); + + + /** + * @brief Convert the 'u' and 'v' channels of the Luv color space to 'c' and 'h' channels of the Lch color space ('L' channel is identical) + * @param u 'u' channel [unknown range!] + * @param v 'v' channel [unknown range!] + * @param c 'c' channel [unknown range!] (return value) + * @param h 'h' channel [-PI ; +PI] (return value) + */ + static void Luv2Lch(float u, float v, float &c, float &h); + + + /** + * @brief Convert 'c' and 'h' channels of the Lch color space to the 'u' and 'v' channels of the Luv color space ('L' channel is identical) + * @param c 'c' channel [unknown range!] ; can be more than 42000 + * @param h 'h' channel [-PI ; +PI] + * @param u 'u' channel [unknown range!] (return value) + * @param v 'v' channel [unknown range!] (return value) + */ + static void Lch2Luv(float c, float h, float &u, float &v); + + + /** + * @brief Convert the XYZ values to Luv values + * Warning: this method has never been used/tested so far + * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param L 'L' channel [0 ; 32768] (return value) + * @param u 'u' channel [-42000 ; 42000] ; can be more than 42000 (return value) + * @param v 'v' channel [-42000 ; 42000] ; can be more than 42000 (return value) + */ + static void XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v); + + + /** + * @brief Convert the Luv values to XYZ values + * Warning: this method has never been used/tested so far + * @param L 'L' channel [0 ; 32768] + * @param u 'u' channel [-42000 ; 42000] ; can be more than 42000 + * @param v 'v' channel [-42000 ; 42000] ; can be more than 42000 + * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) + * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) + * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) + */ + static void Luv2XYZ (float L, float u, float v, float &X, float &Y, float &Z); + + /** * @brief Return "f" in function of CIE's kappa and epsilon constants * @param f f can be fx fy fz where: @@ -332,6 +434,259 @@ public: } + /** + * @brief Calculate the effective direction (up or down) to linearly interpolating 2 colors so that it follows the shortest or longest path + * @param h1 First hue [0 ; 1] + * @param h2 Second hue [0 ; 1] + * @param path Path to follow (shortest/longest) + * @return The interpolation direction + */ + static inline eInterpolationDirection getHueInterpolationDirection (double h1, double h2, eInterpolationPath path) { + if (path==IP_SHORTEST) { + if (h2>h1) { + if (h2-h1<=0.5) + return ID_UP; + else + return ID_DOWN; + } + else { + if (h1-h2<=0.5) + return ID_DOWN; + else + return ID_UP; + } + } + else { + if (h2>h1) { + if (h2-h1<=0.5) + return ID_DOWN; + else + return ID_UP; + } + else { + if (h1-h2<=0.5) + return ID_UP; + else + return ID_DOWN; + } + } + } + + + /** + * @brief Calculate a color by linearly interpolating 2 colors + * @param h1 First hue + * @param h2 Second hue + * @param balance Factor from 0 (first hue) to 1 (second hue) + * @param dir Tells which direction the interpolation have to follow. You can get the value with getHueInterpolationDirection + * @return The interpolated hue + */ + static inline double interpolateHueHSV (double h1, double h2, double balance, eInterpolationDirection dir) { + if (h1==h2) + return h1; + if (dir==ID_DOWN) { + if (h1 < h2){ + double temp = h1; + h1 = h2-1.; + h2 = temp; + balance = 1. - balance; + } + double h3 = h1 + balance * (h2-h1); + if (h3<0.) + h3 += 1.; + return h3; + } + else { + if (h1 > h2){ + h2 += 1.; + } + double h3 = h1 + balance * (h2-h1); + if (h3>1.) + h3 -= 1.; + return h3; + } + } + + /** + * @brief Interpolate 2 colors from their respective red/green/blue channels, with a balance factor + * @param balance gives weight to the first and second color [0 ; 1] + * 0. = output color == first color + * 0.5 = output color == equally mixed colors + * 1. = output color == second color + * @param r1 red channel of color 1 [0 ; 65535] + * @param g1 green channel of color 1 [0 ; 65535] + * @param b1 blue channel of color 1 [0 ; 65535] + * @param r2 red channel of color 2 [0 ; 65535] + * @param g2 green channel of color 2 [0 ; 65535] + * @param b2 blue channel of color 2 [0 ; 65535] + * @param channels bitfield of channel to interpolate (CHANNEL_LIGHTNESS|CHANNEL_CHROMATICITY|CHANNEL_HUE) + * @param xyz_rgb color space + * @param ro red channel of output color [0 ; 65535] (return value) + * @param go green channel of output color [0 ; 65535] (return value) + * @param bo blue channel of output color [0 ; 65535] (return value) + */ + static void interpolateRGBColor (const float balance, const float r1, const float g1, const float b1, const float r2, const float g2, const float b2, int channels, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo); + + /** + * @brief Interpolate 2 colors from their respective red/green/blue channels, with a balance factor + * @param realL luminance hsl [0; 1] + * @param iplow low luminance for rl [0;1] + * @param ihigh high luminance for r2 [0;1] + * @param algm algorithm [0;2] + * @param balance gives weight to the first and second color [0 ; 1] + * 0. = output color == first color + * 0.5 = output color == equally mixed colors + * 1. = output color == second color + * @param twoc 2 colors or 512 int + * @param r1 red channel of color 1 [0 ; 65535] + * @param g1 green channel of color 1 [0 ; 65535] + * @param b1 blue channel of color 1 [0 ; 65535] + * @param rl red channel of color low [0 ; 65535] + * @param gl green channel of color low [0 ; 65535] + * @param bl blue channel of color low [0 ; 65535] + + * @param r2 red channel of color 2 or high[0 ; 65535] + * @param g2 green channel of color 2 or high[0 ; 65535] + * @param b2 blue channel of color 2 [or high 0 ; 65535] + * @param channels bitfield of channel to interpolate (CHANNEL_LIGHTNESS|CHANNEL_CHROMATICITY|CHANNEL_HUE) + * @param xyz_rgb color space + * @param rgb_xyz inverse color space + * @param ro red channel of output color [0 ; 65535] (return value) + * @param go green channel of output color [0 ; 65535] (return value) + * @param bo blue channel of output color [0 ; 65535] (return value) + */ + static void interpolateRGBColor (float realL, float iplow, float iphigh, int algm, const float balance, int twoc, int metchrom, bool chr, bool lum, float chromat, float luma, const float r1, const float g1, const float b1, const float xl, const float yl, const float zl, const float x2, const float y2, const float z2, int channels, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo); + + + /** + * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [0;1] range + * Chose the shorter path from hue 1 to hue 2. + * @param h1 First hue [0; 1] + * @param h2 Second hue [0; 1] + * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 + * @return the interpolated value [0;1] + */ + /*template + static inline T interpolatePolarHue_01 (T h1, T h2, U balance) { + + if (h1==h2) + return h1; + if ((h1 > h2) && (h1-h2 > T(0.5))){ + h1 -= T(1.); + double value = h1 + T(balance) * (h2-h1); + if (value < T(0.)) + value += T(1.); + return value; + } + else if (h2-h1 > T(0.5)) { + h2 -= T(1.); + double value = h1 + T(balance) * (h2-h1); + if (value < T(0.)) + value += T(1.); + return value; + } + else + return h1 + T(balance) * (h2-h1); + }*/ + + + /** + * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [-PI ; +PI] range + * Chose the shorter path from hue 1 to hue 2. + * @param h1 First hue [-PI ; +PI] + * @param h2 Second hue [-PI ; +PI] + * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 + * @return the interpolated value [-PI ; +PI] + */ + /*template + static inline T interpolatePolarHue_PI (T h1, T h2, U balance) { + if (h1==h2) + return h1; + if ((h1 > h2) && (h1-h2 > T(M_PI))){ + h1 -= T(2*M_PI); + T value = h1 + T(balance) * (h2-h1); + if (value < T(-M_PI)) + value += T(2*M_PI); + return value; + } + else if (h2-h1 > T(M_PI)) { + h2 -= T(2*M_PI); + T value = h1 + T(balance) * (h2-h1); + if (value < T(0)) + value += T(2*M_PI); + return value; + } + else + return h1 + T(balance) * (h2-h1); + }*/ + + + /** + * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [0;1] range + * Chose the shorter path from hue 1 to hue 2. + * @param h1 First hue [0; 1] + * @param h2 Second hue [0; 1] + * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 + * @return the interpolated value [0;1] + */ + template + static inline T interpolatePolarHue_01 (T h1, T h2, U balance) { + float d = h2 - h1; + float f; + f=T(balance); + double h; + if (h1 > h2){ + std::swap(h1,h2); + d = -d; + f=1.f-f; + } + if (d < T(-M_PI) || d < T(0) || d > T(M_PI)) { //there was an inversion here !! d > T(M_PI) + h1 += T(2*M_PI); + h = h1 + f*(h2-h1); + h = std::fmod(h,2*M_PI); + } + else h = h1 + f * d; + // not strictly necessary..but in case of + if(h < T(-M_PI)) h=T(2*M_PI)-h; + if(h > T(M_PI)) h=h-T(2*M_PI); + + return h; + } + + + /** + * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [-PI ; +PI] range + * Chose the shorter path from hue 1 to hue 2. + * @param h1 First hue [-PI ; +PI] + * @param h2 Second hue [-PI ; +PI] + * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 + * @return the interpolated value [-PI ; +PI ] + */ + template + static inline T interpolatePolarHue_PI (T h1, T h2, U balance) { + float d = h2 - h1; + float f; + f=T(balance); + double h; + if (h1 > h2){ + std::swap(h1,h2); + d = -d; + f=1.f-f; + } + if (d < T(0) || d < T(0.5) || d > T(1.)) { //there was an inversion here !! d > T(M_PI) + h1 += T(1.); + h = h1 + f*(h2-h1); + h = std::fmod(h,1.); + } + else h = h1 + f * d; + // not strictly necessary..but in case of + if(h < T(0)) h=T(1.)-h; + if(h > T(1)) h=h-T(1.); + + return h; + } + + /** * @brief Get the gamma curves' parameters used by LCMS2 * @param pwr gamma value [>1] @@ -347,7 +702,7 @@ public: */ static void calcGamma (double pwr, double ts, int mode, int imax, double &gamma0, double &gamma1, double &gamma2, double &gamma3, double &gamma4,double &gamma5); - + /** * @brief Used by Black and White to correct gamma for each channel red, green and blue channel * @param r red channel input and output value [0 ; 65535] @@ -506,6 +861,14 @@ public: static inline double igamma26_11 (double x) { return x <= 0.054127 ? x/11.0 : exp(log((x+0.086603)/1.086603)*2.6); } + /** + * @brief Get the gamma value for Gamma=1.3 Slope=2 + * @param x red, green or blue channel's value [0 ; 1] + * @return the gamma modified's value [0 ; 1] + */ + static inline double gamma13_2 (double x) { + return x <= 0.016613 ? x*2.0 : 1.009968*exp(log(x)/1.3)-0.016613; + } // gamma function with adjustable parameters @@ -612,10 +975,10 @@ public: * @param moreRGB (Debug target only) to calculate iterations for values >65535 */ #ifdef _DEBUG - static void gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); + static void gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); static void gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); #else - static void gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); + static void gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); static void gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); #endif diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 60afbf8fe..a0916615c 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -106,6 +106,30 @@ namespace rtengine { } + /** @ brief Return the number of control points of the curve + * This method return the number of control points of a curve. Not suitable for parametric curves. + * @return number of control points of the curve. 0 will be sent back for Parametric curves + */ + int Curve::getSize () const { + return N; + } + + /** @ brief Return the a control point's value + * This method return a control points' value. Not suitable for parametric curves. + * @param cpNum id of the control points we're interested in + * @param x Y value of the control points, or -1 if invalid + * @param y Y value of the control points, or -1 if invalid + */ + void Curve::getControlPoint(int cpNum, double &x, double &y) const { + if (this->x && cpNum < N) { + x = this->x[cpNum]; + y = this->y[cpNum]; + } + else { + x = y = -1.; + } + } + // Wikipedia sRGB: Unlike most other RGB color spaces, the sRGB gamma cannot be expressed as a single numerical value. // The overall gamma is approximately 2.2, consisting of a linear (gamma 1.0) section near black, and a non-linear section elsewhere involving a 2.4 exponent // and a gamma (slope of log output versus log input) changing from 1.0 through about 2.3. @@ -389,6 +413,58 @@ void CurveFactory::curveCL ( bool & clcutili,const std::vector& clcurveP } } +// add curve Colortoning : C=f(L) +void CurveFactory::curveToningCL ( bool & clctoningutili,const std::vector& clcurvePoints, LUTf & clToningCurve,int skip){ + bool needed; + DiagonalCurve* dCurve = NULL; + LUTf dCcurve(65536,0); + + float val; + for (int i=0; i<32768; i++) { + dCcurve[i] = (float)i / 32767.0; + } + + needed = false; + if (!clcurvePoints.empty() && clcurvePoints[0]!=0) { + dCurve = new DiagonalCurve (clcurvePoints, CURVES_MIN_POLY_POINTS/skip); + + if (dCurve && !dCurve->isIdentity()) + {needed = true;clctoningutili=true;} + } + fillCurveArray(dCurve, clToningCurve, skip, needed); + // clToningCurve.dump("CLToning"); + if (dCurve) { + delete dCurve; + dCurve = NULL; + } +} + +// add curve Colortoning : CLf(L) +void CurveFactory::curveToningLL ( bool & llctoningutili,const std::vector& llcurvePoints, LUTf & llToningCurve, int skip){ + bool needed; + DiagonalCurve* dCurve = NULL; + LUTf dCcurve(65536,0); + + float val; + for (int i=0; i<32768; i++) { + dCcurve[i] = (float)i / 32767.0; + } + needed = false; + if (!llcurvePoints.empty() && llcurvePoints[0]!=0) { + dCurve = new DiagonalCurve (llcurvePoints, CURVES_MIN_POLY_POINTS/skip); + + if (dCurve && !dCurve->isIdentity()) + {needed = true;llctoningutili=true;} + } + fillCurveArray(dCurve, llToningCurve, skip, needed); +// llToningCurve.dump("LLToning"); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili, bool & ccutili, bool & cclutili, double saturation, double rstprotection, const std::vector& acurvePoints, const std::vector& bcurvePoints,const std::vector& cccurvePoints, @@ -1028,8 +1104,6 @@ void CurveFactory::curveCL ( bool & clcutili,const std::vector& clcurveP } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - void ColorAppearance::Reset() { lutColCurve.reset(); } @@ -1050,4 +1124,277 @@ void ToneCurve::Set(Curve *pCurve) { for (int i=0; i<65536; i++) lutToneCurve[i] = pCurve->getVal(double(i)/65535.) * 65535.; } +void OpacityCurve::Reset() { + lutOpacityCurve.reset(); +} + +void OpacityCurve::Set(const Curve *pCurve) { + if (pCurve->isIdentity()) { + lutOpacityCurve.reset(); // raise this value if the quality suffers from this number of samples + return; + } + lutOpacityCurve(501); // raise this value if the quality suffers from this number of samples + + for (int i=0; i<501; i++) lutOpacityCurve[i] = pCurve->getVal(double(i)/500.); + //lutOpacityCurve.dump("opacity"); +} + +void OpacityCurve::Set(const std::vector &curvePoints) { + FlatCurve* tcurve = NULL; + + if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0]setIdentityValue(0.); + } + if (tcurve) { + Set(tcurve); + delete tcurve; + tcurve = NULL; + } +} + +void ColorGradientCurve::Reset() { + lut1.reset(); + lut2.reset(); + lut3.reset(); +} + +void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin) { + if (pCurve->isIdentity()) { + lut1.reset(); + lut2.reset(); + lut3.reset(); + return; + } + if (!lut1) { + lut1(501); + lut2(501); + lut3(501); + } + + float r, g, b, xx, yy, zz; + float lr1,lr2; + int upperBound = lut1.getUpperBound(); + if (pCurve->isIdentity()) { + Color::hsv2rgb(0.5f, satur, lumin, r, g, b); + Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); + + for (int i=0; i<=500; ++i) { + // WARNING: set the identity value according to what is set in the GUI + lut1[i] = xx; + lut2[i] = yy; + lut3[i] = zz; + } + return; + } + + int nPoints = pCurve->getSize(); + int ptNum = 0; + double nextX, nextY; + pCurve->getControlPoint(ptNum, nextX, nextY); + double prevY = nextY; + double dY = 0.; + low=nextX; + lr1=(0.5f+low)/2.f;//optimize use of gamut in low light..one can optimize more using directly low ? + //lr1=low; + for (int i=0; i<=upperBound; ++i) { + double x = double(i)/double(upperBound); + + if (x > nextX) { + ++ptNum; + if (ptNum < nPoints) { + prevY = nextY; + pCurve->getControlPoint(ptNum, nextX, nextY); + dY = nextY - prevY; + high=nextX; + lr2=(0.5f + high)/2.f;//optimize use of gamut in high light..one can optimize more using directly high ? + //lr2=high; + } + } + + if (!ptNum) { + Color::hsv2rgb(float(prevY), satur, lr1, r, g, b); + Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); + lut1[i] = xx; + lut2[i] = yy; + lut3[i] = zz; + } + else if (ptNum >= nPoints) { + Color::hsv2rgb(float(nextY), satur, lr2, r, g, b); + Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); + lut1[i] = xx; + lut2[i] = yy; + lut3[i] = zz; + } + else { + double currY = pCurve->getVal(x) - prevY; + if (dY > 0.000001 || dY < -0.000001) { + float r1, g1, b1, r2, g2, b2, ro, go, bo; + Color::hsv2rgb(float(prevY), satur, lr1, r1, g1, b1); + Color::hsv2rgb(float(nextY), satur, lr2, r2, g2, b2); + bool chr = false; + bool lum = true; + LUTf dum; + float X1,X2,Y1,Y2,Z1,Z2,L1,a_1,b_1,c1,h1; + Color::rgbxyz(r2, g2, b2, X2, Y2, Z2, xyz_rgb); + Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); + //I use XYZ to mix color 1 and 2 rather than rgb (gamut) and rather than Lab artifacts + X1 = X1 + (X2-X1)*currY/dY; if(X1<0.f) X1=0.f;//negative value not good + Y1 = Y1 + (Y2-Y1)*currY/dY; if(Y1<0.f) Y1=0.f; + Z1 = Z1 + (Z2-Z1)*currY/dY; if(Z1<0.f) Z1=0.f; + Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1);//prepare to gamut control + Color::Lab2Lch(a_1, b_1, c1, h1); + float Lr=L1/327.68f; + float RR,GG,BB; + #ifndef NDEBUG + bool neg=false; + bool more_rgb=false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); + #else + Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); + #endif + L1=Lr*327.68f; + float a,b,X,Y,Z; + // converting back to rgb + Color::Lch2Lab(c1, h1, a, b); + Color::Lab2XYZ(L1, a, b, X, Y, Z); + lut1[i] = X; + lut2[i] = Y; + lut3[i] = Z; + } + else { + Color::hsv2rgb(float(nextY), satur, lumin, r, g, b); + Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); + lut1[i] = xx; + lut2[i] = yy; + lut3[i] = zz; + } + } + } + /* + #ifndef NDEBUG + lutRed.dump("red"); + lutGreen.dump("green"); + lutBlue.dump("blue"); + #endif + */ +} + +void ColorGradientCurve::SetXYZ(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin) { + FlatCurve* tcurve = NULL; + + if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0]isIdentity()) { + lut1.reset(); + lut2.reset(); + lut3.reset(); + return; + } + if (!lut1) { + lut1(501); + lut2(501); + lut3(501); + } + + float r, g, b; + + int upperBound = lut1.getUpperBound(); + + int nPoints = pCurve->getSize(); + int ptNum = 0; + double nextX, nextY; + pCurve->getControlPoint(ptNum, nextX, nextY); + double prevY = nextY; + double dY = 0.; + Color::eInterpolationDirection dir = Color::ID_DOWN; + for (int i=0; i<=upperBound; ++i) { + double x = double(i)/double(upperBound); + + if (x > nextX) { + ++ptNum; + if (ptNum < nPoints) { + prevY = nextY; + pCurve->getControlPoint(ptNum, nextX, nextY); + dY = nextY - prevY; + dir = Color::getHueInterpolationDirection(prevY, nextY, Color::IP_SHORTEST); + } + } + + if (!ptNum) { + Color::hsv2rgb(float(prevY), 1.f, 1.f, r, g, b); + lut1[i] = r; + lut2[i] = g; + lut3[i] = b; + } + else if (ptNum >= nPoints) { + Color::hsv2rgb(float(nextY), 1.f, 1.f, r, g, b); + lut1[i] = r; + lut2[i] = g; + lut3[i] = b; + } + else { + double currY = pCurve->getVal(x) - prevY; + if (dY > 0.0000001 || dY < -0.0000001) { + #if 1 + float ro, go, bo; + double h2 = Color::interpolateHueHSV(prevY, nextY, currY/dY, dir); + Color::hsv2rgb(h2, 1.f, 1.f, ro, go, bo); + #else + float r1, g1, b1, r2, g2, b2, ro, go, bo; + Color::hsv2rgb(float(prevY), 1., 1., r1, g1, b1); + Color::hsv2rgb(float(nextY), 1., 1., r2, g2, b2); + Color::interpolateRGBColor(currY/dY, r1, g1, b1, r2, g2, b2, Color::CHANNEL_LIGHTNESS|Color::CHANNEL_CHROMATICITY|Color::CHANNEL_HUE, xyz_rgb, rgb_xyz, ro, go, bo); + #endif + lut1[i] = ro; + lut2[i] = go; + lut3[i] = bo; + } + else { + Color::hsv2rgb(float(nextY), 1.f, 1.f, r, g, b); + lut1[i] = r; + lut2[i] = g; + lut3[i] = b; + } + } + } + /* + #ifndef NDEBUG + lut1.dump("red"); + lut2.dump("green"); + lut3.dump("blue"); + #endif + */ +} + +void ColorGradientCurve::SetRGB(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3]) { + FlatCurve* tcurve = NULL; + + if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0]& clcurvePoints, LUTf & clCurve, LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip); + static void curveToningCL ( bool & clctoningutili, const std::vector& clcurvePoints, LUTf & clToningCurve, int skip); + static void curveToningLL ( bool & llctoningutili, const std::vector& llcurvePoints, LUTf & llToningCurve, int skip); static void complexsgnCurve ( float adjustr, bool & autili, bool & butili, bool & ccutili, bool & clcutili, double saturation, double rstprotection, const std::vector& acurvePoints, const std::vector& bcurvePoints,const std::vector& cccurvePoints,const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, @@ -266,6 +268,8 @@ class Curve { Curve (); virtual ~Curve () {}; void AddPolygons (); + int getSize () const; // return the number of control points + void getControlPoint(int cpNum, double &x, double &y) const; virtual double getVal (double t) const = 0; virtual void getVal (const std::vector& t, std::vector& res) const = 0; @@ -277,10 +281,6 @@ class DiagonalCurve : public Curve { protected: DiagonalCurveType kind; - unsigned int minSearch; // a effacer!!! - unsigned int maxSearch; // a effacer!!! - unsigned int searchArray[21]; // a effacer!!! - void spline_cubic_set (); void NURBS_set (); @@ -326,6 +326,57 @@ class ToneCurve { operator bool (void) const { return lutToneCurve; } }; +class OpacityCurve { + public: + LUTf lutOpacityCurve; // 0xffff range + + virtual ~OpacityCurve() {}; + + void Reset(); + void Set(const Curve *pCurve); + void Set(const std::vector &curvePoints); + + // TODO: transfer this method to the Color class... + float blend (float x, float lower, float upper) const { + return (upper-lower)*lutOpacityCurve[x*500.f] + lower; + } + void blend3f (float x, float lower1, float upper1, float &result1, float lower2, float upper2, float &result2, float lower3, float upper3, float &result3) const { + float opacity = lutOpacityCurve[x*500.f]; + result1 = (upper1-lower1)*opacity + lower1; + result2 = (upper2-lower2)*opacity + lower2; + result3 = (upper3-lower3)*opacity + lower3; + } + + operator bool (void) const { return lutOpacityCurve; } +}; + +class ColorGradientCurve { + public: + LUTf lut1; // [0.;1.] range (float values) + LUTf lut2; // [0.;1.] range (float values) + LUTf lut3; // [0.;1.] range (float values) + double low; + double high; + + virtual ~ColorGradientCurve() {}; + + void Reset(); + void SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin); + void SetXYZ(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin); + void SetRGB(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3]); + void SetRGB(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3]); + + /** + * @brief Get the value of Red, Green and Blue corresponding to the requested index + * @param index value in the [0 ; 1] range + * @param r corresponding red value [0 ; 65535] (return value) + * @param g corresponding green value [0 ; 65535] (return value) + * @param b corresponding blue value [0 ; 65535] (return value) + */ + void getVal(float index, float &r, float &g, float &b) const; + operator bool (void) const { return lut1 && lut2 && lut3; } +}; + class ColorAppearance { public: LUTf lutColCurve; // 0xffff range diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 4843d2b16..8c28a7742 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -191,7 +191,7 @@ void Crop::update (int todo) { if (!params.sh.hq) shradius *= radius / 1800.0; cshmap->update (baseCrop, shradius, parent->ipf.lumimul, params.sh.hq, skip); if(parent->shmap->min_f < 65535.f) // don't call forceStat with wrong values - cshmap->forceStat (parent->shmap->max_f, parent->shmap->min_f, parent->shmap->avg); + cshmap->forceStat (parent->shmap->max_f, parent->shmap->min_f, parent->shmap->avg); } // shadows & highlights & tone curve & convert to cielab @@ -210,8 +210,8 @@ void Crop::update (int todo) { if (todo & M_RGBCURVE) parent->ipf.rgbProc (baseCrop, laboCrop, this, parent->hltonecurve, parent->shtonecurve, parent->tonecurve, cshmap, - params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, parent->customToneCurve1, - parent->customToneCurve2, parent->beforeToneCurveBW, parent->afterToneCurveBW,rrm, ggm, bbm, + params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, parent->ctColorCurve, parent->ctOpacityCurve, parent->clToningcurve,parent->cl2Toningcurve, + parent->customToneCurve1, parent->customToneCurve2, parent->beforeToneCurveBW, parent->afterToneCurveBW,rrm, ggm, bbm, parent->bwAutoR, parent->bwAutoG, parent->bwAutoB); /*xref=000;yref=000; diff --git a/rtengine/flatcurves.cc b/rtengine/flatcurves.cc index 3236b57d1..c661b618e 100644 --- a/rtengine/flatcurves.cc +++ b/rtengine/flatcurves.cc @@ -62,10 +62,7 @@ FlatCurve::FlatCurve (const std::vector& p, bool isPeriodic, int poly_pn leftTangent[N] = p[3]; rightTangent[N] = p[4]; } - else { - N--; - } - if (!identity && N > 0+(periodic?1:0) ) { + if (!identity && N > (periodic?1:0) ) { CtrlPoints_set (); fillHash(); } @@ -99,7 +96,7 @@ bool FlatCurve::setIdentityValue (double iVal) { identityValue = iVal; bool identity = true; - for (int i=0; i= identityValue+1.e-7 || y[i] <= identityValue-1.e-7) { identity = false; break; @@ -115,12 +112,13 @@ bool FlatCurve::setIdentityValue (double iVal) { void FlatCurve::CtrlPoints_set () { - int nbSubCurvesPoints = N*6; + int N_ = periodic ? N : N-1; + int nbSubCurvesPoints = N_*6; std::vector sc_x(nbSubCurvesPoints); // X sub-curve points ( XP0,XP1,XP2, XP2,XP3,XP4, ...) std::vector sc_y(nbSubCurvesPoints); // Y sub-curve points ( YP0,YP1,YP2, YP2,YP3,YP4, ...) - std::vector sc_length(N*2); // Length of the subcurves - std::vector sc_isLinear(N*2); // true if the subcurve is linear + std::vector sc_length(N_*2); // Length of the subcurves + std::vector sc_isLinear(N_*2); // true if the subcurve is linear double total_length=0.; // Create the list of Bezier sub-curves @@ -129,7 +127,7 @@ void FlatCurve::CtrlPoints_set () { unsigned int j = 0; unsigned int k = 0; - for (int i = 0; i < N;) { + for (int i = 0; i < N_;) { double length; double dx; double dy; @@ -300,7 +298,7 @@ void FlatCurve::CtrlPoints_set () { nbr_points = (int)(((double)(ppn) * sc_length[i] )/ total_length); if (nbr_points<0){ for(size_t it=0;it < sc_x.size(); it+=3) printf("sc_length[%zd/3]=%f \n",it,sc_length[it/3]); - printf("Flat curve: error detected!\n i=%d periodic=%d nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f",i,periodic,nbr_points,ppn,N,sc_length[i/3],total_length); + printf("Flat curve: error detected!\n i=%d k=%d periodic=%d nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f\n",i,k,periodic,nbr_points,ppn,N,sc_length[i/3],total_length); exit(0); } // increment along the curve, not along the X axis @@ -334,13 +332,6 @@ double FlatCurve::getVal (double t) const { switch (kind) { case FCT_MinMaxCPoints : { - /* To be updated if we have to handle non periodic flat curves - // values under and over the first and last point - if (t>x[N-1]) - return y[N-1]; - else if (tworkingSpaceMatrix (params.icm.working); + double wp[3][3] = { + {wprof[0][0],wprof[0][1],wprof[0][2]}, + {wprof[1][0],wprof[1][1],wprof[1][2]}, + {wprof[2][0],wprof[2][1],wprof[2][2]}}; + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); + double wip[3][3] = { + {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, + {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, + {wiprof[2][0],wiprof[2][1],wiprof[2][2]} + }; + params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip); + + bool clctoningutili=false; + bool llctoningutili=false; + CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve,scale==1 ? 1 : 16); + // clToningcurve.dump("CLToning3"); + CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve,scale==1 ? 1 : 16); + CurveFactory::curveBW (params.blackwhite.beforeCurve,params.blackwhite.afterCurve, vhist16bw, histToneCurveBW, beforeToneCurveBW, afterToneCurveBW,scale==1 ? 1 : 1); //initialize rrm bbm ggm different from zero to avoid black screen in some cases double rrm=33.; double ggm=33.; double bbm=33.; - + + int satTH=80; + int satPR=30; + int indi=0; + if(params.colorToning.enabled && params.colorToning.autosat){//for colortoning evaluation of saturation settings + float moyS=0.f; + float eqty=0.f; + ipf.moyeqt (oprevi, moyS, eqty);//return image : mean saturation and standard dev of saturation + //printf("moy=%f ET=%f\n", moyS,eqty); + float satp=((moyS+1.5f*eqty)-0.3f)/0.7f;//1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale + if(satp >= 0.92f) satp=0.92f;//avoid values too high (out of gamut) + if(satp <= 0.15f) satp=0.15f;//avoid too low values + + satTH=(int) 100.f*satp; + satPR=(int) 100.f*(moyS-0.85f*eqty);//-0.85 sigma==>20% pixels with low saturation + } + if(actListener) { + if(params.blackwhite.enabled) {actListener->autoColorTonChanged(0, satTH, satPR);} + else { + if(params.colorToning.autosat){ + if(params.colorToning.method=="Lab") indi=1; + else if(params.colorToning.method=="RGBCurves") indi=1; + else if(params.colorToning.method=="RGBSliders") indi=1; + else if(params.colorToning.method=="Splico") indi=2; + else if(params.colorToning.method=="Splitlr") indi=2; + + actListener->autoColorTonChanged(indi, satTH, satPR);} + } + } // if it's just crop we just need the histogram, no image updates if ( todo & M_RGBCURVE ) { ipf.rgbProc (oprevi, oprevl, NULL, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation, - rCurve, gCurve, bCurve, customToneCurve1, customToneCurve2,beforeToneCurveBW, afterToneCurveBW, rrm, ggm, bbm, bwAutoR, bwAutoG, bwAutoB, params.toneCurve.expcomp, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); - if(params.blackwhite.enabled && params.blackwhite.autoc && abwListener) { + rCurve, gCurve, bCurve, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2,beforeToneCurveBW, afterToneCurveBW, rrm, ggm, bbm, bwAutoR, bwAutoG, bwAutoB, params.toneCurve.expcomp, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); + if(params.blackwhite.enabled && params.blackwhite.autoc && abwListener) { if (settings->verbose) printf("ImProcCoordinator / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", bwAutoR, bwAutoG, bwAutoB); abwListener->BWChanged((float) rrm, (float) ggm, (float) bbm); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 6d7999f6e..d646423ef 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -81,7 +81,6 @@ class ImProcCoordinator : public StagedImageProcessor { float bwAutoR, bwAutoG, bwAutoB; float CAMMean; - LUTf hltonecurve; LUTf shtonecurve; LUTf tonecurve; @@ -92,6 +91,8 @@ class ImProcCoordinator : public StagedImageProcessor { LUTf satcurve; LUTf lhskcurve; LUTf clcurve; + LUTf clToningcurve; + LUTf cl2Toningcurve; LUTu vhist16,vhist16bw; LUTu lhist16,lhist16Cropped; @@ -121,6 +122,8 @@ class ImProcCoordinator : public StagedImageProcessor { ToneCurve customToneCurve1; ToneCurve customToneCurve2; + ColorGradientCurve ctColorCurve; + OpacityCurve ctOpacityCurve; ColorAppearance customColCurve1; ColorAppearance customColCurve2; ColorAppearance customColCurve3; @@ -141,6 +144,7 @@ class ImProcCoordinator : public StagedImageProcessor { AutoExpListener* aeListener; AutoCamListener* acListener; AutoBWListener* abwListener; + AutoColorTonListener* actListener; HistogramListener* hListener; std::vector sizeListeners; @@ -216,6 +220,7 @@ class ImProcCoordinator : public StagedImageProcessor { void setHistogramListener(HistogramListener *h) {hListener = h; } void setAutoCamListener (AutoCamListener* acl) {acListener = acl; } void setAutoBWListener (AutoBWListener* abw) {abwListener = abw; } + void setAutoColorTonListener (AutoColorTonListener* bwct) {actListener = bwct; } void saveInputICCReference (const Glib::ustring& fname); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 28f9b0701..ee598ac72 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -1883,14 +1883,13 @@ if(params->dirpyrequalizer.enabled) { float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; - bool alread=false; float artifact=(float) settings->artifact_cbdl; if(artifact > 6.f) artifact=6.f; if(artifact <0.f) artifact=1.f; - + int hotbad=0; float chrom=50.f; - ImProcFunctions::badpixcam (ncie, artifact, 5, 2 , b_l, t_l, t_r, b_r, params->dirpyrequalizer.skinprotect, chrom, hotbad); alread=true;//enabled remove artifacts for cbDL + ImProcFunctions::badpixcam (ncie, artifact, 5, 2 , b_l, t_l, t_r, b_r, params->dirpyrequalizer.skinprotect, chrom, hotbad); //enabled remove artifacts for cbDL } } @@ -1935,7 +1934,7 @@ printf("BADPIX"); #ifndef _DEBUG #pragma omp for schedule(dynamic, 10) #endif - for (int i=0; ish_p[i][j]/(32768.f)); ncie->J_p[i][j]=100.0f* SQR(interm); @@ -1948,83 +1947,82 @@ printf("BADPIX"); if((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) || (params->dirpyrequalizer.enabled && settings->autocielab) ||(params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl >0 && settings->autocielab)){ - - if(epdEnabled && params->colorappearance.tonecie && algepd) ImProcFunctions::EPDToneMapCIE(ncie, a_w, c_, w_h, width, height, begh, endh, minQ, maxQ, Iterates, scale ); - //EPDToneMapCIE adated to CIECAM + + if(epdEnabled && params->colorappearance.tonecie && algepd) ImProcFunctions::EPDToneMapCIE(ncie, a_w, c_, w_h, width, height, begh, endh, minQ, maxQ, Iterates, scale ); + //EPDToneMapCIE adated to CIECAM - const float eps=0.0001f; - const float co_e=(pow_F(f_l,0.25f))+eps; + const float eps=0.0001f; + const float co_e=(pow_F(f_l,0.25f))+eps; TMatrix wiprofa = iccStore->workingSpaceInverseMatrix (params->icm.working); const float wipa[3][3] = { - {wiprofa[0][0],wiprofa[0][1],wiprofa[0][2]}, - {wiprofa[1][0],wiprofa[1][1],wiprofa[1][2]}, - {wiprofa[2][0],wiprofa[2][1],wiprofa[2][2]} + {float(wiprofa[0][0]),float(wiprofa[0][1]),float(wiprofa[0][2])}, + {float(wiprofa[1][0]),float(wiprofa[1][1]),float(wiprofa[1][2])}, + {float(wiprofa[2][0]),float(wiprofa[2][1]),float(wiprofa[2][2])} }; -#ifndef _DEBUG +#ifndef _DEBUG #pragma omp parallel #endif -{ - - +{ + + #ifndef _DEBUG #pragma omp for schedule(dynamic, 10) #endif for (int i=0; iJ_p[i][j]=(100.0f* ncie->Q_p[i][j]*ncie->Q_p[i][j])/(w_h*w_h); - if(epdEnabled) ncie->J_p[i][j]=(100.0f* ncie->Q_p[i][j]*ncie->Q_p[i][j])/SQR((4.f/c)*(aw+4.f)); - - const float ncie_C_p = (ncie->M_p[i][j])/co_e; - //show histogram in CIECAM mode (Q,J, M,s,C) - if(ciedata) { - // Data for J Q M s and C histograms - int posl, posc; - float brli=327.f; - float chsacol=327.f; - int libr=0; - int colch=0; - float sa_t; - if(curveMode==ColorAppearanceParams::TC_MODE_BRIGHT) {brli=70.0f; libr=1;} - else if(curveMode==ColorAppearanceParams::TC_MODE_LIGHT) {brli=327.f;libr=0;} - if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA) {chsacol=327.f;colch=0;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_SATUR) {chsacol=450.0f;colch=1;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_COLORF) {chsacol=327.0f;colch=2;} - //update histogram - if(pW!=1){//only with improccoordinator - if(libr==1) posl=CLIP((int)(ncie->Q_p[i][j]*brli));//40.0 to 100.0 approximative factor for Q - 327 for J - else if(libr==0) posl=CLIP((int)(ncie->J_p[i][j]*brli));//327 for J - hist16JCAM[posl]++; - } - chropC=true; - if(pW!=1){//only with improccoordinator - if(colch==0) posc=CLIP((int)(ncie_C_p*chsacol));//450.0 approximative factor for s 320 for M - else if(colch==1) {sa_t=100.f*sqrtf(ncie_C_p/ncie->Q_p[i][j]); posc=CLIP((int)(sa_t*chsacol));}//Q_p always > 0 - else if(colch==2) posc=CLIP((int)(ncie->M_p[i][j]*chsacol)); - hist16_CCAM[posc]++; - } - } - //end histograms + float xx,yy,zz; + float x,y,z; + // if(epdEnabled) ncie->J_p[i][j]=(100.0f* ncie->Q_p[i][j]*ncie->Q_p[i][j])/(w_h*w_h); + if(epdEnabled) ncie->J_p[i][j]=(100.0f* ncie->Q_p[i][j]*ncie->Q_p[i][j])/SQR((4.f/c)*(aw+4.f)); - ColorTemp::jch2xyz_ciecam02float( xx, yy, zz, - ncie->J_p[i][j], ncie_C_p, ncie->h_p[i][j], - xw2, yw2, zw2, - yb2, la2, - f2, c2, nc2, gamu, pow1n, nbbj, ncbj, flj, czj, dj, awj); - x=(float)xx*655.35f; - y=(float)yy*655.35f; - z=(float)zz*655.35f; - float Ll,aa,bb; - //convert xyz=>lab - Color::XYZ2Lab(x, y, z, Ll, aa, bb); - if(gamu==1) { - float HH, Lprov1, Chprov1; + const float ncie_C_p = (ncie->M_p[i][j])/co_e; + //show histogram in CIECAM mode (Q,J, M,s,C) + if(ciedata) { + // Data for J Q M s and C histograms + int posl, posc; + float brli=327.f; + float chsacol=327.f; + int libr=0; + int colch=0; + float sa_t; + if(curveMode==ColorAppearanceParams::TC_MODE_BRIGHT) {brli=70.0f; libr=1;} + else if(curveMode==ColorAppearanceParams::TC_MODE_LIGHT) {brli=327.f;libr=0;} + if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA) {chsacol=327.f;colch=0;} + else if(curveMode3==ColorAppearanceParams::TC_MODE_SATUR) {chsacol=450.0f;colch=1;} + else if(curveMode3==ColorAppearanceParams::TC_MODE_COLORF) {chsacol=327.0f;colch=2;} + //update histogram + if(pW!=1){//only with improccoordinator + if(libr==1) posl=CLIP((int)(ncie->Q_p[i][j]*brli));//40.0 to 100.0 approximative factor for Q - 327 for J + else if(libr==0) posl=CLIP((int)(ncie->J_p[i][j]*brli));//327 for J + hist16JCAM[posl]++; + } + chropC=true; + if(pW!=1){//only with improccoordinator + if(colch==0) posc=CLIP((int)(ncie_C_p*chsacol));//450.0 approximative factor for s 320 for M + else if(colch==1) {sa_t=100.f*sqrtf(ncie_C_p/ncie->Q_p[i][j]); posc=CLIP((int)(sa_t*chsacol));}//Q_p always > 0 + else if(colch==2) posc=CLIP((int)(ncie->M_p[i][j]*chsacol)); + hist16_CCAM[posc]++; + } + } + //end histograms + + ColorTemp::jch2xyz_ciecam02float( xx, yy, zz, + ncie->J_p[i][j], ncie_C_p, ncie->h_p[i][j], + xw2, yw2, zw2, + yb2, la2, + f2, c2, nc2, gamu, pow1n, nbbj, ncbj, flj, czj, dj, awj); + x=(float)xx*655.35f; + y=(float)yy*655.35f; + z=(float)zz*655.35f; + float Ll,aa,bb; + //convert xyz=>lab + Color::XYZ2Lab(x, y, z, Ll, aa, bb); + if(gamu==1) { + float Lprov1, Chprov1; Lprov1=Ll/327.68f; Chprov1=sqrtf(SQR(aa) + SQR(bb))/327.68f; - HH=xatan2f(bb,aa); float2 sincosval; if(Chprov1==0.0f) { sincosval.y = 1.f; @@ -2048,17 +2046,15 @@ if((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enab lab->L[i][j]=Lprov1*327.68f; lab->a[i][j]=327.68f*Chprov1*sincosval.y; lab->b[i][j]=327.68f*Chprov1*sincosval.x; - } else { - lab->L[i][j]=Ll; - lab->a[i][j]=aa; - lab->b[i][j]=bb; - + } else { + lab->L[i][j]=Ll; + lab->a[i][j]=aa; + lab->b[i][j]=bb; + } } - } +} //end parallelization - } - //end parallelization //show CIECAM histograms if(ciedata) { //update histogram J and Q @@ -2083,19 +2079,71 @@ if((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enab } } //end CIECAM + +void ImProcFunctions::moyeqt (Imagefloat* working, float &moyS, float &eqty) { +// MyTime t1e,t2e; +// t1e.set(); + + int tHh=working->height; + int tWw=working->width; + float moy=0.f; + float eqt=0.f; +#pragma omp parallel +{ +float mo=0.f; +#ifndef _DEBUG + #pragma omp for reduction(+:moy) +#endif + for (int i=0; ir(i,j)); + float g = CLIP(working->g(i,j)); + float b = CLIP(working->b(i,j)); + float h, s, v; + Color::rgb2hsv(r, g, b, h, s, v); + moy+=s; + } + } + mo=moy/(tHh*tWw); + moyS=mo; +#ifndef _DEBUG + #pragma omp for reduction(+:eqt) +#endif + for (int i=0; ir(i,j)); + float g = CLIP(working->g(i,j)); + float b = CLIP(working->b(i,j)); + float h, s, v; + Color::rgb2hsv(r, g, b, h, s, v); + eqt+=SQR(s-mo); + } + } +} + eqt=eqt/(tHh*tWw); + eqty=(sqrt(eqt)); + + // t2e.set(); + // printf("Moyeqt:%d\n", t2e.etime(t1e)); + +} + + + + void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, + SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve,LUTf & cl2Toningcurve, const ToneCurve & customToneCurve1,const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1,const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob ) { - rgbProc (working, lab, editBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2,rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh); + rgbProc (working, lab, editBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve,customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2,rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh); } // Process RGB image and convert to LAB space void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ToneCurve & customToneCurve1, - const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1,const ToneCurve & customToneCurvebw2,double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh) { + SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve,LUTf & cl2Toningcurve, + const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1,const ToneCurve & customToneCurvebw2,double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh) { LUTf iGammaLUTf; - Imagefloat *tmpImage; + Imagefloat *tmpImage=NULL; // NOTE: We're getting all 3 pointers here, but this function may not need them all, so one could optimize this Imagefloat* editImgFloat = NULL; @@ -2162,7 +2210,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e params->chmixer.green[0]!=0 || params->chmixer.green[1]!=100 || params->chmixer.green[2]!=0 || params->chmixer.blue[0]!=0 || params->chmixer.blue[1]!=0 || params->chmixer.blue[2]!=100); - double pi = M_PI; FlatCurve* hCurve; FlatCurve* sCurve; FlatCurve* vCurve; @@ -2178,9 +2225,30 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e bool bwlCurveEnabled = bwlCurveType > FCT_Linear; // TODO: We should create a 'skip' value like for CurveFactory::complexsgnCurve (rtengine/curves.cc) - if (hCurveEnabled) hCurve = new FlatCurve(params->hsvequalizer.hcurve); - if (sCurveEnabled) sCurve = new FlatCurve(params->hsvequalizer.scurve); - if (vCurveEnabled) vCurve = new FlatCurve(params->hsvequalizer.vcurve); + if (hCurveEnabled) { + hCurve = new FlatCurve(params->hsvequalizer.hcurve); + if (hCurve->isIdentity()) { + delete hCurve; + hCurve = NULL; + hCurveEnabled = false; + } + } + if (sCurveEnabled) { + sCurve = new FlatCurve(params->hsvequalizer.scurve); + if (sCurve->isIdentity()) { + delete sCurve; + sCurve = NULL; + sCurveEnabled = false; + } + } + if (vCurveEnabled) { + vCurve = new FlatCurve(params->hsvequalizer.vcurve); + if (vCurve->isIdentity()) { + delete vCurve; + vCurve = NULL; + vCurveEnabled = false; + } + } if (bwlCurveEnabled) { bwlCurve = new FlatCurve(params->blackwhite.luminanceCurve); if (bwlCurve->isIdentity()) { @@ -2207,6 +2275,56 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e bool hasToneCurvebw1 = bool(customToneCurvebw1); bool hasToneCurvebw2 = bool(customToneCurvebw2); + bool hasColorToning = params->colorToning.enabled && bool(ctOpacityCurve) && bool(ctColorCurve); + + float satLimit = float(params->colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; + float satLimitOpacity = 1.f-(float(params->colorToning.saturatedOpacity)/100.f); + float strProtect = 1.f-(float(params->colorToning.strengthprotection)/100.f); + + /* + // Debug output - Color LUTf points + if (ctColorCurve) { + printf("\nColor curve:"); + for (size_t i=0; i<501; i++) { + if (i==0 || i==250 || i==500) + printf("\n(%.1f)[", float(i)/500.f); + printf("%.3f ", ctColorCurve.lutHueCurve[float(i)]); + if (i==0 || i==250 || i==500) + printf("]\n"); + } + printf("\n"); + } + */ + + /* + // Debug output - Opacity LUTf points + if (ctOpacityCurve) { + printf("\nOpacity curve:"); + for (size_t i=0; i<501; i++) { + if (i==0 || i==250 || i==500) + printf("\n(%.1f)[", float(i)/500.f); + printf("%.3f ", ctOpacityCurve.lutOpacityCurve[float(i)]); + if (i==0 || i==250 || i==500) + printf("]\n"); + } + printf("\n"); + } + */ + + float RedLow = (100.f + float(params->colorToning.redlow))/100.f;//printf("Rel=%f\n",RedLow); + float GreenLow = (100.f + float(params->colorToning.greenlow))/100.f;//printf("Gre=%f\n",GreenLow); + float BlueLow = (100.f + float(params->colorToning.bluelow))/100.f;//printf("Blu=%f\n",BlueLow); + float RedMed = (100.f + float(params->colorToning.redmed))/100.f; + float GreenMed = (100.f + float(params->colorToning.greenmed))/100.f; + float BlueMed = (100.f + float(params->colorToning.bluemed))/100.f; + float RedHigh = (100.f + float(params->colorToning.redhigh))/100.f;//printf("RedH=%f\n",RedHigh); + float GreenHigh = (100.f + float(params->colorToning.greenhigh))/100.f; + float BlueHigh = (100.f + float(params->colorToning.bluehigh))/100.f; + float SatLow = float(params->colorToning.shadowsColSat.value[0])/100.f; + float SatHigh = float(params->colorToning.hlColSat.value[0])/100.f; + + float Balan = float(params->colorToning.balance); + float chMixRR = float(params->chmixer.red[0]); float chMixRG = float(params->chmixer.red[1]); float chMixRB = float(params->chmixer.red[2]); @@ -2216,6 +2334,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e float chMixBR = float(params->chmixer.blue[0]); float chMixBG = float(params->chmixer.blue[1]); float chMixBB = float(params->chmixer.blue[2]); + int shHighlights = params->sh.highlights; int shShadows = params->sh.shadows; bool blackwhite = params->blackwhite.enabled; @@ -2272,7 +2391,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } } - if(blackwhite) + if (hasColorToning || blackwhite) tmpImage = new Imagefloat(working->width,working->height); #define TS 112 @@ -2313,8 +2432,11 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e editWhateverTmp = (float(*))data; } - -#pragma omp for schedule(dynamic) collapse(2) nowait + + +#ifdef _OPENMP +#pragma omp for schedule(dynamic) collapse(2) +#endif for(int ii=0;iiheight;ii+=TS) for(int jj=0;jjwidth;jj+=TS) { istart = ii; @@ -2735,6 +2857,168 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } } + if (hasColorToning && !blackwhite) { + if (params->colorToning.method=="Splitlr") { + float balanS, balanH; + float reducac= 0.4f; + int preser=0; + if(params->colorToning.lumamode == true) preser=1; + + balanS = 1.f + Balan/100.f;//balan between 0 and 2 + balanH = 1.f - Balan/100.f; + float rh, gh, bh; + float rl, gl, bl; + float xh, yh, zh; + float xl, yl, zl; + float iplow,iphigh; + iplow=(float)ctColorCurve.low; + iphigh=(float)ctColorCurve.high; + //2 colours + ctColorCurve.getVal(iphigh, xh, yh, zh); + ctColorCurve.getVal(iplow, xl, yl, zl); + + Color::xyz2rgb(xh, yh, zh, rh, gh, bh, wip); + Color::xyz2rgb(xl, yl, zl, rl, gl, bl, wip); + //reteave rgb value with s and l =1 + retreavergb(rl,gl,bl); + retreavergb(rh,gh,bh); + //printf("rl=%f gl=%f bl=%f\n",rl,gl,bl); + + for (int i=istart,ti=0; icolorToning.method=="Splitco") { +/* +#if 1 + for (int i=istart,ti=0; i crash + gtemp[ti*TS+tj] = CLIP(go); + btemp[ti*TS+tj] = CLIP(bo); + } + } +#else +*/ + float reducac = 0.3f; + int preser = 0; + //bool execbal = params->colorToning.method=="Splitbal"; + if(params->colorToning.lumamode == true) preser = 1; + + for (int i=istart,ti=0; icolorToning.method=="Lab") { + int algm=0; + bool twocol = true;//true=500 color false=2 color + int metchrom; + if (params->colorToning.twocolor=="Std" ) metchrom=0; + else if (params->colorToning.twocolor=="All" ) metchrom=1; + else if (params->colorToning.twocolor=="Separ") metchrom=2; + else if (params->colorToning.twocolor=="Two" ) metchrom=3; + + if(metchrom==3) twocol=false; + + float iplow,iphigh; + if(twocol==false){ + iplow=(float)ctColorCurve.low; + iphigh=(float)ctColorCurve.high; + } + + int twoc=0;//integer instead of bool to let more possible choice...other than 2 and 500. + if (twocol==false) twoc=0; // 2 colours + else twoc=1; // 500 colours + if (params->colorToning.method=="Lab") algm=1; + else if (params->colorToning.method=="Lch") algm=2;//in case of + if (algm <=2) { + for (int i=istart,ti=0; i crash + gtemp[ti*TS+tj] = CLIP(go); + btemp[ti*TS+tj] = CLIP(bo); + } + } + } + } + else if (params->colorToning.method.substr(0,3)=="RGB") { + // color toning + for (int i=istart,ti=0; i(s/satLimit, 1.f)*(1.f-satLimitOpacity)) * ctOpacityCurve.lutOpacityCurve[l_*500.f]; + + float r2, g2, b2; + ctColorCurve.getVal(l_, r2, g2, b2); // get the color from the color curve + + float h2, s2, l2; + Color::rgb2hsl(r2,g2,b2,h2,s2,l2); // transform this new color to hsl + + Color::hsl2rgb(h2, s+((1.f-s)*(1.f-l)*0.7f), l, r2, g2, b2); + + rtemp[ti*TS+tj] = r+(r2-r)*opacity; // merge the color to the old color, depending on the opacity + gtemp[ti*TS+tj] = g+(g2-g)*opacity; + btemp[ti*TS+tj] = b+(b2-b)*opacity; + } + } + } + } // filling the pipette buffer if (editID == EUID_BlackWhiteBeforeCurve) { @@ -2880,25 +3164,30 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e #endif //convert CH ==> ab L=Lr*327.68f; - float a_,b_; - a_=0.f;//grey - b_=0.f;//grey + // float a_,b_; + // a_=0.f;//grey + // b_=0.f;//grey //convert lab=>rgb - Color::Lab2XYZ(L, a_, b_, X, Y, Z); + Color::Lab2XYZ(L, 0.f, 0.f, X, Y, Z); float rr_,gg_,bb_; Color::xyz2rgb(X,Y,Z,rr_,gg_,bb_,wip); + rtemp[ti*TS+tj] = gtemp[ti*TS+tj]= btemp[ti*TS+tj] = rr_; + // tmpImage->r(i,j) = tmpImage->g(i,j) = tmpImage->b(i,j) = CLIP(val[0]*kcorec); + + if (hasgammabw) + Color::trcGammaBW (rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj], gammabwr, gammabwg, gammabwb); //gamma correction: pseudo TRC curve - if (hasgammabw) - Color::trcGammaBW (rr_, gg_, bb_, gammabwr, gammabwg, gammabwb); - rtemp[ti*TS+tj] = rr_; - gtemp[ti*TS+tj] = gg_; - btemp[ti*TS+tj] = bb_; + // if (hasgammabw) + // Color::trcGammaBW (rr_, gg_, bb_, gammabwr, gammabwg, gammabwb); + // rtemp[ti*TS+tj] = rr_; + // gtemp[ti*TS+tj] = gg_; + // btemp[ti*TS+tj] = bb_; } } } } - if(!blackwhite){ + if(!blackwhite) { // ready, fill lab for (int i=istart,ti=0; ib[i][j] = (200.0f * (fy - fz) ); //test for color accuracy - /*float fy = (0.00862069 * lab->L[i][j])/327.68 + 0.137932; // (L+16)/116 + /* + float fy = (0.00862069 * lab->L[i][j])/327.68 + 0.137932; // (L+16)/116 float fx = (0.002 * lab->a[i][j])/327.68 + fy; float fz = fy - (0.005 * lab->b[i][j])/327.68; @@ -2943,8 +3233,8 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e int R,G,B; xyz2srgb(x_,y_,z_,R,G,B); r=(float)R; g=(float)G; b=(float)B; - float xxx=1;*/ - + float xxx=1; + */ } } } else { // black & white @@ -2971,52 +3261,12 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e free(buffer); if (editIFloatBuffer) free (editIFloatBuffer); if (editWhateverBuffer) free (editWhateverBuffer); + } - - //black and white - if(blackwhite){ + // starting a new tile processing with a 'reduction' clause for the auto mixer computing + if (blackwhite) {//channel-mixer int tW = working->width; int tH = working->height; - -/* - else if (algm==1) {//Luminance mixer -#ifdef _OPENMP -#pragma omp for schedule(dynamic, 5) -#endif - for (int i=0; ir(i,j); - float g = tmpImage->g(i,j); - float b = tmpImage->b(i,j); - if (bwlCurveEnabled) { - float h,s,v; - Color::rgb2hsv(r,g,b,h,s,v); - if (v<0) v=0; - float valparam = bwlCurve->getVal((double)h)-0.5f; - valparam *= (1.f-(SQR(SQR(1.f-min(s,1.0f))))); - //float valcor=1.f/(0.501f-valparam); - - if (valparam < -0.00001f || valparam > 0.00001f) - v *= (1.f + 4.f*valparam); - v = CLIPD(v); - Color::hsv2rgb(h, s, v, r, g, b); - } - - // get luminance - r = g = b = (0.2126f*r + 0.7152f*g + 0.0722f*b); // (constant taken from Gimp, see https://git.gnome.org/browse/gimp/tree/libgimpcolor/gimprgb.h) - //r = g = b = (0.299f*r + 0.587f*g + 0.114f*b); // (obsolete constant) - - //gamma correction: pseudo TRC curve - if (hasgammabw) Color::trcGammaBW (r, g, b, gammabwr, gammabwg, gammabwb); - - tmpImage->r(i,j) = r; - tmpImage->g(i,j) = g; - tmpImage->b(i,j) = b; - } - } - } -*/ - if (algm==2) {//channel-mixer //end auto chmix float mix[3][3]; @@ -3095,7 +3345,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } } } - if (editID == EUID_BlackWhiteAfterCurve) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 5) @@ -3138,58 +3387,783 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } } + //colortoning with black and white + if (hasColorToning) { + if(params->colorToning.method=="Splitco") { +/* + #if 1 + for (int i=istart,ti=0; i crash + gtemp[ti*TS+tj] = CLIP(go); + btemp[ti*TS+tj] = CLIP(bo); + } + } +#else +*/ + int preser=0; + if(params->colorToning.lumamode == true) preser=1; + + float reducac= 0.3f; #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 5) #endif - for (int i=0; ir(i,j); - float g = tmpImage->g(i,j); - float b = tmpImage->b(i,j); + + for (int i=0; ir(i,j); + float g = tmpImage->g(i,j); + float b = tmpImage->b(i,j); + + float lumbefore=0.299f*r + 0.587f*g + 0.114f*b; + if(lumbefore < 65000.f && lumbefore > 500.f) { //reduct artifacts for highlights an extrem shadows + float ro,go,bo; + int mode=1; + toningsmh (r, g, b, ro, go, bo, RedLow, GreenLow, BlueLow, RedMed, GreenMed, BlueMed, RedHigh, GreenHigh, BlueHigh, reducac, mode, preser, strProtect); + float lumafter=0.299f*ro + 0.587f*go + 0.114f*bo; + float preserv=1.f; + if(preser==1) preserv=lumbefore/lumafter; + ro*=preserv; + go*=preserv; + bo*=preserv; + ro=CLIP(ro); + go=CLIP(go); + bo=CLIP(bo); + tmpImage->r(i,j)=ro; + tmpImage->g(i,j)=go; + tmpImage->b(i,j)=bo; + } + } + } +//#endif + } - float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; - float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; - float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; - - float fx,fy,fz; - - fx = (x<65535.0f ? cachef[std::max(x,0.f)] : (327.68f*float(exp(log(x/MAXVALF)/3.0f )))); - fy = (y<65535.0f ? cachef[std::max(y,0.f)] : (327.68f*float(exp(log(y/MAXVALF)/3.0f )))); - fz = (z<65535.0f ? cachef[std::max(z,0.f)] : (327.68f*float(exp(log(z/MAXVALF)/3.0f )))); + else if (params->colorToning.method=="Splitlr") { + float balanS, balanH; + float reducac= 0.4f; + int preser=0; + if(params->colorToning.lumamode == true) preser=1; - lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; - lab->a[i][j] = (500.0f * (fx - fy) ); - lab->b[i][j] = (200.0f * (fy - fz) ); + balanS = 1.f + Balan/100.f;//balan between 0 and 2 + balanH = 1.f - Balan/100.f; + float rh, gh, bh; + float rl, gl, bl; + float xh, yh, zh; + float xl, yl, zl; + float iplow,iphigh; + iplow=(float)ctColorCurve.low; + iphigh=(float)ctColorCurve.high; + + //2 colours + ctColorCurve.getVal(iphigh, xh, yh, zh); + ctColorCurve.getVal(iplow, xl, yl, zl); + + Color::xyz2rgb(xh, yh, zh, rh, gh, bh, wip); + Color::xyz2rgb(xl, yl, zl, rl, gl, bl, wip); + + //retrieve rgb value with s and l =1 + retreavergb(rl,gl,bl); + retreavergb(rh,gh,bh); +#ifdef _OPENMP +#pragma omp parallel for schedule(dynamic, 5) +#endif + for (int i=0; ir(i,j); + float g = tmpImage->g(i,j); + float b = tmpImage->b(i,j); + + float ro,go,bo; + int mode=1; + toning2col (r, g, b, ro, go, bo, iplow, iphigh, rl, gl, bl, rh, gh, bh, SatLow, SatHigh, balanS, balanH, reducac, mode, preser, strProtect); + tmpImage->r(i,j)=ro; + tmpImage->g(i,j)=go; + tmpImage->b(i,j)=bo; + } + } + } + + //colortoning with shift color Lab + else if (params->colorToning.method=="Lab") { + int algm=0; + bool twocol = true; + int metchrom; + if (params->colorToning.twocolor=="Std" ) metchrom=0; + else if (params->colorToning.twocolor=="All" ) metchrom=1; + else if (params->colorToning.twocolor=="Separ") metchrom=2; + else if (params->colorToning.twocolor=="Two" ) metchrom=3; + + if(metchrom==3) twocol=false; + + float iplow,iphigh; + if(twocol==false) { + iplow=(float)ctColorCurve.low; + iphigh=(float)ctColorCurve.high; + + } + int twoc=0;//integer instead of bool to let more possible choice...other than 2 and 500. + if(twocol==false) twoc=0; // 2 colours + else twoc=1; // 500 colours + if (params->colorToning.method=="Lab") algm=1; + else if(params->colorToning.method=="Lch") algm=2; //in case of + if(algm <=2) { +#ifdef _OPENMP +#pragma omp parallel for schedule(dynamic, 5) +#endif + for (int i=0; ir(i,j); + float g = tmpImage->g(i,j); + float b = tmpImage->b(i,j); + float ro,bo,go; + labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve,cl2Toningcurve, iplow, iphigh, wp, wip); + tmpImage->r(i,j)=CLIP(ro); + tmpImage->g(i,j)=CLIP(go); + tmpImage->b(i,j)=CLIP(bo); + + } + } + } + } + + else if (params->colorToning.method.substr(0,3)=="RGB") { + // color toning +#ifdef _OPENMP +#pragma omp parallel for schedule(dynamic, 5) +#endif + for (int i=0; ir(i,j); + float g = tmpImage->g(i,j); + float b = tmpImage->b(i,j); + + // Luminance = (0.299f*r + 0.587f*g + 0.114f*b) + + float h,s,l; + Color::rgb2hsl(r,g,b,h,s,l); + + float l_ = Color::gamma_srgb(l*65535.f)/65535.f; + + // get the opacity and tweak it to preserve saturated colors + float opacity = ctOpacityCurve.lutOpacityCurve[l_*500.f]/4.f; + + float r2, g2, b2; + ctColorCurve.getVal(l_, r2, g2, b2); // get the color from the color curve + + float h2, s2, l2; + Color::rgb2hsl(r2,g2,b2,h2,s2,l2); // transform this new color to hsl + + Color::hsl2rgb(h2, s2, l, r2, g2, b2); + + tmpImage->r(i,j)= r+(r2-r)*opacity; + tmpImage->g(i,j) = g+(g2-g)*opacity; + tmpImage->b(i,j)= b+(b2-b)*opacity; + } + } + } + } + // filling the pipette buffer by the content of the temp pipette buffers + // due to optimization, we have to test now if the pipette has been filled in the second tile loop, by + // testing editID + /*if (editImgFloat) { + for (int i=istart,ti=0; ir(i,j) = editIFloatTmpR[ti*TS+tj]; + editImgFloat->g(i,j) = editIFloatTmpG[ti*TS+tj]; + editImgFloat->b(i,j) = editIFloatTmpB[ti*TS+tj]; + } + } + else*/ + /* + if (editWhatever && (editID==EUID_BlackWhiteAfterCurve)) { + for (int i=istart,ti=0; iv(i,j) = editWhateverTmp[ti*TS+tj]; + } + } +*/ + + // ready, fill lab (has to be the same code than the "fill lab" above!) + +#ifdef _OPENMP +#pragma omp parallel for schedule(dynamic, 5) +#endif + for (int i=0; ir(i,j); + float g = tmpImage->g(i,j); + float b = tmpImage->b(i,j); + + float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; + float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; + float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; + + float fx,fy,fz; + + fx = (x<65535.0f ? cachef[std::max(x,0.f)] : (327.68f*float(exp(log(x/MAXVALF)/3.0f )))); + fy = (y<65535.0f ? cachef[std::max(y,0.f)] : (327.68f*float(exp(log(y/MAXVALF)/3.0f )))); + fz = (z<65535.0f ? cachef[std::max(z,0.f)] : (327.68f*float(exp(log(z/MAXVALF)/3.0f )))); + + lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; + lab->a[i][j] = (500.0f * (fx - fy) ); + lab->b[i][j] = (200.0f * (fy - fz) ); + //test for color accuracy + /*float fy = (0.00862069 * lab->L[i][j])/327.68 + 0.137932; // (L+16)/116 + float fx = (0.002 * lab->a[i][j])/327.68 + fy; + float fz = fy - (0.005 * lab->b[i][j])/327.68; - //test for color accuracy - /*float fy = (0.00862069 * lab->L[i][j])/327.68 + 0.137932; // (L+16)/116 - float fx = (0.002 * lab->a[i][j])/327.68 + fy; - float fz = fy - (0.005 * lab->b[i][j])/327.68; + float x_ = 65535*Lab2xyz(fx)*Color::D50x; + float y_ = 65535*Lab2xyz(fy); + float z_ = 65535*Lab2xyz(fz)*Color::D50z; - float x_ = 65535*Lab2xyz(fx)*Color::D50x; - float y_ = 65535*Lab2xyz(fy); - float z_ = 65535*Lab2xyz(fz)*Color::D50z; + int R,G,B; + xyz2srgb(x_,y_,z_,R,G,B); + r=(float)R; g=(float)G; b=(float)B; + float xxx=1;*/ - int R,G,B; - xyz2srgb(x_,y_,z_,R,G,B); - r=(float)R; g=(float)G; b=(float)B; - float xxx=1;*/ + } + } - } - } - if(tmpImage) - delete tmpImage; + + if(tmpImage) + delete tmpImage; } - - -// delete tmpImage; - if (hCurveEnabled) delete hCurve; if (sCurveEnabled) delete sCurve; if (vCurveEnabled) delete vCurve; +} + +/** +* @brief retreave RGB value with maximum saturation +* @param r red input and in exit new r +* @param g green input and in exit new g +* @param b blue input and in exit new b +**/ +void ImProcFunctions::retreavergb (float &r, float &g, float &b) { + float mini = min(r,g,b); + float maxi = max(r,g,b); + float kkm=65535.f/maxi; + if(b==mini && r==maxi) {r=65535.f;g=kkm*(g-b);b=0.f;} + else if(b==mini && g==maxi) {g=65535.f;r=kkm*(r-b);b=0.f;} + else if(g==mini && r==maxi) {r=65535.f;b=kkm*(b-g);g=0.f;} + else if(g==mini && b==maxi) {b=65535.f;r=kkm*(r-g);g=0.f;} + else if(r==mini && b==maxi) {b=65535.f;g=kkm*(g-r);r=0.f;} + else if(r==mini && g==maxi) {g=65535.f;b=kkm*(b-r);r=0.f;} +} + +/** +* @brief Interpolate by decreasing with a parabol k = aa*v*v + bb*v +c v[0..1] +* @param reducac val ue of the reduction in the middle of the range +* @param vinf value [0..1] for beginning decrease +* @param aa second degree parameter +* @param bb first degree parameter +* @param cc third parameter +**/ +void ImProcFunctions::secondeg_end (float reducac, float vinf, float &aa, float &bb, float &cc) { + float zrd=reducac;//value at me linear =0.5 + float v0=vinf;//max shadows + float me=(1.f + v0)/2.f;//"median" value = (v0 + 1.=/2) + //float a1=1.f-v0; + float a2=me-v0; + float a3=1.f-v0*v0; + float a4=me*me-v0*v0; + aa = (1.f + (zrd-1.f)*(1-v0)/a2)/(a4*(1.f-v0)/a2 - a3); + bb = -(1.f + a3*aa)/(1.f-v0); + cc = - (aa +bb); +} + +/** +* @brief Interpolate by increasing with a parabol k = aa*v*v + bb*v v[0..1] +* @param reducac val ue of the reduction in the middle of the range +* @param vend value [0..1] for beginning increase +* @param aa second degree parameter +* @param bb first degree parameter +**/ +void ImProcFunctions::secondeg_begin (float reducac, float vend, float &aam, float &bbm) { + float zrmd=reducac;//linear = 0.5 + float v0m=vend; + float mem=vend/2.f;//(0. + 0.8)/2.f + aam=(1.f-zrmd*v0m/mem)/(v0m*v0m-mem*v0m);// + bbm=(1.f-aam*v0m*v0m)/v0m; +} + + +/** +* @brief color toning with 9 sliders shadows middletones highlight +* @param r red input values [0..65535] +* @param g green input values [0..65535] +* @param b blue input values [0..65535] +* @param ro red output values [0..65535] +* @param go green output values [0..65535] +* @param bo blue output values [0..65535] +* @param RedLow [0..1] value after transformations of sliders [-100..100] for shadows +* @param GreenLow [0..1] value after transformations of sliders [-100..100] for shadows +* @param BlueLow [0..1] value after transformations of sliders [-100..100] for shadows +* @param RedMed [0..1] value after transformations of sliders [-100..100] for midtones +* @param GreenMed [0..1] value after transformations of sliders [-100..100] for midtones +* @param BlueMed [0..1] value after transformations of sliders [-100..100] for midtones +* @param RedHigh [0..1] value after transformations of sliders [-100..100] for highlights +* @param GreenHigh [0..1] value after transformations of sliders [-100..100] for highlights +* @param BlueHigh [0..1] value after transformations of sliders [-100..100] for highlights +* @param reducac value of the reduction in the middle of the range for second degree increse or decrease action +* @param mode ? +* @param preser whether to preserve luminance (if 1) or not +**/ +void ImProcFunctions::toningsmh (float r, float g, float b, float &ro, float &go, float &bo, float RedLow, float GreenLow, float BlueLow, float RedMed, float GreenMed, float BlueMed, float RedHigh, float GreenHigh, float BlueHigh, float reducac, int mode, int preser, float strProtect) { + float bmu = mode==1 ? 0.5f : 0.4f; + float RedL = 1.f + (RedLow -1.f)*0.4f; + float GreenL = 1.f + (GreenLow-1.f)*0.4f; + float BlueL = 1.f + (BlueLow -1.f)*bmu; + float h,s,v; + Color::rgb2hsv(r, g, b, h, s, v); + float ksat=1.f; + float ksatlow=1.f; +// float s_0=0.55f; +// float s_1=0.85f; + /* + if(mode==0) {//color + if(s < s_0) ksat=SQR((1.f/s_0)*s); + if(s > s_1) ksat=SQR((1.f/(s_1-1.f))*s - (1.f/(s_1-1.f))); + } + */ + ksat=1.f; + float kl=1.f; + float rlo=1.f;//0.4 0.5 + float rlm=1.5f;//1.1 + float rlh=2.2f;//1.1 + float rlob=bmu;//for BW old mode + if(mode==0){//color + rlo*=pow_F(strProtect,0.4f);//0.5 ==> 0.75 + rlh*=pow_F(strProtect,0.4f); + rlm*=pow_F(strProtect,0.4f); + } + else {//bw coefficient to preserve same results as before for satlimtopacity = 0.5 (default) + rlo=strProtect*0.8f;//0.4 + rlob=strProtect;//0.5 + rlm=strProtect*2.2f;//1.1 + rlh=strProtect*2.4f;//1.2 + } + if(mode==0) rlob=rlo; + + //second degree + float aa,bb,cc; + float v0=0.15f; + //fixed value of reducac=0.3 + //secondeg_end (reducac, v0, aa, bb, cc); + if(mode==1) { + reducac=0.5f;//black and white mode + if(v > 0.15f) + kl =(-1.f/0.85f)*v + (1.f)/0.85f;//Low light ==> decrease action after v=0.15 + } + else { //color + secondeg_end (reducac, v0, aa, bb, cc); + float aab,bbb; + secondeg_begin (0.7f, v0, aab, bbb); + + if(v > v0) kl=aa*v*v+bb*v+cc;//verified ==> exact + else if (mode==0) kl=aab*v*v+bbb*v;//ksatlow=ksat; + } + + if(RedLow !=1.f) { + RedL = 1.f + (RedLow-1.f) * kl * ksat * rlo; //0.4 + if(RedLow >= 1.f) { + g -= 20000.f*(RedL-1.f) * ksatlow; + b -= 20000.f*(RedL-1.f) * ksatlow; + } + else { + r += 20000.f*(RedL-1.f) * ksatlow; + } + r=CLIP(r); + g=CLIP(g); + b=CLIP(b); + } + + if(GreenLow !=1.f) { + GreenL = 1.f + (GreenLow-1.f) * kl * ksat * rlo; //0.4 + if(GreenLow >= 1.f) { + r -= 20000.f*(GreenL-1.f) * ksatlow; + b -= 20000.f*(GreenL-1.f) * ksatlow; + } + else { + g += 20000.f*(GreenL-1.f) * ksatlow; + } + + r=CLIP(r); + b=CLIP(b); + g=CLIP(g); + } + + if(BlueLow !=1.f) { + BlueL = 1.f + (BlueLow-1.f) * kl * ksat * rlob; + if(BlueLow >= 1.f) { + r -= 20000.f*(BlueL-1.f) * ksatlow; + g -= 20000.f*(BlueL-1.f) * ksatlow; + } + else { + b += 20000.f*(BlueL-1.f)* ksatlow; + } + + r=CLIP(r); + g=CLIP(g); + b=CLIP(b); + } + // mid tones + float km; + float v0m=0.5f;//max action + float v0mm=0.5f;//max + + if(v= 1.f) { + r += 20000.f*(RedM-1.f); + g -= 10000.f*(RedM-1.f); + b -= 10000.f*(RedM-1.f); + r=CLIP(r); + g=CLIP(g); + b=CLIP(b); + } + else { + r += 10000.f*(RedM-1.f); + g -= 20000.f*(RedM-1.f); + b -= 20000.f*(RedM-1.f); + r=CLIP(r); + g=CLIP(g); + b=CLIP(b); + } + } + + float GreenM = 1.f + (GreenMed-1.f)*rlm; + if(GreenMed !=1.f) { + GreenM = 1.f + (GreenMed-1.f) * km * rlm; + if(GreenMed >= 1.f) { + r -= 10000.f*(GreenM-1.f); + g += 20000.f*(GreenM-1.f); + b -= 10000.f*(GreenM-1.f); + r=CLIP(r); + g=CLIP(g); + b=CLIP(b); + } + else { + r -= 20000.f*(GreenM-1.f); + g += 10000.f*(GreenM-1.f); + b -= 20000.f*(GreenM-1.f); + r=CLIP(r); + g=CLIP(g); + b=CLIP(b); + } + } + + float BlueM = 1.f + (BlueMed-1.f)*rlm; + if(BlueMed !=1.f) { + BlueM = 1.f + (BlueMed-1.f) * km * rlm; + if(BlueMed >= 1.f) { + r -= 10000.f*(BlueM-1.f); + g -= 10000.f*(BlueM-1.f); + b += 20000.f*(BlueM-1.f); + r=CLIP(r); + g=CLIP(g); + b=CLIP(b); + } + else { + r -= 20000.f*(BlueM-1.f); + g -= 20000.f*(BlueM-1.f); + b += 10000.f*(BlueM-1.f); + r=CLIP(r); + g=CLIP(g); + b=CLIP(b); + } + } + + //high tones + float kh; + kh=1.f; + float v00=0.8f;//max action + float aa0, bb0; + secondeg_begin (reducac, v00, aa0, bb0); +// float hmu=1.5f; +// if(mode==1) hmu=1.2f;//for BW old mode + + if(v > v00) { kh =(-1.f/(1.f-v00))*v + (1.f)/(1.f-v00); }//High tones + else kh=aa0*v*v+bb0*v;//verification = good + + float RedH=1.f + (RedHigh-1.f)*rlh; + float GreenH=1.f + (GreenHigh-1.f)*rlh; + float BlueH=1.f + (BlueHigh-1.f)*rlh;//1.2 + if(RedHigh !=1.f) { + RedH = 1.f + (RedHigh-1.f) * kh * rlh; //1.2 + if(RedHigh >= 1.f) { + r += 20000.f*(RedH-1.f); + r=CLIP(r); + } + else { + g -= 20000.f*(RedH-1.f); + b -= 20000.f*(RedH-1.f); + } + g=CLIP(g); + b=CLIP(b); + } + if(GreenHigh !=1.f) { + GreenH = 1.f + (GreenHigh-1.f) * kh * rlh; //1.2 + if(GreenHigh >= 1.f) { + g += 20000.f*(GreenH-1.f); + g=CLIP(g); + } + else { + r -= 20000.f*(GreenH-1.f); + b -= 20000.f*(GreenH-1.f); + } + r=CLIP(r); + b=CLIP(b); + } + if(BlueHigh !=1.f) { + BlueH = 1.f + (BlueHigh-1.f) * kh * rlh; //1.2 + if(BlueHigh >= 1.f) { + b += 20000.f*(BlueH-1.f); + b=CLIP(b); + } + else { + r -= 20000.f*(BlueH-1.f); + g -= 20000.f*(BlueH-1.f); + } + r=CLIP(r); + g=CLIP(g); + } + + ro=r; + go=g; + bo=b; +} + +/** +* @brief color toning with 2 colors - 2 sliders saturation shadows and highlight and one balance +* @param r g b input values [0..65535] +* @param ro go bo output values [0..65535] +* @param iplow iphigh [0..1] from curve color - value of luminance shadows and highlights +* @param rl gl bl [0..65535] - color of reference shadow +* @param rh gh bh [0..65535] - color of reference highlight +* @param SatLow SatHigh [0..1] from sliders saturation shadows and highlight +* @param balanS [0..1] balance for shadows (one slider) +* @param balanH [0..1] balance for highlights (same slider than for balanS) +* @param reducac value of the reduction in the middle of the range for second degree, increase or decrease action +**/ +void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float rl, float gl,float bl, float rh, float gh, float bh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect) { + float lumbefore=0.299f*r + 0.587f*g + 0.114f*b; + float h,s,l; + Color::rgb2hsl(r,g,b,h,s,l); + float v; + Color::rgb2hsv(r, g, b, h, s, v); + float ksat=1.f; + float ksatlow=1.f; + float s_0=0.55f; + float s_1=0.85f; +/* + if(mode==0) {//color + if(s < s_0) ksat=SQR((1.f/s_0)*s); + if(s > s_1) ksat=SQR((1.f/(s_1-1.f))*s - (1.f/(s_1-1.f))); + } + */ + ksat=1.f; + float kl=1.f; + float rlo=1.f; + float rlh=2.2f; + rlo*=pow_F(strProtect,0.4f);//0.5 ==> 0.75 transfered value for more action + rlh*=pow_F(strProtect,0.4f); + //low tones + //second degree + float aa, bb, cc; + //fixed value of reducac =0.4; + secondeg_end (reducac, iplow, aa, bb, cc); + float aab, bbb, ccb; + + secondeg_begin (0.7f, iplow, aab, bbb); + + if(v > iplow) kl=aa*v*v+bb*v+cc; + else if (mode==0) kl=aab*v*v+bbb*v; + + //rl gl bl + float RedL, GreenL, BlueL; + float krl=rl/(rl+gl+bl); + float kgl=gl/(rl+gl+bl); + float kbl=bl/(rl+gl+bl); + + if(SatLow > 0.f) { + float kmgb; + if(g<20000.f || b < 20000.f || r < 20000.f) { kmgb=min(r,g,b);kl *= pow((kmgb/20000.f),0.85f); } //I have tested ...0.85 compromise... + RedL = 1.f + (SatLow*krl) * kl * ksat * rlo * balanS; //0.4 + if(krl > 0.f) { + g -= 20000.f*(RedL-1.f) * ksatlow; + b -= 20000.f*(RedL-1.f) * ksatlow; + } + g=CLIP(g); + b=CLIP(b); + + GreenL = 1.f + (SatLow*kgl) * kl * ksat * rlo * balanS; //0.4 + if(kgl > 0.f) { + r -= 20000.f*(GreenL-1.f) * ksatlow; + b -= 20000.f*(GreenL-1.f) * ksatlow; + } + r=CLIP(r); + b=CLIP(b); + + BlueL = 1.f + (SatLow*kbl) * kl * ksat * rlo * balanS; //0.4 + if(kbl > 0.f) { + r -= 20000.f*(BlueL-1.f) * ksatlow; + g -= 20000.f*(BlueL-1.f) * ksatlow; + } + r=CLIP(r); + g=CLIP(g); + } + + //high tones + float kh=1.f; + kh=1.f; + float aa0, bb0; + //fixed value of reducac ==0.4; + secondeg_begin (reducac, iphigh, aa0, bb0); + + if(v > iphigh) { kh =(-1.f/(1.f-iphigh))*v + (1.f)/(1.f-iphigh); } //Low light ==> decrease action after iplow + else kh=aa0*v*v+bb0*v; + float kmgb; + if(g>45535.f || b > 45535.f || r > 45535.f) { + kmgb=max(r,g,b); + float cora=1.f/(45535.f-65535.f); + float corb=1.f-cora*45535.f; + float cor=kmgb*cora+corb; + kh *= cor; + /* best algo if necessary with non linear response...little differences and more time! + float aa=1.f /(pow(45535.f,0.65f) - pow(65535.f,0.65f)); + float bb=1.f-aa*pow(45535.f,0.65f); + float cor=aa*pow(kmbg,0.65f)+bb; + kh*=cor;*/ + } + + float RedH, GreenH, BlueH; + float krh=rh/(rh+gh+bh); + float kgh=gh/(rh+gh+bh); + float kbh=bh/(rh+gh+bh); + if(SatHigh > 0.f) { + RedH = 1.f + (SatHigh*krh) * kh * rlh * balanH; //1.2 + if(krh > 0.f) { + r += 20000.f*(RedH-1.f); + r=CLIP(r); + } + g=CLIP(g); + b=CLIP(b); + + GreenH = 1.f + (SatHigh*kgh) * kh * rlh * balanH; //1.2 + if(kgh> 0.f) { + g += 20000.f*(GreenH-1.f); + g=CLIP(g); + } + r=CLIP(r); + b=CLIP(b); + BlueH = 1.f + (SatHigh*kbh) * kh * rlh * balanH; //1.2 + if(kbh > 0.f) { + b += 20000.f*(BlueH-1.f); + b=CLIP(b); + } + r=CLIP(r); + g=CLIP(g); + } + float lumafter=0.299f*r + 0.587f*g + 0.114f*b; + float preserv=1.f; + if(preser==1) preserv=lumbefore/lumafter; + + //float preserv=lumbefore/lumafter; + ro=r; + go=g; + bo=b; + ro*=preserv; + go*=preserv; + bo*=preserv; + ro=CLIP(ro); + go=CLIP(go); + bo=CLIP(bo); +} + +/** +* @brief color toning with interpolation in mode Lab +* @param r g b input values [0..65535] +* @param ro go bo output values [0..65535] +* @param algm metchrom twoc - methods +* @param ctColorCurve curve 500 colors +* @param ctOpacityCurve curve standard 'ab' +* @param clToningcurve curve special 'ab' and 'a' +* @param cl2Toningcurve curve special 'b' +* @param iplow iphigh [0..1] luminance +* @param wp wip 3x3 matrix and inverse conversion rgb XYZ +**/ +void ImProcFunctions::labtoning (float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve,LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3] ) { + float realL; + float h,s,l; + Color::rgb2hsl(r,g,b,h,s,l); + float x2, y2, z2; + float xl, yl, zl; + + if(twoc!=1) { + l = (Color::gammatab_13_2[ l*65535.f])/65535.f;//to compensate L from Lab + iphigh = (Color::gammatab_13_2[iphigh*65535.f])/65535.f; + iplow = (Color::gammatab_13_2[ iplow*65535.f])/65535.f; + } + + if(twoc==1) { + ctColorCurve.getVal(l, x2, y2, z2); + } + else { + ctColorCurve.getVal(iphigh, x2, y2, z2); + ctColorCurve.getVal(iplow, xl, yl, zl); + } + realL=l; + + + //float opacity = ctOpacityCurve.lutOpacityCurve[l*500.f]; + + + // get the opacity and tweak it to preserve saturated colors + //float l_ = Color::gamma_srgb(l*65535.f)/65535.f; + float opacity = (1.f-min(s/satLimit, 1.f)*(1.f-satLimitOpacity)) * ctOpacityCurve.lutOpacityCurve[l*500.f]; + + float opacity2 = (1.f-min(s/satLimit, 1.f)*(1.f-satLimitOpacity)); + + //float ro, go, bo; + bool chr = true; + bool lum = false; + float lm=l; + float chromat, luma; + if (clToningcurve[lm*65535.f]/(lm*65535.f) < 1.f) + {chromat = (clToningcurve[(lm)*65535.f]/(lm*65535.f))-1.f;} //special effect + else + {chromat = 1.f-SQR(SQR((lm*65535.f)/clToningcurve[(lm)*65535.f]));} //apply C=f(L) acts on 'a' and 'b' + + if (cl2Toningcurve[lm*65535.f]/(lm*65535.f) < 1.f) + {luma = (cl2Toningcurve[(lm)*65535.f]/(lm*65535.f))-1.f;} //special effect + else + {luma = 1.f-SQR(SQR((lm*65535.f)/(cl2Toningcurve[(lm)*65535.f])));} //apply C2=f(L) acts only on 'b' + int todo=1; + if (algm==1) Color::interpolateRGBColor(realL, iplow, iphigh, algm, opacity, twoc, metchrom, chr, lum, chromat, luma, r, g, b, xl, yl, zl, x2, y2, z2, todo, wp, wip, ro, go, bo); + else Color::interpolateRGBColor(realL, iplow, iphigh, algm, opacity2, twoc, metchrom, chr, lum, chromat, luma, r, g, b, xl, yl, zl, x2, y2, z2, todo, wp, wip, ro, go, bo); } @@ -3343,7 +4317,8 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI // reference to the params structure has to be done outside of the parallelization to avoid CPU cache problem bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated int chromaticity = params->labCurve.chromaticity; - bool bwToning = params->labCurve.chromaticity==-100 /*|| params->blackwhite.method=="Ch" */ || params->blackwhite.enabled; + bool bwonly = params->blackwhite.enabled && !params->colorToning.enabled; + bool bwToning = params->labCurve.chromaticity==-100 /*|| params->blackwhite.method=="Ch" || params->blackwhite.enabled */ || bwonly; //if(chromaticity==-100) chromaticity==-99; bool LCredsk = params->labCurve.lcredsk; bool ccut = ccutili; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 1aef3dfe5..3d70e5a18 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -195,12 +195,22 @@ class ImProcFunctions { void firstAnalysis (Imagefloat* working, const ProcParams* params, LUTu & vhist16, double gamma); void rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, + SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve,LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1,const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob); void rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, + SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1,const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh); + void labtoning (float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve,LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3] ); + void toning2col (float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float rl, float gl,float bl, float rh, float gh, float bh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect); + void toningsmh (float r, float g, float b, float &ro, float &go, float &bo, float RedLow, float GreenLow, float BlueLow, float RedMed, float GreenMed, float BlueMed, float RedHigh, float GreenHigh, float BlueHigh, float reducac, int mode, int preser, float strProtect); + void toningsmh2 (float r, float g, float b, float &ro, float &go, float &bo, float low[3], float satLow, float med[3], float satMed, float high[3], float satHigh, float reducac, int mode, int preser); + void secondeg_begin (float reducac, float vend, float &aam, float &bbm); + void secondeg_end (float reducac, float vinf, float &aa, float &bb, float &cc); + + void retreavergb (float &r, float &g, float &b); + void moyeqt (Imagefloat* working, float &moyS, float &eqty); + void luminanceCurve (LabImage* lold, LabImage* lnew, LUTf &curve); void ciecam_02float (CieImage* ncie, float adap, int begh, int endh, int pW, int pwb, LabImage* lab, const ProcParams* params, const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, diff --git a/rtengine/procevents.h b/rtengine/procevents.h index cb13ab444..98226ea71 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -280,7 +280,37 @@ enum ProcEvent { // EvDirPyrEqualizeralg=254, EvDPDNmedian=254, EvDPDNmedmet=255, - NUMOFEVENTS=256 + EvColorToningEnabled=256, + EvColorToningColor =257, + EvColorToningOpacity=258, + EvColorToningCLCurve=259, + EvColorToningMethod=260, +// EvColorToningTwocolor=259, + EvColorToningLLCurve=261, + EvColorToningredlow=262, + EvColorToninggreenlow=263, + EvColorToningbluelow=264, + EvColorToningredmed=265, + EvColorToninggreenmed=266, + EvColorToningbluemed=267, + EvColorToningredhigh=268, + EvColorToninggreenhigh=269, + EvColorToningbluehigh=270, + EvColorToningbalance=271, + EvColorToningNeutral=272, + EvColorToningsatlow=273, + EvColorToningsathigh=274, + EvColorToningTwocolor=275, + EvColorToningNeutralcur=276, + EvColorToningLumamode=277, + EvColorToningShadows=278, + EvColorToningHighights=279, + EvColorToningSatProtection=280, + EvColorToningSatThreshold=281, + EvColorToningStrProtection=282, + EvColorToningautosat=283, + + NUMOFEVENTS=284 }; } #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index fa432356f..f5b0c1e2a 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -110,10 +110,327 @@ void CropParams::mapToResized(int resizedWidth, int resizedHeight, int scale, in } } +ColorToningParams::ColorToningParams () : hlColSat(60, 80, false), shadowsColSat(80, 208, false) { + setDefault(); +} + +void ColorToningParams::setDefault() { + enabled = false; + autosat=true; + method = "Lab"; + colorCurve.resize(9); + colorCurve.at(0) = double(FCT_MinMaxCPoints); + colorCurve.at(1) = 0.05; + colorCurve.at(2) = 0.62; + colorCurve.at(3) = 0.25; + colorCurve.at(4) = 0.25; + colorCurve.at(5) = 0.585; + colorCurve.at(6) = 0.11; + colorCurve.at(7) = 0.25; + colorCurve.at(8) = 0.25; + + opacityCurve.resize(17); + opacityCurve.at(0 ) = double(FCT_MinMaxCPoints); + opacityCurve.at(1 ) = 0.; // first point + opacityCurve.at(2 ) = 0.30; + opacityCurve.at(3 ) = 0.35; + opacityCurve.at(4 ) = 0.; + opacityCurve.at(5 ) = 0.25; // second point + opacityCurve.at(6 ) = 0.8; + opacityCurve.at(7 ) = 0.35; + opacityCurve.at(8 ) = 0.35; + opacityCurve.at(9 ) = 0.7; + opacityCurve.at(10) = 0.8; + opacityCurve.at(11) = 0.35; + opacityCurve.at(12) = 0.35; + opacityCurve.at(13) = 1.0; + opacityCurve.at(14) = 0.3; + opacityCurve.at(15) = 0.; + opacityCurve.at(16) = 0.; + + hlColSat.setValues(60, 80); + shadowsColSat.setValues(80, 208); + balance = 0; + satProtectionThreshold = 30; + saturatedOpacity = 80; + strengthprotection = 50; + lumamode = true; + twocolor = "Std"; + redlow = 0.0; + greenlow = 0.0; + bluelow = 0.0; + satlow = 0.0; + sathigh = 0.0; + redmed = 0.0; + greenmed = 0.0; + bluemed = 0.0; + redhigh = 0.0; + greenhigh = 0.0; + bluehigh = 0.0; + + //clcurve.clear (); + //clcurve.push_back(DCT_Linear); + clcurve.resize(7); + clcurve.at(0) = double(DCT_NURBS); + clcurve.at(1) = 0.0; + clcurve.at(2) = 0.0; + clcurve.at(3) = 0.35; + clcurve.at(4) = 0.65; + clcurve.at(5) = 1.; + clcurve.at(6) = 1.; + + // colorToning.llcurve.clear (); + // colorToning.llcurve.push_back(DCT_Linear); + cl2curve.resize(7); + cl2curve.at(0) = double(DCT_NURBS); + cl2curve.at(1) = 0.0; + cl2curve.at(2) = 0.0; + cl2curve.at(3) = 0.35; + cl2curve.at(4) = 0.65; + cl2curve.at(5) = 1.; + cl2curve.at(6) = 1.; + + /* colorToning.llcurve.at(1) = 0.0; + llcurve.at(2) = 0.0; + llcurve.at(3) = 0.3; + llcurve.at(4) = 0.19; + llcurve.at(5) = 0.69; + llcurve.at(6) = 0.8; + llcurve.at(7) = 1.; + llcurve.at(8) = 1.; +*/ + +} + +void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vector &opacityCurve) const { + // check if non null first + if (!redlow && !greenlow && !bluelow && !redmed && !greenmed && !bluemed && !redhigh && !greenhigh && !bluehigh) { + colorCurve.resize(1); + colorCurve.at(0) = FCT_Linear; + opacityCurve.resize(1); + opacityCurve.at(0) = FCT_Linear; + return; + } + + float low[3]; // RGB color for shadows + float med[3]; // RGB color for mid-tones + float high[3]; // RGB color for highlights + float lowSat = 0.f; + float medSat = 0.f; + float highSat = 0.f; + float minTmp, maxTmp; + + // Fill the shadow mixer values of the Color TOning tool + low[0] = float(redlow )/100.f; // [-1. ; +1.] + low[1] = float(greenlow)/100.f; // [-1. ; +1.] + low[2] = float(bluelow )/100.f; // [-1. ; +1.] + minTmp = min(low[0], low[1], low[2]); + maxTmp = max(low[0], low[1], low[2]); + if (maxTmp-minTmp > 0.005f) { + float v[3]; + lowSat = (maxTmp-minTmp)/2.f; + if (low[0] == minTmp) v[0] = 0.f; + else if (low[1] == minTmp) v[1] = 0.f; + else if (low[2] == minTmp) v[2] = 0.f; + if (low[0] == maxTmp) v[0] = 1.f; + else if (low[1] == maxTmp) v[1] = 1.f; + else if (low[2] == maxTmp) v[2] = 1.f; + if (low[3] != minTmp && low[0] != maxTmp) v[0] = (low[0]-minTmp)/(maxTmp-minTmp); + else if (low[1] != minTmp && low[1] != maxTmp) v[1] = (low[1]-minTmp)/(maxTmp-minTmp); + else if (low[2] != minTmp && low[2] != maxTmp) v[2] = (low[2]-minTmp)/(maxTmp-minTmp); + low[0] = v[0]; + low[1] = v[1]; + low[2] = v[2]; + } + else { + low[0] = low[1] = low[2] = 1.f; + } + + // Fill the mid-tones mixer values of the Color TOning tool + med[0] = float(redmed )/100.f; // [-1. ; +1.] + med[1] = float(greenmed)/100.f; // [-1. ; +1.] + med[2] = float(bluemed )/100.f; // [-1. ; +1.] + minTmp = min(med[0], med[1], med[2]); + maxTmp = max(med[0], med[1], med[2]); + if (maxTmp-minTmp > 0.005f) { + float v[3]; + medSat = (maxTmp-minTmp)/2.f; + if (med[0] == minTmp) v[0] = 0.f; + else if (med[1] == minTmp) v[1] = 0.f; + else if (med[2] == minTmp) v[2] = 0.f; + if (med[0] == maxTmp) v[0] = 1.f; + else if (med[1] == maxTmp) v[1] = 1.f; + else if (med[2] == maxTmp) v[2] = 1.f; + if (med[3] != minTmp && med[0] != maxTmp) v[0] = (med[0]-minTmp)/(maxTmp-minTmp); + else if (med[1] != minTmp && med[1] != maxTmp) v[1] = (med[1]-minTmp)/(maxTmp-minTmp); + else if (med[2] != minTmp && med[2] != maxTmp) v[2] = (med[2]-minTmp)/(maxTmp-minTmp); + med[0] = v[0]; + med[1] = v[1]; + med[2] = v[2]; + } + else { + med[0] = med[1] = med[2] = 1.f; + } + + // Fill the highlight mixer values of the Color TOning tool + high[0] = float(redhigh )/100.f; // [-1. ; +1.] + high[1] = float(greenhigh)/100.f; // [-1. ; +1.] + high[2] = float(bluehigh )/100.f; // [-1. ; +1.] + minTmp = min(high[0], high[1], high[2]); + maxTmp = max(high[0], high[1], high[2]); + if (maxTmp-minTmp > 0.005f) { + float v[3]; + highSat = (maxTmp-minTmp)/2.f; + if (high[0] == minTmp) v[0] = 0.f; + else if (high[1] == minTmp) v[1] = 0.f; + else if (high[2] == minTmp) v[2] = 0.f; + if (high[0] == maxTmp) v[0] = 1.f; + else if (high[1] == maxTmp) v[1] = 1.f; + else if (high[2] == maxTmp) v[2] = 1.f; + if (high[3] != minTmp && high[0] != maxTmp) v[0] = (high[0]-minTmp)/(maxTmp-minTmp); + else if (high[1] != minTmp && high[1] != maxTmp) v[1] = (high[1]-minTmp)/(maxTmp-minTmp); + else if (high[2] != minTmp && high[2] != maxTmp) v[2] = (high[2]-minTmp)/(maxTmp-minTmp); + high[0] = v[0]; + high[1] = v[1]; + high[2] = v[2]; + } + else { + high[0] = high[1] = high[2] = 1.f; + } + + + + + const double xPosLow = 0.1; + const double xPosMed = 0.4; + const double xPosHigh = 0.7; + + + + + colorCurve.resize( medSat!=0.f ? 13 : 9 ); + colorCurve.at(0) = FCT_MinMaxCPoints; + opacityCurve.resize(13); + opacityCurve.at(0) = FCT_MinMaxCPoints; + + float h, s, l; + int idx = 1; + + if (lowSat == 0.f) { + if (medSat != 0.f) + Color::rgb2hsl(med[0], med[1], med[2], h, s, l); + else// highSat can't be null if the 2 other ones are! + Color::rgb2hsl(high[0], high[1], high[2], h, s, l); + } + else + Color::rgb2hsl(low[0], low[1], low[2], h, s, l); + colorCurve.at(idx++) = xPosLow; + colorCurve.at(idx++) = h; + colorCurve.at(idx++) = 0.35; + colorCurve.at(idx++) = 0.35; + + if (medSat != 0.f) { + Color::rgb2hsl(med[0], med[1], med[2], h, s, l); + colorCurve.at(idx++) = xPosMed; + colorCurve.at(idx++) = h; + colorCurve.at(idx++) = 0.35; + colorCurve.at(idx++) = 0.35; + } + + if (highSat == 0.f) { + if (medSat != 0.f) + Color::rgb2hsl(med[0], med[1], med[2], h, s, l); + else// lowSat can't be null if the 2 other ones are! + Color::rgb2hsl(low[0], low[1], low[2], h, s, l); + } + else + Color::rgb2hsl(high[0], high[1], high[2], h, s, l); + colorCurve.at(idx++) = xPosHigh; + colorCurve.at(idx++) = h; + colorCurve.at(idx++) = 0.35; + colorCurve.at(idx) = 0.35; + + opacityCurve.at(1) = xPosLow; + opacityCurve.at(2) = double(lowSat); + opacityCurve.at(3) = 0.35; + opacityCurve.at(4) = 0.35; + opacityCurve.at(5) = xPosMed; + opacityCurve.at(6) = double(medSat); + opacityCurve.at(7) = 0.35; + opacityCurve.at(8) = 0.35; + opacityCurve.at(9) = xPosHigh; + opacityCurve.at(10) = double(highSat); + opacityCurve.at(11) = 0.35; + opacityCurve.at(12) = 0.35; +} + +void ColorToningParams::slidersToCurve(std::vector &colorCurve, std::vector &opacityCurve) const { + if (hlColSat.value[0]==0 && shadowsColSat.value[0]==0) { // if both opacity are null, set both curves to Linear + colorCurve.resize(1); + colorCurve.at(0) = FCT_Linear; + opacityCurve.resize(1); + opacityCurve.at(0) = FCT_Linear; + return; + } + + colorCurve.resize(9); + colorCurve.at(0) = FCT_MinMaxCPoints; + colorCurve.at(1) = 0.26 + 0.12*double(balance)/100.; + colorCurve.at(2) = double(shadowsColSat.value[1])/360.; + colorCurve.at(3) = 0.35; + colorCurve.at(4) = 0.35; + colorCurve.at(5) = 0.64 + 0.12*double(balance)/100.; + colorCurve.at(6) = double(hlColSat.value[1])/360.; + colorCurve.at(7) = 0.35; + colorCurve.at(8) = 0.35; + + opacityCurve.resize(9); + opacityCurve.at(0) = FCT_MinMaxCPoints; + opacityCurve.at(1) = colorCurve.at(1); + opacityCurve.at(2) = double(shadowsColSat.value[0])/100.; + opacityCurve.at(3) = 0.35; + opacityCurve.at(4) = 0.35; + opacityCurve.at(5) = colorCurve.at(5); + opacityCurve.at(6) = double(hlColSat.value[0])/100.; + opacityCurve.at(7) = 0.35; + opacityCurve.at(8) = 0.35; +} + +void ColorToningParams::getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurve &opacityCurveLUT, const double xyz_rgb[3][3], const double rgb_xyz[3][3]) const { + float satur=0.8f; + float lumin=0.5f;//middle of luminance for optimization of gamut - no real importance...as we work in XYZ and gamut control + + // Transform slider values to control points + std::vector cCurve, oCurve; + if (method=="RGBSliders" || method=="Splitlr") + slidersToCurve(cCurve, oCurve); + else if (method=="Splitco") + mixerToCurve(cCurve, oCurve); + else { + cCurve = this->colorCurve; + oCurve = this->opacityCurve; + } + + if(method=="Lab") { + if(twocolor=="Separ") satur=0.9f; + if(twocolor=="All" || twocolor=="Two") satur=0.9f; + colorCurveLUT.SetXYZ(cCurve, xyz_rgb, rgb_xyz, satur, lumin); + opacityCurveLUT.Set(oCurve); + } + else if(method=="Splitlr" || method=="Splitco") { + colorCurveLUT.SetXYZ(cCurve, xyz_rgb, rgb_xyz, satur, lumin); + opacityCurveLUT.Set(oCurve); + } + else if(method.substr(0,3)=="RGB") { + colorCurveLUT.SetRGB(cCurve, xyz_rgb, rgb_xyz); + opacityCurveLUT.Set(oCurve); + } +} + ProcParams::ProcParams () { setDefaults (); -} +} void ProcParams::init () { @@ -123,7 +440,7 @@ void ProcParams::init () { void ProcParams::cleanup () { WBParams::cleanup(); -} +} ProcParams* ProcParams::create () { @@ -155,12 +472,12 @@ void ProcParams::setDefaults () { toneCurve.curveMode2 = ToneCurveParams::TC_MODE_STD; toneCurve.hrenabled = false; toneCurve.method = "Blend"; - labCurve.brightness = 0; + labCurve.brightness = 0; labCurve.contrast = 0; labCurve.chromaticity = 0; - labCurve.avoidcolorshift = true; + labCurve.avoidcolorshift = false; labCurve.lcredsk = true; - + labCurve.rstprotection = 0; labCurve.lcurve.clear (); labCurve.lcurve.push_back(DCT_Linear); @@ -176,7 +493,7 @@ void ProcParams::setDefaults () { labCurve.lhcurve.push_back(FCT_Linear); labCurve.hhcurve.clear (); labCurve.hhcurve.push_back(FCT_Linear); - + labCurve.lccurve.clear (); labCurve.lccurve.push_back(DCT_Linear); labCurve.clcurve.clear (); @@ -190,6 +507,7 @@ void ProcParams::setDefaults () { rgbCurves.bcurve.clear (); rgbCurves.bcurve.push_back(DCT_Linear); + colorToning.setDefault(); sharpenEdge.enabled = false; sharpenEdge.passes = 2; @@ -464,17 +782,17 @@ void ProcParams::setDefaults () { raw.dcb_iterations=2; raw.dcb_enhance=false; raw.lmmse_iterations=2; - + //raw.all_enhance=false; - + // exposure before interpolation raw.expos=1.0; raw.preser=0.0; - raw.blackzero=0.0; - raw.blackone=0.0; - raw.blacktwo=0.0; - raw.blackthree=0.0; - raw.twogreen=true; + raw.blackzero=0.0; + raw.blackone=0.0; + raw.blacktwo=0.0; + raw.blackthree=0.0; + raw.twogreen=true; exif.clear (); iptc.clear (); @@ -1059,6 +1377,54 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_double_list("RGB Curves", "bCurve", RGBbcurve); } + // save Color Toning + if (!pedited || pedited->colorToning.enabled) keyFile.set_boolean ("ColorToning", "Enabled", colorToning.enabled); + if (!pedited || pedited->colorToning.method) keyFile.set_string ("ColorToning", "Method", colorToning.method); + if (!pedited || pedited->colorToning.lumamode) keyFile.set_boolean ("ColorToning", "Lumamode", colorToning.lumamode); + if (!pedited || pedited->colorToning.twocolor) keyFile.set_string ("ColorToning", "Twocolor", colorToning.twocolor); + if (!pedited || pedited->colorToning.redlow) keyFile.set_double ("ColorToning", "Redlow", colorToning.redlow); + if (!pedited || pedited->colorToning.greenlow) keyFile.set_double ("ColorToning", "Greenlow", colorToning.greenlow); + if (!pedited || pedited->colorToning.bluelow) keyFile.set_double ("ColorToning", "Bluelow", colorToning.bluelow); + if (!pedited || pedited->colorToning.satlow) keyFile.set_double ("ColorToning", "Satlow", colorToning.satlow); + if (!pedited || pedited->colorToning.balance) keyFile.set_integer ("ColorToning", "Balance", colorToning.balance); + if (!pedited || pedited->colorToning.sathigh) keyFile.set_double ("ColorToning", "Sathigh", colorToning.sathigh); + if (!pedited || pedited->colorToning.redmed) keyFile.set_double ("ColorToning", "Redmed", colorToning.redmed); + if (!pedited || pedited->colorToning.greenmed) keyFile.set_double ("ColorToning", "Greenmed", colorToning.greenmed); + if (!pedited || pedited->colorToning.bluemed) keyFile.set_double ("ColorToning", "Bluemed", colorToning.bluemed); + if (!pedited || pedited->colorToning.redhigh) keyFile.set_double ("ColorToning", "Redhigh", colorToning.redhigh); + if (!pedited || pedited->colorToning.greenhigh) keyFile.set_double ("ColorToning", "Greenhigh", colorToning.greenhigh); + if (!pedited || pedited->colorToning.bluehigh) keyFile.set_double ("ColorToning", "Bluehigh", colorToning.bluehigh); + if (!pedited || pedited->colorToning.autosat) keyFile.set_boolean ("ColorToning", "Autosat", colorToning.autosat); + + if (!pedited || pedited->colorToning.opacityCurve) { + Glib::ArrayHandle curve = colorToning.opacityCurve; + keyFile.set_double_list("ColorToning", "OpacityCurve", curve); + } + if (!pedited || pedited->colorToning.colorCurve) { + Glib::ArrayHandle curve = colorToning.colorCurve; + keyFile.set_double_list("ColorToning", "ColorCurve", curve); + } + if (!pedited || pedited->colorToning.satProtectionThreshold) keyFile.set_integer ("ColorToning", "SatProtectionThreshold", colorToning.satProtectionThreshold ); + if (!pedited || pedited->colorToning.saturatedOpacity) keyFile.set_integer ("ColorToning", "SaturatedOpacity", colorToning.saturatedOpacity ); + if (!pedited || pedited->colorToning.strengthprotection) keyFile.set_integer ("ColorToning", "Strengthprotection", colorToning.strengthprotection ); + + if (!pedited || pedited->colorToning.hlColSat) { + Glib::ArrayHandle thresh (colorToning.hlColSat.value, 2, Glib::OWNERSHIP_NONE); + keyFile.set_integer_list("ColorToning", "HighlightsColorSaturation", thresh); + } + if (!pedited || pedited->colorToning.shadowsColSat) { + Glib::ArrayHandle thresh (colorToning.shadowsColSat.value, 2, Glib::OWNERSHIP_NONE); + keyFile.set_integer_list("ColorToning", "ShadowsColorSaturation", thresh); + } + if (!pedited || pedited->colorToning.clcurve) { + Glib::ArrayHandle clcurve = colorToning.clcurve; + keyFile.set_double_list("ColorToning", "ClCurve", clcurve); + } + if (!pedited || pedited->colorToning.cl2curve) { + Glib::ArrayHandle cl2curve = colorToning.cl2curve; + keyFile.set_double_list("ColorToning", "Cl2Curve", cl2curve); + } + // save raw parameters if (!pedited || pedited->raw.darkFrame) keyFile.set_string ("RAW", "DarkFrame", relativePathIfInside(fname, fnameAbsolute, raw.dark_frame) ); if (!pedited || pedited->raw.dfAuto) keyFile.set_boolean ("RAW", "DarkFrameAuto", raw.df_autoselect ); @@ -1693,12 +2059,50 @@ if (keyFile.has_group ("HSV Equalizer")) { // load RGB curves if (keyFile.has_group ("RGB Curves")) { - if (keyFile.has_key ("RGB Curves", "LumaMode")) { rgbCurves.lumamode = keyFile.get_boolean ("RGB Curves", "LumaMode"); if (pedited) pedited->rgbCurves.lumamode = true; } + if (keyFile.has_key ("RGB Curves", "LumaMode")) { rgbCurves.lumamode = keyFile.get_boolean ("RGB Curves", "LumaMode"); if (pedited) pedited->rgbCurves.lumamode = true; } if (keyFile.has_key ("RGB Curves", "rCurve")) { rgbCurves.rcurve = keyFile.get_double_list ("RGB Curves", "rCurve"); if (pedited) pedited->rgbCurves.rcurve = true; } if (keyFile.has_key ("RGB Curves", "gCurve")) { rgbCurves.gcurve = keyFile.get_double_list ("RGB Curves", "gCurve"); if (pedited) pedited->rgbCurves.gcurve = true; } if (keyFile.has_key ("RGB Curves", "bCurve")) { rgbCurves.bcurve = keyFile.get_double_list ("RGB Curves", "bCurve"); if (pedited) pedited->rgbCurves.bcurve = true; } } + // load Color Toning +if (keyFile.has_group ("ColorToning")) { + if (keyFile.has_key ("ColorToning", "Enabled")) { colorToning.enabled = keyFile.get_boolean ("ColorToning", "Enabled"); if (pedited) pedited->colorToning.enabled = true; } + if (keyFile.has_key ("ColorToning", "Method")) { colorToning.method = keyFile.get_string ("ColorToning", "Method"); if (pedited) pedited->colorToning.method = true; } + if (keyFile.has_key ("ColorToning", "Lumamode")) { colorToning.lumamode = keyFile.get_boolean ("ColorToning", "Lumamode"); if (pedited) pedited->colorToning.lumamode = true; } + if (keyFile.has_key ("ColorToning", "Twocolor")) { colorToning.twocolor = keyFile.get_string ("ColorToning", "Twocolor"); if (pedited) pedited->colorToning.twocolor = true; } + if (keyFile.has_key ("ColorToning", "OpacityCurve")) { colorToning.opacityCurve = keyFile.get_double_list ("ColorToning", "OpacityCurve"); if (pedited) pedited->colorToning.opacityCurve = true; } + if (keyFile.has_key ("ColorToning", "ColorCurve")) { colorToning.colorCurve = keyFile.get_double_list ("ColorToning", "ColorCurve"); if (pedited) pedited->colorToning.colorCurve = true; } + if (keyFile.has_key ("ColorToning", "Autosat")) { colorToning.autosat = keyFile.get_boolean ("ColorToning", "Autosat"); if (pedited) pedited->colorToning.autosat = true; } + if (keyFile.has_key ("ColorToning", "SatProtectionThreshold")) { colorToning.satProtectionThreshold = keyFile.get_integer ("ColorToning", "SatProtectionThreshold"); if (pedited) pedited->colorToning.satProtectionThreshold = true; } + if (keyFile.has_key ("ColorToning", "SaturatedOpacity")) { colorToning.saturatedOpacity = keyFile.get_integer ("ColorToning", "SaturatedOpacity"); if (pedited) pedited->colorToning.saturatedOpacity = true; } + if (keyFile.has_key ("ColorToning", "Strengthprotection")) { colorToning.strengthprotection = keyFile.get_integer ("ColorToning", "Strengthprotection"); if (pedited) pedited->colorToning.strengthprotection = true; } + if (keyFile.has_key ("ColorToning", "HighlightsColorSaturation")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("ColorToning", "HighlightsColorSaturation"); + colorToning.hlColSat.setValues(thresh.data()[0], thresh.data()[1]); + if (pedited) pedited->colorToning.hlColSat = true; + } + if (keyFile.has_key ("ColorToning", "ShadowsColorSaturation")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("ColorToning", "ShadowsColorSaturation"); + colorToning.shadowsColSat.setValues(thresh.data()[0], thresh.data()[1]); + if (pedited) pedited->colorToning.shadowsColSat = true; + } + if (keyFile.has_key ("ColorToning", "ClCurve")) { colorToning.clcurve = keyFile.get_double_list ("ColorToning", "ClCurve"); if (pedited) pedited->colorToning.clcurve = true; } + if (keyFile.has_key ("ColorToning", "Cl2Curve")) { colorToning.cl2curve = keyFile.get_double_list ("ColorToning", "Cl2Curve"); if (pedited) pedited->colorToning.cl2curve = true; } + if (keyFile.has_key ("ColorToning", "Redlow")) { colorToning.redlow = keyFile.get_double ("ColorToning", "Redlow"); if (pedited) pedited->colorToning.redlow = true; } + if (keyFile.has_key ("ColorToning", "Greenlow")) { colorToning.greenlow = keyFile.get_double ("ColorToning", "Greenlow"); if (pedited) pedited->colorToning.greenlow = true; } + if (keyFile.has_key ("ColorToning", "Bluelow")) { colorToning.bluelow = keyFile.get_double ("ColorToning", "Bluelow"); if (pedited) pedited->colorToning.bluelow = true; } + if (keyFile.has_key ("ColorToning", "Satlow")) { colorToning.satlow = keyFile.get_double ("ColorToning", "Satlow"); if (pedited) pedited->colorToning.satlow = true; } + if (keyFile.has_key ("ColorToning", "Balance")) { colorToning.balance = keyFile.get_integer ("ColorToning", "Balance"); if (pedited) pedited->colorToning.balance = true; } + if (keyFile.has_key ("ColorToning", "Sathigh")) { colorToning.sathigh = keyFile.get_double ("ColorToning", "Sathigh"); if (pedited) pedited->colorToning.sathigh = true; } + if (keyFile.has_key ("ColorToning", "Redmed")) { colorToning.redmed = keyFile.get_double ("ColorToning", "Redmed"); if (pedited) pedited->colorToning.redmed = true; } + if (keyFile.has_key ("ColorToning", "Greenmed")) { colorToning.greenmed = keyFile.get_double ("ColorToning", "Greenmed"); if (pedited) pedited->colorToning.greenmed = true; } + if (keyFile.has_key ("ColorToning", "Bluemed")) { colorToning.bluemed = keyFile.get_double ("ColorToning", "Bluemed"); if (pedited) pedited->colorToning.bluemed = true; } + if (keyFile.has_key ("ColorToning", "Redhigh")) { colorToning.redhigh = keyFile.get_double ("ColorToning", "Redhigh"); if (pedited) pedited->colorToning.redhigh = true; } + if (keyFile.has_key ("ColorToning", "Greenhigh")) { colorToning.greenhigh = keyFile.get_double ("ColorToning", "Greenhigh"); if (pedited) pedited->colorToning.greenhigh = true; } + if (keyFile.has_key ("ColorToning", "Bluehigh")) { colorToning.bluehigh = keyFile.get_double ("ColorToning", "Bluehigh"); if (pedited) pedited->colorToning.bluehigh = true; } +} + // load raw settings if (keyFile.has_group ("RAW")) { if (keyFile.has_key ("RAW", "DarkFrame")) { raw.dark_frame = expandRelativePath(fname, "", keyFile.get_string ("RAW", "DarkFrame" )); if (pedited) pedited->raw.darkFrame = true; } @@ -2056,6 +2460,31 @@ bool ProcParams::operator== (const ProcParams& other) { && rgbCurves.rcurve == other.rgbCurves.rcurve && rgbCurves.gcurve == other.rgbCurves.gcurve && rgbCurves.bcurve == other.rgbCurves.bcurve + && colorToning.enabled == other.colorToning.enabled + && colorToning.twocolor == other.colorToning.twocolor + && colorToning.method == other.colorToning.method + && colorToning.colorCurve == other.colorToning.colorCurve + && colorToning.opacityCurve == other.colorToning.opacityCurve + && colorToning.autosat == other.colorToning.autosat + && colorToning.satProtectionThreshold == other.colorToning.satProtectionThreshold + && colorToning.saturatedOpacity == other.colorToning.saturatedOpacity + && colorToning.strengthprotection == other.colorToning.strengthprotection + && colorToning.hlColSat == other.colorToning.hlColSat + && colorToning.shadowsColSat == other.colorToning.shadowsColSat + && colorToning.balance == other.colorToning.balance + && colorToning.clcurve == other.colorToning.clcurve + && colorToning.cl2curve == other.colorToning.cl2curve + && colorToning.redlow == other.colorToning.redlow + && colorToning.greenlow == other.colorToning.greenlow + && colorToning.bluelow == other.colorToning.bluelow + && colorToning.satlow == other.colorToning.satlow + && colorToning.sathigh == other.colorToning.sathigh + && colorToning.redmed == other.colorToning.redmed + && colorToning.greenmed == other.colorToning.greenmed + && colorToning.bluemed == other.colorToning.bluemed + && colorToning.redhigh == other.colorToning.redhigh + && colorToning.greenhigh == other.colorToning.greenhigh + && colorToning.bluehigh == other.colorToning.bluehigh && exif==other.exif && iptc==other.iptc && raw.expos==other.raw.expos diff --git a/rtengine/procparams.h b/rtengine/procparams.h index a71cb59dd..427949130 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -29,6 +29,10 @@ class ParamsEdited; namespace rtengine { + +class ColorGradientCurve; +class OpacityCurve; + namespace procparams { template @@ -44,36 +48,36 @@ class Threshold { #endif public: - Threshold (T val1, T val2, bool startAtOne) { + Threshold (T bottom, T top, bool startAtOne) { initEq1 = startAtOne; - value[0] = val1; - value[1] = val2; + value[0] = bottom; + value[1] = top; value[2] = T(0); value[3] = T(0); _isDouble = false; } - Threshold (T val1, T val2, T val3, T val4, bool startAtOne) { + Threshold (T bottomLeft, T topLeft, T bottomRight, T topRight, bool startAtOne) { initEq1 = startAtOne; - value[0] = val1; - value[1] = val2; - value[2] = val3; - value[3] = val4; + value[0] = bottomLeft; + value[1] = topLeft; + value[2] = bottomRight; + value[3] = topRight; _isDouble = true; } // for convenience, since 'values' is public - void setValues(T val1, T val2) { - value[0] = val1; - value[1] = val2; + void setValues(T bottom, T top) { + value[0] = bottom; + value[1] = top; } // for convenience, since 'values' is public - void setValues(T val1, T val2, T val3, T val4) { - value[0] = val1; - value[1] = val2; - value[2] = val3; - value[3] = val4; + void setValues(T bottomLeft, T topLeft, T bottomRight, T topRight) { + value[0] = bottomLeft; + value[1] = topLeft; + value[2] = bottomRight; + value[3] = topRight; } bool isDouble() const { return _isDouble; } @@ -244,6 +248,67 @@ class RGBCurvesParams { std::vector bcurve; }; +/** + * Parameters of the Color Toning + */ + +class ColorToningParams { + + public: + bool enabled; + bool autosat; + std::vector opacityCurve; + std::vector colorCurve; + int satProtectionThreshold; + int saturatedOpacity; + int strengthprotection; + int balance; + Threshold hlColSat; + Threshold shadowsColSat; + std::vector clcurve; + std::vector cl2curve; + + /* Can be either: + * Splitlr : + * Splitco : + * Splitbal : + * Lab : + * Lch : + * RGBSliders : + * RGBCurves : + */ + Glib::ustring method; + + /* Can be either: + * Std : + * All : + * Separ : + * Two : + */ + Glib::ustring twocolor; + double redlow; + double greenlow; + double bluelow; + double redmed; + double greenmed; + double bluemed; + double redhigh; + double greenhigh; + double bluehigh; + double satlow; + double sathigh; + bool lumamode; + + ColorToningParams (); + void setDefault(); // SHOULD BE GENERALIZED TO ALL CLASSES! + /// @brief Transform the mixer values to their curve equivalences + void mixerToCurve(std::vector &colorCurve, std::vector &opacityCurve) const; + /// @brief Specifically transform the sliders values to their curve equivalences + void slidersToCurve(std::vector &colorCurve, std::vector &opacityCurve) const; + /// @brief Fill the ColorGradientCurve and OpacityCurve LUTf from the control points curve or sliders value + void getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurve &opacityCurveLUT, const double xyz_rgb[3][3], const double rgb_xyz[3][3]) const; +}; + /** * Parameters of the sharpening */ @@ -357,10 +422,10 @@ class WBParams { static void cleanup(); }; - /** - * Parameters of colorappearance - */ - class ColorAppearanceParams { +/** + * Parameters of colorappearance + */ +class ColorAppearanceParams { public: enum eTCModeId { @@ -832,6 +897,7 @@ class ProcParams { ToneCurveParams toneCurve; ///< Tone curve parameters LCurveParams labCurve; ///< CIELAB luminance curve parameters RGBCurvesParams rgbCurves; ///< RGB curves parameters + ColorToningParams colorToning; ///< Color Toning parameters SharpeningParams sharpening; ///< Sharpening parameters SharpenEdgeParams sharpenEdge; ///< Sharpen edge parameters SharpenMicroParams sharpenMicro; ///< Sharpen microcontrast parameters diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 05b7bb6b1..19f05c9e9 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -275,8 +275,37 @@ DIRPYREQUALIZER, // EvDirPyrEqualizerSkin DIRPYREQUALIZER, // EvDirPyrEqlgamutlab DIRPYREQUALIZER, // EvDirPyrEqualizerHueskin ALLNORAW, // EvDPDNmedian -ALLNORAW //EvDPDNmedmet +ALLNORAW, //EvDPDNmedmet //DIRPYREQUALIZER // EvDirPyrEqualizeralg +RGBCURVE, // EvColorToningEnabled +RGBCURVE, // EvColorToningColor +RGBCURVE, // EvColorToningOpacity +RGBCURVE, // EvColorToningCLCurve +RGBCURVE, // EvColorToningMethod +//RGBCURVE, // EvColorToningTwocolor +RGBCURVE, // EvColorToningLLCurve +RGBCURVE, // EvColorToningredlow +RGBCURVE, // EvColorToninggreenlow +RGBCURVE, // EvColorToningbluelow +RGBCURVE, // EvColorToningredmed +RGBCURVE, // EvColorToninggreenmed +RGBCURVE, // EvColorToningbluemed +RGBCURVE, // EvColorToningredhigh +RGBCURVE, // EvColorToninggreenhigh +RGBCURVE, // EvColorToningbluehigh +RGBCURVE, // EvColorToningbalance +RGBCURVE, // EvColorToningNeutral +RGBCURVE, // EvColorToningsatlow +RGBCURVE, // EvColorToningsathigh +RGBCURVE, // EvColorToningTwocolor +RGBCURVE, // EvColorToningNeutralcur +RGBCURVE, // EvColorToningLumamode +RGBCURVE, // EvColorToningShadows +RGBCURVE, // EvColorToningHighights +RGBCURVE, // EvColorToningSatProtection +RGBCURVE, // EvColorToningSatThreshold +RGBCURVE, //EvColorToningStrProtection +RGBCURVE //EvColorToningautosat //LUMINANCECURVE // EvCATsharpcie diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 1a2a78a03..49b335dd4 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -258,6 +258,12 @@ namespace rtengine { virtual void autoCamChanged (double ccam) {} virtual void adapCamChanged (double cadap) {} }; + + class AutoColorTonListener { + public : + virtual ~AutoColorTonListener() {} + virtual void autoColorTonChanged (int bwct, int satthres, int satprot) {} + }; class AutoBWListener { public : @@ -354,7 +360,8 @@ namespace rtengine { virtual void setPreviewImageListener (PreviewImageListener* l) =0; virtual void setAutoCamListener (AutoCamListener* l) =0; virtual void setAutoBWListener (AutoBWListener* l) =0; - + virtual void setAutoColorTonListener (AutoColorTonListener* l) =0; + virtual ~StagedImageProcessor () {} /** Returns a staged, cached image processing manager supporting partial updates diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 3f16e40b4..a355b0c39 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -764,6 +764,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei LUTf satcurve (65536); LUTf lhskcurve (65536); LUTf clcurve (65536); + LUTf clToningcurve (65536); + LUTf cl2Toningcurve (65536); LUTf rCurve (65536); LUTf gCurve (65536); @@ -772,6 +774,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei LUTu dummy; ToneCurve customToneCurve1, customToneCurve2; + ColorGradientCurve ctColorCurve; + OpacityCurve ctOpacityCurve; ColorAppearance customColCurve1; ColorAppearance customColCurve2; ColorAppearance customColCurve3; @@ -789,16 +793,41 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, 16); CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 16); CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 16); - + + TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + double wp[3][3] = { + {wprof[0][0],wprof[0][1],wprof[0][2]}, + {wprof[1][0],wprof[1][1],wprof[1][2]}, + {wprof[2][0],wprof[2][1],wprof[2][2]}}; + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); + double wip[3][3] = { + {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, + {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, + {wiprof[2][0],wiprof[2][1],wiprof[2][2]} + }; + params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip); + LabImage* labView = new LabImage (fw,fh); CieImage* cieView = new CieImage (fw,fh); + bool clctoningutili=false; + bool llctoningutili=false; + CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve,scale==1 ? 1 : 16); + CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, scale==1 ? 1 : 16); CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, hist16, dummy, customToneCurvebw1, customToneCurvebw2, 16); double rrm, ggm, bbm; float autor, autog, autob; autor = autog = autob = -9000.f; // This will ask to compute the "auto" values for the B&W tool - ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2,rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh); + ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2,rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh); + + // freeing up some memory + customToneCurve1.Reset(); + customToneCurve2.Reset(); + ctColorCurve.Reset(); + ctOpacityCurve.Reset(); + customToneCurvebw1.Reset(); + customToneCurvebw2.Reset(); if (shmap) delete shmap; diff --git a/rtengine/settings.h b/rtengine/settings.h index 39ae44700..052712f5e 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -57,7 +57,8 @@ namespace rtengine { bool ciebadpixgauss; int CRI_color; // N� for display Lab value ; 0 disabled int denoiselabgamma; // 0=gamma 26 11 1=gamma 40 5 2 =gamma 55 10 - + // double colortoningab; // + // double decaction; // bool bw_complementary; double artifact_cbdl; double level0_cbdl; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 8cb8a7a7f..84ef35e62 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -189,6 +189,8 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p LUTf lhskcurve (65536,0); LUTf lumacurve(65536,0); LUTf clcurve (65536,0); + LUTf clToningcurve (65536,0); + LUTf cl2Toningcurve (65536,0); LUTf rCurve (65536,0); LUTf gCurve (65536,0); @@ -196,6 +198,8 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p LUTu dummy; ToneCurve customToneCurve1, customToneCurve2; + ColorGradientCurve ctColorCurve; + OpacityCurve ctOpacityCurve; ColorAppearance customColCurve1, customColCurve2,customColCurve3 ; ToneCurve customToneCurvebw1; ToneCurve customToneCurvebw2; @@ -211,6 +215,25 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 1); CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 1); + TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); + + double wp[3][3] = { + {wprof[0][0],wprof[0][1],wprof[0][2]}, + {wprof[1][0],wprof[1][1],wprof[1][2]}, + {wprof[2][0],wprof[2][1],wprof[2][2]}}; + double wip[3][3] = { + {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, + {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, + {wiprof[2][0],wiprof[2][1],wiprof[2][2]} + }; + params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip); + + bool clctoningutili=false; + CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve, 1); + bool llctoningutili=false; + CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, 1); + LabImage* labView = new LabImage (fw,fh); @@ -218,10 +241,18 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p double rrm, ggm, bbm; float autor, autog, autob; autor = -9000.f; // This will ask to compute the "auto" values for the B&W tool (have to be inferior to -5000) - ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, customToneCurve1, customToneCurve2,customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh); + ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve,customToneCurve1, customToneCurve2,customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh); if (settings->verbose) printf("Output image / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", autor, autog, autob); + // freeing up some memory + customToneCurve1.Reset(); + customToneCurve2.Reset(); + ctColorCurve.Reset(); + ctOpacityCurve.Reset(); + customToneCurvebw1.Reset(); + customToneCurvebw2.Reset(); + // Freeing baseImg because not used anymore delete baseImg; baseImg = NULL; @@ -569,15 +600,17 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p else { // if Default gamma mode: we use the profile selected in the "Output profile" combobox; // gamma come from the selected profile, otherwise it comes from "Free gamma" tool - - readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, params.blackwhite.enabled); + + // readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, params.blackwhite.enabled); + bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled ; + readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, bwonly); if (settings->verbose) printf("Output profile: \"%s\"\n", params.icm.output.c_str()); } delete labView; labView = NULL; - if(params.blackwhite.enabled) {//force BW r=g=b + if(params.blackwhite.enabled && !params.colorToning.enabled ) {//force BW r=g=b for (int ccw=0;ccwr(cch,ccw)=readyImg->g(cch,ccw); diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index c88754039..528b5a970 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -9,7 +9,7 @@ set (BASESOURCEFILES resize.cc icmpanel.cc crop.cc shadowshighlights.cc impulsedenoise.cc dirpyrdenoise.cc epd.cc exifpanel.cc toolpanel.cc lensprofile.cc - sharpening.cc vibrance.cc rgbcurves.cc + sharpening.cc vibrance.cc rgbcurves.cc colortoning.cc whitebalance.cc vignetting.cc gradient.cc pcvignette.cc rotate.cc distortion.cc crophandler.cc dirbrowser.cc curveeditor.cc curveeditorgroup.cc diagonalcurveeditorsubgroup.cc flatcurveeditorsubgroup.cc diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 220ef4482..ebd6fcfbb 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -77,8 +77,13 @@ #define ADDSET_BLACKWHITE_GAMMA 69 #define ADDSET_DIRPYREQ_THRESHOLD 70 #define ADDSET_DIRPYREQ_SKINPROTECT 71 +#define ADDSET_COLORTONING_SPLIT 72 +#define ADDSET_COLORTONING_SATTHRESHOLD 73 +#define ADDSET_COLORTONING_SATOPACITY 74 +#define ADDSET_COLORTONING_BALANCE 75 +#define ADDSET_COLORTONING_STRPROTECT 76 // When adding items, make sure to update ADDSET_PARAM_NUM -#define ADDSET_PARAM_NUM 72 // THIS IS USED AS A DELIMITER!! +#define ADDSET_PARAM_NUM 77 // THIS IS USED AS A DELIMITER!! #endif diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc index f213b6771..f73dd8a1e 100644 --- a/rtgui/adjuster.cc +++ b/rtgui/adjuster.cc @@ -83,10 +83,10 @@ Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep if (vlabel.empty()) { // No label, everything goes in hbox if (imgIcon1) hbox->pack_start (*imgIcon1, Gtk::PACK_SHRINK, 0); + hbox->pack_start (*slider, Gtk::PACK_EXPAND_WIDGET, 0); + if (imgIcon2) hbox->pack_start (*imgIcon2, Gtk::PACK_SHRINK, 0); hbox->pack_end (*reset, Gtk::PACK_SHRINK, 0); hbox->pack_end (*spin, Gtk::PACK_SHRINK, 0); - if (imgIcon2) hbox->pack_start (*imgIcon2, Gtk::PACK_SHRINK, 0); - hbox->pack_start (*slider, true, true); } else { // A label is provided, spreading the widgets in 2 rows diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index a99fa4bd5..dfd227753 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -143,6 +143,7 @@ void BatchToolPanelCoordinator::initSession () { chmixer->setAdjusterBehavior (false); blackwhite->setAdjusterBehavior (false,false); + colortoning->setAdjusterBehavior (false, false, false, false, false); shadowshighlights->setAdjusterBehavior (false, false, false); dirpyrequalizer->setAdjusterBehavior (false, false, false); @@ -172,6 +173,7 @@ void BatchToolPanelCoordinator::initSession () { sharpenEdge->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT],options.baBehav[ADDSET_SHARPENEDGE_PASS]); sharpenMicro->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT],options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]); icm->setAdjusterBehavior (options.baBehav[ADDSET_FREE_OUPUT_GAMMA],options.baBehav[ADDSET_FREE_OUTPUT_SLOPE]); + colortoning->setAdjusterBehavior (options.baBehav[ADDSET_COLORTONING_SPLIT], options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD], options.baBehav[ADDSET_COLORTONING_SATOPACITY], options.baBehav[ADDSET_COLORTONING_STRPROTECT], options.baBehav[ADDSET_COLORTONING_BALANCE]); chmixer->setAdjusterBehavior (options.baBehav[ADDSET_CHMIXER] ); blackwhite->setAdjusterBehavior (options.baBehav[ADDSET_BLACKWHITE_HUES],options.baBehav[ADDSET_BLACKWHITE_GAMMA]); @@ -240,6 +242,14 @@ void BatchToolPanelCoordinator::initSession () { //if (options.baBehav[ADDSET_CS_BLUEYELLOW]) pparams.colorShift.a = 0; //if (options.baBehav[ADDSET_CS_GREENMAGENTA]) pparams.colorShift.b = 0; + if (options.baBehav[ADDSET_COLORTONING_SPLIT]) pparams.colorToning.redlow = pparams.colorToning.greenlow = pparams.colorToning.bluelow = + pparams.colorToning.redmed = pparams.colorToning.greenmed = pparams.colorToning.bluemed = + pparams.colorToning.redhigh = pparams.colorToning.greenhigh = pparams.colorToning.bluehigh = + pparams.colorToning.satlow = pparams.colorToning.sathigh = 0; + if (options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD]) pparams.colorToning.satProtectionThreshold = 0; + if (options.baBehav[ADDSET_COLORTONING_SATOPACITY]) pparams.colorToning.saturatedOpacity = 0; + if (options.baBehav[ADDSET_COLORTONING_BALANCE]) pparams.colorToning.balance = 0; + if (options.baBehav[ADDSET_COLORTONING_STRPROTECT]) pparams.colorToning.strengthprotection = 0; if (options.baBehav[ADDSET_ROTATE_DEGREE]) pparams.rotate.degree = 0; if (options.baBehav[ADDSET_DIST_AMOUNT]) pparams.distortion.amount = 0; @@ -330,7 +340,7 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G crop->write (&pparams, &pparamsEdited); } else if (event==rtengine::EvCTRotate) { - crop->rotateCrop (pparams.coarse.rotate, pparams.coarse.hflip, pparams.coarse.vflip); + crop->rotateCrop (pparams.coarse.rotate, pparams.coarse.hflip, pparams.coarse.vflip); crop->write (&pparams, &pparamsEdited); resize->update (pparams.crop.enabled, pparams.crop.w, pparams.crop.h, w, h); resize->write (&pparams, &pparamsEdited); @@ -384,11 +394,11 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G int oldDeg = initialPP[i].coarse.rotate; rtengine::procparams::CropParams& crop = initialPP[i].crop; - int rotation = (360 + newDeg - oldDeg) % 360; - ProcParams pptemp = selected[i]->getProcParams(); // Get actual procparams - if((pptemp.coarse.hflip != pptemp.coarse.vflip) && ((rotation%180)==90)) - rotation = (rotation + 180)%360; - + int rotation = (360 + newDeg - oldDeg) % 360; + ProcParams pptemp = selected[i]->getProcParams(); // Get actual procparams + if((pptemp.coarse.hflip != pptemp.coarse.vflip) && ((rotation%180)==90)) + rotation = (rotation + 180)%360; + switch (rotation) { case 90: diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index 6d8ba108f..500e40836 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -824,7 +824,7 @@ void BlackWhite::enabled_toggled () { if (listener) { if (enabled->get_inconsistent()) listener->panelChanged (EvBWChmixEnabled, M("GENERAL_UNCHANGED")); - else if (enabled->get_active ()) { + else if (enabled->get_active ()) { listener->panelChanged (EvBWChmixEnabled, M("GENERAL_ENABLED")); } else { diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc new file mode 100644 index 000000000..49766841d --- /dev/null +++ b/rtgui/colortoning.cc @@ -0,0 +1,1129 @@ +/* + * This file is part of RawTherapee. + */ +#include "colortoning.h" +#include +#include "mycurve.h" + +using namespace rtengine; +using namespace rtengine::procparams; + +ColorToning::ColorToning () : FoldableToolPanel(this) +{ + nextbw=0; + CurveListener::setMulti(true); + enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED"))); + enabled->set_active (false); + enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &ColorToning::enabledChanged) ); + + pack_start(*enabled); + pack_start(*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4); + + //---------------method + + method = Gtk::manage (new MyComboBoxText ()); + method->append_text (M("TP_COLORTONING_LAB")); + method->append_text (M("TP_COLORTONING_RGBSLIDERS")); + method->append_text (M("TP_COLORTONING_RGBCURVES")); +// method->append_text (M("TP_COLORTONING_SPLITBW")); + method->append_text (M("TP_COLORTONING_SPLITCOCO")); + method->append_text (M("TP_COLORTONING_SPLITLR")); + method->set_active (0); + method->set_tooltip_text (M("TP_COLORTONING_METHOD_TOOLTIP")); + + ctbox = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_METHOD"))); + ctbox->pack_start (*lab, Gtk::PACK_SHRINK, 4); + ctbox->pack_start (*method); + pack_start (*ctbox); + + methodconn = method->signal_changed().connect ( sigc::mem_fun(*this, &ColorToning::methodChanged) ); + + //----------- Color curve ------------------------------ + + colorSep = Gtk::manage (new Gtk::HSeparator()); + pack_start (*colorSep); + + colLabel = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_LABCOL"))); + colLabel->set_tooltip_text (M("TP_COLORTONING_LABCOL_TOOLTIP")); + + interLabel = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_LABINT"))); + interLabel->set_tooltip_text (M("TP_COLORTONING_LABINT_TOOLTIP")); + pack_start (*colLabel, Gtk::PACK_SHRINK, 4); + pack_start (*interLabel, Gtk::PACK_SHRINK, 4); + + colorCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_COLOR")); + colorCurveEditorG->setCurveListener (this); + + colorShape = static_cast(colorCurveEditorG->addCurve(CT_Flat, "", NULL, false)); + colorShape->setCurveColorProvider(this, 1); + std::vector milestones; + // whole hue range + for (int i=0; i<7; i++) { + float R, G, B; + float x = float(i)*(1.0f/6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + } + colorShape->setLeftBarBgGradient(milestones); + + // luminance gradient + milestones.clear(); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + colorShape->setBottomBarBgGradient(milestones); + + // This will add the reset button at the end of the curveType buttons + colorCurveEditorG->curveListComplete(); + colorCurveEditorG->show(); + + pack_start( *colorCurveEditorG, Gtk::PACK_SHRINK, 2); + + //----------------------red green blue yellow colours + + twocolor = Gtk::manage (new MyComboBoxText ()); + twocolor->append_text (M("TP_COLORTONING_TWOSTD")); + twocolor->append_text (M("TP_COLORTONING_TWOALL")); + twocolor->append_text (M("TP_COLORTONING_TWOBY")); + twocolor->append_text (M("TP_COLORTONING_TWO2")); + twocolor->set_tooltip_text (M("TP_COLORTONING_TWOCOLOR_TOOLTIP")); + twocolor->set_active (0); + + twocconn = twocolor->signal_changed().connect( sigc::mem_fun(*this, &ColorToning::twocolorChanged) ); + + pack_start (*twocolor, Gtk::PACK_SHRINK, 4); + + //----------- Opacity curve ------------------------------ + + opacityCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_OPACITY")); + opacityCurveEditorG->setCurveListener (this); + + opacityShape = static_cast(opacityCurveEditorG->addCurve(CT_Flat, "", NULL, false)); + opacityShape->setIdentityValue(0.); + opacityShape->setBottomBarBgGradient(milestones); + + // This will add the reset button at the end of the curveType buttons + opacityCurveEditorG->curveListComplete(); + opacityCurveEditorG->show(); + + pack_start( *opacityCurveEditorG, Gtk::PACK_SHRINK, 2); + + //---------Chroma curve 1 -------------------- + labchroma1="TP_COLORTONING_CHROMAC"; + labchroma2="TP_COLORTONING_CHROMA2"; +// itot = Gtk::manage (new RTImage ("Chanmixer-RGBY.png")); + iby = Gtk::manage (new RTImage ("Chanmixer-BY.png")); + irg = Gtk::manage (new RTImage ("Chanmixer-RG.png")); + + clCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M(labchroma1)); + clCurveEditorG->setCurveListener (this); + clshape = static_cast(clCurveEditorG->addCurve(CT_Diagonal, M("TP_COLORTONING_AB"),irg)); + clshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_CL_TOOLTIP")); + //clshape->setEditID(EUID_Lab_CLCurve, BT_SINGLEPLANE_FLOAT); + + clshape->setLeftBarColorProvider(this, 1); + clshape->setRangeDefaultMilestones(0.25, 0.5, 0.75); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + + clshape->setBottomBarBgGradient(milestones); + clCurveEditorG->curveListComplete(); + + pack_start( *clCurveEditorG, Gtk::PACK_SHRINK, 2); + + //---------Chroma curve 2 -------------------- + + //cl2CurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_CHROMA2")); + cl2CurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M(labchroma1)); + cl2CurveEditorG->setCurveListener (this); + + cl2shape = static_cast(cl2CurveEditorG->addCurve(CT_Diagonal, M("TP_COLORTONING_BY"),iby)); + cl2shape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_LL_TOOLTIP")); + //clshape->setEditID(EUID_Lab_CLCurve, BT_SINGLEPLANE_FLOAT); + + cl2shape->setLeftBarColorProvider(this, 1); + cl2shape->setRangeDefaultMilestones(0.25, 0.5, 0.75); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + + cl2shape->setBottomBarBgGradient(milestones); + cl2CurveEditorG->curveListComplete(); + + pack_start( *cl2CurveEditorG, Gtk::PACK_SHRINK, 2); + + //--------------------- Reset curves ----------------------------- + neutrcurHBox = Gtk::manage (new Gtk::HBox ()); + neutrcurHBox->set_border_width (2); + + neutralcur = Gtk::manage (new Gtk::Button (M("TP_COLORTONING_NEUTRALCUR"))); + RTImage *resetImgc = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); + neutralcur->set_image(*resetImgc); + neutralcur->set_tooltip_text (M("TP_COLORTONING_NEUTRALCUR_TIP")); + neutralcurconn = neutralcur->signal_pressed().connect( sigc::mem_fun(*this, &ColorToning::neutralcur_pressed) ); + neutralcur->show(); + neutrcurHBox->pack_start (*neutralcur); + + pack_start (*neutrcurHBox); + + //----------- Sliders + balance ------------------------------ + + hlColSat = Gtk::manage (new ThresholdAdjuster (M("TP_COLORTONING_HIGHLIGHT"), 0., 100., 60., M("TP_COLORTONING_STRENGTH"), 1., 0., 360., 80., M("TP_COLORTONING_HUE"), 1., NULL, false)); + hlColSat->setAdjusterListener (this); + hlColSat->setBgColorProvider(this, 2); + hlColSat->setUpdatePolicy(RTUP_DYNAMIC); + + pack_start( *hlColSat, Gtk::PACK_SHRINK, 0); + + shadowsColSat = Gtk::manage (new ThresholdAdjuster (M("TP_COLORTONING_SHADOWS"), 0., 100., 80., M("TP_COLORTONING_STRENGTH"), 1., 0., 360., 208., M("TP_COLORTONING_HUE"), 1., NULL, false)); + shadowsColSat->setAdjusterListener (this); + shadowsColSat->setBgColorProvider(this, 3); + shadowsColSat->setUpdatePolicy(RTUP_DYNAMIC); + + pack_start( *shadowsColSat, Gtk::PACK_SHRINK, 0); + + //satlow = Gtk::manage (new Adjuster (M("TP_COLORTONING_SATL"), 0., 100., 1., 0.)); + //pack_start (*satlow, Gtk::PACK_EXPAND_WIDGET); + + //sathigh = Gtk::manage (new Adjuster (M("TP_COLORTONING_SATH"), 0., 100., 1., 0.)); + //pack_start (*sathigh, Gtk::PACK_EXPAND_WIDGET); + + balance = Gtk::manage( new Adjuster(M("TP_COLORTONING_BALANCE"), -100., 100., 1., 0.) ); + balance->setAdjusterListener(this); + + pack_start (*balance, Gtk::PACK_SHRINK, 2); + + //----------- Saturation and strength protection ------------------------------ + + satLimiterSep = Gtk::manage (new Gtk::HSeparator()); + pack_start (*satLimiterSep, Gtk::PACK_SHRINK); + + autosat = Gtk::manage (new Gtk::CheckButton (M("TP_COLORTONING_AUTOSAT"))); + autosat->set_active (true); + autosatConn = autosat->signal_toggled().connect( sigc::mem_fun(*this, &ColorToning::autosatChanged) ); + + pack_start(*autosat); + pack_start (*autosat, Gtk::PACK_SHRINK, 2); + + satProtectionThreshold = Gtk::manage( new Adjuster(M("TP_COLORTONING_SATURATIONTHRESHOLD"), 0., 100., 1., 70.) ); + satProtectionThreshold->setAdjusterListener(this); + satProtectionThreshold->set_sensitive(false); + + pack_start( *satProtectionThreshold, Gtk::PACK_SHRINK, 2); + + saturatedOpacity = Gtk::manage( new Adjuster(M("TP_COLORTONING_SATURATEDOPACITY"), 0., 100., 1., 50.) );; + saturatedOpacity->setAdjusterListener(this); + saturatedOpacity->set_sensitive(false); + + pack_start( *saturatedOpacity, Gtk::PACK_SHRINK, 2); //I have moved after Chanmixer + + strengthprotection = Gtk::manage( new Adjuster(M("TP_COLORTONING_STRPROTECT"), 0., 100., 1., 50.) );; + strengthprotection->setAdjusterListener(this); + + //pack_start( *strengthprotection, Gtk::PACK_SHRINK, 2); //I have moved after Chanmixer + + + // --------------------Sliders BW Colortoning ------------------- + + chanMixerBox = Gtk::manage (new Gtk::VBox()); + Gtk::VBox *chanMixerHLBox = Gtk::manage (new Gtk::VBox()); + Gtk::VBox *chanMixerMidBox = Gtk::manage (new Gtk::VBox()); + Gtk::VBox *chanMixerShadowsBox = Gtk::manage (new Gtk::VBox()); + + Gtk::Image* iblueR = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelL = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagL = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenR = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* icyanL = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); + Gtk::Image* iredR = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + + Gtk::Image* iblueRm = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelLm = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagLm = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenRm = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* icyanLm = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); + Gtk::Image* iredRm = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + + Gtk::Image* iblueRh = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelLh = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagLh = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenRh = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* icyanLh = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); + Gtk::Image* iredRh = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + + redhigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanLh, iredRh )); + greenhigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagLh , igreenRh)); + bluehigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelLh , iblueRh )); + + redmed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanLm, iredRm )); + greenmed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagLm , igreenRm)); + bluemed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelLm , iblueRm )); + + redlow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanL, iredR )); + greenlow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagL , igreenR)); + bluelow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelL , iblueR )); + + chanMixerHLBox->pack_start (*redhigh); + chanMixerHLBox->pack_start (*greenhigh); + chanMixerHLBox->pack_start (*bluehigh); + chanMixerMidBox->pack_start (*redmed); + chanMixerMidBox->pack_start (*greenmed); + chanMixerMidBox->pack_start (*bluemed); + chanMixerShadowsBox->pack_start (*redlow); + chanMixerShadowsBox->pack_start (*greenlow); + chanMixerShadowsBox->pack_start (*bluelow); + + Gtk::Frame *chanMixerHLFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_HIGHLIGHT"))); + Gtk::Frame *chanMixerMidFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_MIDTONES"))); + Gtk::Frame *chanMixerShadowsFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_SHADOWS"))); + + chanMixerHLFrame->add(*chanMixerHLBox); + chanMixerMidFrame->add(*chanMixerMidBox); + chanMixerShadowsFrame->add(*chanMixerShadowsBox); + + chanMixerBox->pack_start(*chanMixerHLFrame, Gtk::PACK_SHRINK); + chanMixerBox->pack_start(*chanMixerMidFrame, Gtk::PACK_SHRINK); + chanMixerBox->pack_start(*chanMixerShadowsFrame, Gtk::PACK_SHRINK); + + pack_start(*chanMixerBox, Gtk::PACK_SHRINK); + pack_start( *strengthprotection, Gtk::PACK_SHRINK, 2); //I have moved after Chanmixer + + //--------------------- Reset sliders --------------------------- + neutrHBox = Gtk::manage (new Gtk::HBox ()); + neutrHBox->set_border_width (2); + + neutral = Gtk::manage (new Gtk::Button (M("TP_COLORTONING_NEUTRAL"))); + RTImage *resetImg = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); + neutral->set_image(*resetImg); + neutral->set_tooltip_text (M("TP_COLORTONING_NEUTRAL_TIP")); + neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &ColorToning::neutral_pressed) ); + neutral->show(); + neutrHBox->pack_start (*neutral); + + pack_start (*neutrHBox); + + //--------------------- Keep luminance checkbox ------------------- + lumamode = Gtk::manage (new Gtk::CheckButton (M("TP_COLORTONING_LUMAMODE"))); + lumamode->set_tooltip_markup (M("TP_COLORTONING_LUMAMODE_TOOLTIP")); + lumamode->set_active (false); + lumamode->show (); + lumamodeConn = lumamode->signal_toggled().connect( sigc::mem_fun(*this, &ColorToning::lumamodeChanged) ); + + pack_start (*lumamode); + + //splitSep = Gtk::manage (new Gtk::HSeparator()); + + //pack_start (*splitSep); + + redlow->setAdjusterListener (this); + greenlow->setAdjusterListener (this); + bluelow->setAdjusterListener (this); + //satlow->setAdjusterListener (this); + //sathigh->setAdjusterListener (this); + balance->setAdjusterListener (this); + redmed->setAdjusterListener (this); + greenmed->setAdjusterListener (this); + bluemed->setAdjusterListener (this); + redhigh->setAdjusterListener (this); + greenhigh->setAdjusterListener (this); + bluehigh->setAdjusterListener (this); + + show_all(); + + disableListener(); + methodChanged(); + enableListener(); +} + +ColorToning::~ColorToning() { + delete colorCurveEditorG; + delete opacityCurveEditorG; + delete clCurveEditorG; + delete cl2CurveEditorG; +} + +void ColorToning::neutralcur_pressed () { + disableListener(); + + std::vector p; +// double fla[9]={1,0.25,0.8,0.25,0.25,0.75,0.6,0.25,0.25}; + double fla[9]={1,0.05,0.62,0.25,0.25,0.585,0.11,0.25,0.25}; + for(int i=0;i<9;i++) p.push_back(fla[i]); + colorShape->setCurve(p); + + + std::vector p2; + + + //double fla2[9]={1,0.7,0.8,0.35,0.35,1,0.3,0,0}; + double fla2[17]={1,0.,0.3,0.35,0.,0.25,0.8,0.35,0.35,0.7,0.8,0.35,0.35,1.0,0.3,0.,0.}; + for(int i=0;i<17;i++) p2.push_back(fla2[i]); + opacityShape->setCurve(p2); + + std::vector p3; + double fla3[9]={3,0,0,0.35,0.65,1,1}; + for(int i=0;i<7;i++) p3.push_back(fla3[i]); + clshape->setCurve(p3); + + std::vector p4; + double fla4[9]={3,0,0,0.35,0.65,1,1}; + for(int i=0;i<7;i++) p4.push_back(fla4[i]); + cl2shape->setCurve(p4); + + enableListener(); + + listener->panelChanged (EvColorToningNeutralcur, M("ADJUSTER_RESET_TO_DEFAULT")); +} + +// Will only reset the chanel mixer +void ColorToning::neutral_pressed () { + disableListener(); + redlow->resetValue(false); + greenlow->resetValue(false); + bluelow->resetValue(false); + redmed->resetValue(false); + greenmed->resetValue(false); + bluemed->resetValue(false); + redhigh->resetValue(false); + greenhigh->resetValue(false); + bluehigh->resetValue(false); + //satlow->resetValue(false); + //sathigh->resetValue(false); + //balance->resetValue(false); + + enableListener(); + + listener->panelChanged (EvColorToningNeutral, M("ADJUSTER_RESET_TO_DEFAULT")); +} + +void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) +{ + disableListener (); + methodconn.block(true); + twocconn.block(true); + colorShape->setCurve (pp->colorToning.colorCurve); + opacityShape->setCurve (pp->colorToning.opacityCurve); + clshape->setCurve (pp->colorToning.clcurve); + cl2shape->setCurve (pp->colorToning.cl2curve); + + if (pedited) { + redlow->setEditedState (pedited->colorToning.redlow ? Edited : UnEdited); + greenlow->setEditedState (pedited->colorToning.greenlow ? Edited : UnEdited); + bluelow->setEditedState (pedited->colorToning.bluelow ? Edited : UnEdited); + //satlow->setEditedState (pedited->colorToning.satlow ? Edited : UnEdited); + //sathigh->setEditedState (pedited->colorToning.sathigh ? Edited : UnEdited); + balance->setEditedState (pedited->colorToning.balance ? Edited : UnEdited); + redmed->setEditedState (pedited->colorToning.redmed ? Edited : UnEdited); + greenmed->setEditedState (pedited->colorToning.greenmed ? Edited : UnEdited); + bluemed->setEditedState (pedited->colorToning.bluemed ? Edited : UnEdited); + redhigh->setEditedState (pedited->colorToning.redhigh ? Edited : UnEdited); + greenhigh->setEditedState (pedited->colorToning.greenhigh ? Edited : UnEdited); + bluehigh->setEditedState (pedited->colorToning.bluehigh ? Edited : UnEdited); + + hlColSat->setEditedState (pedited->colorToning.hlColSat ? Edited : UnEdited); + shadowsColSat->setEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited); + + enabled->set_inconsistent (!pedited->colorToning.enabled); + colorShape->setUnChanged (!pedited->colorToning.colorCurve); + opacityShape->setUnChanged (!pedited->colorToning.opacityCurve); + autosat->set_inconsistent (!pedited->colorToning.autosat); + clshape->setUnChanged (!pedited->colorToning.clcurve); + cl2shape->setUnChanged (!pedited->colorToning.cl2curve); + lumamode->set_inconsistent (!pedited->colorToning.lumamode); + } + redlow->setValue (pp->colorToning.redlow); + greenlow->setValue (pp->colorToning.greenlow); + bluelow->setValue (pp->colorToning.bluelow); + //satlow->setValue (pp->colorToning.satlow); + //sathigh->setValue (pp->colorToning.sathigh); + balance->setValue (pp->colorToning.balance); + redmed->setValue (pp->colorToning.redmed); + greenmed->setValue (pp->colorToning.greenmed); + bluemed->setValue (pp->colorToning.bluemed); + redhigh->setValue (pp->colorToning.redhigh); + greenhigh->setValue (pp->colorToning.greenhigh); + bluehigh->setValue (pp->colorToning.bluehigh); + + enaConn.block (true); + enabled->set_active (pp->colorToning.enabled); + enaConn.block (false); + lastEnabled = pp->colorToning.enabled; + + autosatConn.block (true); + autosat->set_active (pp->colorToning.autosat); + autosatConn.block (false); + lastautosat = pp->colorToning.autosat; + + satProtectionThreshold->setValue (pp->colorToning.satProtectionThreshold); + saturatedOpacity->setValue (pp->colorToning.saturatedOpacity); + hlColSat->setValue (pp->colorToning.hlColSat); + shadowsColSat->setValue (pp->colorToning.shadowsColSat); + strengthprotection->setValue (pp->colorToning.strengthprotection); + lumamodeConn.block (true); + lumamode->set_active (pp->colorToning.lumamode); + lumamodeConn.block (false); + + lastLumamode = pp->colorToning.lumamode; + + if (pedited && !pedited->colorToning.method) + method->set_active (5); + else if (pp->colorToning.method=="Lab") + method->set_active (0); + else if (pp->colorToning.method=="RGBSliders") + method->set_active (1); + else if (pp->colorToning.method=="RGBCurves") + method->set_active (2); + //else if (pp->colorToning.method=="Split") + // method->set_active (1); + else if (pp->colorToning.method=="Splitco") + method->set_active (3); + // else if (pp->colorToning.method=="Splitbal") + // method->set_active (5); + else if (pp->colorToning.method=="Splitlr") + method->set_active (4); + methodChanged(); + methodconn.block(false); + + + if (pedited && !pedited->colorToning.twocolor) + twocolor->set_active (4); + else if (pp->colorToning.twocolor=="Std") + twocolor->set_active (0); + else if (pp->colorToning.twocolor=="All") + twocolor->set_active (1); + else if (pp->colorToning.twocolor=="Separ") + twocolor->set_active (2); + else if (pp->colorToning.twocolor=="Two") + twocolor->set_active (3); + + twocolorChanged(); + + twocconn.block(false); + + enableListener (); +} + +void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) { + pp->colorToning.redlow = redlow->getValue (); + pp->colorToning.greenlow = greenlow->getValue (); + pp->colorToning.bluelow = bluelow->getValue (); + //pp->colorToning.satlow = satlow->getValue (); + //pp->colorToning.sathigh = sathigh->getValue (); + pp->colorToning.balance = balance->getIntValue (); + pp->colorToning.redmed = redmed->getValue (); + pp->colorToning.greenmed = greenmed->getValue (); + pp->colorToning.bluemed = bluemed->getValue (); + pp->colorToning.redhigh = redhigh->getValue (); + pp->colorToning.greenhigh = greenhigh->getValue (); + pp->colorToning.bluehigh = bluehigh->getValue (); + + pp->colorToning.enabled = enabled->get_active(); + pp->colorToning.colorCurve = colorShape->getCurve (); + pp->colorToning.opacityCurve = opacityShape->getCurve (); + pp->colorToning.clcurve = clshape->getCurve (); + pp->colorToning.cl2curve = cl2shape->getCurve (); + pp->colorToning.lumamode = lumamode->get_active(); + + pp->colorToning.hlColSat = hlColSat->getValue (); + pp->colorToning.shadowsColSat = shadowsColSat->getValue (); + pp->colorToning.autosat = autosat->get_active(); + pp->colorToning.satProtectionThreshold = satProtectionThreshold->getIntValue(); + pp->colorToning.saturatedOpacity = saturatedOpacity->getIntValue(); + pp->colorToning.strengthprotection = strengthprotection->getIntValue(); + + if (pedited) { + pedited->colorToning.redlow = redlow->getEditedState (); + pedited->colorToning.greenlow = greenlow->getEditedState (); + pedited->colorToning.bluelow = bluelow->getEditedState (); + //pedited->colorToning.satlow = satlow->getEditedState (); + //pedited->colorToning.sathigh = sathigh->getEditedState (); + pedited->colorToning.balance = balance->getEditedState (); + pedited->colorToning.redmed = redmed->getEditedState (); + pedited->colorToning.greenmed = greenmed->getEditedState (); + pedited->colorToning.bluemed = bluemed->getEditedState (); + pedited->colorToning.redhigh = redhigh->getEditedState (); + pedited->colorToning.greenhigh = greenhigh->getEditedState (); + pedited->colorToning.bluehigh = bluehigh->getEditedState (); + pedited->colorToning.method = method->get_active_text()!=M("GENERAL_UNCHANGED"); + pedited->colorToning.twocolor = twocolor->get_active_text()!=M("GENERAL_UNCHANGED"); + + pedited->colorToning.enabled = !enabled->get_inconsistent(); + pedited->colorToning.autosat = !autosat->get_inconsistent(); + pedited->colorToning.colorCurve = !colorShape->isUnChanged (); + pedited->colorToning.opacityCurve = !opacityShape->isUnChanged (); + pedited->colorToning.clcurve = !clshape->isUnChanged (); + pedited->colorToning.cl2curve = !cl2shape->isUnChanged (); + pedited->colorToning.lumamode = !lumamode->get_inconsistent(); + + pedited->colorToning.hlColSat = hlColSat->getEditedState (); + pedited->colorToning.shadowsColSat = shadowsColSat->getEditedState (); + } +// if (pedited) { +// pedited->colorToning.method = method->get_active_row_number()!=6; +// } + + if (method->get_active_row_number()==0) + pp->colorToning.method = "Lab"; +// else if (method->get_active_row_number()==1) +// pp->colorToning.method = "Split"; + else if (method->get_active_row_number()==1) + pp->colorToning.method = "RGBSliders"; + else if (method->get_active_row_number()==2) + pp->colorToning.method = "RGBCurves"; + else if (method->get_active_row_number()==3) + pp->colorToning.method = "Splitco"; +// else if (method->get_active_row_number()==5) +// pp->colorToning.method = "Splitbal"; + else if (method->get_active_row_number()==4) + pp->colorToning.method = "Splitlr"; + + if (twocolor->get_active_row_number()==0) + pp->colorToning.twocolor = "Std"; + else if (twocolor->get_active_row_number()==1) + pp->colorToning.twocolor = "All"; + else if (twocolor->get_active_row_number()==2) + pp->colorToning.twocolor = "Separ"; + else if (twocolor->get_active_row_number()==3) + pp->colorToning.twocolor = "Two"; +} + +void ColorToning::lumamodeChanged () { + + if (batchMode) { + if (lumamode->get_inconsistent()) { + lumamode->set_inconsistent (false); + lumamodeConn.block (true); + lumamode->set_active (false); + lumamodeConn.block (false); + } + else if (lastLumamode) + lumamode->set_inconsistent (true); + + lastLumamode = lumamode->get_active (); + } + + if (listener) { + if (lumamode->get_active ()) + listener->panelChanged (EvColorToningLumamode, M("GENERAL_ENABLED")); + else + listener->panelChanged (EvColorToningLumamode, M("GENERAL_DISABLED")); + } +} + +void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { + + redlow->setDefault (defParams->colorToning.redlow); + greenlow->setDefault (defParams->colorToning.greenlow); + bluelow->setDefault (defParams->colorToning.bluelow); + //satlow->setDefault (defParams->colorToning.satlow); + //sathigh->setDefault (defParams->colorToning.sathigh); + balance->setDefault (defParams->colorToning.balance); + redmed->setDefault (defParams->colorToning.redmed); + greenmed->setDefault (defParams->colorToning.greenmed); + bluemed->setDefault (defParams->colorToning.bluemed); + redhigh->setDefault (defParams->colorToning.redhigh); + greenhigh->setDefault (defParams->colorToning.greenhigh); + bluehigh->setDefault (defParams->colorToning.bluehigh); + satProtectionThreshold->setDefault (defParams->colorToning.satProtectionThreshold); + saturatedOpacity->setDefault (defParams->colorToning.saturatedOpacity); + hlColSat->setDefault (defParams->colorToning.hlColSat); + shadowsColSat->setDefault (defParams->colorToning.shadowsColSat); + strengthprotection->setDefault (defParams->colorToning.strengthprotection); + + if (pedited) { + redlow->setDefaultEditedState (pedited->colorToning.redlow ? Edited : UnEdited); + greenlow->setDefaultEditedState (pedited->colorToning.greenlow ? Edited : UnEdited); + bluelow->setDefaultEditedState (pedited->colorToning.bluelow ? Edited : UnEdited); + //satlow->setDefaultEditedState (pedited->colorToning.satlow ? Edited : UnEdited); + //sathigh->setDefaultEditedState (pedited->colorToning.sathigh ? Edited : UnEdited); + balance->setDefaultEditedState (pedited->colorToning.balance ? Edited : UnEdited); + redmed->setDefaultEditedState (pedited->colorToning.redmed ? Edited : UnEdited); + greenmed->setDefaultEditedState (pedited->colorToning.greenmed ? Edited : UnEdited); + bluemed->setDefaultEditedState (pedited->colorToning.bluemed ? Edited : UnEdited); + redhigh->setDefaultEditedState (pedited->colorToning.redhigh ? Edited : UnEdited); + greenhigh->setDefaultEditedState (pedited->colorToning.greenhigh ? Edited : UnEdited); + bluehigh->setDefaultEditedState (pedited->colorToning.bluehigh ? Edited : UnEdited); + satProtectionThreshold->setDefaultEditedState (pedited->colorToning.satProtectionThreshold ? Edited : UnEdited); + saturatedOpacity->setDefaultEditedState (pedited->colorToning.saturatedOpacity ? Edited : UnEdited); + hlColSat->setDefaultEditedState (pedited->colorToning.hlColSat ? Edited : UnEdited); + shadowsColSat->setDefaultEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited); + strengthprotection->setDefaultEditedState (pedited->colorToning.strengthprotection ? Edited : UnEdited); + } + else { + redlow->setDefaultEditedState (Irrelevant); + greenlow->setDefaultEditedState (Irrelevant); + bluelow->setDefaultEditedState (Irrelevant); + //satlow->setDefaultEditedState (Irrelevant); + //sathigh->setDefaultEditedState (Irrelevant); + balance->setDefaultEditedState (Irrelevant); + redmed->setDefaultEditedState (Irrelevant); + greenmed->setDefaultEditedState (Irrelevant); + bluemed->setDefaultEditedState (Irrelevant); + redhigh->setDefaultEditedState (Irrelevant); + greenhigh->setDefaultEditedState (Irrelevant); + bluehigh->setDefaultEditedState (Irrelevant); + satProtectionThreshold->setDefaultEditedState (Irrelevant); + saturatedOpacity->setDefaultEditedState (Irrelevant); + hlColSat->setDefaultEditedState (Irrelevant); + shadowsColSat->setDefaultEditedState (Irrelevant); + strengthprotection->setDefaultEditedState (Irrelevant); + } +} + +void ColorToning::setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd) { + redlow->setAddMode(splitAdd); + greenlow->setAddMode(splitAdd); + bluelow->setAddMode(splitAdd); + //satlow->setAddMode(splitAdd); + //sathigh->setAddMode(splitAdd); + balance->setAddMode(splitAdd); + redmed->setAddMode(splitAdd); + greenmed->setAddMode(splitAdd); + bluemed->setAddMode(splitAdd); + redhigh->setAddMode(splitAdd); + greenhigh->setAddMode(splitAdd); + bluehigh->setAddMode(splitAdd); + satProtectionThreshold->setAddMode(satThresholdAdd); + saturatedOpacity->setAddMode(satOpacityAdd); + balance->setAddMode(balanceAdd); + strengthprotection->setAddMode(strprotectAdd); + +} + +void ColorToning::adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop) { + if (listener && enabled->get_active()) + listener->panelChanged (a==hlColSat ? EvColorToningHighights : EvColorToningShadows, + Glib::ustring::compose(Glib::ustring(M("TP_COLORTONING_HUE")+": %1"+"\n"+M("TP_COLORTONING_STRENGTH")+": %2"), int(newTop), int(newBottom))); +} + +int CTChanged_UI (void* data) { + GThreadLock lock; + (static_cast(data))->CTComp_ (); + return 0; +} + + +void ColorToning::autoColorTonChanged(int bwct, int satthres, int satprot){ + nextbw = bwct; + nextsatth=satthres; + nextsatpr=satprot; + g_idle_add (CTChanged_UI, this); +} + +bool ColorToning::CTComp_ () { + + disableListener (); + saturatedOpacity->setValue (nextsatpr); + satProtectionThreshold->setValue (nextsatth); + if(nextbw==1) { + saturatedOpacity->show(); + satProtectionThreshold->show(); + autosat->show(); + } + else { + saturatedOpacity->hide(); + satProtectionThreshold->hide(); + autosat->hide(); + } + + enableListener (); + + + return false; +} + +void ColorToning::adjusterChanged (Adjuster* a, double newval) { + + if (!listener || !enabled->get_active()) + return; + + if (a==redlow) + listener->panelChanged (EvColorToningredlow, redlow->getTextValue()); + else if (a==greenlow) + listener->panelChanged (EvColorToninggreenlow, greenlow->getTextValue()); + else if (a==bluelow) + listener->panelChanged (EvColorToningbluelow, bluelow->getTextValue()); + else if (a==redmed) + listener->panelChanged (EvColorToningredmed, redmed->getTextValue()); + else if (a==greenmed) + listener->panelChanged (EvColorToninggreenmed, greenmed->getTextValue()); + else if (a==bluemed) + listener->panelChanged (EvColorToningbluemed, bluemed->getTextValue()); + else if (a==redhigh) + listener->panelChanged (EvColorToningredhigh, redhigh->getTextValue()); + else if (a==greenhigh) + listener->panelChanged (EvColorToninggreenhigh, greenhigh->getTextValue()); + else if (a==bluehigh) + listener->panelChanged (EvColorToningbluehigh, bluehigh->getTextValue()); + else if (a==balance) + listener->panelChanged (EvColorToningbalance, balance->getTextValue()); + /*else if (a==satlow) + listener->panelChanged (EvColorToningsatlow, satlow->getTextValue()); + else if (a==sathigh) + listener->panelChanged (EvColorToningsatlow, sathigh->getTextValue());*/ + else if (a==satProtectionThreshold) + listener->panelChanged (EvColorToningSatThreshold, a->getTextValue()); + else if (a==saturatedOpacity) + listener->panelChanged (EvColorToningSatProtection, a->getTextValue()); + else if (a==strengthprotection) + listener->panelChanged (EvColorToningStrProtection, a->getTextValue()); + + + } + +//Two Color changed +void ColorToning::twocolorChanged () { + if (!batchMode) { + if(method->get_active_row_number()==0) { // Lab + if(twocolor->get_active_row_number()==0) { + colorCurveEditorG->show(); // visible + opacityCurveEditorG->show(); // visible + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } + else if(twocolor->get_active_row_number()==1 || twocolor->get_active_row_number()==3) { + colorCurveEditorG->show(); // visible + opacityCurveEditorG->hide(); + clCurveEditorG->show(); // visible + cl2CurveEditorG->hide(); + irg->hide(); + + } + else if(twocolor->get_active_row_number()==2) { + colorCurveEditorG->show(); // visible + opacityCurveEditorG->hide(); + clCurveEditorG->show(); // visible + cl2CurveEditorG->show(); // visible + irg->show(); + + + } + } + else if(method->get_active_row_number()==1) { // RGB Sliders + colorCurveEditorG->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } + else if(method->get_active_row_number()==2) { // RGB Curves + colorCurveEditorG->show(); // visible + opacityCurveEditorG->show(); // visible + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } + else if(method->get_active_row_number()==3) { // Split LR + colorCurveEditorG->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } + else if(method->get_active_row_number()==4) { // Split color + colorCurveEditorG->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } + } + + if (listener) + listener->panelChanged (EvColorToningTwocolor, method->get_active_text ()); +} + + +void ColorToning::methodChanged () { + + if (!batchMode) { + if (method->get_active_row_number()==0) { // Lab + colorSep->show(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->show(); + twocolor->show(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + neutrcurHBox->show(); + hlColSat->hide(); + shadowsColSat->hide(); + balance->hide(); + satLimiterSep->show(); + satProtectionThreshold->show(); + saturatedOpacity->show(); + + strengthprotection->hide(); + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->hide(); + //splitSep->hide(); + //satlow->hide(); + //sathigh->hide(); + + twocolorChanged(); + } + else if (method->get_active_row_number()==1) { // RGB Sliders + colorSep->hide(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->hide(); + twocolor->hide(); + twocolor->set_active (false); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + neutrcurHBox->hide(); + hlColSat->show(); + shadowsColSat->show(); + balance->show(); + satLimiterSep->show(); + satProtectionThreshold->show(); + saturatedOpacity->show(); + strengthprotection->hide(); + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->hide(); + + //splitSep->hide(); + //satlow->hide(); + //sathigh->hide(); + } + else if (method->get_active_row_number()==2) { // RGB Curves + colorSep->hide(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->show(); + twocolor->hide(); + twocolor->set_active (false); + opacityCurveEditorG->show(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + neutrcurHBox->show(); + hlColSat->hide(); + shadowsColSat->hide(); + balance->hide(); + satLimiterSep->show(); + satProtectionThreshold->show(); + saturatedOpacity->show(); + strengthprotection->hide(); + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->hide(); + //splitSep->hide(); + //satlow->hide(); + //sathigh->hide(); + } + else if (method->get_active_row_number()==3) { // Split LR + colorSep->hide(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->hide(); + twocolor->hide(); + twocolor->set_active (false); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + neutrcurHBox->hide(); + hlColSat->hide(); + shadowsColSat->hide(); + balance->hide(); + satLimiterSep->hide(); + satProtectionThreshold->hide(); + saturatedOpacity->hide(); + strengthprotection->show(); + chanMixerBox->show(); + neutrHBox->show(); + lumamode->show(); + //splitSep->show(); + //satlow->hide(); + //sathigh->hide(); + } + else if (method->get_active_row_number()==4) { // Split Color + colorSep->show(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->hide(); + twocolor->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + neutrcurHBox->hide(); + hlColSat->show(); + shadowsColSat->show(); + balance->show(); + satLimiterSep->hide(); + satProtectionThreshold->hide(); + saturatedOpacity->hide(); + strengthprotection->show(); + + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->show(); + //splitSep->hide(); + //satlow->show(); + //sathigh->show(); + } + } + + if (listener && enabled->get_active ()) + listener->panelChanged (EvColorToningMethod, method->get_active_text ()); +} + + +void ColorToning::autoOpenCurve () { + colorShape->openIfNonlinear(); + opacityShape->openIfNonlinear(); + clshape->openIfNonlinear(); + cl2shape->openIfNonlinear(); +} + +void ColorToning::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { + + float R, G, B; + if (callerId == 1) { // ch - main curve + Color::hsv2rgb01(float(valY), 1.0f, 0.5f, R, G, B); + } + else if (callerId == 2) { // Slider 1 background + if (valY > 0.5) + // the hue range + Color::hsv2rgb01(float(valX), 1.0f, 0.5f, R, G, B); + else { + // the strength applied to the current hue + double strength, hue; + float r_, g_, b_; + hlColSat->getValue(strength, hue); + Color::hsv2rgb01(valY*2.f, 1.f, 1.f, r_, g_, b_); + Color::hsv2rgb01(hue/360.f, 1.f, 1.f, R, G, B); + R = r_+(R-r_)*valX; + G = g_+(G-g_)*valX; + B = b_+(B-b_)*valX; + } + } + else if (callerId == 3) { // Slider 2 background + if (valY > 0.5) + // the hue range + Color::hsv2rgb01(float(valX), 1.0f, 0.5f, R, G, B); + else { + // the strength applied to the current hue + double strength, hue; + float r_, g_, b_; + shadowsColSat->getValue(strength, hue); + Color::hsv2rgb01(valY*2.f, 1.f, 1.f, r_, g_, b_); + Color::hsv2rgb01(hue/360.f, 1.f, 1.f, R, G, B); + R = r_+(R-r_)*valX; + G = g_+(G-g_)*valX; + B = b_+(B-b_)*valX; + } + } + caller->ccRed = double(R); + caller->ccGreen = double(G); + caller->ccBlue = double(B); +} + +void ColorToning::curveChanged (CurveEditor* ce) { + + if (listener) { + if (ce == colorShape) + listener->panelChanged (EvColorToningColor, M("HISTORY_CUSTOMCURVE")); + else if (ce == opacityShape) + listener->panelChanged (EvColorToningOpacity, M("HISTORY_CUSTOMCURVE")); + else if (ce == clshape) + listener->panelChanged (EvColorToningCLCurve, M("HISTORY_CUSTOMCURVE")); + else if (ce == cl2shape) + listener->panelChanged (EvColorToningLLCurve, M("HISTORY_CUSTOMCURVE")); + } +} + +void ColorToning::enabledChanged () { + + if (batchMode) { + if (enabled->get_inconsistent()) { + enabled->set_inconsistent (false); + enaConn.block (true); + enabled->set_active (false); + enaConn.block (false); + } + else if (lastEnabled) + enabled->set_inconsistent (true); + + lastEnabled = enabled->get_active (); + } + if (listener) { + if (enabled->get_active()) + listener->panelChanged (EvColorToningEnabled, M("GENERAL_ENABLED")); + else + listener->panelChanged (EvColorToningEnabled, M("GENERAL_DISABLED")); + } +} + +void ColorToning::autosatChanged () { + + if (batchMode) { + if (autosat->get_inconsistent()) { + autosat->set_inconsistent (false); + autosatConn.block (true); + autosat->set_active (false); + autosatConn.block (false); + } + else if (lastautosat) + autosat->set_inconsistent (true); + + lastautosat = autosat->get_active (); + } + if (listener) { + if (autosat->get_active()) + {listener->panelChanged (EvColorToningautosat, M("GENERAL_ENABLED")); + saturatedOpacity->set_sensitive(false); + satProtectionThreshold->set_sensitive(false); + + } + + else + {listener->panelChanged (EvColorToningautosat, M("GENERAL_DISABLED")); + saturatedOpacity->set_sensitive(true); + satProtectionThreshold->set_sensitive(true); + + } + + } +} + +void ColorToning::trimValues (rtengine::procparams::ProcParams* pp) { + + redlow->trimValue(pp->colorToning.redlow); + greenlow->trimValue(pp->colorToning.greenlow); + bluelow->trimValue(pp->colorToning.bluelow); + //satlow->trimValue(pp->colorToning.satlow); + //sathigh->trimValue(pp->colorToning.sathigh); + balance->trimValue(pp->colorToning.balance); + redmed->trimValue(pp->colorToning.redmed); + greenmed->trimValue(pp->colorToning.greenmed); + bluemed->trimValue(pp->colorToning.bluemed); + redhigh->trimValue(pp->colorToning.redhigh); + greenhigh->trimValue(pp->colorToning.greenhigh); + bluehigh->trimValue(pp->colorToning.bluehigh); +} + +void ColorToning::setBatchMode (bool batchMode) +{ + ToolPanel::setBatchMode (batchMode); + method->append_text (M("GENERAL_UNCHANGED")); + twocolor->append_text (M("GENERAL_UNCHANGED")); + hlColSat->showEditedCB (); + shadowsColSat->showEditedCB (); + redlow->showEditedCB (); + greenlow->showEditedCB (); + bluelow->showEditedCB (); + //satlow->showEditedCB (); + //sathigh->showEditedCB (); + balance->showEditedCB (); + redmed->showEditedCB (); + greenmed->showEditedCB (); + bluemed->showEditedCB (); + redhigh->showEditedCB (); + greenhigh->showEditedCB (); + bluehigh->showEditedCB (); + + colorCurveEditorG->setBatchMode (batchMode); + opacityCurveEditorG->setBatchMode (batchMode); + clCurveEditorG->setBatchMode (batchMode); + cl2CurveEditorG->setBatchMode (batchMode); + +} diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h new file mode 100644 index 000000000..871e1debd --- /dev/null +++ b/rtgui/colortoning.h @@ -0,0 +1,113 @@ +/* + * This file is part of RawTherapee. + */ +#ifndef _COLORTONING_H_ +#define _COLORTONING_H_ + +#include +#include "adjuster.h" +#include "toolpanel.h" +#include "guiutils.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" +#include "thresholdadjuster.h" +#include "colorprovider.h" + +class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rtengine::AutoColorTonListener,public CurveListener, public ColorProvider, + public ThresholdAdjusterListener, public AdjusterListener { + + protected: + Gtk::CheckButton* enabled; + //Gtk::HSeparator* splitSep; + Gtk::HSeparator* satLimiterSep; + Gtk::HSeparator* colorSep; + CurveEditorGroup* colorCurveEditorG; + CurveEditorGroup* opacityCurveEditorG; + CurveEditorGroup* clCurveEditorG; + CurveEditorGroup* cl2CurveEditorG; + FlatCurveEditor* opacityShape; + FlatCurveEditor* colorShape; + DiagonalCurveEditor* clshape; + DiagonalCurveEditor* cl2shape; + Gtk::HBox* ctbox; + + Gtk::VBox* chanMixerBox; + MyComboBoxText* method; + sigc::connection methodconn; + MyComboBoxText* twocolor; + Adjuster* redlow; + Adjuster* greenlow; + Adjuster* bluelow; + Adjuster* redmed; + Adjuster* greenmed; + Adjuster* bluemed; + Adjuster* redhigh; + Adjuster* greenhigh; + Adjuster* bluehigh; + Adjuster* balance; + //Adjuster* satlow; + //Adjuster* sathigh; + Gtk::CheckButton* autosat; + ThresholdAdjuster* shadowsColSat; + ThresholdAdjuster* hlColSat; + Adjuster* satProtectionThreshold; + Adjuster* saturatedOpacity; + Adjuster* strengthprotection; + Gtk::Image* itot; + Gtk::Image* iby; + Gtk::Image* irg; + + Gtk::Button* neutral; + Gtk::Button* neutralcur; + Gtk::HBox* neutrHBox; + Gtk::HBox* neutrcurHBox; + Gtk::HBox* chromaHbox; + Gtk::Label* colLabel; + Gtk::Label* interLabel; + Gtk::Label* chroLabel; + int nextbw; + int nextsatth; + int nextsatpr; + Glib::ustring labchroma1; + Glib::ustring labchroma2; + Glib::ustring nextbalcolor; + Glib::ustring balcolor; + bool lastEnabled; + sigc::connection enaConn; + bool lasttwocolor; + sigc::connection neutralconn, twocconn, neutralcurconn; + bool lastautosat; + sigc::connection autosatConn; + + Gtk::CheckButton* lumamode; + bool lastLumamode; + sigc::connection lumamodeConn; + + public: + ColorToning (); + ~ColorToning(); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void setBatchMode (bool batchMode); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void trimValues (rtengine::procparams::ProcParams* pp); + void adjusterChanged (Adjuster* a, double newval); + void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop); + void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd); + void neutral_pressed (); + void neutralcur_pressed (); + void autoColorTonChanged (int bwct, int satthres, int satprot); + bool CTComp_ (); + + void enabledChanged (); + void curveChanged (CurveEditor* ce); + void autosatChanged (); + void autoOpenCurve (); + void methodChanged (); + void twocolorChanged (); + void lumamodeChanged (); + + void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); +}; + +#endif diff --git a/rtgui/defringe.cc b/rtgui/defringe.cc index fd8460780..ebb6e7282 100644 --- a/rtgui/defringe.cc +++ b/rtgui/defringe.cc @@ -37,7 +37,7 @@ Defringe::Defringe () : FoldableToolPanel(this) { enabled->set_active (false); enabled->set_tooltip_markup (M("TP_SHARPENING_TOOLTIP")); - enabled->show (); + // enabled->show (); pack_start (*enabled); Gtk::HSeparator *hsep1 = Gtk::manage (new Gtk::HSeparator()); @@ -59,14 +59,16 @@ Defringe::Defringe () : FoldableToolPanel(this) { threshold = Gtk::manage (new Adjuster (M("TP_DEFRINGE_THRESHOLD"), 0, 100, 1, 13)); radius->setAdjusterListener (this); threshold->setAdjusterListener (this); - radius->show(); - threshold->show(); + // radius->show(); + // threshold->show(); pack_start (*radius); pack_start (*threshold); curveEditorPF->curveListComplete(); pack_start (*curveEditorPF, Gtk::PACK_SHRINK, 4); + + show (); } Defringe::~Defringe () { @@ -115,7 +117,7 @@ void Defringe::read (const ProcParams* pp, const ParamsEdited* pedited) { void Defringe::autoOpenCurve () { // WARNING: The following line won't work, since linear is a flat curve at 0. - chshape->openIfNonlinear(); + // chshape->openIfNonlinear(); } void Defringe::write (ProcParams* pp, ParamsEdited* pedited) { diff --git a/rtgui/options.cc b/rtgui/options.cc index 35609fc9d..9346b3816 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -226,8 +226,8 @@ void Options::setDefaults () { font = "sans, 8"; windowWidth = 1200; - windowHeight = 680; - windowX = 0; + windowHeight = 680; + windowX = 0; windowY = 0; windowMaximized = true; saveAsDialogWidth = 920; @@ -260,8 +260,8 @@ void Options::setDefaults () { adjusterDelay = 0; startupDir = STARTUPDIR_LAST; startupPath = ""; - useBundledProfiles = true; - detailWindowWidth = -1; + useBundledProfiles = true; + detailWindowWidth = -1; detailWindowHeight = -1; dirBrowserWidth = 260; dirBrowserHeight = 350; @@ -486,6 +486,7 @@ void Options::setDefaults () { 0, // ADDSET_BLACKWHITE_GAMMA 0, // ADDSET_DIRPYREQ_THRESHOLD 0, // ADDSET_DIRPYREQ_SKINPROTECT + 0, // ADDSET_COLORTONING_SPLIT }; baBehav = std::vector (babehav, babehav+ADDSET_PARAM_NUM); @@ -533,7 +534,8 @@ void Options::setDefaults () { rtSettings.autocielab=true; rtSettings.denoiselabgamma=2; rtSettings.HistogramWorking = false; - + // rtSettings.colortoningab =0.7; +//rtSettings.decaction =0.3; // rtSettings.ciebadpixgauss=false; rtSettings.rgbcurveslumamode_gamut=true; lastIccDir = rtSettings.iccDirectory; @@ -707,7 +709,7 @@ if (keyFile.has_group ("GUI")) { if (keyFile.has_key ("GUI", "WindowHeight")) windowHeight = keyFile.get_integer ("GUI", "WindowHeight"); if (keyFile.has_key ("GUI", "WindowX")) windowX = keyFile.get_integer ("GUI", "WindowX"); if (keyFile.has_key ("GUI", "WindowY")) windowY = keyFile.get_integer ("GUI", "WindowY"); - if (keyFile.has_key ("GUI", "WindowMaximized")) windowMaximized = keyFile.get_boolean ("GUI", "WindowMaximized"); + if (keyFile.has_key ("GUI", "WindowMaximized")) windowMaximized = keyFile.get_boolean ("GUI", "WindowMaximized"); if (keyFile.has_key ("GUI", "DetailWindowWidth")) detailWindowWidth = keyFile.get_integer ("GUI", "DetailWindowWidth"); if (keyFile.has_key ("GUI", "DetailWindowHeight")) detailWindowHeight = keyFile.get_integer ("GUI", "DetailWindowHeight"); if (keyFile.has_key ("GUI", "DirBrowserWidth")) dirBrowserWidth = keyFile.get_integer ("GUI", "DirBrowserWidth"); @@ -768,6 +770,8 @@ if (keyFile.has_group ("Color Management")) { if (keyFile.has_key ("Color Management", "CBDLArtif")) rtSettings.artifact_cbdl = keyFile.get_double("Color Management", "CBDLArtif"); if (keyFile.has_key ("Color Management", "CBDLlevel0")) rtSettings.level0_cbdl = keyFile.get_double("Color Management", "CBDLlevel0"); if (keyFile.has_key ("Color Management", "CBDLlevel123")) rtSettings.level123_cbdl = keyFile.get_double("Color Management", "CBDLlevel123"); + // if (keyFile.has_key ("Color Management", "Colortoningab")) rtSettings.colortoningab = keyFile.get_double("Color Management", "Colortoningab"); + // if (keyFile.has_key ("Color Management", "Decaction")) rtSettings.decaction = keyFile.get_double("Color Management", "Decaction"); if (keyFile.has_key ("Color Management", "WhiteBalanceSpotSize")) whiteBalanceSpotSize = keyFile.get_integer("Color Management", "WhiteBalanceSpotSize"); if( keyFile.has_key ("Color Management", "GamutICC")) rtSettings.gamutICC = keyFile.get_boolean("Color Management", "GamutICC"); @@ -997,9 +1001,9 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_string ("GUI", "Font", font); keyFile.set_integer ("GUI", "WindowWidth", windowWidth); - keyFile.set_integer ("GUI", "WindowHeight", windowHeight); + keyFile.set_integer ("GUI", "WindowHeight", windowHeight); keyFile.set_integer ("GUI", "WindowX", windowX); - keyFile.set_integer ("GUI", "WindowY", windowY); + keyFile.set_integer ("GUI", "WindowY", windowY); keyFile.set_boolean ("GUI", "WindowMaximized", windowMaximized); keyFile.set_integer ("GUI", "DetailWindowWidth", detailWindowWidth); keyFile.set_integer ("GUI", "DetailWindowHeight", detailWindowHeight); @@ -1077,6 +1081,8 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_double ("Color Management", "CBDLArtif", rtSettings.artifact_cbdl); keyFile.set_double ("Color Management", "CBDLlevel0", rtSettings.level0_cbdl); keyFile.set_double ("Color Management", "CBDLlevel123", rtSettings.level123_cbdl); + // keyFile.set_double ("Color Management", "Colortoningab", rtSettings.colortoningab); +// keyFile.set_double ("Color Management", "Decaction", rtSettings.decaction); Glib::ArrayHandle bab = baBehav; @@ -1287,7 +1293,7 @@ bool Options::load () { } void Options::save () { - + if (options.multiUser==false) { options.saveToFile (Glib::build_filename(argv0, "options")); } diff --git a/rtgui/options.h b/rtgui/options.h index 3937c3df0..a9b4b7b71 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -263,6 +263,7 @@ class Options { Glib::ustring lastPFCurvesDir; Glib::ustring lastHsvCurvesDir; Glib::ustring lastToneCurvesDir; + Glib::ustring lastColorToningCurvesDir; Glib::ustring lastVibranceCurvesDir; Glib::ustring lastProfilingReferenceDir; Glib::ustring lastBWCurvesDir; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 0a53bd820..1117b37a8 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -67,6 +67,33 @@ void ParamsEdited::set (bool v) { rgbCurves.rcurve = v; rgbCurves.gcurve = v; rgbCurves.bcurve = v; + colorToning.enabled = v; + colorToning.autosat = v; + colorToning.opacityCurve = v; + colorToning.colorCurve = v; + colorToning.satProtectionThreshold = v; + colorToning.saturatedOpacity = v; + colorToning.strengthprotection = v; + colorToning.shadowsColSat = v; + colorToning.hlColSat = v; + colorToning.balance = v; + colorToning.clcurve = v; + colorToning.method = v; + colorToning.twocolor = v; + colorToning.cl2curve = v; + colorToning.redlow = v; + colorToning.greenlow = v; + colorToning.bluelow = v; + colorToning.satlow = v; + colorToning.sathigh = v; + colorToning.redmed = v; + colorToning.greenmed = v; + colorToning.bluemed = v; + colorToning.redhigh = v; + colorToning.greenhigh = v; + colorToning.bluehigh = v; + colorToning.lumamode = v; + sharpening.enabled = v; sharpening.radius = v; sharpening.amount = v; @@ -355,6 +382,32 @@ void ParamsEdited::initFrom (const std::vector rgbCurves.rcurve = rgbCurves.rcurve && p.rgbCurves.rcurve == other.rgbCurves.rcurve; rgbCurves.gcurve = rgbCurves.gcurve && p.rgbCurves.gcurve == other.rgbCurves.gcurve; rgbCurves.bcurve = rgbCurves.bcurve && p.rgbCurves.bcurve == other.rgbCurves.bcurve; + colorToning.enabled = colorToning.enabled && p.colorToning.enabled == other.colorToning.enabled; + colorToning.twocolor = colorToning.twocolor && p.colorToning.twocolor == other.colorToning.twocolor; + colorToning.opacityCurve = colorToning.opacityCurve && p.colorToning.opacityCurve == other.colorToning.opacityCurve; + colorToning.colorCurve = colorToning.colorCurve && p.colorToning.colorCurve == other.colorToning.colorCurve; + colorToning.autosat = colorToning.autosat && p.colorToning.autosat == other.colorToning.autosat; + colorToning.satProtectionThreshold = colorToning.satProtectionThreshold && p.colorToning.satProtectionThreshold == other.colorToning.satProtectionThreshold; + colorToning.saturatedOpacity = colorToning.saturatedOpacity && p.colorToning.saturatedOpacity == other.colorToning.saturatedOpacity; + colorToning.strengthprotection = colorToning.strengthprotection && p.colorToning.strengthprotection == other.colorToning.strengthprotection; + colorToning.shadowsColSat = colorToning.shadowsColSat && p.colorToning.shadowsColSat == other.colorToning.shadowsColSat; + colorToning.hlColSat = colorToning.hlColSat && p.colorToning.hlColSat == other.colorToning.hlColSat; + colorToning.balance = colorToning.balance && p.colorToning.balance == other.colorToning.balance; + colorToning.clcurve = colorToning.clcurve && p.colorToning.clcurve == other.colorToning.clcurve; + colorToning.cl2curve = colorToning.cl2curve && p.colorToning.cl2curve == other.colorToning.cl2curve; + colorToning.method = colorToning.method && p.colorToning.method == other.colorToning.method; + colorToning.redlow = colorToning.redlow && p.colorToning.redlow == other.colorToning.redlow; + colorToning.greenlow = colorToning.greenlow && p.colorToning.greenlow == other.colorToning.greenlow; + colorToning.bluelow = colorToning.bluelow && p.colorToning.bluelow == other.colorToning.bluelow; + colorToning.satlow = colorToning.satlow && p.colorToning.satlow == other.colorToning.satlow; + colorToning.sathigh = colorToning.sathigh && p.colorToning.sathigh == other.colorToning.sathigh; + colorToning.redmed = colorToning.redmed && p.colorToning.redmed == other.colorToning.redmed; + colorToning.greenmed = colorToning.greenmed && p.colorToning.greenmed == other.colorToning.greenmed; + colorToning.bluemed = colorToning.bluemed && p.colorToning.bluemed == other.colorToning.bluemed; + colorToning.redhigh = colorToning.redhigh && p.colorToning.redhigh == other.colorToning.redhigh; + colorToning.greenhigh = colorToning.greenhigh && p.colorToning.greenhigh == other.colorToning.greenhigh; + colorToning.bluehigh = colorToning.bluehigh && p.colorToning.bluehigh == other.colorToning.bluehigh; + colorToning.lumamode = colorToning.lumamode && p.colorToning.lumamode == other.colorToning.lumamode; sharpenEdge.enabled = sharpenEdge.enabled && p.sharpenEdge.enabled == other.sharpenEdge.enabled; sharpenEdge.passes = sharpenEdge.passes && p.sharpenEdge.passes == other.sharpenEdge.passes; sharpenEdge.amount = sharpenEdge.amount && p.sharpenEdge.amount == other.sharpenEdge.amount; @@ -642,6 +695,37 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (rgbCurves.gcurve) toEdit.rgbCurves.gcurve = mods.rgbCurves.gcurve; if (rgbCurves.bcurve) toEdit.rgbCurves.bcurve = mods.rgbCurves.bcurve; + if (colorToning.enabled) toEdit.colorToning.enabled = mods.colorToning.enabled; + if (colorToning.twocolor) toEdit.colorToning.twocolor = mods.colorToning.twocolor; + if (colorToning.opacityCurve) toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; + if (colorToning.colorCurve) toEdit.colorToning.colorCurve = mods.colorToning.colorCurve; + if (colorToning.enabled) toEdit.colorToning.enabled = mods.colorToning.enabled; + if (colorToning.opacityCurve) toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; + if (colorToning.colorCurve) toEdit.colorToning.colorCurve = mods.colorToning.colorCurve; + if (colorToning.satProtectionThreshold) toEdit.colorToning.satProtectionThreshold = dontforceSet && options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD] ? toEdit.colorToning.satProtectionThreshold + mods.colorToning.satProtectionThreshold : mods.colorToning.satProtectionThreshold; + if (colorToning.autosat) toEdit.colorToning.autosat = mods.colorToning.autosat; + if (colorToning.saturatedOpacity) toEdit.colorToning.saturatedOpacity = dontforceSet && options.baBehav[ADDSET_COLORTONING_SATOPACITY] ? toEdit.colorToning.saturatedOpacity + mods.colorToning.saturatedOpacity : mods.colorToning.saturatedOpacity; + if (colorToning.strengthprotection) toEdit.colorToning.strengthprotection = dontforceSet && options.baBehav[ADDSET_COLORTONING_STRPROTECT] ? toEdit.colorToning.strengthprotection + mods.colorToning.strengthprotection: mods.colorToning.strengthprotection; + + if (colorToning.shadowsColSat) toEdit.colorToning.shadowsColSat = mods.colorToning.shadowsColSat; + if (colorToning.hlColSat) toEdit.colorToning.hlColSat = mods.colorToning.hlColSat; + if (colorToning.balance) toEdit.colorToning.balance = dontforceSet && options.baBehav[ADDSET_COLORTONING_BALANCE] ? toEdit.colorToning.balance + mods.colorToning.balance : mods.colorToning.balance; + if (colorToning.clcurve) toEdit.colorToning.clcurve = mods.colorToning.clcurve; + if (colorToning.method) toEdit.colorToning.method = mods.colorToning.method; + if (colorToning.cl2curve) toEdit.colorToning.cl2curve = mods.colorToning.cl2curve; + if (colorToning.lumamode) toEdit.colorToning.lumamode = mods.colorToning.lumamode; + if (colorToning.satlow) toEdit.colorToning.satlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.satlow + mods.colorToning.satlow : mods.colorToning.satlow; + if (colorToning.sathigh) toEdit.colorToning.sathigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.sathigh + mods.colorToning.sathigh : mods.colorToning.sathigh; + if (colorToning.redlow) toEdit.colorToning.redlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redlow + mods.colorToning.redlow : mods.colorToning.redlow; + if (colorToning.greenlow) toEdit.colorToning.greenlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenlow + mods.colorToning.greenlow : mods.colorToning.greenlow; + if (colorToning.bluelow) toEdit.colorToning.bluelow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluelow + mods.colorToning.bluelow : mods.colorToning.bluelow; + if (colorToning.redmed) toEdit.colorToning.redmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redmed + mods.colorToning.redmed : mods.colorToning.redmed; + if (colorToning.greenmed) toEdit.colorToning.greenmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenmed + mods.colorToning.greenmed : mods.colorToning.greenmed; + if (colorToning.bluemed) toEdit.colorToning.bluemed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluemed + mods.colorToning.bluemed : mods.colorToning.bluemed; + if (colorToning.redhigh) toEdit.colorToning.redhigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redhigh + mods.colorToning.redhigh : mods.colorToning.redhigh; + if (colorToning.greenhigh) toEdit.colorToning.greenhigh= dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenhigh + mods.colorToning.greenhigh : mods.colorToning.greenhigh; + if (colorToning.bluehigh) toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; + if (sharpenEdge.enabled) toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; if (sharpenEdge.passes) toEdit.sharpenEdge.passes = dontforceSet && options.baBehav[ADDSET_SHARPENEDGE_PASS] ? toEdit.sharpenEdge.passes + mods.sharpenEdge.passes : mods.sharpenEdge.passes; if (sharpenEdge.amount) toEdit.sharpenEdge.amount = dontforceSet && options.baBehav[ADDSET_SHARPENEDGE_AMOUNT] ? toEdit.sharpenEdge.amount + mods.sharpenEdge.amount : mods.sharpenEdge.amount; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index b7d2eada7..65776f351 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -87,6 +87,37 @@ class RGBCurvesParamsEdited { bool bcurve; }; +class ColorToningEdited { + + public: + bool enabled; + bool opacityCurve; + bool colorCurve; + bool clcurve; + bool method; + bool autosat; + bool satProtectionThreshold; + bool saturatedOpacity; + bool strengthprotection; + bool shadowsColSat; + bool hlColSat; + bool balance; + bool twocolor; + bool cl2curve; + bool redlow; + bool greenlow; + bool bluelow; + bool redmed; + bool greenmed; + bool bluemed; + bool redhigh; + bool greenhigh; + bool bluehigh; + bool satlow; + bool sathigh; + bool lumamode; +}; + class SharpenEdgeParamsEdited { public : @@ -493,6 +524,7 @@ class ParamsEdited { ToneCurveParamsEdited toneCurve; LCurveParamsEdited labCurve; RGBCurvesParamsEdited rgbCurves; + ColorToningEdited colorToning; SharpeningParamsEdited sharpening; SharpenEdgeParamsEdited sharpenEdge; SharpenMicroParamsEdited sharpenMicro; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 2887cfd94..869f36434 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -67,6 +67,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { dirpyrden = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DIRPYRDENOISE"))); hsveq = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_HSVEQUALIZER"))); rgbcurves = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RGBCURVES"))); + colortoning = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COLORTONING"))); // options in lens: distortion = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DISTORTION"))); @@ -150,6 +151,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { vboxes[2]->pack_start (*blackwhite, Gtk::PACK_SHRINK, 2); vboxes[2]->pack_start (*hsveq, Gtk::PACK_SHRINK, 2); vboxes[2]->pack_start (*rgbcurves, Gtk::PACK_SHRINK, 2); + vboxes[2]->pack_start (*colortoning, Gtk::PACK_SHRINK, 2); vboxes[3]->pack_start (*lens, Gtk::PACK_SHRINK, 2); vboxes[3]->pack_start (*hseps[3], Gtk::PACK_SHRINK, 2); @@ -268,6 +270,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { chmixerbwConn = blackwhite->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); hsveqConn = hsveq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); rgbcurvesConn = rgbcurves->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); + colortoningConn = colortoning->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); distortionConn = distortion->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); cacorrConn = cacorr->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); @@ -497,6 +500,7 @@ void PartialPasteDlg::colorToggled () { chmixerbwConn.block (true); hsveqConn.block (true); rgbcurvesConn.block (true); + colortoningConn.block (true); gamcsconn.block (true); color->set_inconsistent (false); @@ -505,6 +509,7 @@ void PartialPasteDlg::colorToggled () { blackwhite->set_active (color->get_active ()); hsveq->set_active (color->get_active ()); rgbcurves->set_active (color->get_active ()); + colortoning->set_active(color->get_active ()); icm->set_active (color->get_active ()); vibranceConn.block (false); @@ -512,6 +517,7 @@ void PartialPasteDlg::colorToggled () { chmixerConn.block (false); hsveqConn.block (false); rgbcurvesConn.block (false); + colortoningConn.block (false); gamcsconn.block (false); } @@ -627,6 +633,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param if (!blackwhite->get_active ()) filterPE.blackwhite = falsePE.blackwhite; if (!hsveq->get_active ()) filterPE.hsvequalizer = falsePE.hsvequalizer; if (!rgbcurves->get_active ()) filterPE.rgbCurves = falsePE.rgbCurves; + if (!colortoning->get_active ()) filterPE.colorToning = falsePE.colorToning; if (!icm->get_active ()) filterPE.icm = falsePE.icm; if (!distortion->get_active ()) filterPE.distortion = falsePE.distortion; diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 206a23ca6..361ef1005 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -63,6 +63,7 @@ class PartialPasteDlg : public Gtk::Dialog { Gtk::CheckButton* blackwhite; Gtk::CheckButton* hsveq; Gtk::CheckButton* rgbcurves; + Gtk::CheckButton* colortoning; // Gtk::CheckButton* icm; // options in lens: @@ -113,7 +114,7 @@ class PartialPasteDlg : public Gtk::Dialog { sigc::connection wbConn, exposureConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn; sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, waveqConn, defringeConn, epdConn, dirpyreqConn; - sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn, chmixerbwConn; + sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn, chmixerbwConn, colortoningConn; sigc::connection distortionConn, cacorrConn, vignettingConn, lcpConn; sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, perspectiveConn, commonTransConn; sigc::connection exifchConn, iptcConn, icmConn, gamcsconn; diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index e6d4e426a..1639e7fbc 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -2,11 +2,13 @@ #define _PPVERSION_ // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes -#define PPVERSION 319 +#define PPVERSION 320 #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified /* Log of version changes + 316 2014-03-29 + [ColorToning] new tool for color toning 319 2014-02-11 Hue skin for Contrast by detail levels 318 2014-02-10 diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index e63167597..2f1180016 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -27,7 +27,7 @@ #include #include "../rtengine/safegtk.h" #include "rtimage.h" - + extern Options options; extern Glib::ustring argv0; @@ -241,6 +241,14 @@ Gtk::Widget* Preferences::getBatchProcPanel () { appendBehavList (mi, M("TP_BWMIX_MIXC"), ADDSET_BLACKWHITE_HUES, false); appendBehavList (mi, M("TP_BWMIX_GAMMA"), ADDSET_BLACKWHITE_GAMMA, false); + mi = behModel->append (); + mi->set_value (behavColumns.label, M("TP_COLORTONING_LABEL")); + appendBehavList (mi, M("TP_COLORTONING_SPLITCOCO"),ADDSET_COLORTONING_SPLIT , true); + appendBehavList (mi, M("TP_COLORTONING_SATURATIONTHRESHOLD"),ADDSET_COLORTONING_SATTHRESHOLD , true); + appendBehavList (mi, M("TP_COLORTONING_SATURATEDOPACITY"),ADDSET_COLORTONING_SATOPACITY , true); + appendBehavList (mi, M("TP_COLORTONING_BALANCE"),ADDSET_COLORTONING_BALANCE , true); + appendBehavList (mi, M("TP_COLORTONING_STRPROTECT"),ADDSET_COLORTONING_STRPROTECT , true); + mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_ROTATE_LABEL")); appendBehavList (mi, M("TP_ROTATE_DEGREE"), ADDSET_ROTATE_DEGREE, false); @@ -603,14 +611,14 @@ Gtk::Widget* Preferences::getGeneralPanel () { ckbHistogramWorking = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_HISTOGRAMWORKING")) ); ckbHistogramWorking->set_tooltip_markup (M("PREFERENCES_HISTOGRAM_TOOLTIP")); - hbworkflow2->pack_start (*ckbHistogramWorking, Gtk::PACK_SHRINK, 4); + hbworkflow2->pack_start (*ckbHistogramWorking, Gtk::PACK_SHRINK, 4); vbworkflow->pack_start (*hbworkflow2, Gtk::PACK_SHRINK, 4); ckbShowProfileSelector = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_SHOWPROFILESELECTOR")) ); Gtk::HBox* hbworkflow2d5 = Gtk::manage( new Gtk::HBox () ); hbworkflow2d5->pack_start (*ckbShowProfileSelector, Gtk::PACK_SHRINK, 4); vbworkflow->pack_start (*hbworkflow2d5, Gtk::PACK_SHRINK, 4); - + Gtk::HBox* hbworkflow3 = Gtk::manage( new Gtk::HBox () ); ckbFileBrowserToolbarSingleRow = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_FILEBROWSERTOOLBARSINGLEROW")) ); @@ -681,7 +689,7 @@ Gtk::Widget* Preferences::getGeneralPanel () { hbUseSystemTheme->pack_start (*useNextStart, Gtk::PACK_SHRINK, 0); hbUseSystemTheme->pack_end(*slimUI, Gtk::PACK_SHRINK, 0); vbftheme->pack_start(*hbUseSystemTheme, Gtk::PACK_SHRINK, 0); - + hbtheme = Gtk::manage( new Gtk::HBox () ); hbtheme->set_spacing (4); @@ -705,17 +713,17 @@ Gtk::Widget* Preferences::getGeneralPanel () { hbtheme->pack_start (*fontbutton); vbftheme->pack_start(*hbtheme, Gtk::PACK_SHRINK, 0); - + Gtk::HBox* hbcolorchooser = Gtk::manage( new Gtk::HBox () ); hbcolorchooser->set_spacing(4); - + hbcolorchooser->pack_start (*cutOverlayLabel, Gtk::PACK_SHRINK, 0); hbcolorchooser->pack_start (*butCropCol, Gtk::PACK_SHRINK, 0); hbcolorchooser->pack_end (*butNavGuideCol, Gtk::PACK_SHRINK, 0); hbcolorchooser->pack_end (*navGuideLabel, Gtk::PACK_SHRINK, 0); vbftheme->pack_start(*hbcolorchooser, Gtk::PACK_SHRINK, 0); - - + + ftheme->add (*vbftheme); mvbsd->pack_start (*ftheme, Gtk::PACK_SHRINK, 0); @@ -889,13 +897,13 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { showBasicExif = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_SHOWBASICEXIF")) ); showExpComp = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_SHOWEXPOSURECOMPENSATION")) ); Gtk::VBox* vbro = Gtk::manage( new Gtk::VBox () ); - Gtk::HBox* hbro1 = Gtk::manage( new Gtk::HBox () ); + Gtk::HBox* hbro1 = Gtk::manage( new Gtk::HBox () ); Gtk::HBox* hbro0 = Gtk::manage( new Gtk::HBox () ); overlayedFileNames = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_OVERLAY_FILENAMES")) ); ckbInternalThumbIfUntouched = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_INTERNALTHUMBIFUNTOUCHED"))); - vbro->set_border_width (4); - vbro->pack_start (*showDateTime, Gtk::PACK_SHRINK, 0); + vbro->set_border_width (4); + vbro->pack_start (*showDateTime, Gtk::PACK_SHRINK, 0); Gtk::Label* dflab = Gtk::manage( new Gtk::Label (M("PREFERENCES_DATEFORMAT")+":", Gtk::ALIGN_LEFT)); dateformat = Gtk::manage( new Gtk::Entry () ); dateformat->set_tooltip_markup (M("PREFERENCES_DATEFORMATHINT")); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 6f9c441a6..0f35c8627 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -51,6 +51,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { sharpenMicro = Gtk::manage (new SharpenMicro ()); lcurve = Gtk::manage (new LCurve ()); rgbcurves = Gtk::manage (new RGBCurves ()); + colortoning = Gtk::manage (new ColorToning ()); lensgeom = Gtk::manage (new LensGeometry ()); lensProf = Gtk::manage (new LensProfilePanel ()); distortion = Gtk::manage (new Distortion ()); @@ -90,6 +91,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { addPanel (detailsPanel, sharpenMicro, M("TP_SHARPENMICRO_LABEL"), true); toolPanels.push_back (sharpenMicro); addPanel (colorPanel, hsvequalizer, M("TP_HSVEQUALIZER_LABEL")); toolPanels.push_back (hsvequalizer); addPanel (colorPanel, rgbcurves, M("TP_RGBCURVES_LABEL")); toolPanels.push_back (rgbcurves); + addPanel (colorPanel, colortoning, M("TP_COLORTONING_LABEL")); toolPanels.push_back (colortoning); addPanel (exposurePanel, epd, M("TP_EPD_LABEL"), true); toolPanels.push_back (epd); addPanel (exposurePanel, pcvignette, M("TP_PCVIGNETTE_LABEL")); toolPanels.push_back (pcvignette); addPanel (exposurePanel, gradient, M("TP_GRADIENT_LABEL")); toolPanels.push_back (gradient); @@ -363,6 +365,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool ipc->setAutoExpListener (toneCurve); ipc->setAutoCamListener (colorappearance); ipc->setAutoBWListener (blackwhite); + ipc->setAutoColorTonListener (colortoning); ipc->setSizeListener (crop); ipc->setSizeListener (resize); diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 9eb65e5ed..d6a74e8a6 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -68,6 +68,7 @@ #include "sharpenmicro.h" #include "sharpenedge.h" #include "rgbcurves.h" +#include "colortoning.h" class ImageEditorCoordinator; @@ -114,8 +115,9 @@ class ToolPanelCoordinator : public ToolPanelListener, SharpenMicro* sharpenMicro; LCurve* lcurve; RGBCurves* rgbcurves; - DirPyrEqualizer * dirpyrequalizer; - HSVEqualizer * hsvequalizer; + ColorToning* colortoning; + DirPyrEqualizer* dirpyrequalizer; + HSVEqualizer* hsvequalizer; RawProcess* rawprocess; PreProcess* preprocess; DarkFrame* darkframe;