The Philips Hue API returns an xy value in certain cases for the color value of the blub. How can I convert this to a HEX string? I've tried various formulas I found online but none of them work on all of the colors from the bulb.
I took a look at the guides suggested below and tried to implement in PHP as follows:
list($x, $y) = $light['state']['xy'];
$z = 1.0 - $x - $y;
$Y = $light['state']['bri'] / 255.0; // The given brightness value
$X = ($Y / $y) * $x;
$Z = ($Y / $y) * $z;
$r = $X * 1.612 - $Y * 0.203 - $Z * 0.302;
$g = -$X * 0.509 + $Y * 1.412 + $Z * 0.066;
$b = $X * 0.026 - $Y * 0.072 + $Z * 0.962;
$r = $r <= 0.0031308 ? 12.92 * $r : (1.0 + 0.055) * pow($r, (1.0 / 2.4)) - 0.055;
$g = $g <= 0.0031308 ? 12.92 * $g : (1.0 + 0.055) * pow($g, (1.0 / 2.4)) - 0.055;
$b = $b <= 0.0031308 ? 12.92 * $b : (1.0 + 0.055) * pow($b, (1.0 / 2.4)) - 0.055;
I set one of my lights to the red at the bottom left of the color picker in the Hue app and set brightness to max. Here are the resulting values:
// Read from bulb
x = 0.6472
y = 0.3302
bri = 254
// XYZ calculations
X = 1.952
Y = 0.996
Z = 0.068
// RGB calculations
r = 1.594 // Out-of-range > 1
g = 0.677
b = 0.233
As you can see, the r value generated is out of range as it is higher than 1. What am I missing in my equations?
As you can see, the r value generated is out of range as it is higher than 1. What am I missing in my equations?
The xy values returned by the Philips hue API are in CIE 1931 color space. This color space indices all colors visible by the human eye. As this color space is larger that what your device can display, not all colors are mapable to colors within the device's color space.
For example if you assume the device's color capabilities as sRGB then all the colors outside the gamut will result in a negative value for R, G and/or B. The solve this you must map these colors to a displayable color within the gamut. The easiest option is to set all value to 0 if they are negative.
Values greater than 1 can also appear. The easiest solution for this problem is to rescale all color values by the same factor so that everything is smaller than 1. A simple approach would be something like
$maxValue = max($r,$g,$b);
$r /= $maxValue;
$g /= $maxValue;
$b /= $maxValue;