PNGGIF::PNG
Decodes a PNG / APNG / GIF (or, via ImageMagick, JPEG/other) image into:
#bmp— the full-resolution RGBA bitmap of the first frame#cellmap—bmpdownscaled to terminal-cell resolution (built lazily)#frames— animation frames (APNG / animated GIF), ornilif static
The cellmap is for solid-block terminal rendering (one cell per sampled
pixel, cell background = pixel color). A character cell is typically ~2x
taller than wide, so the missing cellmap dimension is derived using
cell_aspect (default 2.0) to keep proportions correct. Output is full
24-bit RGB; consumers pick their own color-reduction if needed.
Constructors
Builds an animated PNG directly from already-decoded, full-canvas
frames ({bitmap, delay_ms}), bypassing file parsing. Each frame is
treated as a full, independent canvas image (blend_op = source, no
disposal). num_plays is the loop count (0 = loop forever).
Decodes file (a path) or a raw Bytes buffer. cell_width/cell_height
constrain the cellmap to a terminal box; scale is used when neither is
given. cell_aspect corrects for non-square cells (see #cell_aspect).
ascii renders glyphs by luminance; speed scales frame delays.
Instance methods
Composites every animation frame onto a full-size canvas (honouring APNG /
GIF dispose + blend semantics) and returns the per-frame {cellmap, delay}
ready for playback. Returns nil for a static image. Ported from tng.js's
renderFrame / compileFrames.
Full canvas dimensions (IHDR / GIF logical screen), which stay fixed even while individual frames declare smaller sub-rectangles.
Terminal cell height-to-width ratio, used to correct aspect when only one
of cell_width/cell_height is fixed (or when scaling). ~2.0 for typical
monospace cells. Set to 1.0 to disable the correction (square cells).
Terminal cell height-to-width ratio, used to correct aspect when only one
of cell_width/cell_height is fixed (or when scaling). ~2.0 for typical
monospace cells. Set to 1.0 to disable the correction (square cells).
#bmp downscaled to terminal-cell resolution, using the rendering knobs
(cell_width/cell_height/scale/cell_aspect) as they stand on the
first read. Built on demand and then memoized: most consumers resample
explicitly via #create_cellmap / #animation_cellmaps and never touch
this, so computing it at construction meant a full nearest-neighbour
resample (and a w × h/2 bitmap allocation) that was immediately garbage
on every decode. Mutating a knob after the first read does not invalidate
the memo.
Downscales bmp to terminal-cell resolution by nearest-neighbour
sampling. Honours cmwidth/cmheight if given, else scale (all
defaulting to the values supplied at construction).
When only one dimension is fixed (or neither), the other is derived from
the image's pixel aspect ratio and corrected by cell_aspect so the
result isn't vertically stretched on non-square cells (terminal cells are
~2x taller than wide). When both cmwidth and cmheight are given, they
are used verbatim.
into is an optional reusable destination: it is resized in place to the target dimensions and every cell overwritten, so a caller re-sampling every animation frame allocates nothing once the buffer is warm. The caller owns the buffer — the returned Bitmap is into, valid only until the caller reuses it. Empty inputs still return a fresh empty Bitmap so an into buffer is never truncated by a degenerate call.