Search on this site
Search in forums

Home » U++ Library support » U++ Library : Other (not classified elsewhere) » Add new color Standard convertions RGB <-> Cie XYZ <-> Cie L*a*b*
Add new color Standard convertions RGB <-> Cie XYZ <-> Cie L*a*b* Tue, 03 May 2011 15:53
 tojocky Messages: 607Registered: April 2008 Location: UK Contributor
Hello All (especialy Mirek),

- http://en.wikipedia.org/wiki/Lab_color_space#cite_note-12
- http://www.easyrgb.com/index.php?X=MATH&H=01#text1
- and others source-code projects

I propose to add the following functions in Core/Color.h/cpp:
```void RGBtoXYZ(double r, double g, double b, double& x, double& y, double& z){
r /= 255;
g /= 255;
b /= 255;
double delta = 0.04045;//?
if (r > delta)
r = pow(((r + 0.055) / 1.055), 2.4);
else r /= 12.92;

if (g > delta)
g = pow(((g + 0.055) / 1.055), 2.4);
else g /= 12.92;

if (b > delta)
b = pow(((b + 0.055) / 1.055), 2.4);
else b /= 12.92;

//Observer. = 2°, Illuminant = D65
x = r * 41.24 + g * 35.76 + b * 18.05;
y = r * 21.26 + g * 71.52 + b * 7.22;
z = r * 1.93 + g * 11.92 + b * 95.05;
}

void XYZtoRGB(double x, double y, double z, int &r, int &g, int &b){
double dr,dg,db;
dr =  0.032406  * x - 0.015372 * y - 0.0049865 * z;
dg = -0.0096891 * x + 0.018758 * y + 0.00041514* z;
db =  0.00055708* x - 0.0020401* y + 0.01057   * z;

if(dr > 0.0031308)
dr = exp(log(dr) / 2.4) * 1.055-0.055;
else dr = dr*12.92;

if(dg > 0.0031308)
dg = exp(log(dg) / 2.4) * 1.055 - 0.055;
else dg = dg*12.92;

if(db > 0.0031308)
db = exp(log(db) / 2.4) * 1.055 - 0.055;
else db = db*12.92;

dr *= 255;
dg *= 255;
db *= 255;

dr = minmax<double>(0.0,dr, 255.0);
dg = minmax<double>(0.0,dg, 255.0);
db = minmax<double>(0.0,db, 255.0);

r = int(dr + 0.5); //?0.5
g = int(dg + 0.5); //?0.5
b = int(db + 0.5); //?0.5
}

void XYZtoCEILab(double x, double y, double z, double& l, double& a, double& b){
x /= 95.047;           //ref_X =  95.047   Observer= 2°, Illuminant= D65
y /= 100.000;          //ref_Y = 100.000
z /= 108.883;          //ref_Z = 108.883
double delta = 0.008856; //pow(6/29,3);
double delta2 = 7.787; //pow(29/6, 2)/3;

if (x > delta)
x = pow(x, 1/3);
else x = (delta2 * x) + (4 / 29);

if (y > delta)
y = pow(y, 1/3);
else y = (delta2 * y) + (4 / 29);

if (z > delta)
z = pow(z, 1/3);
else z = (delta2 * z) + (4 / 29);

l = (116 * y) - 16;
a = 500 * (x - y);
b = 200 * (y - z);
}

void CEILabtoXYZ(double l, double a, double b, double& x, double& y, double& z){
y = (l + 16) / 116;
x = y + a / 500;
z = y - b / 200;

double delta = 0.20689655; //6/29;
double delta2 = 7.787; //pow(29/6, 2)/3;

if (x > delta)
x = pow(x, 3);
else x = ((delta2 * x) - (4 / 29)) / delta2;

if (y > delta)
y = pow(y, 3);
else y = ((delta2 * y) - (4 / 29)) / delta2;

if (z > delta)
z = pow(z, 3);
else z = ((delta2 * z) - (4 / 29)) / delta2;
}

void RGBtoCEILab(double r, double g, double b, double& l, double& a, double& lb){
double x,y,z;
RGBtoXYZ(r,g,b,x,y,z);
XYZtoCEILab(x,y,z,l,a,lb);
}

void CEILabtoRGB(double l, double a, double lb, double& r, double& g, double& b){
double x,y,z;
CEILabtoXYZ(l,a,lb,x,y,z);
RGBtoXYZ(x,y,z,r,g,b);
}
```

This functions I will use in histogram equalization of image according by:
http://en.wikipedia.org/wiki/Histogram_equalisation

HSV/HSL is not so exact as CIE L*a*b*

