与设备无关的位图.docx

上传人:b****5 文档编号:8633757 上传时间:2023-02-01 格式:DOCX 页数:175 大小:363.10KB
下载 相关 举报
与设备无关的位图.docx_第1页
第1页 / 共175页
与设备无关的位图.docx_第2页
第2页 / 共175页
与设备无关的位图.docx_第3页
第3页 / 共175页
与设备无关的位图.docx_第4页
第4页 / 共175页
与设备无关的位图.docx_第5页
第5页 / 共175页
点击查看更多>>
下载资源
资源描述

与设备无关的位图.docx

《与设备无关的位图.docx》由会员分享,可在线阅读,更多相关《与设备无关的位图.docx(175页珍藏版)》请在冰豆网上搜索。

与设备无关的位图.docx

与设备无关的位图

与设备无关的位图

与设备无关的位图

涛儿软件工作室  整理编译  

在上一章我们了解到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;//signatureword"BM"or0x4D42

DWORDbfSize;//entiresizeoffile

WORDbfReserved1;//mustbezero

WORDbfReserved2;//mustbezero

DWORDbfOffsetBits;//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=12

WORDbcWidth;//widthofimageinpixels

WORDbcHeight;//heightofimageinpixels

WORDbcPlanes;//=1

WORDbcBitCount;//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的语法表示为:

1<

这样,bcBitCount字段等于:

∙1代表2色DIB

 

∙4代表16色DIB

 

∙8代表256色DIB

 

∙24代表full-ColorDIB

 

当我提到「8位DIB」时,就是说每图素占8位的DIB。

对于前三种情况(也就是位数为1、4和8时),BITMAPCOREHEADER后紧跟色彩对照表,24位DIB没有色彩对照表。

色彩对照表是一个3字节RGBTRIPLE结构的数组,数组中的每个元素代表图像中的每种颜色:

typedefstructtagRGBTRIPLE//rgbt

{

BYTErgbtBlue;//bluelevel

BYTErgbtGreen;//greenlevel

BYTErgbtRed;//redlevel

}

RGBTRIPLE;

这样排列色彩对照表以便DIB中最重要的颜色首先显示,我们将在下一章说明原因。

WINGDI.H表头文件也定义了下面的结构:

typedefstructtagBITMAPCOREINFO//bmci

