Image.Color (image v0.67.0-dev)

Copy Markdown View Source

Vectorised colour-space conversions for Nx tensors of pixel rows.

Per-pixel conversion via Color.convert/2 is correct but slow when there are tens of thousands of pixels in flight (e.g. palette extraction from an image). The helpers in this module do the same conversions as a single tensor op so the cost is O(matmul + element-wise) rather than O(n × Elixir-call).

All functions in this module require Nx. They are not compiled if Nx is not loaded.

Summary

Functions

Converts a tensor of sRGB pixel rows to an Oklab tensor.

Functions

srgb_tensor_to_oklab(tensor)

@spec srgb_tensor_to_oklab(Nx.Tensor.t()) :: Nx.Tensor.t()

Converts a tensor of sRGB pixel rows to an Oklab tensor.

Input values are interpreted as 8-bit sRGB (0–255) when the tensor type is integer; as unit-range linear sRGB (0.0–1.0) is not assumed — even float tensors are treated as gamma-encoded sRGB on the [0, 1] scale, matching what Image.to_nx/2 returns when the source image is in the sRGB colourspace.

The pipeline is the standard one:

sRGB  linear-sRGB  XYZ (D65)  LMS    LMS'  Oklab

All of it is expressed as Nx tensor ops so a 90 000-row input is one matmul-heavy pass rather than 90 000 Elixir function calls.

Arguments

  • tensor is an Nx.Tensor.t/0 of shape {n, 3} (alpha bands must be stripped before calling — alpha is a property of the source image, not of the colour conversion).

Returns

  • An Nx.Tensor.t/0 of shape {n, 3}, type f32, where column 0 is L, column 1 is a, and column 2 is b.

Examples

iex> rgb = Nx.tensor([[255, 0, 0], [0, 255, 0], [0, 0, 255]], type: :u8)
iex> oklab = Image.Color.srgb_tensor_to_oklab(rgb)
iex> Nx.shape(oklab)
{3, 3}