Skip to main content

Module graphics

Module graphics 

Source
Available on crate feature kitty-graphics only.
Expand description

API for inspecting images and placements stored via the Kitty graphics protocol.

The central object is Graphics, an opaque handle to the image storage associated with a terminal’s active screen. From it you can iterate over placements and look up individual images.

§Obtaining a Graphics handle

A Graphics handle is obtained from a terminal via Terminal::kitty_graphics. The handle is borrowed from the terminal and remains valid until the next mutating terminal call (e.g. Terminal::vt_write or Terminal::reset).

Before images can be stored, Kitty graphics must be enabled on the terminal by setting a non-zero storage limit with Terminal::set_kitty_image_storage_limit and a PNG decoder must be installed via set_png_decoder.

§Iterating placements

Placements are inspected through a PlacementIterator. The typical workflow is:

  1. Create an iterator with PlacementIterator::new.
  2. Populate it from the storage with PlacementIterator::update, returning a PlacementIteration object.
  3. Optionally filter by z-layer with PlacementIteration::set_layer.
  4. Advance with PlacementIteration::next and read per-placement data with various methods on PlacementIteration, such as PlacementIteration::image_id.
  5. For each placement, look up its image with Graphics::image to access pixel data and dimensions.

§Looking up images

Given an image ID (obtained from a placement via PlacementIteration::image_id), call Graphics::image to get an Image handle. From this handle, various methods provide the image dimensions, pixel format, compression, and a reference to the raw pixel data.

§Rendering helpers

Several functions assist with rendering a placement:

§Lifetimes and thread-safety

All handles borrowed from the terminal (Graphics, Image) are invalidated by any mutating terminal call. The placement iterator is independently owned and must be freed by the caller, but the data it yields is only valid while the underlying terminal is not mutated.

§Example

The following example creates a terminal, sends a Kitty graphics image, then iterates placements and prints image metadata:

use libghostty_vt::{
    Terminal,
    TerminalOptions,
    alloc::{Allocator, Bytes},
    kitty::graphics,
};

/// Minimal PNG decoder.
///
/// A real implementation would use a PNG library (libpng, stb_image, etc.)
/// to decode the PNG data. This example uses a hardcoded 1x1 red pixel
/// since we know exactly what image we're sending.
///
/// WARNING: This is only an example for providing a callback, it DOES NOT
/// actually decode the PNG it is passed. It hardcodes a response.
struct StubPngDecoder;

impl graphics::DecodePng for StubPngDecoder {
   fn decode_png<'alloc, 'ctx>(
       &mut self,
       alloc: &'alloc Allocator<'ctx>,
       data: &[u8],
   ) -> Option<graphics::DecodedImage<'alloc>> {
       // Allocate RGBA pixel data through the provided allocator.
       let mut data = Bytes::new_with_alloc(alloc, 4).ok()?;

       // Fill with red (R=255, G=0, B=0, A=255).
       data.copy_from_slice(&[255, 0, 0, 255]);
  
       Some(graphics::DecodedImage {
           width: 1,
           height: 1,
           data,
       })
   }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    graphics::set_png_decoder(Some(Box::new(StubPngDecoder)))?;

    let mut terminal = Terminal::new(TerminalOptions {
       cols: 80,
       rows: 24,
       max_scrollback: 0
   })?;

   // Set cell pixel dimensions so kitty graphics can compute grid sizes.
   terminal.resize(80, 24, 8, 16)?;

   // Set a storage limit (64MiB) to enable Kitty graphics.
   terminal.set_kitty_image_storage_limit(64 * 1024 * 1024)?;

   // Install pty_write to see the protocol response.
   terminal.on_pty_write(|_, data| println!("{}", data.escape_ascii()))?;

   // Send a Kitty graphics command with an inline 1x1 PNG image.
   //
   // The escape sequence is:
   //   ESC _G a=T,f=100,q=1; <base64 PNG data> ESC \
   //
   // Where:
   //   a=T   — transmit and display
   //   f=100 — PNG format
   //   q=1   — request a response (q=0 would suppress it)
   println!("Sending Kitty graphics PNG image:");
   terminal.vt_write(
     b"\x1b_Ga=T,f=100,q=1;\
      iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAA\
      DUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==\
     \x1b\\"
   );

   let graphics = terminal.kitty_graphics()?;
   let mut iter = graphics::PlacementIterator::new()?;
   let mut placements = iter.update(&graphics)?;

   let mut placement_count = 0usize;
   while let Some(placement) = placements.next() {
       placement_count += 1;
       let image_id = placement.image_id()?;
       println!(
           "  placement #{}: image_id={} placement_id={} virtual={} z={}",
           placement_count,
           image_id,
           placement.placement_id()?,
           placement.is_virtual()?,
           placement.z()?,
      );

      // Look up the image and print its properties.
      let image = graphics.image(image_id).unwrap();
      println!(
          "    image: number={} size={}x{} format={:?} data_len={}",
          image.number()?,
          image.width()?,
          image.height()?,
          image.format()?,
          image.data()?.len(),
      );

      let pixel_size = placement.pixel_size(&image, &terminal)?;
      println!(
          "    rendered pixel size: {}x{}",
          pixel_size.width, pixel_size.height,
      );
      let grid_size = placement.grid_size(&image, &terminal)?;
      println!(
          "    grid size: {} cols x {} rows",
          grid_size.cols, grid_size.rows,
      );
   }
   println!("Total placements: {placement_count}");
   Ok(())
}

Structs§

DecodedImage
Result of decoding an image.
Graphics
Opaque reference to a Kitty graphics image storage.
GridSize
The size of an image in grid coordinates.
Image
Opaque reference to a Kitty graphics image.
PixelSize
The size of an image in pixel coordinates.
PlacementIteration
Obtained via PlacementIterator::update. The reference is borrowed from the storage with lifetime 't and remains valid until the next mutating terminal call.
PlacementIterator
Opaque reference to a Kitty graphics placement iterator.
PlacementRenderInfo
Combined rendering geometry for a placement in a single sized struct.
RustPngDecoderpng
A PNG decoder for set_png_decoder using the png crate.
SourceRect
The pixel position and size of a source rectangle.
ViewportPos
The position of an image in the viewport.

Enums§

Compression
Compression of a Kitty graphics image.
ImageFormat
Pixel format of a Kitty graphics image.
Layer
Z-layer classification for kitty graphics placements.

Traits§

DecodePng
A PNG decoder that can be used by the Kitty graphics protocol to decode PNG images into 8-bit RGBA pixels.

Functions§

set_png_decoder
Set the PNG decoder.