天天看点

位图文件(.bmp文件)结构

位图文件结构简单,是数字图像处理时常用的输入和输出数据格式。

位图文件是逐像素保存图像的,一般不压缩。

位图文件由多种色彩模式,现在最常用的是24位真彩色。即用RGB方式来保存像素颜色,每个像素三个字节,每个字节的值表示一种颜色值,范围是0-255,共能表示16777216种颜色。

位图文件分为四部分:

1.位图文件头 占14字节

2.位图信息头 占40字节

3.颜色表 24位真彩色图像没有这部分内容

4.位图数据 存放像素信息

各部分的具体结构:

1.位图文件头:0----13字节

起始字节 所占字节数 具体内容 标志
1 2 文件类型(Windows位图为“BM”) bfType
3 4 文件大小 bfSize
7 4 保留 bfReserved
11 4 第一个位图数据的偏移量(一般为54) bfOffBits

2.位图信息头:14----53字节

起始字节 所占字节数 具体内容 标志
15 4 位图信息的长度(一般为40) biSize
19 4 位图的宽度 biWidth
23 4 位图的高度 biHeight
27 2 位图的位面数(=1) biPlanes
29 2 每个像素所占位数(=24 真彩图) biBitCount
31 4 位图压缩类型(=0 未压缩) biCompression
35 4 图像的大小(以字节为单位,必须是4的倍数) biSizeImage
39 4 位图水平分辨率(像素/米) biXPelsPerMeter
43 4 位图垂直分辨率(像素/米) biYPelsPerMeter
47 4 位图实际使用的颜色数(=0 使用所有颜色) biClrUsed
51 4 指定重要的颜色数(=0 都重要) biClrImportant

3.颜色表:24位真彩色图像没有这部分内容

4.位图数据:

对于24位真彩色图,位图数据存储图像中每个像素的RGB颜色值。一个像素占三个字节,每个字节分别表示RGB三个分量的值。但顺序与通常的恰好相反,为B、G、R。

像素的存放顺序是从图像的最后一行到第一行。每行从左至右。并且,BMP文件采用一种“对齐”机制。即,每行像素所占字节数必须是4的整数倍,如果实际像素所占字数不是4的倍数,则补充空字节,使每行所占的字节数为4的整数倍。下一行像素从空字节后开始存放。例如,图片每行有两个像素,占6字节,则补充2字节的空字节,下一行数据从这2字节后开始存放。实际每行像素占用8字节空间。

了解了这些,就可以将位图读取到程序中。程序中通常用矩阵的形式来保存图像。下面是示例代码:

/*
*变量定义
*/
int flag;		//标志变量
char pic[1000][1000][3];	//存放图像中每个像素的RGB值
char bfType[2];	//存放图像类型标志
struct bf_head	//定义文件信息头结构体
{
	long int bfSize;	//文件大小
	long bfReserved;
	long bfOffBits;		//第一个位图数据的开始字节位置
}bf_h;
struct bi_head			//定义图像信息头结构体
{
	long biSize;	//图像大小
	long biWidth;	//图像宽度
	long biHeight;	//图像高度
	short int biPlanes;		//位图的位面数
	short int biBitCount;	//每个像素所占位数
	long biCompression;		//位图压缩类型
	long biSizeImage;		//图像的大小
	long biXPelsPerMeter;	//位图水平分辨率
	long biYpelsPerMeter;	//位图垂直分辨率
	long biClrUsed;			//位图实际使用的颜色数
	long biClrImportant;	//指定重要的颜色数
}bi_h;

/*
*读取文件
*/
string lpszPathName="name.bmp";//要打开的bmp文件文件名
int x,y,k;	//循环控制变量
FILE *fp=fopen(lpszPathName,"rb");	//以二进制的方式打开文件对话框中的图像
fread(bfType,2,1,fp);	//读取从第1个字节开始的2个字符读一次存入bfType中
if (bfType[0]=='B'&&bfType[1]=='M')	//如果文件类型为“BM”,则该文件时BMP文件
{
	fread(&bf_h,12,1,fp);	//读文件信息头
	fread(&bi_h,40,1,fp);	//读图像信息头
	//在读取像素之前总共读取了54个字节 第55个字节开始为像素字节
	//fread会移动读取文件的指针
	if (bi_h.biBitCount==24)//像素位数等于24,时24位真彩色,可以进行处理
	{
		flag=1;//24位真彩色,标志量赋值
		//图像从最后一行开始存储,因此先读的存在数组后面
		for (y=bi_h.biHeight-1;y>=0;y--)
		{//这层循环次数等于像素行数,也就是图像高度
			for (x=0;x<bi_h.biWidth;x++)
			{
				//行中的像素是从左往右的,x由小到大,与实际的相同
				//这层循环次数等于像素列数,也就是图像宽度
				//分别读(x,y)处像素的RGB三个颜色分量分别存入
				//pic[x][y][0],pic[x][y][1],pic[x][y][2]中
				//文件中颜色值的存放顺序是BGR,所以用倒序来读,保存到数组中就是RGB
				for (k=2;k>=0;k--)
					fread(&pic[y][x][k],1,1,fp);//这里y表示行的下标
			}
			//由于BMP文件的“对齐”机制,每一行像素数据的长度若不是4的倍数,
			//则填充一些数据使它是4的倍数。
			if (((bi_h.biWidth*3)%4)!=0) 
				fseek(fp,4-(bi_h.biWidth*3)%4,1);//跳过无图像数据的字节
		}
	}
}
fclose(fp);
           

继续阅读