Bitmap位图格式探究

 

 前几天花了些时间学习研究了下BMP文件结构,对BMP的文件结构有了大致的了解。本以为可以解决问题,但结果却还徒劳。在此记录下BMP文件结构,也算前几天的总结。

BMP文件准确的来说是由四个部分组成的,BMP文件头,BMP信息头,调色板和颜色数据区。

1、文件头(BITMAPFILEHEADER)

  1. typedef   struct   tagBITMAPFILEHEADER   {       
  2.    WORD   bfType;              //类型,BMP为0x4D42   
  3.    DWORD  bfSize;//整个文件的大小,可以由BMP文件头,BMP信息头,调色板大小和数据区大小相+得出   
  4.     WORD         bfReserved1;      //保留字,置为0   
  5.    WORD         bfReserved2;      //保留字,置为0   
  6.    DWORD       bfOffBits;           //整个头大小,BMP文件头,BMP信息头和调色板大小相+得到   
  7. } BITMAPFILEHEADER,   *PBITMAPFILEHEADER;  

sizeof(BITMAPFILEHEADER) = 14 Byte;

虽然根据字节对齐原则应该是16Byte,但是如果有看过这个结构定义的话,就应该知道,这个结构在定义的时候取消了自动对齐。(定义开始时候先#include<pshpack2.h>然后结束后再#include<popack.h>)

2、信息头(BITMAPINFOHEADER)

 

  1. typedef   struct   tagBITMAPINFOHEADER{     
  2.     DWORD   biSize;// 本结构所占用字节数                                
  3.     LONG    biWidth;// 位图的宽度,以像素为单位                       
  4.   
  5.     LONG    biHeight; //   位图的高度,以像素为单位                       
  6.     WORD   biPlanes; //   目标设备的级别,必须为1      
  7.     WORD   biBitCount; // 每个像素所需的位数,必须是1(双色),                                                         
  8.                        //   4(16色),8(256色)或24(真彩色)之一      
  9.     DWORD   biCompression; //   位图压缩类型,必须是   0(不压缩),             
  10.                           //   1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一      
  11.     DWORD   biSizeImage; //   位图的大小,以字节为单位                        
  12.   
  13.     LONG    biXPelsPerMeter;//   位图水平分辨率,每米像素数                     
  14.     LONG    biYPelsPerMeter;//   位图垂直分辨率,每米像素数      
  15.     DWORD   biClrUsed; //   位图实际使用的颜色表中的颜色数      
  16.     DWORD   biClrImportant;//   位图显示过程中重要的颜色数      
  17. }   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)

  1.   typedef struct tagRGBQUAD {  
  2.       BYTE rgbBlue;          // 蓝色的亮度(值范围为0-255)   
  3.       BYTE rgbGreen;       // 绿色的亮度(值范围为0-255)   
  4.       BYTE rgbRed;          // 红色的亮度(值范围为0-255)   
  5.       BYTE rgbReserved;  // 保留,必须为0   
  6.   } 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种颜色,每种颜色各占一个字节。

位图数据区还有一个需要注意的就是上面所说的像素位置问题:数据记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。这个问题解决了,那么就可以自由填充颜色了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值