Color.Conversion.Lindbloom
(Color v0.4.0)
Copy Markdown
Color space conversion functions based on the formulas published by Bruce Lindbloom at http://www.brucelindbloom.com/index.html?Math.html.
All functions operate on plain tuples/lists of floats so they can be
composed freely. Reference whites (wr) are supplied as {xr, yr, zr}
tuples in the same scale as the XYZ values (typically Y = 1.0 or
Y = 100.0; both work as long as the inputs are consistent).
The CIE constants ε and κ are used in their exact rational form as
recommended by Lindbloom, rather than the rounded values found in many
older references.
Constants
ε = 216/24389 ≈ 0.008856.κ = 24389/27 ≈ 903.2963.
Summary
Functions
Returns the CIE constants ε and κ used by the conversions.
Applies simple gamma companding (linear → non-linear).
Inverts simple gamma companding (non-linear → linear).
Applies the Hybrid Log-Gamma inverse EOTF (linear scene-referred light → HLG signal).
Applies the HLG EOTF (HLG signal → linear scene-referred light).
Inverts a 3x3 matrix represented as a list of rows. Used to derive the XYZ→RGB matrix from the RGB→XYZ matrix.
Applies the L companding function (linear → L).
Inverts the L companding function (L → linear).
Converts CIE L*a*b* to cylindrical LCHab.
Converts CIE L*a*b* to a CIE XYZ triple.
Converts cylindrical LCHab to CIE L*a*b*.
Converts cylindrical LCHuv to CIE L*u*v*.
Converts CIE L*u*v* to cylindrical LCHuv.
Converts CIE L*u*v* to a CIE XYZ triple.
Multiplies two 3x3 matrices given as lists of rows.
Applies the SMPTE ST 2084 / BT.2100 PQ inverse EOTF (linear luminance → non-linear PQ signal).
Applies the SMPTE ST 2084 / BT.2100 PQ EOTF
(PQ signal → linear luminance in [0, 1] where 1.0 = 10,000 cd/m²).
Applies the ITU-R BT.709 opto-electronic transfer function (linear → non-linear).
Inverts the BT.709 OETF (non-linear → linear).
Applies the ITU-R BT.2020 OETF at 12-bit precision (linear → non-linear).
Inverts the BT.2020 12-bit OETF (non-linear → linear).
Converts linear RGB to XYZ using a working-space matrix m.
Applies the sRGB companding function (linear → sRGB).
Inverts the sRGB companding function (sRGB → linear).
Computes the 3x3 RGB→XYZ matrix for an RGB working space from its primary chromaticities and reference white, per Lindbloom.
Converts xyY chromaticity coordinates to a CIE XYZ triple.
Converts a CIE XYZ triple to CIE L*a*b*.
Converts a CIE XYZ triple to CIE L*u*v*.
Converts XYZ to linear RGB using the inverse working-space matrix mi.
Converts a CIE XYZ triple to xyY.
Functions
Returns the CIE constants ε and κ used by the conversions.
Returns
- A
{epsilon, kappa}tuple of floats.
Examples
iex> {e, k} = Color.Conversion.Lindbloom.constants()
iex> Float.round(e, 6)
0.008856
iex> Float.round(k, 4)
903.2963
Applies simple gamma companding (linear → non-linear).
Arguments
vis a linear channel value.gammais the gamma exponent (for example2.2).
Inverts simple gamma companding (non-linear → linear).
Arguments
vis a companded channel value.gammais the gamma exponent.
Applies the Hybrid Log-Gamma inverse EOTF (linear scene-referred light → HLG signal).
Input and output are both in [0, 1]. The HLG curve is gamma at the
dark end and logarithmic at the bright end, meeting at E = 1/12.
Arguments
vis a linear channel value in[0, 1].
Applies the HLG EOTF (HLG signal → linear scene-referred light).
Arguments
vis an HLG-encoded channel value in[0, 1].
Inverts a 3x3 matrix represented as a list of rows. Used to derive the XYZ→RGB matrix from the RGB→XYZ matrix.
Arguments
mis a 3x3 matrix as a list of three three-element rows.
Returns
- The inverse matrix in the same shape.
Applies the L companding function (linear → L).
Arguments
vis a linear channel value in[0, 1].
Inverts the L companding function (L → linear).
Arguments
vis an L*-companded channel value.
Converts CIE L*a*b* to cylindrical LCHab.
Arguments
labis an{l, a, b}tuple.
Returns
- An
{l, c, h}tuple wherehis in degrees in the range[0, 360).
Examples
iex> Color.Conversion.Lindbloom.lab_to_lchab({50.0, 0.0, 0.0})
{50.0, 0.0, 0.0}
Converts CIE L*a*b* to a CIE XYZ triple.
Arguments
labis an{l, a, b}tuple.wris the{Xr, Yr, Zr}reference white tuple.
Returns
- An
{X, Y, Z}tuple.
Examples
iex> {x, y, z} = Color.Conversion.Lindbloom.lab_to_xyz({100.0, 0.0, 0.0}, {0.95047, 1.0, 1.08883})
iex> {Float.round(x, 5), Float.round(y, 5), Float.round(z, 5)}
{0.95047, 1.0, 1.08883}
Converts cylindrical LCHab to CIE L*a*b*.
Arguments
lchis an{l, c, h}tuple withhin degrees.
Returns
- An
{l, a, b}tuple.
Examples
iex> Color.Conversion.Lindbloom.lchab_to_lab({50.0, 0.0, 0.0})
{50.0, 0.0, 0.0}
Converts cylindrical LCHuv to CIE L*u*v*.
Arguments
lchis an{l, c, h}tuple withhin degrees.
Returns
- An
{l, u, v}tuple.
Examples
iex> Color.Conversion.Lindbloom.lchuv_to_luv({50.0, 0.0, 0.0})
{50.0, 0.0, 0.0}
Converts CIE L*u*v* to cylindrical LCHuv.
Arguments
luvis an{l, u, v}tuple.
Returns
- An
{l, c, h}tuple wherehis in degrees in the range[0, 360).
Examples
iex> Color.Conversion.Lindbloom.luv_to_lchuv({50.0, 0.0, 0.0})
{50.0, 0.0, 0.0}
Converts CIE L*u*v* to a CIE XYZ triple.
Arguments
luvis an{l, u, v}tuple.wris the{Xr, Yr, Zr}reference white tuple.
Returns
- An
{X, Y, Z}tuple.
Examples
iex> Color.Conversion.Lindbloom.luv_to_xyz({0.0, 0.0, 0.0}, {0.95047, 1.0, 1.08883})
{0.0, 0.0, 0.0}
Multiplies two 3x3 matrices given as lists of rows.
Arguments
ais a 3x3 matrix as a list of three three-element rows.bis a 3x3 matrix in the same shape.
Returns
- The product
a · bin the same shape.
Applies the SMPTE ST 2084 / BT.2100 PQ inverse EOTF (linear luminance → non-linear PQ signal).
Input is absolute luminance in [0, 1] where 1.0 represents
10,000 cd/m². Output is the PQ-encoded signal in [0, 1].
Arguments
vis a linear luminance value in[0, 1].
Applies the SMPTE ST 2084 / BT.2100 PQ EOTF
(PQ signal → linear luminance in [0, 1] where 1.0 = 10,000 cd/m²).
Arguments
vis a PQ-encoded value in[0, 1].
Applies the ITU-R BT.709 opto-electronic transfer function (linear → non-linear).
BT.709 uses the same shape as the Rec. 2020 SDR curve but is defined at 8/10-bit precision; this implementation matches both.
Arguments
vis a linear channel value in[0, 1].
Inverts the BT.709 OETF (non-linear → linear).
Arguments
vis a non-linear BT.709 channel value in[0, 1].
Applies the ITU-R BT.2020 OETF at 12-bit precision (linear → non-linear).
BT.2020 refines the BT.709 curve with higher-precision constants for 12-bit systems. At 10-bit precision BT.2020 is identical to BT.709.
Arguments
vis a linear channel value in[0, 1].
Inverts the BT.2020 12-bit OETF (non-linear → linear).
Arguments
vis a non-linear BT.2020 channel value in[0, 1].
Converts linear RGB to XYZ using a working-space matrix m.
Uses plain f64 arithmetic rather than Nx: for single-color 3x3 work
the BEAM's float ops are roughly 25x faster than Nx on the host
backend, and preserve double precision. Nx is still the right choice
for batched color operations elsewhere in this project.
Arguments
rgbis an{r, g, b}tuple of linear (companding-removed) values.mis the 3x3 RGB→XYZ matrix for the working space, as a list of three three-element rows.
Returns
- An
{X, Y, Z}tuple.
Examples
iex> m = [[0.4124564, 0.3575761, 0.1804375],
...> [0.2126729, 0.7151522, 0.0721750],
...> [0.0193339, 0.1191920, 0.9503041]]
iex> {x, y, z} = Color.Conversion.Lindbloom.rgb_to_xyz({1.0, 1.0, 1.0}, m)
iex> {Float.round(x, 4), Float.round(y, 4), Float.round(z, 4)}
{0.9505, 1.0, 1.0888}
Applies the sRGB companding function (linear → sRGB).
Arguments
vis a linear channel value in[0, 1].
Inverts the sRGB companding function (sRGB → linear).
Arguments
vis a companded sRGB channel value in[0, 1].
Computes the 3x3 RGB→XYZ matrix for an RGB working space from its primary chromaticities and reference white, per Lindbloom.
Given the primaries {xr, yr}, {xg, yg}, {xb, yb} and the reference
white {Xw, Yw, Zw} the matrix is [Sr·Xr Sg·Xg Sb·Xb; …] where the
scale factors S are found by solving M · [Sr Sg Sb]ᵀ = W.
Arguments
primariesis a{{xr, yr}, {xg, yg}, {xb, yb}}tuple of chromaticities.wris the{Xw, Yw, Zw}reference white.
Returns
- The RGB→XYZ matrix as a list of three three-element rows.
Converts xyY chromaticity coordinates to a CIE XYZ triple.
Arguments
xyyis an{x, y, y_big}tuple.
Returns
- An
{X, Y, Z}tuple.
Examples
iex> {x, y, z} = Color.Conversion.Lindbloom.xyy_to_xyz({0.3127, 0.3290, 1.0})
iex> {Float.round(x, 5), Float.round(y, 5), Float.round(z, 5)}
{0.95046, 1.0, 1.08906}
Converts a CIE XYZ triple to CIE L*a*b*.
Arguments
xyzis an{X, Y, Z}tuple.wris the{Xr, Yr, Zr}reference white tuple.
Returns
- An
{l, a, b}tuple.
Examples
iex> Color.Conversion.Lindbloom.xyz_to_lab({0.95047, 1.0, 1.08883}, {0.95047, 1.0, 1.08883})
{100.0, 0.0, 0.0}
Converts a CIE XYZ triple to CIE L*u*v*.
Arguments
xyzis an{X, Y, Z}tuple.wris the{Xr, Yr, Zr}reference white tuple.
Returns
- An
{l, u, v}tuple.
Examples
iex> Color.Conversion.Lindbloom.xyz_to_luv({0.0, 0.0, 0.0}, {0.95047, 1.0, 1.08883})
{0.0, 0.0, 0.0}
Converts XYZ to linear RGB using the inverse working-space matrix mi.
Arguments
xyzis an{X, Y, Z}tuple.miis the 3x3 XYZ→RGB (inverse) matrix, as a list of three three-element rows.
Returns
- An
{r, g, b}tuple of linear values.
Converts a CIE XYZ triple to xyY.
When X + Y + Z = 0 the chromaticity is taken from the reference white
as prescribed by Lindbloom.
Arguments
xyzis an{x, y, z}tuple.wris the{xr, yr, zr}reference white used whenX + Y + Z = 0.
Returns
- An
{x, y, y_big}tuple wherexandyare chromaticity coordinates andy_bigis the originalY.
Examples
iex> Color.Conversion.Lindbloom.xyz_to_xyy({0.5, 0.5, 0.5}, {0.95047, 1.0, 1.08883})
{0.3333333333333333, 0.3333333333333333, 0.5}
iex> {x, y, yy} = Color.Conversion.Lindbloom.xyz_to_xyy({0.95047, 1.0, 1.08883}, {0.95047, 1.0, 1.08883})
iex> {Float.round(x, 5), Float.round(y, 5), Float.round(yy, 4)}
{0.31273, 0.32902, 1.0}