IMAGE(6) IMAGE(6)
NAME
image - external format for images
DESCRIPTION
Images are described in draw-image(2), and the definition of
pixel values is in colour(6). Fonts and images are stored in
external files in machine-independent formats.
Image files are read and written using Display.readimage and
Display.writeimage (see draw-display(2)). An image is a
rectangular array of pixels, where each pixel is organised
as one or more channels, as determined by the image.
An uncompressed image file starts with 5 strings: chan,
r.min.x, r.min.y, r.max.x, and r.max.y. Each is right-
justified and blank padded in 11 characters, followed by a
blank. The chan value is a textual string describing the
pixel format (see below for a discussion of channel descrip-
tors), and the rectangle coordinates are decimal strings.
The rest of the file contains the r.max.y-r.min.y rows of
pixel data. A row consists of the byte containing pixel
r.min.x and all the bytes up to and including the byte con-
taining pixel r.max.x-1. For images with depth d less than
eight, a pixel with x-coordinate = x will appear as d con-
tiguous bits in a byte, with the pixel's high order bit
starting at the byte's bit number w*(x mod (8/w)), where
bits within a byte are numbered 0 to 7 from the high order
to the low order bit. Rows contain integral number of
bytes, so there may be some unused pixels at either end of a
row. If d is greater than 8, the definition of images
requires that it be a multiple of 8, so pixel values take up
an integral number of bytes.
The Image.readpixels and Image.writepixel operations
described in draw-image(2) also deal with rows in this for-
mat, stored in Limbo arrays of bytes.
The channel format string is a sequence of two-character
channel descriptions, each comprising a letter (r for red, g
for green, b for blue, a for alpha, m for colour-mapped, k
for greyscale, and x for ``don't care'') followed by a num-
ber of bits per pixel. The sum of the channel bits per
pixel is the depth of the image, which must be either a
divisor or a multiple of eight. It is an error to have more
than one of any channel but x. An image must have either a
greyscale channel; a colour-mapped channel; or red, green,
and blue channels. If the alpha channel is present, it must
be at least as deep as any other channel.
The channel string defines the format of the pixels in the
Page 1 Plan 9 (printed 10/28/25)
IMAGE(6) IMAGE(6)
file, and should not be confused with ordering of bytes in
the file, which is little-endian. In particular 'r8g8b8'
pixels have byte ordering blue, green, and red within the
file. See colour(6) for more details of the pixel format.
A previous Inferno image format replaces the channel string
with a decimal ldepth, which is the base two logarithm of
the number of bits per pixel in the image. In this case,
ldepths 0, 1, 2, and 3 correspond to channel descriptors k1,
k2, k4, and m8, respectively. Furthermore, the pixel values
are inverted compared to the current colour maps; in partic-
ular, an all-zero pixel is white and all-ones is black.
That format is still readable but cannot be written; older
files should be converted to the newer one. The image file
reading operations automatically invert the pixel values to
produce correct results.
A compressed image file begins with the 11 bytes
"compressed\n", immediately followed by a header as
described above, followed by the image data. (The pixel
data once uncompressed has the format described above.) The
rest of the file is a string of compression blocks, each
encoding a number of rows of the image's pixel data. Com-
pression blocks are at most 6024 bytes long, so that they
fit comfortably in a single 9P message. Since a compression
block must encode a whole number of rows, there is a limit
(about 5825 bytes) to the width of images that may be
encoded. Most wide images are in subfonts, which, at 1 bit
per pixel (the usual case for fonts), can be 46600 pixels
wide.
A compression block begins with two decimal strings of
twelve bytes each. The first number is one more than the y
coordinate of the last row in the block. The second is the
number of bytes of compressed data in the block, not includ-
ing the two decimal strings. This number must not be larger
than 6000.
Pixels are encoded using a version of Lempel & Ziv's sliding
window scheme LZ77, best described in J A Storer & T G Szy-
manski `Data Compression via Textual Substitution', JACM
29#4, pp. 928-951.
The compression block is a string of variable-length code
words encoding substrings of the pixel data. A code word
either gives the substring directly or indicates that it is
a copy of data occurring previously in the pixel stream.
In a code word whose first byte has the high-order bit set,
the rest of the byte indicates the length of a substring
encoded directly. Values from 0 to 127 encode lengths from
1 to 128 bytes. Subsequent bytes are the literal pixel
Page 2 Plan 9 (printed 10/28/25)
IMAGE(6) IMAGE(6)
data.
If the high-order bit is zero, the next 5 bits encode the
length of a substring copied from previous pixels. Values
from 0 to 31 encode lengths from 3 to 34 bytes. The bottom
two bits of the first byte and the 8 bits of the next byte
encode an offset backward from the current position in the
pixel data at which the copy is to be found. Values from 0
to 1023 encode offsets from 1 to 1024. The encoding may be
`prescient', with the length larger than the offset, which
works just fine: the new data is identical to the data at
the given offset, even though the two strings overlap.
SEE ALSO
draw-intro(2), draw-image(2), draw(3), colour(6), font(6)
Page 3 Plan 9 (printed 10/28/25)