版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、 与设备无关的位图涛儿软件工作室 整理编译 在上一章我们了解到Windows GDI位图对象(也称为与设备相关的位图,或DDB)有许多程序设计用途。但是我并没有展示把这些位图储存到磁盘文件或把它们加载内存的方法。这是以前在Windows中使用的方法,现在根本不用了。因为位图的位格式相当依赖于设备,所以DDB不适用于图像交换。DDB内没有色彩对照表来指定位图的位与色彩之间的联系。DDB只有在Windows开机到关机的生命期内被建立和清除时才有意义。DIB 文件格式有意思的是,DIB格式并不是源自于Windows。它首先定义在OS/2的1.1版中,该操作
2、系统最初由IBM和Microsoft在八十年代中期开始开发。OS/2 1.1在1988年发布,并且是第一个包含了类似Windows的图形使用者接口的OS/2版本,该图形使用者接口被称之为Presentation Manager(PM)。Presentation Manager包含了定义位图格式的图形程序接口(GPI)。然后在Windows 3.0中(发布于1990)使用了OS/2位图格式,这时称之为DIB。Windows 3.0也包含了原始DIB格式的变体,并在Windows下成为标准。在Windows 95(以及Windows NT 4.0)和Windows 98(以及Windows NT
3、5.0)下也定义了一些其它的增强能力,我会在本章讨论它们。DIB首先作为一种文件格式,它的扩展名为.BMP,在极少情况下为.DIB。Windows应用程序使用的位图图像被当做DIB文件建立,并作为只读资源储存在程序的可执行文件中。图标和鼠标光标也是形式稍有不同的DIB文件。程序能将DIB文件减去前14个字节加载连续的内存块中。这时就可以称它为packed DIB(packed-DIB)格式的位图。在Windows下执行的应用程序能使用packed DIB格式,通过Windows剪贴簿来交换图像或建立画刷。程序也可以完全存取DIB的内容并以任意方式修改DIB。程序也能在内存中建立自己的DIB然后
4、把它们存入文件。程序使用GDI函数呼叫就能绘制这些DIB内的图像,也能在程序中利用别的内存DIB直接设定和操作图素位。在内存中加载了DIB后,程序也能通过几个Windows API函数呼叫来使用DIB数据,我将在本章中讨论有关内容。与DIB相关的API呼叫是很少的,并且主要与视讯显示器或打印机页面上显示DIB相关,还与转换GDI位图对象有关。除了这些内容以外,还有许多应用程序需要完成的DIB任务,而这些任务Windows操作系统并不支持。例如,程序可能存取了24位DIB并且想把它转化为带有最佳化的256色调色盘的8位DIB,而Windows不会为您执行这些操作。但是在本章和下一章将向您显示Wi
5、ndows API之外的操作DIB的方式。OS/2样式的DIB先不要陷入太多的细节,让我们看一下与首先在OS/2 1.1中出现的位图格式兼容的Windows DIB格式。DIB文件有四个主要部分:· 文件表头· 信息表头· RGB色彩对照表(不一定有)· 位图图素位您可以把前两部分看成是C的数据结构,把第三部分看成是数据结构的数组。在Windows表头文件WINGDI.H中说明了这些结构。在内存中的packed DIB格式内有三个部分:· 信息表头· RGB色彩对照表(不一定有)· 位图图素位除了没有文件表头外,其它部分与储
6、存在文件内的DIB相同。DIB文件(不是内存中的packed DIB)以定义为如下结构的14个字节的文件表头开始:typedef struct tagBITMAPFILEHEADER / bmfh WORD bfType ; / signature word "BM" or 0x4D42 DWORD bfSize ; / entire size of file WORD bfReserved1 ; / must be zero WORD bfReserved2 ; / must be zero DWORD bfOffsetBits ; / offset in file of
7、 DIB pixel bits BITMAPFILEHEADER, * PBITMAPFILEHEADER ; 在WINGDI.H内定义的结构可能与这不完全相同,但在功能上是相同的。第一个注释(就是文字bmfh)指出了给这种数据型态的数据变量命名时推荐的缩写。如果在我的程序内看到了名为pbmfh的变量,这可能是一个指向BITMAPFILEHEADER型态结构的指针或指向PBITMAPFILEHEADER型态变量的指针。结构的长度为14字节,它以两个字母BM开头以指明是位图文件。这是一个WORD值0x4D42。紧跟在BM后的DWORD以字节为单位指出了包括文件表头在内的文件大小。下两个WORD字
8、段设定为0。(在与DIB文件格式相似的鼠标光标文件内,这两个字段指出光标的热点(hot spot)。结构还包含一个DWORD字段,它指出了文件中图素位开始位置的字节偏移量。此数值来自DIB信息表头中的信息,为了使用的方便提供在这里。在OS/2样式的DIB内,BITMAPFILEHEADER结构后紧跟了BITMAPCOREHEADER结构,它提供了关于DIB图像的基本信息。紧缩的DIB(Packed DIB)开始于BITMAPCOREHEADER:typedef struct tagBITMAPCOREHEADER / bmch DWORD bcSize ; / size of the stru
9、cture = 12 WORD bcWidth ; / width of image in pixels WORD bcHeight ; / height of image in pixels WORD bcPlanes ; / = 1 WORD bcBitCount ; / bits per pixel (1, 4, 8, or 24) BITMAPCOREHEADER, * PBITMAPCOREHEADER ; core(核心)用在这里看起来有点奇特,它是指这种格式是其它由它所衍生的位图格式的基础。BITMAPCOREHEADER结构中的bcSize字段指出了数据结构的大小,在这种情况下
10、是12字节。bcWidth和bcHeight字段包含了以图素为单位的位图大小。尽管这些字段使用WORD意味着一个DIB可能为65,535图素高和宽,但是我们几乎不会用到那么大的单位。bcPlanes字段的值始终是1。这个字段是我们在上一章中遇到的早期Windows GDI位图对象的残留物。bcBitCount字段指出了每图素的位数。对于OS/2样式的DIB,这可能是1、4、8或24。DIB图像中的颜色数等于2bmch.bcBitCount,或用C的语法表示为:1 << bmch.bcBitCount 这样,bcBitCount字段等于:· 1代表2色DIB· 4
11、代表16色DIB· 8代表256色DIB· 24代表full -Color DIB当我提到8位DIB时,就是说每图素占8位的DIB。对于前三种情况(也就是位数为1、4和8时),BITMAPCOREHEADER后紧跟色彩对照表,24位DIB没有色彩对照表。色彩对照表是一个3字节RGBTRIPLE结构的数组,数组中的每个元素代表图像中的每种颜色:typedef struct tagRGBTRIPLE / rgbt BYTE rgbtBlue ; / blue level BYTE rgbtGreen ; / green level BYTE rgbtRed ; / red le
12、vel RGBTRIPLE ; 这样排列色彩对照表以便DIB中最重要的颜色首先显示,我们将在下一章说明原因。WINGDI.H表头文件也定义了下面的结构:typedef struct tagBITMAPCOREINFO / bmci BITMAPCOREHEADER bmciHeader ; / core-header structure RGBTRIPLE bmciColors1 ; / color table array BITMAPCOREINFO, * PBITMAPCOREINFO ; 这个结构把信息表头与色彩对照表结合起来。虽然在这个结构中RGBTRIPLE结构的数量等于1,但在DI
13、B文件内您绝对不会发现只有一个RGBTRIPLE。根据每个图素的位数,色彩对照表的大小始终是2、16或256个RGBTRIPLE结构。如果需要为8位DIB配置PBITMAPCOREINFO结构,您可以这样做:pbmci = malloc (sizeof (BITMAPCOREINFO) + 255 * sizeof (RGBTRIPLE) ; 然后可以这样存取RGBTRIPLE结构:pbmci->bmciColorsi 因为RGBTRIPLE结构的长度是3字节,许多RGBTRIPLE结构可能在DIB中以奇数地址开始。然而,因为在DIB文件内始终有偶数个的RGBTRIPLE结构,所以紧跟在
14、色彩对照表数组后的数据块总是以WORD地址边界开始。紧跟在色彩对照表(24位DIB中是信息表头)后的数据是图素位本身。由下而上像大多数位图格式一样,DIB中的图素位是以水平行组织的,用视讯显示器硬件的术语称作扫描线。行数等于BITMAPCOREHEADER结构的bcHeight字段。然而,与大多数位图格式不同的是,DIB从图像的底行开始,往上表示图像。在此应定义一些术语,当我们说顶行和底行时,指的是当其正确显示在显示器或打印机的页面上时出现在虚拟图像的顶部和底部。就好像肖像的顶行是头发,底行是下巴,在DIB文件中的第一行指的是DIB文件的色彩对照表后的图素行,最后行指的是文件最末端的图素行。因
15、此,在DIB中,图像的底行是文件的第一行,图像的顶行是文件的最后一行。这称之为由下而上的组织。因为这种组织和直觉相反,您可能会问:为什么要这么做?好,现在我们回到OS/2的Presentation Manager。IBM的人认为PM内的坐标系统包括窗口、图形和位图应该是一致的。这引起了争论:大多数人,包括在全画面文字方式下编程和窗口环境下工作的程序写作者认为应使用垂直坐标在屏幕上向下增加的坐标。然而,计算机图形程序写作者认为应使用解析几何的数学方法进行视讯显示,这是一个垂直坐标在空间中向上增加的直角(或笛卡尔)坐标系。简而言之,数学方法赢了。PM内的所有事物都以左下角为原点(包括窗口坐标),因
16、此DIB也就有了那种方式。DIB图素位DIB文件的最后部分(在大多数情况下是DIB文件的主体)由实际的DIB的图素字节成。图素位是由从图像的底行开始并沿着图像向上增长的水平行组织的。DIB中的行数等于BITMAPCOREHEADER结构的bcHeight字段。每一行的图素数等于该结构的bcWidth字段。每一行从最左边的图素开始,直到图像的右边。每个图素的位数可以从bcBitCount字段取得,为1、4、8或24。以字节为单位的每行长度始终是4的倍数。行的长度可以计算为:RowLength = 4 * (bmch.bcWidth * bmch.bcBitCount + 31) / 32) ;
17、或者在C内用更有效的方法:RowLength = (bmch.bcWidth * bmch.bcBitCount + 31) & 31) >> 3 ; 如果需要,可通过在右边补充行(通常是用零)来完成长度。图素数据的总字节数等于RowLength和bmch.bcHeight的乘积。要了解图素编码的方式,让我们分别考虑四种情况。在下面的图表中,每个字节的位显示在框内并且编了号,7表示最高位,0表示最低位。图素也从行的最左端从0开始编号。对于每图素1位的DIB,每字节对应为8图素。最左边的图素是第一个字节的最高位:Error! Reference source not foun
18、d.每个图素可以是0或1。0表示该图素的颜色由色彩对照表中第一个RGBTRIPLE项目给出。1表示图素的颜色由色彩对照表的第二个项目给出。对于每图素4位的DIB,每个字节对应两个图素。最左边的图素是第一个字节的高4位,以此类推:Error! Reference source not found.每图素4位的值的范围从0到15。此值是指向色彩对照表中16个项目的索引。对于每图素8位的DIB,每个字节为1个图素:Error! Reference source not found.字节的值从0到255。同样,这也是指向色彩对照表中256个项目的索引。对于每图素24位的DIB,每个图素需要3个字节来代
19、表红、绿和蓝的颜色值。图素位的每一行,基本上就是RGBTRIPLE结构的数组,可能需要在每行的末端补0以便该行为4字节的倍数:Error! Reference source not found.每图素24位的DIB没有色彩对照表。扩展的Windows DIB现在我们掌握了Windows 3.0中介绍的与OS/2兼容的DIB,同时也看一看Windows中DIB的扩展版本。这种DIB形式跟前面的格式一样,以BITMAPFILEHEADER结构开始,但是接着是BITMAPINFOHEADER结构,而不是BITMAPCOREHEADER结构:typedef struct tagBITMAPINFOHE
20、ADER / bmih DWORD biSize ; / size of the structure = 40 LONG biWidth ; / width of the image in pixels LONG biHeight ; / height of the image in pixels WORD biPlanes ; / = 1 WORD biBitCount ; / bits per pixel (1, 4, 8, 16, 24, or 32) DWORD biCompression ; / compression code DWORD biSizeImage ; / numbe
21、r of bytes in image LONG biXPelsPerMeter ; / horizontal resolution LONG biYPelsPerMeter ; / vertical resolution DWORD biClrUsed ; / number of colors used DWORD biClrImportant ; / number of important colors BITMAPINFOHEADER, * PBITMAPINFOHEADER ; 您可以通过检查结构的第一字段区分与OS/2兼容的DIB和Windows DIB,前者为12,后者为40。您将
22、注意到,在这个结构内有六个附加的字段,但是BITMAPINFOHEADER不是简单地由BITMAPCOREHEADER加上一些新字段而成。仔细看一下:在BITMAPCOREHEADER结构中,bcWidth和bcHeight字段是16位WORD值;而在BITMAPINFOHEADER结构中它们是32位LONG值。这是一个令人讨厌的小变化,当心它会给您带来麻烦。另一个变化是:对于使用BITMAPINFOHEADER结构的1位、4位和8位DIB,色彩对照表不是RGBTRIPLE结构的数组。相反,BITMAPINFOHEADER结构紧跟着一个RGBQUAD结构的数组:typedef struct t
23、agRGBQUAD / rgb BYTE rgbBlue ; / blue level BYTE rgbGreen ; / green level BYTE rgbRed ; / red level BYTE rgbReserved ; / = 0 RGBQUAD ; 除了包括总是设定为0的第四个字段外,与RGBTRIPLE结构相同。 WINGDI.H表头文件也定义了以下结构:typedef struct tagBITMAPINFO / bmi BITMAPINFOHEADER bmiHeader ; / info-header structure RGBQUAD bmiColors1 ; /
24、 color table array BITMAPINFO, * PBITMAPINFO ; 注意,如果BITMAPINFO结构以32位的地址边界开始,因为BITMAPINFOHEADER结构的长度是40字节,所以RGBQUAD数组内的每一个项目也以32位边界开始。这样就确保通过32位微处理器能更有效地对色彩对照表数据寻址。尽管BITMAPINFOHEADER最初是在Windows 3.0中定义的,但是许多字段在Windows 95和Windows NT 4.0中又重新定义了,并且被带入Windows 98和Windows NT 5.0中。比如现在的文件中说:如果biHeight是负数,则位图
25、是由上而下的DIB,原点在左上角。这很好,但是在1990年刚开始定义DIB格式时,如果有人做了这个决定,那会更好。我的建议是避免建立由上而下的DIB。有一些程序在编写时没有考虑这种新特性,在遇到负的biHeight字段时会当掉。还有如Microsoft Word 97带有的Microsoft Photo Editor在遇到由上而下的DIB时会报告图像高度不合法(虽然Word 97本身不会出错)。biPlanes字段始终是1,但biBitCount字段现在可以是16或32以及1、4、8或24。这也是在Windows 95和Windows NT 4.0中的新特性。一会儿我将介绍这些附加格式工作的方
26、式。现在让我们先跳过biCompression和biSizeImage字段,一会儿再讨论它们。biXPelsPerMeter和biYPelsPerMeter字段以每公尺多少图素这种笨拙的单位指出图像的实际尺寸。(pel-picture element(图像元素)-是IBM对图素的称呼。)Windows在内部不使用此类信息。然而,应用程序能够利用它以准确的大小显示DIB。如果DIB来源于没有方图素的设备,这些字段是很有用的。在大多数DIB内,这些字段设定为0,这表示没有建议的实际大小。每英寸72点的分辨率(有时用于视讯显示器,尽管实际分辨率依赖于显示器的大小)大约相当于每公尺2835个图素,30
27、0 DPI的普通打印机的分辨率是每公尺11,811个图素。biClrUsed是非常重要的字段,因为它影响色彩对照表中项目的数量。对于4位和8位DIB,它能分别指出色彩对照表中包含了小于16或256个项目。虽然并不常用,但这是一种缩小DIB大小的方法。例如,假设DIB图像仅包括64个灰阶,biClrUsed字段设定为64,并且色彩对照表为256个字节大小的色彩对照表包含了64个RGBQUAD结构。图素值的范围从0x00到0x3F。DIB仍然每图素需要1字节,但每个图素字节的高2位为零。如果biClrUsed字段设定为0,意味着色彩对照表包含了由biBitCount字段表示的全部项目数。从Wind
28、ows 95开始,biClrUsed字段对于16位、24位或32位DIB可以为非零。在这些情况下,Windows不使用色彩对照表解释图素位。相反地,它指出DIB中色彩对照表的大小,程序使用该信息来设定调色盘在256色视讯显示器上显示DIB。您可能想起在OS/2兼容格式中,24位DIB没有色彩对照表。在Windows 3.0中的扩展格式中,也与这一样。而在Windows 95中,24位DIB有色彩对照表,biClrUsed字段指出了它的大小。总结如下:· 对于1位DIB,biClrUsed始终是0或2。色彩对照表始终有两个项目。· 对于4位DIB,如果biClrUsed字段是
29、0或16,则色彩对照表有16个项目。如果是从2到15的数,则指的是色彩对照表中的项目数。每个图素的最大值是小于该数的1。· 对于8位DIB,如果biClrUsed字段是0或256,则色彩对照表有256个项目。如果是从2到225的数,则指的是色彩对照表中的项目数。每个图素的最大值是小于该数的1。· 对于16位、24位或32位DIB,biClrUsed字段通常为0。如果它不为0,则指的是色彩对照表中的项目数。执行于256色显示卡的应用程序能使用这些项目来为DIB设定调色盘。另一个警告:原先使用早期DIB文件编写的程序不支持24位DIB中的色彩对照表,如果在程序使用24位DIB的
30、色彩对照表的话,就要冒一定的风险。biClrImportant字段实际上没有biClrUsed字段重要,它通常被设定为0以指出色彩对照表中所有的颜色都是重要的,或者它与biClrUsed有相同的值。两种方法意味着同一件事,如果它被设定为0与biClrUsed之间的值,就意味着DIB图像能仅仅通过色彩对照表中第一个biClrImportant项目合理地取得。当在256色显示卡上并排显示两个或更多8位DIB时,这是很有用的。对于1位、4位、8位和24位的DIB,图素位的组织和OS/2兼容的DIB是相同的,一会儿我将讨论16位和32位DIB。真实检查当遇到一个由其它程序或别人建立的DIB时,您希望从
31、中发现什么内容呢?尽管在Windows3.0首次推出时,OS/2样式的DIB已经很普遍了,但最近这种格式却已经很少出现了。许多程序写作者在实际编写快速DIB例程时忽略了它们。您遇到的任何4位DIB可能是Windows的小画家程序使用16色视讯显示器建立的,在这些显示器上色彩对照表具有标准的16种颜色。最普遍的DIB可能是每图素8位。8位DIB分为两类:灰阶DIB和混色DIB。不幸的是,表头信息中并没有指出8位DIB的型态。许多灰阶DIB有一个等于64的biClrUsed字段,指出色彩对照表中的64个项目。这些项目通常以上升的灰阶层排列,也就是说色彩对照表以00-00-00、04-04-04、0
32、8-08-08、0C-0C-0C的RGB值开始,并包括F0-F0-F0、F4-F4-F4、F8-F8-F8和FC-FC-FC的RGB值。此类色彩对照表可用下列公式计算:rgbi.rgbRed = rgbi.rgbGreen = rgbi.rgbBlue = i * 256 / 64 ; 在这里rgb是RGBQUAD结构的数组,i的范围从0到63。灰阶色彩对照表可用下列公式计算:rgbi.rgbRed = rgbi.rgbGreen = rgbi.rgbBlue = i * 255 / 63 ; 因而此表以FF-FF-FF结尾。实际上使用哪个计算公式并没有什么区别。许多视讯显示卡和显示器没有比6
33、位更大的色彩精确度。第一个公式承认了这个事实。然而当产生小于64的灰阶时可能是16或32(在此情况下公式的除数分别是15和31)使用第二个公式更适合,因为它确保了色彩对照表的最后一个项目是FF-FF-FF,也就是白色。当某些8位灰阶DIB在色彩对照表内有64个项目时,其它灰阶的DIB会有256个项目。biClrUsed字段实际上可以为0(指出色彩对照表中有256个项目)或者从2到256的数。当然,biClrUsed值是2的话就没有任何意义(因为这样的8位DIB能当作1位DIB被重新编码)或者小于或等于16的值也没意义(因为它能当作4位DIB被重新编码)。任何情况下,色彩对照表中的项目数必须与b
34、iClrUsed字段相同(如果biClrUsed是0,则是256),并且图素值不能超过色彩对照表项目数减1的值。这是因为图素值是指向色彩对照表数组的索引。对于biClrUsed值为64的8位DIB,图素值的范围从0x00到0x3F。在这里应记住一件重要的事情:当8位DIB具有由整个灰阶组成的色彩对照表(也就是说,当红色、绿色和蓝色程度相等时),或当这些灰阶层在色彩对照表中递增(像上面描述的那样)时,图素值自身就代表了灰色的程度。也就是说,如果biClrUsed是64,那么0x00图素值为黑色,0x20的图素值是50%的灰阶,0x3F的图素值为白色。这对于一些图像处理作业是很重要的,因为您可以完
35、全忽略色彩对照表,仅需处理图素值。这是很有用的,如果让我回溯时光去对BITMAPINFOHEADER结构做一个简单的更改,我会添加一个旗标指出DIB映像是不是灰阶的,如果是,DIB就没有色彩对照表,并且图素值直接代表灰阶。混色的8位DIB一般使用整个色彩对照表,它的biClrUsed字段为0或256。然而您也可能遇到较小的颜色数,如236。我们应承认一个事实:程序通常只能在Windows颜色面内更改236个项目以正确显示这些DIB,我将在 下章讨论这些内容。biXPelsPerMeter和biYPelsPerMeter很少为非零值,biClrImportant字段不为0或biClrUsed值的
36、情况也很少。DIB压缩前面我没有讨论BITMAPINFOHEADER中的biCompression和biSizeImage字段,现在我们讨论一下这些值。biCompression字段可以为四个常数之一,它们是:BI_RGB、BI_RLE8、BI_RLE4或BI_BITFIELDS。它们定义在WINGDI.H表头文件中,值分别为0到3。此字段有两个用途:对于4位和8位DIB,它指出图素位被用一种运行长度(run-length)编码方式压缩了。对于16位和32位DIB,它指出了颜色屏蔽(color masking)是否用于对图素位进行编码。这两个特性都是在Windows 95中发表的。首先让我们看
37、一下RLE压缩:· 对于1位DIB,biCompression字段始终是BI_RGB。· 对于4位DIB,biCompression字段可以是BI_RGB或BI_RLE4。· 对于8位DIB,biCompression字段可以是BI_RGB或BI_RLE8。· 对于24位DIB,biCompression字段始终是BI_RGB。如果值是BI_RGB,图素位储存的方式和OS/2兼容的DIB一样,否则就使用运行长度编码压缩图素位。运行长度编码(RLE)是一种最简单的数据压缩形式,它是根据DIB映射在一列内经常有相同的图素字符串这个事实进行的。RLE通过对重复
38、图素的值及重复的次数编码来节省空间,而用于DIB的RLE方案只定义了很少的矩形DIB图像,也就是说,矩形的某些区域是未定义的,这能被用于表示非矩形图像。8位DIB的运行长度编码在概念上更简单一些,因此让我们从这里入手。表15-1会帮助您理解当biCompression字段等于BI_RGB8时,图素位的编码方式。表15-1字节1字节2字节3字节4含义0000行尾0001映射尾0002dxdy移到(x+dx,y+dy)00n = 03到FF使用下面n个图素n = 01到FF图素重复图素n次当对压缩的DIB译码时,可成对查看DIB数据字节,例如此表内的字节1和字节2。表格以这些字节值的递增方式排列,
39、但由下而上讨论这个表格会更有意义。如果第一个字节非零(表格最后一行的情况),那么它就是运行长度的重复因子。下面的图素值被重复多次,例如,字节对0x05 0x27 解碼后的图素值为:0x27 0x27 0x27 0x27 0x27 当然DIB会有许多数据不是图素到图素的重复,表格倒数第二行处理这种情况,它指出紧跟着的图素数应逐个使用。例如:考虑序列0x00 0x06 0x45 0x32 0x77 0x34 0x59 0x90 解碼后的图素值为:0x45 0x32 0x77 0x34 0x59 0x90 这些序列总是以2字节的界限排列。如果第二个字节是奇数,那么序列内就有一个未使用的多余字节。例如
40、,序列0x00 0x05 0x45 0x32 0x77 0x34 0x59 0x00 解碼后的图素值为:0x45 0x32 0x77 0x34 0x59 这就是运行长度编码的工作方式。很明显地,如果在DIB图像内没有重复的图素,使用此压缩技术实际上会增加了DIB文件的大小。上面表格的前三行指出了矩形DIB图像的某些部分可以不被定义的方法。想象一下,您写的程序对已压缩的DIB进行解压缩,在这个解压缩的例程中,您将保持一对数字(x,y),开始为(0,0)。每对一个图素译码,x的值就增加1,每完成一行就将x重新设为0并且增加y的值。当遇到跟着0x02的字节0x00时,您读取下两个字节并把它们作为无正
41、负号的增量添加到目前的x和y值中,然后继续解碼。当遇到跟着0x00的0x00时,您就解完了一行,应将x设0并增加y值。当遇到跟着0x01的0x00时,您就完成译码了。这些代码准许DIB包含那些未定义的区域,它们用于对非矩形图像编码或在制作数字动画和电影时非常有用(因为几乎每一格影像都有来自前一格的信息而不需重新编码)。对于4位DIB,编码一般是相同的,但更复杂,因为字节和图素之间不是一对一的关系。如果读取的第一个字节非零,那就是一个重复因子n。第二个字节(被重复的)包含2个图素,在n个图素的被解碼的序列中交替出现。例如,字节对0x07 0x35 被解碼为:0x35 0x35 0x35 0x3?
42、 其中的问号指出图素还未知,如果是上面显示的0x07 0x35对紧跟着下面的字节对:0x05 0x24 则整个解碼的序列为:0x35 0x35 0x35 0x32 0x42 0x42 如果字节对中的第一字节是0x00 ,第二个字节是0x03或更大,则使用第二字节指出的图素数。例如,序列0x00 0x05 0x23 0x57 0x10 0x00 解碼为:0x23 0x57 0x1? 注意必须填补解碼的序列使其成为偶数字节。无论biCompression字段是BI_RLE4或BI_RLE8,biSizeImage字段都指出了字节内DIB图素数据的大小。如果biCompression字段是BI_RG
43、B,则biSizeImage通常为0,但是它能被设定为行内位组长度的biHeight倍,就像在本章前面计算的那样。目前文件说由上而下的DIB不能被压缩。由上而下的DIB是在biHeight字段为负数的情况下出现的。颜色掩码(Color Masking)biCompression字段也用于连结Windows 95中新出现的16位和32位DIB。对于这些DIB,biCompression字段可以是BI_RGB或BI_BITFIELDS(均定义为值3)。让我们看一下24位DIB的图素格式,它始终有一个等于BI_RGB的biCompression字段:也就是说,每一行基本上都是RGBTRIPLE结构的
44、数组,在每行末端有可能补充值以使行内的字节是4的倍数。Error! Reference source not found.对于具有biCompression字段等于BI_RGB的16位DIB,每个图素需要两个字节。颜色是这样来编码的:Error! Reference source not found.每种颜色使用5位。对于行内的第一个图素,蓝色值是第一个字节的最低五位。绿色值在第一和第二个字节中都有位:绿色值的两个最高位是第二个字节中的两个最低位,绿色值的三个最低位是第一个字节中的三个最高位。红色值是第二个字节中的2到6位。第二个字节的最高位是0。当以16位字组存取图素值时,这会更加有意义。因
45、为多个字节值的最低位首先被储存,图素字组如下:Error! Reference source not found.假设在wPixel内储存了16位图素,您能用下列公式计算红色、绿色和蓝色值:Red = (0x7C00 & wPixel) >> 10) << 3 ; Green = (0x03E0 & wPixel) >> 5) << 3 ; Blue = (0x001F & wPixel) >> 0) << 3 ; 首先,使用屏蔽值与图素进行了位AND运算。此结果是:红色向右移动10位,绿色向右移动
46、5位,蓝色向右移动0位。(这些移动值我称之为右移值)。这就产生了从0x00和0x1F的颜色值,这些值必须向左移动3位以合成从0x00到0xF8的颜色值。(这些移动值我称之为左移值。)请记住:如果16位DIB的图素宽度是奇数,每行会在末端补充多余的2字节以使字节宽度能被4整除。对于32位DIB,如果biCompression等于BI_RGB,每个图素需要4字节。蓝色值是第一个字节,绿色为第二个,红色为第三个,第四字节等于0。也可这么说,图素是RGBQUAD结构的数组。因为每个图素的长度是4字节,在列末端就不需填补字节。若想以32位双字组存取每个图素,它就像这样:Error! Reference
47、source not found.如果dwPixel是32位双字组,Red = (0x00FF0000 & dwPixel) >> 16) << 0 ; Green = (0x0000FF00 & dwPixel) >> 8) << 0 ; Blue = (0x000000FF & dwPixel) >> 0) << 0 ; 左移值全为零,因为颜色值在0xFF已是最大。注意这个双字组与Windows GDI函数呼叫中用于指定RGB颜色的32位COLORREF值不一致。在COLORREF值中,红色占最
48、低位的字节。到目前为止,我们讨论了当biCompression字段为BI_RGB时,16位和32位DIB的内定情况。如果biCompression字段为BI_BITFIELDS,则紧跟着DIB的BITMAPINFOHEADER结构的是三个32位颜色屏蔽,第一个用于红色,第二个用于绿色,第三个用于蓝色。可以使用C的位AND运算子(&)把这些屏蔽应用于16位或32位的图素值上。然后通过右移值向右移动结果,这些值只有检查完屏蔽后才能知道。颜色屏蔽的规则应该很明确:每个颜色屏蔽位串内的1必须是连续的,并且1不能在三个屏蔽位串中重迭。让我们来举个例子,如果您有一个16位DIB,并且biCompr
49、ession字段为BI_BITFIELDS。您应该检查BITMAPINFOHEADER结构之后的前三个双字组:0x0000F800 0x000007E0 0x0000001F 注意,因为这是16位DIB,所以只有位于底部16位的位值才能被设定为1。您可以把变量dwMask0、dwMask1和dwMask2设定为这些值。现在可以编写从掩码中计算右移和左移值的一些例程了:int MaskToRShift (DWORD dwMask) int iShift ; if ( dwMask = 0) return 0 ; for ( iShift = 0 ; !(dwMask & 1) ; iShift+) dwMask >>= 1 ; return iShift ; int MaskToLShift (DWORD dwMask) int iShift ; if ( dwMask = 0) return 0 ; while (!(dwMask & 1) dwMask >>= 1 ; for (iShift = 0 ; dwMask & 1 ; iShift+) dwMask >>
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026届河北省邢台宁晋县联考中考历史考前最后一卷含解析
- 2026届江苏省泰州市高港区达标名校中考押题历史预测卷含解析
- 2026年机电一体化专业顶岗实习报告范文
- 危货运输车隐患排查评估整治技术指南(2025年版)
- 基坑施工安全控制要点(完整版)
- 2026年粮储系统新员工心得体会:不负青春艰苦奋斗
- 高铁乘客突发疾病应急演练脚本
- 2026年建筑工程技术专业毕业实习报告
- 2026届山西省运城市芮城县中考语文全真模拟试卷含解析
- 上海市重点达标名校2026届中考押题英语预测卷含答案
- 敦煌曲子戏研究报告
- 新疆2022年中考数学试卷(含答案)
- 人教部编版小学语文说明文阅读专项练习(一)(含答案)
- NB-T35026-2022混凝土重力坝设计规范
- LYT 2085-2013 森林火灾损失评估技术规范
- 工程量清单计价指南(四电部分)
- 怎样才能做到有效巡视病房
- 教师专业发展PPT完整全套教学课件
- 八年级国家义务教育质量监测德育考核试题
- 气体充装站试生产方案
- 《幼儿园游戏化美术教育活动的实践研究》结题报告
评论
0/150
提交评论