正 文

Windows下BMP文件的读取及显示


www.7dspace.com  更新日期:2006-2-6 5:34:59  七度空间


  前言

  BMP文件的读取及显示是一个难度不大而又相当重要的工作。对BMP文件格式已都有详细介绍,本文主要致力于非压缩BMP读取及显示的实践工作,实现了8位及24位BMP文件的读取,并列出解析过程中所遇到的难点。

  bmp文件格式简介:

  1、8位的bmp文件主要有以下三部分依次组成:

  头部信息.

  调色板信息.(按b ,g ,r, reversed 的顺序存放各调色板的颜色信息,共256个)

  主数据区(存放各个像素对应的调色板的序号)

  2、24位的bmp文件主要有以下两部分依次组成.

  头部信息.

  主数据区(按b ,g ,r 的顺序存放各像素的信息)

  3、相关的结构体:

  3.1头部信息结构体:

  a)位图文件头

typedef struct tagBITMAPFILEHEADER { // bmfh
 WORD bfType;
 DWORD bfSize;
 WORD bfReserved1;
 WORD bfReserved2;
 DWORD bfOffBits;
} BITMAPFILEHEADER;

  其中的bfType值应该是“BM”(0x4d42),标志该文件是位图文件。bfSize的值是位图文件的大小

  b)位图信息头

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;

  3.2、调色板数据结构体: (8位中使用)

typedef struct
{
 BYTE b;
 BYTE g;
 BYTE r;
 BYTE reserved;
}paletteRGB;

  3.3、主数据区BGR颜色结构: (24位中使用)

typedef struct
{
 BYTE b;
 BYTE g;
 BYTE r;
}structRGB;

  解析工作:

  1、SetPixel函数

  在windows vc编译环境下,使用sdk编程方式,画像素点的函数为:

COLORREF SetPixel( int x, int y, COLORREF crColor );

  其中,COLORREF类型的颜色值是这样定义的:

crColor=b<<16+g<<8+r;

  或等价于 crColor=b*65536+g*256+r;

  2、Windows环境下扫描行的字节数:

  Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充.这一点相当重要,忽视这点将导致错误发生.

  我的解决方案如下:

externWidth=(mBMFileInfo.bmWidth*mBMFileInfo.bmBitCount)/8;

//计算每行实际的字节宽度

if(externWidth%4!=0)//计算应补足的字节数.
 externWidth=4-externWidth%4;
else
 externWidth=0;

  核心代码:

  这里只列出核以的代码段,详细代码请参阅源码:

//头部解析

void BMParse::showHeadInfo()
{
 assertF(mInputFile!=NULL,"in showHeadInfo,mInputFile is null\n");
 fread(&mBMFileStr,sizeof(BMPFileStr),1,mInputFile);
 fread(&mBMFileInfo,sizeof(BMPFileInfo),1,mInputFile);

 //adjusting

 mWinBMPFileStr.bfType=mBMFileStr.bfType;
 mWinBMPFileStr.bfSize=mBMFileStr.bfSize1+mBMFileStr.bfSize2*65536;
 mWinBMPFileStr.reserved1=mBMFileStr.reserved1;
 mWinBMPFileStr.reserved2=mBMFileStr.reserved2;
 mWinBMPFileStr.bfOffset=mBMFileStr.bfOffset1+mBMFileStr.bfOffset2*65536;
 return;
}

//颜色区(8位的带调色板)解析:

void BMParse::parseBMPMatrix()
{
 if(mWinBMPFileStr.bfType!=19778)
 {
  cout<<"This is not a bmp file"<<endl;
  return;
 }

 if(mBMFileInfo.bmCompression!=0)
 {
  cout<<"File is compressed"<<endl;
  return;
  }

 int i,j;
 structRGB tmpRGB;
 BYTE tmpData;
 int externWidth;
 bmpMatrix=(unsigned long**)malloc(sizeof(unsigned long*)*mBMFileInfo.bmHeight);
 for(i=0;i<mBMFileInfo.bmHeight;i++)
  bmpMatrix[i]=(unsigned long*)malloc(sizeof(unsigned long)*mBMFileInfo.bmWidth);

  //bmp file structure in windows,keep %4==0 in row byte num.

  externWidth=(mBMFileInfo.bmWidth*mBMFileInfo.bmBitCount)/8;
  if(externWidth%4!=0)
   xternWidth=4-externWidth%4;
  else
   externWidth=0;
   switch(mBMFileInfo.bmBitCount)
   {
    case 8: paletteArr=(paletteRGB*)malloc(sizeof(paletteRGB)*256);
    for(i=0;i<256;i++)
    {
      fread(&paletteArr[i],sizeof(paletteRGB),1,mInputFile);
      fseek(mInputFile,1078, SEEK_SET);

      for(j=mBMFileInfo.bmHeight-1;j>=0;j--)
      {
       for(i=0;i<mBMFileInfo.bmWidth;i++)
       {
        fread(&tmpData,sizeof(BYTE),1,mInputFile);
        bmpMatrix[j][i]=((unsigned long)paletteArr[tmpData].b)*65536+((unsignedlong)paletteArr[tmpData].g)*256+(unsigned long)paletteArr[tmpData].r;
       }
       /*补齐位调整*/
       for(i=0;i<externWidth;i++)
       fread(&tmpData,sizeof(BYTE),1,mInputFile);

      }
      break;
     case 16:
      printf("not finished\n");
      break;
     case 24:
      for(j=mBMFileInfo.bmHeight-1;j>=0;j--)
      {
       for(i=0;i<mBMFileInfo.bmWidth;i++)
       {
        fread(&tmpRGB,sizeof(structRGB),1,mInputFile);
        bmpMatrix[j][i]=((unsigned long)tmpRGB.b)*65536+((unsigned long)tmpRGB.g)*256+(unsigned long)tmpRGB.r;
       }
       /*补齐位调整*/
       for(i=0;i<externWidth;i++)
        fread(&tmpData,sizeof(BYTE),1,mInputFile);
      }
      break;
     default: printf("bmBitCount:%d not finished\n",mBMFileInfo.bmBitCount);
     reak;
    }
   }

  //显示程序段:
  void BMParse::showBMP(HDC inHdc)
  {
   int i,j;
   for(j=0;j<mBMFileInfo.bmHeight;j++)
   for(i=0;i<mBMFileInfo.bmWidth;i++)
   {
    SetPixel(inHdc,i,j,bmpMatrix[j][i]);
   }
  }

  实验结论:

  本文对Windows下非压缩8位及24位位图的解析进行了有益的总结并加以实践,有较强的针对性.可以对需要参考的人士起到一定的帮助作用。


上一篇:Word入门动画教程68:旋转或翻转图片
下一篇:常用插件使用不完全攻略
标题:Windows下BMP文件的读取及显示 作者:EmilMatthew 来源:blog
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