First of all, XPM isn't all bad. It's very common and well supported in the X world. Also, bitmap means literally a map of bits, in X this is a black/white (0/1 = binary) image called an XBM. What Microsoft calls a bitmap is actually a map of more than bits, it should be called a Pixmap (Pixel Map). X gets this right. What you meant was a binary image format.

The XPM image format uses printable ASCII characters as keys to the color values in the color index. When the number of printable ASCII characters (approx 80) runs out, the amount of characters used per pixel increases.

The total size of the XPM file of dimensions (WIDTH, HEIGHT) using COLS colours can be worked out as follows:

  chars_per_pixel = COLS <= 80? 1 : 2;
  header_size = 32; /* approx */
  color_index_size = (chars_per_pixel + 14) * COLS;
  pixels_size = (chars_per_pixel * WIDTH + 4) * HEIGHT;

  file_size = header_size + color_index_size + pixel_size;

Say you have an image that is 64x64 with 81 colors, the total size is going to be 32 + 1296 + 8448 = 9776 bytes

If you re-indexed the image to 80 colors, the new size would be 32 + 1200 + 4352 = 5584 bytes which is a reduction in size of 43%

Say your sprite engine uses 24 images per character (3 frames for each 8 directions) and 81 colors, the total size for a characters images would be 235Kb. If you were to use a reduced color composite image (ie all of the images for that character in one big file) of dimensions (3 * 64, 8 * 64) = (192, 512), the size would be 32 + 1200 + 100352 = 102Kb or under half the size. Using one index table for all of a characters animation is not only a big win for reducing size, it also reduces the number of system calls to open and read a file, X calls (slow) and pallete calculations to create the Pixmap from 24 down to just 1.

So, if you are making an application using XPM images, make sure you keep your colors below the magic threshold and use composite images.