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
@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' → OklabAll 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
tensoris anNx.Tensor.t/0of 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/0of shape{n, 3}, typef32, where column0isL, column1isa, and column2isb.
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}