The BODY chunk holds the pixels. It must come after the
bitmap header, whose width, height and
compression say how to read it. This is where PBM differs from ILBM: the pixels are
bytes, not bitplanes, so an ILBM reader cannot read them. No document describes the
layout; it is known from the files and from FFmpeg’s and Netpbm’s readers.
Rows
The rows run from the top of the picture to the bottom. Each pixel is one byte, its colour number in the colour map, from left to right. When the width is odd, one pad byte follows each row, so every row is an even number of bytes:
RowBytes = w + (w mod 2)
width + (width % 2)- The unpacked size of the
BODYish × RowBytes. - The pad byte is not a pixel. Its value is not fixed.
- There is no mask plane, whatever the masking field says.
0Row 0wpixels, a byte each, and a pad byte ifwis oddRowBytes…Row 1 the sameRowBytes…Row h − 1 the bottom rowRowBytes
BODYAn uncompressed example
A 1 × 1 picture with compression 0 has one row of one pixel, padded to two bytes:
42 4F 44 59 00 00 00 02 38 FF
38); FF is the pad byteByteRun1
With compression 1, each row is packed on its own with ByteRun1, a run-length encoding that is the same as Apple’s PackBits. A run should never carry over from one row to the next. To unpack, read a control byte n as a signed number:
| n | Byte | Meaning |
|---|---|---|
| 0 to 127 | 00 to 7F | Copy the next n + 1 bytes as they are (1 to 128). |
| −1 to −127 | FF to 81 | Repeat the next byte −n + 1 times (2 to 128). Read unsigned, that is 257 − n times. |
| −128 | 80 | Do nothing. |
- Work out how many bytes a row unpacks to:
RowBytes, pad byte included. - Read a control byte and do what the table says, until the row has that many bytes.
- The next byte starts the next row.
The ILBM document’s advice for packers holds here too: a run of 3 or more equal bytes is always a repeat; a run of 2 is a repeat unless it sits between two literal runs.
000005BA 42 4F 44 59 00 00 09 71 81 00 81 00 C1 00 81 00
000005CA 81 00 C1 00 E0 00 00 0E 81 00 81 00 E3 00
Row 0: 81 is −127, so 128 bytes of colour 0; again 128; then
C1, −63, 64 more: 320 pixels. Row 1 is the same. Row 2:
E0 is −32, 33 bytes of 0; 00 copies one byte,
0E, so pixel 33 is colour 14; then 128, 128 and, with E3
(−29), 30 bytes of 0: 33 + 1 + 128 + 128 + 30 = 320.
Short, long and damaged data
- When the
BODY’s size is odd, a pad byte follows it, outside the chunk. Some writers count a pad byte in the size instead, so one byte follows the last row; the explorer shows it as a pad byte and does not count it as a problem. - More bytes after the last row are reported, and readers ignore them.
- When the data ends early, the explorer reports the row it ends in and shows the rows it has.
- A run that carries on past the end of a row is reported, and its extra bytes are dropped.
- With a compression other than 0 or 1 the explorer shows the
BODYas bytes.
The TINY thumbnail’s pixels are stored in the same way, with the same compression.