Tricks of the Windows Game Programming Gurus:Advanced DirectDraw and Bitmapped Graphics

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

#### Loading .BMP files

There are a number of ways to read a `.BMP` file—you can write a reader yourself, use a Win32 API function, or a mixture of the two. Because figuring out Win32 functions is usually as hard as writing your own, you might as well write a `.BMP` loader yourself. A `.BMP` file consists of three parts, as shown in Figure 7.23.

Figure 7.23 The structure of a `.BMP` file on disk.

The three parts are as follows:

  Bitmap file header—This holds general information about the bitmap and is contained in the Win32 data structure `BITMAPFILEHEADER`:

      typedef struct tagBITMAPFILEHEADER

              { // bmfh

              WORD    bfType; // Specifies the file type.

                              // Must be 0x4D42 for .BMP

              DWORD   bfSize; // Specifies the size in bytes of

                              // the bitmap file.

              WORD    bfReserved1; //Reserved; must be zero.

              WORD    bfReserved2; // Reserved; must be zero.

              DWORD   bfOffBits;   // Specifies the offset, in

                                   // bytes, from the

                                   // BITMAPFILEHEADER structure

                                   // to the bitmap bits.

              } BITMAPFILEHEADER;

  Bitmap info section—This is composed of two other data structures, the `BITMAPINFOHEADER` section and the palette information (if there is one):

      typedef struct tagBITMAPINFO

              { // bmi

              BITMAPINFOHEADER bmiHeader; // the info header

              RGBQUAD bmiColors[1];  // palette (if there is one)

              } BITMAPINFO;

  And here’s the `BITMAPINFOHEADER` structure:

      typedef struct tagBITMAPINFOHEADER{ // bmih

         DWORD biSize;   // Specifies the number of

                         // bytes required by the structure.

         LONG  biWidth;  // Specifies the width of the bitmap, in pixels.

         LONG  biHeight; // Specifies the height of the bitmap, in pixels.

                         // If biHeight is positive, the bitmap is a

                         // bottom-up DIB and its

                         // origin is the lower left corner

                         // If biHeight is negative, the bitmap

                         // is a top-down DIB and its origin is the upper

                            left corner.

         WORD  biPlanes;   // Specifies the number of color planes, must

                              be 1.

         WORD  biBitCount  // Specifies the number of bits per pixel.

                           // This value must be 1, 4, 8, 16, 24, or 32.

         DWORD biCompression;   // specifies type of compression (advanced)

                                // it will always be

                               // BI_RGB for uncompressed .BMPs

                                // which is what we’re going to use

         DWORD biSizeImage;     // size of image in bytes

         LONG  biXPelsPerMeter; // specifies the number of

                                // pixels per meter in X-axis

         LONG  biYPelsPerMeter; // specifies the number of

                                // pixels per meter in Y-axis

         DWORD biClrUsed;       // specifies the number of

                                // colors used by the bitmap

         DWORD biClrImportant;  // specifies the number of

                                // colors that are important

      } BITMAPINFOHEADER;

  > Note: 8-bit images will usually have the `biClrUsed` and `biClrImportant` fields both set to 256, while 16 and 24-bit images will set them to 0. Hence, always test the `biBitCount` to find out how many bits per pixel are used and go from there.

  Bitmap data area—This is a byte stream that describes the pixels of the image (this may or may not be in compressed form) in 1-, 4-, 8-, 16-, or 24-bit format. The data is in line-by-line order, but it may be upside-down so that the first line of data is the last line of the image, as shown in Figure 7.24. You can detect this by looking at the sign of `biHeight`—a positive sign means the bitmap is upside-down, and a negative sign means the bitmap is normal.

Figure 7.24 The image data in a `.BMP` file is sometimes inverted on the y-axis.

To read a `.BMP` file manually, you first open the file (with any file I/O technique you like) and then read in the `BITMAPFILEHEADER`. Next, read in the `BITMAPINFO` section, which is really just a `BITMAPINFOHEADER` plus palette (if 256 color), so really you’re just reading in the `BITMAPINFOHEADER` structure. From this, you determine the size of the bitmap (`biWidth`, `biHeight`) and its color depth (`biBitCount`, `biClrUsed`). Here you also read in the bitmap data along with the palette (if there is one). Of course, there are a lot of details, such as allocating buffers to read the data and moving file pointers around. Also, the palette entries are `RGBQUAD`, which are in reverse order of normal `PALETTEENTRY`s, so you have to convert them like this:

    typedef struct tagRGBQUAD

            { // rgbq

            BYTE    rgbBlue;     // blue

            BYTE    rgbGreen;    // green

            BYTE    rgbRed;      // red

            BYTE    rgbReserved; // unused

            } RGBQUAD;

Back in Chapter 4, “Windows GDI, Controls, and Last-Minute Gift Ideas,” you may recall the `LoadBitmap()` function that’s used to load bitmap resources from disk. You could use this function, but then you would always have to compile all your game bitmaps into your `.EXE` as a resource. Although this is cool for a complete product, it’s not something you want to do when developing. Basically, you want to be able to tweak your graphics with a paint or modeling program, dump the bitmaps in a directory, and run your game to see what’s up. Hence, you need a more general disk file-based bitmap reading function, which you’ll write in a moment. Before you do, take a look at the Win32 API function to load bitmaps. Run `LoadImage()`:

    HANDLE LoadImage(

      HINSTANCE hinst, // handle of the instance that contains

                       // the image

      LPCTSTR lpszName,  // name or identifier of image

      UINT    uType,     // type of image

      int     cxDesired, // desired width

      int     cyDesired, // desired height

      UINT    fuLoad);   // load flags

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.