将 RGB 颜色转换为 XY
convert RGB color to XY
我使用 RUCKUS API 来改变 lamp 的颜色,我需要将颜色从 RGB 转换为 XY 以调用 API.
我试过这个代码:
1) 从颜色对象中获取 RGB 值并将它们转换为介于 0 和 1 之间
function rgb_to_cie(red, green, blue)
{
//Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color displayed on the screen of your device
var red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
var green = (green > 0.04045) ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : (green / 12.92);
var blue = (blue > 0.04045) ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : (blue / 12.92);
//RGB values to XYZ using the Wide RGB D65 conversion formula
var X = red * 0.664511 + green * 0.154324 + blue * 0.162028;
var Y = red * 0.283881 + green * 0.668433 + blue * 0.047685;
var Z = red * 0.000088 + green * 0.072310 + blue * 0.986039;
//Calculate the xy values from the XYZ values
var x = (X / (X + Y + Z)).toFixed(4);
var y = (Y / (X + Y + Z)).toFixed(4);
if (isNaN(x))
x = 0;
if (isNaN(y))
y = 0;
return [x, y];
}
但是没有提供合适的解决方案。
所以如果我通过 r:182 g: 255 B: 65 然后我得到 x 作为 22932 和 y 为 35249(根据 API 的文档)
我该怎么做?
有几个错误:
首先:您使用的是正常变换公式,其中红色、绿色和蓝色应在 0.0 到 1.0 的范围内。因此,您可能需要将这些值除以 255。
其次:您正在应用伽玛。要转换为 X、Y、Z,您需要线性值。通常我们有伽马校正的 RGB(例如像素值)。所以你矫枉过正了。相反,您应该应用伽玛的倒数,这样您将得到线性 R、G、B,这样您就可以应用线性变换来得到 X、Y、Z。
第三:您将返回 x,y 而不是 X,Y 作为您的问题(和评论)。另一方面,您确定需要 X,Y 吗?通常 x,y 用于 "colour"。我希望有一个 x,y + Y(或一些亮度参数)。
您可能应该缩减这些值。如您所见,范围通常是 0 到 1,或 0 到 100(过去),或 0 到 255、0 到 65535。没有标准:这些只是没有单位的数字。 [与电脑屏幕相反,Phillips Hue应该知道它的最大亮度是多少,但是..这是一个例外]。
我找到了解决方案,如果您正在寻找答案,我会在此处附上答案,
let red = 100
let green = 100
let blue = 100
let redC = (red / 255)
let greenC = (green / 255)
let blueC = (blue / 255)
console.log(redC, greenC , blueC)
let redN = (redC > 0.04045) ? Math.pow((redC + 0.055) / (1.0 + 0.055), 2.4): (redC / 12.92)
let greenN = (greenC > 0.04045) ? Math.pow((greenC + 0.055) / (1.0 + 0.055), 2.4) : (greenC / 12.92)
let blueN = (blueC > 0.04045) ? Math.pow((blueC + 0.055) / (1.0 + 0.055), 2.4) : (blueC / 12.92)
console.log(redN, greenN, blueN)
let X = redN * 0.664511 + greenN * 0.154324 + blueN * 0.162028;
let Y = redN * 0.283881 + greenN * 0.668433 + blueN * 0.047685;
let Z = redN * 0.000088 + greenN * 0.072310 + blueN * 0.986039;
console.log(X, Y, Z)
let x = X / (X + Y + Z);
let y = Y / (X + Y + Z);
X = x * 65536
Y = y * 65536
我使用 RUCKUS API 来改变 lamp 的颜色,我需要将颜色从 RGB 转换为 XY 以调用 API.
我试过这个代码:
1) 从颜色对象中获取 RGB 值并将它们转换为介于 0 和 1 之间
function rgb_to_cie(red, green, blue)
{
//Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color displayed on the screen of your device
var red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
var green = (green > 0.04045) ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : (green / 12.92);
var blue = (blue > 0.04045) ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : (blue / 12.92);
//RGB values to XYZ using the Wide RGB D65 conversion formula
var X = red * 0.664511 + green * 0.154324 + blue * 0.162028;
var Y = red * 0.283881 + green * 0.668433 + blue * 0.047685;
var Z = red * 0.000088 + green * 0.072310 + blue * 0.986039;
//Calculate the xy values from the XYZ values
var x = (X / (X + Y + Z)).toFixed(4);
var y = (Y / (X + Y + Z)).toFixed(4);
if (isNaN(x))
x = 0;
if (isNaN(y))
y = 0;
return [x, y];
}
但是没有提供合适的解决方案。
所以如果我通过 r:182 g: 255 B: 65 然后我得到 x 作为 22932 和 y 为 35249(根据 API 的文档)
我该怎么做?
有几个错误:
首先:您使用的是正常变换公式,其中红色、绿色和蓝色应在 0.0 到 1.0 的范围内。因此,您可能需要将这些值除以 255。
其次:您正在应用伽玛。要转换为 X、Y、Z,您需要线性值。通常我们有伽马校正的 RGB(例如像素值)。所以你矫枉过正了。相反,您应该应用伽玛的倒数,这样您将得到线性 R、G、B,这样您就可以应用线性变换来得到 X、Y、Z。
第三:您将返回 x,y 而不是 X,Y 作为您的问题(和评论)。另一方面,您确定需要 X,Y 吗?通常 x,y 用于 "colour"。我希望有一个 x,y + Y(或一些亮度参数)。
您可能应该缩减这些值。如您所见,范围通常是 0 到 1,或 0 到 100(过去),或 0 到 255、0 到 65535。没有标准:这些只是没有单位的数字。 [与电脑屏幕相反,Phillips Hue应该知道它的最大亮度是多少,但是..这是一个例外]。
我找到了解决方案,如果您正在寻找答案,我会在此处附上答案,
let red = 100
let green = 100
let blue = 100
let redC = (red / 255)
let greenC = (green / 255)
let blueC = (blue / 255)
console.log(redC, greenC , blueC)
let redN = (redC > 0.04045) ? Math.pow((redC + 0.055) / (1.0 + 0.055), 2.4): (redC / 12.92)
let greenN = (greenC > 0.04045) ? Math.pow((greenC + 0.055) / (1.0 + 0.055), 2.4) : (greenC / 12.92)
let blueN = (blueC > 0.04045) ? Math.pow((blueC + 0.055) / (1.0 + 0.055), 2.4) : (blueC / 12.92)
console.log(redN, greenN, blueN)
let X = redN * 0.664511 + greenN * 0.154324 + blueN * 0.162028;
let Y = redN * 0.283881 + greenN * 0.668433 + blueN * 0.047685;
let Z = redN * 0.000088 + greenN * 0.072310 + blueN * 0.986039;
console.log(X, Y, Z)
let x = X / (X + Y + Z);
let y = Y / (X + Y + Z);
X = x * 65536
Y = y * 65536