{

BITMAPCOREHEADERbmciHeader;//core-headerstructure

RGBTRIPLEbmciColors[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的乘积。

要了解图素编码的方式,让我们分别考虑四种情况。

在下面的图表中,每个字节的位显示在框内并且编了号,7表示最高位,0表示最低位。

图素也从行的最左端从0开始编号。

对于每图素1位的DIB,每字节对应为8图素。

最左边的图素是第一个字节的最高位:

 

每个图素可以是0或1。

0表示该图素的颜色由色彩对照表中第一个RGBTRIPLE项目给出。

1表示图素的颜色由色彩对照表的第二个项目给出。

对于每图素4位的DIB,每个字节对应两个图素。

最左边的图素是第一个字节的高4位,以此类推:

 

每图素4位的值的范围从0到15。

此值是指向色彩对照表中16个项目的索引。

对于每图素8位的DIB,每个字节为1个图素:

 

字节的值从0到255。

同样,这也是指向色彩对照表中256个项目的索引。

对于每图素24位的DIB,每个图素需要3个字节来代表红、绿和蓝的颜色值。

图素位的每一行,基本上就是RGBTRIPLE结构的数组,可能需要在每行的末端补0以便该行为4字节的倍数:

 

每图素24位的DIB没有色彩对照表。

扩展的WindowsDIB

现在我们掌握了Windows3.0中介绍的与OS/2兼容的DIB,同时也看一看Windows中DIB的扩展版本。

这种DIB形式跟前面的格式一样,以BITMAPFILEHEADER结构开始,但是接着是BITMAPINFOHEADER结构,而不是BITMAPCOREHEADER结构:

typedefstructtagBITMAPINFOHEADER//bmih

{

DWORDbiSize;//sizeofthestructure=40

LONGbiWidth;//widthoftheimageinpixels

LONGbiHeight;//heightoftheimageinpixels

WORDbiPlanes;//=1

WORDbiBitCount;//bitsperpixel(1,4,8,16,24,or32)

DWORDbiCompression;//compressioncode

DWORDbiSizeImage;//numberofbytesinimage

LONGbiXPelsPerMeter;//horizontalresolution

LONGbiYPelsPerMeter;//verticalresolution

DWORDbiClrUsed;//numberofcolorsused

DWORDbiClrImportant;//numberofimportantcolors

}

BITMAPINFOHEADER,*PBITMAPINFOHEADER;

您可以通过检查结构的第一字段区分与OS/2兼容的DIB和WindowsDIB,前者为12,后者为40。

您将注意到,在这个结构内有六个附加的字段,但是BITMAPINFOHEADER不是简单地由BITMAPCOREHEADER加上一些新字段而成。

仔细看一下:

在BITMAPCOREHEADER结构中,bcWidth和bcHeight字段是16位WORD值;而在BITMAPINFOHEADER结构中它们是32位LONG值。

这是一个令人讨厌的小变化,当心它会给您带来麻烦。

另一个变化是:

对于使用BITMAPINFOHEADER结构的1位、4位和8位DIB,色彩对照表不是RGBTRIPLE结构的数组。

相反,BITMAPINFOHEADER结构紧跟着一个RGBQUAD结构的数组:

typedefstructtagRGBQUAD//rgb

{

BYTErgbBlue;//bluelevel

BYTErgbGreen;//greenlevel

BYTErgbRed;//redlevel

BYTErgbReserved;//=0

}

RGBQUAD;

除了包括总是设定为0的第四个字段外,与RGBTRIPLE结构相同。

WINGDI.H表头文件也定义了以下结构:

typedefstructtagBITMAPINFO//bmi

{

BITMAPINFOHEADERbmiHeader;//info-headerstructure

RGBQUADbmiColors[1];//colortablearray

}

BITMAPINFO,*PBITMAPINFO;

注意,如果BITMAPINFO结构以32位的地址边界开始,因为BITMAPINFOHEADER结构的长度是40字节,所以RGBQUAD数组内的每一个项目也以32位边界开始。

这样就确保通过32位微处理器能更有效地对色彩对照表数据寻址。

尽管BITMAPINFOHEADER最初是在Windows3.0中定义的,但是许多字段在Windows95和WindowsNT4.0中又重新定义了,并且被带入Windows98和WindowsNT5.0中。

比如现在的文件中说:

「如果biHeight是负数,则位图是由上而下的DIB,原点在左上角」。

这很好,但是在1990年刚开始定义DIB格式时,如果有人做了这个决定,那会更好。

我的建议是避免建立由上而下的DIB。

有一些程序在编写时没有考虑这种新「特性」,在遇到负的biHeight字段时会当掉。

还有如MicrosoftWord97带有的MicrosoftPhotoEditor在遇到由上而下的DIB时会报告「图像高度不合法」(虽然Word97本身不会出错)。

biPlanes字段始终是1,但biBitCount字段现在可以是16或32以及1、4、8或24。

这也是在Windows95和WindowsNT4.0中的新特性。

一会儿我将介绍这些附加格式工作的方式。

现在让我们先跳过biCompression和biSizeImage字段,一会儿再讨论它们。

biXPelsPerMeter和biYPelsPerMeter字段以每公尺多少图素这种笨拙的单位指出图像的实际尺寸。

(「pel」--pictureelement(图像元素)--是IBM对图素的称呼。

)Windows在内部不使用此类信息。

然而,应用程序能够利用它以准确的大小显示DIB。

如果DIB来源于没有方图素的设备,这些字段是很有用的。

在大多数DIB内,这些字段设定为0,这表示没有建议的实际大小。

每英寸72点的分辨率(有时用于视讯显示器,尽管实际分辨率依赖于显示器的大小)大约相当于每公尺2835个图素,300DPI的普通打印机的分辨率是每公尺11,811个图素。

biClrUsed是非常重要的字段,因为它影响色彩对照表中项目的数量。

对于4位和8位DIB,它能分别指出色彩对照表中包含了小于16或256个项目。

虽然并不常用,但这是一种缩小DIB大小的方法。

例如,假设DIB图像仅包括64个灰阶,biClrUsed字段设定为64,并且色彩对照表为256个字节大小的色彩对照表包含了64个RGBQUAD结构。

图素值的范围从0x00到0x3F。

DIB仍然每图素需要1字节,但每个图素字节的高2位为零。

如果biClrUsed字段设定为0,意味着色彩对照表包含了由biBitCount字段表示的全部项目数。

从Windows95开始,biClrUsed字段对于16位、24位或32位DIB可以为非零。

在这些情况下,Windows不使用色彩对照表解释图素位。

相反地,它指出DIB中色彩对照表的大小,程序使用该信息来设定调色盘在256色视讯显示器上显示DIB。

您可能想起在OS/2兼容格式中,24位DIB没有色彩对照表。

在Windows3.0中的扩展格式中,也与这一样。

而在Windows95中,24位DIB有色彩对照表,biClrUsed字段指出了它的大小。

总结如下:

∙对于1位DIB,biClrUsed始终是0或2。

色彩对照表始终有两个项目。

 

∙对于4位DIB,如果biClrUsed字段是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的色彩对照表的话,就要冒一定的风险。

biClrImportant字段实际上没有biClrUsed字段重要,它通常被设定为0以指出色彩对照表中所有的颜色都是重要的,或者它与biClrUsed有相同的值。

两种方法意味着同一件事,如果它被设定为0与biClrUsed之间的值,就意味着DIB图像能仅仅通过色彩对照表中第一个biClrImportant项目合理地取得。

当在256色显示卡上并排显示两个或更多8位DIB时,这是很有用的。

对于1位、4位、8位和24位的DIB,图素位的组织和OS/2兼容的DIB是相同的,一会儿我将讨论16位和32位DIB。

真实检查

当遇到一个由其它程序或别人建立的DIB时,您希望从中发现什么内容呢?

尽管在Windows3.0首次推出时,OS/2样式的DIB已经很普遍了,但最近这种格式却已经很少出现了。

许多程序写作者在实际编写快速DIB例程时忽略了它们。

您遇到的任何4位DIB可能是Windows的「小画家」程序使用16色视讯显示器建立的,在这些显示器上色彩对照表具有标准的16种颜色。

最普遍的DIB可能是每图素8位。

8位DIB分为两类:

灰阶DIB和混色DIB。

不幸的是,表头信息中并没有指出8位DIB的型态。

许多灰阶DIB有一个等于64的biClrUsed字段,指出色彩对照表中的64个项目。

这些项目通常以上升的灰阶层排列

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1