tui: image rendering — Kitty Graphics Protocol backend #12

Closed
opened 2026-04-11 13:01:00 +00:00 by charles · 0 comments
Owner

User story

As a user running loom-tui inside a Kitty-compatible terminal, I want images (gallery thumbnails, model previews, generate preview) displayed inline at native resolution, so that the TUI looks as informative as the GTK app.

Acceptance criteria

ImageRenderer trait

  • loom_tui::image::ImageRenderer trait defined with render(&self, image: &[u8], rect: Rect, frame: &mut Frame) -> RenderHandle, delete(&self, handle: RenderHandle), protocol_name(&self) -> &'static str
  • RenderHandle is an opaque type carrying enough info to delete or replace a previously-rendered image

Kitty protocol

  • Transmits RGBA or PNG using a=T, chunked at 4096 bytes of base64 per chunk (m=1/m=0)
  • Supports f=32 (RGBA) and f=100 (PNG) payload formats; chooses PNG for files already PNG to skip redecoding
  • Uses virtual placement (U=1, C=1) so images move with ratatui reflow
  • Deletes stale images via a=d,d=A before re-rendering a cell region
  • Caches image IDs (u32) keyed by hash of (path_or_bytes, width_cells, height_cells) to avoid redundant transmissions within a session
  • Handles image decode/scale on a background tokio task; main loop receives the ready-to-transmit payload via mpsc

Integration

  • Provides a KittyRenderer struct implementing ImageRenderer
  • image crate used for decoding/scaling
  • Unit tests cover: chunk boundary calculation, base64 payload framing, cache hit on identical input

Out of scope

  • Sixel backend (separate ticket)
  • Chafa / block-art fallback (separate ticket)
  • Auto-detection of best protocol (separate ticket)
  • Actually wiring images into gallery / model browser screens (those tickets consume this trait)

References

## User story As a user running loom-tui inside a Kitty-compatible terminal, I want images (gallery thumbnails, model previews, generate preview) displayed inline at native resolution, so that the TUI looks as informative as the GTK app. ## Acceptance criteria ### ImageRenderer trait - [ ] `loom_tui::image::ImageRenderer` trait defined with `render(&self, image: &[u8], rect: Rect, frame: &mut Frame) -> RenderHandle`, `delete(&self, handle: RenderHandle)`, `protocol_name(&self) -> &'static str` - [ ] `RenderHandle` is an opaque type carrying enough info to delete or replace a previously-rendered image ### Kitty protocol - [ ] Transmits RGBA or PNG using `a=T`, chunked at 4096 bytes of base64 per chunk (`m=1`/`m=0`) - [ ] Supports `f=32` (RGBA) and `f=100` (PNG) payload formats; chooses PNG for files already PNG to skip redecoding - [ ] Uses virtual placement (`U=1`, `C=1`) so images move with ratatui reflow - [ ] Deletes stale images via `a=d,d=A` before re-rendering a cell region - [ ] Caches image IDs (`u32`) keyed by hash of `(path_or_bytes, width_cells, height_cells)` to avoid redundant transmissions within a session - [ ] Handles image decode/scale on a background tokio task; main loop receives the ready-to-transmit payload via `mpsc` ### Integration - [ ] Provides a `KittyRenderer` struct implementing `ImageRenderer` - [ ] `image` crate used for decoding/scaling - [ ] Unit tests cover: chunk boundary calculation, base64 payload framing, cache hit on identical input ## Out of scope - Sixel backend (separate ticket) - Chafa / block-art fallback (separate ticket) - Auto-detection of best protocol (separate ticket) - Actually wiring images into gallery / model browser screens (those tickets consume this trait) ## References - Spec §2.2 "Image Rendering Subsystem" - Kitty Graphics Protocol: https://sw.kovidgoyal.net/kitty/graphics-protocol/
charles added this to the loom-tui v0.1.0 milestone 2026-04-11 13:01:00 +00:00
Sign in to join this conversation.
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#12
No description provided.