Created
February 15, 2020 04:31
-
-
Save Kautenja/93b4e441e10b47df35745e1cafba194f to your computer and use it in GitHub Desktop.
methods for changing between RGB and xyZ color space for Hue devices
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Methods for converting color spaces for hue devices. | |
Reference: https://developers.meethue.com/develop/application-design-guidance/color-conversion-formulas-rgb-to-xy-and-back/ | |
""" | |
from numba import jit | |
@jit(nopython=True) | |
def correct_xyz2rgb_gamma(channel): | |
""" | |
Correct the gamma of a channel during an XYZ to sRGB conversion. | |
Args: | |
channel: the channel to correct the gamma of | |
Returns: | |
the channel after correcting the gamma | |
""" | |
# apply the correction | |
if channel <= 0.0031308: | |
channel = channel * 12.92 | |
else: | |
channel = 1.055 * pow(channel, (1.0 / 2.4)) - 0.055 | |
# normalize channel as int in [0, 255] | |
return min(255, max(0, int(channel * 255))) | |
@jit(nopython=True) | |
def xy_bri_to_rgb(x, y, brightness): | |
""" | |
Convert an XY-Brightness color to RGB. | |
Args: | |
x: the x value of the color [0.0, 1.0] | |
y: the y value of the color [0.0, 1.0] | |
brightness: the brightness value of the color [0, 254] | |
Returns: | |
an RGB tuple | |
""" | |
z = 1.0 - x - y | |
# calculate the XYZ values | |
Y = brightness / 255.0 | |
X = (Y / y) * x | |
Z = (Y / y) * z | |
# Wide gamut conversion D65 and correct gamma | |
r = correct_xyz2rgb_gamma( X * 1.656492 - Y * 0.354851 - Z * 0.255038) | |
g = correct_xyz2rgb_gamma(-X * 0.707196 + Y * 1.655397 + Z * 0.036152) | |
b = correct_xyz2rgb_gamma( X * 0.051713 - Y * 0.121364 + Z * 1.011530) | |
return r, g, b | |
@jit(nopython=True) | |
def correct_rgb2xyz_gamma(channel): | |
""" | |
Correct the gamma of a channel during an XYZ to sRGB conversion. | |
Args: | |
channel: the channel to correct the gamma of | |
Returns: | |
the channel after correcting the gamma | |
""" | |
# normalize channel in [0, 1] | |
channel /= 255 | |
# apply the correction | |
if channel > 0.04045: | |
channel = pow((channel + 0.055) / 1.055, 2.4) | |
else: | |
channel = channel / 12.92 | |
return channel | |
@jit(nopython=True) | |
def rgb_to_xy_bri(r, g, b): | |
""" | |
Convert a color from RGB color space to x,y Brightness for Philips hue. | |
Args: | |
rgb: an RGB tuple | |
Returns: | |
a tuple of | |
- the x,y values | |
- the brightness | |
""" | |
# correct the gamma | |
r = correct_rgb2xyz_gamma(r) | |
g = correct_rgb2xyz_gamma(g) | |
b = correct_rgb2xyz_gamma(b) | |
# Wide gamut conversion D65 | |
X = r * 0.664511 + g * 0.154324 + b * 0.162028 | |
Y = r * 0.283881 + g * 0.668433 + b * 0.047685 | |
Z = r * 0.000088 + g * 0.072310 + b * 0.986039 | |
# calculate the denominator to prevent any divide by zero errors | |
denominator = X + Y + Z | |
x = X / denominator if denominator > 0 else 0 | |
y = Y / denominator if denominator > 0 else 0 | |
# return the x, y tuple and shift and bound the brightness | |
return (x, y), min(255, max(0, int(Y * 255.0))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment