Skip to content

Repository files navigation

icy_sixel

A high-performance, 100% pure Rust implementation of SIXEL graphics encoding and decoding.

Crates.io Documentation License

What is SIXEL?

SIXEL (Six Pixels) is a bitmap graphics format for terminals, originally developed by DEC for the VT200 series terminals in the 1980s. It allows displaying images directly in terminal emulators that support the format.

Modern terminals with SIXEL support include:

  • xterm (with +sixel build option)
  • mlterm, foot, WezTerm, Contour, ctx, and many more

Crates

This repository contains two crates:

icy_sixel - Library

The core Rust library for encoding and decoding SIXEL graphics.

cargo add icy_sixel

Features:

  • High-quality color quantization (Wu's algorithm + Floyd-Steinberg dithering)
  • SIMD-accelerated decoder
  • Full transparency support
  • Configurable pixel aspect ratio and background mode
  • No C dependencies

icy_sixel-cli - Command-Line Tool

A CLI for converting images to/from SIXEL and playing animated GIFs.

cargo install icy_sixel-cli

Commands:

  • sixel encode - Convert PNG/JPEG/GIF/WebP to SIXEL
  • sixel decode - Convert SIXEL back to PNG
  • sixel animate - Play animated GIFs in the terminal

Quick Start

Library Usage

use icy_sixel::SixelImage;

let rgba = vec![255, 0, 0, 255]; // Red pixel
let sixel = SixelImage::try_from_rgba(rgba, 1, 1)?.encode()?;
print!("{}", sixel);

CLI Usage

# Display image in terminal
sixel encode image.png

# Play animated GIF
sixel animate animation.gif

# Convert SIXEL to PNG
sixel decode image.six -o output.png

Decoder Performance: Batch vs. Streaming

Version 0.7.0 supports both one-shot decoding with SixelImage::decode() and incremental decoding with SixelDecoder::begin_dcs() / feed() / finish(). Both use the same decoding core; streaming avoids buffering the entire encoded input, but still retains the growing RGBA canvas. Streaming was introduced in 0.7.0 and is not available in 0.6.x.

Measured on 2026-09-06 with Linux x86_64, AMD Ryzen 9 9950X3D and Rust 1.96.0, after the decoder optimizations for 0.7.0:

Fixture Batch (non-streaming) Streaming, 1-byte chunks Streaming, 1-KiB chunks Streaming, 8-KiB chunks
Test page 67.41 µs 127.87 µs 68.87 µs 69.73 µs
Beelitz photo 6.79 ms 11.35 ms 6.49 ms 6.45 ms
Transparency 46.26 µs 101.94 µs 47.30 µs 47.61 µs

With 1-KiB chunks, streaming latency was within about 5% of batch decoding for these fixtures. Feeding one byte at a time took 1.7–2.2× as long because of per-call overhead. Prefer buffered chunks when available; streaming is useful for consuming incoming terminal data without waiting for the entire DCS sequence. Small apparent streaming wins can reflect CPU scheduling and clock variation, not an inherently faster decoder.

These are Criterion point estimates from the same streaming/* benchmark group (30 samples, 1-second warm-up, 2-second measurement target). Each case includes a fresh decoder, allocation, parsing, finalization and image disposal, with embedded input and no timed file I/O. They compare current APIs, not old and new releases. See the benchmark documentation for methodology, historical comparisons and profiling, and the library README for streaming usage and termination semantics.

Building

git clone https://github.com/mkrueger/icy_sixel
cd icy_sixel

# Build everything
cargo build --release

# Run tests
cargo test

# Run benchmarks
cargo bench

License

Licensed under either of:

at your option.

Related Projects

  • libsixel - The original C implementation
  • quantette - Color quantization library used by icy_sixel

About

100% Rust sixel encoder/decoder.

Resources

Stars

33 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages