diff --git a/rtdata/profiles/Neutral.pp3 b/rtdata/profiles/Neutral.pp3 index f985bad8d..758ca88a1 100644 --- a/rtdata/profiles/Neutral.pp3 +++ b/rtdata/profiles/Neutral.pp3 @@ -32,7 +32,7 @@ Brightness=0 Contrast=0 Chromaticity=0 BWtoning=false -AvoidColorShift=true +AvoidColorShift=false RedAndSkinTonesProtection=0 LCredsk=true LCurve=0; diff --git a/rtengine/color.cc b/rtengine/color.cc index ffa5808f3..b66654946 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; /* * Munsell Lch correction * Copyright (c) 2011 Jacques Desmis @@ -402,8 +402,10 @@ namespace rtengine { float fz = fy - (0.005 * b); x = 65535.0*f2xyz(fx)*D50x; - y = 65535.0*f2xyz(fy); + // y = 65535.0*f2xyz(fy); z = 65535.0*f2xyz(fz)*D50z; + y=(L>epskap) ? 65535.0*fy*fy*fy : 65535.0*L/kappa; + } void Color::XYZ2Lab(float X, float Y, float Z, float &L, float &a, float &b) { @@ -411,9 +413,9 @@ namespace rtengine { float X1 = X/D50x; float Z1 = Z/D50z; - float fx = (X1<65535.0 ? cachef[X1] : (327.68*exp(log(X1/MAXVAL)/3.0 ))); - float fy = (Y<65535.0 ? cachef[Y] : (327.68*exp(log(Y/MAXVAL)/3.0 ))); - float fz = (Z1<65535.0 ? cachef[Z1] : (327.68*exp(log(Z1/MAXVAL)/3.0 ))); + float fx = (X1<65535.0 ? (cachef[std::max(X1,0.f)]) : (327.68*exp(log(X1/MAXVAL)/3.0 ))); + float fy = (Y<65535.0 ? (cachef[std::max(Y,0.f)]) : (327.68*exp(log(Y/MAXVAL)/3.0 ))); + float fz = (Z1<65535.0 ? (cachef[std::max(Z1,0.f)]) : (327.68*exp(log(Z1/MAXVAL)/3.0 ))); L = (116.0 * fy - 5242.88); //5242.88=16.0*327.68; a = (500.0 * (fx - fy) ); @@ -425,10 +427,12 @@ namespace rtengine { float fy = (0.00862069 * L/327.68) + 0.137932; // (L+16)/116 float fx = (0.002 * a/327.68) + fy; float fz = fy - (0.005 * b/327.68); + float LL=L/327.68; float X = 65535.0*f2xyz(fx)*D50x; - Y = 65535.0*f2xyz(fy); + // Y = 65535.0*f2xyz(fy); float Z = 65535.0*f2xyz(fz)*D50z; + Y=(LL>epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/kappa; u = 4.0*X/(X+15*Y+3*Z)-u0; v = 9.0*Y/(X+15*Y+3*Z)-v0; @@ -669,7 +673,7 @@ namespace rtengine { void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) #endif { - const float ClipLevel = 65534.5f; + const float ClipLevel = 65535.0f; bool inGamut; #ifdef _DEBUG neg=false, more_rgb=false; @@ -687,8 +691,10 @@ namespace rtengine { float fz = fy - (0.005f * bprov1); float x_ = 65535.0f * f2xyz(fx)*D50x; - float y_ = 65535.0f * f2xyz(fy); + // 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; + xyz2rgb(x_,y_,z_,R,G,B,wip); // gamut control before saturation to put Lab values in future gamut, but not RGB @@ -696,23 +702,19 @@ namespace rtengine { #ifdef _DEBUG neg=true; #endif - if (Lprov1 < 0.01f) - Lprov1 = 0.05f; + if (Lprov1 < 0.01f) Lprov1 = 0.01f; Chprov1 *= higherCoef; // decrease the chromaticity value - if (Chprov1 <= 3.0f) - Lprov1 += lowerCoef; + if (Chprov1 <= 3.0f) Lprov1 += lowerCoef; inGamut = false; - } + } else // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut - else if (!isHLEnabled && (R>ClipLevel || G>ClipLevel || B>ClipLevel) && (R<=ClipLevel || G<=ClipLevel || B<=ClipLevel)) { + if (!isHLEnabled && (R>ClipLevel || G>ClipLevel || B>ClipLevel)) { #ifdef _DEBUG more_rgb=true; #endif - if (Lprov1 > 99.99f) - Lprov1 = 99.8f; + if (Lprov1 > 99.999f) Lprov1 = 99.98f; Chprov1 *= higherCoef; - if (Chprov1 <= 3.0f) - Lprov1 -= lowerCoef; + if (Chprov1 <= 3.0f) Lprov1 -= lowerCoef; inGamut = false; } } @@ -783,9 +785,9 @@ namespace rtengine { //gamut control : Lab values are in gamut #ifdef _DEBUG - gamutLchonly(HH, Lprov1, Chprov1, R, G, B, wip, isHLEnabled, 0.4f, 0.95f, neg, more_rgb); + gamutLchonly(HH, Lprov1, Chprov1, R, G, B, wip, isHLEnabled, 0.15f, 0.96f, neg, more_rgb); #else - gamutLchonly(HH, Lprov1, Chprov1, R, G, B, wip, isHLEnabled, 0.4f, 0.95f); + gamutLchonly(HH, Lprov1, Chprov1, R, G, B, wip, isHLEnabled, 0.15f, 0.96f); #endif #ifdef _DEBUG diff --git a/rtengine/color.h b/rtengine/color.h index 0e5c00f54..e3834a7cb 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -88,7 +88,7 @@ private: public: const static double sRGBGamma; // standard average gamma const static double sRGBGammaCurve; // 2.4 in the curve - const static double eps_max, kappa; + const static double eps_max, kappa, epskap; const static float D50x, D50z; const static double u0, v0; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 0ce21cd38..b50340ac2 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -423,21 +423,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, LUTf & hltone float fx,fy,fz; - //if (x>0) { - fx = (x<65535.0f ? cachef[x] : (327.68f*exp(log(x/MAXVAL)/3.0f ))); - //} else { - // fx = (x>-65535.0 ? -cachef[-x] : (-327.68*exp(log(-x/MAXVAL)/3.0 ))); - //} - //if (y>0) { - fy = (y<65535.0f ? cachef[y] : (327.68f*exp(log(y/MAXVAL)/3.0f ))); - //} else { - // fy = (y>-65535.0 ? -cachef[-y] : (-327.68*exp(log(-y/MAXVAL)/3.0 ))); - //} - //if (z>0) { - fz = (z<65535.0f ? cachef[z] : (327.68f*exp(log(z/MAXVAL)/3.0f ))); - //} else { - // fz = (z>-65535.0 ? -cachef[-z] : (-327.68*exp(log(-z/MAXVAL)/3.0 ))); - //} + fx = (x<65535.0f ? cachef[std::max(x,0.f)] : (327.68f*exp(log(x/MAXVAL)/3.0f ))); + fy = (y<65535.0f ? cachef[std::max(y,0.f)] : (327.68f*exp(log(y/MAXVAL)/3.0f ))); + fz = (z<65535.0f ? cachef[std::max(z,0.f)] : (327.68f*exp(log(z/MAXVAL)/3.0f ))); lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; lab->a[i][j] = (500.0f * (fx - fy) ); @@ -744,10 +732,10 @@ void ImProcFunctions::chromiLuminanceCurve (LabImage* lold, LabImage* lnew, LUTf 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.4f, 0.95f, neg, more_rgb); + 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.4f, 0.95f); + Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); #endif lnew->L[i][j]=Lprov1*327.68f; diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index c77d1b6a0..f0025a26b 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -27,6 +27,7 @@ #include "settings.h" #include "curves.h" #include "alignedbuffer.h" +#include "color.h" #ifdef _OPENMP @@ -66,16 +67,18 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) { float* ra = lab->a[i]; float* rb = lab->b[i]; - float fy,fx,fz,x_,y_,z_; + float fy,fx,fz,x_,y_,z_,LL; for (int j=0; jW; j++) { fy = (0.00862069 * rL[j]) / 327.68 + 0.137932; // (L+16)/116 fx = (0.002 * ra[j]) / 327.68 + fy; fz = fy - (0.005 * rb[j]) / 327.68; - + LL=rL[j]/327.68; x_ = Color::f2xyz(fx)*Color::D50x; - y_ = Color::f2xyz(fy); + //y_ = Color::f2xyz(fy); + y_= (LL>Color::epskap) ? fy*fy*fy : LL/Color::kappa; + z_ = Color::f2xyz(fz)*Color::D50z; buffer[iy++] = (unsigned short)CLIP(x_* MAXVAL+0.5); @@ -98,7 +101,7 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) { int ix = i * 3 * lab->W; float R,G,B; - float fy,fx,fz,x_,y_,z_; + float fy,fx,fz,x_,y_,z_,LL; for (int j=0; jW; j++) { @@ -107,10 +110,12 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) { fy = (0.00862069 * rL[j]) / 327.68 + 0.137932; // (L+16)/116 fx = (0.002 * ra[j]) / 327.68 + fy; fz = fy - (0.005 * rb[j]) / 327.68; + LL=rL[j]/327.68; x_ = 65535.0 * Color::f2xyz(fx)*Color::D50x; - y_ = 65535.0 * Color::f2xyz(fy); + // y_ = 65535.0 * Color::f2xyz(fy); z_ = 65535.0 * Color::f2xyz(fz)*Color::D50z; + y_= (LL>Color::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; Color::xyz2srgb(x_,y_,z_,R,G,B); @@ -164,10 +169,12 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, float fy = (0.00862069 * rL[j])/327.68 + 0.137932; // (L+16)/116 float fx = (0.002 * ra[j])/327.68 + fy; float fz = fy - (0.005 * rb[j])/327.68; + float LL=rL[j]/327.68; float x_ = 65535.0 * Color::f2xyz(fx)*Color::D50x; - float y_ = 65535.0 * Color::f2xyz(fy); + //float y_ = 65535.0 * Color::f2xyz(fy); float z_ = 65535.0 * Color::f2xyz(fz)*Color::D50z; + float y_= (LL>Color::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; buffer[iy++] = CLIP((int)(x_+0.5)); buffer[iy++] = CLIP((int)(y_+0.5)); @@ -204,10 +211,12 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, float fy = (0.00862069 * rL[j])/327.68 + 0.137932; // (L+16)/116 float fx = (0.002 * ra[j])/327.68 + fy; float fz = fy - (0.005 * rb[j])/327.68; + float LL=rL[j]/327.68; float x_ = 65535.0 * Color::f2xyz(fx)*Color::D50x; - float y_ = 65535.0 * Color::f2xyz(fy); + //float y_ = 65535.0 * Color::f2xyz(fy); float z_ = 65535.0 * Color::f2xyz(fz)*Color::D50z; + float y_= (LL>Color::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; Color::xyz2rgb(x_,y_,z_,R,G,B,rgb_xyz); @@ -248,10 +257,12 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int float fy = (0.00862069 * rL[j])/327.68 + 0.137932; // (L+16)/116 float fx = (0.002 * ra[j])/327.68 + fy; float fz = fy - (0.005 * rb[j])/327.68; + float LL=rL[j]/327.68; float x_ = 65535.0 * Color::f2xyz(fx)*Color::D50x; - float y_ = 65535.0 * Color::f2xyz(fy); + //float y_ = 65535.0 * Color::f2xyz(fy); float z_ = 65535.0 * Color::f2xyz(fz)*Color::D50z; + float y_= (LL>Color::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; xa[j-cx] = CLIP((int)(x_+0.5)); ya[j-cx] = CLIP((int)(y_+0.5)); @@ -279,10 +290,12 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int float fy = (0.00862069 * rL[j])/327.68 + 0.137932; // (L+16)/116 float fx = (0.002 * ra[j])/327.68 + fy; float fz = fy - (0.005 * rb[j])/327.68; + float LL=rL[j]/327.68; float x_ = 65535.0 * Color::f2xyz(fx)*Color::D50x; - float y_ = 65535.0 * Color::f2xyz(fy); + //float y_ = 65535.0 * Color::f2xyz(fy); float z_ = 65535.0 * Color::f2xyz(fz)*Color::D50z; + float y_= (LL>Color::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; Color::xyz2srgb(x_,y_,z_,R,G,B); @@ -388,10 +401,12 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int float fy = (0.00862069 * rL[j])/327.68 + 0.137932; // (L+16)/116 float fx = (0.002 * ra[j])/327.68 + fy; float fz = fy - (0.005 * rb[j])/327.68; + float LL=rL[j]/327.68; float x_ = 65535.0 * Color::f2xyz(fx)*Color::D50x; - float y_ = 65535.0 * Color::f2xyz(fy); + // float y_ = 65535.0 * Color::f2xyz(fy); float z_ = 65535.0 * Color::f2xyz(fz)*Color::D50z; + float y_= (LL>Color::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; xa[j-cx] = CLIP((int)x_); ya[j-cx] = CLIP((int)y_); @@ -419,10 +434,12 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int float fy = (0.00862069 * rL[j])/327.68 + 0.137932; // (L+16)/116 float fx = (0.002 * ra[j])/327.68 + fy; float fz = fy - (0.005 * rb[j])/327.68; + float LL=rL[j]/327.68; float x_ = 65535.0 * Color::f2xyz(fx)*Color::D50x; - float y_ = 65535.0 * Color::f2xyz(fy); + //float y_ = 65535.0 * Color::f2xyz(fy); float z_ = 65535.0 * Color::f2xyz(fz)*Color::D50z; + float y_= (LL>Color::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; Color::xyz2srgb(x_,y_,z_,R,G,B); diff --git a/rtengine/ipvibrance.cc b/rtengine/ipvibrance.cc index e37f6753e..a52a0cfcf 100644 --- a/rtengine/ipvibrance.cc +++ b/rtengine/ipvibrance.cc @@ -28,6 +28,7 @@ #include "../rtgui/thresholdselector.h" #include "curves.h" //#include "calc_distort.h" +#include "color.h" #ifdef _OPENMP #include @@ -265,12 +266,12 @@ void ImProcFunctions::vibrance (LabImage* lab) { bool neg=false; bool more_rgb=false; //gamut control : Lab values are in gamut - Color::gamutLchonly(HH, Lprov, Chprov, R, G, B, wip, highlight, 0.2f, 0.98f, neg, more_rgb); + Color::gamutLchonly(HH, Lprov, Chprov, R, G, B, wip, highlight, 0.15f, 0.98f, neg, more_rgb); if(neg) negat++; if(more_rgb) moreRGB++; #else //gamut control : Lab values are in gamut - Color::gamutLchonly(HH, Lprov, Chprov, R, G, B, wip, highlight, 0.2f, 0.98f); + Color::gamutLchonly(HH, Lprov, Chprov, R, G, B, wip, highlight, 0.15f, 0.98f); #endif float saturation=SAT(R,G,B); @@ -416,10 +417,11 @@ void ImProcFunctions::vibrance (LabImage* lab) { float fyy = (0.00862069f *Lprov )+ 0.137932f; float fxx = (0.002f * aprovn) + fyy; float fzz = fyy - (0.005f * bprovn); - float xx_ = 65535.0f * Color::f2xyz(fxx)*Color::D50x; - float yy_ = 65535.0f * Color::f2xyz(fyy); + // float yy_ = 65535.0f * Color::f2xyz(fyy); float zz_ = 65535.0f * Color::f2xyz(fzz)*Color::D50z; + float yy_= (Lprov>Color::epskap) ? 65535.0*fyy*fyy*fyy : 65535.0*Lprov/Color::kappa; + Color::xyz2rgb(xx_,yy_,zz_,R,G,B,wip); if(R<0.0f || G<0.0f || B<0.0f) {