BITMAP的一些知识

来源:互联网 发布:淘宝白色恋人假货 编辑:程序博客网 时间:2024/05/18 14:23

 

一、BMP文件结构  
   
  BMP文件组成  
  BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。    
  BMP文件头  
  BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。    
  其结构定义如下:  
  typedef   struct   tagBITMAPFILEHEADER  
  {  
  WORDbfType;   //   位图文件的类型,必须为BM  
  DWORD   bfSize;   //   位图文件的大小,以字节为单位    
  WORDbfReserved1;   //   位图文件保留字,必须为0  
  WORDbfReserved2;   //   位图文件保留字,必须为0  
  DWORD   bfOffBits;   //   位图数据的起始位置,以相对于位图  
  //   文件头的偏移量表示,以字节为单位  
  }   BITMAPFILEHEADER;  
   
   
  3.   位图信息头  
   
   
  BMP位图信息头数据用于说明位图的尺寸等信息。  
  typedef   struct   tagBITMAPINFOHEADER{  
  DWORD   biSize;   //   本结构所占用字节数  
  LONGbiWidth;   //   位图的宽度,以像素为单位  
  LONGbiHeight;   //   位图的高度,以像素为单位  
  WORD   biPlanes;   //   目标设备的级别,必须为1  
  WORD   biBitCount//   每个像素所需的位数,必须是1(双色),  
  //   4(16色),8(256色)或24(真彩色)之一  
  DWORD   biCompression;   //   位图压缩类型,必须是   0(不压缩),  
  //   1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一  
  DWORD   biSizeImage;   //   位图的大小,以字节为单位  
  LONGbiXPelsPerMeter;   //   位图水平分辨率,每米像素数  
  LONGbiYPelsPerMeter;   //   位图垂直分辨率,每米像素数  
  DWORD   biClrUsed;//   位图实际使用的颜色表中的颜色数  
  DWORD   biClrImportant;//   位图显示过程中重要的颜色数  
  }   BITMAPINFOHEADER;  
   
   
  4.   颜色表  
   
    颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:  
  typedef   struct   tagRGBQUAD   {  
  BYTErgbBlue;//   蓝色的亮度(值范围为0-255)  
  BYTErgbGreen;   //   绿色的亮度(值范围为0-255)  
  BYTErgbRed;   //   红色的亮度(值范围为0-255)  
  BYTErgbReserved;//   保留,必须为0  
  }   RGBQUAD;  
  颜色表中RGBQUAD结构数据的个数有biBitCount来确定:  
  当biBitCount=1,4,8时,分别有2,16,256个表项;  
  当biBitCount=24时,没有颜色表项。  
  位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:  
  typedef   struct   tagBITMAPINFO   {  
  BITMAPINFOHEADER   bmiHeader;   //   位图信息头  
  RGBQUAD   bmiColors[1];   //   颜色表  
  }   BITMAPINFO;  
   
   
  5.   位图数据  
    位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:  
  当biBitCount=1时,8个像素占1个字节;  
  当biBitCount=4时,2个像素占1个字节;  
  当biBitCount=8时,1个像素占1个字节;  
  当biBitCount=24时,1个像素占3个字节;  
  Windows规定一个扫描行所占的字节数必须是  
  4的倍数(即以long为单位),不足的以0填充,  
  一个扫描行所占的字节数计算方法:  
  DataSizePerLine=   (biWidth*   biBitCount+31)/8;    
  //   一个扫描行所占的字节数  
  DataSizePerLine=   DataSizePerLine/4*4;   //   字节数必须是4的倍数  
  位图数据的大小(不压缩情况下):  
  DataSize=   DataSizePerLine*   biHeight;  

 

 二、BMP位图一般显示方法  
   
  1.   申请内存空间用于存放位图文件  
    GlobalAlloc(GHND,FileLength);  
   
  2.   位图文件读入所申请内存空间中  
       LoadFileToMemory(   mpBitsSrc,mFileName);  
   
  3.   在OnPaint等函数中用创建显示用位图  
    用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容DC,  
    用SelectBitmap()选择显示位图。  
   
  4.   用BitBlt或StretchBlt等函数显示位图  
   
  5.   用DeleteObject()删除所创建的位图  
   
    以上方法的缺点是:   1)显示速度慢;   2)   内存占用大;   3)   位图在缩小显示时图形失真大,(可通过安装字体平滑软件来解决);   4)   在低颜色位数的设备上(如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。  
   
  三、BMP位图缩放显示  
       用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:  
   
  1.   打开视频函数DrawDibOpen(),一般放在在构造函数中  
   
  2.   申请内存空间用于存放位图文件  
    GlobalAlloc(GHND,FileLength);  
   
  3.   位图文件读入所申请内存空间中----    
    LoadFileToMemory(   mpBitsSrc,mFileName);  
   
  4.   在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图  
   
  5.   关闭视频函数DrawDibClose(),一般放在在析构函数中  
   
    以上方法的优点是:   1)显示速度快;   2)   内存占用少;   3)   缩放显示时图形失真小,4)   在低颜色位数的设备上显示高颜色位数的图形图形时失真小;   5)   通过直接处理位图数据,可以制作简单动画。  
   
  四、CViewBimap类编程要点  
   
  1.   在CViewBimap类中添加视频函数等成员  
   
  HDRAWDIB   m_hDrawDib;   //   视频函数  
  HANDLEmhBitsSrc;   //   位图文件句柄(内存)  
  LPSTR   mpBitsSrc;   //   位图文件地址(内存)  
  BITMAPINFOHEADER   *mpBitmapInfo;   //   位图信息头  
   
  2.   在CViewBimap类构造函数中添加打开视频函数  
    m_hDrawDib=   DrawDibOpen();  
   
  3.   在CViewBimap类析构函数中添加关闭视频函数  
   
  if(   m_hDrawDib   !=   NULL)  
  {  
  DrawDibClose(   m_hDrawDib);  
  m_hDrawDib   =   NULL;  
  }  
   
  4.   在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()  
  voidCViewBitmap::OnPaint()  
  {  
  CPaintDC   dc(this);   //   device   context   for   painting  
  GraphicDraw(   );  
  }  
   
  voidCViewBitmap::GraphicDraw(   void   )  
  {  
  CClientDC   dc(this);   //   device   context   for   painting  
  BITMAPFILEHEADER   *pBitmapFileHeader;  
  ULONG   bfoffBits=   0;  
  CPoint   Wid;  
   
  //   图形文件名有效   (=0   BMP)  
  if(   mBitmapFileType   <   ID_BITMAP_BMP   )   return;  
   
  //   图形文件名有效   (=0   BMP)  
  //   准备显示真彩位图  
  pBitmapFileHeader=   (BITMAPFILEHEADER   *)   mpBitsSrc;  
  bfoffBits=   pBitmapFileHeader->bfOffBits;  
   
  //   使用普通函数显示位图  
   
  if(   m_hDrawDib   ==   NULL   ||   mDispMethod   ==   0)  
  {  
  HBITMAP   hBitmap=::CreateDIBitmap(dc.m_hDC,  
  mpBitmapInfo,   CBM_INIT,   mpBitsSrc+bfoffBits,  
  (LPBITMAPINFO)   mpBitmapInfo,DIB_RGB_COLORS);    
  //   建立位图  
  HDC   hMemDC=::CreateCompatibleDC(dc.m_hDC);//   建立内存  
  HBITMAP   hBitmapOld=   SelectBitmap(hMemDC,   hBitmap);   //   选择对象  
  //   成员CRect   mDispR用于指示图形显示区域的大小.  
  //   成员CPoint   mPos用于指示图形显示起始位置坐标.  
  if(   mPos.x   >   (mpBitmapInfo-   >biWidth   -   mDispR.Width()   ))  
  mPos.x=   mpBitmapInfo->biWidth   -   mDispR.Width()   ;  
  if(   mPos.y   >   (mpBitmapInfo-   >biHeight-   mDispR.Height()))  
  mPos.y=   mpBitmapInfo-   >biHeight-   mDispR.Height();  
  if(   mPos.x   <   0   )   mPos.x=   0;  
  if(   mPos.y   <   0   )   mPos.y=   0;  
   
  if(   mFullViewTog   ==   0)  
  {  
  //   显示真彩位图  
  ::BitBlt(dc.m_hDC,0,0,   mDispR.Width(),   mDispR.Height(),  
  hMemDC,mPos.x,mPos.y,   SRCCOPY);  
  }   else   {  
  ::StretchBlt(dc.m_hDC,0,0,   mDispR.Width(),   mDispR.Height(),  
  hMemDC,0,0,   mpBitmapInfo-   >biWidth,   mpBitmapInfo-  
  >biHeight,   SRCCOPY);  
  }  
  //   结束显示真彩位图  
  ::DeleteObject(SelectObject(hMemDC,hBitmapOld));    
  //   删   除   位   图  
  }   else   {  
   
  //   使用视频函数显示位图  
   
  if(   mPos.x   >   (mpBitmapInfo-   >biWidth   -   mDispR.Width()   ))  
  mPos.x=   mpBitmapInfo-   >biWidth   -   mDispR.Width()   ;  
  if(   mPos.y   >   (mpBitmapInfo-   >biHeight-   mDispR.Height()))  
  mPos.y=   mpBitmapInfo-   >biHeight-   mDispR.Height();  
  if(   mPos.x   <   0   )   mPos.x=   0;  
  if(   mPos.y   <   0   )   mPos.y=   0;  
   
  //   显示真彩位图  
  DrawDibRealize(   m_hDrawDib,   dc.GetSafeHdc(),   TRUE);  
   
  if(   mFullViewTog   ==   0)  
  {  
  Wid.x=   mDispR.Width();  
  Wid.y=   mDispR.Height();  
  //   1:1   显示时,   不能大于图形大小  
  if(   Wid.x   >   mpBitmapInfo-   >biWidth   )  
  Wid.x   =   mpBitmapInfo-   >biWidth;  
  if(   Wid.y   >   mpBitmapInfo-   >biHeight)  
  Wid.y   =   mpBitmapInfo-   >biHeight;  
   
  DrawDibDraw(   m_hDrawDib,   dc.GetSafeHdc()  
  ,   0,   0,   Wid.x,   Wid.y,  
  mpBitmapInfo,   (LPVOID)   (mpBitsSrc+bfoffBits),  
  mPos.x,   mPos.y,   Wid.x,   Wid.y,   DDF_BACKGROUNDPAL);  
  }   else   {  
  DrawDibDraw(   m_hDrawDib,   dc.GetSafeHdc(),  
  0,   0,   mDispR.Width(),   mDispR.Height(),  
  mpBitmapInfo,   (LPVOID)   (mpBitsSrc+bfoffBits),  
  0,   0,   mpBitmapInfo-   >biWidth,   mpBitmapInfo-   >biHeight,  
  DDF_BACKGROUNDPAL);  
  }  
  }  
  return;  
  }  

 

  五、使用CViewBimap类显示BMP位图  
    1.   在Visual   C++5.0中新建一个名称为mymap工程文件,类型为MFC   AppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。  
   
  2.   在Visual   C++5.0中点击下拉式菜单Project-   >Add   To   project-   >Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。  
   
  3.   在Visual   C++5.0中按Ctrl_W进入MFC   ClassWizard,选择类名称为CMainFrame,ObjectIDs:   ID_VIEW_BITMAP,Messages选择Command,然后点击Add   Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在Member   functions:   中点击OnViewBimap条目,点击Edit   Code按钮编辑程序代码。代码如下:  
   
  void   CMainFrame::OnViewBitmap()  
  {  
  //   TODO:   Add   your   command   handler   code   here  
  CViewBitmap   *pViewBitmap=   NULL;  
   
  pViewBitmap=   new   CViewBitmap(   "BITMAP.BMP",   this);  
  pViewBitmap-   >ShowWindow(   TRUE);  
  }  
   
  并在该程序的头部添加#include   "bitmap0.h",然后编译运行。  
   
  4.   找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。  
   
  5.   运行时,点击下拉式菜单“查看(V)-   >ViewBitmap”(英文版为View-   >   ViewBitmap)即可显示BITMAP.BMP位图。  
   
  六、CViewBimap类功能说明  
   
  1.   在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。  
   
  2.   在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区小,则对位图放大;   如果位图比客户区大,则对位图缩小。  
   
  3.   支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区,就可以显示该位图。  
   
    程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图放大时两者差别不大,但在位图缩小时,两者差别明显;   使用视频函数时位图失真小,显示速度快。  
    还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可以体会到使用视频函数的优越性了吧。  
    在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示程序中加以适当调整即可,读者可自行完成。  

 

