http://www.360doc.com/content/10/1107/14/1188581_67355279.shtml

调色板

当bpp小于等于8时,BMP使用调色板记录色彩信息,调色板中每条数据(即每种色彩值)都是一个uint型数据。当调色板存在时,图像数据块中存 储的只是各个像素的色彩在调色板中的索引值,必须通过在调色板中查表,才能获知各个像素的真实颜色。若引入调色板,则调色板数据块紧随在图像参数数据块之 后。

当bpp == 1时,调色板合法索引值只有0和1。因此调色板中只有2个色彩值,分别表示索引值为0和1时的色彩信息。

当bpp == 4或bpp == 8时,合法索引值范围扩大为[0,15]和[0,255]。但图像中不一定使用到了全部16种或256种颜色。第47-50字节存储的uint型数据指出 图像中实际应用的色彩数,也即调色板中的色彩值数目。当然,它不应超出调色板的合法索引值的范围。

当bpp == 4或bpp == 8时,可以采用Run-Length-Encoding方式压缩图像的存储空间,即压缩方式选项的值为1或2(当选项值为0时,不压缩)。这种编码格式所 考虑的情况是,若4bpp或8bpp位图的尺寸较大时,由于色彩总数非常有限,所以图像中必然会有很多颜色重复的像素。因此BMP图像格式的设计者决定采 取一个简单的措施来挽回一些被浪费掉的存储空间。这个简单的措施就是RLE压缩方法。

RLE, Run-Length-Encoding

如果你是一个有优化癖的程序员,当你发现一张8bpp、宽300像素的位图中有一行像素只有两种颜色:前100个像素是红色,后200个像素是蓝 色,然而你的位图却忠实地用100字节来存储前半行重复的红色,又用200字节来存储后半行重复的蓝色,那么你一定会抓狂到大骂BMP格式的设计者是白 痴。

为了避免被骂,BMP格式的设计者想出了这样的办法:先用一个字节来存储重复色彩的数量,再用一个字节来存储这个色彩的值,即用两个字节代表一段颜 色重复的像素。并且,他们给重复色彩的数量起了个名字,叫做Run-Length,可能是因为只有在运行时我们才能知道这段重复色彩的长度。由于 runlength为0时没有意义,因此设计者把runlength=0当做每行的终止符。于是,同样存储一行300个像素,原先需要300字节,现在只 用5个字节就搞定!

字节

1

2

3

4

5

内容

100

red

200

blue

0

由于你是一个有着严重优化癖的程序员,所以你对这样粗制滥造的优化方法并不满足,因为你很快发现,如果一张位图中没有连续重复的像素(例如红蓝像素 点阵),那么用刚才发明的这个办法存储300个像素,居然要用601字节!当然,这种情况下最好的办法是不用压缩算法。可是,如果既有重复像素,又有点阵 的情况呢?比如前150像素是重复的绿色,后150像素是红蓝相间的像素点阵。

为了满足你变态的优化癖,BMP格式的设计者只好继续发展这个算法。首先,他们保留了“用一个字节来存储重复色彩的数量,再用一个字节来存储这个色 彩的值”的设计思路,然后修改了runlength为0的含义。设计者规定,当遇到runlength==0时,我们要继续读取下一个字节,若该字节值为 n,意味着后面的n个像素将采用“逐字翻译”的方式来解析,也就是说,这n个像素的前面没有runlength这个字节。用这种方法压缩“前150像素是 重复的绿色,后150像素是红蓝相间的像素点阵”的300个像素,只需要154个字节。

字节

1

2

3

4

后150个字节

内容

150

green

0

150

red,blue,…,red,blue

这个近似完美的结果中有个小问题:设计BMP格式的天才们把runlength==0的含义修改后,我们就没有行终结符了。不过天才终归是天才,他 们发现“逐字翻译”的像素数必须大于2才有意义(想想这是为什么?),因此runlength==0之后的那个字节的值为0、1或2时,目前还没有意义。 于是天才们规定,当这个值为0时,表示行结束符;当这个值为1时,表示文件结束符;当这个值为2时,似乎仍然没有什么意义;只有当该值大于等于3时,才是 “逐字翻译”。完整的压缩结果是:

字节

1

2

3

4

后150个字节

155

156

内容

150

green

0

150

red,blue,…,red,blue

0

0

这就是传说中的Run-Length-Encoding for 8bpp。4bpp的RLE跟8bpp时没有本质差别。

RGBBit-Fields

当图像中引用的色彩超过256种时,我们就需要16bpp或更高bpp的位图。调色板不适合bpp较大的位图,因此16bpp以上的位图都不使用调色板。不使用调色板的位图图像有两种编码格式:RGB和Bit-Fields(下称BF)。

RGB编码格式是一种均分的思想,使Red、Green、Blue三个颜色分量所包含的信息容量尽可能一样大。

16bpp-RGB:在每个像素所占的16bits中,低5位表示Blue分量;中5为表示Green分量;高5位表示Red分量;最高1位无意义 (后来有些应用程序将其视为透明度Alpha分量,但这并不是标准)。所以从低到高的顺序实际上是B-G-R,这也是我在BMP简介的表格里,把RGB的 编码方式都写成BGR的原因。

24bpp-RGB:24bpp的位图又称为真彩位图,它通常只有这一种编码格式,在24bits中,低8位表示Blue分量;中8为表示Green分量;高8位表示Red分量。

32bpp-RGB:在32bits中,低24位的编码方式与24bpp位图相同,最高8位用来表示透明度Alpha分量。32bpp的位图尺寸太大,一般只有在图像处理的中间过程中使用。对于需要半透过效果的图像,更好的选择是PNG格式。

BF编码格式与RGB不同,它利用位域操作,人为地确定RGB三分量所包含的信息容量。在图像参数信息模块的介绍中提及,当压缩方式选项置为BF 时,图像参数结构体将比平时多出16字节。这16字节实际上是4个dword的位域掩码。按照先后顺序,它们分别是R、G、B、A四个分量的位域掩码。当 然如果没有Alpha分量,则Alpha掩码没有实际意义。

位域掩码的作用是:指出像素色彩值中RGB分量,就像子网掩码指出子网网段一样。

16bpp-BF-565:这是BF编码格式最著名和最普遍的应用。它的Red、Green和Blue分量的位域掩码分别是0xF800、0x07E0和0x001F。

我们平时所能够见到的位图中使用BF编码格式的并不多,因为它看上去比较麻烦,而效果也不见得比RGB要好(你能用肉眼分辨出16bpp-RGB和16bpp-BF-565之间的区别吗?)。

BF编码格式的重要应用在于游戏软件。游戏软件通常包含数量庞大的小尺寸图片。如果一张图片中几乎没有Blue分量,那么使用16bpp-RGB格 式显然会浪费掉B分量所占的5位。此时若采用16bpp-BF-772格式,只给B分量2位,那么R与G分量都拥有7位的容量,几乎接近真彩图像。因此存 储空间小、仿真彩能力强的特点使BF编码格式仍然有着独特的用武之地。

32bpp-BF-xxx:我一直不明白为什么会存在32bpp的位图。如果说32bpp-RGB格式的存在是因为在图像处理过程中存储起来比较高效(不用压缩),那么32bpp-BF又是为什么存在呢?

图像数据块

图像数据块从文件头中起始偏移量字段所指出的位置开始,其中存放着位图图像的数据,数据格式由图像参数信息块中的压缩方式选项的取值决定。操作图像数据块时,有一些注意事项:

当压缩方式为RGB时,图像数据块以“行”为单位双字对齐。例如一张宽度为5像素的8bpp的图像,其实际使用的存储空间是每行8个字节。又如一幅4bpp、宽度为5像素的位图图像,其实际使用的存储空间是每行4个字节。

当bpp < 8时,每个字节将存放多个像素的色彩索引,则先出现的像素存放在高位中。例如某4bpp图像第一行像素的顺序是red, green, blue, yellow, …则图像数据块中第一个字节的高4位值为red,低4位值为green;第二字节高4位值为blue,低4位值为yellow。1bpp时的情况以此类 推。

还记得前面提到,图像参数里,高度有可能是负值吗?这看上去很逗,但事实是,你见过的大多数位图,其图像参数里的高度都是负值。BMP格式设计者规 定,当高度为正值时,图像数据块中记录的第一行像素数据是图像的最后一行;而数据块中最后一行数据才是实际图像的第一行,也就是说,数据块中的行记录与实 际图像反序。而当高度为负值时,数据块中的行记录与实际图像才是同序的。

如果你觉得这太奇怪了,我很理解。不过我们必须怀着无比崇敬之情接受这个看似滑稽的规定。这是因为在那个年代里,那些设计BMP格式的天才首先都是 数学家,让天才的数学家们习惯左上角为原点,并且y轴方向向下的二维直角坐标系的格局显然是很困难的,既然他们手上又有设计BMP的大权,于是……唉,这 就是历史。

转载于:https://blog.51cto.com/jkers/677107

转贴:BMP格式详解 二 (转载)相关推荐

  1. BMP位图格式详解二--转载

    转自:http://www.cnblogs.com/xiehy/archive/2011/06/07/2074405.html BMP文件格式,又称为Bitmap(位图)或是DIB(Device-In ...

  2. BMP位图格式详解二

    BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Windows系统中广泛使用的图像文件格式.由于它可以不作任何变换地保存图像 ...

  3. BMP格式详解<转>

    BMP格式详解 BMP文件格式详解(BMP file format) BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Win ...

  4. 图片 bmp 格式详解

    1 概述 BMP(Bitmap-File)图片文件格式,又称为 Bitmap (位图)或是 DIB(Device-Independent Device,设备无关位图),是 Windows 系统中广泛使 ...

  5. BMP格式详解(有调色板)

    <div class="htmledit_views" id="content_views">                           ...

  6. bmp图片的格式详解

    BMP文件格式详解(BMP file format) BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Windows系统中广 ...

  7. BMP文件格式详解(BMP file format) (转)

    自:http://www.cnblogs.com/Jason_Yao/archive/2009/12/02/1615295.html BMP文件格式,又称为Bitmap(位图)或是DIB(Device ...

  8. BMP文件格式详解(BMP file format)[图文解说]

    BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Windows系统中广泛使用的图像文件格式.由于它可以不作任何变换地保存图像 ...

  9. urlencoded格式详解和JSON格式详解

    urlencoded格式详解和JSON格式详解 目录 urlencoded格式详解和JSON格式详解 一.表单格式详解 二.JSON格式详解 [json 格式口诀]: 1.1 什么是JSON 1.2 ...

最新文章

  1. php 5/0,PHP 5.5.0 released.该怎么解决
  2. idea解决打开大文件消耗CPU问题
  3. Excel为整列设置函数
  4. spark sql 查看分区_Spark SQL解析查询parquet格式Hive表获取分区字段和查询条件
  5. mysql表设计 列命名_MYSQL数据库字段命名及设计规范
  6. java 内部类 作用,内部类,java内部类的四大作用
  7. java初级学习04
  8. SSH框架下的在线人数统计的一种解决途径
  9. 计算机二级考试数据结构题库,计算机二级考试选择题库1.数据结构与算法
  10. php点击按钮保存图片到相册,手机端点击下载按钮将页面保存成图片到本地
  11. 静候 CSDN 佳音
  12. ai文字渐变_AI制作渐变色立体文字效果
  13. Github头像上传不了、加载不出来
  14. linux批量删除文件或者文件夹
  15. php wordphp 读取图片,利用PHPWORD类替换word模版文字,图片等
  16. Linux需要学什么
  17. 英特尔暂缓扩建大连芯片厂 或吞并全球最大芯片生厂商之一美光科技
  18. 【狂神说:秦疆老师】Spring5笔记
  19. 电气器件系列三:电流互感器
  20. Unity3D - Shader - 凹凸映射(Bump mapping)之美

热门文章

  1. 索爱麦克风免驱动的语音录入测试
  2. python判断值是否在excel中_python接口自动化测试之根据excel中的期望结果是否存在于请求返回的响应值中来判断用例是否执行成功...
  3. matlab/simulink常见问题汇总
  4. 详解python中的round()函数
  5. python的sorted函数用法_Python sorted函数及用法
  6. VS2010和opencv2.4.9的配置
  7. 【C++】42.使用YAML文件进行参数配置、读取与生成YAML文件
  8. 【吐血推荐】领域驱动设计学习输出
  9. 通过源码分析MyBatis的缓存
  10. 一台电脑上同启动两个Tomcat的方式,windows/Linux配置