Any comment are welcome!
Re: Add new color Standard convertions RGB <-> Cie XYZ <-> Cie L*a*b* [message #32775 is a reply to message #32252] Tue, 07 June 2011 20:57
 mirek Messages: 12740Registered: November 2005 Ultimate Member
 tojocky wrote on Tue, 03 May 2011 09:53 Hello All (especialy Mirek), According by addresses: - http://en.wikipedia.org/wiki/Lab_color_space#cite_note-12 - http://www.easyrgb.com/index.php?X=MATH&H=01#text1 - and others source-code projects I propose to add the following functions in Core/Color.h/cpp: ```void RGBtoXYZ(double r, double g, double b, double& x, double& y, double& z){ r /= 255; g /= 255; b /= 255; double delta = 0.04045;//? if (r > delta) r = pow(((r + 0.055) / 1.055), 2.4); else r /= 12.92; if (g > delta) g = pow(((g + 0.055) / 1.055), 2.4); else g /= 12.92; if (b > delta) b = pow(((b + 0.055) / 1.055), 2.4); else b /= 12.92; //Observer. = 2°, Illuminant = D65 x = r * 41.24 + g * 35.76 + b * 18.05; y = r * 21.26 + g * 71.52 + b * 7.22; z = r * 1.93 + g * 11.92 + b * 95.05; } void XYZtoRGB(double x, double y, double z, int &r, int &g, int &b){ double dr,dg,db; dr = 0.032406 * x - 0.015372 * y - 0.0049865 * z; dg = -0.0096891 * x + 0.018758 * y + 0.00041514* z; db = 0.00055708* x - 0.0020401* y + 0.01057 * z; if(dr > 0.0031308) dr = exp(log(dr) / 2.4) * 1.055-0.055; else dr = dr*12.92; if(dg > 0.0031308) dg = exp(log(dg) / 2.4) * 1.055 - 0.055; else dg = dg*12.92; if(db > 0.0031308) db = exp(log(db) / 2.4) * 1.055 - 0.055; else db = db*12.92; dr *= 255; dg *= 255; db *= 255; dr = minmax(0.0,dr, 255.0); dg = minmax(0.0,dg, 255.0); db = minmax(0.0,db, 255.0); r = int(dr + 0.5); //?0.5 g = int(dg + 0.5); //?0.5 b = int(db + 0.5); //?0.5 } void XYZtoCEILab(double x, double y, double z, double& l, double& a, double& b){ x /= 95.047; //ref_X = 95.047 Observer= 2°, Illuminant= D65 y /= 100.000; //ref_Y = 100.000 z /= 108.883; //ref_Z = 108.883 double delta = 0.008856; //pow(6/29,3); double delta2 = 7.787; //pow(29/6, 2)/3; if (x > delta) x = pow(x, 1/3); else x = (delta2 * x) + (4 / 29); if (y > delta) y = pow(y, 1/3); else y = (delta2 * y) + (4 / 29); if (z > delta) z = pow(z, 1/3); else z = (delta2 * z) + (4 / 29); l = (116 * y) - 16; a = 500 * (x - y); b = 200 * (y - z); } void CEILabtoXYZ(double l, double a, double b, double& x, double& y, double& z){ y = (l + 16) / 116; x = y + a / 500; z = y - b / 200; double delta = 0.20689655; //6/29; double delta2 = 7.787; //pow(29/6, 2)/3; if (x > delta) x = pow(x, 3); else x = ((delta2 * x) - (4 / 29)) / delta2; if (y > delta) y = pow(y, 3); else y = ((delta2 * y) - (4 / 29)) / delta2; if (z > delta) z = pow(z, 3); else z = ((delta2 * z) - (4 / 29)) / delta2; } void RGBtoCEILab(double r, double g, double b, double& l, double& a, double& lb){ double x,y,z; RGBtoXYZ(r,g,b,x,y,z); XYZtoCEILab(x,y,z,l,a,lb); } void CEILabtoRGB(double l, double a, double lb, double& r, double& g, double& b){ double x,y,z; CEILabtoXYZ(l,a,lb,x,y,z); RGBtoXYZ(x,y,z,r,g,b); } ``` This functions I will use in histogram equalization of image according by: http://en.wikipedia.org/wiki/Histogram_equalisation HSV/HSL is not so exact as CIE L*a*b* Any comment are welcome!

This is fine code, but I am afraid too specialised for Core (I guess Core is sort of overloaded now).

What about bazaar or plugin or maybe Geom? Or perhaps Painter?

Maybe we should start a new "high level" raster graphics package? I think the equalization code would fit nicely there.
Re: Add new color Standard convertions RGB <-> Cie XYZ <-> Cie L*a*b* [message #32776 is a reply to message #32775] Tue, 07 June 2011 23:03
 tojocky Messages: 607Registered: April 2008 Location: UK Contributor
 mirek wrote on Tue, 07 June 2011 21:57 This is fine code, but I am afraid too specialised for Core (I guess Core is sort of overloaded now). What about bazaar or plugin or maybe Geom? Or perhaps Painter? Maybe we should start a new "high level" raster graphics package? I think the equalization code would fit nicely there.

This code is not quite correct. I have the latest tested version. I used this code to autolevel color images (converted into CIE L*a*b*). HSV autolevel of color images losts some color (this problem persists in Photoshop too).

Ok, I can prepare a package and uploat into bazaar. But I think it is a better idea to include it in Painter.

[Updated on: Wed, 08 June 2011 23:06]

Report message to a moderator

 Previous Topic: new! ANTI VIRUS FALSE POSITIVE with Upp (GUI MT FileSel) Next Topic: Weired appearance of GUI elements
Goto Forum:

Current Time: Thu Oct 01 18:36:02 CEST 2020

Total time taken to generate the page: 0.01038 seconds