improvement gamut-control and conversions RGB<=>Lab see issue1551 and issue1552

This commit is contained in:
jdc 2012-09-16 07:02:02 +02:00
parent e123a5eed2
commit beeeb0c195
6 changed files with 63 additions and 54 deletions

View File

@ -32,7 +32,7 @@ Brightness=0
Contrast=0
Chromaticity=0
BWtoning=false
AvoidColorShift=true
AvoidColorShift=false
RedAndSkinTonesProtection=0
LCredsk=true
LCurve=0;

View File

@ -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 <jdesmis@gmail.com>
@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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; j<lab->W; 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; j<lab->W; 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);

View File

@ -28,6 +28,7 @@
#include "../rtgui/thresholdselector.h"
#include "curves.h"
//#include "calc_distort.h"
#include "color.h"
#ifdef _OPENMP
#include <omp.h>
@ -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) {