问题描述
我的目标是将RGB像素转换为CIELab色彩空间,以便仅在CIELab中进行某些特殊计算。为此,我必须首先将RGB转换为XYZ,这是非常困难的部分。
My goal is to convert an RGB pixel into CIELab color space for some special calculations only possible in CIELab. For this, I must convert RGB to XYZ first, which is the really hard part.
我试图在Objective-C中实现这个算法,但结果是错误的。
I tried to implement this algorithm in Objective-C (mostly using plain C though), but the results are wrong.
我的代码是基于。他们有一个在线颜色转换器工作伟大。
My code is based on the pseudo-implementation provided by easyrgb.com. They have an online-color-converter which works great. They say that their pseudo-code is the same one used in their converter.
这是他们的伪代码:
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 :
This is my attempt to implement it in 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;
}
但是,我没有得到与他们的工具观察者和照明设置)。
However, I don't get the same results as their tool (with same Observer and Illuminant setting).
在我的测试中,我将这些值输入到他们的工具中,得到了XYZ的结果,这远离我的实现产生的RGB值。请参阅屏幕截图:
In my test, I entered these values into their tool and got this result for XYZ which is far off from what my implementation produces for that RGB value. Please see screenshot:
得到的Lab颜色值非常接近Photoshop告诉我的值,工作伟大。
The resulting Lab color values are pretty close to what Photoshop tells me, so the converter works great.
上面的C代码给我这个结果:
The C-code above gives me this results though:
X = 35.76... // should be 42.282
Y = 71.52... // should be 74.129
Z = 11.92... // should be 46.262
任何想法导致这种失败的原因是什么?
Any idea what's the cause for this failure? Did I do a mistake in my implementation, or do I need other constants?
如果你知道一些测试的RGB到XYZ,XYZ到CIELab或RGB到CIELab,XYZ到实验室或RGB到实验室实施,请不要犹豫,在这里张贴。
If you know some tested RGB to XYZ, XYZ to CIELab or RGB to CIELab, XYZ to Lab or RGB to Lab implementations, please don't hesitate to post them here.
基本上,我想做的只是计算两种颜色之间的偏差,也称为Delta-E。这就是为什么我需要从RGB转换为XYZ到Lab(或CIELab)...
Basically, all I want to do is calculate the deviation between two colors, also known as Delta-E. That's why I need to convert from RGB to XYZ to Lab (or CIELab)...
推荐答案
我相信这里是你的问题,这是截断为整数:
I believe here is your problem, this is truncating to an integer:
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
我还没有检查其他问题的代码。
I haven't checked the rest of the code for other problems.
这篇关于这个RGB到XYZ颜色空间转换算法有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!