Examples of Bitmap Headers

To give you some idea about what to expect when looking at bitmap headers, we'll take a look at three typical ones. We'll start with one of the least complex (Microsoft Windows Bitmap), and proceed to two that are more complex (Sun Raster and Kofax raster).

To do this, we'll provide a C data structure, which will provide an idea of the size and relative position of each field in the headers.

Example 1: Microsoft Windows Bitmap Version 1.x Format Header

//
// Header structure for the MS Windows 1.x Bitmap Format
//    a BYTE is an unsigned char
//    a WORD is an unsigned short int (16-bits)
//
typedef struct _WinHeader1x
{
//
//  Type    Name        Offset   Comment
//
    WORD    Type;       /* 00h   File Type Identifier (always 0)  */
    WORD    Width;      /* 02h   Width of Bitmap in Pixels        */
    WORD    Height;     /* 04h   Height of Bitmap in Scan-lines   */
    WORD    Width;      /* 06h   Width of Bitmap in Bytes         */
    BYTE    Planes;     /* 08h   Number of Color Planes           */
    BYTE    BitsPixel;  /* 09h   Number of Bits Per Pixel         */
} OLDWINHEAD;

As you can see from the comments, this particular header contains a file identification value, the width and height of the image, the width of a single line of the image (in bytes), the number of color planes, and the number of bits per pixel. This information is close to the bare minimum required to describe a bitmap image so it can be read and rendered in an arbitrary environment.

Note that the Windows 1.x header contains no information about color or image data compression. A more advanced image format will have provisions for both color information and at least a simple compression scheme. An example of a more elaborate header is that found in the Sun Raster image file format shown in the next example:

Example 2: Sun Raster Format Header

//
// Header structure for the Sun Raster Image File Format
//  a WORD here is an unsigned long int (32 bits)
//
typedef struct _SunRasterHead
{
//
//  Type   Name        Offset   Comment
//
    WORD   Magic;      /* 00h   Magic Number (59a66a95h)      */
    WORD   Width;      /* 04h   Width of Image in Pixels      */
    WORD   Height;     /* 08h   Height of Image in Pixels     */
    WORD   Depth;      /* 0Ch   Number of Bits Per Pixel      */
    WORD   Length;     /* 10h   Length of Image in Bytes      */
    WORD   Type;       /* 14h   File Format Encoding Type     */
    WORD   MapType;    /* 18h   Type of Color Map             */
    WORD   MapLength;  /* 1Ch   Length of Color Map in Bytes  */
} SUNRASHEAD;

The Sun Raster header contains information similar to the Windows 1.x bitmap header illustrated above. But note that it also contains fields for the type of data encoding method and the type and size of the color map or palette associated with the bitmap data.

Neither of the two headers mentioned above contains a text description field. One such header that does is that associated with the Kofax Image File Format shown in Example 3.

Example 3: Kofax Raster Format Header

//
//  Header structure for the Kofax Raster Image File Format
//    a LONG is a signed long int (32 bits)
//    a SHORT is a signed short int (16 bits)
//
typedef struct _KofaxHeader
{
//
//  Type    Name             Offset   Comment
//
    LONG    Magic;           /* 00h   Magic Number (68464B2Eh)     */
    SHORT   HeaderSize;      /* 04h   Header Size                  */
    SHORT   HeaderVersion;   /* 06h   Header Version Number        */
    LONG    ImageId;         /* 0Ah   Image Identification Number  */
    SHORT   Width;           /* 0Ch   Image Width in Bytes         */
    SHORT   Length;          /* 0Eh   Image Length in Scan-lines   */
    SHORT   Format;          /* 10h   Image Data Code (Encoding)   */
    CHAR    Bitsex;          /* 11h   Non-zero if Bitsex Reversed  */
    CHAR    Color;           /* 12h   Non-zero if Color Inverted   */
    SHORT   Xres;            /* 14h   Horizontal Dots Per Inch     */
    SHORT   Yres;            /* 16h   Vertical Dots Per Inch       */
    CHAR    Planes;          /* 18h   Number of Planes             */
    CHAR    BitsPerPixel;    /* 19h   Number of Bits Per Pixel     */
    SHORT   PaperSize;       /* 1Ah   Original Paper Size          */
    CHAR    Reserved1[20];   /* 1Ch   20-byte Reserved Field       */
    LONG    Dcreated;        /* 30h   Date Created                 */
    LONG    Dmodified;       /* 34h   Date Modified                */
    LONG    Daccessed;       /* 38h   Date Accessed                */
    CHAR    Reserved2[4];    /* 3Ch   4-Byte Reserved Field        */
    LONG    Ioffset;         /* 40h   Index Text Info Offset       */
    LONG    Ilength;         /* 44h   Index Text Info Length       */
    LONG    Coffset;         /* 48h   Comment Text Offset          */
    LONG    Clength;         /* 4Ch   Comment Text Length in Bytes */
    LONG    Uoffset;         /* 50h   User Data Offset             */
    LONG    Ulength;         /* 54h   User Data Length in Bytes    */
    LONG    Doffset;         /* 58h   Image Data Offset            */
    LONG    Dlength;         /* 5Ch   Image Data Length in Bytes   */
    CHAR    Reserved3[32];   /* 60h   32-byte Reserved Field       */
} KFXHEAD;

Note that the Kofax header is considerably larger than either the Windows bitmap or Sun raster headers. Included are fields which describe the horizontal and vertical resolution, paper size of the image subject, offset values of different types of data stored in the file, and the time and date that the image was created, last modified, and accessed.

Also note the appearance of several fields marked reserved. The Kofax format header is intentionally padded to 128 bytes to accommodate common read and write buffer sizes. It uses only 72 bytes of the header in the revision presented here, but is padded to 128 bytes. The Kofax format specification promises that the first 128 bytes of every Kofax image file will be the header, regardless of future revisions. Applications are thus free to ignore the reserved data, and the format is presumably designed to allow this without dire penalty. See the general discussion of reserved fields in the section called "Unused Space" earlier in this chapter.

Optimizing Header Reading

Header reading speed can be optimized by looking at the ways in which your application uses the data, because reading the header data can usually be performed in several ways. If only selected values in the header are needed, the application can calculate the offset of the data from some key landmark such as the start of the file. The application can then seek directly to the data value required and read the data value. The offset values appearing in the comments in the header examples above can be used as offset arguments for the seek function used.

If most of the data contained in the header is needed by the application, then it may be more convenient to read the entire header into a buffer or pre-allocated data structure. This can be performed quickly, taking advantage of any efficiencies provided by an integral-power-of-two block reads, as mentioned above. All of the header data will be available in memory and can be cached for use when needed. One problem, however, occurs when the byte order of the file is different from the native byte order of the system on which the file is being read. Most block read functions, for example, are not designed to supply automatic conversion of data. Another problem may arise when data structures are padded by the compiler or runtime environment for purposes of data member alignment. These problems and others are discussed in more detail in Chapter 6, Platform Dependencies.



Copyright © 1996, 1994 O'Reilly & Associates, Inc. All Rights Reserved.