Inline terminal image rendering — Kitty graphics protocol / iTerm2 inline images.
The pixel-free logic (capability detection, intrinsic dimension sniffing,
cell-box sizing, escape encoding, base64/PNG transcoding) now lives in the
lanterna fork's Java class
com.googlecode.lanterna.terminal.image.TerminalImage. This namespace is the
thin Clojure adapter that keeps vis's map-shaped API ({:images …},
{:w :h}, {:cols :rows}) plus the attachment-aware paste probe, which
reaches back into vis internals and so stays here.
The escape strings are emitted DIRECTLY to the tty AFTER Lanterna's delta refresh (the screen loop owns that), placed over rows the renderer reserved as blanks. Lanterna never sees the graphics bytes, so its cell diff stays intact and the image survives subsequent delta frames.
Inline terminal image rendering — Kitty graphics protocol / iTerm2 inline
images.
The pixel-free logic (capability detection, intrinsic dimension sniffing,
cell-box sizing, escape encoding, base64/PNG transcoding) now lives in the
lanterna fork's Java class
`com.googlecode.lanterna.terminal.image.TerminalImage`. This namespace is the
thin Clojure adapter that keeps vis's map-shaped API (`{:images …}`,
`{:w :h}`, `{:cols :rows}`) plus the attachment-aware paste probe, which
reaches back into vis internals and so stays here.
The escape strings are emitted DIRECTLY to the tty AFTER Lanterna's delta
refresh (the screen loop owns that), placed over rows the renderer
reserved as blanks. Lanterna never sees the graphics bytes, so its cell
diff stays intact and the image survives subsequent delta frames.(cell-size {:keys [w h]} max-cols max-rows)Fit an image of {:w :h} px into max-cols × max-rows cells,
aspect-preserving. Returns {:cols :rows} (>= 1).
Fit an image of `{:w :h}` px into `max-cols` × `max-rows` cells,
aspect-preserving. Returns `{:cols :rows}` (>= 1).(detect-capabilities)(detect-capabilities env)Sniff which inline-image protocol the host terminal speaks from env
(defaults to the process environment). Returns {:images :kitty|:iterm2|nil}.
tmux and screen report nil — they don't reliably forward graphics.
Sniff which inline-image protocol the host terminal speaks from `env`
(defaults to the process environment). Returns `{:images :kitty|:iterm2|nil}`.
tmux and screen report `nil` — they don't reliably forward graphics.(encode-iterm2 data {:keys [cols]})iTerm2 \x1b]1337;File= inline-image sequence for base64 data.
iTerm2 `\x1b]1337;File=` inline-image sequence for base64 `data`.
(encode-kitty data {:keys [cols rows]})Kitty graphics \x1b_G transmit+display sequence for base64 data,
sized to cols×rows cells. C=1 keeps the cursor put after placement.
Kitty graphics `\x1b_G` transmit+display sequence for base64 `data`, sized to `cols`×`rows` cells. `C=1` keeps the cursor put after placement.
(graphical-terminal?)(graphical-terminal? env)Whether we're in a GRAPHICAL terminal — one that speaks an inline-image
protocol (kitty/Ghostty/WezTerm/Warp → Kitty, iTerm2 → iTerm2) — as opposed
to a plain/non-graphical terminal (or tmux/screen, which mangle graphics
pass-through). Callers branch on this to draw an inline image vs. a text-card
fallback. The 0-arity reuses the memoized capability detection; pass env to
probe an explicit environment (delegates to TerminalImage/isGraphicalTerminal).
Whether we're in a GRAPHICAL terminal — one that speaks an inline-image protocol (kitty/Ghostty/WezTerm/Warp → Kitty, iTerm2 → iTerm2) — as opposed to a plain/non-graphical terminal (or tmux/screen, which mangle graphics pass-through). Callers branch on this to draw an inline image vs. a text-card fallback. The 0-arity reuses the memoized capability detection; pass `env` to probe an explicit environment (delegates to `TerminalImage/isGraphicalTerminal`).
(image-dimensions b mime)Intrinsic {:w :h} pixel size from the leading bytes of an image, or nil.
Intrinsic `{:w :h}` pixel size from the leading bytes of an image, or nil.
(images-protocol):kitty, :iterm2, or nil for the current terminal.
`:kitty`, `:iterm2`, or nil for the current terminal.
(probe-dimensions path mime)Read path's head and sniff its {:w :h} pixel dimensions. nil on failure.
Read `path`'s head and sniff its `{:w :h}` pixel dimensions. nil on failure.
(probe-paste-image text {:keys [workspace-root]})Detect the FIRST image the pasted text points at (a dropped file path).
Returns {:path :mime :filename :size :size-label :width :height} or nil.
workspace-root anchors relative candidates. Never throws.
Detect the FIRST image the pasted `text` points at (a dropped file path).
Returns `{:path :mime :filename :size :size-label :width :height}` or nil.
`workspace-root` anchors relative candidates. Never throws.(read-base64 path)Read path and base64-encode its bytes, or nil on failure. Cached by
path + mtime + size so an unchanged file is encoded at most once.
Read `path` and base64-encode its bytes, or nil on failure. Cached by path + mtime + size so an unchanged file is encoded at most once.
(render-sequence path mime box)Full escape sequence that draws the image at path (mime) into a
cols×rows cell box for the current terminal, or nil when the terminal
can't render inline images / the file can't be decoded.
Full escape sequence that draws the image at `path` (`mime`) into a `cols`×`rows` cell box for the current terminal, or nil when the terminal can't render inline images / the file can't be decoded.
(transcode->png-base64 path {:keys [cols rows]})Decode path (any ImageIO-readable format) and re-encode it as a PNG
base64 string, downscaled so it fits the cols×rows cell box in pixels.
The Kitty protocol's f=100 only accepts PNG, so a JPEG/GIF/BMP drop must
pass through here first. Uses AWT/ImageIO (JVM-only — unavailable in the
macOS native image); returns nil on any failure so callers fall back to a
text card.
Decode `path` (any ImageIO-readable format) and re-encode it as a PNG base64 string, downscaled so it fits the `cols`×`rows` cell box in pixels. The Kitty protocol's `f=100` only accepts PNG, so a JPEG/GIF/BMP drop must pass through here first. Uses AWT/ImageIO (JVM-only — unavailable in the macOS native image); returns nil on any failure so callers fall back to a text card.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |