BMP   F ile   F ormat

BMP (BitMaP) files, sometimes called DIBs for (Device Independent Bitmap) are the Microsoft Windows native graphic format. They are not intended for transfer through the internet and are not recognized by HTML. Most BMPs are not compressed and the format is really quite simple. There are a few wrinkles.
  1. Each scan line of image data is padded to the next four byte boundary.
  2. Scan lines are stored bottom to top instead of top to bottom.
  3. BMPs can be 1 bit, 4 bit, 8 bit or 24 bit.
  4. RGB values are stored backwards i.e. BGR.

  1. line_length=(((byte_width-1)/4)+1)*4; Calclulates the line length to the next four byte boundary. Where byte_width can be the ceiling of image_width/8 or image_width/2 for 1 & 4 bit BMPS respectively, or image_width for 8 bit BMPS, or 3*image_width for 24 bit BMPS.
  2. y=image_height-line_no-1; Finds the correct position to display a line.
  3. 1, 4 & 8 bit BMPs require a color map, where each entry in the map has three values for the RGB values of one of the colors used in the image plus an extra byte that serves no purpose other than to waste space. An 8 bit BMP has a maximum of 256 entries in the color map and each byte in the image data is an index into the color map. A 4 bit BMP has a maximum of 16 entries in the color map and each byte in the image data holds two indices into the color map for two contiguous pixels. The upper nibble for the first pixel and the the lower nibble for the second pixel. Find the first index by shifting the index byte right four bits (rgb_table_index>>4) and the second index by masking the index bytes left four bits (rgb_table_index&0x0f). A 1 bit (monchrome) BMP has 2 entries in the color map and each byte in the image data holds 8 indices into the color map for 8 contiguous pixels. Each bit represents a pixel. 24 bit BMPs do not require a color map and each set of three bytes gives the RGB values of a pixel.
4 bit & 8 bit BMPs can be compressed. BMPs use a very simple form of compression called Run Length Encoded (RLE). Instead of storing a value for each pixel RLE stores a number, N, followed by an index. This means that the next N pixels are of the color for this index. This works very well for the type of pictures that are normally drawn with Window's Paint Brush which usually have large blocks of a single color. It would not work well at all for continuous tone images like scanned photographs.

For example a checkerboard could be encoded

      10 B 10 W
      10 B 10 W
      10 B 10 W
      10 B 10 W
      10 B 10 W
      10 B 10 W
      10 B 10 W
      10 B 10 W
      10 B 10 W
      10 B 10 W
      10 W 10 B
      10 W 10 B
      10 W 10 B
      10 W 10 B
      10 W 10 B
      10 W 10 B
      10 W 10 B
      10 W 10 B
      10 W 10 B

      instead of

      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      B B B B B B B B B B W W W W W W W W W W
      W W W W W W W W W W B B B B B B B B B B
      W W W W W W W W W W B B B B B B B B B B
      W W W W W W W W W W B B B B B B B B B B
      W W W W W W W W W W B B B B B B B B B B
      W W W W W W W W W W B B B B B B B B B B
      W W W W W W W W W W B B B B B B B B B B
      W W W W W W W W W W B B B B B B B B B B
      W W W W W W W W W W B B B B B B B B B B
      
A BMP file consists of the four following parts:
  1. BITMAPFILEHEADER
  2. BITMAPINFOHEADER
  3. A color table of RGBQUAD structures (1, 4 & 8 bit only)
  4. An array of bytes for the actual image data
The following structures definitions are taken form the windows.h file that comes with Visual C++.
typedef struct tagBITMAPFILEHEADER {    /* bmfh */
    UINT    bfType;
    DWORD   bfSize;
    UINT    bfReserved1;
    UINT    bfReserved2;
    DWORD   bfOffBits;
    } BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {    /* bmih */
    DWORD   biSize;
    LONG    biWidth;
    LONG    biHeight;
    WORD    biPlanes;
    WORD    biBitCount;
    DWORD   biCompression;
    DWORD   biSizeImage;
    LONG    biXPelsPerMeter;
    LONG    biYPelsPerMeter;
    DWORD   biClrUsed;
    DWORD   biClrImportant;
    } BITMAPINFOHEADER;


typedef struct tagRGBQUAD {     /* rgbq */
    BYTE    rgbBlue;
    BYTE    rgbGreen;
    BYTE    rgbRed;
    BYTE    rgbReserved;
    } RGBQUAD;
      
