首页 > 其他分享 >浅谈图像格式 .bmp

浅谈图像格式 .bmp

时间:2023-08-29 18:46:29浏览次数:45  
标签:图像格式 每行 字节 00 像素 bmp 补零 数据 浅谈

 

云无月 云无月 .NET / Unity3D / Python    

位图(Bitmap)格式其实并不能说是一种很常见的格式(从我们日常的使用频率上来讲,远不如 .jpg .png .gif 等),因为其数据没有经过压缩,或最多只采用行程长度编码(RLE,run-length encoding)来进行轻度的无损数据压缩。以至于,LaTeX 并不能像插入 .jpg 甚至于矢量图那样便捷地插入 BMP 图片,知乎的专栏封面上传也不支持 BMP。

但是,.bmp 仍然发挥着很重要的角色,而且也确实有拿来聊一聊,进而学习一些更深入的知识的意义。正是因为它没有进行数据压缩,其内部存储的色彩信息(灰度图,RGB 或 ARGB)直接以二进制的形式暴露在外,也十分方便借助计算机软件进行简单或深入的分析。那么,今天,我将带领大家从二进制文件的角度,探索 .bmp 格式的奥秘。


文件头

位图格式的文件头长度可变,而且其中参数繁多。但是我们日常生活中遇到的 .bmp 格式图片的文件头长度绝大多数都是 54 字节,其中包括 14 字节的 Bitmap 文件头以及 40 字节的 DIB (Device Independent Bitmap) 数据头,或称位图信息数据头(BItmap Information Header)。其他形式的在此暂不讨论。

以下两张图表大家不必认真观看,因为在后续章节中我们将会针对实际例子,借助十六进制数据和表格进行具体分析。

位图文件头 Bitmap File Header (14 bytes)

 

这是一张汉化版的英文维基百科相关词条(BMP file format - Wikipedia)中的表格。

 

位图信息数据头 DIB Header (54 bytes)

 

对于压缩方式,虽然 Bitmap 格式提供简单的压缩功能,但是绝大多数情况下,并没有采用任何压缩手段。

 

原始位图数据 Raw Bitmap Data

接下来才是重头戏——原始位图数据。拿最常见的 24BPP RGB (24 比特每像素,红绿蓝三通道) 位图来说,每种颜色需要 8 比特,或者说 1 字节,来存储。在二进制文件中,通常情况下,RGB 按照蓝、绿、红的顺序依次表示图片中的像素点,而 RGBA 则按照蓝、绿、红、透明的顺序(从左下开始,横向逐行向上扫描)。特殊时候,也会出现顺序与上述情况不同的特例,这时色彩顺序会写在 DIB Header 的 Bit Fields 中,以不同色彩通道的 Mask 的形式进行规定。由于 BI_BITFIELDS 也是一种压缩方式,而通常 BMP 不采用任何压缩方式,所以绝大多数时候,我们都是按照前面说的顺序进行排序。

关于 Bit Fields,在此贴一张维基百科的图片,便于理解。

这里与别处不同,采用的是 big endian(事实上,整个 BMP 文件中,只有此处使用 big endian。big endian 指的是先出现的数字在高位)。因此,如果 Mask 呈现如下表中的数据:

则由于 Blue 对应数字最大,因此顺序为蓝、绿、红、透明。

数据按照像素行进行包装,便于读取。但是这并不是全部,因为其中还可能会有补零(zero-padding)。这涉及到计算机的数据结构对齐(data structure alignment)的问题。

主流的 CPU 每次从内存中读取并处理数据块(chunk),且通常为 32 比特(4 字节)。因此,为了提升读取效率,位图每行的数据(字节)都需要是 4 的倍数。不可避免地,有些时候每行的结尾就会出现补零(其实补其他任意数字也是可以的,但常见都是补 0)。

对于每行补零的个数,是有计算方法的。公式如下(知乎的 LaTeX 公式不能很好地支持中文,因此无法进行翻译,抱歉):

 

即,每行的字节数等于:每像素比特数乘以图片宽度31 的和除以 32,并向下取整,最后乘以 4

得到了每行的字节数,进而就能够得到原始位图数据,或者说存储图片的所有像素的色彩信息的数据,的大小了:

 

即,原始位图数据大小等于:每行的字节数乘以图像高度(也就是总行数)

再加上之前说的文件头的数据大小(通常为 54 字节),就能够得到文件大小了。

 

实践:文件大小

说完了理论,我们来看一看实际效果吧。

这里有一张 10x10 的 BMP:

在 Windows 画图的保存选项中,选择 24BPP RGB(同时我们也可以看到, .bmp 和 .dib 是等效的):

 

 

从上到下颜色依次为(每种颜色宽度 10 像素,高度 2 像素):

 

  1. 蓝(0,0,255)
  2. 青(0,255,255)
  3. 绿(0,255,0)
  4. 黄(0,255,255)
  5. 红(255,0,0)

首先,我们来计算一下每行的字节数:

 

所以,原始位图数据的大小为:

 

前面已经说过,文件头的大小通常为 54 字节。因此,整个文件的大小应该为:

 

右键查看文件属性:

 

看来我们的计算是完全正确的,的确是 374 字节。

 

 

实践:头文件内容

我们通过查看二进制文件来进一步分析上面这张图。(借助软件 Sublime Text 进行简易的二进制查询)

为了防止在寻找对应数字的时候出现迷惑,我们先来大致理一理基础的进制转换。图中,每个数字都是十六进制,也就是 4 比特。每字节有 8 比特,也就是 2 个十六进制数字。每四个数字分为一组,占 2 字节。因此每行共 16 字节

假如我们想要找第 0x22 (十进制为 34)个字节,方法如下:

首先,找到第三行。因为每行 16 字节,所以在十六进制下的 22,直接看左边第一位数字对应的就是第三行(行号从 0 开始)。然后,开始寻找第三个字节(同样地,列号也从 0 开始)。因此答案是 40。

 

再试一次。假如我们想要找第 0xBC 个字节,方法如下:

 

首先,找到第 12 (B=11)行,然后找第 13 个字节。 不难找到吧?

相信看到这里,大家都已经具备阅读十六进制的能力了。我们现在步入正题。

首先,位图头文件有 14 字节,因此我们先看这一部分(为方便观察,标注了位置数字,并两个数字为一组,为一字节)。

还记得它们分别是什么意思吗?我把图片再贴一遍。

位置 00,尺寸 2,内容 42 4D,也就是 ASCII 表的“BM”两个字母。

 

位置 02,尺寸 4,内容 76 01 00 00,表示文件大小。因为是 little endian(靠前的数字对应低数位),所以实际十六进制数字为 00000176。对应十进制数字为:

 

这与我们先前的计算以及实际答案完全相同。

 

位置 06,尺寸 2,内容 00 00,预留字段,通常为 0。

 

位置 08,尺寸 2,内容 00 00,同上。

 

位置 0A,尺寸 4,内容 36 00 00 00,表示位图数据的开始位置。同样为 little endian,对应十进制数字为 54(这也是文件头的总长度)。

 

然后,再来看 DIB 数据头的 40 字节内容。

 

位置 0E,尺寸 4,内容 28 00 00 00,意思是 DIB header 大小。对应十进制数字为 40 (little endian)。

 

位置 12,尺寸 4,内容 0A 00 00 00,代表图像宽度。对应十进制 10。

位置 16,尺寸 4,内容 0A 00 00 00,代表图像高度,10。

位置 1A,尺寸 2,内容 01 00,表示色彩平面的数量,必须为 1。

位置 1C,尺寸 2,内容 18 00,表示每像素用多少比特来表示。对应十进制 24。

位置 1E,尺寸 4,内容 00 00 00 00,表示采用何种压缩方式。此处为不压缩。

位置 22,尺寸 4,内容 40 01 00 00,表示原始位图数据的大小。对应十进制 320。还记得 little endian 怎么计算吗?

 

剩下的内容我们可以不看,因为几乎用不到,它们也“如我们所愿”,都是 0。



实践:原始位图数据

分析完文件头,剩下的内容就是我们期待已久的,以数组形式排列的所有像素的色彩信息。

大家还记得前面提到过的数据结构对齐吗?如果每像素 24 比特(3 字节),那么总共 10x10 大小的图片,原始位图数据的大小不应该是 300 字节吗?但是实际却是 320 字节。由此可见,每行都有额外的补零。

之前我们已经计算过了,每行字节数为 32 字节。这是一个除不尽 3 的数字。

 

所以,每行有 10 个像素信息(30 字节),外加 2 字节的补零。也就是说,每 32 字节(在下图中正好为两行)中都会有 2 字节的补零。实际是不是这样呢?我们从 0x36 (54)位,也就是原始位图数据的起始位置开始看,每两行都会有用绿色方框括住的 2 字节补零。

然后,从图片的最下面开始看,最先出现的是红色,也就是(255,0,0)。前面已经说过,位图文件中,每像素三种颜色的数据的出现顺序依次为蓝,绿,红。因此红色对应的数据应当为 00 00 FF。不难看出,前 20 个像素点(请注意跳过补零)内容都是 00 00 FF。

下一个颜色为黄色,即 00 FF FF,再之后是绿色,即 00 FF 00……

 

是不是看起来清楚多了?

 

 

最后还有一点想说的,就是并不是所有位图文件都需要补零。我们再来看另外一个例子。这里有一张 1920x1080 尺寸的 BMP(也就是本篇文章的封面图)。经计算:

 

而 5760 是 3 的倍数,因此对于这张图片,就不需要补零了。也就是说,有 1920x1080 个像素点,原始位图数据的大小就正好为

字节。再加上 54 字节的头文件,文件的大小应该为 6,220,854 字节。实际上呢?

 

 

岂不美哉?一丁点字节都不浪费。

 





今天我们就先讲到这里。下次有机会的话,我将为大家展示如何借助 BMP 文件的格式做一些简单有趣的图像处理。

 https://zhuanlan.zhihu.com/p/25119530

标签:图像格式,每行,字节,00,像素,bmp,补零,数据,浅谈
From: https://www.cnblogs.com/jiftle/p/17665614.html

相关文章

  • 浅谈5G技术会给视频监控行业带来的一些变革情况
    5G是第五代移动通信技术,能够提供更高的带宽和更快的传输速度,这将为视频技术的发展带来大量机会。随着5G技术的逐步普及与商用,人们将能够享受到更加流畅的高清视频体验,并且5G技术还拥有更低的延迟和更高的网络容量。这些优势不仅将推动视频技术的变革,也将创造出更多的商业机会和产......
  • 如何批量转换图片格式(jpg,png,gif,bmp),一招教你快速搞定
    工具一.作图狗www.huahaotu.com作图狗是一款非常好用的在线图像批量处理编辑网站,支持将图片批量裁剪、压缩、拼图、转换格式、图片转文字等,还支持给图片添加文字、图片水印,批量处理,节省频繁操作的时间。    工具二:电脑自带工具软件介绍:除了使用其他软件来转换图......
  • BMP图像格式
    BMP图像格式有以下几种通道图像类型1位图像:每个像素使用1比特表示,图像只有黑白两种颜色(通常是黑色和白色)。每个像素的颜色信息存储在位图的颜色表中。4位图像:每个像素使用4比特表示,图像可以有16种颜色。每个像素的颜色信息存储在位图的颜色表中。8位图像:每个像素使用8比特表示,......
  • 浅谈缺一分治
    这个思想好像并不常见,我也是一个月前在lxr讲dp的课上第一次听说这个名字,后来ACM比赛中出了一个gym题,也可以运用相同的思想,但是脑子短路没搞出来,现在随便记一记。缺一分治,顾名思义,就是在题目中有一个位置的限制和其它位置不一样,我们利用分治的思想,枚举每一个位置,然后把\(......
  • 浅谈谷歌优化之“AMP 状态”报告
    报告内容严重问题:受严重AMP问题影响的网页无法在Google上显示。在您的网站上发现的严重问题列表会显示在AMP报告顶级页面中图表的正下方,标题为AMP网页无效的原因。点击该列表中的某个问题可查看包含所选问题的网页。非严重问题(警告):存在非严重问题的AMP网页只要不是同时存在任......
  • 浅谈视频汇聚平台EasyCVR视频平台在城市安全综合监测预警台风天气中的重要作用
    夏日已至,台风和暴雨等极端天气频繁出现。在城市运行过程中,台风所带来的暴雨可能会导致城市内涝等次生灾害,引发交通瘫痪、地铁停运、管网泄漏爆管、路面塌陷、防洪排涝、燃气爆炸、供热安全、管廊安全、消防火灾等安全隐患,影响城市的正常运行,甚至造成人员伤亡。面对台风带来的城市灾......
  • go.mod 浅谈理解
    go.mod对于上次接触golang这门语言还是在上次了,最近对zig比较感兴趣,而突然折腾回golang的时候发现这玩意在1.1.1版本更新了一个叫go.mod的东西。go.mod是Go语言的官方包管理工具,用于解决之前没有地方记录依赖包具体版本的问题,方便依赖包的管理。Go.mod其实就是一个Module......
  • 浅谈LIS
    连续上升子序列(LIS)定义\(一个序列中单调不减的子序列或单调递增的子序列(看题决定,做法几乎一致),下文以严格上升子序列为例\)做法一\(暴力dp,设f_i表示以i结尾的LIS的最长长度,f_i=max(f_j|j<i,a_j<a_i)+1。\)\(dp比较好理解,就是由上一个比当前小的数加上当前的数组成最长上升......
  • 浅谈 Linux 下 vim 的使用
    Vim是从vi发展出来的一个文本编辑器,其代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。Vi是老式的字处理器,功能虽然已经很齐全了,但还有可以进步的地方。Vim可以说是程序开发者的一项很好用的工具。对于大多数用户来说,Vim刚开始学习的时候可能会进......
  • 浅谈视频汇聚平台EasyCVR中AI中台的应用功能
    AI中台是将人工智能技术如深度学习、计算机视觉、知识图谱、自然语言理解等模块化,集约硬件的计算能力、算法的训练能力、模型的部署能力、基础业务的展现能力等人工智能能力,结合中台的数据资源,封装成整体中台系统。在EasyCVR视频共享融合云平台中,AI中台是专门提供人工智能视频......