feat(tui): image rendering — chafa backend + half-block fallback #56

Merged
charles merged 1 commit from tui/chafa-14 into main 2026-04-11 20:42:08 +00:00
Owner

Summary

Adds the two "works anywhere" image backends so Phase 2 has a guaranteed terminal fallback. Stacks on #55. Closes charles/loom#14.

What's in

  • image::chafa::ChafaRenderer — shells out to chafa --format=symbols --size=WxH --colors={256|full} (full under $COLORTERM=truecolor|24bit) and prints the output at the rect. ChafaRenderer::detect() returns Err(ChafaNotFound) when the binary isn't on $PATH, so #15 can fall through
  • image::chafa::HalfBlockRenderer — pure-Rust fallback decoding the input via the image crate and emitting glyphs with 24-bit ANSI fg/bg sampled from pairs of vertical pixels. Always available
  • render_halfblocks — pure function exposed for tests; takes PNG bytes and target cell dimensions, returns a ready-to-print ANSI block
  • Shared print_block_at helper that cursors to each target row before emitting a line

Tests (2 new, 53 total)

  • halfblocks_produce_deterministic_output_for_fixed_fixture — same input twice → same output, contains and \x1b[0m
  • chafa_detect_returns_not_found_with_empty_path — with $PATH cleared, ChafaRenderer::detect() errors out. Uses unsafe { std::env::set_var } with restore to play nicely with the global env
## Summary Adds the two "works anywhere" image backends so Phase 2 has a guaranteed terminal fallback. Stacks on #55. Closes charles/loom#14. ## What's in - **`image::chafa::ChafaRenderer`** — shells out to `chafa --format=symbols --size=WxH --colors={256|full}` (full under `$COLORTERM=truecolor|24bit`) and prints the output at the rect. `ChafaRenderer::detect()` returns `Err(ChafaNotFound)` when the binary isn't on `$PATH`, so `#15` can fall through - **`image::chafa::HalfBlockRenderer`** — pure-Rust fallback decoding the input via the `image` crate and emitting `▀` glyphs with 24-bit ANSI fg/bg sampled from pairs of vertical pixels. Always available - **`render_halfblocks`** — pure function exposed for tests; takes PNG bytes and target cell dimensions, returns a ready-to-print ANSI block - Shared `print_block_at` helper that cursors to each target row before emitting a line ## Tests (2 new, 53 total) - `halfblocks_produce_deterministic_output_for_fixed_fixture` — same input twice → same output, contains `▀` and `\x1b[0m` - `chafa_detect_returns_not_found_with_empty_path` — with `$PATH` cleared, `ChafaRenderer::detect()` errors out. Uses `unsafe { std::env::set_var }` with restore to play nicely with the global env
Adds the two "always available" image backends called for by spec §2.2:

- image::chafa::ChafaRenderer — shells out to the chafa binary with
  --format=symbols --size=WxH --colors={256|full depending on COLORTERM}
  and prints the resulting ANSI/UTF-8 block at the target rect.
  Returns ChafaNotFound when the binary isn't on PATH so auto-detect
  can fall through
- image::chafa::HalfBlockRenderer — pure-Rust fallback using U+2580
  half-blocks with 24-bit ANSI fg/bg derived from image-crate pixel
  sampling. Always available, always deterministic

Both share the same print_block_at helper that walks a pre-formatted
block of text lines and cursors to each target row before emitting.

Closes charles/loom#14

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
charles changed target branch from tui/kitty-12 to main 2026-04-11 20:42:02 +00:00
charles deleted branch tui/chafa-14 2026-04-11 20:42:09 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/loom!56
No description provided.