Introduction
This is the first form of the BMP bitmap, from Windows 2.0 and OS/2 1.x. A file holds a device independent bitmap (DIB): a 14-byte file header, a 12-byte header giving the size of the image and its bits per pixel, a palette and the rows of pixels. The pixels are never compressed.
The 12-byte header is called BITMAPCOREHEADER in the Windows headers. Its
width and height are 16-bit numbers, it has no compression field, and its palette
entries are 3 bytes each. Windows 3.0 replaced it with a 40-byte header, and OS/2 2.x
with a longer header of its own; those bitmaps are separate formats. Later versions of
Windows and OS/2 still read these older files, as do most image programs, but few
programs write them now. Files use the extension .bmp.
Structure
The file has four parts, in this order. The colour table is there only 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, 12, then the width, height, planes and bit count12 bytes26Colour table the palette, 3 bytes per entryup to 768 bytes…Pixel data rows padded to 4 bytes, bottom row first, at the offset in the file headervaries
File header
The file starts with the 14-byte BITMAPFILEHEADER. 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] | bfType | The signature BM (42 4D). |
| 2 | 4 | u32 | bfSize | The size of the whole file in bytes. Some programs write a wrong value or zero, so readers should not depend on it. |
| 6 | 2 | u16 | bfReserved1 | Reserved, zero. |
| 8 | 2 | u16 | bfReserved2 | Reserved, zero. |
| 10 | 4 | u32 | bfOffBits | The offset from the start of the file to the pixel data. |
Header
The 12-byte header follows at offset 14. OS/2 1.x calls the same structure
BITMAPINFOHEADER, with the fields named cbFix,
cx, cy, cPlanes and cBitCount.
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 | bcSize | The header size, 12. |
| 4 | 2 | u16 | bcWidth | The width in pixels. |
| 6 | 2 | u16 | bcHeight | The height in pixels. It is unsigned, so the rows are always stored bottom row first. |
| 8 | 2 | u16 | bcPlanes | The number of planes, always 1. |
| 10 | 2 | u16 | bcBitCount | Bits per pixel: 1, 4, 8 or 24. |
There is no compression field, no image size, no resolution and no count of colours. The pixels are always stored as they are.
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. A 24-bit image has no colour table. Each entry
is an RGBTRIPLE of 3 bytes, with no reserved byte:
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 1 | u8 | rgbtBlue | Blue, 0 to 255. |
| 1 | 1 | u8 | rgbtGreen | Green, 0 to 255. |
| 2 | 1 | u8 | rgbtRed | Red, 0 to 255. |
The header has no field for the number of colours, so the table normally holds all
the entries the bit count allows: 2, 16 or 256, which is 6, 48 or 768 bytes. Some
files hold fewer. The table then ends where the pixels start, at
bfOffBits, so a reader can take the number of entries as
(bfOffBits − 26) ÷ 3 when that is smaller than the full count.
The table can hold any colours in any order. A 1-bit image is not always black and white, so always look colours up in the table.
Pixel data
The pixels start at bfOffBits. They 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.
A complete file
This 2 by 2 pixel, 24-bit image is 42 bytes long. The 12-byte header is marked. The pixels start at offset 26: the bottom row, blue and green, then the top row, red and white, each 6 bytes padded to 8.
00000000 42 4D 2A 00 00 00 00 00 00 00 1A 00 00 00 0C 00
00000010 00 00 02 00 02 00 01 00 18 00 FF 00 00 00 FF 00
00000020 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 four bytes at offset 14, the header size,
hold 12. A file that fails either check is turned down, and the explorer tries the
parsers for the other BMP formats.
A Windows bitmap of Windows 3.0 and later also starts with BM, but its
header is 40 to 124 bytes long, and an OS/2 2.x bitmap’s is 16 to 64 bytes.
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
Links
Software
- GIMP – free image editor that opens these older bitmaps (Windows, macOS, Linux)
- ImageMagick – command-line tools that convert them to other formats (Windows, macOS, Linux)
- Deark – command-line file extractor that converts them to PNG (Windows, macOS, Linux)
Developers
- Pillow – imaging library that reads them (Python)
Reference
- BITMAPCOREHEADER structure – Microsoft’s reference for the 12-byte header
- RGBTRIPLE structure – Microsoft’s reference for the 3-byte colour table entry