Color.Gamut.Diagram
(Color v0.11.0)
Copy Markdown
Geometric primitives for drawing chromaticity diagrams — the "horseshoe" plots used to visualise gamuts side-by-side.
This module is pure data. It does no rendering; it returns
lists of points and maps of triangles that any renderer (SVG,
PNG, a 3D engine) can consume. The companion renderer that
ships with the library is the Gamut tab of
Color.Palette.Visualizer, which emits inline SVG.
Projections
Two chromaticity projections are supported:
:xy— CIE 1931(x, y). The historical default, the plot everyone recognises. Badly perceptually skewed — the green region dominates visually, the blue corner is crushed.:uv— CIE 1976(u', v'). Modern default. Same underlying chromaticity data, a more perceptually uniform projection:u' = 4x / (−2x + 12y + 3),v' = 9y / (−2x + 12y + 3).
Primitives
spectral_locus/2— the horseshoe itself, as a list of points tracing monochromatic light from 380 nm (violet) to 700 nm (red).triangle/2— one working space's primaries and white point, as a four-entry map.planckian_locus/2— the curve of blackbody chromaticities from 1000 K to 25000 K, with CCT annotations.chromaticity/2— projects anyColor.input()to a single point in the chosen plane.xy_to_uv/1/uv_to_xy/1— the projection conversions, exposed in case callers have raw chromaticities already.
Summary
Functions
Returns the chromaticity of any colour input in the requested projection.
Returns points along the Planckian (blackbody) locus from
min to max Kelvin at the given step.
Returns the visible-spectrum locus — the outer curve of the chromaticity diagram — as a list of points.
Returns the primaries and white point of a named RGB working space as chromaticities in the requested projection.
Converts a CIE 1976 (u', v') chromaticity back to CIE 1931
(x, y).
Converts a CIE 1931 (x, y) chromaticity to CIE 1976
(u', v').
Types
@type projection() :: :xy | :uv
Functions
@spec chromaticity(Color.input(), projection()) :: {:ok, point()} | {:error, Exception.t()}
Returns the chromaticity of any colour input in the requested projection.
Arguments
coloris anything accepted byColor.new/1.projectionis:xy(default) or:uv.
Returns
{:ok, %{x, y}}or{:ok, %{u, v}}on success.{:error, exception}if the colour can't be parsed or converted.
Examples
iex> {:ok, point} = Color.Gamut.Diagram.chromaticity("#ff0000")
iex> {Float.round(point.x, 3), Float.round(point.y, 3)}
{0.64, 0.33}
iex> {:ok, point} = Color.Gamut.Diagram.chromaticity("white")
iex> {Float.round(point.x, 4), Float.round(point.y, 4)}
{0.3127, 0.329}
@spec planckian_locus(Range.t(), projection()) :: [map()]
Returns points along the Planckian (blackbody) locus from
min to max Kelvin at the given step.
Arguments
rangeis aRange.t()of Kelvin values, e.g.1000..20000//500.projectionis:xy(default) or:uv.
Returns
- A list of maps with
:kelvinplus the projection's coordinate keys.
Examples
iex> points = Color.Gamut.Diagram.planckian_locus(2000..10000//1000)
iex> length(points)
9
iex> d65ish = Enum.find(points, &(&1.kelvin == 6000))
iex> Float.round(d65ish.x, 3)
0.322
@spec spectral_locus( projection(), keyword() ) :: [spectral_point()]
Returns the visible-spectrum locus — the outer curve of the chromaticity diagram — as a list of points.
The list traces monochromatic light from the shortest to the longest wavelength in the CIE 1931 2° observer's CMF table. To close the diagram visually, callers typically add a line segment from the last point back to the first (the "line of purples") when rendering.
Arguments
projectionis:xy(default) or:uv.
Options
:observeris2(default) or10— CIE 1931 2° or CIE 1964 10° standard observer.:stepis the wavelength step in nm to subsample the CMF table by. Default5nm (every point). Use a larger value (e.g.10) for faster rendering at small sizes.
Returns
- A list of maps with
:wavelengthplus the projection's coordinate keys (:x, :yor:u, :v).
Examples
iex> points = Color.Gamut.Diagram.spectral_locus(:xy)
iex> first = hd(points)
iex> first.wavelength
380.0
iex> Float.round(first.x, 4)
0.1741
iex> points = Color.Gamut.Diagram.spectral_locus(:uv)
iex> point = Enum.find(points, &(&1.wavelength == 520.0))
iex> Float.round(point.u, 4)
0.0231
@spec triangle(atom(), projection()) :: triangle()
Returns the primaries and white point of a named RGB working space as chromaticities in the requested projection.
Arguments
working_spaceis a working-space atom (for example:SRGB,:P3_D65,:AdobeRGB/:Adobe,:Rec2020,:ProPhoto).projectionis:xy(default) or:uv.
Returns
- A map with
:red,:green,:blue,:whitekeys, each a%{x, y}or%{u, v}point.
Examples
iex> t = Color.Gamut.Diagram.triangle(:SRGB)
iex> {Float.round(t.red.x, 2), Float.round(t.red.y, 2)}
{0.64, 0.33}
iex> t = Color.Gamut.Diagram.triangle(:P3_D65)
iex> {Float.round(t.green.x, 3), Float.round(t.green.y, 3)}
{0.265, 0.69}
Converts a CIE 1976 (u', v') chromaticity back to CIE 1931
(x, y).
Arguments
{u, v}is a u'v' chromaticity tuple.
Returns
{x, y}— the xy coordinates.
Examples
iex> {x, y} = Color.Gamut.Diagram.uv_to_xy({0.1978, 0.4683})
iex> {Float.round(x, 3), Float.round(y, 3)}
{0.313, 0.329}
Converts a CIE 1931 (x, y) chromaticity to CIE 1976
(u', v').
Arguments
{x, y}is a chromaticity tuple.
Returns
{u, v}— the u'v' coordinates.
Examples
iex> {u, v} = Color.Gamut.Diagram.xy_to_uv({0.3127, 0.3290})
iex> {Float.round(u, 4), Float.round(v, 4)}
{0.1978, 0.4683}