Chapter 7.Working with Bitmaps

Working with Bitmaps

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;

typedef struct tagBITMAPINFO
        { // bmi
        BITMAPINFOHEADER bmiHeader; // the info header
        RGBQUAD bmiColors[1];  // palette (if there is one)
        } BITMAPINFO;

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.

    the palette entries are RGBQUAD, which are in reverse order of normal PALETTEENTRYs, 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;
HANDLE LoadImage(	// A Win32 function
  HINSTANCE hinst, // handle of the instance that contains
                   // the image: Set it to NULL 
  LPCTSTR lpszName,  // name or identifier of image: ANDRE.BMP
  UINT    uType,     // type of image:  IMAGE_BITMAP
  int     cxDesired, // desired width: 如果不为零,则缩放,推荐0
  int     cyDesired, // desired height
  UINT    fuLoad );  // load flags:LR_LOADFROMFILE | LR_CREATEDIBSECTION

自己写的函数:

typedef struct BITMAP_FILE_TAG
        {
        BITMAPFILEHEADER bitmapfileheader;  // this contains the
                                            // bitmapfile header
        BITMAPINFOHEADER bitmapinfoheader;  // this is all the info
                                            // including the palette
        PALETTEENTRY     palette[256];// we will store the palette here
        UCHAR            *buffer;    // this is a pointer to the data

        } BITMAP_FILE, *BITMAP_FILE_PTR;

int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
{
// this function opens a bitmap file and loads the data into bitmap

int file_handle,  // the file handle
    index;        // looping index

UCHAR   *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
OFSTRUCT file_data;          // the file data information

// open the file if it exists
if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
   return(0);

// now load the bitmap file header
_lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));

// test if this is a bitmap file
if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
   {
   // close the file
   _lclose(file_handle);

   // return error
   return(0);
   } // end if

// now we know this is a bitmap, so read in all the sections
// first the bitmap infoheader

// now load the bitmap file header
_lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));

// now load the color palette if there is one
if (bitmap->bitmapinfoheader.biBitCount == 8)
   {
   _lread(file_handle, &bitmap->palette,
          MAX_COLORS_PALETTE*sizeof(PALETTEENTRY));

   // now set all the flags in the palette correctly
   // and fix the reversed
   // BGR RGBQUAD data format
   for (index=0; index < MAX_COLORS_PALETTE; index++)
       {
       // reverse the red and green fields
       int temp_color                = bitmap->palette[index].peRed;
       bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
       bitmap->palette[index].peBlue = temp_color;

       // always set the flags word to this
       bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
       } // end for index

    } // end if

// finally the image data itself
_lseek(file_handle,
       -(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);

// now read in the image

if (bitmap->bitmapinfoheader.biBitCount==8 ||
    bitmap->bitmapinfoheader.biBitCount==16 ||
    bitmap->bitmapinfoheader.biBitCount==24)
   {
   // delete the last image if there was one
   if (bitmap->buffer)
       free(bitmap->buffer);

   // allocate the memory for the image
   if (!(bitmap->buffer =
       (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
      {
      // close the file
      _lclose(file_handle);

      // return error
      return(0);
      } // end if

   // now read it in
   _lread(file_handle,bitmap->buffer,
          bitmap->bitmapinfoheader.biSizeImage);

   } // end if
else
   {
   // serious problem
   return(0);

   } // end else

// close the file
_lclose(file_handle);

// flip the bitmap
Flip_Bitmap(bitmap->buffer,
            bitmap->bitmapinfoheader.biWidth*
            (bitmap->bitmapinfoheader.biBitCount/8),
            bitmap->bitmapinfoheader.biHeight);

// return success
return(1);

} // end Load_Bitmap_File

int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
{
// this function is used to flip bottom-up .BMP images

UCHAR *buffer; // used to perform the image processing
int index; // looping index

// allocate the temporary buffer
if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
return(0);

// copy image to work area
memcpy(buffer,image,bytes_per_line*height);

// flip vertically
for (index=0; index < height; index++)
memcpy(&image[((height-1) - index)*bytes_per_line],
&buffer[index*bytes_per_line], bytes_per_line);

// release the memory
free(buffer);

// return success
return(1);

} // end Flip_Bitmap

int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
{
// this function releases all memory associated with "bitmap"
if (bitmap->buffer)
{
// release memory
free(bitmap->buffer);

// reset pointer
bitmap->buffer = NULL;

} // end if

// return success
return(1);

} // end Unload_Bitmap_File

    1.Regardless of the image format, the buffer that holds the image UCHAR buffer is just a byte pointer, so you must do any casting or pointer arithmetic if the image is 16- or 24-bit.
    2. the function allocates a buffer for the image, so the buffer must be released back to the operating system when you're done mucking with the image bits.

 

载入8位位图:使用该位图自己的调色板

BITMAP_FILE bitmap; // holds the 8-bit image

// given that the 8-bit image has been loaded

if (FAILED(lpddpal->SetEntries(0,0,MAX_COLORS_PALETTE,
   
bitmap.palette)))
{ /* error */ }

载入16位位图

    very few paint programs can generate 16-bit .BMP files, so if you want to use a 16-bit DirectDraw mode, you may have to load a 24-bit bitmap and then manually convert the bits to 16-bit by using a color-scaling algorithm. In general, you would perform the following operations to convert a 24-bit image to a 16-bit image:

  1. Create a buffer that's mxn WORDs, where each WORD is 16-bit. This will hold your 16-bit final image.

  2. Access the image buffer after loading the 24-bit image into your BITMAP_FILE structure, and convert each 24-bit pixel to 16-bit by using the following crude color transform:

    // each pixel in BITMAP_FILE.buffer[] is encoded as 3-bytes
    // in BGR order, or BLUE, GREEN, RED
    
    // assuming index is pointing to the next pixel...
    UCHAR blue  = (bitmap.buffer[index*3 + 0]) >> 3,
          green = (bitmap.buffer[index*3 + 1]) >> 2,
          red   = (bitmap.buffer[index*3 + 2]) >> 3;
    // build up 16 bit color word
    USHORT color = __RGB16BIT565(red,green,blue);

载入24位位图

    Then BITMAP_FILE.buffer[] will hold the data in 3-byte pixels left to right, row by row, but in BGR (blue, green, red) format

// each pixel in BITMAP_FILE.buffer[] is encoded as 3-bytes
// in BGR order, or BLUE, GREEN, RED

// assuming index is pointing to the next pixel...
UCHAR blue  = (bitmap.buffer[index*3 + 0]),
      green = (bitmap.buffer[index*3 + 1]),
      red   = (bitmap.buffer[index*3 + 2]);

// this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)
_RGB32BIT(0,red,green,blue);
// this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)
#define _RGB32BIT(a,r,g,b)  ((B) + ((g) << 8) + ((r) << 16) + ((a) << 24))
 
 

 

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值