Color.SRGB (Color v0.4.0)

Copy Markdown

sRGB color space, using the Lindbloom sRGB working space (primaries from IEC 61966-2-1, D65 reference white) and the sRGB companding function.

Channels r, g and b are unit floats in the nominal range [0, 1]. The legacy 0..255 convention is not used — convert with scale255/1 / unscale255/1 if you need 8-bit values.

Summary

Functions

Converts a CIE XYZ color to sRGB.

Parses a CSS hex color or CSS named color into an sRGB struct.

Scales unit-range sRGB channels to the conventional 0..255 byte range.

Formats an sRGB color as a CSS hex string.

Converts an sRGB color to a CIE XYZ color.

Builds an sRGB struct from 0..255 byte channels.

Types

t()

@type t() :: %Color.SRGB{
  alpha: number() | nil,
  b: number() | nil,
  g: number() | nil,
  r: number() | nil
}

Functions

from_xyz(xyz)

@spec from_xyz(Color.XYZ.t()) :: {:ok, t()}

Converts a CIE XYZ color to sRGB.

This assumes the xyz is already in the sRGB working space's reference white (D65/2°). If your XYZ is under a different illuminant, adapt it with Color.ChromaticAdaptation first.

Arguments

  • xyz is a Color.XYZ struct on the Y ∈ [0, 1] scale.

Returns

Examples

iex> xyz = %Color.XYZ{x: 0.95047, y: 1.0, z: 1.08883, illuminant: :D65, observer_angle: 2}
iex> {:ok, srgb} = Color.SRGB.from_xyz(xyz)
iex> {Float.round(srgb.r, 4), Float.round(srgb.g, 4), Float.round(srgb.b, 4)}
{1.0, 1.0, 1.0}

parse(string)

Parses a CSS hex color or CSS named color into an sRGB struct.

Accepts any of the CSS Color Module Level 4 hex forms:

  • #RGB — 4-bit-per-channel shorthand (e.g. #f80).

  • #RGBA — shorthand with alpha.

  • #RRGGBB — 8-bit per channel.

  • #RRGGBBAA — 8-bit per channel with alpha.

The leading # is optional. Parsing is case-insensitive. Any other string is looked up in Color.CSS.Names, so named colors like "rebeccapurple" also work.

Arguments

  • input is a string.

Returns

  • {:ok, %Color.SRGB{}} with unit-range channels.

  • {:error, reason} if the input can't be parsed.

Examples

iex> {:ok, red} = Color.SRGB.parse("#ff0000")
iex> {red.r, red.g, red.b}
{1.0, 0.0, 0.0}

iex> {:ok, c} = Color.SRGB.parse("#f80")
iex> {c.r, c.g, c.b}
{1.0, 0.5333333333333333, 0.0}

iex> {:ok, c} = Color.SRGB.parse("rebeccapurple")
iex> {c.r, c.g, c.b}
{0.4, 0.2, 0.6}

iex> {:ok, c} = Color.SRGB.parse("#ff000080")
iex> {c.r, c.g, c.b, Float.round(c.alpha, 4)}
{1.0, 0.0, 0.0, 0.502}

scale255(srgb)

Scales unit-range sRGB channels to the conventional 0..255 byte range.

Arguments

  • srgb is a Color.SRGB struct with unit-range channels.

Returns

  • A {r, g, b} tuple of floats in [0, 255].

Examples

iex> Color.SRGB.scale255(%Color.SRGB{r: 1.0, g: 0.5, b: 0.0})
{255.0, 127.5, 0.0}

to_hex(srgb)

Formats an sRGB color as a CSS hex string.

Channels are clamped to [0, 1] and rounded to 8 bits. If the alpha channel is nil or 1.0, a six-digit #RRGGBB is produced. Otherwise an eight-digit #RRGGBBAA is produced.

Arguments

Returns

  • A lowercase hex string starting with #.

Examples

iex> Color.SRGB.to_hex(%Color.SRGB{r: 1.0, g: 0.0, b: 0.0})
"#ff0000"

iex> Color.SRGB.to_hex(%Color.SRGB{r: 1.0, g: 0.5333333, b: 0.0})
"#ff8800"

iex> Color.SRGB.to_hex(%Color.SRGB{r: 1.0, g: 0.0, b: 0.0, alpha: 0.5})
"#ff000080"

to_xyz(srgb)

@spec to_xyz(t()) :: {:ok, Color.XYZ.t()}

Converts an sRGB color to a CIE XYZ color.

Arguments

  • srgb is a Color.SRGB struct with unit-range channels.

Returns

  • A Color.XYZ struct tagged with the sRGB working space illuminant (:D65, 2° observer). Y ∈ [0, 1].

Examples

iex> {:ok, xyz} = Color.SRGB.to_xyz(%Color.SRGB{r: 1.0, g: 1.0, b: 1.0})
iex> {Float.round(xyz.x, 4), Float.round(xyz.y, 4), Float.round(xyz.z, 4)}
{0.9505, 1.0, 1.0888}

unscale255(arg, alpha \\ nil)

Builds an sRGB struct from 0..255 byte channels.

Arguments

  • rgb is an {r, g, b} tuple of numbers in [0, 255].

  • alpha is an optional alpha value, defaults to nil.

Returns

Examples

iex> Color.SRGB.unscale255({255, 0, 0})
%Color.SRGB{r: 1.0, g: 0.0, b: 0.0, alpha: nil}