class

PNGGIF::PNG

Inherits Reference < Object

Decodes a PNG / APNG / GIF (or, via ImageMagick, JPEG/other) image into:

  • #bmp — the full-resolution RGBA bitmap of the first frame
  • #cellmapbmp downscaled to terminal-cell resolution (built lazily)
  • #frames — animation frames (APNG / animated GIF), or nil if 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

from_frames(frames : Array(Tuple(Bitmap, Int32)), canvas_width : Int32, canvas_height : Int32, num_plays : Int32 = 0) : PNG

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).

Source
new(file : String | Bytes, scale : Float64 = 1.0, cell_width : Int32 | Nil = nil, cell_height : Int32 | Nil = nil, ascii : Bool = false, speed : Float64 = 1.0, cell_aspect : Float64 = 2.0)

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.

Source

Instance methods

animation_cellmaps(cmwidth : Int32 | Nil = @cell_width, cmheight : Int32 | Nil = @cell_height, scale : Float64 = @scale) : Array(Tuple(Bitmap, Int32)) | Nil

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.

Source
ascii=(ascii : Bool)
Source
ascii?
Source
bit_depth
Source
bmp?
Source
canvas_height
Source
canvas_width

Full canvas dimensions (IHDR / GIF logical screen), which stay fixed even while individual frames declare smaller sub-rectangles.

Source
cell_aspect

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).

Source
cell_aspect=(cell_aspect : Float64)

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).

Source
cell_height
Source
cell_height=(cell_height : Int32 | Nil)
Source
cell_width
Source
cell_width=(cell_width : Int32 | Nil)
Source
cellmap

#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.

Source
color_type
Source
create_cellmap(bmp : Bitmap, cmwidth : Int32 | Nil = @cell_width, cmheight : Int32 | Nil = @cell_height, scale : Float64 = @scale, cell_aspect : Float64 = @cell_aspect, into : Bitmap | Nil = nil) : Bitmap

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.

Source
frames
Source
height
Source
num_plays
Source
scale

Rendering knobs forwarded from the consumer.

Source
scale=(scale : Float64)

Rendering knobs forwarded from the consumer.

Source
speed
Source
speed=(speed : Float64)
Source
width
Source