Skip to content

perf(images): render iTerm2 inline images in one sequence - #14

Open
paviro wants to merge 1 commit into
mainfrom
worktree-iterm2-inline-fast
Open

perf(images): render iTerm2 inline images in one sequence#14
paviro wants to merge 1 commit into
mainfrom
worktree-iterm2-inline-fast

Conversation

@paviro

@paviro paviro commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Problem

Images render slowly in iTerm2. The cause is not protocol selection — the graphics backend already forces ProtocolType::Iterm2 in iTerm2. It's the encoding: images were built with ratatui-image's SlicedProtocol, which for the iTerm2 protocol slices the image into one PNG + one OSC 1337 inline-image sequence per terminal row. A ~50-row fullscreen image emits dozens of PNG encodes and inline-image sequences for the terminal to decode and place.

Slicing only matters when an image scrolls partially in and out of view. The fullscreen image viewer never scrolls an image, so the slicing was pure overhead — paid only for SignedPosition-based centering, which the plain Image widget does just as well.

Change

Switch the graphics path from SlicedProtocol/SlicedImage to the non-sliced Protocol/Image widget across graphics.rs, worker.rs, and mod.rs:

  • iTerm2 now emits a single whole-image OSC 1337 sequence.
  • Kitty and Sixel keep their single transmission / single DCS.
  • Centering is done by rendering Image::new(&proto) into a centered sub-Rect.

The color-managed decode pipeline (EXIF, ICC→sRGB, viewport downscale cap), background worker builds, and cache are unchanged.

Verification

  • cargo build clean, no warnings.
  • cargo test --lib tui::image passes (7 tests).
  • Manual check in iTerm2: open an entry's image in the fullscreen viewer — appears near-instantly; ←/→ nav and resize paint promptly, centered/letterboxed. Optionally capture output under a pty and confirm exactly one ESC ]1337;File=inline=1 per image instead of one per row.

The graphics backend built images with ratatui-image's SlicedProtocol.
For the iTerm2 protocol that slices the image into one PNG plus one OSC
1337 inline-image sequence per terminal row, so a fullscreen image emits
dozens of encodes and sequences for the terminal to decode and place,
which iTerm2 renders slowly.

Slicing only matters for images that scroll partially in and out of view.
The fullscreen viewer never scrolls an image, so switch to the non-sliced
Protocol/Image widget: iTerm2 now gets a single whole-image OSC 1337,
Kitty and Sixel keep their single transmission. The color-managed decode
pipeline, worker builds, and cache are unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant