Bitmap文件结构探讨

 

BMP位图浅析(从网上找资料总结,文章写得通俗易懂,使大家方便明白bmp结构)
 

BMP文件相关的技术文档,网上可以找到太多了,但这些文档都只适合专业的人去看,所以我写了这篇貌似菜鸟能看懂的文章,但愿它不只是貌似而已。阅读本文前最好先看看《颜色的RGB数字表示方法

什么是位图

计算机能以位图和矢量图格式显示图像。

位图(Bitmap)图像又称点阵图或光栅图,它使用我们称为像素(象素,Pixel)的一格一格的小点来描述图像。计算机屏幕其实就是一张包含大量像素点的网格。当我们把位图放大时,每一个像素小点看上去就像是一个个马赛克色块。

矢量图(Vector)使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等,它们都是通过数学公式计算获得的。

位图和矢量图最简单的区别就是:矢量图可以无限放大,而且不会失真;而位图则不能。

像Photoshop(PS)这样主要用于处理位图的软件,我们称之为图像处理软件;专门处理矢量图的软件,我们称之为图形设计软件,例如Adobe Illustrator,CorelDRAW,Flash MX等。

BMP位图文件

常见的图像文件格式有:BMP、JPG(JPE,JPEG)、GIF等。

BMP图像文件(Bitmap-File)格式是Windows采用的图像文件存储格式,在Windows环境下运行的所有图像处理软件都支持这种格式。Windows 3.0以后的BMP文件都是指设备无关位图(DIB,device-independent bitmap)。BMP位图文件默认的文件扩展名是.BMP,有时它也会以.DIB或.RLE作扩展名。

创建BMP文件

打开Photoshop,新建一个尺寸为2*3像素的文件。

Bitmap文件结构探讨_第1张图片

放大图片到最大(1600%),然后用铅笔工具对每个像素都点一个不同颜色的点,如下图所示。

Bitmap文件结构探讨_第2张图片

储存这个文件为BMP格式,文件名为“MyBmp.bmp”,在BMP选项中选择Windows,24位。

Bitmap文件结构探讨_第3张图片

BMP文件结构

BMP文件由4部分组成:位图文件头(bitmap-file header)

  1. 位图信息头(bitmap-information header)

  2. 颜色表(color table)

  3. 颜色点阵数据(bits data)

24位真彩色位图没有颜色表,所以只有1、2、4这三部分。

用UltraEdit打开MyBmp.bmp,可以看到这个文件的全部数据如下图所示:

位图文件头

其结构定义如下:

typedef struct tagBITMAPFILEHEADER{

 WORDbfType; // 位图文件的类型,必须为BM
DWORD bfSize; // 位图文件的大小,以字节为单位
WORDbfReserved1; // 位图文件保留字,必须为0
WORDbfReserved2; // 位图文件保留字,必须为0
DWORD bfOffBits; // 位图数据的起始位置,以相对于位图
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;

 

位图文件头分4部分,共14字节:

名称 占用空间 内容 实际数据
bfType 2字节 标识,就是“BM”二字 BM
bfSize 4字节 整个BMP文件的大小 0x50(80)
bfReserved1/2 4字节 保留字,没用 0
bfOffBits 4字节 偏移数,即 位图文件头+位图信息头+调色板 的大小 0x36(54)

 

注意,Windows的数据是倒着念的,这是PC电脑的特色。如果一段数据为50 1A 25 3C,倒着念就是3C 25 1A 50,即0x3C251A50。因此,如果bfSize的数据为50 00 00 00,实际上就成了0x00000050,也就是0x50。

位图信息头

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;

 

位图信息头共40字节:

 

名称 占用空间 内容 实际数据
biSize 4字节 位图信息头的大小,为40 0x28(40)
biWidth 4字节 位图的宽度,单位是像素 2
biHeight 4字节 位图的高度,单位是像素 3
biPlanes 2字节 固定值1 1
biBitCount 2字节 每个像素的位数
1-黑白图,4-16色,8-256色,24-真彩色
0x18(24)
biCompression 4字节 压缩方式,BI_RGB(0)为不压缩 0
biSizeImage 4字节 位图全部像素占用的字节数,BI_RGB时可设为0 0x1A
biXPelsPerMeter 4字节 水平分辨率(像素/米) 0xB12(2834)
biYPelsPerMeter 4字节 垂直分辨率(像素/米) 0xB12(2834)
biClrUsed 4字节 位图使用的颜色数
如果为0,则颜色数为2的biBitCount次方
0
biClrImportant 4字节 重要的颜色数,0代表所有颜色都重要 0

 

作为真彩色位图,我们主要关心的是biWidth和biHeight这两个数值,两个数值告诉我们图像的尺寸。biSize,biPlanes,biBitCount这几个数值是固定的。想偷懒的话,其它的数值可以一律用0来填充。

颜色表

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;

24位真彩色位图没有颜色表。要想在Photoshop中创建有颜色表的BMP图像,选择图像>模式>索引颜色;要想查看颜色表,选择图像>模式>颜色表。本文为了简化,只讨论24位真彩色位图。

颜色点阵数据

位图全部的像素,是按照自下向上,自左向右的顺序排列的。

Bitmap文件结构探讨_第4张图片

RGB数据也是倒着念的,原始数据是按B、G、R的顺序排列的。

你应该注意到图中用黑色框起来的00 00了,在每行颜色的末尾添加的两个0字节,是为了行补位。为什么要行补位呢?因为32位的Windows操作系统处理4个字节(32位)的速度比较快,所以BMP的每一行颜色占用的字节数规定为4的整数倍。MyBmp.bmp中一行颜色有两个像素,共占用6字节,如果要补齐4*2=8字节,就要再加两个0字节。

行补位的公式为:widthBytes = (width*biBitCount+31)/32*4

举一个例子,对于2色图,如果图象宽是31,则每一行需要31位存储,合3个字节加7位,因为字节数必须是4的整倍数,所以应该是4,而此时的Width=31,biBitCount=1,widthbytes=4,和我们设想的一样。再举一个256色的例子,如果图象宽是31,则每一行需要31个字节存储,因为字节数必须是4的整倍数,所以应该是32,而此时的Width=31,biBitCount=8,widthbytes=(31*8+31)/32*4=8(取整)*4=32

对于上图的例子中,计算得8,故六个字节后加上两个字节。

 

位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:

当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节;

 

Phtoshop在文件的末尾还补充了两个0字节,好像是要整体补位。不过我看过的BMP资料中都没有提到还要整体补位的,其它软件生成的BMP文件也没有整体补位的,这看起来像是Adobe的独创,不知道目的何在。

Photoshop和Windows的BMP文件比较

用Photoshop保存的MyBmp.bmp:

经Windows画图转存过的BMP文件:

可以看出Windows的BMP文件最后少了两个0字节,没有整体补位。bfSize(文件大小),biSizeImage(全部像素大小)也相应地减去2。

你可能感兴趣的:(C#基础)