![891e7361581e4ef91ff011b38378bedc.png](https://img-blog.csdnimg.cn/img_convert/891e7361581e4ef91ff011b38378bedc.png)
BMP文件完全解析
一副平面图像,最终呈现的是一个彩色的二维矩阵,三基色的组合构成了几乎肉眼可见的所有色彩,为了显示彩色矩阵,使用高密度排列的RGB彩色像素组成的屏幕来显示,因此处理器需要知道每一个像素的色彩值,即构成色彩的RGB三原色亮度。不过初期没有彩色显示器,只有电子管做的黑白显示器,它依赖电子管的发射电子的强度定义黑白亮度信息。
色彩空间
![063e30cce6e41070b5aa4c2a7320a324.png](https://img-blog.csdnimg.cn/img_convert/063e30cce6e41070b5aa4c2a7320a324.png)
![6494d63eca865c4d7f9d969d038773c4.png](https://img-blog.csdnimg.cn/img_convert/6494d63eca865c4d7f9d969d038773c4.png)
由于半导体制成的处理器只能处理二进制,所以描述构成图像的像素最终也是二进制形式,一般常用RGB888格式,也就是构成色彩的三基色有8位的分辨率,即256级深度。但是嵌入式平台一般常用RGB565来降低色彩位深来降低存储占用及加速图像显示等。
色彩深度
![05a998c3b76c3529566819d44db9f530.png](https://img-blog.csdnimg.cn/img_convert/05a998c3b76c3529566819d44db9f530.png)
为了描述组成图像的像素色彩信息,需要知道图像的长、宽像素、像素位深等信息,最简单的方法就是将图像所有的像素信息按照行或者列排列方式保存成数组,然后按照图像的信息将数组刷新到屏幕就可以显示图像了,原理和点阵显示字符、汉字很相似,只不过图像是所有的点都需要显示(最方便的就是存储为二维结构,即使不需要边角的图像信息),而点阵字符显示则可能需要跳过一些点。
为了规范图像的信息和像素数据,诞生了不同的图像文件存储格式,常见的如BMP、PNG、JPG、JPEG、GIF等等。
以BMP为例,我们新建一个最最最简单的图片,即仅有一个像素的图片,打开画图工具如下。
![7aff9f0a363604f728cb93fd769f5004.png](https://img-blog.csdnimg.cn/img_convert/7aff9f0a363604f728cb93fd769f5004.png)
将画板放到最大,这样方便绘制。
![87898448cd1b9d51fed5811b1eccbffa.png](https://img-blog.csdnimg.cn/img_convert/87898448cd1b9d51fed5811b1eccbffa.png)
编辑自己的画笔,因为默认的颜色不是纯色,方法如下。
![905dfc3cd8c6e0a059d51164dc65d4c5.png](https://img-blog.csdnimg.cn/img_convert/905dfc3cd8c6e0a059d51164dc65d4c5.png)
使用画笔将画板的一个像素涂成红色,如下。
![9867922d292907c194c193e065f6d7a1.png](https://img-blog.csdnimg.cn/img_convert/9867922d292907c194c193e065f6d7a1.png)
将图片保存成BMP格式。
![f1ea5184d8a0ee3e85b6b52997b0146c.png](https://img-blog.csdnimg.cn/img_convert/f1ea5184d8a0ee3e85b6b52997b0146c.png)
选择默认的24位格式存储。
![d1234b2881ede5fb91005516b212eb34.png](https://img-blog.csdnimg.cn/img_convert/d1234b2881ede5fb91005516b212eb34.png)
使用sublimit打开BMP文件。
![2a33c91c6f7a46fe6c811e17f39b7e68.png](https://img-blog.csdnimg.cn/img_convert/2a33c91c6f7a46fe6c811e17f39b7e68.png)
开头0~1字节42、4d为B、M字符,表示BMP文件,第2~5字节表示整个BMP文件的大小,小端模式,即0x0000003a,58字节,这和文件的详情是一致的。
![6a87f3d56857d662484e5539681b0314.png](https://img-blog.csdnimg.cn/img_convert/6a87f3d56857d662484e5539681b0314.png)
![cf05aa4e3461dc3cf7a286eeb3306492.png](https://img-blog.csdnimg.cn/img_convert/cf05aa4e3461dc3cf7a286eeb3306492.png)
接着6~9字节是保留数据,一般都是0,接着10~13字节表示图片存储的位置(绿色部分),即0x00000036,即第54字节,所以图像像素的存储信息有4字节,54~57字节。
![7444679a2d922a447635634bde57b8bf.png](https://img-blog.csdnimg.cn/img_convert/7444679a2d922a447635634bde57b8bf.png)
接着14~17字节为位图信息数据头,一般是40,即0x00000028。
![6ae85ae17cdeefd252c75205b17bd480.png](https://img-blog.csdnimg.cn/img_convert/6ae85ae17cdeefd252c75205b17bd480.png)
18~21字节表示图像宽度,即0x00000001,22~25字节表示图像高度。
![79515ba4ab9bf7231edcec11fb682391.png](https://img-blog.csdnimg.cn/img_convert/79515ba4ab9bf7231edcec11fb682391.png)
26~27字节表示色彩平面数量,必须为1,即0x0001,28~29字节表示每个像素存储的位数(蓝色部分,0x0018,即24位)。
![546350709fed5235621bc6126cf099e0.png](https://img-blog.csdnimg.cn/img_convert/546350709fed5235621bc6126cf099e0.png)
30~33字节为压缩方式,0表示不压缩,34~37字节表示原始位图数据的大小,即0x00000004,即4字节
![853bbf0cfb481b6146b44b63afba3904.png](https://img-blog.csdnimg.cn/img_convert/853bbf0cfb481b6146b44b63afba3904.png)
38~41字节表示横向分辨率,42~45字节表示纵向分辨率,46~49字节表示调色板颜色数,50~53字节表示重要颜色数,最后的54~57字节(红色部分)即原始的像素数据,这些才是最终需要显示到屏幕上的数据。
可以看到最终的像素数据,即0x000000ff,由于BMP行固定为4字节倍数,所以即便一个像素24位也需要4字节来表示,而最后的一个字节0为填充的空数据,所以这一个像素数据就是0x0000ff,根据小端模式,所以最后的数据为0xff0000,即红色。
同样的,绘制绿色和蓝色的像素结果如下,即0x00ff00和0x0000ff。
![4cad5688ff6ca5697a8af1e5813bc840.png](https://img-blog.csdnimg.cn/img_convert/4cad5688ff6ca5697a8af1e5813bc840.png)
同理显示两个像素,可以看到BMP大小,图像宽度等数据均变化,结果如下。
![22b50bf0706b956e40adafbae1609f1c.png](https://img-blog.csdnimg.cn/img_convert/22b50bf0706b956e40adafbae1609f1c.png)
最终数据也符合预期的结果,同样为了保持4字节对齐,本来2像素*24位=48位/8位=6字节需要增加两个空的字节数据以塞满4字节的倍数空间。
随便打开一个BMP文件,可以看到还是一样的规律,这样只需要按照这个规律就可以解码BMP图片来显示到屏幕上了。有第三方已经编写好了编码、解码库,我们只需要移植好就可以直接使用了,这样就不必关注到底是如何解码图片的了,极大的方便了使用。
欢迎各位仙男仙女提出意见及转发支持哦