diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 08113c625..ef313ffbc 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -62,6 +62,12 @@ namespace rtengine { poly_y.push_back(y3); } + // Wikipedia sRGB: Unlike most other RGB color spaces, the sRGB gamma cannot be expressed as a single numerical value. + // The overall gamma is approximately 2.2, consisting of a linear (gamma 1.0) section near black, and a non-linear section elsewhere involving a 2.4 exponent + // and a gamma (slope of log output versus log input) changing from 1.0 through about 2.3. + const double CurveFactory::sRGBGamma = 2.2; + const double CurveFactory::sRGBGammaCurve = 2.4; + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void CurveFactory::complexsgnCurve (double saturation, bool satlimit, double satlimthresh, \ diff --git a/rtengine/curves.h b/rtengine/curves.h index eb3a5fd51..017569bd8 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -126,6 +126,9 @@ class CurveFactory { public: + const static double sRGBGamma; // standard average gamma + const static double sRGBGammaCurve; // 2.4 in the curve + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // accurately determine value from integer array with float as index @@ -154,10 +157,10 @@ class CurveFactory { // standard srgb gamma and its inverse static inline double gamma2 (double x) { - return x <= 0.00304 ? x*12.92 : 1.055*exp(log(x)/2.4)-0.055; + return x <= 0.00304 ? x*12.92 : 1.055*exp(log(x)/sRGBGammaCurve)-0.055; } static inline double igamma2 (double x) { - return x <= 0.03928 ? x/12.92 : exp(log((x+0.055)/1.055)*2.4); + return x <= 0.03928 ? x/12.92 : exp(log((x+0.055)/1.055)*sRGBGammaCurve); } // gamma function with adjustable parameters static inline double gamma (double x, double gamma, double start, double slope, double mul, double add){ diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index abe181d79..dc26e1b10 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -25,7 +25,8 @@ #include #include #include -//#include +#include + #ifdef _OPENMP #include @@ -344,7 +345,7 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int if (!freegamma) {//if Free gamma not selected // gamma : ga0,ga1,ga2,ga3,ga4,ga5 by calcul if(gam=="BT709_g2.2_s4.5") {ga0=2.222;ga1=1./1.099258;ga2=0.099258/1.099258;ga3=1./4.5; ga4=0.01805;ga5=0.0;}//BT709 2.2 4.5 - my prefered as D.Coffin ga4=0.01805 - else if (gam=="sRGB_g2.4_s12.92") {ga0=2.3999 ; ga1=1./1.0550; ga2=0.0550/1.0550;ga3=1./12.92;ga4=0.039289;}//sRGB 2.4 12.92 - RT default as Lightroom + else if (gam=="sRGB_g2.4_s12.92") {ga0=CurveFactory::sRGBGammaCurve-0.0001; ga1=1./1.0550; ga2=0.0550/1.0550;ga3=1./12.92;ga4=0.039289;}//sRGB 2.4 12.92 - RT default as Lightroom else if (gam=="High_g1.3_s3.35") {ga0=1.3 ; ga1=1./1.001724; ga2=0.001724/1.001724;ga3=1./3.35;ga4=0.001715;}//for high dynamic images else if (gam== "Low_g2.6_s6.9") {ga0=2.6 ; ga1=1./1.12213; ga2=0.12213/1.12213;ga3=1./6.90;ga4=0.01;} //gamma 2.6 variable : for low contrast images else if (gam=="linear_g1.0") {ga0=1.0; ga1=1.;ga2=0.;ga3=1./eps;ga4=0.;}//gamma=1 linear : for high dynamic images (cf : D.Coffin...) diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index ef49ca242..5da8708ad 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -22,6 +22,7 @@ #include #include #include +#include #define HR_SCALE 2 @@ -142,8 +143,8 @@ class RawImageSource : public ImageSource { ColorTemp getSpotWB (std::vector red, std::vector green, std::vector& blue, int tran); double getDefGain () { return defGain; } - // double getGamma () { return 2.2; } - double getGamma () { return 2.4; }//normalize gamma to sRGB + + double getGamma () { return CurveFactory::sRGBGamma; } void getFullSize (int& w, int& h, int tr = TR_NONE); void getSize (int tran, PreviewProps pp, int& w, int& h); diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index a05748e2f..30b629fb8 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -499,9 +499,9 @@ void Thumbnail::initGamma () { igammatab = new unsigned short[256]; gammatab = new unsigned char[65536]; for (int i=0; i<256; i++) - igammatab[i] = (unsigned short)(255.0*pow((double)i/255.0,1.0/0.45)); + igammatab[i] = (unsigned short)(255.0*pow((double)i/255.0,CurveFactory::sRGBGamma)); for (int i=0; i<65536; i++) - gammatab[i] = (unsigned char)(255.0*pow((double)i/65535.0,0.45)); + gammatab[i] = (unsigned char)(255.0*pow((double)i/65535.0,1.f/CurveFactory::sRGBGamma)); } void Thumbnail::cleanupGamma () { @@ -689,7 +689,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei ipf.setScale (sqrt(double(fw*fw+fh*fh))/sqrt(double(thumbImg->width*thumbImg->width+thumbImg->height*thumbImg->height))*scale); LUTu hist16 (65536); - ipf.firstAnalysis (baseImg, ¶ms, hist16, isRaw ? 2.2 : 0.0); + double gamma = isRaw ? CurveFactory::sRGBGamma : 0; // usually in ImageSource, but we don't have that here + ipf.firstAnalysis (baseImg, ¶ms, hist16, gamma); // perform transform if (ipf.needsTransform()) { @@ -722,7 +723,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei LUTf satcurve (65536); LUTu dummy; - CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, isRaw ? 2.2 : 0, true, params.toneCurve.curve, + CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, gamma, true, params.toneCurve.curve, hist16, dummy, curve1, curve2, curve, dummy, 16); LabImage* labView = new LabImage (fw,fh); @@ -847,7 +848,7 @@ void Thumbnail::getSpotWB (const procparams::ProcParams& params, int xp, int yp, // calculate spot wb (copy & pasted from stdimagesource) unsigned short igammatab[256]; for (int i=0; i<256; i++) - igammatab[i] = (unsigned short)(255.0*pow(i/255.0,1.0/0.45)); + igammatab[i] = (unsigned short)(255.0*pow(i/255.0,CurveFactory::sRGBGamma)); int x; int y; double reds = 0, greens = 0, blues = 0; int rn = 0, gn = 0, bn = 0; diff --git a/rtgui/navigator.cc b/rtgui/navigator.cc index d5e619dea..4802a58cd 100644 --- a/rtgui/navigator.cc +++ b/rtgui/navigator.cc @@ -20,6 +20,7 @@ #include #include // from rtengine #include +#include #define D50x 0.96422 #define D50z 0.82521 @@ -164,9 +165,9 @@ void Navigator::rgb2lab (Glib::ustring profile, int r, int g, int b, int &LAB_l, double ep=216.0/24389.0; double ka=24389.0/27.0; - volatile double var_R = r / 255.0; - volatile double var_G = g / 255.0; - volatile double var_B = b / 255.0; + double var_R = r / 255.0; + double var_G = g / 255.0; + double var_B = b / 255.0; if (profile=="sRGB") {//apply sRGB inverse gamma @@ -175,15 +176,15 @@ void Navigator::rgb2lab (Glib::ustring profile, int r, int g, int b, int &LAB_l, // today as the gamma output can not be configured // it is better that the user has the gamma of the output space if ( var_R > 0.04045 ) - var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), 2.4); + var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::CurveFactory::sRGBGammaCurve); else var_R = var_R / 12.92; if ( var_G > 0.04045 ) - var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), 2.4); + var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::CurveFactory::sRGBGammaCurve); else var_G = var_G / 12.92; if ( var_B > 0.04045 ) - var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), 2.4); + var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::CurveFactory::sRGBGammaCurve); else var_B = var_B / 12.92; }