Change color_RGB_to_xy formula & return brightness (#2095)

* Use RGB to XY calculations from Philips Hue developer site

* uppercase X,Y,Z

* rename cx,cy to x,y

* return brightness in color_RGB_to_xy

* remove try/catch

* update existing platforms using color_RGB_to_xy

* improve wemo w/ jaharkes suggestion

* allow brightness override of rgb_to_xy
This commit is contained in:
Nolan Gilley 2016-05-21 13:19:27 -04:00 committed by Paulus Schoutsen
parent 31c2d45a7a
commit 191fc8f8d4
5 changed files with 40 additions and 37 deletions

View File

@ -235,14 +235,16 @@ class HueLight(Light):
if ATTR_TRANSITION in kwargs:
command['transitiontime'] = kwargs[ATTR_TRANSITION] * 10
if ATTR_BRIGHTNESS in kwargs:
command['bri'] = kwargs[ATTR_BRIGHTNESS]
if ATTR_XY_COLOR in kwargs:
command['xy'] = kwargs[ATTR_XY_COLOR]
elif ATTR_RGB_COLOR in kwargs:
command['xy'] = color_util.color_RGB_to_xy(
xyb = color_util.color_RGB_to_xy(
*(int(val) for val in kwargs[ATTR_RGB_COLOR]))
command['xy'] = xyb[0], xyb[1]
command['bri'] = xyb[2]
if ATTR_BRIGHTNESS in kwargs:
command['bri'] = kwargs[ATTR_BRIGHTNESS]
if ATTR_COLOR_TEMP in kwargs:
command['ct'] = kwargs[ATTR_COLOR_TEMP]

View File

@ -105,6 +105,7 @@ class WemoLight(Light):
elif ATTR_RGB_COLOR in kwargs:
xycolor = color_util.color_RGB_to_xy(
*(int(val) for val in kwargs[ATTR_RGB_COLOR]))
kwargs.setdefault(ATTR_BRIGHTNESS, xycolor[2])
else:
xycolor = None

View File

@ -97,7 +97,9 @@ class WinkLight(Light):
}
if rgb_color:
state_kwargs['color_xy'] = color_util.color_RGB_to_xy(*rgb_color)
xyb = color_util.color_RGB_to_xy(*rgb_color)
state_kwargs['color_xy'] = xyb[0], xyb[1]
state_kwargs['brightness'] = xyb[2]
if color_temp_mired:
state_kwargs['color_kelvin'] = mired_to_kelvin(color_temp_mired)

View File

@ -7,44 +7,41 @@ HASS_COLOR_MAX = 500 # mireds (inverted)
HASS_COLOR_MIN = 154
# Taken from: http://www.cse.unr.edu/~quiroz/inc/colortransforms.py
# Taken from:
# http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
# License: Code is given as is. Use at your own risk and discretion.
# pylint: disable=invalid-name
def color_RGB_to_xy(R, G, B):
"""Convert from RGB color to XY color."""
if R + G + B == 0:
return 0, 0
return 0, 0, 0
var_R = (R / 255.)
var_G = (G / 255.)
var_B = (B / 255.)
R = R / 255
B = B / 255
G = G / 255
if var_R > 0.04045:
var_R = ((var_R + 0.055) / 1.055) ** 2.4
else:
var_R /= 12.92
# Gamma correction
R = pow((R + 0.055) / (1.0 + 0.055),
2.4) if (R > 0.04045) else (R / 12.92)
G = pow((G + 0.055) / (1.0 + 0.055),
2.4) if (G > 0.04045) else (G / 12.92)
B = pow((B + 0.055) / (1.0 + 0.055),
2.4) if (B > 0.04045) else (B / 12.92)
if var_G > 0.04045:
var_G = ((var_G + 0.055) / 1.055) ** 2.4
else:
var_G /= 12.92
# Wide RGB D65 conversion formula
X = R * 0.664511 + G * 0.154324 + B * 0.162028
Y = R * 0.313881 + G * 0.668433 + B * 0.047685
Z = R * 0.000088 + G * 0.072310 + B * 0.986039
if var_B > 0.04045:
var_B = ((var_B + 0.055) / 1.055) ** 2.4
else:
var_B /= 12.92
# Convert XYZ to xy
x = X / (X + Y + Z)
y = Y / (X + Y + Z)
var_R *= 100
var_G *= 100
var_B *= 100
# Brightness
Y = 1 if Y > 1 else Y
brightness = round(Y * 255)
# Observer. = 2 deg, Illuminant = D65
X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505
# Convert XYZ to xy, see CIE 1931 color space on wikipedia
return X / (X + Y + Z), Y / (X + Y + Z)
return round(x, 3), round(y, 3), brightness
# taken from

View File

@ -9,16 +9,17 @@ class TestColorUtil(unittest.TestCase):
# pylint: disable=invalid-name
def test_color_RGB_to_xy(self):
"""Test color_RGB_to_xy."""
self.assertEqual((0, 0), color_util.color_RGB_to_xy(0, 0, 0))
self.assertEqual((0.3127159072215825, 0.3290014805066623),
self.assertEqual((0, 0, 0), color_util.color_RGB_to_xy(0, 0, 0))
self.assertEqual((0.32, 0.336, 255),
color_util.color_RGB_to_xy(255, 255, 255))
self.assertEqual((0.15001662234042554, 0.060006648936170214),
self.assertEqual((0.136, 0.04, 12),
color_util.color_RGB_to_xy(0, 0, 255))
self.assertEqual((0.3, 0.6), color_util.color_RGB_to_xy(0, 255, 0))
self.assertEqual((0.172, 0.747, 170),
color_util.color_RGB_to_xy(0, 255, 0))
self.assertEqual((0.6400744994567747, 0.3299705106316933),
self.assertEqual((0.679, 0.321, 80),
color_util.color_RGB_to_xy(255, 0, 0))
def test_color_xy_brightness_to_RGB(self):