The image data starts at byte 128 and holds every row of the image, top row first.
Each row is the bytes of the first plane, then the second plane and so on, so a decoded row is
planes × bytes per line bytes. The bytes are run-length encoded unless the
encoding field is 0.
Packets
The encoded data is a run of packets of one or two bytes:
| First byte | Meaning |
|---|---|
C0 to FF (top two bits set) | A run: the low six bits are a count, 1 to 63, and the next byte is repeated that many times. |
00 to BF | A literal: the byte itself, one value. |
A value of C0 or above cannot be written as a literal, so it is always
written as a run, even of one: the pair C1 C5 stands for one byte
C5. This is why PCX can expand a picture that has many bright pixels.
C4 07 03 C2 80
Rows and planes
ZSoft’s reference says each scan line is decoded on its own, with a packet ending at the
end of a row. Decoding counts the bytes produced, up to planes × bytes per
line for each row, and the planes within a row run on without a break. Some
writers ignore this and let runs cross from one row to the next, so a good decoder
treats the data as one stream and only uses row lengths to find the picture. The
explorer does the same, and reports any run that crosses a row.
Decode only the rows the header says exist: the data can be followed by a 256-colour palette rather than more rows.
Padding
Bytes per line can be more than the window’s width needs, so a row can have spare bytes at the end of each plane. Only the pixels inside the window are shown; the rest is padding.
Getting pixels from planes
In a planar image, a pixel’s number is built from the bits of every plane. In a 16-colour image with four 1-bit planes the first plane holds the lowest bit of each pixel and the last holds the highest, the most significant bit of each byte being the leftmost pixel. A 24-bit image has three planes of whole bytes, for red, green and blue.