我的代码正处于十字路口,说实话,我不太确定发生了什么......这可能很明显,但我看不出问题出在哪里。
我正在尝试将 RGB 转换为 XYZ 到 Lab,到目前为止,R(X) 和 G(Y) 部分似乎一切正常,但我无法查明 B(Z) 的错误,它是让我发疯。
这是我的代码,我使用的是 2 Degree D50
void SearchColour()
{
double[] xyz = new double[3];
double[] lab = new double[3];
double[] rgb = new double[3];
rgb[0] = searchColourr / 255.0d;
rgb[1] = searchColourg / 255.0d;
rgb[2] = searchColourb / 255.0d;
if (rgb[0] > .04045d)
{
rgb[0] = Math.Pow((rgb[0] + .055d) / 1.055d, 2.4d);
}
else
{
rgb[0] = rgb[0] / 12.92d;
}
if (rgb[1] > .04045d)
{
rgb[1] = Math.Pow((rgb[1] + .055d) / 1.055d, 2.4d);
}
else
{
rgb[1] = rgb[1] / 12.92d;
}
if (rgb[2] > .04045d)
{
rgb[2] = Math.Pow((rgb[2] + .055d) / 1.055d, 2.4d);
}
else
{
rgb[2] = rgb[2] / 12.92d;
}
//D50 sRGB working space
xyz[0] = ((rgb[0] * 0.4360747d) + (rgb[1] * 0.3850649d) + (rgb[2] * 0.1430804d));
xyz[1] = ((rgb[0] * 0.2225045d) + (rgb[1] * 0.7168786d) + (rgb[2] * 0.0606169d));
xyz[2] = ((rgb[0] * 0.0139322d) + (rgb[1] * 0.0971045d) + (rgb[2] * 0.7141733d));
xyz[0] = xyz[0] / 0.9642d;
xyz[1] = xyz[1] / 1d;
xyz[2] = xyz[2] / 0.8252d;
if (xyz[0] > .008856d)
{
xyz[0] = Math.Pow(xyz[0], 0.3333333333333333);
}
else
{
xyz[0] = (7.787d * xyz[0]) + (16 / 116);
}
if (xyz[1] > .008856d)
{
xyz[1] = Math.Pow(xyz[1], 0.3333333333333333);
}
else
{
xyz[1] = (7.787d * xyz[1]) + (16 / 116);
}
if (xyz[2] > .008856d)
{
xyz[2] = Math.Pow(xyz[2], 0.33333333333333);
}
else
{
xyz[2] = (7.787d * xyz[2]) + (16 / 116);
}
lab[0] = (116 * xyz[1]) - 16;
lab[1] = 500 * (xyz[0] - xyz[1]);
lab[2] = 200 * (xyz[1] - xyz[2]);
searchColourResultl = lab[0];
searchColourResulta = lab[1];
searchColourResultb1 = lab[2];
}
为了测试,我使用了 RGB 代码 113,75,41,它给了我
35.699016618103713、13.845077110631209、22.692020016283632
这是不正确的,因为当我将它与 NiX 转换器交叉引用时,它为我提供了相同的 RGB 代码
35.70、13.84、26.81
如果我将其输入 Excel 电子表格,它会给我
35.69902、13.84508、26.81392
excel 和 C# 代码在各个方面都非常相似,但我看不出 C# 代码中的错误出在哪里。
尝试将双精度数更改为浮点数,使情况变得更糟,并将 LAB 中的 B 值发送到 -145
将Y光源从0.8251调整为0.8252,没有区别
2023 年 2 月 12 日
好吧,这变得更奇怪了。我刚刚调整了它(通过将每个部分分成不同的功能并且它起作用了。
void BreakdownRGB()
{
r = searchColourr / 255.0d;
g = searchColourg / 255.0d;
b = searchColourb / 255.0d;
if (r > .04045d)
{
r = Math.Pow((r + .055d) / 1.055d, 2.4d);
}
else
{
r = r / 12.92d;
}
if (g > .04045d)
{
g = Math.Pow((g + .055d) / 1.055d, 2.4d);
}
else
{
g = g / 12.92d;
}
if (b > .04045d)
{
b = Math.Pow((b + .055d) / 1.055d, 2.4d);
}
else
{
b = b / 12.92d;
}
}
void RGBtoXYZ()
{
//D50 sRGB working space
x = ((r * 0.4360747d) + (g * 0.3850649d) + (b * 0.1430804d));
y = ((r * 0.2225045d) + (g * 0.7168786d) + (b * 0.0606169d));
z = ((r * 0.0139322d) + (g * 0.0971045d) + (b * 0.7141733d));
x = x / 0.9642d;
y = y / 1d;
z = z / 0.8252d;
if (x > .008856d)
{
x = Math.Pow(x, 0.3333333333333333);
}
else
{
x = (7.787d * x) + (16 / 116);
}
if (y > .008856d)
{
y = Math.Pow(y, 0.3333333333333333);
}
else
{
y = (7.787d * y) + (16 / 116);
}
if (z > .008856d)
{
z = Math.Pow(z, 0.3333333333333333);
}
else
{
z = (7.787d * z) + (16 / 116);
}
}
void XYZtoLAB()
{
l = (116 * y) - 16;
a = 500 * (x - y);
b2 = 200 * (y - z);
searchColourResultl = Math.Round(l,5);
searchColourResulta = Math.Round(a, 5);
searchColourResultb1 = Math.Round(b2, 5);
}
但是如果我改成不同的号码(57,37,18),那就很奇怪了
如果我一步步运行,计算xyz[2]时就会出错。在 Excel 中,它给出的结果为 0.201027329,但在 C# (Unity) 中,它给出的结果为 0.06309629423128113,xyz[0] 和 xyz[1] 是正确的。
c# 给出的 RGB 值是
R = 0.040915196906853191
G = 0.018500220128379697
B = 0.0060488330228570539
这在Excel表格上得到确认
如果我改变
if (z > .008856d)
到
if (z < .008856d)
它可以工作,但不适用于其他 RGB 代码
如果您乐意使用库,Unicolour 经过充分测试并给出了预期的结果:
var config = new Configuration(RgbConfiguration.StandardRgb, XyzConfiguration.D50);
var colour = new Unicolour(config, ColourSpace.Rgb255, 113, 75, 41);
Console.WriteLine(colour.Lab); // 35.70 +13.84 +26.81