Eric,
Thanks for implementing my color distance code. Since you are using CIE Lab color space from Guillaume's library, I had another look at the RGB <> CIEXYZ <> CIELab formulas. They are not quite correct. In your project, you will not see a big difference. However, if you will use the lib for other purposes, you'll see a BIG difference.
Further, Guillaume's library uses sRGB with D50 reference white, like all other copy/paste solutions. If you would compare the conversion with PhotoShop, you'll be surprised that the results do not match. Adobe uses RGB Bradford adapted with D65 reference white.
If you want to use RGB Bradford adapted CIELab conversion, do the following:
In CIEXYZ class, add:
public static readonly CIEXYZ D50 = new CIEXYZ(0.96422, 1.00000, 0.82521);
In
RGBtoXYZ
method change matrix constants to:
0.4360747 0.3850649 0.1430804
0.2225045 0.7168786 0.0606169
0.0139322 0.0971045 0.7141733
In
XYZtoRGB
method, change matrix constants to (watchout for +/- signs):
3.1338561 -1.6168667 -0.4906146
-0.9787684 1.9161415 0.0334540
0.0719453 -0.2289914 1.4052427
In XYZtoLab method:
change D65 to D50
In LabtoXYZ method:
change D65 to D50
Here are the corrections for sRGB with D65 reference white:
public static CIEXYZ RGBtoXYZ(int red, int green, int blue)
{
double rLinear = (double)red/255.0;
double gLinear = (double)green/255.0;
double bLinear = (double)blue/255.0;
double r = (rLinear > 0.04045)? Math.Pow((rLinear + 0.055)/(1 + 0.055), 2.4) : (rLinear/12.92) ;
double g = (gLinear > 0.04045)? Math.Pow((gLinear + 0.055)/(1 + 0.055), 2.4) : (gLinear/12.92) ;
double b = (bLinear > 0.04045)? Math.Pow((bLinear + 0.055)/(1 + 0.055), 2.4) : (bLinear/12.92) ;
return new CIEXYZ(
(r*0.4124564 + g*0.3575761 + b*0.1804375),
(r*0.2126729 + g*0.7151522 + b*0.0721750),
(r*0.0193339 + g*0.1191920 + b*0.9503041)
);
}
public static RGB XYZtoRGB(double x, double y, double z)
{
double[] Clinear = new double[3];
Clinear[0] = x*3.2404542 - y*1.5371385 - z*0.4985314;
Clinear[1] = -x*0.9692660 + y*1.8760108 - z*0.0415560;
Clinear[2] = x*0.0556434 - y*0.2040259 + z*1.0572252;
for(int i=0; i<3; i++)
{
Clinear[i] = (Clinear[i]<=0.0031308)? 12.92*Clinear[i] : (1+0.055)* Math.Pow(Clinear[i], (1.0/2.4)) - 0.055;
}
return new RGB(
Convert.ToInt32( Double.Parse(String.Format("{0:0.00}", Clinear[0]*255.0)) ),
Convert.ToInt32( Double.Parse(String.Format("{0:0.00}", Clinear[1]*255.0)) ),
Convert.ToInt32( Double.Parse(String.Format("{0:0.00}", Clinear[2]*255.0)) )
);
}
Happy coding.
Rob
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.