2013-03-15 64 views

回答

2

我不是很有经验的C++,但我移植this snippet过:

//ported from http://cookbooks.adobe.com/post_Useful_color_equations__RGB_to_LAB_converter-14227.html 
struct Color{ 
    float R,G,B,X,Y,Z,L,a,b; 
}; 

#define REF_X 95.047; // Observer= 2°, Illuminant= D65 
#define REF_Y 100.000; 
#define REF_Z 108.883; 

Color rgb2xyz(int R,int G,int B){ 
    float r = R/255.0; 
    float g = G/255.0; 
    float b = B/255.0; 

    if (r > 0.04045){ r = pow((r + 0.055)/1.055, 2.4); } 
    else { r = r/12.92; } 
    if (g > 0.04045){ g = pow((g + 0.055)/1.055, 2.4); } 
    else { g = g/12.92; } 
    if (b > 0.04045){ b = pow((b + 0.055)/1.055, 2.4); } 
    else { b = b/12.92; } 

    r = r * 100; 
    g = g * 100; 
    b = b * 100; 
    //Observer. = 2°, Illuminant = D65 
    Color xyz; 
    xyz.X = r * 0.4124 + g * 0.3576 + b * 0.1805; 
    xyz.Y = r * 0.2126 + g * 0.7152 + b * 0.0722; 
    xyz.Z = r * 0.0193 + g * 0.1192 + b * 0.9505; 
    return xyz; 
} 
Color xyz2lab(float X,float Y, float Z){ 
    float x = X/REF_X; 
    float y = Y/REF_X; 
    float z = Z/REF_X; 

    if (x > 0.008856) { x = pow(x , .3333333333f); } 
    else { x = (7.787 * x) + (16/116.0); } 
    if (y > 0.008856) { y = pow(y , .3333333333f); } 
    else { y = (7.787 * y) + (16/116.0); } 
    if (z > 0.008856) { z = pow(z , .3333333333f); } 
    else { z = (7.787 * z) + (16/116.0); } 

    Color lab; 
    lab.L = (116 * y) - 16; 
    lab.a = 500 * (x - y); 
    lab.b = 200 * (y - z); 
    return lab; 
} 
Color lab2xyz(float l, float a, float b){ 
    float y = (l + 16)/116; 
    float x = a/500 + y; 
    float z = y - b/200; 

    if (pow(y , 3) > 0.008856) { y = pow(y , 3); } 
    else { y = (y - 16/116)/7.787; } 
    if (pow(x , 3) > 0.008856) { x = pow(x , 3); } 
    else { x = (x - 16/116)/7.787; } 
    if (pow(z , 3) > 0.008856) { z = pow(z , 3); } 
    else { z = (z - 16/116)/7.787; } 

    Color xyz; 
    xyz.X = x * REF_X; 
    xyz.Y = y * REF_Y; 
    xyz.Z = z * REF_Z; 
    return xyz; 
} 
Color xyz2rgb(float X,float Y,float Z){ 
    //X from 0 to 95.047  (Observer = 2°, Illuminant = D65) 
    //Y from 0 to 100.000 
    //Z from 0 to 108.883 
    X = ofClamp(X, 0, 95.047); 

    float x = X * .01; 
    float y = Y * .01; 
    float z = Z * .01; 

    float r = x * 3.2406 + y * -1.5372 + z * -0.4986; 
    float g = x * -0.9689 + y * 1.8758 + z * 0.0415; 
    float b = x * 0.0557 + y * -0.2040 + z * 1.0570; 

    if (r > 0.0031308) { r = 1.055 * pow(r , (1/2.4f)) - 0.055; } 
    else { r = 12.92 * r; } 
    if (g > 0.0031308) { g = 1.055 * pow(g , (1/2.4f)) - 0.055; } 
    else { g = 12.92 * g; } 
    if (b > 0.0031308) { b = 1.055 * pow(b , (1/2.4f)) - 0.055; } 
    else { b = 12.92 * b; } 

    Color rgb; 
    rgb.R = round(r * 255); 
    rgb.G = round(g * 255); 
    rgb.B = round(b * 255); 
    return rgb; 
} 
Color rgb2lab(int R,int G,int B){ 
    Color xyz = rgb2xyz(R, G, B); 
    return xyz2lab(xyz.X, xyz.Y, xyz.Z); 
} 
Color lab2rgb(int L,int a,int b){ 
    Color xyz = lab2xyz(L, a, b); 
    return xyz2rgb(xyz.X, xyz.Y, xyz.Z); 
} 

测量距离将是微不足道的东西如:

float distLab(Color c1,Color c2){ 
    float dL = c1.L - c2.L; 
    float da = c1.a - c2.a; 
    float db = c1.b - c2.b; 
    return sqrt(dL*dL + da*da + db*db); 
} 

ofVec3f(c1.L,c1.a,c1.b).distance(ofVec3f(c2.L,c2.a,c2.b));

另请参阅this answer为openframeworks基本示例。 image by colour search