asciinator
What it is
Section titled “What it is”asciinator is a small Python tool that converts images into ANSI-colored terminal art. It exposes three rendering modes and a 24-bit color path, all sharing the same core “rasterize image, quantize to per-cell color, emit ANSI” pipeline:
halfblock(default) — uses the Unicode upper-half-block glyph (▀, U+2580) with 24-bit foreground and background color, packing two image rows into every terminal line. This doubles vertical resolution compared to one-cell-per-pixel approaches and is the right answer for almost every “show me an image in the terminal” use case.shade— uses Unicode shade-density glyphs (█▓▒░) with 24-bit foreground color. Useful when only one color per cell is acceptable (e.g., over a non-true-color fallback path) or for a chunkier aesthetic.ascii— classic ramp@%#*+=-:.with 24-bit foreground color. Pure-ASCII fallback or deliberate retro look.
Key takeaways for KN-86
Section titled “Key takeaways for KN-86”- Halfblock with
▀+ fg/bg is the canonical “image in the terminal” technique. Any time KN-86 needs to render imagery — a splash bitmap, a cart’s title-card art, a faction sigil, an album-cover-equivalent for a music cart — the halfblock pipeline is the right call. It’s well-understood and has decades of “raster.bel”-style prior art in the demo scene. - Three modes map naturally onto KN-86’s aesthetic-mode story. On a monochrome amber device the
shademode (single fg color, density-based dithering) is the only one that renders correctly; the halfblock and ascii modes both assume per-cell color delta and degrade on a mono display. So the right framing for KN-86: shipshade-style rendering by default (using intensity-mapped block density against the amber palette), documenthalfblockas the desktop-emulator-only path, and treatasciias a stylistic option. - Document the technique in NoshAPI. A
(draw-image path :mode 'shade)primitive (or its FFI equivalent — see ADR-0005 for the surface conventions) lets cart authors include real raster art without each cart hand-rolling the pixel-to-cell conversion. - Tooling vs. runtime. asciinator itself is a Python CLI — KN-86 isn’t going to embed a Python interpreter. The value here is the technique, not the library. The 30-line core of “load image, resample to (cols × rows×2), pick fg=top-row color and bg=bottom-row color, emit
\e[38;2;…;48;2;…m▀” is the reference algorithm; a C or Lisp implementation behind NoshAPI is straightforward.
Pending. The PyPI page itself doesn’t carry a clean example output worth embedding here. (Optional follow-up: run asciinator locally against a small reference image (the KN-86 logo or a CIPHER glyph) and save the terminal output as a PNG to use as the reference image.)
- The SVG extra (
asciinator[svg]) handles vector input. Useful if KN-86 cart authors author imagery as SVG (clean lines, clean color regions, no resampling artifacts) and the runtime rasterizes at cart-load time. - For per-frame video / animation rendering, asciinator-style halfblock output is also how
chafa,imgcat, and the Kitty/iTerm/Sixel graphics protocols work conceptually. The Kitty protocol gives true-pixel rendering when the terminal supports it (and the l123 entry notes thatratatui-imagealready integrates Kitty/iTerm/Sixel for graphs). KN-86 likely doesn’t need this path — the framebuffer is the display, not a terminal escape sequence target — but the technique is worth knowing as a fallback. - The 24-bit color emit format is ANSI standard:
\e[38;2;R;G;Bmfor foreground,\e[48;2;R;G;Bmfor background. Both Bubble Tea / Lip Gloss and termbox2 handle this transparently; cart authors never need to write the raw escape themselves.