2024年5月3日发(作者:)

BMP的颜色位深说明

今天同事遇到一个问题,由于客户要求的图片一定是BMP R5 G6 B5模式,可是存出来的

这种图片格式,在PC机上显示时,会有如下问题:第一,几乎是所有图片预览工具都看不到,

第二,用画图工具打开的时候,发现首尾的顺序不对,本属于左边的一块区域被填充到了右边,

而在PS里打开就很正常。这使我有点困惑了,为什么会出现这种现像?R5 G6 B5到底又是一

种什么格式呢?查过资料之后,我终于明白,原来是这样的:

BMP取自位图BitMaP的缩写,也称为DIB(与设备无关的位图)是微软视窗图形子系统

(GDI)内部使用的一种位图图形格式,它是微软视窗平台上的一个简单的图形文件格式。

我们知道,BMP根据颜色深度,可以分为2(1位)、16(4位)、256(8位)、65536

(16位)和1670万(24位)以及32位含有alpha通道。8位图像可以是索引彩色图像外,也

可以是灰阶图像,而索引彩色图片所使用的颜色来源就是RGB颜色值。图像上的每个点阵都是

由这些调色板上的RGB值混合而来,由于这个源因,从16位开始,对于调色的板的定义就有

多种模式:

X1 R5 G5 B5是PC操作系统默认的16位BMP颜色位深分配格式,使用的是标准的RGB

颜色,其中X1代表1位的黑白值(或者未使用),R5代表红色位深为5位,G5代表绿色位深

为5位,B5代表了蓝色位深为5位。四个值相加刚好是16位;

R5 G6 B5,电子产品中较为常用的图像模式,这种模式是红色R位深为5位,G5代表绿

色G位深为6位,B5代表了蓝色B位深为5位。三个值相加刚好是16位;这种模式常和翻转

序列配合使用。

A1 R5 G5 B5,这种图像模式暂时未知主要应用于哪里。模式是A1代表1位的alpha透明

通道,R5代表红色位深为5位,G5代表绿色位深为5位,B5代表了蓝色位深为5位。四个值

相加刚好是16位;16位椐我的了解好像是没有透明通道的,为什么会有这种格式,我也不太清

楚,而且这种模式在PS里一直都是打灰的,没见可以使用过,这里记录一下,有知道的朋友,

我们可以一起探讨。

X4 R4 G4 B4 ,4位的黑白值(或者未使用),红色位深4位,绿色位深4位,蓝色位深

4位。四个值相加刚好是16位;

还有一些,我不在仔细一一说明,载个别人写的内容参考一下:

A8 R8 G8 B8—每像素 32 位: 对于 RGB 和 alpha 通道,每像素 8 位。

A1 R5 G5 B5—每像素 16 位: 对于 RGB 通道,每像素 5 位,alpha 通道,每像素 1

位。

A4 R4 G4 B4—每像素 16 位: 对于 RGB 和 alpha 通道,每像素 4 位。

R8 G8 B8—每像素 24 位: 对于 RGB 通道,每像素 8 位;无 alpha。

R5 G6 B5—每像素 16 位: 对于 R 和 B 通道,每像素 5 位,对于 G 通道,每像素 6

位;无 alpha。

A2 R10 G10 B10—每像素 32 位: 对于 RGB 通道,每像素 10 位;alpha 通道,每像

素 2 位。

X8 R8 G8 B8—每像素 32 位: 对于 RGB 通道,每像素 8 位;8 位未使用;无 alpha。

X1 R5 G5 B5—每像素 16 位: 对于 RGB 通道,每像素 5 位;1 位未使用;无 alpha。

R3 G3 B2—每像素 8 位: 对于 R 和 G 通道,每像素 3 位,对于 B 通道,每像素 2

位;无 alpha。

A8 R3 G3 B2—每像素 16 位: 对于 R 和 G 通道,每像素 3 位,对于 B 通道,每像

素 2 位;对于 alpha 通道,每像素 8 位。

X4 R4 G4 B4—每像素 16 位: 对于 RGB 通道和 4 个未使用位,每像素 4 位。

A16 B16 G16 R16—每像素 64 位: 对于 RGB 和 alpha 通道,每像素 16 位。

当我们了解了上面这些内容以后,我们就会发现ACDSee只所以不能读这种格式的图片,

应该是软件自动识别的是X1 R5 G5 B5这种格式,遇到R5 G6 B5这种模式时,测试到第一位

的颜色值不是黑白,当异常处理,就会不显示该图。而画图能识别这种图片,但是又会出错,我

的猜测是:画图是从windows95开始,就已经有的小工具,画图对新的图片格式的兼容性不是

很好,他没有检测第一位的位深,而是直接把R5 G6 B5模式当成X1 R5 G5 B5来识别,从第

二位开始组合颜色,所以就会出现,前面的一部份被贴在后面,当然这也只是我的猜测。

BMP部份资料:

存储算法

P文件通常是不压缩的,所以它们通常比同一幅图像的压缩图像文件格式要大很多。例如,

一个800×600的24位几乎占据1.4MB空间。因此它们通常不适合在因特网或者其他低速或者

有容量限制的媒介上进行传输。

