BMP图片信息数据解析示例

BMP (Bitmap)文件格式也就是位图

下面我用一张 1位的图片来研究BMP文件的数据格式,找到对应信息,初学,如有错误请指出谢谢。

1、文件信息(14字节)

typedef struct tag_bitmap_file_header{
	unsigned short 		file_type;//文件类型,BMP 文件值固定为 0x4D42,存储为小端模式,转换成 ASCII 就是 “BM”
	unsigned int 		file_size;//整个文件的大小,以字节为单位
	unsigned short 		reserved1;//保留
	unsigned short 		reserved2;//保留
	unsigned int 		offset_bits;//位图数据在文件中的偏移值,等于 “文件信息+位图信息+调色板信息”
} __attribute__((packed)) bitmap_file_header;

这个结构体的大小固定为 14 个字节

一个字节等于二进制位的8位。short 占 2个字节,int 占4个字节,char 1个。在我的图片数据上找位置如下:

文件大小 0x50=80字节和图片符合, 数据位置在0x3E=62

2、位图信息 (40字节)

typedef struct tag_bitmap_info_header {
	unsigned int 		bitmap_info_size;//位图信息的大小,固定为 40
	int 				bitmap_width;//位图宽度
	int 				bitmap_height;//位图高度,影响位图数据的存储方式。值为正数时,从位图数据的最后一行开始保存,也就是文件位图数据的第一行是图片数据的最后一行,这种存储方式支持压缩。值为负数时,文件位图数据的第一行就是图片数据的第一行
	unsigned short 		planes;//位图的位面数,固定为 1
	unsigned short 		image_depth;//位图的图像深度,(1,4,8,16,24,32)表示位图数据中,几个二进制位表示一个像素点,如 8 bits 表示,8 个二进制位表示一个像素点
	unsigned int 		compression;//位图压缩类型,必须是 0(BI_RGB 不压缩 ),  1(BI_RLE8 压缩类型 ),2(BI_RLE4压缩类型)
	unsigned int 		image_size;//位图的数据大小
	int 				x_pels_permeter;//指定位图目标设备的水平打印分辨率,表示水平方向每米的像素点数量,可以是 0
	int 				y_pels_permeter;//指定位图目标设备的垂直打印分辨率,表示垂直方向每米的像素点数量,可以是 0
	unsigned int 		color_used;//位图实际使用的颜色表中的颜色所有数,为0使用所有调色板项
	unsigned int 		color_important;
} __attribute__((packed)) bitmap_info_header;//重要的颜色数量,值通常等于 color_used,值为 0 时表示所有颜色都重要

 这个结构体的大小固定为 40 个字节

大小 0x28 = 40   宽度 0x21=33  高度 0x02=2   位深 0x01=1 符合(两行结束和开头的黄色框是一起的)

3、调色板信息 (xx字节)

typedef struct tag_bitmap_palette {
	unsigned char 		blue;//该颜色的蓝色分量
	unsigned char 		green;//该颜色的绿色分量
	unsigned char 		red;//该颜色的红色分量
	unsigned char 		reserved;//保留字节
} __attribute__((packed)) bitmap_palette;

这个结构体的大小固定为 4 个字节。

可选,调色板就是索引与其对应的颜色的映射表。当小于等于8bit 时,必带有调色板信息,数据存的是颜色值对应调色板颜色的索引值。bmp 1位 数据存的是调色板的索引值,超过8位存的是数据。

这张图片存2个颜色,索引0 位置 为 #ffffff ,索引1 为#000000

4、位图数据 (xx字节)

BMP文件存储位图数据时,图像的扫描方式是在行内按从左到右扫描、在行间从下到上扫描的顺序。Windows规定图像文件中,一个图像的扫描行所占的字节数必须是4的倍数(即以字为单位),不足的以0填充

色深1位,8个像素占1个字节; (11111111)

色深4位,2个像素占1个字节; (1111)(0000)

色深8位,1个像素占1个字节; 

色深24位,1个像素占3个字节; 

      对于BMP等位图来说,要求是4字节对齐,即每行字节数必须为4的整数倍,因此满足以4字节为对齐单位向下对齐,所以每行字节数为:(8Bit = 1Byte)

  ulong rows_len = (((biWidth * biBitCount) / 8 + 3) / 4) * 4

 当BMP图位宽不足 8 时,多个像素才占用 1Byte,因此可以将除8外移,同时因为字节数必须为4的整数倍,3 * 8需变成31,则行字节数为:

ulong rows_len = (((biWidth * biBitCount)  + 31) / 32) * 4 或

ulong rows_len = ((biWidth*biBitCount + 31) >>5)<<2;

所以 扫描行实际长度(包含填充)rows_len = 8,开始找数据位置:

 62开始,图片是从下往上扫描,所以红色框是图片第二行的数据,黄色框是第一行的数据,最后补齐两字节。(色深为1-8 数据存的是调色板的索引,超过存的是实际颜色数据,注意调色板存的顺序是 bgr  例如取数据bgr时顺序别用反)

色深位1 ,宽高:33*2 == 66像素 ,1像素点占1个二进制位位,以一行为例:

00 00 ff ff 80 00 00 00

00000000 00000000 11111111 11111111 10000000 00000000 0000000 00000000

00000000 00000000 11111111 11111111 1 这33位是数据,对应的调色板索引,所以图片是从白到黑色,如下图:

参考:https://blog.youkuaiyun.com/u012313335/article/details/80432155

https://blog.youkuaiyun.com/lk_luck/article/details/115122351

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值