package org.styloot.hobo;
public class CIELabColor {
public final double L;
public final double a;
public final double b;
public CIELabColor(double li, double ai, double bi) {
L = li; a = ai; b = bi;
}
public static CIELabColor CIELabFromRGB(int r, int g, int b) {
return CIELabFromRGB((byte)(r-128), (byte)(g-128), (byte)(b-128));
}
public static CIELabColor CIELabFromRGB(byte r, byte g, byte b) {
//First Calculate XYZ
double var_R = ( (double)(r+128) / 255.0);
double var_G = ( (double)(g+128) / 255.0);
double var_B = ( (double)(b+128) / 255.0);
if (var_R > 0.04045) {
var_R = Math.pow(( ( var_R + 0.055 ) / 1.055 ), 2.4);
} else {
var_R /= 12.92;
}
if (var_G > 0.04045) {
var_G = Math.pow(( ( var_G + 0.055 ) / 1.055 ), 2.4);
} else {
var_G /= 12.92;
}
if (var_B > 0.04045) {
var_B = Math.pow(( ( var_B + 0.055 ) / 1.055 ), 2.4);
} else {
var_B /= 12.92;
}
var_R *= 100;
var_G *= 100;
var_B *= 100;
double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
//Now convert to CIE
double var_X = X / ref_X;
double var_Y = Y / ref_Y;
double var_Z = Z / ref_Z;
if (var_X > 0.008856)
var_X = Math.pow(var_X, 1.0/3.0 );
else
var_X = ( 7.787 * var_X ) + ( 16. / 116. );
if (var_Y > 0.008856)
var_Y = Math.pow(var_Y, 1.0/3.0 );
else
var_Y = ( 7.787 * var_Y ) + ( 16. / 116. );
if (var_Z > 0.008856)
var_Z = Math.pow(var_Z, 1.0/3.0 );
else
var_Z = ( 7.787 * var_Z ) + ( 16. / 116. );
return new CIELabColor(( 116. * var_Y ) - 16.0, 500. * ( var_X - var_Y ), 200. * ( var_Y - var_Z ));
}
private static final double ref_X = 95.047;
private static final double ref_Y = 100.000;
private static final double ref_Z = 108.883;
private static final double KL = 1;
private static final double K1 = 0.045;
private static final double K2 = 0.015;
public static final double SQRT_REGULARIZATION = 0.00001;
public double distanceTo(CIELabColor other) {
//Color distance
return Math.sqrt(distance2To(other));
}
public static double distance2(double xL, double xa, double xb, double yL, double ya, double yb) {
/* This version does the math without boxing/unboxing overhead.
*/
double dL = xL - yL;
double da = xa - ya;
double db = xb - yb;
double Cx = Math.sqrt(xa*xa+xb*xb + SQRT_REGULARIZATION);
double Cy = Math.sqrt(ya*ya+yb*yb + SQRT_REGULARIZATION);
double dC = Cx - Cy;
double dH = Math.sqrt(da*da+db*db-dC*dC);
return (Math.pow(dL/KL,2) + Math.pow(dC/(1+K1*Cy), 2) + Math.pow(dH/(1+K2*Cy), 2));
}
public static double distance2(CIELabColor base, double yL, double ya, double yb) {
return distance2(base.L, base.a, base.b, yL, ya, yb);
}
public double distance2To(CIELabColor other) {
//Color distance squared
return distance2(L, a, b, other.L, other.a, other.b);
}
public String toString() {
return "CIELab(" + L + ", " + a + ", " + b + ")";
}
}