Color.Conversion.Oklab (Color v0.9.0)

Copy Markdown

Pure math for the Oklab perceptual color space, published by Björn Ottosson in 2020 (https://bottosson.github.io/posts/oklab/).

Oklab is defined relative to CIE XYZ under the D65 reference white with Y on the [0, 1] scale. If you have an XYZ tagged with a different illuminant, chromatically adapt it to D65 before using these functions — they do not adapt automatically.

Note that Ottosson's published matrices use an implicit D65 of approximately (0.9505, 1.0, 1.0883) — the Z component differs from Lindbloom's published D65 (1.08883) by about 5 × 10⁻⁴. This is intrinsic to the Oklab matrices and not a numerical bug. Round-tripping an XYZ through Oklab and back preserves the value to roughly 1 × 10⁻⁷.

The pipeline is:

XYZ M1 LMS  LMS' M2 Oklab

with M1 the D65 Hunt-Pointer-Estevez-like matrix and M2 the final linear projection. The functions here are the inverse of each other to double precision.

Summary

Functions

Converts Oklab {L, a, b} to cylindrical Oklch {L, C, h}.

Converts an Oklab {L, a, b} triple to CIE XYZ (D65, Y ∈ [0, 1]).

Converts cylindrical Oklch {L, C, h} to Oklab {L, a, b}.

Converts a CIE XYZ triple (D65, Y ∈ [0, 1]) to an Oklab {L, a, b}.

Functions

oklab_to_oklch(arg)

Converts Oklab {L, a, b} to cylindrical Oklch {L, C, h}.

The hue h is returned in degrees in the range [0, 360).

Arguments

  • oklab is an {L, a, b} tuple.

Returns

  • An {L, C, h} tuple.

Examples

iex> Color.Conversion.Oklab.oklab_to_oklch({0.5, 0.0, 0.0})
{0.5, 0.0, 0.0}

oklab_to_xyz(oklab)

Converts an Oklab {L, a, b} triple to CIE XYZ (D65, Y ∈ [0, 1]).

Arguments

  • oklab is an {L, a, b} tuple.

Returns

  • An {X, Y, Z} tuple.

Examples

iex> {x, y, z} = Color.Conversion.Oklab.oklab_to_xyz({1.0, 0.0, 0.0})
iex> {Float.round(x, 4), Float.round(y, 4), Float.round(z, 4)}
{0.9505, 1.0, 1.0883}

oklch_to_oklab(arg)

Converts cylindrical Oklch {L, C, h} to Oklab {L, a, b}.

Arguments

  • oklch is an {L, C, h} tuple where h is in degrees.

Returns

  • An {L, a, b} tuple.

Examples

iex> Color.Conversion.Oklab.oklch_to_oklab({0.5, 0.0, 0.0})
{0.5, 0.0, 0.0}

xyz_to_oklab(xyz)

Converts a CIE XYZ triple (D65, Y ∈ [0, 1]) to an Oklab {L, a, b}.

Arguments

  • xyz is an {X, Y, Z} tuple relative to the D65 reference white.

Returns

  • An {l, a, b} tuple where L is perceptual lightness (0 for black, 1 for the reference white) and a/b are green-red / blue-yellow opponent axes.

Examples

iex> {l, a, b} = Color.Conversion.Oklab.xyz_to_oklab({0.95047, 1.0, 1.08883})
iex> {Float.round(l, 3), abs(a) < 1.0e-4, abs(b) < 1.0e-4}
{1.0, true, true}