Pure Elixir PNG decoder and generator for terminal image rendering.
Decoder
Supports PNG (grayscale, RGB, RGBA, indexed) and resizes pixel data
to a target dimension. Non-PNG formats fall back to ImageMagick's
convert command (via Trebejo.Image).
Generator
Produces minimal PNG binaries from raw pixel data — both RGB and RGBA variants. Used by the Kitty and iTerm2 rendering protocols.
Usage
{:ok, {w, h, pixels}} = Alaja.ImageRenderer.PNG.decode("image.png")
png_bin = Alaja.ImageRenderer.PNG.generate_rgb(pixels, 100, 100)
Summary
Functions
Reads and decodes a PNG file. Returns {:ok, {width, height, pixels}}
where pixels is a flat list of {r, g, b} tuples, or an error tuple.
Reads, decodes, and resizes a PNG file.
Generates an RGB PNG binary from pixel data.
Generates an RGBA PNG binary from pixel data (with alpha channel).
Functions
@spec decode(String.t()) :: {:ok, {pos_integer(), pos_integer(), [{0..255, 0..255, 0..255}]}} | :not_png | {:error, String.t()}
Reads and decodes a PNG file. Returns {:ok, {width, height, pixels}}
where pixels is a flat list of {r, g, b} tuples, or an error tuple.
For non-PNG formats, returns :not_png so callers can attempt a
fallback decode via ImageMagick.
@spec decode_and_resize(String.t(), pos_integer(), pos_integer()) :: {:ok, [[{0..255, 0..255, 0..255}]]} | {:error, String.t()}
Reads, decodes, and resizes a PNG file.
When target_h is 0, the height is derived from the aspect ratio
(accounting for terminal cells being roughly 2:1 tall).
@spec generate_rgb([[{0..255, 0..255, 0..255}]], pos_integer(), pos_integer()) :: binary()
Generates an RGB PNG binary from pixel data.
@spec generate_rgba( [[{0..255, 0..255, 0..255, 0..255}]], pos_integer(), pos_integer() ) :: binary()
Generates an RGBA PNG binary from pixel data (with alpha channel).