@lib/sixel
v1.0.3
Published
Fast sixel encoder for indexed color bitmap terminal graphics
Readme
@lib/sixel
Draw indexed color bitmap graphics on terminals supporting sixel graphics, without dependencies.
Install:
npm install --save @lib/sixelAPI
ƒ encodeSixelImage(config: SixelImageConfig): void
Encode an indexed 256-color image stored as one-byte pixels, into a string of DEC terminal control codes to render it using sixels.
configConfiguration object.
Ⓘ SixelImageConfig
Configuration for generating a Sixel image.
imageContiguous image buffer, one byte per pixel.widthImage width in pixels, unsigned 16-bit integer.heightImage height in pixels, unsigned 16-bit integer.paletteRGB values 0-1 for every palette index used in image data.writeCallback to write a chunk of output bytes. It should make a copy as needed, the same chunk buffer is re-used between calls.transparentIndexPalette index of transparent color (default: no transparency).strideDistance in memory between vertically adjacent pixels (default: image width in pixels).offsetByte offset to start of image data (default: 0).
Example
Create a file mandelbrot.ts:
import { encodeSixelImage } from '@lib/sixel';
const size = 257;
const image = new Uint8Array(size * size);
const step = 4 / (size - 1);
let pos = 0;
for(let b = 2; b >= -2; b -= step) {
for(let a = -2; a <= 2; a += step) {
let p = 0, q = 0, i = 0;
while(i++ < 16 && p * p + q * q < 4) {
const t = p * p - q * q + a;
q = 2 * p * q + b;
p = t;
}
image[pos++] = i & 1;
}
}
encodeSixelImage({
image,
width: size,
height: size,
palette: [[0, 0, 0], [1, 1, 1]],
write(chunk: Uint8Array) { process.stdout.write(chunk); }
});
process.stdout.write('\n');
// This is how to output a PGM image instead:
// process.stdout.write('P5 ' + size + ' ' + size + ' 1\n');
// process.stdout.write(image);Run it:
npx @lib/run mandelbrotIt should literally output a fractal image like at the top of this readme.
Algorithm
Sixel graphics is based on encoding images as bands 6 pixels tall. A band uses one bit per pixel to distinguish covered versus transparent. It's possible to switch colors between columns, but not individual pixels. A workaround is to print several overlapping bands leaving holes for different colors.
This algorithm keeps redrawing a band until all colors are rendered. It will also switch colors in the middle of a band, if the current color is not re-used within the next 7 columns.
Sixel also supports RLE compression, repeating the same hole pattern for multiple columns. This algorithm tries to take maximum advantage even if it means drawing extra pixels, before they have the correct color.
Extreme SIMD-style branchless bit twiddling hacks are used for speed, with clarifying code comments.
More information
- Sixel on Wikipedia.
- Are We Sixel Yet? - Supported and unsupported terminals.
- chafa - Terminal graphics library and tooling (sixel and other alternatives).
License
0BSD, which means use as you wish and no need to mention this project or its author. Consider it public domain in practice.
