我正在尝试将Lab颜色转换为RGB。作为此转换的示例,Photoshop 转换
L= 100, a = 0, b = 127
进入
R=255, G=252, B=0.
此颜色为亮黄色。
我编写了以下转换例程(C / Objective C)。然而,有些事情 是不正确的。代码将输出
XYZ = 100.000000 100.000000 4.862713
RGB = 163.908401 90.755638 -13.093634
这里RGB结果与Photoshop的RGB之间的不匹配似乎非常大。 负蓝色成分也是一个问题。
有关如何更正以下代码的任何想法将不胜感激?或者,将Lab转换为RGB的任何其他算法/公式/伪代码?谢谢。
代码:
/*
* See Wikipedia artice on Lab color space
*
* http://en.wikipedia.org/wiki/Lab_color_space
*
*/
CGFloat fInv (CGFloat t) {
CGFloat T0 = (CGFloat) 6.0f/29.0f;
if (t > T0) {
return t*t*t;
}
return 3.0 * T0 * T0 * (t - 4.0f/29.0f);
}
int test() {
//
// Bright yellow test
//
CGFloat Ls = 100.0f;
CGFloat as = 0.0f;
CGFloat bs = 127.0f;
//
// Reference white point (ad hoc)
//
CGFloat Xn = 100;
CGFloat Yn = 100;
CGFloat Zn = 100;
//
// Taken Wikipedia (see above)
//
CGFloat X = Xn * fInv(1/116.0f * (Ls + 16.0f) + 1/500.0f * as);
CGFloat Y = Yn * fInv(1/116.0f * (Ls + 16.0f));
CGFloat Z = Zn * fInv(1/116.0f * (Ls + 16.0f) - 1/200.0f * bs);
NSLog(@" XYZ = %f %f %f", X, Y, Z);
//
//
// XYZ to RGB transfomration using AppleRGB. Taken from
//
// http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
//
//
CGFloat r = 2.9515373 * X - 1.2894116 * Y - 0.4738445 * Z;
CGFloat g = -1.0851093 * X + 1.9908566 * Y + 0.0372026 * Z;
CGFloat b = 0.0854934 * X - 0.2694964 * Y + 1.0912975 * Z;
NSLog(@" RGB = %f %f %f", r, g, b);
}
答案 0 :(得分:2)
尝试从this site实施公式。我刚刚实现了RGB-> Lab(通过XYZ),它工作正常。
C ++代码:
// using http://www.easyrgb.com/index.php?X=MATH&H=01#text1
void rgb2lab( float R, float G, float B, float & l_s, float &a_s, float &b_s )
{
float var_R = R/255.0;
float var_G = G/255.0;
float var_B = B/255.0;
if ( var_R > 0.04045 ) var_R = pow( (( var_R + 0.055 ) / 1.055 ), 2.4 );
else var_R = var_R / 12.92;
if ( var_G > 0.04045 ) var_G = pow( ( ( var_G + 0.055 ) / 1.055 ), 2.4);
else var_G = var_G / 12.92;
if ( var_B > 0.04045 ) var_B = pow( ( ( var_B + 0.055 ) / 1.055 ), 2.4);
else var_B = var_B / 12.92;
var_R = var_R * 100.;
var_G = var_G * 100.;
var_B = var_B * 100.;
//Observer. = 2°, Illuminant = D65
float X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
float Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
float Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
float var_X = X / 95.047 ; //ref_X = 95.047 Observer= 2°, Illuminant= D65
float var_Y = Y / 100.000; //ref_Y = 100.000
float var_Z = Z / 108.883; //ref_Z = 108.883
if ( var_X > 0.008856 ) var_X = pow(var_X , ( 1./3. ) );
else var_X = ( 7.787 * var_X ) + ( 16. / 116. );
if ( var_Y > 0.008856 ) var_Y = pow(var_Y , ( 1./3. ));
else var_Y = ( 7.787 * var_Y ) + ( 16. / 116. );
if ( var_Z > 0.008856 ) var_Z = pow(var_Z , ( 1./3. ));
else var_Z = ( 7.787 * var_Z ) + ( 16. / 116. );
l_s = ( 116. * var_Y ) - 16.;
a_s = 500. * ( var_X - var_Y );
b_s = 200. * ( var_Y - var_Z );
}
//http://www.easyrgb.com/index.php?X=MATH&H=01#text1
void lab2rgb( float l_s, float a_s, float b_s, float& R, float& G, float& B )
{
float var_Y = ( l_s + 16. ) / 116.;
float var_X = a_s / 500. + var_Y;
float var_Z = var_Y - b_s / 200.;
if ( pow(var_Y,3) > 0.008856 ) var_Y = pow(var_Y,3);
else var_Y = ( var_Y - 16. / 116. ) / 7.787;
if ( pow(var_X,3) > 0.008856 ) var_X = pow(var_X,3);
else var_X = ( var_X - 16. / 116. ) / 7.787;
if ( pow(var_Z,3) > 0.008856 ) var_Z = pow(var_Z,3);
else var_Z = ( var_Z - 16. / 116. ) / 7.787;
float X = 95.047 * var_X ; //ref_X = 95.047 Observer= 2°, Illuminant= D65
float Y = 100.000 * var_Y ; //ref_Y = 100.000
float Z = 108.883 * var_Z ; //ref_Z = 108.883
var_X = X / 100. ; //X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
var_Y = Y / 100. ; //Y from 0 to 100.000
var_Z = Z / 100. ; //Z from 0 to 108.883
float var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
float var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
float var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
if ( var_R > 0.0031308 ) var_R = 1.055 * pow(var_R , ( 1 / 2.4 )) - 0.055;
else var_R = 12.92 * var_R;
if ( var_G > 0.0031308 ) var_G = 1.055 * pow(var_G , ( 1 / 2.4 ) ) - 0.055;
else var_G = 12.92 * var_G;
if ( var_B > 0.0031308 ) var_B = 1.055 * pow( var_B , ( 1 / 2.4 ) ) - 0.055;
else var_B = 12.92 * var_B;
R = var_R * 255.;
G = var_G * 255.;
B = var_B * 255.;
}
答案 1 :(得分:1)
尝试
void LAB2RGB(int L, int a, int b, unsigned char & R, unsigned char & G, unsigned char & B)
{
float X, Y, Z, fX, fY, fZ;
int RR, GG, BB;
fY = pow((L + 16.0) / 116.0, 3.0);
if (fY < 0.008856)
fY = L / 903.3;
Y = fY;
if (fY > 0.008856)
fY = powf(fY, 1.0/3.0);
else
fY = 7.787 * fY + 16.0/116.0;
fX = a / 500.0 + fY;
if (fX > 0.206893)
X = powf(fX, 3.0);
else
X = (fX - 16.0/116.0) / 7.787;
fZ = fY - b /200.0;
if (fZ > 0.206893)
Z = powf(fZ, 3.0);
else
Z = (fZ - 16.0/116.0) / 7.787;
X *= (0.950456 * 255);
Y *= 255;
Z *= (1.088754 * 255);
RR = (int)(3.240479*X - 1.537150*Y - 0.498535*Z + 0.5);
GG = (int)(-0.969256*X + 1.875992*Y + 0.041556*Z + 0.5);
BB = (int)(0.055648*X - 0.204043*Y + 1.057311*Z + 0.5);
R = (unsigned char)(RR < 0 ? 0 : RR > 255 ? 255 : RR);
G = (unsigned char)(GG < 0 ? 0 : GG > 255 ? 255 : GG);
B = (unsigned char)(BB < 0 ? 0 : BB > 255 ? 255 : BB);
//printf("Lab=(%f,%f,%f) ==> RGB(%f,%f,%f)\n",L,a,b,*R,*G,*B);
}
答案 2 :(得分:0)
每个i-device的颜色略有不同,但我相信Apple建议将sRGB作为所有设备的设备色彩空间。当然,对于iPad 3/4,显示器与sRGB相匹配。 (见this colour analysis)
这意味着,如果您使用的是准确的颜色,则应使用sRGB ICC配置文件来帮助您转换Lab颜色值。您可以使用开源软件Little CMS为您执行此转换。