Image.Pixel (image v0.65.0)

Copy Markdown View Source

Bridges the Color library and libvips pixel arguments.

Every libvips operation that takes a color (background, fill, draw, flatten, embed, …) ultimately wants a flat list of numbers in the interpretation, value range, and band layout of the image it is operating on. This module owns that conversion so that callers can pass user-friendly inputs (atoms, hex strings, Color.* structs, numeric lists) without worrying about whether the target image is sRGB, Lab, scRGB, CMYK, or 16-bit.

Example

iex> {:ok, image} = Image.new(2, 2, color: :black)
iex> Image.Pixel.to_pixel(image, :red)
{:ok, [255, 0, 0]}

iex> {:ok, image} = Image.new(2, 2, color: :black)
iex> {:ok, lab_image} = Image.to_colorspace(image, :lab)
iex> {:ok, [l, a, b]} = Image.Pixel.to_pixel(lab_image, :red)
iex> {Float.round(l, 2), Float.round(a, 2), Float.round(b, 2)}
{53.24, 80.09, 67.2}

Summary

Types

t()

Anything that to_pixel/3 knows how to turn into a pixel.

A transparency value.

Functions

A defguard that loosely matches things that look like a pixel input.

The maximum opacity value (255).

The minimum opacity value (0).

Converts a color to a pixel matching the interpretation and band layout of image.

Same as to_pixel/3, but raises on error.

Resolves a color input to an sRGB pixel [r, g, b] (or [r, g, b, a]) with channels in 0..255, regardless of any image context.

Same as to_srgb/1, but raises on error.

Returns a transparency value in 0..255 where 0 is transparent and 255 is opaque.

Types

t()

@type t() :: struct() | [number()] | String.t() | atom()

Anything that to_pixel/3 knows how to turn into a pixel.

This includes any input accepted by Color.new/2 (a Color.* struct, a numeric list of length 3..5, a hex string, a CSS named color string or atom), plus the Image-specific transparency aliases :none, :transparent, and :opaque.

transparency()

@type transparency() :: :none | :transparent | :opaque | 0..255 | float()

A transparency value.

  • :none and :transparent are equivalent to 0 (fully transparent).
  • :opaque is equivalent to 255 (fully opaque).
  • An integer in 0..255 is used as-is.
  • A float in 0.0..1.0 is scaled to 0..255.

Functions

is_pixel(value)

(macro)

A defguard that loosely matches things that look like a pixel input.

This is intentionally permissive — it accepts anything that might be a color (struct, numeric list, atom that isn't a boolean, binary). Actual validation happens in to_pixel/3.

Use this in function-head guards where you need to dispatch a color argument away from an image argument (the Image.if_then_else/4 pattern).

max_opacity()

@spec max_opacity() :: 255

The maximum opacity value (255).

min_opacity()

@spec min_opacity() :: 0

The minimum opacity value (0).

to_pixel(image, color, options \\ [])

@spec to_pixel(
  image :: Vix.Vips.Image.t() | Vix.Vips.MutableImage.t(),
  color :: t(),
  options :: Keyword.t()
) :: {:ok, [number()]} | {:error, String.t()}

Converts a color to a pixel matching the interpretation and band layout of image.

Arguments

  • image is the target Vix.Vips.Image.t/0. Its interpretation and band count determine the output shape and value range.

  • color is anything Color.new/2 accepts: a Color.* struct, a list of 3/4/5 numbers, a hex string ("#ff0000", "#f80", "#ff000080"), a CSS named color ("rebeccapurple", :misty_rose), or one of Image's transparency aliases (:none, :transparent, :opaque).

  • options is a keyword list — see below.

Options

  • :alpha — if the target image has an alpha band, force this transparency. Accepts any value transparency/1 accepts. If unset, the input color's own alpha is used (or full opacity if none).

  • :intent — passed through to Color.convert/3. One of :relative_colorimetric (default), :absolute_colorimetric, :perceptual, or :saturation.

Returns

  • {:ok, [number(), ...]} — a flat list of numbers in the band order and pixel range that the image's interpretation expects.

  • {:error, reason}.

Notes

  • For 8-bit interpretations (:srgb, :rgb, :cmyk, :hsv, :bw) the output is integers in 0..255.

  • For 16-bit interpretations (:rgb16, :grey16) the output is integers in 0..65535.

  • For float interpretations (:scrgb, :lab, :lch, etc.) the output is floats in the natural range of that space.

  • The output band count matches Vix.Vips.Image.bands/1 exactly. Alpha is appended when the image has an alpha band, and stripped when it does not.

  • 1-band (:bw, :grey16) images receive a single luminance channel computed from the perceptually-uniform Color.Lab L*.

Examples

iex> {:ok, image} = Image.new(2, 2, color: :black)
iex> Image.Pixel.to_pixel(image, :red)
{:ok, [255, 0, 0]}

iex> {:ok, image} = Image.new(2, 2, color: [0, 0, 0, 255])
iex> Image.Pixel.to_pixel(image, :red)
{:ok, [255, 0, 0, 255]}

iex> {:ok, image} = Image.new(2, 2, color: [0, 0, 0, 255])
iex> Image.Pixel.to_pixel(image, :red, alpha: 0.5)
{:ok, [255, 0, 0, 128]}

iex> {:ok, image} = Image.new(2, 2, color: :black)
iex> Image.Pixel.to_pixel(image, "#ff000080")
{:ok, [255, 0, 0]}

to_pixel!(image, color, options \\ [])

@spec to_pixel!(image :: Vix.Vips.Image.t(), color :: t(), options :: Keyword.t()) ::
  [number()]

Same as to_pixel/3, but raises on error.

to_srgb(color)

@spec to_srgb(color :: t()) :: {:ok, [0..255]} | {:error, Image.Error.t() | term()}

Resolves a color input to an sRGB pixel [r, g, b] (or [r, g, b, a]) with channels in 0..255, regardless of any image context.

Use this for callers that need sRGB output specifically — for example SVG renderers — rather than the interpretation of an image. For image-aware encoding use to_pixel/3.

Arguments

  • color is anything Color.new/2 accepts, plus the transparency aliases.

Returns

  • {:ok, [0..255, 0..255, 0..255]} or {:ok, [0..255, 0..255, 0..255, 0..255]} if the source had an alpha channel.

  • {:error, reason}.

Examples

iex> Image.Pixel.to_srgb(:red)
{:ok, [255, 0, 0]}

iex> Image.Pixel.to_srgb("#ff000080")
{:ok, [255, 0, 0, 128]}

iex> Image.Pixel.to_srgb(%Color.Lab{l: 53.24, a: 80.09, b: 67.20})
{:ok, [255, 0, 0]}

to_srgb!(color)

@spec to_srgb!(color :: t()) :: [0..255]

Same as to_srgb/1, but raises on error.

transparency(int)

@spec transparency(value :: transparency()) ::
  {:ok, 0..255} | {:error, Image.Error.t()}

Returns a transparency value in 0..255 where 0 is transparent and 255 is opaque.

Arguments

  • transparency is one of:
    • The atoms :none, :transparent, or :opaque.

    • An integer in 0..255.

    • A float in 0.0..1.0.

Returns

  • {:ok, 0..255} or

  • {:error, reason}.

Examples

iex> Image.Pixel.transparency(:opaque)
{:ok, 255}

iex> Image.Pixel.transparency(:transparent)
{:ok, 0}

iex> Image.Pixel.transparency(0.5)
{:ok, 128}

iex> Image.Pixel.transparency(200)
{:ok, 200}