An XBM file is C source text: a few #define lines and one array. The X
library’s XReadBitmapFile defines what a reader accepts, and
XWriteBitmapFile what a writer produces. This page follows the libX11
code for both.
Defines
Each define has the form #define name_suffix value,
with a decimal integer value. Only the part after the last underscore matters to the
reader; the name before it is ignored, and other defines are skipped.
| Suffix | Required | Meaning |
|---|---|---|
_width | yes | the width in pixels; must not be 0 |
_height | yes | the height in pixels; must not be 0 |
_x_hot | no | the hotspot column, for a cursor |
_y_hot | no | the hotspot row |
The width and height must come before the array. Without the hotspot defines, Xlib reports the hotspot as −1, −1, and a writer leaves them out when they are −1.
The bits array
The array’s name must end in bits, conventionally
name_bits. Its declaration says which form the file is:
| Declaration | Form | Each value |
|---|---|---|
static unsigned char name_bits[] = { | X11 | 8 bits |
static char name_bits[] = { | X11 | 8 bits |
static short name_bits[] = { | X10 | 16 bits |
The values are hexadecimal, normally written 0x followed by two digits
(four in X10), separated by commas and white space, and the array ends with
};. Xlib reads only the first bits array in a file. Extra values after
the last row are ignored; too few make the file invalid.
Xlib’s writer puts 12 values on each line, each written 0x%02x, after
three spaces. It takes the name prefix from the file name it is given, minus any
directory.
Rows and bit order
The rows run from the top of the image to the bottom, with no row count or separator. In the X11 form each row is ceil(width / 8) bytes. The first byte holds the leftmost 8 pixels, and within each byte the least significant bit, bit 0, is the leftmost pixel. A 1 bit is a foreground pixel, which X usually draws in black; 0 is background. Bits past the right edge in a row’s last byte are padding and are ignored.
This is the opposite bit order to most other one-bit formats, such as MacPaint and BMP, where the most significant bit is leftmost. Some third-party descriptions get it wrong; libX11 builds its image with the bit order set to least significant bit first.
For pixel (x, y) in the X11 form: byte number y × ceil(width / 8) + floor(x / 8) of the array, bit x mod 8.
The X10 form
X version 10 wrote the array as 16-bit short values. Each row is a whole
number of them, ceil(width / 16), and each value holds 16 pixels: its low
byte is the left 8 pixels and its high byte the next 8, again least significant bit
first. So a reader can split each value into low byte then high byte, and drop the
last high byte of a row when the width needs only an odd number of bytes. Xlib still
reads this form but writes only the X11 form.
Limits and errors
The format sets no maximum size. Xlib rejects a line of 255 characters or more, a missing or zero width or height, a file with no bits array, and an array with too few values or a malformed value.
| Xlib result | Meaning |
|---|---|
BitmapSuccess | the file was read |
BitmapOpenFailed | the file could not be opened |
BitmapFileInvalid | the file is not valid bitmap data |
BitmapNoMemory | not enough memory |
Example
A 10 × 3 image. Row 0 has pixels 0 and 9 set, row 1 is fully set, row 2 has only pixel 1 set. Each row takes 2 bytes:
#define tiny_width 10
#define tiny_height 3
static unsigned char tiny_bits[] = {
0x01, 0x02, 0xff, 0x03, 0x02, 0x00};
| Row | Bytes | Pixels 0 to 9 |
|---|---|---|
| 0 | 0x01, 0x02 | #........# |
| 1 | 0xff, 0x03 | ########## |
| 2 | 0x02, 0x00 | .#........ |
In row 0, 0x02 in the second byte is bit 1, which is pixel 8 + 1 = 9.
The same image in the X10 form is static short tiny_bits[] = { 0x0201, 0x03ff,
0x0002 };.