Chinaunix首页 | 论坛 | 博客
  • 博客访问: 106505
  • 博文数量: 46
  • 博客积分: 1920
  • 博客等级: 上尉
  • 技术积分: 355
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-29 14:33
文章分类
文章存档

2011年(1)

2010年(24)

2009年(21)

我的朋友

分类: 嵌入式

2010-01-20 17:22:09


 前几天花了些时间学习研究了下BMP文件结构,对BMP的文件结构有了大致的了解。本以为可以解决问题,但结果却还徒劳。在此记录下BMP文件结构,也算前几天的总结。
BMP文件准确的来说是由四个部分组成的,BMP文件头,BMP信息头,调色板和颜色数据区。
1、文件头(BITMAPFILEHEADER)
view plaincopy to clipboardprint?
typedef   struct   tagBITMAPFILEHEADER   {       
   WORD   bfType;              //类型,BMP为0x4D42  
   DWORD  bfSize;//整个文件的大小,可以由BMP文件头,BMP信息头,调色板大小和数据区大小相+得出  
    WORD         bfReserved1;      //保留字,置为0  
   WORD         bfReserved2;      //保留字,置为0  
   DWORD       bfOffBits;           //整个头大小,BMP文件头,BMP信息头和调色板大小相+得到  
} BITMAPFILEHEADER,   *PBITMAPFILEHEADER; 
  typedef   struct   tagBITMAPFILEHEADER   {    
     WORD   bfType;              //类型,BMP为0x4D42
     DWORD  bfSize;//整个文件的大小,可以由BMP文件头,BMP信息头,调色板大小和数据区大小相+得出
      WORD         bfReserved1;      //保留字,置为0
     WORD         bfReserved2;      //保留字,置为0
     DWORD       bfOffBits;           //整个头大小,BMP文件头,BMP信息头和调色板大小相+得到
  } BITMAPFILEHEADER,   *PBITMAPFILEHEADER;
sizeof(BITMAPFILEHEADER) = 14 Byte;
虽然根据字节对齐原则应该是16Byte,但是如果有看过这个结构定义的话,就应该知道,这个结构在定义的时候取消了自动对齐。(定义开始时候先#include然后结束后再#include
2、信息头(BITMAPINFOHEADER)
 
view plaincopy to clipboardprint?
typedef   struct   tagBITMAPINFOHEADER{     
    DWORD   biSize;// 本结构所占用字节数                               
    LONG    biWidth;// 位图的宽度,以像素为单位                      
 
    LONG    biHeight; //   位图的高度,以像素为单位                      
    WORD   biPlanes; //   目标设备的级别,必须为1     
    WORD   biBitCount; // 每个像素所需的位数,必须是1(双色),                                                        
                       //   4(16色),8(256色)或24(真彩色)之一     
    DWORD   biCompression; //   位图压缩类型,必须是   0(不压缩),            
                          //   1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一     
    DWORD   biSizeImage; //   位图的大小,以字节为单位                       
 
    LONG    biXPelsPerMeter;//   位图水平分辨率,每米像素数                    
    LONG    biYPelsPerMeter;//   位图垂直分辨率,每米像素数     
    DWORD   biClrUsed; //   位图实际使用的颜色表中的颜色数     
    DWORD   biClrImportant;//   位图显示过程中重要的颜色数     
}   BITMAPINFOHEADER; 
  typedef   struct   tagBITMAPINFOHEADER{  
      DWORD   biSize;// 本结构所占用字节数                            
      LONG    biWidth;// 位图的宽度,以像素为单位                   
      LONG    biHeight; //   位图的高度,以像素为单位                   
      WORD   biPlanes; //   目标设备的级别,必须为1  
      WORD   biBitCount; // 每个像素所需的位数,必须是1(双色),                                                     
                         //   4(16色),8(256色)或24(真彩色)之一  
      DWORD   biCompression; //   位图压缩类型,必须是   0(不压缩),         
                            //   1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一  
      DWORD   biSizeImage; //   位图的大小,以字节为单位                    
      LONG    biXPelsPerMeter;//   位图水平分辨率,每米像素数                 
      LONG    biYPelsPerMeter;//   位图垂直分辨率,每米像素数  
      DWORD   biClrUsed; //   位图实际使用的颜色表中的颜色数  
      DWORD   biClrImportant;//   位图显示过程中重要的颜色数  
  }   BITMAPINFOHEADER;
BITMAPINFOHEADER结构中,结构大小(biSize)、位图宽度(biWidth)、高度(biHeight)、位图色深(biBitCount)、压缩类型(biCompression)、位图大小(biSizeImage)都需要设置正确。
这里,计算数据区文件大小的时候感觉需要注意的。位图是按像素点来保存的,而且一般来说,数据记录顺序是在扫描行内是从左到右,扫描行之间是从下到上,即数据区是从下往上存的,保存在数据区最前部的是最后一行的像素颜色数据,而在最后的是第一行像素颜色值。根据规定,每行数据要4字节对齐,即不是4字节倍数的要补足四字节。每行数据量可以根据如下公式:
DWORD DataSizePerLine = (biWidth * biBitCount + 8 * biBitCount - 1) / (8 * biBitCount); //每行实际数据量的大小
           DataSizePerLine  =  DataSizeLine % 4 ? (DataSizeLine / 4 * 4 + 4) : DataSieLine;  //4字节对齐
位图数据区总数据量为:
              DWORD DataSize   =  DataSizeLine * biHeight;
3、调色板结构(RGBQUAD)
view plaincopy to clipboardprint?
  typedef struct tagRGBQUAD {  
      BYTE rgbBlue;          // 蓝色的亮度(值范围为0-255)  
      BYTE rgbGreen;       // 绿色的亮度(值范围为0-255)  
      BYTE rgbRed;          // 红色的亮度(值范围为0-255)  
      BYTE rgbReserved;  // 保留,必须为0  
  } RGBQUAD; 
  typedef struct tagRGBQUAD {
      BYTE rgbBlue;          // 蓝色的亮度(值范围为0-255)
      BYTE rgbGreen;       // 绿色的亮度(值范围为0-255)
      BYTE rgbRed;          // 红色的亮度(值范围为0-255)
      BYTE rgbReserved;  // 保留,必须为0
  } RGBQUAD;
颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。
双色(biBitCount=1)、16色(biBitCount=4)、256色(biBitCount=8)使用的是调色板的颜色,数据区使用的是调色板的索引值。当为真彩色以上时(即biBitcount >= 24),位图是不用调色板的。在真彩色中都是直接使用位图数据来保存真实的颜色值,而不使用调色板的索引值。
这里用双色的举个例子。因为是双色的,所以有两个调色板项(2^1)。即RGBQUAD rgbquad[2];定义两种颜色。如果是16色(2^4)那么就有16项,即rgbquad[16];
4、位图数据BMPDATA
  当biBitCount=1时,8个像素占1个字节;
  当biBitCount=4时,2个像素占1个字节;
  当biBitCount=8时,1个像素占1个字节;
  当biBitCount=24时,1个像素占3个字节;
数据区域最主要的还是填充位置和值。8bit色深及以下的是使用调色板的索引值。所以当biBitCount=1时,数据区的值就只有2种,即调色板的下标。
而当biBitCount=24时候,保存的便是RGB的颜色值了,3种颜色,每种颜色各占一个字节。
位图数据区还有一个需要注意的就是上面所说的像素位置问题:数据记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。这个问题解决了,那么就可以自由填充颜色了。
 
 
阅读(886) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~