Introduction
This is the bitmap format of OS/2 2.x and later. A file holds a device independent
bitmap (DIB): a 14-byte file header, a header of 16 to 64 bytes describing the image, an
optional palette and the pixels. It starts with BM, like a Windows
bitmap.
The header, BITMAPINFOHEADER2 (also known as
OS22XBITMAPHEADER), lines up with the first 40 bytes of the Windows header,
but it is a different format. Compression 3 means Huffman 1D and 4 means RLE24, where
Windows uses them for bit masks and JPEG. The header can be cut short, with the missing
fields taken as zero, and it adds OS/2’s own fields for units, halftoning and colour
encoding. Files use the extension .bmp.
Structure
The file has four parts, in this order. The colour table is there at 8 bits per pixel and below. All numbers are little-endian.
0File headerBM, the file size and the offset of the pixels14 bytes14Header its size, then as many fields as that size covers16 to 64 bytes…Colour table the palette, 4 bytes per entryup to 1024 bytes…Pixel data rows padded to 4 bytes, bottom row first, or compressed; at the offset in the file headervaries
File header
The file starts with the 14-byte BITMAPFILEHEADER2. It has no padding, so
the fields after the first are not aligned to 4 bytes.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | char[2] | usType | The signature BM (42 4D). |
| 2 | 4 | u32 | cbSize | A size field; readers should not depend on it. |
| 6 | 2 | i16 | xHotspot | Used by icons and pointers; zero in a bitmap. |
| 8 | 2 | i16 | yHotspot | Zero in a bitmap. |
| 10 | 4 | u32 | offBits | The offset from the start of the file to the pixel data. |
Header
The header follows at offset 14. Its first field, cbFix, gives its length.
A header can stop after any field: the fields it holds are the ones that fit in
cbFix bytes, and every field after that is taken as zero. The full header is
64 bytes; the shortest, 16 bytes, ends after the bit count. Offsets in this table are
from the start of the header; add 14 for the offset in the file.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 4 | u32 | cbFix | The header size, 16 to 64. |
| 4 | 4 | u32 | cx | The width in pixels. |
| 8 | 4 | u32 | cy | The height in pixels. It is unsigned: the rows are stored bottom row first. |
| 12 | 2 | u16 | cPlanes | The number of planes, 1. |
| 14 | 2 | u16 | cBitCount | Bits per pixel, usually 1, 4, 8 or 24. A 16-byte header ends here. |
| 16 | 4 | u32 | ulCompression | How the pixels are stored: one of the compression values, 0 for none. |
| 20 | 4 | u32 | cbImage | The size of the pixel data in bytes. |
| 24 | 4 | u32 | cxResolution | Horizontal resolution. |
| 28 | 4 | u32 | cyResolution | Vertical resolution. |
| 32 | 4 | u32 | cclrUsed | The number of entries in the colour table. 0 means the most the bit count allows. |
| 36 | 4 | u32 | cclrImportant | The number of colours needed to show the image. 0 means all of them. |
| 40 | 2 | u16 | usUnits | The resolution units; 0 is pixels per metre. |
| 42 | 2 | u16 | usReserved | Reserved. |
| 44 | 2 | u16 | usRecording | The row order; 0, bottom row first, is the only value defined. |
| 46 | 2 | u16 | usRendering | The halftoning method used, if any; 0 is none. |
| 48 | 4 | u32 | cSize1 | The first halftoning parameter. |
| 52 | 4 | u32 | cSize2 | The second halftoning parameter. |
| 56 | 4 | u32 | ulColorEncoding | The colour encoding; 0 is RGB. |
| 60 | 4 | u32 | ulIdentifier | Free for the application’s own use. The full header ends here, at 64 bytes. |
Because a missing field counts as zero, a 16-byte header means an uncompressed image whose colour table has the full number of entries.
Colour table
At 1, 4 and 8 bits per pixel the colour table follows the header, and each pixel is
a number that picks one of its entries. It holds cclrUsed entries, or 2, 16
or 256 when cclrUsed is 0 or missing. A 24-bit image normally has none.
Each entry is an RGB2 of 4 bytes:
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 1 | u8 | bBlue | Blue, 0 to 255. |
| 1 | 1 | u8 | bGreen | Green, 0 to 255. |
| 2 | 1 | u8 | bRed | Red, 0 to 255. |
| 3 | 1 | u8 | fcOptions | Reserved, zero. |
The table is 4 × entries bytes long, so a full 256-colour table takes 1024
bytes. It can hold any colours in any order, so always look colours up in it. The
pixels start at offBits, which may leave a gap after the table.
Pixel data
Uncompressed pixels are stored as rows from the bottom of the picture to the top, and pixels within a row run from left to right. Each row is padded with zero bytes to a multiple of 4 bytes:
const stride = Math.floor((bitCount * width + 31) / 32) * 4;
| Bit count | Each pixel is | Packing |
|---|---|---|
1 | an index into a 2-colour table | 8 pixels per byte; the highest bit is the leftmost pixel |
4 | an index into a 16-colour table | 2 pixels per byte; the high nibble is the left pixel |
8 | an index into a 256-colour table | 1 pixel per byte |
24 | a colour | 3 bytes: blue, green, red |
To find the row drawn at line y from the top, read row
height − 1 − y of the data.
Compression
ulCompression says how the pixel data is stored. When the header is too
short to hold it, it is 0. A compressed image’s cbImage gives the size of
the compressed data.
| Value | Name | Bit count | Meaning |
|---|---|---|---|
| 0x00 (0) | BCA_UNCOMP | any | Uncompressed. |
| 0x01 (1) | BCA_RLE8 | 8 | Run-length encoded 8-bit indexes. |
| 0x02 (2) | BCA_RLE4 | 4 | Run-length encoded 4-bit indexes. |
| 0x03 (3) | BCA_HUFFMAN1D | 1 | Huffman 1D coding of a 1-bit image. |
| 0x04 (4) | BCA_RLE24 | 24 | Run-length encoded 24-bit colours. |
RLE8 data is read two bytes at a time. In encoded mode the first byte is a count from 1 to 255 and the second is a palette index to repeat that many times. A first byte of zero is an escape, and the second byte says what it means:
| Second byte | Meaning |
|---|---|
| 0x00 (0) | End of line: go to the start of the next row. |
| 0x01 (1) | End of bitmap: the image is complete. |
| 0x02 (2) | Delta: the next two bytes move the position right and on by that many pixels and rows. Skipped pixels are left undefined. |
| 0x03 (3) to 0xFF (255) | Absolute mode: that many literal palette indexes follow, padded with a zero byte to an even length. |
RLE4 works the same way with 4-bit indexes. In encoded mode the count is a number of pixels and the second byte holds two indexes, used in turn: high nibble, low nibble, high nibble and so on. In absolute mode the count is a number of pixels, packed two to a byte, and the bytes are padded to an even length.
RLE24 runs are a count byte followed by three colour bytes, one pixel’s colour, repeated that many times. A count of zero starts an escape. That the escapes and absolute mode work as in RLE8, with three bytes per literal pixel, is understood rather than confirmed from a published specification.
Huffman 1D applies to 1-bit images. It is understood to be the one-dimensional coding of CCITT Group 3 fax. Few programs read or write it, and this page does not describe the code.
A complete file
This 2 by 2 pixel, 24-bit image has the shortest header, 16 bytes, and is 46 bytes long. The header is marked. The pixels start at offset 30: the bottom row, blue and green, then the top row, red and white, each 6 bytes padded to 8.
00000000 42 4D 2E 00 00 00 00 00 00 00 1E 00 00 00 10 00
00000010 00 00 02 00 00 00 02 00 00 00 01 00 18 00 FF 00
00000020 00 00 FF 00 00 00 00 00 FF FF FF FF 00 00
Telling it apart
The explorer’s parser for this format checks two things: the file starts with
BM (42 4D), and the header size, the four bytes at offset 14,
is from 16 to 64 but not 40, 52 or 56. A file that fails either check is turned down,
and the explorer tries the parsers for the other BMP formats.
Sizes of 40, 52 and 56 bytes are also Windows header sizes, and a file with one of them is read as a Windows bitmap. An OS/2 2.x bitmap cut to one of those lengths therefore cannot be told apart from a Windows one by its header size. A Windows 2 and OS/2 1.x bitmap has a 12-byte header.
Variants
- Windows bitmap (BM) – Windows 3.0 and later: a 40- to 124-byte header
- Windows 2 and OS/2 1.x bitmap (BM) – the first bitmaps, with a 12-byte header
- OS/2 2.x bitmap (BM) – a 16- to 64-byte header, with Huffman 1D and RLE24
- OS/2 bitmap array (BA) – several OS/2 bitmaps, icons or pointers for different screens, chained in one file
- OS/2 icon (IC) – a black and white OS/2 icon: AND and XOR masks in one 1-bit bitmap
- OS/2 colour icon (CI) – a colour OS/2 icon: a 1-bit mask bitmap followed by a colour image
- OS/2 pointer (PT) – a black and white OS/2 mouse pointer, with its hotspot in the header
- OS/2 colour pointer (CP) – a colour OS/2 mouse pointer: masks, a colour image and a hotspot