计算机视觉
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.2 灰度位图图像和彩色位图图像

2.1节简单介绍了位图的基本情况,如8位图像和24位图像等。本节介绍灰度和彩色位图图像。

一般出版物为了降低成本,都采用灰度图像,也就是没有彩色的图像。那么,这种灰度图像属于8位图像,还是24位图像呢?具体在计算机中是如何表示的呢?这些问题参考位图的结构,如图2.4所示。

img

图2.4 位图的结构

在上述结构定义中,三个结构体分别定义如下。其中,BITMAPFILEHEADER为

img

其各个参数含义如下:

(1)bfType:位图文件类型,必须是0x424D,即字符串"BM",也就是说,所有的“*.bmp”文件的头2字节都是"BM"。若磁盘损坏,则可以根据这个标志位恢复部分位图数据。

(2)bfSize:位图文件大小,包括14字节。

(3)bfReserved1,bfReserved2:Windows的保留字,暂不使用。

(4)bfOffBits:从文件头到实际的位图数据的偏移字节数。

BITMAPINFOHEADER定义为:

img

BITMAPINFOHEADER结构体的各个参数的详细说明如下:

(1)biSize:本结构体的长度,为40 B。

(2)biWidth:位图的宽度,以像素为单位。

(3)biHeight:位图的高度,以像素为单位。

(4)biPlanes:目标设备的级别,必须是1。

(5)biBitCount:每个像素所占的位数(bit),其值必须为1(黑白图像)、4(16色图)、8(256色)、24(真彩色图),新的BMP格式支持32位色。

(6)biCompression:位图压缩类型,有效值为BI_RGB(未经压缩)、BI_RLE8、BI_RLE4、BI_BITFILEDS(均为Windows定义常量)。这里只讨论未经压缩的情况,即biCompression=BI_RGB。

(7)biSizeImage:实际的位图数据占用的字节数,该值的大小在第4部分位图数据中有具体解释。

(8)biXPelsPerMeter:指定目标设备的水平分辨率,单位是像素/米。

(9)biYPelsPerMeter:指定目标设备的垂直分辨率,单位是像素/米。

(10)biClrUsed:位图实际用到的颜色数,若该值为零,则用到的颜色数为2的biBitCount次幂。

(11)biClrImportant:位图显示过程中重要的颜色数,若该值为零,则认为所有的颜色都是重要的。

而颜色表部分实际上由占4字节的RGBQUAD结构体数组组成,该结构体数组的长度由biClrUsed指定(若该值为零,则由biBitCount指定,即2的biBitCount次幂个元素)。RGBQUAD结构体定义为:

img

其各个参数定义如下:

(1)rgbBlue:该种颜色的蓝色分量值;

(2)rgbGreen:该种颜色的绿色分量值;

(3)rgbRed:该种颜色的红色分量值;

(4)rgbReserved:保留值,有时可用来表示α通道值。

有些位图需要颜色表,而有些位图(如真彩色图)不需要颜色表,颜色表的长度由BITMAPINFOHEADER结构中的biBitCount分量决定。对于biBitCount值为1的二值图像,每像素占 1bit,图像中只有两种(如黑白)颜色,颜色表也就有21=2个表项,整个颜色表的大小为2×sizeof(RGBQUAD)=2×4=8 B;对于biBitCount值为8的灰度图像,每像素占8bit,图像中有28=256种颜色,颜色表也就有256个表项,且每个表项的R、G、B分量都相等,整个颜色表的大小为256×4=2014 B;而对于大于256种颜色的彩色图像,如biBitCount=24,由于每像素3 B中分别代表了R、G、B三个分量的值,此时不需要颜色表,因此真彩色图的BITMAPINFOHEADER结构体后面直接就是位图数据。

注意,有的工程师在编写自己的位图类时,RGBQUAD中元素的顺序可能会翻转为R、G、B,而不是默认的B、G、R顺序,此时会导致显示器显示的图像颜色不正确。一旦出现该情况,可以根据实际情况,调试解决该问题。

第三部分是位图数据,即图像数据,其紧跟在文件头、颜色表(若有颜色表)之后,记录了图像的每个像素值。对于有颜色表的位图,位图数据就是该像素颜色在颜色表中的索引值;对于真彩色图,位图数据就是实际的R、G、B值(三个分量的存储顺序是B、G、R)。

下面分别就2色、16色、256色和真彩色位图的位图数据进行说明。

对于2色位图,用1位就可以表示该像素的颜色,所以1 B能存储8个像素的颜色值。对于16色位图,用4 bit可以表示1个像素的颜色,所以1B可以存储2个像素的颜色值。对于256色位图,1 B刚好存储1个像素的颜色值。对于真彩色位图,3 B才能表示1个像素的颜色值。但实际应用中需要注意以下特殊情况:

(1)Windows规定一个扫描行所占的字节数必须是4的倍数,若不足4的倍数则要对其进行扩充。假设图像的宽为biWidth个像素,每个像素biBitCount位,其一个扫描行所占的真实字节数的计算公式为

DataSizePerLine=(biWidth×biBitCount /8+ 3)/ 4×4

那么,在不压缩的情况下,位图数据的大小(BITMAPINFOHEADER结构中的biSizeImage成员)计算公式为

biSizeImage=DataSizePerLine×biHeight

但在实际编程实现时,往往会出现显示的图像是斜的,这一般是由于没有按照4的整数倍对齐图像数据造成的。显然,若图像每行字节数不是4的整数倍,则这时图像每行最后都用多余的字节补成4的整数倍这个方法是没用的,这些字节实际上可以用于边信息通信,如信息隐藏等。

(2)一般程序中,BMP文件的数据是从图像的左下角开始逐行扫描图像的,即从下到上、从左到右来安排图像的像素值,因此图像坐标零点在图像左下角。但有些工程师在编写程序时并没有按照这种规范,而只是简单从上到下、从左到右排列像素值,这时会造成图像倒立。例如,OpenCV中有专门的标志位来确认这种现象。