Improve Philips Hue color conversion 2 (#20118)
* Add gamut capability to color util * Include gamut in hue_test * Improve Philips Hue color conversion * correct import for new location hue.light * include file changes between PR's * update aiohue version * update aiohue version * update aiohue version * fix hue_test Now Idea why it failed compared to the previous time * Include gamut in hue_test * fix hue_test * Try to test hue gamut conversion supply a color that is well outside the color gamut of the light, and see if the response is correctly converted to within the reach of the light. * switch from gamut A to gamut B for the tests. * remove white space in blanck line * Fix gamut hue test * Add Gamut tests for the util.color * fix hue gamut test * fix hue gamut test * Improve Philips Hue color conversionpull/20143/head
parent
a3f0d55737
commit
11602c1da0
|
@ -19,7 +19,7 @@ from .bridge import HueBridge
|
|||
# Loading the config flow file will register the flow
|
||||
from .config_flow import configured_hosts
|
||||
|
||||
REQUIREMENTS = ['aiohue==1.5.0']
|
||||
REQUIREMENTS = ['aiohue==1.8.0']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -221,9 +221,16 @@ class HueLight(Light):
|
|||
if is_group:
|
||||
self.is_osram = False
|
||||
self.is_philips = False
|
||||
self.gamut_typ = 'None'
|
||||
self.gamut = None
|
||||
else:
|
||||
self.is_osram = light.manufacturername == 'OSRAM'
|
||||
self.is_philips = light.manufacturername == 'Philips'
|
||||
self.gamut_typ = self.light.colorgamuttype
|
||||
self.gamut = self.light.colorgamut
|
||||
if not self.gamut:
|
||||
err_msg = 'Can not get color gamut of light "%s"'
|
||||
_LOGGER.warning(err_msg, self.name)
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
|
@ -256,7 +263,7 @@ class HueLight(Light):
|
|||
source = self.light.action if self.is_group else self.light.state
|
||||
|
||||
if mode in ('xy', 'hs') and 'xy' in source:
|
||||
return color.color_xy_to_hs(*source['xy'])
|
||||
return color.color_xy_to_hs(*source['xy'], self.gamut)
|
||||
|
||||
return None
|
||||
|
||||
|
@ -290,6 +297,11 @@ class HueLight(Light):
|
|||
"""Flag supported features."""
|
||||
return SUPPORT_HUE.get(self.light.type, SUPPORT_HUE_EXTENDED)
|
||||
|
||||
@property
|
||||
def effect(self):
|
||||
"""Return the current effect."""
|
||||
return self.light.state.get('effect', None)
|
||||
|
||||
@property
|
||||
def effect_list(self):
|
||||
"""Return the list of supported effects."""
|
||||
|
@ -331,7 +343,9 @@ class HueLight(Light):
|
|||
# Philips hue bulb models respond differently to hue/sat
|
||||
# requests, so we convert to XY first to ensure a consistent
|
||||
# color.
|
||||
command['xy'] = color.color_hs_to_xy(*kwargs[ATTR_HS_COLOR])
|
||||
xy_color = color.color_hs_to_xy(*kwargs[ATTR_HS_COLOR],
|
||||
self.gamut)
|
||||
command['xy'] = xy_color
|
||||
elif ATTR_COLOR_TEMP in kwargs:
|
||||
temp = kwargs[ATTR_COLOR_TEMP]
|
||||
command['ct'] = max(self.min_mireds, min(temp, self.max_mireds))
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
import math
|
||||
import colorsys
|
||||
|
||||
from typing import Tuple, List
|
||||
from typing import Tuple, List, Optional
|
||||
import attr
|
||||
|
||||
# Official CSS3 colors from w3.org:
|
||||
# https://www.w3.org/TR/2010/PR-css3-color-20101028/#html4
|
||||
|
@ -162,6 +163,24 @@ COLORS = {
|
|||
}
|
||||
|
||||
|
||||
@attr.s()
|
||||
class XYPoint:
|
||||
"""Represents a CIE 1931 XY coordinate pair."""
|
||||
|
||||
x = attr.ib(type=float)
|
||||
y = attr.ib(type=float)
|
||||
|
||||
|
||||
@attr.s()
|
||||
class GamutType:
|
||||
"""Represents the Gamut of a light."""
|
||||
|
||||
# ColorGamut = gamut(xypoint(xR,yR),xypoint(xG,yG),xypoint(xB,yB))
|
||||
red = attr.ib(type=XYPoint)
|
||||
green = attr.ib(type=XYPoint)
|
||||
blue = attr.ib(type=XYPoint)
|
||||
|
||||
|
||||
def color_name_to_rgb(color_name: str) -> Tuple[int, int, int]:
|
||||
"""Convert color name to RGB hex value."""
|
||||
# COLORS map has no spaces in it, so make the color_name have no
|
||||
|
@ -174,9 +193,10 @@ def color_name_to_rgb(color_name: str) -> Tuple[int, int, int]:
|
|||
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
def color_RGB_to_xy(iR: int, iG: int, iB: int) -> Tuple[float, float]:
|
||||
def color_RGB_to_xy(iR: int, iG: int, iB: int,
|
||||
Gamut: Optional[GamutType] = None) -> Tuple[float, float]:
|
||||
"""Convert from RGB color to XY color."""
|
||||
return color_RGB_to_xy_brightness(iR, iG, iB)[:2]
|
||||
return color_RGB_to_xy_brightness(iR, iG, iB, Gamut)[:2]
|
||||
|
||||
|
||||
# Taken from:
|
||||
|
@ -184,7 +204,8 @@ def color_RGB_to_xy(iR: int, iG: int, iB: int) -> Tuple[float, float]:
|
|||
# License: Code is given as is. Use at your own risk and discretion.
|
||||
# pylint: disable=invalid-name
|
||||
def color_RGB_to_xy_brightness(
|
||||
iR: int, iG: int, iB: int) -> Tuple[float, float, int]:
|
||||
iR: int, iG: int, iB: int,
|
||||
Gamut: Optional[GamutType] = None) -> Tuple[float, float, int]:
|
||||
"""Convert from RGB color to XY color."""
|
||||
if iR + iG + iB == 0:
|
||||
return 0.0, 0.0, 0
|
||||
|
@ -214,19 +235,36 @@ def color_RGB_to_xy_brightness(
|
|||
Y = 1 if Y > 1 else Y
|
||||
brightness = round(Y * 255)
|
||||
|
||||
# Check if the given xy value is within the color-reach of the lamp.
|
||||
if Gamut:
|
||||
in_reach = check_point_in_lamps_reach((x, y), Gamut)
|
||||
if not in_reach:
|
||||
xy_closest = get_closest_point_to_point((x, y), Gamut)
|
||||
x = xy_closest[0]
|
||||
y = xy_closest[1]
|
||||
|
||||
return round(x, 3), round(y, 3), brightness
|
||||
|
||||
|
||||
def color_xy_to_RGB(vX: float, vY: float) -> Tuple[int, int, int]:
|
||||
def color_xy_to_RGB(
|
||||
vX: float, vY: float,
|
||||
Gamut: Optional[GamutType] = None) -> Tuple[int, int, int]:
|
||||
"""Convert from XY to a normalized RGB."""
|
||||
return color_xy_brightness_to_RGB(vX, vY, 255)
|
||||
return color_xy_brightness_to_RGB(vX, vY, 255, Gamut)
|
||||
|
||||
|
||||
# Converted to Python from Obj-C, original source from:
|
||||
# http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
|
||||
def color_xy_brightness_to_RGB(vX: float, vY: float,
|
||||
ibrightness: int) -> Tuple[int, int, int]:
|
||||
def color_xy_brightness_to_RGB(
|
||||
vX: float, vY: float, ibrightness: int,
|
||||
Gamut: Optional[GamutType] = None) -> Tuple[int, int, int]:
|
||||
"""Convert from XYZ to RGB."""
|
||||
if Gamut:
|
||||
if not check_point_in_lamps_reach((vX, vY), Gamut):
|
||||
xy_closest = get_closest_point_to_point((vX, vY), Gamut)
|
||||
vX = xy_closest[0]
|
||||
vY = xy_closest[1]
|
||||
|
||||
brightness = ibrightness / 255.
|
||||
if brightness == 0:
|
||||
return (0, 0, 0)
|
||||
|
@ -338,15 +376,17 @@ def color_hs_to_RGB(iH: float, iS: float) -> Tuple[int, int, int]:
|
|||
return color_hsv_to_RGB(iH, iS, 100)
|
||||
|
||||
|
||||
def color_xy_to_hs(vX: float, vY: float) -> Tuple[float, float]:
|
||||
def color_xy_to_hs(vX: float, vY: float,
|
||||
Gamut: Optional[GamutType] = None) -> Tuple[float, float]:
|
||||
"""Convert an xy color to its hs representation."""
|
||||
h, s, _ = color_RGB_to_hsv(*color_xy_to_RGB(vX, vY))
|
||||
h, s, _ = color_RGB_to_hsv(*color_xy_to_RGB(vX, vY, Gamut))
|
||||
return h, s
|
||||
|
||||
|
||||
def color_hs_to_xy(iH: float, iS: float) -> Tuple[float, float]:
|
||||
def color_hs_to_xy(iH: float, iS: float,
|
||||
Gamut: Optional[GamutType] = None) -> Tuple[float, float]:
|
||||
"""Convert an hs color to its xy representation."""
|
||||
return color_RGB_to_xy(*color_hs_to_RGB(iH, iS))
|
||||
return color_RGB_to_xy(*color_hs_to_RGB(iH, iS), Gamut)
|
||||
|
||||
|
||||
def _match_max_scale(input_colors: Tuple, output_colors: Tuple) -> Tuple:
|
||||
|
@ -474,3 +514,89 @@ def color_temperature_mired_to_kelvin(mired_temperature: float) -> float:
|
|||
def color_temperature_kelvin_to_mired(kelvin_temperature: float) -> float:
|
||||
"""Convert degrees kelvin to mired shift."""
|
||||
return math.floor(1000000 / kelvin_temperature)
|
||||
|
||||
|
||||
# The following 5 functions are adapted from rgbxy provided by Benjamin Knight
|
||||
# License: The MIT License (MIT), 2014.
|
||||
# https://github.com/benknight/hue-python-rgb-converter
|
||||
def cross_product(p1: XYPoint, p2: XYPoint) -> float:
|
||||
"""Calculate the cross product of two XYPoints."""
|
||||
return float(p1.x * p2.y - p1.y * p2.x)
|
||||
|
||||
|
||||
def get_distance_between_two_points(one: XYPoint, two: XYPoint) -> float:
|
||||
"""Calculate the distance between two XYPoints."""
|
||||
dx = one.x - two.x
|
||||
dy = one.y - two.y
|
||||
return math.sqrt(dx * dx + dy * dy)
|
||||
|
||||
|
||||
def get_closest_point_to_line(A: XYPoint, B: XYPoint, P: XYPoint) -> XYPoint:
|
||||
"""
|
||||
Find the closest point from P to a line defined by A and B.
|
||||
|
||||
This point will be reproducible by the lamp
|
||||
as it is on the edge of the gamut.
|
||||
"""
|
||||
AP = XYPoint(P.x - A.x, P.y - A.y)
|
||||
AB = XYPoint(B.x - A.x, B.y - A.y)
|
||||
ab2 = AB.x * AB.x + AB.y * AB.y
|
||||
ap_ab = AP.x * AB.x + AP.y * AB.y
|
||||
t = ap_ab / ab2
|
||||
|
||||
if t < 0.0:
|
||||
t = 0.0
|
||||
elif t > 1.0:
|
||||
t = 1.0
|
||||
|
||||
return XYPoint(A.x + AB.x * t, A.y + AB.y * t)
|
||||
|
||||
|
||||
def get_closest_point_to_point(xy_tuple: Tuple[float, float],
|
||||
Gamut: GamutType) -> Tuple[float, float]:
|
||||
"""
|
||||
Get the closest matching color within the gamut of the light.
|
||||
|
||||
Should only be used if the supplied color is outside of the color gamut.
|
||||
"""
|
||||
xy_point = XYPoint(xy_tuple[0], xy_tuple[1])
|
||||
|
||||
# find the closest point on each line in the CIE 1931 'triangle'.
|
||||
pAB = get_closest_point_to_line(Gamut.red, Gamut.green, xy_point)
|
||||
pAC = get_closest_point_to_line(Gamut.blue, Gamut.red, xy_point)
|
||||
pBC = get_closest_point_to_line(Gamut.green, Gamut.blue, xy_point)
|
||||
|
||||
# Get the distances per point and see which point is closer to our Point.
|
||||
dAB = get_distance_between_two_points(xy_point, pAB)
|
||||
dAC = get_distance_between_two_points(xy_point, pAC)
|
||||
dBC = get_distance_between_two_points(xy_point, pBC)
|
||||
|
||||
lowest = dAB
|
||||
closest_point = pAB
|
||||
|
||||
if dAC < lowest:
|
||||
lowest = dAC
|
||||
closest_point = pAC
|
||||
|
||||
if dBC < lowest:
|
||||
lowest = dBC
|
||||
closest_point = pBC
|
||||
|
||||
# Change the xy value to a value which is within the reach of the lamp.
|
||||
cx = closest_point.x
|
||||
cy = closest_point.y
|
||||
|
||||
return (cx, cy)
|
||||
|
||||
|
||||
def check_point_in_lamps_reach(p: Tuple[float, float],
|
||||
Gamut: GamutType) -> bool:
|
||||
"""Check if the provided XYPoint can be recreated by a Hue lamp."""
|
||||
v1 = XYPoint(Gamut.green.x - Gamut.red.x, Gamut.green.y - Gamut.red.y)
|
||||
v2 = XYPoint(Gamut.blue.x - Gamut.red.x, Gamut.blue.y - Gamut.red.y)
|
||||
|
||||
q = XYPoint(p[0] - Gamut.red.x, p[1] - Gamut.red.y)
|
||||
s = cross_product(q, v2) / cross_product(v1, v2)
|
||||
t = cross_product(v1, q) / cross_product(v1, v2)
|
||||
|
||||
return (s >= 0.0) and (t >= 0.0) and (s + t <= 1.0)
|
||||
|
|
|
@ -112,7 +112,7 @@ aioharmony==0.1.2
|
|||
aiohttp_cors==0.7.0
|
||||
|
||||
# homeassistant.components.hue
|
||||
aiohue==1.5.0
|
||||
aiohue==1.8.0
|
||||
|
||||
# homeassistant.components.sensor.imap
|
||||
aioimaplib==0.7.13
|
||||
|
|
|
@ -38,7 +38,7 @@ aioautomatic==0.6.5
|
|||
aiohttp_cors==0.7.0
|
||||
|
||||
# homeassistant.components.hue
|
||||
aiohue==1.5.0
|
||||
aiohue==1.8.0
|
||||
|
||||
# homeassistant.components.unifi
|
||||
aiounifi==4
|
||||
|
|
|
@ -85,6 +85,16 @@ LIGHT_1_ON = {
|
|||
"colormode": "xy",
|
||||
"reachable": True
|
||||
},
|
||||
"capabilities": {
|
||||
"control": {
|
||||
"colorgamuttype": "A",
|
||||
"colorgamut": [
|
||||
[0.704, 0.296],
|
||||
[0.2151, 0.7106],
|
||||
[0.138, 0.08]
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "Extended color light",
|
||||
"name": "Hue Lamp 1",
|
||||
"modelid": "LCT001",
|
||||
|
@ -105,6 +115,16 @@ LIGHT_1_OFF = {
|
|||
"colormode": "xy",
|
||||
"reachable": True
|
||||
},
|
||||
"capabilities": {
|
||||
"control": {
|
||||
"colorgamuttype": "A",
|
||||
"colorgamut": [
|
||||
[0.704, 0.296],
|
||||
[0.2151, 0.7106],
|
||||
[0.138, 0.08]
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "Extended color light",
|
||||
"name": "Hue Lamp 1",
|
||||
"modelid": "LCT001",
|
||||
|
@ -125,6 +145,16 @@ LIGHT_2_OFF = {
|
|||
"colormode": "hs",
|
||||
"reachable": True
|
||||
},
|
||||
"capabilities": {
|
||||
"control": {
|
||||
"colorgamuttype": "A",
|
||||
"colorgamut": [
|
||||
[0.704, 0.296],
|
||||
[0.2151, 0.7106],
|
||||
[0.138, 0.08]
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "Extended color light",
|
||||
"name": "Hue Lamp 2",
|
||||
"modelid": "LCT001",
|
||||
|
@ -145,6 +175,16 @@ LIGHT_2_ON = {
|
|||
"colormode": "hs",
|
||||
"reachable": True
|
||||
},
|
||||
"capabilities": {
|
||||
"control": {
|
||||
"colorgamuttype": "A",
|
||||
"colorgamut": [
|
||||
[0.704, 0.296],
|
||||
[0.2151, 0.7106],
|
||||
[0.138, 0.08]
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "Extended color light",
|
||||
"name": "Hue Lamp 2 new",
|
||||
"modelid": "LCT001",
|
||||
|
@ -156,6 +196,23 @@ LIGHT_RESPONSE = {
|
|||
"1": LIGHT_1_ON,
|
||||
"2": LIGHT_2_OFF,
|
||||
}
|
||||
LIGHT_RAW = {
|
||||
"capabilities": {
|
||||
"control": {
|
||||
"colorgamuttype": "A",
|
||||
"colorgamut": [
|
||||
[0.704, 0.296],
|
||||
[0.2151, 0.7106],
|
||||
[0.138, 0.08]
|
||||
]
|
||||
}
|
||||
},
|
||||
"swversion": "66009461",
|
||||
}
|
||||
LIGHT_GAMUT = color.GamutType(color.XYPoint(0.704, 0.296),
|
||||
color.XYPoint(0.2151, 0.7106),
|
||||
color.XYPoint(0.138, 0.08))
|
||||
LIGHT_GAMUT_TYPE = 'A'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -380,6 +437,16 @@ async def test_new_light_discovered(hass, mock_bridge):
|
|||
"colormode": "hs",
|
||||
"reachable": True
|
||||
},
|
||||
"capabilities": {
|
||||
"control": {
|
||||
"colorgamuttype": "A",
|
||||
"colorgamut": [
|
||||
[0.704, 0.296],
|
||||
[0.2151, 0.7106],
|
||||
[0.138, 0.08]
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "Extended color light",
|
||||
"name": "Hue Lamp 3",
|
||||
"modelid": "LCT001",
|
||||
|
@ -493,6 +560,16 @@ async def test_other_light_update(hass, mock_bridge):
|
|||
"colormode": "hs",
|
||||
"reachable": True
|
||||
},
|
||||
"capabilities": {
|
||||
"control": {
|
||||
"colorgamuttype": "A",
|
||||
"colorgamut": [
|
||||
[0.704, 0.296],
|
||||
[0.2151, 0.7106],
|
||||
[0.138, 0.08]
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "Extended color light",
|
||||
"name": "Hue Lamp 2 new",
|
||||
"modelid": "LCT001",
|
||||
|
@ -573,6 +650,21 @@ async def test_light_turn_on_service(hass, mock_bridge):
|
|||
assert light is not None
|
||||
assert light.state == 'on'
|
||||
|
||||
# test hue gamut in turn_on service
|
||||
await hass.services.async_call('light', 'turn_on', {
|
||||
'entity_id': 'light.hue_lamp_2',
|
||||
'rgb_color': [0, 0, 255],
|
||||
}, blocking=True)
|
||||
|
||||
assert len(mock_bridge.mock_requests) == 5
|
||||
|
||||
assert mock_bridge.mock_requests[3]['json'] == {
|
||||
'on': True,
|
||||
'xy': (0.138, 0.08),
|
||||
'effect': 'none',
|
||||
'alert': 'none',
|
||||
}
|
||||
|
||||
|
||||
async def test_light_turn_off_service(hass, mock_bridge):
|
||||
"""Test calling the turn on service on a light."""
|
||||
|
@ -608,7 +700,8 @@ async def test_light_turn_off_service(hass, mock_bridge):
|
|||
def test_available():
|
||||
"""Test available property."""
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={'reachable': False}),
|
||||
light=Mock(state={'reachable': False},
|
||||
raw=LIGHT_RAW),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(allow_unreachable=False),
|
||||
is_group=False,
|
||||
|
@ -617,7 +710,8 @@ def test_available():
|
|||
assert light.available is False
|
||||
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={'reachable': False}),
|
||||
light=Mock(state={'reachable': False},
|
||||
raw=LIGHT_RAW),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(allow_unreachable=True),
|
||||
is_group=False,
|
||||
|
@ -626,7 +720,8 @@ def test_available():
|
|||
assert light.available is True
|
||||
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={'reachable': False}),
|
||||
light=Mock(state={'reachable': False},
|
||||
raw=LIGHT_RAW),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(allow_unreachable=False),
|
||||
is_group=True,
|
||||
|
@ -639,10 +734,13 @@ def test_hs_color():
|
|||
"""Test hs_color property."""
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={
|
||||
'colormode': 'ct',
|
||||
'hue': 1234,
|
||||
'sat': 123,
|
||||
}),
|
||||
'colormode': 'ct',
|
||||
'hue': 1234,
|
||||
'sat': 123,
|
||||
},
|
||||
raw=LIGHT_RAW,
|
||||
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||
colorgamut=LIGHT_GAMUT),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(),
|
||||
is_group=False,
|
||||
|
@ -652,10 +750,13 @@ def test_hs_color():
|
|||
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={
|
||||
'colormode': 'hs',
|
||||
'hue': 1234,
|
||||
'sat': 123,
|
||||
}),
|
||||
'colormode': 'hs',
|
||||
'hue': 1234,
|
||||
'sat': 123,
|
||||
},
|
||||
raw=LIGHT_RAW,
|
||||
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||
colorgamut=LIGHT_GAMUT),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(),
|
||||
is_group=False,
|
||||
|
@ -665,14 +766,17 @@ def test_hs_color():
|
|||
|
||||
light = hue_light.HueLight(
|
||||
light=Mock(state={
|
||||
'colormode': 'xy',
|
||||
'hue': 1234,
|
||||
'sat': 123,
|
||||
'xy': [0.4, 0.5]
|
||||
}),
|
||||
'colormode': 'xy',
|
||||
'hue': 1234,
|
||||
'sat': 123,
|
||||
'xy': [0.4, 0.5]
|
||||
},
|
||||
raw=LIGHT_RAW,
|
||||
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||
colorgamut=LIGHT_GAMUT),
|
||||
request_bridge_update=None,
|
||||
bridge=Mock(),
|
||||
is_group=False,
|
||||
)
|
||||
|
||||
assert light.hs_color == color.color_xy_to_hs(0.4, 0.5)
|
||||
assert light.hs_color == color.color_xy_to_hs(0.4, 0.5, LIGHT_GAMUT)
|
||||
|
|
|
@ -5,6 +5,10 @@ import homeassistant.util.color as color_util
|
|||
import pytest
|
||||
import voluptuous as vol
|
||||
|
||||
GAMUT = color_util.GamutType(color_util.XYPoint(0.704, 0.296),
|
||||
color_util.XYPoint(0.2151, 0.7106),
|
||||
color_util.XYPoint(0.138, 0.08))
|
||||
|
||||
|
||||
class TestColorUtil(unittest.TestCase):
|
||||
"""Test color util methods."""
|
||||
|
@ -29,6 +33,15 @@ class TestColorUtil(unittest.TestCase):
|
|||
assert (0.701, 0.299, 16) == \
|
||||
color_util.color_RGB_to_xy_brightness(128, 0, 0)
|
||||
|
||||
assert (0.7, 0.299, 72) == \
|
||||
color_util.color_RGB_to_xy_brightness(255, 0, 0, GAMUT)
|
||||
|
||||
assert (0.215, 0.711, 170) == \
|
||||
color_util.color_RGB_to_xy_brightness(0, 255, 0, GAMUT)
|
||||
|
||||
assert (0.138, 0.08, 12) == \
|
||||
color_util.color_RGB_to_xy_brightness(0, 0, 255, GAMUT)
|
||||
|
||||
def test_color_RGB_to_xy(self):
|
||||
"""Test color_RGB_to_xy."""
|
||||
assert (0, 0) == \
|
||||
|
@ -48,6 +61,15 @@ class TestColorUtil(unittest.TestCase):
|
|||
assert (0.701, 0.299) == \
|
||||
color_util.color_RGB_to_xy(128, 0, 0)
|
||||
|
||||
assert (0.138, 0.08) == \
|
||||
color_util.color_RGB_to_xy(0, 0, 255, GAMUT)
|
||||
|
||||
assert (0.215, 0.711) == \
|
||||
color_util.color_RGB_to_xy(0, 255, 0, GAMUT)
|
||||
|
||||
assert (0.7, 0.299) == \
|
||||
color_util.color_RGB_to_xy(255, 0, 0, GAMUT)
|
||||
|
||||
def test_color_xy_brightness_to_RGB(self):
|
||||
"""Test color_xy_brightness_to_RGB."""
|
||||
assert (0, 0, 0) == \
|
||||
|
@ -68,6 +90,15 @@ class TestColorUtil(unittest.TestCase):
|
|||
assert (0, 63, 255) == \
|
||||
color_util.color_xy_brightness_to_RGB(0, 0, 255)
|
||||
|
||||
assert (255, 0, 3) == \
|
||||
color_util.color_xy_brightness_to_RGB(1, 0, 255, GAMUT)
|
||||
|
||||
assert (82, 255, 0) == \
|
||||
color_util.color_xy_brightness_to_RGB(0, 1, 255, GAMUT)
|
||||
|
||||
assert (9, 85, 255) == \
|
||||
color_util.color_xy_brightness_to_RGB(0, 0, 255, GAMUT)
|
||||
|
||||
def test_color_xy_to_RGB(self):
|
||||
"""Test color_xy_to_RGB."""
|
||||
assert (255, 243, 222) == \
|
||||
|
@ -82,6 +113,15 @@ class TestColorUtil(unittest.TestCase):
|
|||
assert (0, 63, 255) == \
|
||||
color_util.color_xy_to_RGB(0, 0)
|
||||
|
||||
assert (255, 0, 3) == \
|
||||
color_util.color_xy_to_RGB(1, 0, GAMUT)
|
||||
|
||||
assert (82, 255, 0) == \
|
||||
color_util.color_xy_to_RGB(0, 1, GAMUT)
|
||||
|
||||
assert (9, 85, 255) == \
|
||||
color_util.color_xy_to_RGB(0, 0, GAMUT)
|
||||
|
||||
def test_color_RGB_to_hsv(self):
|
||||
"""Test color_RGB_to_hsv."""
|
||||
assert (0, 0, 0) == \
|
||||
|
@ -150,6 +190,15 @@ class TestColorUtil(unittest.TestCase):
|
|||
assert (225.176, 100) == \
|
||||
color_util.color_xy_to_hs(0, 0)
|
||||
|
||||
assert (359.294, 100) == \
|
||||
color_util.color_xy_to_hs(1, 0, GAMUT)
|
||||
|
||||
assert (100.706, 100) == \
|
||||
color_util.color_xy_to_hs(0, 1, GAMUT)
|
||||
|
||||
assert (221.463, 96.471) == \
|
||||
color_util.color_xy_to_hs(0, 0, GAMUT)
|
||||
|
||||
def test_color_hs_to_xy(self):
|
||||
"""Test color_hs_to_xy."""
|
||||
assert (0.151, 0.343) == \
|
||||
|
@ -167,6 +216,21 @@ class TestColorUtil(unittest.TestCase):
|
|||
assert (0.323, 0.329) == \
|
||||
color_util.color_hs_to_xy(360, 0)
|
||||
|
||||
assert (0.7, 0.299) == \
|
||||
color_util.color_hs_to_xy(0, 100, GAMUT)
|
||||
|
||||
assert (0.215, 0.711) == \
|
||||
color_util.color_hs_to_xy(120, 100, GAMUT)
|
||||
|
||||
assert (0.17, 0.34) == \
|
||||
color_util.color_hs_to_xy(180, 100, GAMUT)
|
||||
|
||||
assert (0.138, 0.08) == \
|
||||
color_util.color_hs_to_xy(240, 100, GAMUT)
|
||||
|
||||
assert (0.7, 0.299) == \
|
||||
color_util.color_hs_to_xy(360, 100, GAMUT)
|
||||
|
||||
def test_rgb_hex_to_rgb_list(self):
|
||||
"""Test rgb_hex_to_rgb_list."""
|
||||
assert [255, 255, 255] == \
|
||||
|
|
Loading…
Reference in New Issue