根据颜色深度的不同,图像上的一个像素可以用一个或者多个字节表示,它由n/8所确定(n是

位深度,1字节包含8个数据位)。图片浏览器等基于字节的ASCII值计算像素的颜色,然后从

调色板中读出相应的值。更为详细的信息请参阅下面关于位图文件的部分。

n位2n种颜色的包含调色板的位图近似字节数可以用下面的公式计算:

BMP文件大小 约等于54+4.2的N次方+(width*height*n)/8,其中高度和宽度都是像素数。

需要注意的是上面公式中的54是位图文件的文件头,是彩色调色板的大小。 如果位图文

件不包含调色板,如24位,32位位图,则位图的近似字节数可以用下面的公式计算:

BMP文件大小 约等于54+(width*height*n)/8,其中高度和宽度都是像素数。

另外需要注意的是这是一个近似值,对于n位的位图图像来说,尽管可能有最多2n中颜

色,一个特定的图像可能并不会使用这些所有的颜色。由于彩色调色板仅仅定义了图像所用的颜

色,所以实际的彩色调色板将小于4.2的N次方。

如果想知道这些值是如何得到的,请参考下面文件格式的部分。

由于存储算法本身决定的因素,根据几个图像参数的不同计算出的大小与实际的文件大小

将会有一些细小的差别。

典型的文件格式

典型的位图文件格式通常包含下面几个数据块:

1.位图头:保存位图文件的总体信息。

2.位图信息:保存位图图像的详细信息。

3.调色板:保存所用颜色的定义。

4.位图数据:保存一个又一个像素的实际图像。

下面的部分将会详细地描述位图文件中保存的数据。需要注意的是这是标准位图的文件格

式,其他一些位图图像可能根据生成文件的应用程序不同所使用格式可能会有细微的区别。

位图头

这部分是识别信息,典型的应用程序会首先普通读取这部分数据以确保的确是位图文件并

且没有损坏。

字节 #0-1 保存位图文件的标识符,这两个字节的典型数据是BM。

字节 #2-5 使用一个dword保存位图文件大小。

字节 #6-9 是保留步部分,实际的值根据生成它们的应用程序不同而不同。

字节 #10-13 保存位图数据位置的地址偏移,也就是起始地址。

位图信息

这部分告诉应用程序图像的详细信息,在屏幕上显示图像将会使用这些信息,它从文件的

第15个字节开始。

字节 #14-17 定义头的大小。它的值是:40 - Windows V3、12 - OS/2 V1、64 - OS/2 V2、

108 - Windows V4、124 - Windows V5

字节 #18-21 保存位图宽度(以像素个数表示)。

字节 #22-25 保存位图高度(以像素个数表示)。

字节 #26-27 保存所用彩色位面的个数。不经常使用。

字节 #28-29 保存每个像素的位数,它是图像的颜色深度。常用值是1、4、8和24。

字节 #30-33 定义所用的压缩算法。允许的值是0、1、2、3、4、5。

0 - 没有压缩(也用BI_RGB表示)

1 - 行程长度编码 8位/像素(也用BI_RLE8表示)

2 - 行程长度编码4位/像素(也用BI_RLE4表示)

3 - Bit field(也用BI_BITFIELDS表示)

4 - JPEG图像(也用BI_JPEG表示)

5 - PNG图像(也用BI_PNG表示)

然而,由于大多数位图文件都是不压缩的,所以最常用的值是0。

字节 #34-37 保存图像大小。这是原始(:en:raw)位图数据的大小,不要与文件大小混淆。

字节 #38-41 保存图像水平方向分辨率。

字节 #42-45 保存图像竖值方向分辨率。

字节 #46-49 保存所用颜色数目。

字节 #50-53 保存所用重要颜色数目。当每个颜色都重要时这个值与颜色数目相等。

调色板

这部分定义了图像中所用的颜色。如上所述,位图图像一个像素接着一个像素存储,每个

像素使用一个或者多个字节的值表示,所以调色板的目的就是要告诉应用程序这些值所对应的实

际颜色。

典型的位图文件使用RGB彩色模型。在这种模型中,每种颜色都是由不同强度(从0到最大强

度)的红色(R)、绿色(G)和蓝色(B)组成的,也就是说,每种颜色都可以使用红色、绿

色和蓝色的值所定义。

在位图文件的实现中,调色板可以包含很多条目,条目个数就是图像中所使用的颜色的个数。每

个条目包含4个字节:其中三个表示红色、绿色和蓝色,第四个字节没有使用(大多数应用程

序将它设为0)。对于每个字节,数值0表示相应的颜色在当前的图像文件中没有使用,而数值

255表示那个颜色使用最大的强度。

位图数据

这部分逐个像素表示图像。像素是从下到上、从左到右保存的。每个像素使用一个或者多

个字节表示。如果一个图像水平线的字节数不是4的倍数,这行就使用空字节补齐,通常是ASCII

码0。

范例: 有一张5*5的图片,应该会有25个pixels,但是因为5不是4的倍数所以会显示成:

@@@@@@xxxxx000xx

xxx000xxxxx000xx

xxx000xxxxx000

x代表调色盘的编号 0代表Null_character @代表调色盘最后几笔资料

有一张4*4的图片,应该会有16个pixels,但是因为是4的倍数所以会显示成:

@@@@@@xxxxxxxxxx

xxxxxx