我从这里得到了一个 XYZ 到 RGB 转换器并将其写入 C#,但是我遇到了一些问题。
public static XYZColor RGBtoXYZ(RGBColor rgb)
{
XYZColor xyz = new XYZColor();
float r, g, b;
r = rgb.R;
g = rgb.G;
b = rgb.B;
if (r > 0.04045f) r = (float)Math.Pow((r + 0.055)/1.055, 2.4);
else r = r / 12.92f;
if (g > 0.04045) g =(float)Math.Pow((g + 0.055f)/1.055f , 2.4f);
else g = g/12.92f;
if (b > 0.04045f) b = (float)Math.Pow((b + 0.055f)/1.055f , 2.4f);
else b = b/12.92f;
r *= 100;
g *= 100;
b *= 100;
xyz.X = r*0.4124f + g*0.3576f + b*0.1805f;
xyz.Y = r*0.2126f + g*0.7152f + b*0.0722f;
xyz.Z = r*0.0193f + g*0.1192f + b*0.9505f;
xyz.A = rgb.A;
return xyz;
}
public static RGBColor XYZtoRGB(XYZColor xyz)
{
RGBColor rgb = new RGBColor();
float x, y, z;
x = xyz.X;
y = xyz.Y;
z = xyz.Z;
x = x/100; //X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
y = y/100; //Y from 0 to 100.000
z = z/100; //Z from 0 to 108.883
rgb.R = x*3.2406f + y*-1.5372f + z*-0.4986f;
rgb.G = x*-0.9689f + y*1.8758f + z*0.0415f;
rgb.B = x*0.0557f + y*-0.2040f + z*1.0570f;
if (rgb.R > 0.0031308f) rgb.R = 1.055f*(float)Math.Pow(rgb.R, (1/2.4f)) - 0.055f;
else rgb.R = 12.92f*rgb.R;
if (rgb.G > 0.0031308f) rgb.G = 1.055f*(float)Math.Pow(rgb.G ,(1/2.4f)) - 0.055f;
else rgb.G = 12.92f*rgb.G;
if (rgb.B > 0.0031308f) rgb.B = 1.055f*(float)Math.Pow(rgb.B, (1/2.4f)) - 0.055f;
else rgb.B = 12.92f*rgb.B;
rgb.A = xyz.A;
return rgb;
}
在我的测试应用程序中,我制作了一个瓷砖地图,每个地图都有自己的颜色,然后通过 HSV 给它一个色调并循环它们,以便它显示完整的光谱。然后,每次更新都会添加色调,因此它会在光谱中移动。
但是,当我将颜色与 XYZ 相互转换时,它会像这样显示。
这是您感兴趣的代码。该HSVtoRGB
方法按预期工作。
Hue += HUEINCREASE;
RGBColor c = ColorMath.HSVtoRGB(Hue, 1, 1, 1);
//Convert to XYZ and back
XYZColor xyz = ColorMath.RGBtoXYZ(c);
c = ColorMath.XYZtoRGB(xyz);
Render.Color = c;
XYZColor 和 RGBColor 都是结构体。RGBColor 保存浮点数,如果它的值大于 1,它会环绕颜色。因此,如果它的红色值为 1.1f,它会将其包装为 .1f;