您好,欢迎访问三七文档
与设备无关的位图涛儿软件工作室整理编译在上一章我们了解到WindowsGDI位图对象(也称为与设备相关的位图,或DDB)有许多程序设计用途。但是我并没有展示把这些位图储存到磁盘文件或把它们加载内存的方法。这是以前在Windows中使用的方法,现在根本不用了。因为位图的位格式相当依赖于设备,所以DDB不适用于图像交换。DDB内没有色彩对照表来指定位图的位与色彩之间的联系。DDB只有在Windows开机到关机的生命期内被建立和清除时才有意义。在Windows3.0中发表了与设备无关的位图(DIB),提供了适用于交换的图像文件格式。正如您所知的,像.GIF或.JPEG之类的其它图像文件格式在Internet上比DIB文件更常见。这主要是因为.GIF和.JPEG格式进行了压缩,明显地减少了下载的时间。尽管有一个用于DIB的压缩方案,但极少使用。DIB内的位图几乎都没有被压缩。如果您想在程序中操作位图,这实际上是一个优点。DIB不像.GIF和.JPEG文件,WindowsAPI直接支持DIB。如果在内存中有DIB,您就可以提供指向该DIB的指标作为某些函数的参数,来显示DIB或把DIB转化为DDB。DIB文件格式有意思的是,DIB格式并不是源自于Windows。它首先定义在OS/2的1.1版中,该操作系统最初由IBM和Microsoft在八十年代中期开始开发。OS/21.1在1988年发布,并且是第一个包含了类似Windows的图形使用者接口的OS/2版本,该图形使用者接口被称之为「PresentationManager(PM)」。「PresentationManager」包含了定义位图格式的「图形程序接口」(GPI)。然后在Windows3.0中(发布于1990)使用了OS/2位图格式,这时称之为DIB。Windows3.0也包含了原始DIB格式的变体,并在Windows下成为标准。在Windows95(以及WindowsNT4.0)和Windows98(以及WindowsNT5.0)下也定义了一些其它的增强能力,我会在本章讨论它们。DIB首先作为一种文件格式,它的扩展名为.BMP,在极少情况下为.DIB。Windows应用程序使用的位图图像被当做DIB文件建立,并作为只读资源储存在程序的可执行文件中。图标和鼠标光标也是形式稍有不同的DIB文件。程序能将DIB文件减去前14个字节加载连续的内存块中。这时就可以称它为「packedDIB(packed-DIB)格式的位图」。在Windows下执行的应用程序能使用packedDIB格式,通过Windows剪贴簿来交换图像或建立画刷。程序也可以完全存取DIB的内容并以任意方式修改DIB。程序也能在内存中建立自己的DIB然后把它们存入文件。程序使用GDI函数呼叫就能「绘制」这些DIB内的图像,也能在程序中利用别的内存DIB直接设定和操作图素位。在内存中加载了DIB后,程序也能通过几个WindowsAPI函数呼叫来使用DIB数据,我将在本章中讨论有关内容。与DIB相关的API呼叫是很少的,并且主要与视讯显示器或打印机页面上显示DIB相关,还与转换GDI位图对象有关。除了这些内容以外,还有许多应用程序需要完成的DIB任务,而这些任务Windows操作系统并不支持。例如,程序可能存取了24位DIB并且想把它转化为带有最佳化的256色调色盘的8位DIB,而Windows不会为您执行这些操作。但是在本章和下一章将向您显示WindowsAPI之外的操作DIB的方式。OS/2样式的DIB先不要陷入太多的细节,让我们看一下与首先在OS/21.1中出现的位图格式兼容的WindowsDIB格式。DIB文件有四个主要部分:文件表头信息表头RGB色彩对照表(不一定有)位图图素位您可以把前两部分看成是C的数据结构,把第三部分看成是数据结构的数组。在Windows表头文件WINGDI.H中说明了这些结构。在内存中的packedDIB格式内有三个部分:信息表头RGB色彩对照表(不一定有)位图图素位除了没有文件表头外,其它部分与储存在文件内的DIB相同。DIB文件(不是内存中的packedDIB)以定义为如下结构的14个字节的文件表头开始:typedefstructtagBITMAPFILEHEADER//bmfh{WORDbfType;//signaturewordBMor0x4D42DWORDbfSize;//entiresizeoffileWORDbfReserved1;//mustbezeroWORDbfReserved2;//mustbezeroDWORDbfOffsetBits;//offsetinfileofDIBpixelbits}BITMAPFILEHEADER,*PBITMAPFILEHEADER;在WINGDI.H内定义的结构可能与这不完全相同,但在功能上是相同的。第一个注释(就是文字「bmfh」)指出了给这种数据型态的数据变量命名时推荐的缩写。如果在我的程序内看到了名为pbmfh的变量,这可能是一个指向BITMAPFILEHEADER型态结构的指针或指向PBITMAPFILEHEADER型态变量的指针。结构的长度为14字节,它以两个字母「BM」开头以指明是位图文件。这是一个WORD值0x4D42。紧跟在「BM」后的DWORD以字节为单位指出了包括文件表头在内的文件大小。下两个WORD字段设定为0。(在与DIB文件格式相似的鼠标光标文件内,这两个字段指出光标的「热点(hotspot)」)。结构还包含一个DWORD字段,它指出了文件中图素位开始位置的字节偏移量。此数值来自DIB信息表头中的信息,为了使用的方便提供在这里。在OS/2样式的DIB内,BITMAPFILEHEADER结构后紧跟了BITMAPCOREHEADER结构,它提供了关于DIB图像的基本信息。紧缩的DIB(PackedDIB)开始于BITMAPCOREHEADER:typedefstructtagBITMAPCOREHEADER//bmch{DWORDbcSize;//sizeofthestructure=12WORDbcWidth;//widthofimageinpixelsWORDbcHeight;//heightofimageinpixelsWORDbcPlanes;//=1WORDbcBitCount;//bitsperpixel(1,4,8,or24)}BITMAPCOREHEADER,*PBITMAPCOREHEADER;「core(核心)」用在这里看起来有点奇特,它是指这种格式是其它由它所衍生的位图格式的基础。BITMAPCOREHEADER结构中的bcSize字段指出了数据结构的大小,在这种情况下是12字节。bcWidth和bcHeight字段包含了以图素为单位的位图大小。尽管这些字段使用WORD意味着一个DIB可能为65,535图素高和宽,但是我们几乎不会用到那么大的单位。bcPlanes字段的值始终是1。这个字段是我们在上一章中遇到的早期WindowsGDI位图对象的残留物。bcBitCount字段指出了每图素的位数。对于OS/2样式的DIB,这可能是1、4、8或24。DIB图像中的颜色数等于2bmch.bcBitCount,或用C的语法表示为:1bmch.bcBitCount这样,bcBitCount字段等于:1代表2色DIB4代表16色DIB8代表256色DIB24代表full-ColorDIB当我提到「8位DIB」时,就是说每图素占8位的DIB。对于前三种情况(也就是位数为1、4和8时),BITMAPCOREHEADER后紧跟色彩对照表,24位DIB没有色彩对照表。色彩对照表是一个3字节RGBTRIPLE结构的数组,数组中的每个元素代表图像中的每种颜色:typedefstructtagRGBTRIPLE//rgbt{BYTErgbtBlue;//bluelevelBYTErgbtGreen;//greenlevelBYTErgbtRed;//redlevel}RGBTRIPLE;这样排列色彩对照表以便DIB中最重要的颜色首先显示,我们将在下一章说明原因。WINGDI.H表头文件也定义了下面的结构:typedefstructtagBITMAPCOREINFO//bmci{BITMAPCOREHEADERbmciHeader;//core-headerstructureRGBTRIPLEbmciColors[1];//colortablearray}BITMAPCOREINFO,*PBITMAPCOREINFO;这个结构把信息表头与色彩对照表结合起来。虽然在这个结构中RGBTRIPLE结构的数量等于1,但在DIB文件内您绝对不会发现只有一个RGBTRIPLE。根据每个图素的位数,色彩对照表的大小始终是2、16或256个RGBTRIPLE结构。如果需要为8位DIB配置PBITMAPCOREINFO结构,您可以这样做:pbmci=malloc(sizeof(BITMAPCOREINFO)+255*sizeof(RGBTRIPLE));然后可以这样存取RGBTRIPLE结构:pbmci-bmciColors[i]因为RGBTRIPLE结构的长度是3字节,许多RGBTRIPLE结构可能在DIB中以奇数地址开始。然而,因为在DIB文件内始终有偶数个的RGBTRIPLE结构,所以紧跟在色彩对照表数组后的数据块总是以WORD地址边界开始。紧跟在色彩对照表(24位DIB中是信息表头)后的数据是图素位本身。由下而上像大多数位图格式一样,DIB中的图素位是以水平行组织的,用视讯显示器硬件的术语称作「扫描线」。行数等于BITMAPCOREHEADER结构的bcHeight字段。然而,与大多数位图格式不同的是,DIB从图像的底行开始,往上表示图像。在此应定义一些术语,当我们说「顶行」和「底行」时,指的是当其正确显示在显示器或打印机的页面上时出现在虚拟图像的顶部和底部。就好像肖像的顶行是头发,底行是下巴,在DIB文件中的「第一行」指的是DIB文件的色彩对照表后的图素行,「最后行」指的是文件最末端的图素行。因此,在DIB中,图像的底行是文件的第一行,图像的顶行是文件的最后一行。这称之为由下而上的组织。因为这种组织和直觉相反,您可能会问:为什么要这么做?好,现在我们回到OS/2的PresentationManager。IBM的人认为PM内的坐标系统-包括窗口、图形和位图-应该是一致的。这引起了争论:大多数人,包括在全画面文字方式下编程和窗口环境下工作的程序写作者认为应使用垂直坐标在屏幕上向下增加的坐标。然而,计算机图形程序写作者认为应使用解析几何的数学方法进行视讯显示,这是一个垂直坐标在空间中向上增加的直角(或笛卡尔)坐标系。简而言之,数学方法赢了。PM内的所有事物都以左下角为原点(包括窗口坐标),因此DIB也就有了那种方式。DIB图素位DIB文件的最后部分(在大多数情况下是DIB文件的主体)由实际的DIB的图素字节成。图素位是由从图像的底行开始并沿着图像向上增长的水平行组织的。DIB中的行数等于BITMAPCOREHEADER结构的bcHeight字段。每一行的图素数等于该结构的bcWidth字段。每一行从最左边的图素开始,直到图像的右边。每个图素的位数可以从bcBitCount字段取得,为1、4、8或24。以字节为单位的每行长度始终是4的倍数。行的长度可以计算为:RowLength=4*((bmch.bcWidth*bmch.bcBitCount+31)/32);或者在C内用更有效的方法:RowLength=((bmch.bcWidth*bmch.bcBitCount+31)&~31)3;如果需要,可通过在右边补充行(通常是用零)来完成长度。图素数据的总字节数等于RowLength和bmch.bcHeight的乘积。要了解图素编码的方式,让我们分别考虑四种情况。在下面的图表中,每个字节的位显示
本文标题:与设备无关的位图
链接地址:https://www.777doc.com/doc-1308573 .html