BMP位图文件格式详解及编程建议

BMP文件渊源流长,虽然对JPG、PNG等格式图像文件来说,确实有点土,但是毕竟BMP文件格式相对简单,容易理解,至于BMP众多的位图格式也不能责怪微软,主要是早期谁也没料到图片技术会发展的这么快,而且每次升级还要兼容,所以只能如此了(有点麻烦但并不复杂)。
BMP位图文件的结构主要由:BMP文件头、位图信息头、颜色表和图形数据四个部分组成,对于24位、32位则没有色彩表字段,低位图则存在色彩索引表。
一、BMP的文件头结构
BMP文件头数据结构包含有BMP文件类型标志、文件大小和位图数据的起始位置等信息。
其结构定义如下:
typedef strUCt tagBITMAPFILEHEADER
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1; // 保留字,必须为0
WORD bfReserved2; // 保留字,必须为0
DWORD bfOffBits;
} BITMAPFILEHEADER;
bfType——为位图文件类型,必须为BM,转化为十六进制码就是0x4d42(小端约定,关于大端和小端概念请参考稍后的天缘文章)
bfSize——位图文件的大小,以字节为单位,表示整个bmp文件的大小,包括2个头段和位图数据区,计算方法如下:
sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER)+ (biWidth* biBitCount+31)/8*biHeight
可能很多网友对公式中的后半段很疑惑,为什么那样计算数据区的大小,这是因为Windows还规定图像文件中一个扫描行所占的字节数必须是4的倍数,不足部分要以0填充,所以数据区的大小不能使用简单的(biWidth*biBitCount*biHeight)/8计算总字节数,而应当折算每行的BIT数,分子中的加31(因为4字节补齐就是32位补齐)就是为了防止一个扫描行多一位或少一位而做的进位(+31)取整(/8)操作。
bfOffBits—— 位图数据的起始位置,也就是数据区的起始位置,基点是位图数据区相对文件头部的偏移量,单位为字节。
二、BMP位图信息头结构
BMP位图信息头结构主要用于说明位图的尺寸、压缩类型等重要信息。其结构如下:
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; //本结构所占字节数,实际上该结构占用40个字节,但Windows每次还是需要您亲自添上
LONG biWidth; //位图的宽度,单位为像素
LONG biHeight; //位图的高度,单位为像素
WORD biPlanes; //目标设备的平面数,约定必须为1
WORD biBitCount//每个像素所需的位数,必须是1(双色)、 4(16色)、8(256色)、24(真彩色)或32(32位真彩)之一
DWORD biCompression; //位图压缩类型,必须是0(不压缩)、1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORD biSizeImage; //位图的大小,以字节为单位,对于BI_RGB必须设置为0,对于压缩文件请参考MSDN
LONG biXPelsPerMeter; //水平分辨率,每米像素数,一般不用关心,设为0
LONG biYPelsPerMeter; //垂直分辨率,每米像素数,一般不用关心,设为0
DWORD biClrUsed;//位图实际使用的颜色表中的颜色数,一般不用关心,设为0
DWORD biClrImportant;//位图显示过程中重要的颜色数,一般不用关心,设为0
} BITMAPINFOHEADER;该结构占据40个字节。
三、BMP的调色板结构,或叫色彩表
这一项在网络上很多文章没有提及,或只说到调色板的概念,主要是因为现在使用颜色表的BMP(24真彩以下的图片很少的缘故),这里介绍一下,颜色表表示BMP文件的DIB(device-independent bitmap)尺寸和颜色信息。结构定义如下:
typedef struct _BITMAPCOREINFO {
BITMAPCOREHEADER bmciHeader; //见下面的结构定义
RGBTRIPLE bmciColors[1]; //见下面的结构定义
} BITMAPCOREINFO;
BITMAPCOREHEADER的定义如下:
typedef struct tagBITMAPCOREHEADER { // bmch
DWORD bcSize; //表示本结构的占用字节数
WORD bcWidth; //位图的宽度
WORD bcHeight; //位图的高度
WORD bcPlanes; //设备平面数,设为1
WORD bcBitCount; //每像素位数,比如为1、4、8、24,实际上最后的24似乎没用,当然也可以使用程序约定使用。
} BITMAPCOREHEADER
RGBTRIPLE的结构定义如下:
typedef struct tagRGBTRIPLE { // rgbt
BYTE rgbtBlue; //蓝色
BYTE rgbtGreen; //绿色
BYTE rgbtRed; //红色
} RGBTRIPLE
四、BMP的位图数据区
提到位图数据区,肯定要涉及到颜色表的概念,颜色表用于说明位图中的颜色,按照位图的像素划分,每一个像素用一个RGBQUAD结构表示一种颜色。RGBQUAD结构的定义如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue;//蓝色
BYTE rgbGreen; // 绿色
BYTE rgbRed; // 红色
BYTE rgbReserved;// 保留
} RGBQUAD;
根据天缘的认识,该结构只是在程序处理时候用得着,随意你怎么解释都可以,只要不把RGB颜色倒反即可。位图信息头和颜色表组成位图信息区,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位图信息头
RGBQUAD bmiColors[1]; // 颜色表
} BITMAPINFO;
结构体里头的RGBQUAD项就是真实的颜色表,大小根据实际情况确定。
颜色表的结构来也很简单,就是使用RGB三色调和最终的位图颜色信息。至于最终实际使用多少字节的RGBQUAD数据还需要由biBitCount决定,所以,并不是上述结构中使用BYTE来定义就表示一定占用四字节。天缘说明如下:
1、当biBitCount=1时,8个像素占1个字节,每个像素智能用一BIT来表示,颜色只能有两种1或0,也就是双色,具体颜色需查色彩表。
2、当biBitCount=4时,2个像素占1个字节,每个像素占半个字节(4位),可能颜色有2^4=16种,也就是16色,具体颜色需查色彩表。
3、当biBitCount=8时,1个像素占1个字节,可能颜色有2^8=256种,也就是256色,具体颜色需查色彩表。
4、当biBitCount=16时,1个像素占2个字节,可能颜色有2^16=65536种,也就是64K,具体颜色需查色彩表。
5、当biBitCount=24时,1个像素占3个字节,可能颜色有2^24=16777216,这么多颜色如果是写色彩表就需要占用至少16M,全宇宙肯定不同意的,所以干脆就拿每个字节表示一种颜色,正好三个字节RGB,“非常6+1”。
6、当biBitCount=32时,1个像素占4个字节,这在网上很多文章中都没有提到,只说到24位,32位真彩就是原来的rgbReserved使用上,作为透明度标示。理解方法同24位,加上Reserved保留的透明度,具体颜色天缘暂时还算不出来。
编程建议(面向数据处理):
1、BMP文件的读取提取到二维数组,对于使用C/C++、VC++的朋友,有现成DIB派生类可以参考,GOOGLE一下即可。
2、对于BMP文件的普通读取、绘图有很多现成的系统函数可供调用,天缘不再细说,比如CreateDIBitmap、CreateCompatibleDC、BitBlt、StretchBlt等等。
2、BMP文件的写操作只需要按照上述的BMP文件格式,把BMP文件头、信息表及位图数据区按照顺序写成BMP文件即可。
http://www.metsky.com/archives/198.html
JPG格式与bmp格式的具体区别是什么?
数据存储格式不一样,具体看看他们的资料吧!
JPG也好,bmp也好,都是一种保存成文件的格式,而不是真正电脑处理的格式。

电脑处理的就是DIB,设备无关位图,不管是什么格式,打开文件的时候就应该转换为DIB来处理了。其实,bmp格式就是直接保存的DIB格式

灰度化,二值化,滤波处理都是针对dib格式,是在内存中处理,不是在磁盘上直接对文件处理。bmp,jpg只是保存的格式不同,当然jpg有压缩,bmp没压缩,最后保存的时候肯定不会一模一样.
将24位位图转换8位位图

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值