Something went wrong. Try again.
A sans-I/O Zig library that reads and writes DEC sixel graphics as z2d surfaces.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie <jeff@ocjtech.us>// SPDX-License-Identifier: MIT
//! Reading and writing DEC sixel graphics as [z2d](https://github.com/vancluever/z2d)//! surfaces.//!//! Sixel is the bitmap format of DEC's graphics terminals and printers: an//! image sent as printable characters inside a device control string, each//! character six pixels in a column. xterm, foot, WezTerm, Ghostty's//! siblings and a good many others still display it.//!//! ## Reading a stream//!//! `relay` copies a `std.Io.Reader` to a `std.Io.Writer` and takes the sixel//! images out as it goes, handing each to a handler of yours as a surface://!//! ```zig//! const Handler = struct {//! gpa: std.mem.Allocator,//! pub fn image(self: *Handler, img: sixel.Image) !void {//! var owned = img;//! defer owned.deinit(self.gpa);//! // ... owned.surface is a z2d.Surface ...//! }//! };//! var handler: Handler = .{ .gpa = gpa };//! try sixel.relay(gpa, &reader.interface, &writer.interface, &handler, .{});//! ```//!//! Everything that is not an image passes through untouched, and as soon as//! it arrives: `relay` writes what it has read before it waits to read more.//!//! ## Reading a slice//!//! ```zig//! var img = try sixel.decode(gpa, bytes, .{});//! defer img.deinit(gpa);//! ```//!//! ## Writing//!//! ```zig//! try sixel.encode(gpa, writer, &surface, .{}); // to a std.Io.Writer//! const bytes = try sixel.encodeAlloc(gpa, &surface, .{}); // to memory you own//! const used = try sixel.encodeBuffer(gpa, &buf, &surface, .{}); // to your buffer//! ```//!//! An image with more colors than registers is reduced to a palette by//! median cut and dithered; one with few enough is written exactly. See//! `quantize`.//!//! ## Sans-I/O//!//! Nothing here opens, reads or writes anything on its own, and nothing takes//! an `Io`. Bytes come in through a `std.Io.Reader` or a slice and go out//! through a `std.Io.Writer` or a slice, and where those lead is the calling//! program's business. Under both read paths is `Parser`, a state machine//! fed bytes in pieces of any size, for anything else that wants to drive a//! decoder.//!//! ## Untrusted input//!//! A sixel stream can claim any size and draw anywhere, so `Limits` bounds//! the canvas a decoder will allocate. What falls outside is dropped and the//! image is marked `clipped`, as a terminal drops what falls off its screen.//! Nothing a stream contains can make a decoder panic or allocate without//! bound.
const std = @import("std");
pub const Canvas = @import("Canvas.zig");pub const Image = @import("Image.zig");pub const Parser = @import("Parser.zig");pub const introducer = @import("introducer.zig");pub const palette = @import("palette.zig");pub const quantize = @import("quantize.zig");
pub const Limits = Canvas.Limits;pub const Aspect = introducer.Aspect;
const decode_ = @import("decode.zig");pub const decode = decode_.decode;pub const DecodeOptions = decode_.Options;pub const DecodeError = decode_.Error;
const relay_ = @import("relay.zig");pub const relay = relay_.relay;pub const RelayOptions = relay_.Options;pub const RelayError = relay_.Error;pub const min_buffer_len = relay_.min_buffer_len;
const encode_ = @import("encode.zig");pub const encode = encode_.encode;pub const encodeBuffer = encode_.encodeBuffer;pub const encodeAlloc = encode_.encodeAlloc;pub const EncodeOptions = encode_.Options;pub const EncodeError = encode_.Error;pub const Dither = encode_.Dither;
test { std.testing.refAllDecls(@This()); _ = decode_; _ = relay_; _ = encode_;}