Skip to content

Image Encoding

Mikkel102454 edited this page Oct 6, 2026 · 3 revisions

Image encoding

Images use a row-major stream of 4-bit palette indices, then Base64 encoding. Pixels are ordered left to right, top to bottom. There is no header or row padding.

Each byte stores the first pixel in its high nibble and the second in its low nibble:

byte = (first_pixel << 4) | second_pixel

For pixel (x, y), the stream index is y * width + x; the byte index is integer division by 2. Even stream indices use the high nibble. With odd image widths, a byte may contain the last pixel of one row and the first of the next.

Size

pixel_count = width * height
raw_bytes = ceil(pixel_count / 2)
base64_characters = 4 * ceil(raw_bytes / 3)

If the total pixel count is odd, the last low nibble is unused. Pad it with zero; it is not rendered.

Dimensions Pixels Raw bytes Base64 characters
2 × 2 4 2 4
3 × 1 3 2 4
100 × 100 10,000 5,000 6,668
792 × 272 215,424 107,712 143,616

A full-display packed image exceeds the firmware's 128 KiB response-body limit once Base64 encoded, even before JSON overhead. Splitting it into commands inside one response does not reduce that total. Prefer drawing commands and smaller image regions.

Palette and transparency

Use 0 black, 1 white, 2 yellow, 3 red, and 4 transparent. The default skip index is 4; the command can override it with transparent. The display does not support fractional alpha.

For a 2 × 2 image containing black, white, yellow, transparent, the bytes are 01 24, encoded as ASQ=. A 3 × 1 image containing black, white, red can use bytes 01 30, encoded as ATA=.

See Draw Image and Color Palette.

Implementation references

Clone this wiki locally