Universal Protocol Support
- 🐱 Kitty - Fast graphics with virtual images, z-index, compression
- 🎨 Sixel - High-quality with palette optimization and dithering
- 🍎 iTerm2 - Native inline images with ECH clearing
- 🧱 Halfblocks - Unicode fallback (works everywhere)
Rich Image Processing
- Smart scaling (fit, fill, stretch, none)
- Advanced dithering (Stucki, Floyd-Steinberg)
- Quality vs speed control
- TUI framework integration (Bubbletea)
Advanced Features
- Automatic protocol detection with fallbacks
- Terminal font size detection via CSI queries
- Tmux passthrough support
- Optimized font size caching
Warning
Kitty Unicode placeholder/relative placement features are currently under construction and not recommended for production use.
- PNG, JPEG, GIF
- Any format supported by Go's
imagepackage - WebP support planned
go get github.com/blacktop/go-termimgpackage main
import "github.com/blacktop/go-termimg"
func main() {
// Detect the terminal once at startup. Rendering never queries the
// terminal itself; without this it only uses environment hints and
// falls back to halfblocks.
termimg.QueryTerminalFeatures()
// Simple one-liner
termimg.PrintFile("image.png")
// Or with control
img, _ := termimg.Open("image.png")
img.Width(50).Height(25).Print()
}// Auto-detect best protocol and render
rendered, err := termimg.Open("image.png").
Width(80).
Height(40).
Scale(termimg.ScaleFit).
Render()// Kitty with virtual images and z-index (experimental)
termimg.Open("overlay.png").
Protocol(termimg.Kitty).
Virtual(true).
ZIndex(5).
Print()
// Sixel with dithering
termimg.Open("photo.jpg").
Protocol(termimg.Sixel).
Dither(true).
DitherMode(termimg.DitherStucki).
Print()import tea "github.com/charmbracelet/bubbletea"
type model struct {
widget *termimg.ImageWidget
}
func (m model) View() string {
rendered, _ := m.widget.Render()
return rendered
}
func main() {
// Detect before the TUI starts reading input: once it does, the
// terminal's replies go to the TUI and detection reports no support.
termimg.QueryTerminalFeatures()
img := termimg.NewImageWidgetFromFile("image.png")
img.SetSize(50, 25).SetProtocol(termimg.Auto)
p := tea.NewProgram(model{widget: img})
p.Run()
}If the host application already knows the terminal's capabilities, supply them instead and the package never reads from the terminal:
err := termimg.SetTerminalFeatures(termimg.TerminalFeatures{
KittyGraphics: true,
FontWidth: 10, // cell size in pixels
FontHeight: 20,
})Install:
go install github.com/blacktop/go-termimg/cmd/imgcat@latestBasic usage:
# Display an image
imgcat image.png
# With specific protocol and size
imgcat -W 100 -H 50 --protocol kitty image.png
# Virtual placement with positioning (Kitty only)
imgcat --virtual --x 10 --y 5 --z-index 3 image.png
# Test terminal capabilities
imgcat --detect
# Show Unicode test grid
imgcat --test-gridAdvanced options:
# Compression and PNG mode (Kitty)
imgcat --compression --png image.png
# Dithering
imgcat --dither photo.jpg
# Scale modes
imgcat --scale fit image.png # Fit within terminal
imgcat --scale fill image.png # Fill terminal, crop if needed
imgcat --scale none image.png # No scalingInstall and run:
go install github.com/blacktop/go-termimg/cmd/gallery@latest
galleryInteractive features:
- File navigation (↑/↓ or k/j keys, page up/down, home/end)
- Virtual mode toggle (v key - Kitty only)
- Grid view toggle (g key)
- Auto-detection of best terminal protocol
QueryTerminalFeatures is the only place the package queries the terminal on
its own. Call it once at startup; rendering and the helpers below report from
its cached result. The low-level query functions (ParallelProtocolDetection,
TerminalQuerier, GetTerminalFontSize, GetITerm2CellSize,
GetITerm2Variable and pkg/csi) also read from the terminal, but only when
you call them yourself.
// Query the terminal and get detailed features
features := termimg.QueryTerminalFeatures()
fmt.Printf("Font size: %dx%d\n", features.FontWidth, features.FontHeight)
// Best available protocol, from what is known
protocol := termimg.DetectProtocol()
// Check specific protocol support
if termimg.KittySupported() {
// Use Kitty features
}Without a detection result or SetTerminalFeatures, these use environment
variables only: Auto falls back to halfblocks when they give no hint, and
the cell size is an estimate for the named terminal, not a measurement.
An explicitly selected protocol is always used as given.
Performance benchmarks for different protocols:
- Halfblocks: ~800µs (fastest, works everywhere)
- Kitty: ~2.5ms (efficient, modern terminals)
- iTerm2: ~2.5ms (fast, macOS)
- Sixel: ~90ms (high quality, slower)
Font size detection is cached to avoid repeated terminal queries.
The cmd/ directory contains several example programs:
# Image viewer
cd cmd/imgcat/
go run main.go ../../test/image.png --id 123 --place --x 5 --y 10
# Interactive gallery
cd cmd/gallery/
go run main.go
# Terminal info
cd cmd/terminfo/
go run main.goMIT Copyright (c) 2024-2025 blacktop