我的目标是将RGB像素转换为CIELab颜色空间,以便在CIELab中进行某些特殊计算.为此,我必须首先将RGB转换为XYZ,这是非常困难的部分.
我试图在Objective-C中实现这个算法(大多数使用普通C,但是结果是错误的).
我的代码是基于easyrgb.com提供的伪实现.他们有一个在线颜色转换器,这是非常有用的.他们说他们的伪代码与他们的转换器中使用的伪代码是一样的.
这是他们的伪代码:
var_R = ( R / 255 ) //R from 0 to 255 var_G = ( G / 255 ) //G from 0 to 255 var_B = ( B / 255 ) //B from 0 to 255 if ( var_R > 0.04045 ) var_R = ( ( var_R + 0.055 ) / 1.055 ) ^ 2.4 else var_R = var_R / 12.92 if ( var_G > 0.04045 ) var_G = ( ( var_G + 0.055 ) / 1.055 ) ^ 2.4 else var_G = var_G / 12.92 if ( var_B > 0.04045 ) var_B = ( ( 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 X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805 Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722 Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505
这是我在Objective-C/C++中实现它的尝试:
void convertRGBtoXYZ(NSInteger * inR,NSInteger * inG,NSInteger * inB,CGFloat * outX,CGFloat * outY,CGFloat * outZ) { // http://www.easyrgb.com/index.PHP?X=MATH&H=02#text2 CGFloat var_R = (*inR / 255); //R from 0 to 255 CGFloat var_G = (*inG / 255); //G from 0 to 255 CGFloat var_B = (*inB / 255); //B from 0 to 255 if (var_R > 0.04045f) { var_R = powf(( (var_R + 0.055f) / 1.055f),2.4f); } else { var_R = var_R / 12.92f; } if (var_G > 0.04045) { var_G = powf(( (var_G + 0.055f) / 1.055f),2.4f); } else { var_G = var_G / 12.92f; } if (var_B > 0.04045f) { var_B = powf(( (var_B + 0.055f) / 1.055f),2.4f); } else { var_B = var_B / 12.92f; } var_R = var_R * 100; var_G = var_G * 100; var_B = var_B * 100; //Observer. = 2°,Illuminant = D65 *outX = var_R * 0.4124f + var_G * 0.3576f + var_B * 0.1805f; *outY = var_R * 0.2126f + var_G * 0.7152f + var_B * 0.0722f; *outZ = var_R * 0.0193f + var_G * 0.1192f + var_B * 0.9505f; }
但是,我没有得到与他们的工具相同的结果(具有相同的观察者和照明设置).
在我的测试中,我将这些值输入到他们的工具中,并为XYZ获得了这个结果,这与我的实现为RGB值产生了很大的差距.请看截图:
所得到的Lab颜色值非常接近Photoshop告诉我的,所以转换器工作很棒.
上面的C代码给了我这个结果:
X = 35.76... // should be 42.282 Y = 71.52... // should be 74.129 Z = 11.92... // should be 46.262
任何想法,这个失败的原因是什么?我在执行过程中犯了错误,还是需要其他常量?
如果你知道一些测试的RGB到XYZ,XYZ到CIELab或RGB到CIELab,XYZ到Lab或RGB到Lab的实现,请不要犹豫,在这里张贴.
基本上,我想做的就是计算两种颜色之间的偏差,也称为Delta-E.这就是为什么我需要将RGB转换为XYZ到Lab(或CIELab)…
解决方法
我相信这是你的问题,这是截断到一个整数:
CGFloat var_R = (*inR / 255); //R from 0 to 255 CGFloat var_G = (*inG / 255); //G from 0 to 255 CGFloat var_B = (*inB / 255); //B from 0 to 255
尝试这个:
CGFloat var_R = (*inR / 255.0f); //R from 0 to 255 CGFloat var_G = (*inG / 255.0f); //G from 0 to 255 CGFloat var_B = (*inB / 255.0f); //B from 0 to 255
我没有检查其他代码的其他问题.