在Windows系统中,以BMP   为扩展名的文件都是DIB文件,保存于磁盘中的DIB文件由4部分所组成:位图文件头、位图信息头、颜色表项和位图图象数据。管理位图文件头、位图信息头、颜色表项的3个结构分别为   BITMAPFILEHEADER,BITMAPINFOHEADER,和RGBQUAD,其中RGBQUAD和BITMAPINFOHEADER结构又可以通过BITMAPINFO来组合。图1-1   展示了DIB文件的数据组织        
    &#172;  
  BITMAPFILEHEADER结构的定义如下  
    typedef     struct     tag   BITMAPFILEHEADER{  
  WORD bfType;  
  DWORD bfSize;  
  WORD bfReserved1;  
  WORD bfReserved2;  
  DWORD bfOffBits;  
  }BITMAPFILEHEADER;  
  其中bfType说明文件为一个位图文件,表示位图的ASCII码为BM,其16进制表示为0x4D42。bfSize   表示以字节为单位的文件大小。bfReserved1和bfReserved2一般不采用,其值均为0。BfOffBits表示从位图文件头开始到位图数据段的字节总数,即字节偏移量。  
  BITMAPINFOHEADER结构的定义如下:  
  typedef     struct     tag   BITMAPINFOHEADER{  
                  DWORD biSize;  
                  DWORD biWidth;  
                  DWORD biHeight;  
                  WORD       biPlanes;  
                  WORD       biBitCount;  
      DWORD biCompression;  
  DWORD biSizeImage;  
  DWORD biXPelsPerMeter;  
  DWORD biYPelsPerMeter;  
  DWORD             biClrUsed;  
  DWORD biClrImportant;  
  }BITMAPINFODEADER;          
    其中,biSize   表示该结构的大小。biWidth   表示以像素为单位的位图宽度。biHeight表示相应的高度,biPlanes   表示目标设备的位平面数,置为1。biBitCount   表示位图每个像素的位数,可能为1、4、8、或24。iCompression   表示位图的被压缩类型。若位图未被压缩,则该值为0;若为1,则表示采用RLE(Run   Length   Encoded)8压缩;若位2,则表示采用RLE4压缩。biSizeImage   表示被压缩位图的字节数。biXPelsPerMeter   表示目标设备的水平分辨率,biYPelsPerMeter表示目标设备的垂直分辨率。biClrUsed   表示位图实际使用的颜色数。biClrImportant   指对于显示该位图比较重要的颜色索引的个数,若该值尾0,则表示所有的颜色都是重要的。  
    RGBQUAD结构的定义如下:  
      typedef     struct       tagRGBQUAD{  
  BYTE             rgbBLUE;  
  BYTE             rgbGREEN;  
  BYTE         rbgRED;  
  BYTE             rgbReserved;  
  }RGBQUAD;      
  其中,rgbBLUE、   rgbGREEN、rbgRED分别表示蓝、绿、红分量;rgbReserved的值为0。  
      BITMAPINFO结构把BITMAPINFOHEADER结构和一张颜色表结合在一起,其定义如下:  
      tyepdef       struct       tagBITMAPINFO{    
  BITMAPINFOHEADER         bmiHeader;  
  RGBQUAD                               bmiColors[1];  
  }BITMAPINFO;  
  事实上,只有1、4、8位位图才有颜色表项。24位位图没有颜色表项,位图头信息后紧跟位图数据。   
 

原创粉丝点击