pnggif
pnggif
Pure-Crystal PNG / APNG / GIF reader.
It decodes an image file (or in-memory buffer) into RGBA bitmaps and, optionally, a downscaled terminal-cell map suitable for solid-block rendering in a TUI (one cell per sampled pixel, the cell background set to the pixel color).
Ported from Blessed's bundled tng.js (MIT).
Features
- PNG: all color types (grayscale, RGB, palette, gray+alpha, RGBA), bit depths 1–16, all scanline filters, Adam7 interlacing, palette transparency. Decompression uses Crystal's stdlib
Compress::Zlib. - APNG: animation frames with dispose/blend compositing.
- GIF (87a/89a): ported LZW decoder, interlacing, transparency, NETSCAPE loop counts, multi-frame animation.
- JPEG / other: converted to PNG via ImageMagick
convertwhen available. - Cellmaps: nearest-neighbour downscaling with non-square-cell aspect correction (
cell_aspect, default2.0) so images don't look stretched.
Usage
require "pnggif"
img = PNGGIF::PNG.new("picture.png", cell_width: 40)
img.width # => image pixel width
img.height # => image pixel height
img.bmp # => Array(Array(PNGGIF::Pixel)), full-resolution RGBA
img.cellmap # => downscaled bitmap, one PNGGIF::Pixel per terminal cell
img.frames # => Array(PNGGIF::Frame)? for animations, else nil
# Pre-composited animation frames ({cellmap, delay_ms}):
if frames = img.animation_cellmaps(40)
frames.each { |cellmap, delay_ms| ... }
end
Each PNGGIF::Pixel has r, g, b, a channels (0–255).
License
AGPLv3
Repository
pnggif
Owner
Statistic
- 1
- 0
- 0
- 1
- 0
- about 7 hours ago
- June 20, 2026
License
Links
Synced at
Sat, 20 Jun 2026 15:41:10 GMT
Languages