diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais
index 6403a3ab6..56553b07d 100644
--- a/rtdata/languages/Francais
+++ b/rtdata/languages/Francais
@@ -416,6 +416,12 @@ HISTORY_MSG_189;CAM02 - Contraste (Q)
HISTORY_MSG_190;CAM02 - Saturation (S)
HISTORY_MSG_191;CAM02 - Niveau de couleur (M)
HISTORY_MSG_192;CAM02 - Teinte (angle)
+HISTORY_MSG_193;CAM02 - Courbe tonale 1
+HISTORY_MSG_194;CAM02 - Courbe tonale 2
+HISTORY_MSG_195;CAM02 - Courbe tonale
+HISTORY_MSG_196;CAM02 - Courbe tonale 2
+HISTORY_MSG_197;CAM02 - Courbe couleur
+HISTORY_MSG_198;CAM02 - Courbe couleur
HISTORY_NEWSNAPSHOTAS;Sous...
HISTORY_NEWSNAPSHOT;Ajouter
HISTORY_NEWSSDIALOGLABEL;Label de la capture:
@@ -912,8 +918,8 @@ TP_COLORAPP_DEGREE_TOOLTIP;Niveau d'adaptation chromatique CIE CAT 2002\nSi vous
TP_COLORAPP_EQUAL;Préservé
TP_COLORAPP_GAMUT;Contrôle du gamut (Lab & CIECAM)
TP_COLORAPP_GAMUT_TOOLTIP;Permet le controle du gamut en mode Lab
-TP_COLORAPP_HUE;Teinte (H)
-TP_COLORAPP_HUE_TOOLTIP;Teinte (H) - angle entre 0° et 360°
+TP_COLORAPP_HUE;Teinte (h)
+TP_COLORAPP_HUE_TOOLTIP;Teinte (h) - angle entre 0° et 360°
TP_COLORAPP_LABEL;Modèle CIE d'Apparence de la Couleur (CAM02)
TP_COLORAPP_LABEL_CAM02;Édition de l'image avec CIECAM
TP_COLORAPP_LABEL_SCENE;Conditions de la scène
@@ -922,8 +928,8 @@ TP_COLORAPP_LIGHT;Luminosité (J)
TP_COLORAPP_LIGHT_TOOLTIP;Luminosité dans CIECAM02 est différent de Lab et RVB
TP_COLORAPP_MODEL;Modèle de Point Blanc
TP_COLORAPP_MODEL_TOOLTIP;BB [RT] + [sortie]:\nLa BB de RT est utilisée pour la scène, CIECAM est réglé sur D50, le blanc du périphérique de sortie utilise la valeur réglé dans Préférences\n\nBB [RT+CAT02] + [sortie]:\nLes réglages de BB de RT sont utilisés par CAT02 et le blanc du périphérique de sortie utilise la valeur réglé dans Préférences
-TP_COLORAPP_RSTPRO;Protection des tons chairs et rouges (C)
-TP_COLORAPP_RSTPRO_TOOLTIP;Protection par le curseur (C) des tons chairs et rouges
+TP_COLORAPP_RSTPRO;Protection des tons chairs et rouges
+TP_COLORAPP_RSTPRO_TOOLTIP;Protection des tons chairs et rouges (curseurs et courbes)
TP_COLORAPP_SURROUND;Entourage
TP_COLORAPP_SURROUND_AVER;Moyen
TP_COLORAPP_SURROUND_DARK;Sombre
@@ -934,6 +940,19 @@ TP_COLORAPP_SURSOURCE;Entourage sombre
TP_COLORAPP_SURSOURCE_TOOLTIP;Peut être utilisé si l'image source a un bord noir.
TP_COLORAPP_WBCAM;BB [RT+CAT02] + [sortie]
TP_COLORAPP_WBRT;BB [RT] + [sortie]
+TP_COLORAPP_CURVEEDITOR1;Courbe tonale 1
+TP_COLORAPP_CURVEEDITOR2;Courbe tonale 2
+TP_COLORAPP_CURVEEDITOR3;Courbes chroma
+TP_COLORAPP_TCMODE_CHROMA;Chroma
+TP_COLORAPP_TCMODE_SATUR;Saturation
+TP_COLORAPP_TCMODE_COLORF;Niveau de couleurs
+TP_COLORAPP_TCMODE_BRIGHTNESS;Brillance
+TP_COLORAPP_TCMODE_LIGHTNESS;Luminosité
+TP_COLORAPP_TCMODE_LABEL1;Courbe mode 1
+TP_COLORAPP_TCMODE_LABEL2;Courbe mode 2
+TP_COLORAPP_TCMODE_LABEL3;Courbe chroma mode
+TP_COLORAPP_CURVEEDITOR2_TOOLTIP;usage similaire aux courbes tonales exposition
+TP_COLORAPP_CURVEEDITOR3_TOOLTIP;Vous pouvez choisir entre chroma -saturation- niveau couleurs
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 f8f83849f..95ca96208 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -416,6 +416,12 @@ HISTORY_MSG_189;CAM02 - Contrast (Q)
HISTORY_MSG_190;CAM02 - Saturation (S)
HISTORY_MSG_191;CAM02 - Colorfullness (M)
HISTORY_MSG_192;CAM02 - Hue (angle)
+HISTORY_MSG_193;CAM02 - Tone curve 1
+HISTORY_MSG_194;CAM02 - Tone curve 2
+HISTORY_MSG_195;CAM02 - Tone curve
+HISTORY_MSG_196;CAM02 - Tone curve 2
+HISTORY_MSG_197;CAM02 - Color curve
+HISTORY_MSG_198;CAM02 - Color curve
HISTORY_NEWSNAPSHOTAS;As...
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
@@ -667,12 +673,15 @@ PREFERENCES_CACHESTRAT;Cache Strategy
PREFERENCES_CACHETHUMBFORM;Cache thumbnail format
PREFERENCES_CACHETHUMBHEIGHT;Maximal thumbnail height
PREFERENCES_CLIPPINGIND;Clipping Indication
-PREFERENCES_VIEW;Output device's white balance setting (monitor, TV, projector,...)
+PREFERENCES_VIEW;Output device's white balance setting (monitor, TV, projector,viewing...)
PREFERENCES_D65;6500K
PREFERENCES_D60;6000K
PREFERENCES_D55;5500K
PREFERENCES_D50;5000K
PREFERENCES_BLACKBODY;Tungsten
+PREFERENCES_FLUOF2;Fluorescent F2
+PREFERENCES_FLUOF7;Fluorescent F7
+PREFERENCES_FLUOF11;Fluorescent F11
PREFERENCES_GREY;Output device's Yb luminance (%)
PREFERENCES_GREY05;Yb=05 CIE L#30
PREFERENCES_GREY10;Yb=10 CIE L#40
@@ -887,7 +896,7 @@ TP_COLORAPP_ADAPTVIEWING_TOOLTIP;Absolute luminance of the viewing environnement
TP_COLORAPP_ALGO;Algorithm
TP_COLORAPP_ALGO_ALL;All
TP_COLORAPP_ALGO_JC;Lightness + Chroma (JC)
-TP_COLORAPP_ALGO_JS;Lightnes + Saturation (JS)
+TP_COLORAPP_ALGO_JS;Lightness + Saturation (JS)
TP_COLORAPP_ALGO_QM;Brightness + Colorfullness (QM)
TP_COLORAPP_ALGO_TOOLTIP;Lets you chose between parameters subsets or all parameters
TP_COLORAPP_BRIGHT;Brightness (Q)
@@ -907,8 +916,8 @@ TP_COLORAPP_DEGREE_TOOLTIP;Amount of CIE Chromatic Adaptation Transform 2002\nIf
TP_COLORAPP_EQUAL;Equal
TP_COLORAPP_GAMUT;Gamut control (Lab & CIECAM)
TP_COLORAPP_GAMUT_TOOLTIP;Allow gamut control in Lab mode
-TP_COLORAPP_HUE;Hue (H)
-TP_COLORAPP_HUE_TOOLTIP;Hue (H) - angle between 0° and 360°
+TP_COLORAPP_HUE;Hue (h)
+TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0° and 360°
TP_COLORAPP_LABEL;CIE Color Appearance Model 2002
TP_COLORAPP_LABEL_CAM02;Modifying image with CIECAM
TP_COLORAPP_LABEL_SCENE;Scene conditions
@@ -917,8 +926,8 @@ TP_COLORAPP_LIGHT;Lightness (J)
TP_COLORAPP_LIGHT_TOOLTIP;Lightness in CIECAM02 is different from Lab and RGB
TP_COLORAPP_MODEL;White-Point Model
TP_COLORAPP_MODEL_TOOLTIP;WB [RT] + [output]:\nRT's WB is used for the scene, CIECAM is set to D50, the output device's white uses the value set in Preferences\n\nWB [RT+CAT02] + [output]:\nRT's WB settings are used by CAT02 and the output device's white uses the value set in Preferences
-TP_COLORAPP_RSTPRO;Red & skin tones protection (C)
-TP_COLORAPP_RSTPRO_TOOLTIP;Red and skin tones protection by the (C) slider
+TP_COLORAPP_RSTPRO;Red & skin tones protection
+TP_COLORAPP_RSTPRO_TOOLTIP;Red and skin tones protection (sliders and curves)
TP_COLORAPP_SURROUND;Surround
TP_COLORAPP_SURROUND_AVER;Average
TP_COLORAPP_SURROUND_DARK;Dark
@@ -929,6 +938,19 @@ TP_COLORAPP_SURSOURCE;Dark surround
TP_COLORAPP_SURSOURCE_TOOLTIP;Can be used if source image has a dark border
TP_COLORAPP_WBCAM;WB [RT+CAT02] + [output]
TP_COLORAPP_WBRT;WB [RT] + [output]
+TP_COLORAPP_CURVEEDITOR1;Tone curve 1
+TP_COLORAPP_CURVEEDITOR2;Tone curve 2
+TP_COLORAPP_CURVEEDITOR3;Chroma curve
+TP_COLORAPP_TCMODE_CHROMA;Chroma
+TP_COLORAPP_TCMODE_SATUR;Saturation
+TP_COLORAPP_TCMODE_COLORF;Colorfullness
+TP_COLORAPP_TCMODE_BRIGHTNESS;Brightness
+TP_COLORAPP_TCMODE_LIGHTNESS;Lightness
+TP_COLORAPP_TCMODE_LABEL1;Curve mode 1
+TP_COLORAPP_TCMODE_LABEL2;Curve mode 2
+TP_COLORAPP_TCMODE_LABEL3;Curve chroma mode
+TP_COLORAPP_CURVEEDITOR2_TOOLTIP;Same usage as exposure tone curve
+TP_COLORAPP_CURVEEDITOR3_TOOLTIP;You can select between chroma saturation colorfullness
TP_CROP_FIXRATIO;Fix ratio:
TP_CROP_GTDIAGONALS;Rule of Diagonals
TP_CROP_GTEPASSPORT;Biometric Passport
diff --git a/rtdata/profiles/BW-1.pp3 b/rtdata/profiles/BW-1.pp3
index 96d721cf8..ffeab7fd0 100644
--- a/rtdata/profiles/BW-1.pp3
+++ b/rtdata/profiles/BW-1.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/BW-2.pp3 b/rtdata/profiles/BW-2.pp3
index 765f106f4..279125605 100644
--- a/rtdata/profiles/BW-2.pp3
+++ b/rtdata/profiles/BW-2.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/BW-3.pp3 b/rtdata/profiles/BW-3.pp3
index f8cb16b67..86eaed06e 100644
--- a/rtdata/profiles/BW-3.pp3
+++ b/rtdata/profiles/BW-3.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/BW-4.pp3 b/rtdata/profiles/BW-4.pp3
index 42c8aefe8..35d552397 100644
--- a/rtdata/profiles/BW-4.pp3
+++ b/rtdata/profiles/BW-4.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Default-ISO-High.pp3 b/rtdata/profiles/Default-ISO-High.pp3
index d2462794b..0d12bcd76 100644
--- a/rtdata/profiles/Default-ISO-High.pp3
+++ b/rtdata/profiles/Default-ISO-High.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Default-ISO-Medium.pp3 b/rtdata/profiles/Default-ISO-Medium.pp3
index 694212683..791f37c84 100644
--- a/rtdata/profiles/Default-ISO-Medium.pp3
+++ b/rtdata/profiles/Default-ISO-Medium.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Default.pp3 b/rtdata/profiles/Default.pp3
index 36ac1bbb9..8c77e006a 100644
--- a/rtdata/profiles/Default.pp3
+++ b/rtdata/profiles/Default.pp3
@@ -106,7 +106,14 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
+
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Highkey-1.pp3 b/rtdata/profiles/Highkey-1.pp3
index cd8332ccd..172054215 100644
--- a/rtdata/profiles/Highkey-1.pp3
+++ b/rtdata/profiles/Highkey-1.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Natural-1.pp3 b/rtdata/profiles/Natural-1.pp3
index 08521855a..571a0aa75 100644
--- a/rtdata/profiles/Natural-1.pp3
+++ b/rtdata/profiles/Natural-1.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Natural-2.pp3 b/rtdata/profiles/Natural-2.pp3
index 866fc0d1c..6af558fd3 100644
--- a/rtdata/profiles/Natural-2.pp3
+++ b/rtdata/profiles/Natural-2.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Neutral.pp3 b/rtdata/profiles/Neutral.pp3
index 0cf2ad992..a72420069 100644
--- a/rtdata/profiles/Neutral.pp3
+++ b/rtdata/profiles/Neutral.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Punchy-1.pp3 b/rtdata/profiles/Punchy-1.pp3
index bc051e165..269572028 100644
--- a/rtdata/profiles/Punchy-1.pp3
+++ b/rtdata/profiles/Punchy-1.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtdata/profiles/Punchy-2.pp3 b/rtdata/profiles/Punchy-2.pp3
index 678f4d18a..5dfb270a9 100644
--- a/rtdata/profiles/Punchy-2.pp3
+++ b/rtdata/profiles/Punchy-2.pp3
@@ -106,7 +106,13 @@ H-Hue=0
RSTProtection=0
AdaptScene=2000
SurrSource=false
-Gamut=false
+Gamut=true
+CurveMode=Lightness
+CurveMode2=Lightness
+CurveMode3=Chroma
+Curve=0;
+Curve2=0;
+Curve3=0;
[Impulse Denoising]
Enabled=false
diff --git a/rtengine/color.cc b/rtengine/color.cc
index c071fa87b..4db2bcce8 100644
--- a/rtengine/color.cc
+++ b/rtengine/color.cc
@@ -48,7 +48,7 @@ namespace rtengine {
const float Color::D50z=0.82521;
const double Color::u0=4.0*D50x/(D50x+15+3*D50z);
const double Color::v0=9.0/(D50x+15+3*D50z);
- const double Color::epskap=8.0;
+ const double Color::epskap=8.0;
/*
* Munsell Lch correction
* Copyright (c) 2011 Jacques Desmis
@@ -201,9 +201,9 @@ namespace rtengine {
r = g = b = 65535.0f * l; // achromatic
else {
double m2;
- double h_ = double(h);
+ double h_ = double(h);
double s_ = double(s);
- double l_ = double(l);
+ double l_ = double(l);
if (l <= 0.5f)
m2 = l_ * (1.0 + s_);
@@ -520,33 +520,76 @@ namespace rtengine {
Z = (12 - 3*u - 20*v)*Y/(4*v);
}
+ void Color::skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s)
+ {
+ float factorskin, factorsat,factor, factorskinext, interm;
+ float scale = 100.0f/100.1f;//reduction in normal zone
+ float scaleext=1.0f;//reduction in transition zone
+ float protect_redh;
+ float deltaHH=0.3f;//HH value transition : I have choice 0.3 radians
+ float HH;
+ bool doskin=false;
+ //rough correspondence between h (JC) and H (lab) that has relatively little importance because transitions that blur the correspondence is not linear
+ if ((float)h>8.6f && (float)h<=74.f ) {HH=(1.15f/65.4f)*(float)h-0.0012f; doskin=true;}//H > 0.15 H<1.3
+ else if((float)h>0.f && (float)h<=8.6f ) {HH=(0.19f/8.6f )*(float)h-0.04f; doskin=true;}//H>-0.04 H < 0.15
+ else if((float)h>355.f && (float)h<=360.f) {HH=(0.11f/5.0f )*(float)h-7.96f; doskin=true;}//H>-0.15 <-0.04
+ else if((float)h>74.f && (float)h<95.f ) {HH=(0.30f/21.0f)*(float)h+0.24285f; doskin=true;}//H>1.3 H<1.6
+
+ if(doskin)
+ {
+ float chromapro=sres/Sp;
+ if(sk==1){//in C mode to adapt dred to J
+ if (J<16.0) dred = 40.0f;
+ else if(J<22.0) dred = (4.1666f)*(float)J -26.6f;
+ else if(J<60.0) dred = 55.0f;
+ else if(J<70.0) dred = -1.5f*(float)J +145.0f;
+ else dred = 40.0f;
+ }
+ if(chromapro>0.0) Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//Scale factor
+ if(chromapro>1.0) {interm=(chromapro-1.0f)*100.0f;
+ factorskin= 1.0f+(interm*scale)/100.0f;
+ factorskinext=1.0f+(interm*scaleext)/100.0f;}
+ else {
+ factorskin= chromapro ;
+ factorskinext= chromapro ;
+ }
+ factorsat=chromapro;
+ factor=factorsat;
+ Color::transitred ( HH, s, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition
+ s*=factor;
+ }
+ else s=ko*sres;
+
+ }
+
+
void Color::scalered ( float rstprotection, float param, float limit, float HH, float deltaHH, float &scale,float &scaleext)
- {
- if(rstprotection<99.9999) {
- if(param > limit)
- scale = rstprotection/100.1f;
- if((HH< (1.3f+deltaHH) && HH >=1.3f))
- scaleext=HH*(1.0f-scale)/deltaHH + 1.0f - (1.3f+deltaHH)*(1.0f-scale)/deltaHH; //transition for Hue (red - yellow)
- else if((HH< 0.15f && HH >(0.15f-deltaHH)))
- scaleext=HH*(scale-1.0f)/deltaHH + 1.0f - (0.15f-deltaHH)*(scale-1.0f)/deltaHH; //transition for hue (red purple)
- }
+ {
+ if(rstprotection<99.9999) {
+ if(param > limit)
+ scale = rstprotection/100.1f;
+ if((HH< (1.3f+deltaHH) && HH >=1.3f))
+ scaleext=HH*(1.0f-scale)/deltaHH + 1.0f - (1.3f+deltaHH)*(1.0f-scale)/deltaHH; //transition for Hue (red - yellow)
+ else if((HH< 0.15f && HH >(0.15f-deltaHH)))
+ scaleext=HH*(scale-1.0f)/deltaHH + 1.0f - (0.15f-deltaHH)*(scale-1.0f)/deltaHH; //transition for hue (red purple)
+ }
}
void Color::transitred (float HH, float Chprov1, float dred, float factorskin, float protect_red, float factorskinext, float deltaHH, float factorsat, float &factor)
{
- if(HH>=0.15f && HH<1.3f) {
- if (Chprov1(0.15f-deltaHH) || HH<(1.3f+deltaHH) ) {
- if (Chprov1 < dred)
- factor = factorskinext;// C=dred=55 => real max of skin tones
- else if (Chprov1 < (dred+protect_red))// transition
- factor = (factorsat-factorskinext)/protect_red*Chprov1+factorsat-(dred+protect_red)*(factorsat-factorskinext)/protect_red;
- }
+ if(HH>=0.15f && HH<1.3f) {
+ if (Chprov1(0.15f-deltaHH) || HH<(1.3f+deltaHH) ) {
+ if (Chprov1 < dred)
+ factor = factorskinext;// C=dred=55 => real max of skin tones
+ else if (Chprov1 < (dred+protect_red))// transition
+ factor = (factorsat-factorskinext)/protect_red*Chprov1+factorsat-(dred+protect_red)*(factorsat-factorskinext)/protect_red;
+ }
}
/*
@@ -588,17 +631,17 @@ namespace rtengine {
correctL=false;
MunsellLch (Lprov1, HH,Chprov1, CC, correctionHue, zo, correctionHueLum, correctL); //munsell chroma correction
#ifdef _DEBUG
- float absCorrectionHue = fabs(correctionHue);
+ float absCorrectionHue = fabs(correctionHue);
if(correctionHue !=0.0) {
- int idx=zo-1;
+ int idx=zo-1;
#pragma omp critical (maxdhue)
{
- munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue);
+munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue);
}
}
if(absCorrectionHue > 0.45)
#pragma omp atomic
- munsDbgInfo->depass++; //verify if no bug in calculation
+ munsDbgInfo->depass++; //verify if no bug in calculation
#endif
correctionHuechroma=correctionHue; //preserve
if(lumaMuns) {
@@ -624,17 +667,17 @@ namespace rtengine {
if(contin1==true && contin2==true)
correctlum=correctlumprov2-correctlumprov;
#ifdef _DEBUG
- float absCorrectLum = fabs(correctlum);
+ float absCorrectLum = fabs(correctlum);
if(correctlum !=0.0) {
- int idx=zo-1;
+ int idx=zo-1;
#pragma omp critical (maxdhuelum)
{
- munsDbgInfo->maxdhuelum[idx] = MAX(munsDbgInfo->maxdhuelum[idx],absCorrectLum);
+ munsDbgInfo->maxdhuelum[idx] = MAX(munsDbgInfo->maxdhuelum[idx],absCorrectLum);
}
}
if(absCorrectLum > 0.35)
#pragma omp atomic
- munsDbgInfo->depassLum++; //verify if no bug in calculation
+ munsDbgInfo->depassLum++; //verify if no bug in calculation
#endif
}
}
@@ -675,7 +718,7 @@ namespace rtengine {
#endif
{
const float ClipLevel = 65535.0f;
- bool inGamut;
+ bool inGamut;
#ifdef _DEBUG
neg=false, more_rgb=false;
#endif
@@ -694,7 +737,7 @@ namespace rtengine {
float x_ = 65535.0f * f2xyz(fx)*D50x;
// float y_ = 65535.0f * f2xyz(fy);
float z_ = 65535.0f * f2xyz(fz)*D50z;
- float y_=(Lprov1>epskap) ? 65535.0*fy*fy*fy : 65535.0*Lprov1/kappa;
+ float y_=(Lprov1>epskap) ? 65535.0*fy*fy*fy : 65535.0*Lprov1/kappa;
xyz2rgb(x_,y_,z_,R,G,B,wip);
@@ -706,9 +749,9 @@ namespace rtengine {
if (Lprov1 < 0.01f) Lprov1 = 0.01f;
Chprov1 *= higherCoef; // decrease the chromaticity value
if (Chprov1 <= 3.0f) Lprov1 += lowerCoef;
- inGamut = false;
+ inGamut = false;
} else
- // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut
+ // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut
if (!isHLEnabled && (R>ClipLevel || G>ClipLevel || B>ClipLevel)) {
#ifdef _DEBUG
more_rgb=true;
@@ -716,7 +759,7 @@ namespace rtengine {
if (Lprov1 > 99.999f) Lprov1 = 99.98f;
Chprov1 *= higherCoef;
if (Chprov1 <= 3.0f) Lprov1 -= lowerCoef;
- inGamut = false;
+ inGamut = false;
}
}
while (!inGamut);
@@ -752,7 +795,7 @@ namespace rtengine {
int negat=0, moreRGB=0;
MunsellDebugInfo* MunsDebugInfo=NULL;
if (corMunsell)
- MunsDebugInfo = new MunsellDebugInfo();
+ MunsDebugInfo = new MunsellDebugInfo();
#pragma omp parallel default(shared) firstprivate(MunsDebugInfo) reduction(+: negat, moreRGB) if (multiThread)
#else
@@ -822,11 +865,11 @@ namespace rtengine {
#ifdef _DEBUG
t2e.set();
if (settings->verbose) {
- printf("Color::LabGamutMunsell (correction performed in %d usec):\n", t2e.etime(t1e));
+ printf("Color::LabGamutMunsell (correction performed in %d usec):\n", t2e.etime(t1e));
printf(" Gamut : G1negat=%iiter G165535=%iiter \n",negat,moreRGB);
if (MunsDebugInfo) {
- printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass);
- printf(" Munsell luminance : MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhuelum[0] ,MunsDebugInfo->maxdhuelum[1], MunsDebugInfo->maxdhuelum[2], MunsDebugInfo->maxdhuelum[3], MunsDebugInfo->depassLum);
+ printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass);
+ printf(" Munsell luminance : MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhuelum[0] ,MunsDebugInfo->maxdhuelum[1], MunsDebugInfo->maxdhuelum[2], MunsDebugInfo->maxdhuelum[3], MunsDebugInfo->depassLum);
}
else {
printf(" Munsell correction wasn't requested\n");
diff --git a/rtengine/color.h b/rtengine/color.h
index e3834a7cb..b0836f1a2 100644
--- a/rtengine/color.h
+++ b/rtengine/color.h
@@ -164,6 +164,7 @@ public:
// end Munsell
static void scalered ( float rstprotection, float param, float limit, float HH, float deltaHH, float &scale, float &scaleext);
static void transitred (float HH, float Chprov1, float dred, float factorskin, float protect_red, float factorskinext, float deltaHH, float factorsat, float &factor);
+ static void skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s);
//void gamutmap(LabImage* );
static void gamutmap(float &X, float &Y, float &Z, const double p[3][3]);
diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc
index 27221eeeb..510ba86ab 100644
--- a/rtengine/colortemp.cc
+++ b/rtengine/colortemp.cc
@@ -893,15 +893,15 @@ int ColorTemp::XYZtoCorColorTemp(double x0, double y0, double z0, double &temp)
return 0; /* success */
}
-void ColorTemp::curvecolor(double satind, double satval, double &sres, double parsat){
- if (satind >=0.0) {
- sres = (1.-(satind)/100.)*satval+(satind)/100.*(1.-SQR(SQR(1.-min(satval,1.0))));
- if (sres>parsat) sres=parsat;
- if (sres<0.) sres=0.;
- } else {
- if (satind < -0.1)
- sres = satval*(1.+(satind)/100.);
- }
+void ColorTemp::curvecolor(double satind, double satval, double &sres, double parsat) {
+ if (satind >=0.0) {
+ sres = (1.-(satind)/100.)*satval+(satind)/100.*(1.-SQR(SQR(1.-min(satval,1.0))));
+ if (sres>parsat) sres=parsat;
+ if (sres<0.) sres=0.;
+ } else {
+ if (satind < -0.1)
+ sres = satval*(1.+(satind)/100.);
+ }
}
@@ -1002,374 +1002,6 @@ void ColorTemp::curveJ (double br, double contr, int db, LUTf & outCurve, LUTu &
for (int i=0; i<(db*32768); i++) outCurve[i] = db*32768.0*dcurve[i];
}
-
-// * Copyright (c) October 2012 Jacques Desmis
-void ColorTemp::ciecam_02 (LabImage* lab, const ProcParams* params )
-{
-if(params->colorappearance.enabled) {
-
-#ifdef _DEBUG
- MyTime t1e,t2e;
- t1e.set();
-#endif
-
- int width = lab->W, height = lab->H;
- double Yw;
- Yw=1.0;
- double Xw, Zw;
- double f,c,nc,yb,la,xw,yw,zw,f2,c2,nc2,yb2,la2;
- double z,fl,n,nbb,ncb,d,aw;
- double xwd,ywd,zwd;
- int alg=0;
- LUTf bright_curve (65536,0);//init curve
- LUTf bright_curveQ (65536,0);//init curve
-
- LUTu hist16 (65536);
- LUTu hist16Q (65536);
- float koef=1.0f;//rough correspondence between L and J
- hist16.clear();hist16Q.clear();
- float sum=0.f;
- float mean;
- for (int i=0; iL[i][j])/327.68f)>95.) koef=1.f;
- else if(((lab->L[i][j])/327.68f)>85.) koef=0.97f;
- else if(((lab->L[i][j])/327.68f)>80.) koef=0.93f;
- else if(((lab->L[i][j])/327.68f)>70.) koef=0.87f;
- else if(((lab->L[i][j])/327.68f)>60.) koef=0.85f;
- else if(((lab->L[i][j])/327.68f)>50.) koef=0.8f;
- else if(((lab->L[i][j])/327.68f)>40.) koef=0.75f;
- else if(((lab->L[i][j])/327.68f)>30.) koef=0.7f;
- else if(((lab->L[i][j])/327.68f)>20.) koef=0.7f;
- else if(((lab->L[i][j])/327.68f)>10.) koef=0.9f;
- else if(((lab->L[i][j])/327.68f)>0.) koef=1.0f;
-
- hist16[CLIP((int)((koef*lab->L[i][j])))]++;//evaluate histogram luminance L # J
- sum+=koef*lab->L[i][j];//evaluate mean J to calcualte Yb
- hist16Q[CLIP((int) (32768.f*sqrt((koef*(lab->L[i][j]))/32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L
- }
- mean=(sum/(height*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone
- if (mean<15.f) yb=3.0;
- else if(mean<30.f) yb=5.0;
- else if(mean<40.f) yb=10.0;
- else if(mean<45.f) yb=15.0;
- else if(mean<50.f) yb=18.0;
- else if(mean<55.f) yb=23.0;
- else if(mean<60.f) yb=30.0;
- else if(mean<70.f) yb=40.0;
- else if(mean<80.f) yb=60.0;
- else if(mean<90.f) yb=80.0;
- else yb=90.0;
-
- ColorTemp::temp2mulxyz (params->wb.temperature, params->wb.green, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB
- //viewing condition for surround
- if(params->colorappearance.surround=="Average") { f = 1.00; c = 0.69; nc = 1.00;f2=1.0,c2=0.69,nc2=1.0;}
- else if(params->colorappearance.surround=="Dim"){ f2 = 0.9; c2 = 0.59; nc2 = 0.9;f=1.0,c=0.69,nc=1.0;}
- else if(params->colorappearance.surround=="Dark"){f2 = 0.8; c2 = 0.525;nc2 = 0.8;f=1.0,c=0.69,nc=1.0;}
- else if(params->colorappearance.surround=="ExtremelyDark"){f2 = 0.8; c2 = 0.41;nc2 = 0.8;f=1.0,c=0.69,nc=1.0;}
-
- //scene condition for surround
- if(params->colorappearance.surrsource) {f = 0.85; c = 0.55; nc = 0.85;}// if user => source image has surround very dark
- //with which algorithme
- if (params->colorappearance.algo=="JC") alg=0;
- else if(params->colorappearance.algo=="JS") alg=1;
- else if(params->colorappearance.algo=="QM") alg=2;
- else if(params->colorappearance.algo=="ALL") alg=3;
- //settings white point of output device
- if (settings->viewingdevice==0) {xwd= 96.42; ywd=100.0; zwd= 82.52;}//5000K
- else if(settings->viewingdevice==1) {xwd= 95.68; ywd=100.0; zwd= 92.15;}//5500
- else if(settings->viewingdevice==2) {xwd= 95.24; ywd=100.0; zwd=100.81;}//6000
- else if(settings->viewingdevice==3) {xwd= 95.04; ywd=100.0; zwd=108.88;}//6500
- else if(settings->viewingdevice==4) {xwd=109.85; ywd=100.0; zwd= 35.58;}//tungsten
- //settings mean Luminance Y of output device
- if(settings->viewingdevicegrey==0) {yb2=5.0;}
- else if(settings->viewingdevicegrey==1) {yb2=10.0;}
- else if(settings->viewingdevicegrey==2) {yb2=15.0;}
- else if(settings->viewingdevicegrey==3) {yb2=18.0;}
- else if(settings->viewingdevicegrey==4) {yb2=23.0;}
- else if(settings->viewingdevicegrey==5) {yb2=30.0;}
- else if(settings->viewingdevicegrey==6) {yb2=40.0;}
-
- //La and la2 = ambiant luminosity scene and viewing
- la=double(params->colorappearance.adapscen);
- la2=double(params->colorappearance.adaplum);
-
- // level of adaptation
- double deg=(params->colorappearance.degree)/100.0;
- double pilot=params->colorappearance.autodegree ? 2.0 : deg;
-
- //algoritm's params
- float jli=params->colorappearance.jlight;
- float chr=params->colorappearance.chroma;
- float contra=params->colorappearance.contrast;
- float qbri=params->colorappearance.qbright;
- float schr=params->colorappearance.schroma;
- float mchr=params->colorappearance.mchroma;
- float qcontra=params->colorappearance.qcontrast;
- float hue=params->colorappearance.colorh;
- double rstprotection = 100.-params->colorappearance.rstprotection;
- //evaluate lightness, contrast
- curveJ (jli, contra, 1, bright_curve, hist16);//lightness and contrast J
- curveJ (qbri, qcontra, 1, bright_curveQ, hist16Q);//brightness and contrast Q
- int gamu=0;
- bool highlight = params->hlrecovery.enabled; //Get the value if "highlight reconstruction" is activated
-
- if(params->colorappearance.gamut==true) gamu=1;//enabled gamut control
- xw=100.0*Xw;
- yw=100.0*Yw;
- zw=100.0*Zw;
- double xw1,yw1,zw1,xw2,yw2,zw2;
- // settings of WB: scene and viewing
- if(params->colorappearance.wbmodel=="RawT") {xw1=96.46;yw1=100.0;zw1=82.445;xw2=xwd;yw2=ywd;zw2=zwd;} //use RT WB; CAT 02 is used for output device (see prefreneces)
- else if(params->colorappearance.wbmodel=="RawTCAT02") {xw1=xw;yw1=yw;zw1=zw;xw2=xwd;yw2=ywd;zw2=zwd;} // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences
-
- /* double maxj=-100.0;
- double minj= 500.0;
- double minc=500.0;
- double maxc=-100.0;
-*/
- bool doneinit=true;
- bool doneinit2=true;
-#ifndef _DEBUG
-#pragma omp parallel default(shared) firstprivate(lab,xw1,xw2,yw1,yw2,zw1,zw2,pilot,jli,chr,yb,la,fl,nc,f,c, height,width,doneinit,doneinit2, nc2,f2,c2, alg, gamu, highlight, rstprotection)
-#endif
-{
- 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]}
- };
-
-#ifndef _DEBUG
-#pragma omp for schedule(dynamic, 10)
-#endif
- for (int i=0; iL[i][j];
- float a=lab->a[i][j];
- float b=lab->b[i][j];
- float x1,y1,z1;
- double x,y,z;
- //convert Lab => XYZ
- Color::Lab2XYZ(L, a, b, x1, y1, z1);
- double J, C, h, Q, M, s, aw, fl, wh;
-
- x=(double)x1/655.35;
- y=(double)y1/655.35;
- z=(double)z1/655.35;
- //process source==> normal
- ColorTemp::xyz2jchqms_ciecam02( J, C, h,
- Q, M, s, aw, fl, wh,
- x, y, z,
- xw1, yw1, zw1,
- yb, la,
- f, c, nc, pilot, doneinit, gamu );
-
- if(alg==0) {
- //lightness J + chroma C
- J=(bright_curve[(float)(J*327.68)])/327.68;//ligthness CIECAM02 + contrast
- double Cp,sres;
- Cp=C/100.0;
- double parsat=1.8;//parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation : for not)
- curvecolor(chr, Cp , sres, parsat);
- float factorskin, factorsat, factor, factorskinext, interm;
- float scale = 100.0f/100.1f;//reduction in normal zone
- float scaleext=1.0f;//reduction in transition zone
- float protect_red,protect_redh;
- float deltaHH=0.3f;//HH value transition : I have choice 0.3 radians
- float HH;
- bool doskin=false;
- //rough correspondence between h (JC) and H (lab) that has relatively little importance because of transitions that blur the correspondence is not linear
- if((float)h>8.6f && (float)h<=74.f) {HH=(1.15f/65.4f)*(float)h-0.0012f;doskin=true;}//H > 0.15 H<1.3
- else if((float)h>0.f && (float)h<=8.6f) {HH=(0.19f/8.6f)*(float)h-0.04f;doskin=true;}//H>-0.04 H < 0.15
- else if((float)h>355.f && (float)h<=360.f) {HH=(0.11f/5.f)*(float)h-7.96f;doskin=true;}//H>-0.15 <-0.04
- else if((float)h>74.f && (float)h<95.f) {HH=(0.3f/21.f)*(float)h+0.24285f;doskin=true;}//H>1.3 H<1.6
- if(doskin){
- float chromapro=sres/Cp;
- float dred=55.0f;//Skin max
- if (J<16.0) dred = 40.0f;
- else if(J<22.0) dred = (4.1666f)*(float)J -26.6f;
- else if(J<60.0) dred = 55.0f;
- else if(J<70.0) dred = -1.5f*(float)J +145.0f;
- else dred = 40.0f;
-
- float protect_red=30.f; //==> 90=60+30 transition
- if(chromapro>0.0) Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//Scale factor
- if(chromapro>1.0) {interm=(chromapro-1.0f)*100.0f;
- factorskin= 1.0f+(interm*scale)/100.0f;
- factorskinext=1.0f+(interm*scaleext)/100.0f;}
- else {
- factorskin= chromapro ;
- factorskinext= chromapro ;
- }
- factorsat=chromapro;
- factor=factorsat;
- Color::transitred ( HH, C, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition
- C*=factor;
- }
- else C=100.0*sres;
- }
- else if(alg==2) {
- //Brightness Q Colorfullness M
- double coef=32760./wh;
- Q=(bright_curveQ[(float)(Q*coef)])/coef;//brightness and contrast
- double Mp, sres;
- double coe=pow(fl,0.25);
- Mp=M/100.0;
- double parsat=2.5;
- curvecolor(mchr, Mp , sres, parsat);
- M=100.0*sres;
- J=(100.0* Q*Q) /(wh*wh);
- C= M/coe;
- }
- else if(alg==1) {
- // Lightness saturation
- J=(bright_curve[(float)(J*327.68)])/327.68;//ligthness CIECAM02 + contrast
- double sres;
- double Sp=s/100.0;
- double parsat=1.5;
- curvecolor(schr, Sp , sres, parsat);
- s=100.*sres;
- double Q1;
- Q1= ( 4.0 / c ) * sqrt( J / 100.0 ) * ( aw + 4.0 ) ;
- C=(s*s*Q1)/(10000.0);
- }
- else if(alg==3) {
- double coef=32760./wh;
- Q=(bright_curveQ[(float)(Q*coef)])/coef;//brightness and contrast
- double Mp, sres;
- double coe=pow(fl,0.25);
- Mp=M/100.0;
- double parsat=2.5;
- if(mchr==-100.0) mchr=-99.8 ;
- if(mchr==100.0) mchr=99.9;
- curvecolor(mchr, Mp , sres, parsat);//colorfullness
- M=100.0*sres;
- J=(100.0* Q*Q) /(wh*wh);
- C= M/coe;
- s = 100.0 * sqrt( M / Q );
- J=(bright_curve[(float)(J*327.68)])/327.68;//ligthness CIECAM02 + contrast
- double Cp;
- double Sp=s/100.0;
- parsat=1.5;
- if(schr==-100.0) schr=-99.;
- if(schr==100.0) schr=98.;
- curvecolor(schr, Sp , sres, parsat); //saturation
- s=100.*sres;
- double Q1;
- Q1= ( 4.0 / c ) * sqrt( J / 100.0 ) * ( aw + 4.0 ) ;
- C=(s*s*Q1)/(10000.0);
- Cp=C/100.0;
- parsat=1.8;//parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation : for not)
- curvecolor(chr, Cp , sres, parsat); //chroma
- float factorskin, factorsat, factor, factorskinext, interm;
- float scale = 100.0f/100.1f;//reduction in normal zone
- float scaleext=1.0f;//reduction in transition zone
- float protect_red,protect_redh;
- float deltaHH=0.3f;//HH value transition : I have choice 0.3 radians
- float HH;
- bool doskin=false;
- //rough correspondence between h (JC) and H (lab) that has relatively little importance because of transitions that blur the correspondence is not linear
- if((float)h>8.6f && (float)h<=74.f) {HH=(1.15f/65.4f)*(float)h-0.0012f;doskin=true;}//H > 0.15 H<1.3
- else if((float)h>0.f && (float)h<=8.6f) {HH=(0.19f/8.6f)*(float)h-0.04f;doskin=true;}//H>-0.04 H < 0.15
- else if((float)h>355.f && (float)h<=360.f) {HH=(0.11f/5.f)*(float)h-7.96f;doskin=true;}//H>-0.15 <-0.04
- else if((float)h>74.f && (float)h<95.f) {HH=(0.3f/21.f)*(float)h+0.24285f;doskin=true;}//H>1.3 H<1.6
- if(doskin){
- float chromapro=sres/Cp;
- float dred=55.0f;//Skin max
- if (J<16.0) dred = 40.0f;
- else if(J<22.0) dred = (4.1666f)*(float)J -26.6f;
- else if(J<60.0) dred = 55.0f;
- else if(J<70.0) dred = -1.5f*(float)J +145.0f;
- else dred = 40.0f;
-
- float protect_red=30.f; //==> 90=60+30 transition
- if(chromapro>0.0) Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//Scale factor
- if(chromapro>1.0) {
- interm=(chromapro-1.0f)*100.0f;
- factorskin= 1.0f+(interm*scale)/100.0f;
- factorskinext=1.0f+(interm*scaleext)/100.0f;
- }
- else {
- factorskin= chromapro ;
- factorskinext= chromapro ;
- }
- factorsat=chromapro;
- factor=factorsat;
- Color::transitred ( HH, C, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition
- C*=factor;
- }
- else C=100.0*sres;
- h=h+hue;if( h < 0.0 ) h += 360.0;//hue
- }
- /*
- if(J>maxj) maxj=J;
- if(C>maxc) maxc=C;
- if(Jmaxj) maxj=J;
- if(C>maxc) maxc=C;
- if(J viewing
- ColorTemp::jch2xyz_ciecam02( xx, yy, zz,
- J, C, h,
- xw2, yw2, zw2,
- yb2, la2,
- f2, c2, nc2, doneinit2, gamu);
- x=(float)xx*655.35;
- y=(float)yy*655.35;
- z=(float)zz*655.35;
- float Ll,aa,bb;
- //convert xyz=>lab
- Color::XYZ2Lab(x, y, z, Ll, aa, bb);
- lab->L[i][j]=Ll;
- lab->a[i][j]=aa;
- lab->b[i][j]=bb;
-
- // gamut control in Lab mode; I must study how to do with cIECAM only
- if(gamu==1) {
- float R,G,B;
- float HH, Lprov1, Chprov1;
- Lprov1=lab->L[i][j]/327.68f;
- Chprov1=sqrt(SQR(lab->a[i][j]/327.68f) + SQR(lab->b[i][j]/327.68f));
- HH=atan2(lab->b[i][j],lab->a[i][j]);
-
-#ifdef _DEBUG
- bool neg=false;
- bool more_rgb=false;
- //gamut control : Lab values are in gamut
- Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb);
-#else
- //gamut control : Lab values are in gamut
- Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f);
-#endif
-
- lab->L[i][j]=Lprov1*327.68f;
- lab->a[i][j]=327.68f*Chprov1*cos(HH);
- lab->b[i][j]=327.68f*Chprov1*sin(HH);
- }
- }
- }
- // End of parallelization
-
-#ifdef _DEBUG
- if (settings->verbose) {
- t2e.set();
- printf("CIECAM02 performed in %d usec:\n", t2e.etime(t1e));
- //printf("minc=%f maxc=%f minj=%f maxj=%f\n",minc,maxc,minj,maxj);
- }
-#endif
-}
-}
-
-
void ColorTemp::cieCAT02(double Xw, double Yw, double Zw, double &CAM02BB00,double &CAM02BB01,double &CAM02BB02,double &CAM02BB10,double &CAM02BB11,double &CAM02BB12,double &CAM02BB20,double &CAM02BB21,double &CAM02BB22, double adap ) {
// CIECAT02 - J.Desmis January 2012 review September 2012
@@ -2040,7 +1672,7 @@ void ColorTemp::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q,
gc = g * (((yw * d) / gw) + (1.0 - d));
bc = b * (((yw * d) / bw) + (1.0 - d));
- ColorTemp::cat02_to_hpe( rp, gp, bp, rc, gc, bc );
+ ColorTemp::cat02_to_hpe( rp, gp, bp, rc, gc, bc, gamu );
if(gamu==1){//gamut correction M.H.Brill S.Susstrunk
rp=MAXR(rp,0.0);
gp=MAXR(gp,0.0);
diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h
index f588d1833..5dc5b758e 100644
--- a/rtengine/colortemp.h
+++ b/rtengine/colortemp.h
@@ -61,7 +61,7 @@ class ColorTemp {
int XYZtoCorColorTemp(double x0,double y0 ,double z0, double &temp);
static void cieCAT02(double Xw, double Yw, double Zw,double &CAM02BB00,double &CAM02BB01,double &CAM02BB02, double &CAM02BB10,double &CAM02BB11,double &CAM02BB12,double &CAM02BB20,double &CAM02BB21,double &CAM02BB22, double adap );
//static void CAT02 (Imagefloat* baseImg, const ProcParams* params);
- static void ciecam_02 (LabImage* lab, const ProcParams* params);
+ //static void ciecam_02 (LabImage* lab, const ProcParams* params);
static double d_factor( double f, double la ) {
return f * (1.0 - ((1.0 / 3.6) * exp((-la - 42.0) / 92.0)));
@@ -90,7 +90,7 @@ class ColorTemp {
gc = g * (((y * d) / g) + (1.0 - d));
bc = b * (((y * d) / b) + (1.0 - d));
- cat02_to_hpe( rp, gp, bp, rc, gc, bc );
+ cat02_to_hpe( rp, gp, bp, rc, gc, bc, gamu );
if(gamu==1){//gamut correction M.H.Brill S.Susstrunk
rp=MAXR(rp,0.0);
gp=MAXR(gp,0.0);
@@ -105,7 +105,7 @@ class ColorTemp {
}
static void xyz_to_cat02 ( double &r, double &g, double &b, double x, double y, double z, int gamu );
- static void cat02_to_hpe ( double &rh, double &gh, double &bh, double r, double g, double b );
+ static void cat02_to_hpe ( double &rh, double &gh, double &bh, double r, double g, double b, int gamu );
static void cat02_to_xyz ( double &x, double &y, double &z, double r, double g, double b, int gamu );
static void hpe_to_xyz ( double &x, double &y, double &z, double r, double g, double b );
@@ -253,11 +253,13 @@ if(gamu==0){
b = ( 0.0030 * x) + (0.0136 * y) + (0.9834 * z);
}
else if (gamu==1) {//gamut correction M.H.Brill S.Susstrunk
- r = ( 0.7328 * x) + (0.4296 * y) - (0.1624 * z);
- g = (-0.7036 * x) + (1.6975 * y) + (0.0061 * z);
+ //r = ( 0.7328 * x) + (0.4296 * y) - (0.1624 * z);
+ //g = (-0.7036 * x) + (1.6975 * y) + (0.0061 * z);
+ //b = ( 0.0000 * x) + (0.0000 * y) + (1.0000 * z);
+ r = ( 1.007245 * x) + (0.011136* y) - (0.018381 * z);//Changjun Li
+ g = (-0.318061 * x) + (1.314589 * y) + (0.003471 * z);
b = ( 0.0000 * x) + (0.0000 * y) + (1.0000 * z);
-
-
+
}
}
@@ -269,9 +271,13 @@ if(gamu==0) {
z = (-0.009628 * r) - (0.005698 * g) + (1.015326 * b);
}
else if(gamu==1) {//gamut correction M.H.Brill S.Susstrunk
- x = ( 1.0978566 * r) - (0.277843 * g) + (0.179987 * b);
- y = ( 0.455053 * r) + (0.473938 * g) + (0.0710096* b);
+ //x = ( 1.0978566 * r) - (0.277843 * g) + (0.179987 * b);
+ //y = ( 0.455053 * r) + (0.473938 * g) + (0.0710096* b);
+ //z = ( 0.000000 * r) - (0.000000 * g) + (1.000000 * b);
+ x = ( 0.99015849 * r) - (0.00838772* g) + (0.018229217 * b);//Changjun Li
+ y = ( 0.239565979 * r) + (0.758664642 * g) + (0.001770137* b);
z = ( 0.000000 * r) - (0.000000 * g) + (1.000000 * b);
+
}
}
@@ -280,16 +286,24 @@ inline void ColorTemp::hpe_to_xyz( double &x, double &y, double &z, double r, do
x = (1.910197 * r) - (1.112124 * g) + (0.201908 * b);
y = (0.370950 * r) + (0.629054 * g) - (0.000008 * b);
z = b;
+
}
-inline void ColorTemp::cat02_to_hpe( double &rh, double &gh, double &bh, double r, double g, double b )
-{
+
+
+
+inline void ColorTemp::cat02_to_hpe( double &rh, double &gh, double &bh, double r, double g, double b, int gamu )
+{ if(gamu==0){
rh = ( 0.7409792 * r) + (0.2180250 * g) + (0.0410058 * b);
gh = ( 0.2853532 * r) + (0.6242014 * g) + (0.0904454 * b);
bh = (-0.0096280 * r) - (0.0056980 * g) + (1.0153260 * b);
+ }
+ else if (gamu==1) {//Changjun Li
+ rh = ( 0.550930835 * r) + (0.519435987* g) - ( 0.070356303* b);
+ gh = ( 0.055954056 * r) + (0.89973132 * g) + (0.044315524 * b);
+ bh = (0.0 * r) - (0.0* g) + (1.0 * b);
+ }
}
-
-
}
#endif
diff --git a/rtengine/curves.cc b/rtengine/curves.cc
index 4c42146c5..17e1a62d8 100644
--- a/rtengine/curves.cc
+++ b/rtengine/curves.cc
@@ -153,6 +153,71 @@ namespace rtengine {
}
}
+void CurveFactory::curveLightBrightColor (
+ ColorAppearanceParams::eTCModeId curveMode1, const std::vector& curvePoints1,
+ ColorAppearanceParams::eTCModeId curveMode2, const std::vector& curvePoints2,
+ ColorAppearanceParams::eCTCModeId curveMode3, const std::vector& curvePoints3,
+
+ ColorAppearance & customColCurve1,
+ ColorAppearance & customColCurve2,
+ ColorAppearance & customColCurve3,
+
+ int skip)
+{
+
+ DiagonalCurve* tcurve = NULL;
+ customColCurve3.Reset();
+
+ if (!curvePoints3.empty() && curvePoints3[0]>DCT_Linear && curvePoints3[0]isIdentity()) {
+ delete tcurve;
+ tcurve = NULL;
+ }
+ else
+ customColCurve3.Set(tcurve);
+ delete tcurve;
+ tcurve = NULL;
+ }
+
+ customColCurve2.Reset();
+
+ if (!curvePoints2.empty() && curvePoints2[0]>DCT_Linear && curvePoints2[0]isIdentity()) {
+ delete tcurve;
+ tcurve = NULL;
+ }
+ else
+ customColCurve2.Set(tcurve);
+ delete tcurve;
+ tcurve = NULL;
+ }
+ // create first curve if needed
+ customColCurve1.Reset();
+
+ if (!curvePoints1.empty() && curvePoints1[0]>DCT_Linear && curvePoints1[0]isIdentity()) {
+ delete tcurve;
+ tcurve = NULL;
+ }
+ else {
+ customColCurve1.Set(tcurve);
+ delete tcurve;
+ tcurve = NULL;
+ }
+ }
+ if (tcurve) delete tcurve;
+
+}
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void CurveFactory::complexsgnCurve ( bool & autili, bool & butili, bool & ccutili, bool & cclutili, double saturation, double rstprotection,
const std::vector& acurvePoints, const std::vector& bcurvePoints,const std::vector& cccurvePoints,
@@ -769,8 +834,17 @@ namespace rtengine {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
+
+void ColorAppearance::Reset() {
+ lutColCurve.reset();
+}
+
+// Fill a LUT with X/Y, ranged 0xffff
+void ColorAppearance::Set(Curve *pCurve) {
+ lutColCurve(65536);
+ for (int i=0; i<65536; i++) lutColCurve[i] = pCurve->getVal(double(i)/65535.) * 65535.;
+}
+
void ToneCurve::Reset() {
lutToneCurve.reset();
}
@@ -778,7 +852,7 @@ void ToneCurve::Reset() {
// Fill a LUT with X/Y, ranged 0xffff
void ToneCurve::Set(Curve *pCurve) {
lutToneCurve(65536);
- for (int i=0;i<65536;i++) lutToneCurve[i] = pCurve->getVal(i/(double)65535) * 65535;
+ for (int i=0; i<65536; i++) lutToneCurve[i] = pCurve->getVal(double(i)/65535.) * 65535.;
}
}
diff --git a/rtengine/curves.h b/rtengine/curves.h
index 00019985e..91a1eb164 100644
--- a/rtengine/curves.h
+++ b/rtengine/curves.h
@@ -40,6 +40,7 @@ using namespace std;
namespace rtengine {
class ToneCurve;
+ class ColorAppearance;
class CurveFactory {
@@ -184,6 +185,14 @@ class CurveFactory {
const std::vector& bcurvePoints,const std::vector& cccurvePoints,const std::vector& cclurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, int skip=1);
static void complexLCurve (double br, double contr, const std::vector& curvePoints, LUTu & histogram, LUTu & histogramCropped,
LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip, bool & utili);
+ static void curveLightBrightColor (
+ ColorAppearanceParams::eTCModeId curveMode, const std::vector& curvePoints,
+ ColorAppearanceParams::eTCModeId curveMode2, const std::vector& curvePoints2,
+ ColorAppearanceParams::eCTCModeId curveMode3, const std::vector& curvePoints3,
+ ColorAppearance & outColCurve1,
+ ColorAppearance & outColCurve2,
+ ColorAppearance & outColCurve3,
+ int skip=1);
static void RGBCurve (const std::vector& curvePoints, LUTf & outCurve, int skip);
};
@@ -283,6 +292,82 @@ class ToneCurve {
operator bool (void) const { return lutToneCurve; }
};
+class ColorAppearance {
+ public:
+ LUTf lutColCurve; // 0xffff range
+
+ virtual ~ColorAppearance() {};
+
+ void Reset();
+ void Set(Curve *pCurve);
+ operator bool (void) const { return lutColCurve; }
+};
+
+class Lightcurve : public ColorAppearance {
+ public:
+ void Apply(float& Li) const;
+};
+
+//lightness curve
+inline void Lightcurve::Apply (float& Li) const {
+
+ assert (lutColCurve);
+
+ Li = lutColCurve[Li];
+}
+
+class Brightcurve : public ColorAppearance {
+ public:
+ void Apply(float& Br) const;
+};
+
+//brightness curve
+inline void Brightcurve::Apply (float& Br) const {
+
+ assert (lutColCurve);
+
+ Br = lutColCurve[Br];
+}
+
+class Chromacurve : public ColorAppearance {
+ public:
+ void Apply(float& Cr) const;
+};
+
+//Chroma curve
+inline void Chromacurve::Apply (float& Cr) const {
+
+ assert (lutColCurve);
+
+ Cr = lutColCurve[Cr];
+}
+class Saturcurve : public ColorAppearance {
+ public:
+ void Apply(float& Sa) const;
+};
+
+//Saturation curve
+inline void Saturcurve::Apply (float& Sa) const {
+
+ assert (lutColCurve);
+
+ Sa = lutColCurve[Sa];
+}
+
+class Colorfcurve : public ColorAppearance {
+ public:
+ void Apply(float& Cf) const;
+};
+
+//Colorfullness curve
+inline void Colorfcurve::Apply (float& Cf) const {
+
+ assert (lutColCurve);
+
+ Cf = lutColCurve[Cf];
+}
+
+
class StandardToneCurve : public ToneCurve {
public:
void Apply(float& r, float& g, float& b) const;
@@ -324,9 +409,8 @@ inline void StandardToneCurve::Apply (float& r, float& g, float& b) const {
// inlined to make sure there will be no cache flush when used
inline void AdobeToneCurve::Apply (float& r, float& g, float& b) const {
-#ifdef _DEBUG
assert (lutToneCurve);
-#endif
+
if (r >= g) {
if (g > b) RGBTone (r, g, b); // Case 1: r >= g > b
else if (b > r) RGBTone (b, r, g); // Case 2: b > r >= g
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index 980c612e5..a0074761b 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -201,7 +201,20 @@ void Crop::update (int todo) {
parent->ipf.dirpyrequalizer (labnCrop);
}
}
- ColorTemp::ciecam_02 (labnCrop, ¶ms);
+ ColorAppearance customColCurve1;
+ ColorAppearance customColCurve2;
+ ColorAppearance customColCurve3;
+
+ CurveFactory::curveLightBrightColor (
+ params.colorappearance.curveMode, params.colorappearance.curve,
+ params.colorappearance.curveMode2, params.colorappearance.curve2,
+ params.colorappearance.curveMode3, params.colorappearance.curve3,
+ customColCurve1,
+ customColCurve2,
+ customColCurve3,
+ 1);
+
+ parent->ipf.ciecam_02 (labnCrop, ¶ms,customColCurve1,customColCurve2,customColCurve3);
// switch back to rgb
parent->ipf.lab2monitorRgb (labnCrop, cropImg);
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 383aefcf5..0eb162a02 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -344,7 +344,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
ipf.chromiLuminanceCurve (nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve,lhskcurve, lumacurve, utili, autili, butili, ccutili,cclutili);
//ipf.colorCurve (nprevl, nprevl);
ipf.vibrance(nprevl);
- // ColorTemp::ciecam_02 (nprevl, ¶ms);
readyphase++;
if (scale==1) {
@@ -384,7 +383,16 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
readyphase++;
}
}
- ColorTemp::ciecam_02 (nprevl, ¶ms);
+ CurveFactory::curveLightBrightColor (
+ params.colorappearance.curveMode, params.colorappearance.curve,
+ params.colorappearance.curveMode2, params.colorappearance.curve2,
+ params.colorappearance.curveMode3, params.colorappearance.curve3,
+ customColCurve1,
+ customColCurve2,
+ customColCurve3,
+ scale==1 ? 1 : 1);
+
+ ipf.ciecam_02 (nprevl, ¶ms, customColCurve1,customColCurve2,customColCurve3);
// process crop, if needed
for (size_t i=0; icolorappearance.enabled) {
+
+#ifdef _DEBUG
+ MyTime t1e,t2e;
+ t1e.set();
+#endif
+
+ int width = lab->W, height = lab->H;
+ double Yw;
+ Yw=1.0;
+ double Xw, Zw;
+ double f,c,nc,yb,la,xw,yw,zw,f2,c2,nc2,yb2,la2;
+ double z,fl,n,nbb,ncb,d,aw;
+ double xwd,ywd,zwd;
+ int alg=0;
+ float sum=0.f;
+ float mean;
+
+ LUTf bright_curve (65536,0);//init curve
+ LUTf bright_curveQ (65536,0);//init curve
+
+ LUTu hist16 (65536);
+ LUTu hist16Q (65536);
+ float koef=1.0f;//rough correspondence between L and J
+ hist16.clear();hist16Q.clear();
+ for (int i=0; iL[i][j])/327.68f)>95.) koef=1.f;
+ else if(((lab->L[i][j])/327.68f)>85.) koef=0.97f;
+ else if(((lab->L[i][j])/327.68f)>80.) koef=0.93f;
+ else if(((lab->L[i][j])/327.68f)>70.) koef=0.87f;
+ else if(((lab->L[i][j])/327.68f)>60.) koef=0.85f;
+ else if(((lab->L[i][j])/327.68f)>50.) koef=0.8f;
+ else if(((lab->L[i][j])/327.68f)>40.) koef=0.75f;
+ else if(((lab->L[i][j])/327.68f)>30.) koef=0.7f;
+ else if(((lab->L[i][j])/327.68f)>20.) koef=0.7f;
+ else if(((lab->L[i][j])/327.68f)>10.) koef=0.9f;
+ else if(((lab->L[i][j])/327.68f)>0.) koef=1.0f;
+
+ hist16[CLIP((int)((koef*lab->L[i][j])))]++;//evaluate histogram luminance L # J
+ sum+=koef*lab->L[i][j];//evaluate mean J to calcualte Yb
+ hist16Q[CLIP((int) (32768.f*sqrt((koef*(lab->L[i][j]))/32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L
+ }
+ mean=(sum/(height*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone
+ if (mean<15.f) yb=3.0;
+ else if(mean<30.f) yb=5.0;
+ else if(mean<40.f) yb=10.0;
+ else if(mean<45.f) yb=15.0;
+ else if(mean<50.f) yb=18.0;
+ else if(mean<55.f) yb=23.0;
+ else if(mean<60.f) yb=30.0;
+ else if(mean<70.f) yb=40.0;
+ else if(mean<80.f) yb=60.0;
+ else if(mean<90.f) yb=80.0;
+ else yb=90.0;
+
+
+ ColorTemp::temp2mulxyz (params->wb.temperature, params->wb.green, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB
+ //viewing condition for surround
+ if(params->colorappearance.surround=="Average") { f = 1.00; c = 0.69; nc = 1.00;f2=1.0,c2=0.69,nc2=1.0;}
+ else if(params->colorappearance.surround=="Dim"){ f2 = 0.9; c2 = 0.59; nc2 = 0.9;f=1.0,c=0.69,nc=1.0;}
+ else if(params->colorappearance.surround=="Dark"){f2 = 0.8; c2 = 0.525;nc2 = 0.8;f=1.0,c=0.69,nc=1.0;}
+ else if(params->colorappearance.surround=="ExtremelyDark"){f2 = 0.8; c2 = 0.41;nc2 = 0.8;f=1.0,c=0.69,nc=1.0;}
+
+ //scene condition for surround
+ if(params->colorappearance.surrsource==true) {f = 0.85; c = 0.55; nc = 0.85;}// if user => source image has surround very dark
+ //with which algorithme
+ if (params->colorappearance.algo=="JC") alg=0;
+ else if(params->colorappearance.algo=="JS") alg=1;
+ else if(params->colorappearance.algo=="QM") alg=2;
+ else if(params->colorappearance.algo=="ALL") alg=3;
+ //settings white point of output device - or illuminant viewing
+ if(settings->viewingdevice==0) {xwd=96.42;ywd=100.0;zwd=82.52;}//5000K
+ else if(settings->viewingdevice==1) {xwd=95.68;ywd=100.0;zwd=92.15;}//5500
+ else if(settings->viewingdevice==2) {xwd=95.24;ywd=100.0;zwd=100.81;}//6000
+ else if(settings->viewingdevice==3) {xwd=95.04;ywd=100.0;zwd=108.88;}//6500
+ else if(settings->viewingdevice==4) {xwd=109.85;ywd=100.0;zwd=35.58;}//tungsten
+ else if(settings->viewingdevice==5) {xwd=99.18;ywd=100.0;zwd=67.39;}//fluo F2
+ else if(settings->viewingdevice==6) {xwd=95.04;ywd=100.0;zwd=108.75;}//fluo F7
+ else if(settings->viewingdevice==7) {xwd=100.96;ywd=100.0;zwd=64.35;}//fluo F11
+
+
+ //settings mean Luminance Y of output device or viewing
+ if(settings->viewingdevicegrey==0) {yb2=5.0;}
+ else if(settings->viewingdevicegrey==1) {yb2=10.0;}
+ else if(settings->viewingdevicegrey==2) {yb2=15.0;}
+ else if(settings->viewingdevicegrey==3) {yb2=18.0;}
+ else if(settings->viewingdevicegrey==4) {yb2=23.0;}
+ else if(settings->viewingdevicegrey==5) {yb2=30.0;}
+ else if(settings->viewingdevicegrey==6) {yb2=40.0;}
+
+ //La and la2 = ambiant luminosity scene and viewing
+ la=double(params->colorappearance.adapscen);
+ la2=double(params->colorappearance.adaplum);
+
+ // level of adaptation
+ double deg=(params->colorappearance.degree)/100.0;
+ double pilot=params->colorappearance.autodegree ? 2.0 : deg;
+
+ //algoritm's params
+ float jli=params->colorappearance.jlight;
+ float chr=params->colorappearance.chroma;
+ float contra=params->colorappearance.contrast;
+ float qbri=params->colorappearance.qbright;
+ float schr=params->colorappearance.schroma;
+ float mchr=params->colorappearance.mchroma;
+ float qcontra=params->colorappearance.qcontrast;
+ float hue=params->colorappearance.colorh;
+ double rstprotection = 100.-params->colorappearance.rstprotection;
+ if(schr>0.0) schr=schr/2.0f;//divide sensibility for saturation
+
+ // extracting datas from 'params' to avoid cache flush (to be confirmed)
+ ColorAppearanceParams::eTCModeId curveMode = params->colorappearance.curveMode;
+ ColorAppearanceParams::eTCModeId curveMode2 = params->colorappearance.curveMode2;
+ bool hasColCurve1 = bool(customColCurve1);
+ bool hasColCurve2 = bool(customColCurve2);
+ ColorAppearanceParams::eCTCModeId curveMode3 = params->colorappearance.curveMode3;
+ bool hasColCurve3 = bool(customColCurve3);
+
+
+
+ //evaluate lightness, contrast
+ ColorTemp::curveJ (jli, contra, 1, bright_curve, hist16);//lightness and contrast J
+ ColorTemp::curveJ (qbri, qcontra, 1, bright_curveQ, hist16Q);//brightness and contrast Q
+ int gamu=0;
+ bool highlight = params->hlrecovery.enabled; //Get the value if "highlight reconstruction" is activated
+
+ if(params->colorappearance.gamut==true) gamu=1;//enabled gamut control
+ xw=100.0*Xw;
+ yw=100.0*Yw;
+ zw=100.0*Zw;
+ double xw1,yw1,zw1,xw2,yw2,zw2;
+ // settings of WB: scene and viewing
+ if(params->colorappearance.wbmodel=="RawT") {xw1=96.46;yw1=100.0;zw1=82.445;xw2=xwd;yw2=ywd;zw2=zwd;} //use RT WB; CAT 02 is used for output device (see prefreneces)
+ else if(params->colorappearance.wbmodel=="RawTCAT02") {xw1=xw;yw1=yw;zw1=zw;xw2=xwd;yw2=ywd;zw2=zwd;} // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences
+ bool doneinit=true;
+ bool doneinit2=true;
+#ifndef _DEBUG
+#pragma omp parallel default(shared) firstprivate(lab,xw1,xw2,yw1,yw2,zw1,zw2,pilot,jli,chr,yb,la,fl,nc,f,c, height,width,doneinit,doneinit2, nc2,f2,c2, alg, gamu, highlight, rstprotection)
+#endif
+{
+ 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]}
+ };
+
+#ifndef _DEBUG
+#pragma omp for schedule(dynamic, 10)
+#endif
+ for (int i=0; iL[i][j];
+ float a=lab->a[i][j];
+ float b=lab->b[i][j];
+ float x1,y1,z1;
+ double x,y,z;
+ //convert Lab => XYZ
+ Color::Lab2XYZ(L, a, b, x1, y1, z1);
+ double J, C, h, Q, M, s, aw, fl, wh;
+ double Jp,Cpr;
+ double Jpro,Cpro, hpro, Qpro, Mpro, spro;
+ bool t1L=false;
+ bool t1B=false;
+ bool t2L=false;
+ bool t2B=false;
+ int c1C=0;
+ int c1s=0;
+ int c1co=0;
+
+ x=(double)x1/655.35;
+ y=(double)y1/655.35;
+ z=(double)z1/655.35;
+ //process source==> normal
+ ColorTemp::xyz2jchqms_ciecam02( J, C, h,
+ Q, M, s, aw, fl, wh,
+ x, y, z,
+ xw1, yw1, zw1,
+ yb, la,
+ f, c, nc, pilot, doneinit, gamu );
+ Jpro=J;
+ Cpro=C;
+ hpro=h;
+ Qpro=Q;
+ Mpro=M;
+ spro=s;
+ // we cannot have all algoritms with all chroma curves
+ if(alg==1) {
+ // Lightness saturation
+ Jpro=(bright_curve[(float)(Jpro*327.68)])/327.68;//ligthness CIECAM02 + contrast
+ double sres;
+ double Sp=spro/100.0;
+ double parsat=1.5;
+ parsat=1.5;//parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation)
+ if(schr==-100.0) schr=-99.8;
+ ColorTemp::curvecolor(schr, Sp , sres, parsat);
+ double coe=pow(fl,0.25);
+ float dred=100.f;// in C mode
+ float protect_red=80.0f; // in C mode
+ dred = 100.0 * sqrt((dred*coe)/Qpro);
+ protect_red=100.0 * sqrt((protect_red*coe)/Qpro);
+ int sk=0;
+ float ko=100.f;
+ Color::skinred(Jpro, hpro, sres, Sp, dred, protect_red,sk,rstprotection,ko, spro);
+ Qpro= ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ;
+ Cpro=(spro*spro*Qpro)/(10000.0);
+ }
+ else if(alg==3 || alg==0 || alg==2) {
+ double coef=32760./wh;
+ if(alg==3 || alg==2) Qpro=(bright_curveQ[(float)(Qpro*coef)])/coef;//brightness and contrast
+ double Mp, sres;
+ double coe=pow(fl,0.25);
+ Mp=Mpro/100.0;
+ double parsat=2.5;
+ if(mchr==-100.0) mchr=-99.8 ;
+ if(mchr==100.0) mchr=99.9;
+ ColorTemp::curvecolor(mchr, Mp , sres, parsat);//colorfullness
+ float dred=100.f;//in C mode
+ float protect_red=80.0f;// in C mode
+ dred *=coe;//in M mode
+ protect_red *=coe;//M mode
+ int sk=0;
+ float ko=100.f;
+ Color::skinred(Jpro, hpro, sres, Mp, dred, protect_red,sk,rstprotection,ko, Mpro);
+ Jpro=(100.0* Qpro*Qpro) /(wh*wh);
+ Cpro= Mpro/coe;
+ spro = 100.0 * sqrt( Mpro / Qpro );
+ if(alg!=2) Jpro=(bright_curve[(float)(Jpro*327.68)])/327.68;//ligthness CIECAM02 + contrast
+ double Cp;
+ double Sp=spro/100.0;
+ parsat=1.5;
+ if(schr==-100.0) schr=-99.;
+ if(schr==100.0) schr=98.;
+ ColorTemp::curvecolor(schr, Sp , sres, parsat); //saturation
+ dred=100.f;// in C mode
+ protect_red=80.0f; // in C mode
+ dred = 100.0 * sqrt((dred*coe)/Q);
+ protect_red=100.0 * sqrt((protect_red*coe)/Q);
+ sk=0;
+ Color::skinred(Jpro, hpro, sres, Sp, dred, protect_red,sk,rstprotection,ko, spro);
+ //double Q1;
+ Qpro= ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ;
+ Cpro=(spro*spro*Qpro)/(10000.0);
+ Cp=Cpro/100.0;
+ parsat=1.8;//parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation : for not)
+ if(chr==-100.0) chr=-99.8;
+ ColorTemp::curvecolor(chr, Cp , sres, parsat); //chroma
+ dred=55.f;
+ protect_red=30.0f;
+ sk=1;
+ Color::skinred(Jpro, hpro, sres, Cp, dred, protect_red,sk,rstprotection, ko, Cpro);
+
+ hpro=hpro+hue;if( hpro < 0.0 ) hpro += 360.0;//hue
+ }
+
+ if (hasColCurve1) {//curve 1 with Lightness and Brightness
+ if (curveMode==ColorAppearanceParams::TC_MODE_LIGHT){
+ float Jj=(float) Jpro*327.68;
+ float Jold=Jj;
+ const Lightcurve& userColCurve = static_cast(customColCurve1);
+ userColCurve.Apply(Jj);
+ Jj=0.7f*(Jj-Jold)+Jold;//divide sensibility
+ Jpro=(double)(Jj/327.68f);
+ t1L=true;
+ }
+ else if (curveMode==ColorAppearanceParams::TC_MODE_BRIGHT){
+ double coef=32760./wh;
+ float Qq=(float) Qpro*coef;
+ float Qold=Qq;
+ const Brightcurve& userColCurve = static_cast(customColCurve1);
+ userColCurve.Apply(Qq);
+ Qq=0.5f*(Qq-Qold)+Qold;//divide sensibility
+ Qpro=(double)(Qq/coef);
+ Jpro=(100.0* Qpro*Qpro) /(wh*wh);
+ t1B=true;
+ }
+ }
+
+ if (hasColCurve2) {//curve 2 with Lightness and Brightness
+ if (curveMode2==ColorAppearanceParams::TC_MODE_LIGHT){
+ float Jj=(float) Jpro*327.68;
+ float Jold=Jj;
+ const Lightcurve& userColCurve = static_cast(customColCurve2);
+ userColCurve.Apply(Jj);
+ Jj=0.7f*(Jj-Jold)+Jold;//divide sensibility
+ Jpro=(double)(Jj/327.68f);
+ t2L=true;
+ }
+ else if (curveMode2==ColorAppearanceParams::TC_MODE_BRIGHT){ //
+ double coef=32760./wh;
+ float Qq=(float) Qpro*coef;
+ float Qold = Qq;
+ const Brightcurve& userColCurve = static_cast(customColCurve2);
+ userColCurve.Apply(Qq);
+ Qq=0.5f*(Qq-Qold)+Qold;//divide sensibility
+ Qpro=(double)(Qq/coef);
+ Jpro=(100.0* Qpro*Qpro) /(wh*wh);
+ t2B=true;
+ }
+ }
+
+ if (hasColCurve3) {//curve 3 with chroma saturation colorfullness
+ if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA){
+ double parsat=1.;
+ double coef=327.68/parsat;
+ float Cc=(float) Cpro*coef;
+ float Ccold=Cc;
+ const Chromacurve& userColCurve = static_cast(customColCurve3);
+ userColCurve.Apply(Cc);
+ float dred=55.f;
+ float protect_red=30.0f;
+ float sk=1;
+ float ko=1.f/coef;
+ Color::skinred(Jpro, hpro, Cc, Ccold, dred, protect_red,sk,rstprotection,ko, Cpro);
+ c1C=1;
+ }
+ else if (curveMode3==ColorAppearanceParams::TC_MODE_SATUR){ //
+ double parsat=0.8;
+ double coef=327.68/parsat;
+ float Ss=(float) spro*coef;
+ float Sold=Ss;
+ const Saturcurve& userColCurve = static_cast(customColCurve3);
+ userColCurve.Apply(Ss);
+ Ss=0.7f*(Ss-Sold)+Sold;//divide sensibility saturation
+ double coe=pow(fl,0.25);
+ float dred=100.f;// in C mode
+ float protect_red=80.0f; // in C mode
+ dred = 100.0 * sqrt((dred*coe)/Qpro);
+ protect_red=100.0 * sqrt((protect_red*coe)/Qpro);
+ int sk=0;
+ float ko=1.f/coef;
+ Color::skinred(Jpro, hpro, Ss, Sold, dred, protect_red,sk,rstprotection,ko, spro);
+ Qpro= ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ;
+ Cpro=(spro*spro*Qpro)/(10000.0);
+ c1s=1;
+
+ }
+ else if (curveMode3==ColorAppearanceParams::TC_MODE_COLORF){ //
+ double parsat=1.;
+ double coef=327.68/parsat;
+ float Mm=(float) Mpro*coef;
+ float Mold=Mm;
+ const Colorfcurve& userColCurve = static_cast(customColCurve3);
+ userColCurve.Apply(Mm);
+ double coe=pow(fl,0.25);
+ float dred=100.f;//in C mode
+ float protect_red=80.0f;// in C mode
+ dred *=coe;//in M mode
+ protect_red *=coe;
+ int sk=0;
+ float ko=1.f/coef;
+ Color::skinred(Jpro, hpro, Mm, Mold, dred, protect_red,sk,rstprotection,ko, Mpro);
+ Cpro= Mpro/coe;
+ c1co=1;
+ }
+ }
+ //to retrieve the correct values of variables
+ if(t2B && t1B) Jpro=(100.0* Qpro*Qpro) /(wh*wh);// for brightness curve
+ if(c1s==1) {
+ Qpro= ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ;//for saturation curve
+ Cpro=(spro*spro*Qpro)/(10000.0);
+ }
+ if(c1co==1) { double coe=pow(fl,0.25);Cpro= Mpro/coe;} // for colorfullness curve
+ //retrieve values C,J...s
+ C=Cpro;
+ J=Jpro;
+ Q=Qpro;
+ M=Mpro;
+ h=hpro;
+ s=spro;
+ double xx,yy,zz;
+ //process normal==> viewing
+ ColorTemp::jch2xyz_ciecam02( xx, yy, zz,
+ J, C, h,
+ xw2, yw2, zw2,
+ yb2, la2,
+ f2, c2, nc2, doneinit2, gamu);
+ x=(float)xx*655.35;
+ y=(float)yy*655.35;
+ z=(float)zz*655.35;
+ float Ll,aa,bb;
+ //convert xyz=>lab
+ Color::XYZ2Lab(x, y, z, Ll, aa, bb);
+ lab->L[i][j]=Ll;
+ lab->a[i][j]=aa;
+ lab->b[i][j]=bb;
+ // gamut control in Lab mode; I must study how to do with cIECAM only
+ if(gamu==1) {
+ float R,G,B;
+ float HH, Lprov1, Chprov1;
+ Lprov1=lab->L[i][j]/327.68f;
+ Chprov1=sqrt(SQR(lab->a[i][j]/327.68f) + SQR(lab->b[i][j]/327.68f));
+ HH=atan2(lab->b[i][j],lab->a[i][j]);
+
+#ifdef _DEBUG
+ bool neg=false;
+ bool more_rgb=false;
+ //gamut control : Lab values are in gamut
+ Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb);
+#else
+ //gamut control : Lab values are in gamut
+ Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f);
+#endif
+
+ lab->L[i][j]=Lprov1*327.68f;
+ lab->a[i][j]=327.68f*Chprov1*cos(HH);
+ lab->b[i][j]=327.68f*Chprov1*sin(HH);
+
+ }
+ }
+ }
+ // End of parallelization
+
+#ifdef _DEBUG
+ if (settings->verbose) {
+ t2e.set();
+ printf("CIECAM02 performed in %d usec:\n", t2e.etime(t1e));
+ // printf("minc=%f maxc=%f minj=%f maxj=%f\n",minc,maxc,minj,maxj);
+ }
+#endif
+}
+}
+
+
+
+
+
+
+
void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve,
SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve,
const ToneCurve & customToneCurve1,const ToneCurve & customToneCurve2 ) {
@@ -800,8 +1233,8 @@ void ImProcFunctions::chromiLuminanceCurve (LabImage* lold, LabImage* lnew, LUTf
bool LCredsk = params->labCurve.lcredsk;
bool ccut = ccutili;
double rstprotection = 100.-params->labCurve.rstprotection; // Red and Skin Tones Protection
- // avoid color shift is disabled when bwToning is activated
- bool avoidColorShift = params->labCurve.avoidcolorshift && !bwToning;
+ // avoid color shift is disabled when bwToning is activated and enabled if gamut is true in colorappearanace
+ bool avoidColorShift = (params->labCurve.avoidcolorshift && !bwToning) || params->colorappearance.gamut;
int protectRed = settings->protectred;
double protectRedH = settings->protectredh;
bool gamutLch = settings->gamutLch;
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index 2ef9a70ff..16849857b 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -92,6 +92,8 @@ class ImProcFunctions {
SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2,
double expcomp, int hlcompr, int hlcomprthresh);
void luminanceCurve (LabImage* lold, LabImage* lnew, LUTf &curve);
+ void ciecam_02 (LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3);
+
void chromiLuminanceCurve (LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve,LUTf & satclcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili);
void vibrance (LabImage* lab);//Jacques' vibrance
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index d6020cf58..78f68aa91 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -214,8 +214,14 @@ enum ProcEvent {
EvCATSChroma=189,
EvCATMChroma=190,
EvCAThue=191,
+ EvCATCurve1=192,
+ EvCATCurve2=193,
+ EvCATCurveMode1=194,
+ EvCATCurveMode2=195,
+ EvCATCurve3=196,
+ EvCATCurveMode3=197,
- NUMOFEVENTS=192
+ NUMOFEVENTS=198
};
}
#endif
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index f27225a9e..3968c8b77 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -215,7 +215,6 @@ void ProcParams::setDefaults () {
colorappearance.degree = 90;
colorappearance.autodegree = true;
colorappearance.surround = "Average";
-// colorappearance.backgrd = 20;
colorappearance.adaplum = 16;
colorappearance.adapscen = 2000.0;
colorappearance.algo = "JC";
@@ -230,7 +229,16 @@ void ProcParams::setDefaults () {
colorappearance.qcontrast = 0.0;
colorappearance.colorh = 0.0;
colorappearance.surrsource = false;
- colorappearance.gamut = false;
+ colorappearance.gamut = true;
+ colorappearance.curve.clear ();
+ colorappearance.curve.push_back(DCT_Linear);
+ colorappearance.curve2.clear ();
+ colorappearance.curve2.push_back(DCT_Linear);
+ colorappearance.curveMode =ColorAppearanceParams::TC_MODE_LIGHT;
+ colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_LIGHT;
+ colorappearance.curve3.clear ();
+ colorappearance.curve3.push_back(DCT_Linear);
+ colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_CHROMA;
impulseDenoise.enabled = false;
impulseDenoise.thresh = 50;
@@ -583,7 +591,62 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, ParamsEdited* p
if (!pedited || pedited->colorappearance.adapscen) keyFile.set_double ("Color appearance", "AdaptScene", colorappearance.adapscen);
if (!pedited || pedited->colorappearance.surrsource) keyFile.set_boolean ("Color appearance", "SurrSource", colorappearance.surrsource);
if (!pedited || pedited->colorappearance.gamut) keyFile.set_boolean ("Color appearance", "Gamut", colorappearance.gamut);
+ if (!pedited || pedited->colorappearance.curveMode) {
+ Glib::ustring method;
+ switch (colorappearance.curveMode) {
+ case (ColorAppearanceParams::TC_MODE_LIGHT):
+ method = "Lightness";
+ break;
+ case (ColorAppearanceParams::TC_MODE_BRIGHT):
+ method = "Brightness";
+ break;
+ }
+ keyFile.set_string ("Color appearance", "CurveMode", method);
+ }
+ if (!pedited || pedited->colorappearance.curveMode2) {
+ Glib::ustring method;
+ switch (colorappearance.curveMode2) {
+ case (ColorAppearanceParams::TC_MODE_LIGHT):
+ method = "Lightness";
+ break;
+ case (ColorAppearanceParams::TC_MODE_BRIGHT):
+ method = "Brightness";
+ break;
+ }
+ keyFile.set_string ("Color appearance", "CurveMode2", method);
+ }
+ if (!pedited || pedited->colorappearance.curveMode3) {
+ Glib::ustring method;
+ switch (colorappearance.curveMode3) {
+ case (ColorAppearanceParams::TC_MODE_CHROMA):
+ method = "Chroma";
+ break;
+ case (ColorAppearanceParams::TC_MODE_SATUR):
+ method = "Saturation";
+ break;
+ case (ColorAppearanceParams::TC_MODE_COLORF):
+ method = "Colorfullness";
+ break;
+
+ }
+ keyFile.set_string ("Color appearance", "CurveMode3", method);
+ }
+
+ if (!pedited || pedited->colorappearance.curve) {
+ Glib::ArrayHandle tcurve = colorappearance.curve;
+ keyFile.set_double_list("Color appearance", "Curve", tcurve);
+ }
+ if (!pedited || pedited->colorappearance.curve2) {
+ Glib::ArrayHandle tcurve = colorappearance.curve2;
+ keyFile.set_double_list("Color appearance", "Curve2", tcurve);
+ }
+ if (!pedited || pedited->colorappearance.curve3) {
+ Glib::ArrayHandle tcurve = colorappearance.curve3;
+ keyFile.set_double_list("Color appearance", "Curve3", tcurve);
+ }
+
+
// save impulseDenoise
if (!pedited || pedited->impulseDenoise.enabled) keyFile.set_boolean ("Impulse Denoising", "Enabled", impulseDenoise.enabled);
if (!pedited || pedited->impulseDenoise.thresh) keyFile.set_integer ("Impulse Denoising", "Threshold", impulseDenoise.thresh);
@@ -1045,7 +1108,34 @@ if (keyFile.has_group ("Color appearance")) {
if (keyFile.has_key ("Color appearance", "AdaptScene")) {colorappearance.adapscen = keyFile.get_double ("Color appearance", "AdaptScene"); if (pedited) pedited->colorappearance.adapscen = true; }
if (keyFile.has_key ("Color appearance", "SurrSource")) {colorappearance.surrsource = keyFile.get_boolean ("Color appearance", "SurrSource"); if (pedited) pedited->colorappearance.surrsource = true; }
if (keyFile.has_key ("Color appearance", "Gamut")) {colorappearance.gamut = keyFile.get_boolean ("Color appearance", "Gamut"); if (pedited) pedited->colorappearance.gamut = true; }
-}
+ if (keyFile.has_key ("Color appearance", "CurveMode")) {
+ Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode");
+ if (sMode == "Lightness") colorappearance.curveMode = ColorAppearanceParams::TC_MODE_LIGHT;
+ else if (sMode == "Brightness") colorappearance.curveMode = ColorAppearanceParams::TC_MODE_BRIGHT;
+ if (pedited) pedited->colorappearance.curveMode = true;
+ }
+ if (keyFile.has_key ("Color appearance", "CurveMode2")) {
+ Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode2");
+ if (sMode == "Lightness") colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_LIGHT;
+ else if (sMode == "Brightness") colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_BRIGHT;
+ if (pedited) pedited->colorappearance.curveMode2 = true;
+ }
+ if (keyFile.has_key ("Color appearance", "CurveMode3")) {
+ Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode3");
+ if (sMode == "Chroma") colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_CHROMA;
+ else if (sMode == "Saturation") colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_SATUR;
+ else if (sMode == "Colorfullness") colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_COLORF;
+
+ if (pedited) pedited->colorappearance.curveMode3 = true;
+ }
+
+ if (ppVersion>200) {
+ if (keyFile.has_key ("Color appearance", "Curve")) { colorappearance.curve = keyFile.get_double_list ("Color appearance", "Curve"); if (pedited) pedited->colorappearance.curve = true; }
+ if (keyFile.has_key ("Color appearance", "Curve2")) { colorappearance.curve2 = keyFile.get_double_list ("Color appearance", "Curve2"); if (pedited) pedited->colorappearance.curve2 = true; }
+ if (keyFile.has_key ("Color appearance", "Curve3")) { colorappearance.curve3 = keyFile.get_double_list ("Color appearance", "Curve3"); if (pedited) pedited->colorappearance.curve3 = true; }
+ }
+
+ }
// load impulseDenoise
if (keyFile.has_group ("Impulse Denoising")) {
@@ -1415,7 +1505,9 @@ bool ProcParams::operator== (const ProcParams& other) {
&& colorappearance.adaplum == other.colorappearance.adaplum
&& colorappearance.wbmodel == other.colorappearance.wbmodel
&& colorappearance.algo == other.colorappearance.algo
-
+ && colorappearance.curveMode == other.colorappearance.curveMode
+ && colorappearance.curveMode2 == other.colorappearance.curveMode2
+ && colorappearance.curveMode3 == other.colorappearance.curveMode3
&& colorappearance.jlight == other.colorappearance.jlight
&& colorappearance.qbright == other.colorappearance.qbright
&& colorappearance.chroma == other.colorappearance.chroma
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 97a8ec8b8..2f2567c30 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -348,19 +348,37 @@ class WBParams {
/**
* Parameters of colorappearance
*/
- class ColorappearanceParams {
+ class ColorAppearanceParams {
public:
+ enum eTCModeId {
+ TC_MODE_LIGHT, // Lightness mode
+ TC_MODE_BRIGHT, // Brightness mode
+ };
+
+ enum eCTCModeId {
+ TC_MODE_CHROMA, // chroma mode
+ TC_MODE_SATUR, // saturation mode
+ TC_MODE_COLORF, // colorfullness mode
+ };
+
bool enabled;
int degree;
bool autodegree;
+ std::vector curve;
+ std::vector curve2;
+ std::vector curve3;
+ eTCModeId curveMode;
+ eTCModeId curveMode2;
+ eCTCModeId curveMode3;
+
Glib::ustring surround;
- double adapscen;
- double adaplum;
+ double adapscen;
+ double adaplum;
Glib::ustring wbmodel;
Glib::ustring algo;
- double contrast;
- double qcontrast;
+ double contrast;
+ double qcontrast;
double jlight;
double qbright;
double chroma;
@@ -368,8 +386,8 @@ class WBParams {
double mchroma;
double colorh;
double rstprotection;
- bool surrsource;
- bool gamut;
+ bool surrsource;
+ bool gamut;
};
/**
@@ -717,7 +735,7 @@ class ProcParams {
VibranceParams vibrance; ///< Vibrance parameters
//ColorBoostParams colorBoost; ///< Color boost parameters
WBParams wb; ///< White balance parameters
- ColorappearanceParams colorappearance;
+ ColorAppearanceParams colorappearance;
//ColorShiftParams colorShift; ///< Color shift parameters
//LumaDenoiseParams lumaDenoise; ///< Luminance denoising parameters
//ColorDenoiseParams colorDenoise; ///< Color denoising parameters
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index bea100473..0e996e389 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -211,7 +211,13 @@ LUMINANCECURVE, // EvCATQbright
LUMINANCECURVE, // EvCATQContrast
LUMINANCECURVE, // EvCATSChroma
LUMINANCECURVE, // EvCATMchroma
-LUMINANCECURVE // EvCAThue
+LUMINANCECURVE, // EvCAThue
+LUMINANCECURVE, // EvCATcurve1
+LUMINANCECURVE, // EvCATcurve2
+LUMINANCECURVE, // EvCATcurvemode1
+LUMINANCECURVE, // EvCATcurvemode2
+LUMINANCECURVE, // EvCATcurve3
+LUMINANCECURVE // EvCATcurvemode3
};
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index f7e9d2475..16dedef75 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -744,6 +744,9 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
LUTu dummy;
ToneCurve customToneCurve1, customToneCurve2;
+ ColorAppearance customColCurve1;
+ ColorAppearance customColCurve2;
+ ColorAppearance customColCurve3;
ipf.g = gamma;
ipf.iGamma = true;
@@ -784,7 +787,17 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
//ipf.luminanceCurve (labView, labView, curve);
ipf.chromiLuminanceCurve (labView, labView, curve1, curve2, satcurve,lhskcurve, curve, utili, autili, butili, ccutili,cclutili);
ipf.vibrance(labView);
- ColorTemp::ciecam_02 (labView, ¶ms);
+ CurveFactory::curveLightBrightColor (
+ params.colorappearance.curveMode, params.colorappearance.curve,
+ params.colorappearance.curveMode2, params.colorappearance.curve2,
+ params.colorappearance.curveMode3, params.colorappearance.curve3,
+
+ customColCurve1,
+ customColCurve2,
+ customColCurve3,
+ 16);
+
+ ipf.ciecam_02 (labView, ¶ms,customColCurve1,customColCurve2,customColCurve3);
// color processing
//ipf.colorCurve (labView, labView);
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index f86ddc49a..dc19077be 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -170,6 +170,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
LUTu dummy;
ToneCurve customToneCurve1, customToneCurve2;
+ ColorAppearance customColCurve1, customColCurve2,customColCurve3 ;
ipf.g = imgsrc->getGamma();
ipf.iGamma = true;
@@ -219,7 +220,6 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
//ipf.luminanceCurve (labView, labView, curve);
ipf.chromiLuminanceCurve (labView, labView, curve1, curve2, satcurve,lhskcurve,curve, utili, autili, butili, ccutili,cclutili);
ipf.vibrance(labView);
-// ColorTemp::ciecam_02 (labView, ¶ms);
ipf.impulsedenoise (labView);
ipf.defringe (labView);
@@ -243,7 +243,17 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
// directional pyramid equalizer
ipf.dirpyrequalizer (labView);//TODO: this is the luminance tonecurve, not the RGB one
- ColorTemp::ciecam_02 (labView, ¶ms);
+
+ CurveFactory::curveLightBrightColor (
+ params.colorappearance.curveMode, params.colorappearance.curve,
+ params.colorappearance.curveMode2, params.colorappearance.curve2,
+ params.colorappearance.curveMode3, params.colorappearance.curve3,
+ customColCurve1,
+ customColCurve2,
+ customColCurve3,
+ 1);
+
+ ipf.ciecam_02 (labView, ¶ms,customColCurve1,customColCurve2,customColCurve2);
// end tile processing...???
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc
index 4158a1e1e..608c21724 100644
--- a/rtgui/colorappearance.cc
+++ b/rtgui/colorappearance.cc
@@ -1,4 +1,3 @@
-/*
/*
* This file is part of RawTherapee.
*
@@ -21,11 +20,16 @@
#include
#include
#include "guiutils.h"
+#include "../rtengine/color.h"
using namespace rtengine;
using namespace rtengine::procparams;
-Colorappearance::Colorappearance () : Gtk::VBox(), FoldableToolPanel(this) {
+ColorAppearance::ColorAppearance () : Gtk::VBox(), FoldableToolPanel(this) {
+ CurveListener::setMulti(true);
+ std::vector milestones;
+ milestones.push_back( GradientMilestone(0., 0., 0., 0.) );
+ milestones.push_back( GradientMilestone(1., 1., 1., 1.) );
set_border_width(4);
@@ -135,11 +139,6 @@ Colorappearance::Colorappearance () : Gtk::VBox(), FoldableToolPanel(this) {
chroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_TOOLTIP"));
p2VBox->pack_start (*chroma);
- rstprotection = Gtk::manage ( new Adjuster (M("TP_COLORAPP_RSTPRO"), 0., 100., 0.1, 0.) );
- if (rstprotection->delay < 1000) rstprotection->delay = 1000;
- rstprotection->throwOnButtonRelease();
- rstprotection->set_tooltip_markup (M("TP_COLORAPP_RSTPRO_TOOLTIP"));
- p2VBox->pack_start (*rstprotection);
schroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA_S"), -100.0, 100.0, 0.1, 0.));
if (schroma->delay < 1000) schroma->delay = 1000;
@@ -152,6 +151,12 @@ Colorappearance::Colorappearance () : Gtk::VBox(), FoldableToolPanel(this) {
mchroma->throwOnButtonRelease();
mchroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_M_TOOLTIP"));
p2VBox->pack_start (*mchroma);
+
+ rstprotection = Gtk::manage ( new Adjuster (M("TP_COLORAPP_RSTPRO"), 0., 100., 0.1, 0.) );
+ if (rstprotection->delay < 1000) rstprotection->delay = 1000;
+ rstprotection->throwOnButtonRelease();
+ rstprotection->set_tooltip_markup (M("TP_COLORAPP_RSTPRO_TOOLTIP"));
+ p2VBox->pack_start (*rstprotection);
contrast = Gtk::manage (new Adjuster (M("TP_COLORAPP_CONTRAST"), -100.0, 100.0, 0.1, 0.));
if (contrast->delay < 1000) contrast->delay = 1000;
@@ -171,6 +176,92 @@ Colorappearance::Colorappearance () : Gtk::VBox(), FoldableToolPanel(this) {
colorh->set_tooltip_markup (M("TP_COLORAPP_HUE_TOOLTIP"));
p2VBox->pack_start (*colorh);
+ p2VBox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4);
+
+ toneCurveMode = Gtk::manage (new MyComboBoxText ());
+ toneCurveMode->append_text (M("TP_COLORAPP_TCMODE_LIGHTNESS"));
+ toneCurveMode->append_text (M("TP_COLORAPP_TCMODE_BRIGHTNESS"));
+ toneCurveMode->set_active (0);
+ toneCurveMode->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL1"));
+
+ curveEditorG = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR1"));
+ curveEditorG->setCurveListener (this);
+
+ shape = static_cast(curveEditorG->addCurve(CT_Diagonal, "", toneCurveMode));
+
+
+
+ tcmodeconn = toneCurveMode->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode1Changed), true );
+
+ toneCurveMode2 = Gtk::manage (new MyComboBoxText ());
+ toneCurveMode2->append_text (M("TP_COLORAPP_TCMODE_LIGHTNESS"));
+ toneCurveMode2->append_text (M("TP_COLORAPP_TCMODE_BRIGHTNESS"));
+ toneCurveMode2->set_active (0);
+ toneCurveMode2->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL2"));
+
+ curveEditorG2 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR2"));
+ curveEditorG2->setCurveListener (this);
+
+ shape2 = static_cast(curveEditorG2->addCurve(CT_Diagonal, "", toneCurveMode2));
+
+ tcmode2conn = toneCurveMode2->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode2Changed), true );
+
+ toneCurveMode3 = Gtk::manage (new MyComboBoxText ());
+ toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_CHROMA"));
+ toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_SATUR"));
+ toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_COLORF"));
+ toneCurveMode3->set_active (0);
+ toneCurveMode3->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL3"));
+
+ curveEditorG3 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR3"));
+ curveEditorG3->setCurveListener (this);
+
+ shape3 = static_cast(curveEditorG3->addCurve(CT_Diagonal, "", toneCurveMode3));
+ shape3->setRangeLabels(
+ M("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"),
+ M("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE4")
+ );
+ shape3->setBottomBarColorProvider(this, 1);
+ shape3->setLeftBarColorProvider(this, 1);
+ shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58);
+
+
+// shape3->setBottomBarColorProvider(this, 2);
+// shape3->setLeftBarColorProvider(this, 2);
+// shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58);
+
+ // The milestones are still the same than those define above
+ //milestones.push_back( GradientMilestone(0., 0., 0., 0.) );
+ //milestones.push_back( GradientMilestone(1., 1., 1., 1.) );
+ shape->setBottomBarBgGradient(milestones);
+ shape->setLeftBarBgGradient(milestones);
+ shape2->setBottomBarBgGradient(milestones);
+ shape2->setLeftBarBgGradient(milestones);
+
+ std::vector shape3Milestones;
+ float R, G, B;
+ for (int i=0; i<7; i++) {
+ float x = float(i)*(1.0f/6.0);
+ Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B);
+ shape3Milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) );
+ }
+ shape3->setBottomBarBgGradient(shape3Milestones);
+ shape3->setLeftBarBgGradient(shape3Milestones);
+
+ shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58);
+
+ curveEditorG->curveListComplete();
+
+ curveEditorG2->curveListComplete();
+ curveEditorG2->setTooltip(M("TP_COLORAPP_CURVEEDITOR2_TOOLTIP"));
+
+ curveEditorG3->curveListComplete();
+ curveEditorG3->setTooltip(M("TP_COLORAPP_CURVEEDITOR3_TOOLTIP"));
+ tcmode3conn = toneCurveMode3->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode3Changed), true );
+
+ p2VBox->pack_start( *curveEditorG, Gtk::PACK_SHRINK, 2);
+ p2VBox->pack_start( *curveEditorG2, Gtk::PACK_SHRINK, 2);
+ p2VBox->pack_start( *curveEditorG3, Gtk::PACK_SHRINK, 2);
p2Frame->add(*p2VBox);
pack_start (*p2Frame, Gtk::PACK_EXPAND_WIDGET, 4);
@@ -221,18 +312,18 @@ Colorappearance::Colorappearance () : Gtk::VBox(), FoldableToolPanel(this) {
gamut = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_GAMUT")));
gamut->set_tooltip_markup (M("TP_COLORAPP_GAMUT_TOOLTIP"));
- gamutconn = gamut->signal_toggled().connect( sigc::mem_fun(*this, &Colorappearance::gamut_toggled) );
+ gamutconn = gamut->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::gamut_toggled) );
pack_start (*gamut, Gtk::PACK_SHRINK);
// ------------------------ Listening events
- surrconn = surrsource->signal_toggled().connect( sigc::mem_fun(*this, &Colorappearance::surrsource_toggled) );
- enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &Colorappearance::enabledChanged) );
- wbmodelconn = wbmodel->signal_changed().connect ( sigc::mem_fun(*this, &Colorappearance::wbmodelChanged) );
- algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &Colorappearance::algoChanged) );
- surroundconn = surround->signal_changed().connect ( sigc::mem_fun(*this, &Colorappearance::surroundChanged) );
+ surrconn = surrsource->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::surrsource_toggled) );
+ enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::enabledChanged) );
+ wbmodelconn = wbmodel->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::wbmodelChanged) );
+ algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::algoChanged) );
+ surroundconn = surround->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::surroundChanged) );
degree->setAdjusterListener (this);
adapscen->setAdjusterListener (this);
@@ -250,17 +341,35 @@ Colorappearance::Colorappearance () : Gtk::VBox(), FoldableToolPanel(this) {
show_all();
}
-bool Colorappearance::bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) {
+ColorAppearance::~ColorAppearance () {
+ delete curveEditorG;
+ delete curveEditorG2;
+ delete curveEditorG3;
+}
+
+
+
+bool ColorAppearance::bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) {
return true;
}
-bool Colorappearance::srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) {
+bool ColorAppearance::srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) {
return true;
}
-void Colorappearance::read (const ProcParams* pp, const ParamsEdited* pedited) {
+void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) {
disableListener ();
+ tcmodeconn.block(true);
+ tcmode2conn.block(true);
+ tcmode3conn.block(true);
+ shape->setCurve (pp->colorappearance.curve);
+ shape2->setCurve (pp->colorappearance.curve2);
+ shape3->setCurve (pp->colorappearance.curve3);
+ toneCurveMode->set_active(pp->colorappearance.curveMode);
+ toneCurveMode2->set_active(pp->colorappearance.curveMode2);
+ toneCurveMode3->set_active(pp->colorappearance.curveMode3);
+ curveMode3Changed(); // This will set the correct sensitive state of depending Adjusters
if (pedited) {
degree->setEditedState (pedited->colorappearance.degree ? Edited : UnEdited);
@@ -280,7 +389,21 @@ void Colorappearance::read (const ProcParams* pp, const ParamsEdited* pedited) {
degree->setAutoInconsistent (multiImage && !pedited->colorappearance.autodegree);
enabled->set_inconsistent (multiImage && !pedited->colorappearance.enabled);
- }
+ shape->setUnChanged (!pedited->colorappearance.curve);
+ shape2->setUnChanged (!pedited->colorappearance.curve2);
+ shape3->setUnChanged (!pedited->colorappearance.curve3);
+ if (!pedited->colorappearance.curveMode) {
+ toneCurveMode->set_active(2);
+ }
+ if (!pedited->colorappearance.curveMode2) {
+ toneCurveMode2->set_active(2);
+ }
+ if (!pedited->colorappearance.curveMode3) {
+ toneCurveMode3->set_active(3);
+ }
+
+
+ }
enaConn.block (true);
enabled->set_active (pp->colorappearance.enabled);
@@ -304,8 +427,6 @@ void Colorappearance::read (const ProcParams* pp, const ParamsEdited* pedited) {
wbmodelconn.block(true);
if (pedited && !pedited->colorappearance.wbmodel)
wbmodel->set_active (2);
-// else if (pp->colorappearance.wbmodel=="Equal")
-// wbmodel->set_active (0);
else if (pp->colorappearance.wbmodel=="RawT")
wbmodel->set_active (0);
else if (pp->colorappearance.wbmodel=="RawTCAT02")
@@ -356,28 +477,53 @@ void Colorappearance::read (const ProcParams* pp, const ParamsEdited* pedited) {
qcontrast->setValue (pp->colorappearance.qcontrast);
colorh->setValue (pp->colorappearance.colorh);
+ tcmode3conn.block(false);
+ tcmode2conn.block(false);
+ tcmodeconn.block(false);
enableListener ();
}
+void ColorAppearance::autoOpenCurve () {
+ shape->openIfNonlinear();
+ shape2->openIfNonlinear();
+ shape3->openIfNonlinear();
-void Colorappearance::write (ProcParams* pp, ParamsEdited* pedited) {
+}
- pp->colorappearance.degree = degree->getValue ();
- pp->colorappearance.autodegree = degree->getAutoValue ();
- pp->colorappearance.enabled = enabled->get_active();
- pp->colorappearance.adapscen = adapscen->getValue ();
- pp->colorappearance.adaplum = adaplum->getValue ();
- pp->colorappearance.jlight = jlight->getValue ();
- pp->colorappearance.qbright = qbright->getValue ();
- pp->colorappearance.chroma = chroma->getValue ();
- pp->colorappearance.schroma = schroma->getValue ();
- pp->colorappearance.mchroma = mchroma->getValue ();
- pp->colorappearance.contrast = contrast->getValue ();
- pp->colorappearance.qcontrast = qcontrast->getValue ();
- pp->colorappearance.colorh = colorh->getValue ();
- pp->colorappearance.rstprotection = rstprotection->getValue ();
+void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited) {
+
+ pp->colorappearance.degree = degree->getValue ();
+ pp->colorappearance.autodegree = degree->getAutoValue ();
+ pp->colorappearance.enabled = enabled->get_active();
+ pp->colorappearance.adapscen = adapscen->getValue ();
+ pp->colorappearance.adaplum = adaplum->getValue ();
+ pp->colorappearance.jlight = jlight->getValue ();
+ pp->colorappearance.qbright = qbright->getValue ();
+ pp->colorappearance.chroma = chroma->getValue ();
+ pp->colorappearance.schroma = schroma->getValue ();
+ pp->colorappearance.mchroma = mchroma->getValue ();
+ pp->colorappearance.contrast = contrast->getValue ();
+ pp->colorappearance.qcontrast = qcontrast->getValue ();
+ pp->colorappearance.colorh = colorh->getValue ();
+ pp->colorappearance.rstprotection = rstprotection->getValue ();
pp->colorappearance.surrsource = surrsource->get_active();
- pp->colorappearance.gamut = gamut->get_active();
+ pp->colorappearance.gamut = gamut->get_active();
+ pp->colorappearance.curve = shape->getCurve ();
+ pp->colorappearance.curve2 = shape2->getCurve ();
+ pp->colorappearance.curve3 = shape3->getCurve ();
+
+ int tcMode = toneCurveMode->get_active_row_number();
+ if (tcMode == 0) pp->colorappearance.curveMode = ColorAppearanceParams::TC_MODE_LIGHT;
+ else if (tcMode == 1) pp->colorappearance.curveMode = ColorAppearanceParams::TC_MODE_BRIGHT;
+
+ tcMode = toneCurveMode2->get_active_row_number();
+ if (tcMode == 0) pp->colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_LIGHT;
+ else if (tcMode == 1) pp->colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_BRIGHT;
+
+ int tcMode3 = toneCurveMode3->get_active_row_number();
+ if (tcMode3 == 0) pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_CHROMA;
+ else if (tcMode3 == 1) pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_SATUR;
+ else if (tcMode3 == 2) pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_COLORF;
if (pedited) {
pedited->colorappearance.degree = degree->getEditedState ();
@@ -399,6 +545,12 @@ void Colorappearance::write (ProcParams* pp, ParamsEdited* pedited) {
pedited->colorappearance.algo = algo->get_active_text()!=M("GENERAL_UNCHANGED");
pedited->colorappearance.surrsource = !surrsource->get_inconsistent();
pedited->colorappearance.gamut = !gamut->get_inconsistent();
+ pedited->colorappearance.curve = !shape->isUnChanged ();
+ pedited->colorappearance.curve2 = !shape2->isUnChanged ();
+ pedited->colorappearance.curve3 = !shape3->isUnChanged ();
+ pedited->colorappearance.curveMode = toneCurveMode->get_active_row_number() != 2;
+ pedited->colorappearance.curveMode2 = toneCurveMode2->get_active_row_number() != 2;
+ pedited->colorappearance.curveMode3 = toneCurveMode3->get_active_row_number() != 3;
}
if (surround->get_active_row_number()==0)
pp->colorappearance.surround = "Average";
@@ -409,8 +561,6 @@ void Colorappearance::write (ProcParams* pp, ParamsEdited* pedited) {
else if (surround->get_active_row_number()==3)
pp->colorappearance.surround = "ExtremelyDark";
-// if (wbmodel->get_active_row_number()==0)
-// pp->colorappearance.wbmodel = "Equal";
if (wbmodel->get_active_row_number()==0)
pp->colorappearance.wbmodel = "RawT";
else if (wbmodel->get_active_row_number()==1)
@@ -426,8 +576,53 @@ void Colorappearance::write (ProcParams* pp, ParamsEdited* pedited) {
pp->colorappearance.algo = "ALL";
}
+void ColorAppearance::curveChanged (CurveEditor* ce) {
-void Colorappearance::surrsource_toggled () {
+ if (listener) {
+ if (ce == shape)
+ listener->panelChanged (EvCATCurve1, M("HISTORY_CUSTOMCURVE"));
+ else if (ce == shape2)
+ listener->panelChanged (EvCATCurve2, M("HISTORY_CUSTOMCURVE"));
+ else if (ce == shape3)
+ listener->panelChanged (EvCATCurve3, M("HISTORY_CUSTOMCURVE"));
+ }
+}
+
+void ColorAppearance::curveMode1Changed () {
+ if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode1Changed_));
+}
+
+bool ColorAppearance::curveMode1Changed_ () {
+ if (listener) listener->panelChanged (EvCATCurveMode1, toneCurveMode->get_active_text());
+ return false;
+}
+
+void ColorAppearance::curveMode2Changed () {
+ if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode2Changed_));
+}
+
+bool ColorAppearance::curveMode2Changed_ () {
+ if (listener) listener->panelChanged (EvCATCurveMode2, toneCurveMode2->get_active_text());
+ return false;
+}
+
+void ColorAppearance::curveMode3Changed () {
+ int tcMode3 = toneCurveMode3->get_active_row_number();
+ if (tcMode3 == 0) {chroma->set_sensitive(true); schroma->set_sensitive(true); }
+ else if (tcMode3 == 2) {chroma->set_sensitive(false); schroma->set_sensitive(false);}
+ else if (tcMode3 == 1) {chroma->set_sensitive(false); schroma->set_sensitive(true); }
+
+ if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode3Changed_));
+}
+
+bool ColorAppearance::curveMode3Changed_ () {
+ if (listener) {
+ listener->panelChanged (EvCATCurveMode3, toneCurveMode3->get_active_text());
+ }
+ return false;
+}
+
+void ColorAppearance::surrsource_toggled () {
if (batchMode) {
if (surrsource->get_inconsistent()) {
@@ -450,7 +645,7 @@ void Colorappearance::surrsource_toggled () {
}
}
-void Colorappearance::gamut_toggled () {
+void ColorAppearance::gamut_toggled () {
if (batchMode) {
if (gamut->get_inconsistent()) {
@@ -474,7 +669,7 @@ void Colorappearance::gamut_toggled () {
}
-void Colorappearance::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
+void ColorAppearance::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
degree->setDefault (defParams->colorappearance.degree);
adapscen->setDefault (defParams->colorappearance.adapscen);
@@ -521,7 +716,22 @@ void Colorappearance::setDefaults (const ProcParams* defParams, const ParamsEdit
}
}
-void Colorappearance::adjusterChanged (Adjuster* a, double newval) {
+void ColorAppearance::colorForValue (double valX, double valY, int callerId, ColorCaller *caller) {
+
+ float R, G, B;
+ if (callerId == 1) { // cc - bottom bar
+
+ float value = (1.f - 0.7f) * float(valX) + 0.7f;
+ // whole hue range
+ // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before)
+ Color::hsv2rgb01(float(valY), float(valX), value, R, G, B);
+ }
+ caller->ccRed = double(R);
+ caller->ccGreen = double(G);
+ caller->ccBlue = double(B);
+}
+
+void ColorAppearance::adjusterChanged (Adjuster* a, double newval) {
if (listener && (multiImage||enabled->get_active()) ) {
if(a==degree)
@@ -552,7 +762,7 @@ void Colorappearance::adjusterChanged (Adjuster* a, double newval) {
}
}
-void Colorappearance::adjusterAutoToggled (Adjuster* a, bool newval) {
+void ColorAppearance::adjusterAutoToggled (Adjuster* a, bool newval) {
if (multiImage) {
if (degree->getAutoInconsistent()) {
@@ -577,7 +787,7 @@ void Colorappearance::adjusterAutoToggled (Adjuster* a, bool newval) {
}
}
-void Colorappearance::enabledChanged () {
+void ColorAppearance::enabledChanged () {
if (multiImage) {
if (enabled->get_inconsistent()) {
@@ -595,28 +805,32 @@ void Colorappearance::enabledChanged () {
if (listener) {
if (enabled->get_inconsistent())
listener->panelChanged (EvCATEnabled, M("GENERAL_UNCHANGED"));
- else if (enabled->get_active ())
+ else if (enabled->get_active ()) {
listener->panelChanged (EvCATEnabled, M("GENERAL_ENABLED"));
+ curveEditorG->set_sensitive (true);
+ toneCurveMode->set_sensitive (true);
+ }
else
listener->panelChanged (EvCATEnabled, M("GENERAL_DISABLED"));
}
}
-void Colorappearance::surroundChanged () {
+void ColorAppearance::surroundChanged () {
if (listener && (multiImage||enabled->get_active()) ) {
listener->panelChanged (EvCATMethodsur, surround->get_active_text ());
}
}
-void Colorappearance::wbmodelChanged () {
+void ColorAppearance::wbmodelChanged () {
if (listener && (multiImage||enabled->get_active()) ) {
listener->panelChanged (EvCATMethodWB, wbmodel->get_active_text ());
}
}
-void Colorappearance::algoChanged () {
+
+void ColorAppearance::algoChanged () {
if ( algo->get_active_row_number()==0 ) {
contrast->show();
@@ -628,9 +842,12 @@ void Colorappearance::algoChanged () {
schroma->hide();
qbright->hide();
colorh->hide();
+ curveEditorG->show();
+ curveEditorG2->show();
+ curveEditorG3->show();
}
else if ( algo->get_active_row_number()==1 ) {
- rstprotection->hide();
+ rstprotection->show();
contrast->show();
qcontrast->hide();
jlight->show();
@@ -639,10 +856,13 @@ void Colorappearance::algoChanged () {
schroma->show();
qbright->hide();
colorh->hide();
+ curveEditorG->show();
+ curveEditorG2->show();
+ curveEditorG3->show();
}
else if ( algo->get_active_row_number()==2 ) {
contrast->hide();
- rstprotection->hide();
+ rstprotection->show();
qcontrast->show();
jlight->hide();
mchroma->show();
@@ -650,6 +870,9 @@ void Colorappearance::algoChanged () {
schroma->hide();
qbright->show();
colorh->hide();
+ curveEditorG->show();
+ curveEditorG2->show();
+ curveEditorG3->show();
}
else if ( algo->get_active_row_number()>=3 ) { // ">=3" because everything has to be visible with the "(unchanged)" option too
contrast->show();
@@ -661,6 +884,9 @@ void Colorappearance::algoChanged () {
schroma->show();
qbright->show();
colorh->show();
+ curveEditorG->show();
+ curveEditorG2->show();
+ curveEditorG3->show();
}
if (listener && (multiImage||enabled->get_active()) ) {
@@ -668,7 +894,7 @@ void Colorappearance::algoChanged () {
}
}
-void Colorappearance::setBatchMode (bool batchMode) {
+void ColorAppearance::setBatchMode (bool batchMode) {
ToolPanel::setBatchMode (batchMode);
@@ -688,10 +914,16 @@ void Colorappearance::setBatchMode (bool batchMode) {
surround->append_text (M("GENERAL_UNCHANGED"));
wbmodel->append_text (M("GENERAL_UNCHANGED"));
algo->append_text (M("GENERAL_UNCHANGED"));
-
+ toneCurveMode->append_text (M("GENERAL_UNCHANGED"));
+// toneCurveMode2->append_text (M("GENERAL_UNCHANGED"));
+// toneCurveMode3->append_text (M("GENERAL_UNCHANGED"));
+
+ curveEditorG->setBatchMode (batchMode);
+// curveEditorG2->setBatchMode (batchMode);
+// curveEditorG3->setBatchMode (batchMode);
}
-void Colorappearance::setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd) {
+void ColorAppearance::setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd) {
degree->setAddMode(degreeadd);
adapscen->setAddMode(adapscenadd);
@@ -705,10 +937,9 @@ void Colorappearance::setAdjusterBehavior (bool degreeadd, bool adapscenadd, boo
contrast->setAddMode(contrastadd);
qcontrast->setAddMode(qcontrastadd);
colorh->setAddMode(colorhadd);
-
}
-void Colorappearance::trimValues (rtengine::procparams::ProcParams* pp) {
+void ColorAppearance::trimValues (rtengine::procparams::ProcParams* pp) {
degree->trimValue(pp->colorappearance.degree);
adapscen->trimValue(pp->colorappearance.adapscen);
@@ -722,5 +953,4 @@ void Colorappearance::trimValues (rtengine::procparams::ProcParams* pp) {
contrast->trimValue(pp->colorappearance.contrast);
qcontrast->trimValue(pp->colorappearance.qcontrast);
colorh->trimValue(pp->colorappearance.colorh);
-
}
diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h
index c49103554..e0c6025c3 100644
--- a/rtgui/colorappearance.h
+++ b/rtgui/colorappearance.h
@@ -22,12 +22,17 @@
#include
#include "adjuster.h"
#include "toolpanel.h"
+#include "curveeditor.h"
+#include "curveeditorgroup.h"
+#include "mycurve.h"
+#include "guiutils.h"
+#include "colorprovider.h"
-class Colorappearance : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel {
+class ColorAppearance : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider {
protected:
- Glib::RefPtr bgTTips;
- Glib::RefPtr srTTips;
+ Glib::RefPtr bgTTips;
+ Glib::RefPtr srTTips;
Glib::RefPtr bgPixbuf;
Glib::RefPtr srPixbuf;
@@ -43,32 +48,44 @@ class Colorappearance : public Gtk::VBox, public AdjusterListener, public Foldab
Adjuster* contrast;
Adjuster* qcontrast;
Adjuster* colorh;
+ MyComboBoxText* toneCurveMode;
+ MyComboBoxText* toneCurveMode2;
+ MyComboBoxText* toneCurveMode3;
//Adjuster* edge;
- Gtk::CheckButton* surrsource;
- Gtk::CheckButton* gamut;
-
+ Gtk::CheckButton* surrsource;
+ Gtk::CheckButton* gamut;
+
Gtk::CheckButton* enabled;
- MyComboBoxText* surround;
- sigc::connection surroundconn;
- MyComboBoxText* wbmodel;
- sigc::connection wbmodelconn;
- MyComboBoxText* algo;
- sigc::connection algoconn;
- sigc::connection surrconn;
- sigc::connection gamutconn;
+ MyComboBoxText* surround;
+ sigc::connection surroundconn;
+ MyComboBoxText* wbmodel;
+ sigc::connection wbmodelconn;
+ MyComboBoxText* algo;
+ sigc::connection algoconn;
+ sigc::connection surrconn;
+ sigc::connection gamutconn;
+ sigc::connection tcmodeconn, tcmode2conn, tcmode3conn;
+ CurveEditorGroup* curveEditorG;
+ CurveEditorGroup* curveEditorG2;
+ CurveEditorGroup* curveEditorG3;
+
+ DiagonalCurveEditor* shape;
+ DiagonalCurveEditor* shape2;
+ DiagonalCurveEditor* shape3;
bool lastEnabled;
bool lastAutoDegree;
sigc::connection enaConn;
- bool lastsurr;
- bool lastgamut;
+ bool lastsurr;
+ bool lastgamut;
bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
bool srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
public:
- Colorappearance ();
+ ColorAppearance ();
+ ~ColorAppearance ();
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
@@ -78,13 +95,27 @@ class Colorappearance : public Gtk::VBox, public AdjusterListener, public Foldab
void adjusterChanged (Adjuster* a, double newval);
void adjusterAutoToggled (Adjuster* a, bool newval);
void enabledChanged ();
- void surroundChanged ();
+ void surroundChanged ();
void wbmodelChanged ();
- void algoChanged ();
- void surrsource_toggled ();
- void gamut_toggled ();
+ void algoChanged ();
+ void surrsource_toggled ();
+ void gamut_toggled ();
+ void curveChanged (CurveEditor* ce);
+ void curveMode1Changed ();
+ bool curveMode1Changed_ ();
+ void curveMode2Changed ();
+ bool curveMode2Changed_ ();
+ void curveMode3Changed ();
+ bool curveMode3Changed_ ();
+
+ void expandCurve (bool isExpanded);
+ bool isCurveExpanded ();
+ void autoOpenCurve ();
+
void setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd);
void trimValues (rtengine::procparams::ProcParams* pp);
+
+ virtual void colorForValue (double valX, double valY, int callerId, ColorCaller *caller);
};
#endif
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 41871b2c6..853a8728d 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -112,6 +112,12 @@ void ParamsEdited::set (bool v) {
colorappearance.rstprotection = v;
colorappearance.surrsource = v;
colorappearance.gamut = v;
+ colorappearance.curve = v;
+ colorappearance.curve2 = v;
+ colorappearance.curve3 = v;
+ colorappearance.curveMode = v;
+ colorappearance.curveMode2 = v;
+ colorappearance.curveMode3 = v;
//colorBoost.amount = v;
//colorBoost.avoidclip = v;
@@ -335,6 +341,12 @@ void ParamsEdited::initFrom (const std::vector
colorappearance.colorh = colorappearance.colorh && p.colorappearance.colorh == other.colorappearance.colorh;
colorappearance.surrsource = colorappearance.surrsource && p.colorappearance.surrsource == other.colorappearance.surrsource;
colorappearance.gamut = colorappearance.gamut && p.colorappearance.gamut == other.colorappearance.gamut;
+ colorappearance.curve = colorappearance.curve && p.colorappearance.curve == other.colorappearance.curve;
+ colorappearance.curve3 = colorappearance.curve3 && p.colorappearance.curve3 == other.colorappearance.curve3;
+ colorappearance.curve2 = colorappearance.curve2 && p.colorappearance.curve2 == other.colorappearance.curve2;
+ colorappearance.curveMode = colorappearance.curveMode && p.colorappearance.curveMode == other.colorappearance.curveMode;
+ colorappearance.curveMode2 = colorappearance.curveMode2 && p.colorappearance.curveMode2 == other.colorappearance.curveMode2;
+ colorappearance.curveMode3 = colorappearance.curveMode3 && p.colorappearance.curveMode3 == other.colorappearance.curveMode3;
//colorBoost.amount = colorBoost.amount && p.colorBoost.amount == other.colorBoost.amount;
//colorBoost.avoidclip = colorBoost.avoidclip && p.colorBoost.avoidclip == other.colorBoost.avoidclip;
@@ -566,6 +578,13 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (defringe.enabled) toEdit.defringe.enabled = mods.defringe.enabled;
if (defringe.radius) toEdit.defringe.radius = mods.defringe.radius;
if (defringe.threshold) toEdit.defringe.threshold = mods.defringe.threshold;
+
+ if (colorappearance.curve) toEdit.colorappearance.curve = mods.colorappearance.curve;
+ if (colorappearance.curve2) toEdit.colorappearance.curve2 = mods.colorappearance.curve2;
+ if (colorappearance.curve3) toEdit.colorappearance.curve3 = mods.colorappearance.curve3;
+ if (colorappearance.curveMode) toEdit.colorappearance.curveMode = mods.colorappearance.curveMode;
+ if (colorappearance.curveMode2) toEdit.colorappearance.curveMode2 = mods.colorappearance.curveMode2;
+ if (colorappearance.curveMode3) toEdit.colorappearance.curveMode3 = mods.colorappearance.curveMode3;
if (colorappearance.enabled) toEdit.colorappearance.enabled = mods.colorappearance.enabled;
if (colorappearance.degree) toEdit.colorappearance.degree = dontforceSet && options.baBehav[ADDSET_CAT_DEGREE] ? toEdit.colorappearance.degree + mods.colorappearance.degree : mods.colorappearance.degree;
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index 5caed7a3b..c3d909904 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -181,9 +181,15 @@ public:
bool thresh;
};
-class ColorappearanceParamsEdited {
+class ColorAppearanceParamsEdited {
public:
+ bool curve;
+ bool curve2;
+ bool curve3;
+ bool curveMode;
+ bool curveMode2;
+ bool curveMode3;
bool enabled;
bool degree;
bool autodegree;
@@ -411,7 +417,7 @@ class ParamsEdited {
SharpenEdgeParamsEdited sharpenEdge;
SharpenMicroParamsEdited sharpenMicro;
VibranceParamsEdited vibrance;
- ColorappearanceParamsEdited colorappearance;
+ ColorAppearanceParamsEdited colorappearance;
//ColorBoostParamsEdited colorBoost;
WBParamsEdited wb;
//ColorShiftParamsEdited colorShift;
diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc
index f64a2a8c1..036263202 100644
--- a/rtgui/preferences.cc
+++ b/rtgui/preferences.cc
@@ -436,6 +436,9 @@ Gtk::Widget* Preferences::getColorManagementPanel () {
view->append_text (M("PREFERENCES_D60"));
view->append_text (M("PREFERENCES_D65"));
view->append_text (M("PREFERENCES_BLACKBODY"));
+ view->append_text (M("PREFERENCES_FLUOF2"));
+ view->append_text (M("PREFERENCES_FLUOF7"));
+ view->append_text (M("PREFERENCES_FLUOF11"));
Gtk::Label* greylab = Gtk::manage (new Gtk::Label (M("PREFERENCES_GREY")+":", Gtk::ALIGN_LEFT));
grey = Gtk::manage (new Gtk::ComboBoxText ());
diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc
index c5eeae589..98851937f 100644
--- a/rtgui/toolpanelcoord.cc
+++ b/rtgui/toolpanelcoord.cc
@@ -56,7 +56,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
distortion = Gtk::manage (new Distortion ());
rotate = Gtk::manage (new Rotate ());
vibrance = Gtk::manage (new Vibrance ());
- colorappearance = Gtk::manage (new Colorappearance ());
+ colorappearance = Gtk::manage (new ColorAppearance ());
whitebalance = Gtk::manage (new WhiteBalance ());
vignetting = Gtk::manage (new Vignetting ());
perspective = Gtk::manage (new PerspCorrection ());
diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h
index 31f0fe168..857330a70 100644
--- a/rtgui/toolpanelcoord.h
+++ b/rtgui/toolpanelcoord.h
@@ -91,7 +91,7 @@ class ToolPanelCoordinator : public ToolPanelListener,
PerspCorrection* perspective;
CACorrection* cacorrection;
HLRecovery* hlrecovery;
- Colorappearance* colorappearance;
+ ColorAppearance* colorappearance;
Vibrance* vibrance;
ChMixer* chmixer;
Resize* resize;