BMP图像基本操作及在DSP中的显示Word文件下载.docx
《BMP图像基本操作及在DSP中的显示Word文件下载.docx》由会员分享,可在线阅读,更多相关《BMP图像基本操作及在DSP中的显示Word文件下载.docx(15页珍藏版)》请在冰豆网上搜索。
5.1 位图转换(2416)15
5.2DSP中显示16位的位图16
1.文档说明
▪本文介绍了BMP图片文件的格式,读取,写入及其他的一些基本操作。
另外还介绍了如何将24位的图像转换为16位的图像,以及如在DSP中显示一张图片。
2 BMP图像格式
要利用计算机对数字化图像进行处理,首先要对图像的文件格式要有清楚的认识,因为我们前面说过,自然界的图像以模拟信号的形式存在,在用计算机进行处理以前,首先要数字化,比如摄像头(CCD)摄取的信号在送往计算机处理前,一般情况下要经过数模转换,这个任务常常由图像采集卡完成,它的输出一般为裸图的形式;
如果用户想要生成目标图像文件,必须根据文件的格式做相应的处理。
随着科技的发展,数码像机、数码摄像机已经进入寻常百姓家,我们可以利用这些设备作为图像处理系统的输入设备来为后续的图像处理提供信息源。
无论是什么设备,它总是提供按一定的图像文件格式来提供信息,比较常用的有BMP格式、JPEG格式、GIF格式等等,所以我们在进行图像处理以前,首先要对图像的格式要有清晰的认识,只有在此基础上才可以进行进一步的开发处理。
在讲述图像文件格式前,先对图像作一个简单的分类。
除了最简单的图像外,所有的图像都有颜色,而单色图像则是带有颜色的图像中比较简单的格式,它一般由黑色区域和白色区域组成,可以用一个比特表示一个像素,“1”表示黑色,“0”表示白色,当然也可以倒过来表示,这种图像称之为二值图像。
我们也可以用8个比特(一个字节)表示一个像素,相当于把黑和白等分为256个级别,“0”表示为黑,“255”表示为白,该字节的数值表示相应像素值的灰度值或亮度值,数值越接近“0”,对应像素点越黑,相反,则对应像素点越白,此种图像我们一般称之为灰度图像。
单色图像和灰度图像又统称为黑白图像,与之对应存在着彩色图像,这种图像要复杂一些,表示图像时,常用的图像彩色模式有RGB模式、CMYK模式和HIS模式,一般情况下我们只使用RGB模式,R对应红色,G对应绿色,B对应蓝色,它们统称为三基色,这三中色彩的不同搭配,就可以搭配成各种现实中的色彩,此时彩色图像的每一个像素都需要3个样本组成的一组数据表示,其中每个样本用于表示该像素的一个基本颜色。
对于现存的所有的图像文件格式,我们在这里主要介绍BMP图像文件格式,并且文件里的图像数据是未压缩的,因为图像的数字化处理主要是对图像中的各个像素进行相应的处理,而未压缩的BMP图像中的像素数值正好与实际要处理的数字图像相对应,这种格式的文件最合适我们对之进行数字化处理。
请读者记住,压缩过的图像是无法直接进行数字化处理的,如JPEG、GIF等格式的文件,此时首先要对图像文件解压缩,这就要涉及到一些比较复杂的压缩算法。
后续章节中我们将针对特殊的文件格式如何转换为BMP格式的文件问题作专门的论述,经过转换,我们就可以利用得到的未压缩的BMP文件格式进行后续处理。
对于JPEG、GIF等格式,由于涉及到压缩算法,这要求读者掌握一定的信息论方面的知识,如果展开的话,可以写一本书,限于篇幅原因,我们只作一般性的讲解,有兴趣的朋友可以参考相关书籍资料。
2.1.BMP文件组成
BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
文件头主要包含文件的大小、文件类型、图像数据偏离文件头的长度等信息;
位图信息头包含图象的尺寸信息、图像用几个比特数值来表示一个像素、图像是否压缩、图像所用的颜色数等信息。
颜色信息包含图像所用到的颜色表,显示图像时需用到这个颜色表来生成调色板,但如果图像为真彩色,既图像的每个像素用24个比特来表示,文件中就没有这一块信息,也就不需要操作调色板。
文件中的数据块表示图像的相应的像素值,需要注意的是:
图像的像素值在文件中的存放顺序为从左到右,从下到上,也就是说,在BMP文件中首先存放的是图像的最后一行像素,最后才存储图像的第一行像素,但对与同一行的像素,则是按照先左边后右边的的顺序存储的;
另外一个需要读者朋友关注的细节是:
文件存储图像的每一行像素值时,如果存储该行像素值所占的字节数为4的倍数,则正常存储,否则,需要在后端补0,凑足4的倍数。
2.2.BMP文件头
BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。
其结构定义如下:
typedefstructtagBITMAPFILEHEADER
{
WORDbfType;
//位图文件的类型,必须为“BM”
DWORDbfSize;
//位图文件的大小,以字节为单位
WORDbfReserved1;
//位图文件保留字,必须为0
WORDbfReserved2;
DWORDbfOffBits;
//位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
}BITMAPFILEHEADER;
该结构占据14个字节。
2.3.位图信息头
BMP位图信息头数据用于说明位图的尺寸等信息。
其结构如下:
typedefstructtagBITMAPINFOHEADER{
DWORDbiSize;
//本结构所占用字节数
LONGbiWidth;
//位图的宽度,以像素为单位
LONGbiHeight;
//位图的高度,以像素为单位
WORDbiPlanes;
//目标设备的平面数不清,必须为1
WORDbiBitCount//每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
DWORDbiCompression;
//位图压缩类型,必须是0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORDbiSizeImage;
//位图的大小,以字节为单位
LONGbiXPelsPerMeter;
//位图水平分辨率,每米像素数
LONGbiYPelsPerMeter;
//位图垂直分辨率,每米像素数
DWORDbiClrUsed;
//位图实际使用的颜色表中的颜色数
DWORDbiClrImportant;
//位图显示过程中重要的颜色数
}BITMAPINFOHEADER;
该结构占据40个字节。
2.3.1成员说明
biSize
说明BITMAPINFOHEADER结构所需要的字数。
注:
这个值并不一定是BITMAPINFOHEADER结构的尺寸,它也可能是sizeof(BITMAPV4HEADER)的值,或是sizeof(BITMAPV5HEADER)的值。
这要根据该位图文件的格式版本来决定,不过,就现在的情况来看,绝大多数的BMP图像都是BITMAPINFOHEADER结构的(可能是后两者太新的缘故吧:
-)。
biWidth
说明图象的宽度,以象素为单位
biHeight
说明图象的高度,以象素为单位。
这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,还是正向的位图。
如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。
大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。
(注:
当高度值是一个负数时(正向图像),图像将不能被压缩(也就是说biCompression成员将不能是BI_RLE8或BI_RLE4)。
biPlanes
为目标设备说明位面数,其值将总是被设为1
biBitCount
指定表示颜色时要用到的位数,常用的值为1(黑白二色图),4(16色图),8(256色),24(真彩色图)(新的.bmp格式支持32位色,下面详细讨论)。
biCompression
说明图象数据压缩的类型。
其值可以是下述值之一:
BI_RGB:
没有压缩;
BI_RLE8:
每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);
BI_RLE4:
每个象素4比特的RLE压缩编码,压缩格式由2字节组成
BI_BITFIELDS:
每个象素的比特由指定的掩码决定。
biSizeImage
指定实际的位图数据占用的字节数,其实也可以从以下的公式中计算出来:
biSizeImage=biWidth’×
biHeight
要注意的是:
上述公式中的biWidth’必须是4的整倍数(所以不是biWidth,而是biWidth’,表示大于或等于biWidth的,最接近4的整倍数。
举个例子,如果biWidth=240,则biWidth’=240;
如果biWidth=241,biWidth’=244)。
如果biCompression为BI_RGB,则该项可能为零
biXPelsPerMeter
说明水平分辨率,用象素/米表示
biYPelsPerMeter
说明垂直分辨率,用象素/米表示
biClrUsed
说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)
biClrImportant
说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
现就BITMAPINFOHEADER结构作如下说明:
2.3.2彩色表的定位
应用程序可使用存储在biSize成员中的信息来查找在BITMAPINFO结构中的彩色表,如下所示:
pColor=((LPSTR)pBitmapInfo+(WORD)(pBitmapInfo->
bmiHeader.biSize))
2.3.3biBitCount的详细说明
biBitCount=1表示位图最多有两种颜色,缺省情况下是黑色和白色,你也可以自己定义这两种颜色。
图像信息头装调色板中将有两个调色板项,称为索引0和索引1。
图象数据阵列中的每一位表示一个象素。
如果一个位是0,显示时就使用索引0的RGB值,如果位是1,则使用索引1的RGB值。
biBitCount=4表示位图最多有16种颜色。
每个象素用4位表示,并用这4位作为彩色表的表项来查找该象素的颜色。
例如,如果位图中的第一个字节为0x1F,它表示有两个象素,第一象素的颜色就在彩色表的第2表项中查找,而第二个象素的颜色就在彩色表的第16表项中查找。
此时,调色板中缺省情况下会有16个RGB项。
对应于索引0到索引15。
biBitCount=8表示位图最多有256种颜色。
每个象素用8位表示,并用这8位作为彩色表的表项来查找该象素的颜色。
例如,如果位图中的第一个字节为0x1F,这个象素的颜色就在彩色表的第32表项中查找。
此时,缺省情况下,调色板中会有256个RGB项,对应于索引0到索引255。
biBitCount=16表示位图最多有216种颜色。
每个色素用16位(2个字节)表示。
这种格式叫作高彩色,或叫增强型16位色,或64K色。
它的情况比较复杂,当biCompression成员的值是BI_RGB时,它没有调色板。
16位中,最低的5位表示蓝色分量,中间的5位表示绿色分量,高的5位表示红色分量,一共占用了15位,最高的一位保留,设为0。
这种格式也被称作55516位位图。
如果biCompression成员的值是BI_BITFIELDS,那么情况就复杂了,首先是原来调色板的位置被三个DWORD变量占据,称为红、绿、蓝掩码。
分别用于描述红、绿、蓝分量在16位中所占的位置。
在Windows95(或98)中,系统可接受两种格式的位域:
555和565,在555格式下,红、绿、蓝的掩码分别是:
0x7C00、0x03E0、0x001F,而在565格式下,它们则分别为:
0xF800、0x07E0、0x001F。
你在读取一个像素之后,可以分别用掩码“与”上像素值,从而提取出想要的颜色分量(当然还要再经过适当的左右移操作)。
在NT系统中,则没有格式限制,只不过要求掩码之间不能有重叠。
这种格式的图像使用起来是比较麻烦的,不过因为它的显示效果接近于真彩,而图像数据又比真彩图像小的多,所以,它更多的被用于游戏软件)。
biBitCount=24表示位图最多有224种颜色。
这种位图没有调色板(bmiColors成员尺寸为0),在位数组中,每3个字节代表一个象素,分别对应于颜色R、G、B。
biBitCount=32表示位图最多有232种颜色。
这种位图的结构与16位位图结构非常类似,当biCompression成员的值是BI_RGB时,它也没有调色板,32位中有24位用于存放RGB值,顺序是:
最高位—保留,红8位、绿8位、蓝8位。
这种格式也被成为88832位图。
如果biCompression成员的值是BI_BITFIELDS时,原来调色板的位置将被三个DWORD变量占据,成为红、绿、蓝掩码,分别用于描述红、绿、蓝分量在32位中所占的位置。
在Windows95(or98)中,系统只接受888格式,也就是说三个掩码的值将只能是:
0xFF0000、0xFF00、0xFF。
而在NT系统中,你只要注意使掩码之间不产生重叠就行。
这种图像格式比较规整,因为它是DWORD对齐的,所以在内存中进行图像处理时可进行汇编级的代码优化(简单))。
2.3.4ClrUsed
BITMAPINFOHEADER结构中的成员ClrUsed指定实际使用的颜色数目。
如果ClrUsed设置成0,位图使用的颜色数目就等于biBitCount成员中的数目。
请注意,如果ClrUsed的值不是可用颜色的最大值或不是0,则在编程时应该注意调色板尺寸的计算,比如在4位位图中,调色板的缺省尺寸应该是16*sizeof(RGBQUAD),但是,如果ClrUsed的值不是16或者不是0,那么调色板的尺寸就应该是ClrUsed*sizeof(RGBQUAD)。
2.3.5图象数据压缩(biCompression)
①BI_RLE8:
每个象素为8比特的RLE压缩编码,可使用编码方式和绝对方式中的任何一种进行压缩,这两种方式可在同一幅图中的任何地方使用。
编码方式:
由2个字节组成,第一个字节指定使用相同颜色的象素数目,第二个字节指定使用的颜色索引。
此外,这个字节对中的第一个字节可设置为0,联合使用第二个字节的值表示:
第二个字节的值为0:
行的结束。
第二个字节的值为1:
图象结束。
第二个字节的值为2:
其后的两个字节表示下一个象素从当前开始的水平和垂直位置的偏移量。
绝对方式:
第一个字节设置为0,而第二个字节设置为0x03~0xFF之间的一个值。
在这种方式中,第二个字节表示跟在这个字节后面的字节数,每个字节包含单个象素的颜色索引。
压缩数据格式需要字边界(wordboundary)对齐。
下面的例子是用16进制表示的8-位压缩图象数据:
0304050600034556670002780002050102780000091E0001
这些压缩数据可解释为:
压缩数据
扩展数据
0304
040404
0506
0606060606
000345566700
455667
0278
7878
00020501
从当前位置右移5个位置后向下移一行
0000
行结束
091E
1E1E1E1E1E1E1E1E1E
0001
RLE编码图象结束
②BI_RLE4:
每个象素为4比特的RLE压缩编码,同样也可使用编码方式和绝对方式中的任何一种进行压缩,这两种方式也可在同一幅图中的任何地方使用。
这两种方式是:
由2个字节组成,第一个字节指定象素数目,第二个字节包含两种颜色索引,一个在高4位,另一个在低4位。
第一个象素使用高4位的颜色索引,第二个使用低4位的颜色索引,第3个使用高4位的颜色索引,依此类推。
这个字节对中的第一个字节设置为0,第二个字节包含有颜色索引数,其后续字节包含有颜色索引,颜色索引存放在该字节的高、低4位中,一个颜色索引对应一个象素。
此外,BI_RLE4也同样联合使用第二个字节中的值表示:
下面的例子是用16进制数表示的4-位压缩图象数据:
0304050600064556670004780002050104780000091E0001
压缩数据
040
06060
000645566700
455667
0478
7878
1E1E1E1E1
RLE图象结束
3.颜色表
颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。
RGBQUAD结构的定义如下:
typedefstructtagRGBQUAD{
BYTErgbBlue;
//蓝色的亮度(值范围为0-255)
BYTErgbGreen;
//绿色的亮度(值范围为0-255)
BYTErgbRed;
//红色的亮度(值范围为0-255)
BYTErgbReserved;
//保留,必须为0
}RGBQUAD;
颜色表中RGBQUAD结构数据的个数由BITMAPINFOHEADER中的biBitCount项来确定,当biBitCount=1,4,8时,分别有2,16,256个颜色表项,当biBitCount=24时,图像为真彩色,图像中每个像素的颜色用三个字节表示,分别对应R、G、B值,图像文件没有颜色表项。
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedefstructtagBITMAPINFO{
BITMAPINFOHEADERbmiHeader;
//位图信息头
RGBQUADbmiColors[1];
//颜色表
}BITMAPINFO;
注意:
RGBQUAD数据结构中,增加了一个保留字段rgbReserved,它不代表任何颜色,必须取固定的值为“0”,同时,RGBQUAD结构中定义的颜色值中,红色、绿色和蓝色的排列顺序与一般真彩色图像文件的颜色数据排列顺序恰好相反,既:
若某个位图中的一个像素点的颜色的描述为“00,00,ff,”,则表示该点为红色,而不是蓝色。
4.位图数据
4.1概述
位图数据记录了位图的每一个像素值或该对应像素的颜色表的索引值,图像记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。
这种格式我们又称为Bottom_Up位图,当然与之相对的还有Up_Down形式的位图,它的记录顺序是从上到下的,对于这种形式的位图,也不存在压缩形式。
位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节,此时图像为真彩色图像。
当图像不是为真彩色时,图像文件中包含颜色表,位图的数据表示对应像素点在颜色表中相应的索引值,当为真彩色时,每一个像素用三个字节表示图像相应像素点彩色值,每个字节分别对应R、G、B分量的值,这时候图像文件中没有颜色表。
上面我已经讲过了,Windows规定图像文件中一个扫描行所占的字节数必须是4的倍数(即以字为单位),不足的以0填充,图像文件中一个扫描行所占的字节数计算方法:
DataSizePerLine=(biWidth*biBitCount+31)/8;
//一个扫描行所占的字节数
位图数据的大小按下式计算(不压缩情况下):
DataSize=DataSizePerLine*biHeight。
上述是BMP文件格式的说明,搞清楚了以上的结构,就可以正确的操作图像文件,对它进行读或写操作了。
再一次强调以下两点:
(1)每一行的字节数必须是4的整倍数,如果不是,则需要补齐。
这在前面介绍biSizeImage时已经提到了。
现举例说明:
比如我有一张BMP图片,分辨率为350*100,色深为24位,那么相应的文件占用多少字节呢,首先文件头和信息头的和为54个字节,这是固定的,其次该图片一共有350*100个像素,每个像素占3个字节(RGB各一位),所以图像信息占用350*100*3=105,000个字节。
因为色深为24位,所以没有颜色表。
文件大小=54+105,000=105,054B;
但是如果用windows的资源管理器查看的话,会发现文件的大小为:
105,254B,为什么会多200个B呢?
这是因为
(1)所说的原因,每一行占用的字节数为350*3=1050,不是4的倍数,1050 mod4=2,所以每一行还必须填充2B的0,100行共200B。
(2)
一般来说,.bMP文件的数据从下到上,从左到右的。
也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,然后是左边第二个象素……接下来是倒数第二行左边第一个象素,左边第二个象素……依次类推,最后得到的是最上面一行的最右一个象素。
4.2 定位图片中的某一像素
操作之前再一次强调以下两点:
(2)每一行的字节数必须是4的整倍数,如果不是,则需要补齐。
也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,然后是左边第二个象素……接下来是倒数第二行左边第