Colour conversion for Hue lights.
Developers think in hex, RGB, and Kelvin. Hue speaks CIE xy and mirek, and
the representable range differs per light. This module bridges the two,
always against the gamut of the light being addressed rather than a
generic one — see Hue.Color.Gamut.
{:ok, xy} = Hue.Color.to_xy("#ff8800", light)
370 = Hue.Color.kelvin_to_mirek(2700)On accuracy
to_hex/1 is not "a shade off" — it discards luminance entirely and
always answers with the brightest colour of the given hue. An xy pair
carries no luminance, so converting back to RGB requires inventing one,
and this invents the maximum (yY: 1.0). Two colours that differ only in
brightness — #000000, #808080, and #ffffff are all achromatic, so
they share one chromaticity, the D65 white point — convert to the exact
same hex: #000000 becomes #ffffff. Use it to show which colour
a light is set to, never how bright.
Bridge-data errors versus caller bugs
A colour that cannot be represented because the bridge reports data this
module cannot use — no "color" key, or one that cannot be turned into a
gamut triangle (see Hue.Color.Gamut.from_light/1) — comes back as
{:error, %Hue.Error{}}. A colour that cannot be represented because the
caller passed something that was never valid — an RGB component outside
0..255, a hex string with non-hex characters, a non-positive Kelvin
value — raises, consistent with the rest of this library (see
Hue.Error's moduledoc).
Summary
Functions
Converts a colour temperature in Kelvin to mirek, Hue's reciprocal unit.
Converts Kelvin to mirek and clamps it to the range light reports for
itself, rather than to a hardcoded constant.
Builds the CLIP v2 body for setting a colour on light.
Converts an xy pair to a hex string, for display only.
Converts a colour into an xy pair inside light's gamut.
Types
Functions
@spec kelvin_to_mirek(pos_integer()) :: pos_integer()
Converts a colour temperature in Kelvin to mirek, Hue's reciprocal unit.
Raises for a non-positive Kelvin value — dividing by zero or a negative temperature was never a valid call, so this is a caller bug rather than something to clamp away.
iex> Hue.Color.kelvin_to_mirek(2700)
370
@spec mirek_for(pos_integer(), map()) :: {:ok, pos_integer()} | {:error, Hue.Error.t()}
Converts Kelvin to mirek and clamps it to the range light reports for
itself, rather than to a hardcoded constant.
Falls back to 153-500
(Philips's published absolute mirek bounds) only if light reports
"color_temperature" but no "mirek_schema" — see the moduledoc note on
those constants above.
@spec payload(input(), map()) :: {:ok, map()} | {:error, Hue.Error.t()}
Builds the CLIP v2 body for setting a colour on light.
@spec to_hex(Hue.Color.Gamut.point()) :: {:ok, String.t()} | {:error, Hue.Error.t()}
Converts an xy pair to a hex string, for display only.
Not a lossless round trip: an xy pair carries no luminance, so this
invents the maximum (yY: 1.0) and always answers with the brightest
colour of that hue. Every achromatic input — {0.3127, 0.3290}, the D65
white point that #000000, any grey, and #ffffff all share — comes back
"#ffffff". See the moduledoc's "On accuracy" section. Good for showing
which colour a light is set to; never use it to judge brightness.
@spec to_xy(input(), map()) :: {:ok, Hue.Color.Gamut.point()} | {:error, Hue.Error.t()}
Converts a colour into an xy pair inside light's gamut.
Accepts a hex string ("#ff8800"), an {r, g, b} tuple of 0..255
integers, or an explicit {:xy, x, y} pair. Whatever the input resolves
to is clamped into light's own reported gamut (see
Hue.Color.Gamut.clamp/2) — a colour outside that triangle is not merely
approximate, it is unrepresentable on this specific light.
Returns {:error, %Hue.Error{reason: :not_color_capable}} if light has
no colour support at all, and {:error, %Hue.Error{reason: :invalid_gamut}} if it claims colour support but the bridge's gamut data
could not be parsed — see Hue.Color.Gamut.from_light/1. Both are
bridge-data problems, not caller bugs.
Raises if input itself could never have been valid — an RGB component
outside 0..255, or a hex string that is not valid hex.