The following is a description of the above structures.

  1. BITMAPFILEHEADER
    1. bfType
      • Declared an unsigned integer. But, this is just to reserve space for 2 bytes. The 2 bytes must be the 2 characters BM to indicate a BitMap file.
    2. bfSize
      • Total size of file in bytes.
    3. bfReserved1
      • Always zero (ignore).
    4. bfReserved2
      • Always zero (ignore).
    5. bfOffBits
      • Specifies the byte offset from the BITMAPFILEHEADER structure to the actual bitmap data in the file.

  2. BITMAPINFOHEADER
    1. biSize
      • Size of BITMAPINFOHEADER structure (should always be 40).
    2. biWidth
      • Width of image in pixels.
    3. biHeight
      • Height of image in pixels.
    4. biPlanes
      • Always one (ignore).
    5. biBitCount
      • Specifies the number of bits per pixel. This value must be 1, 4, 8, or 24.
    6. biCompression
      • Specifies the type of compression.
        1. BI_RGB No compression.
        2. BI_RLE8 8 bit RLE
        3. BI_RLE4 4 bit RLE
    7. biSizeImage
      • Specifies the size, in bytes, of the image data. May be zero if the bitmap is in the BI_RGB format.
    8. biXPelsPerMeter
      • Ignore.
    9. biYPelsPerMeter
      • Ignore.
    10. biClrUsed
      • Specifies the number of color indices in the color table. Zero indicaes the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member e.g. 8 bit -> 256 colors.

        The maximum number of colors = 2N. Where N = biBitCount. 2N is the same as 1 << N. The same as you can get powers of 10 by shifting the decimal point in a decimal number, only it is binary.

    11. biClrImportant
      • Ignore.

  3. A color table of RGBQUAD structures (1, 4 & 8 bit only)

  4. An array of bytes for the actual image data
The following description of BMP Run Length Encoded compression for 8 bit images comes from the Visual C++ help files.

"BI_RLE8

When the biCompression member is set to BI_RLE8, the bitmap is compressed using a run-length encoding format for an 8-bit bitmap. This format may be compressed in either of two modes: encoded and absolute. Both modes can occur anywhere throughout a single bitmap. Encoded mode consists of two bytes: the first byte specifies the number of consecutive pixels to be drawn using the color index contained in the second byte. In addition, the first byte of the pair can be set to zero to indicate an escape that denotes an end of line, end of bitmap, or a delta. The interpretation of the escape depends on the value of the second byte of the pair. The following list shows the meaning of the second byte:

Value   Meaning

0       End of line.
1       End of bitmap.
2       Delta. The two bytes following the
	escape contain unsigned values
	indicating the horizontal and vertical
	offset of the next pixel from the
	current position.
Absolute mode is signaled by the first byte set to zero and the second byte set to a value between 0x03 and 0xFF. In absolute mode, the second byte represents the number of bytes that follow, each of which contains the color index of a single pixel. When the second byte is set to 2 or less, the escape has the same meaning as in encoded mode. In absolute mode, each run must be aligned on a word boundary. The following example shows the hexadecimal values of an 8-bit compressed bitmap:
03 04 05 06 00 03 45 56 67 00 02 78 00 02 05 01
02 78 00 00 09 1E 00 01
This bitmap would expand as follows (two-digit values represent a color index for a single pixel):
04 04 04
06 06 06 06 06
45 56 67
78 78
move current position 5 right and 1 down
78 78
end of line
1E 1E 1E 1E 1E 1E 1E 1E 1E
end of RLE bitmap"

To display an image with VGA 256 color mode the 256 DAC (Digital to Analog Converter) registers must be loaded with the RGB values from the color map. Once the color map is loaded you can poke the color map indices into the video segment (0XA000) at the offset given by y*screen_width+x where x & y are the column & row for the pixel.

Note: The DAC registers are only 6 bits and the RGB values must be shifted right 2 bits before being loaded into the DAC registers.

I have C source code for a simple program to display BMP files. This simple program can only display 8 bit BMP files (compressed or non-compressed). It does not check to see if the pixels are on the screen before displaying them, so it may cause a problem if the image is larger than 320 x 200 pixels.

This code uses three include files for some in-line assembly functions needed for displaying the pixels. If you know a little about the EGA/VGA BIOS and 8086 assembly language these functions should be easy to program.

PC Intern By Michael Tischer, Published by Abacus is an excellent book on DOS system programming, and explains how to program such functions.

Or, for a nominal fee, you can buy my source code on my Shareware & Freeware page, which includes the needed include files.

Click here for bmpvu.c you can save it to your hard disk from your browsers file menu.


Return to Image Compression Formats Page
Return to My Home Page