windows3.0与OS/2兼容的DIB(BITMAPCOREHEADER结构解析)

来源:互联网 发布:东方网络 编辑:程序博客网 时间:2024/06/11 16:51
在OS/2样式的DIB内,BITMAPFILEHEADER结构后紧跟了BITMAPCOREHEADER结构,它提供了关于DIB图像的基本信息。紧缩的DIB(Packed DIB)开始于BITMAPCOREHEADER:
typedef struct tagBITMAPCOREHEADER // bmch
{
DWORD bcSize ; // size of the structure = 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字段指出了数据结构的大小,在这种情况下是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
整理编撰:Defoe.Tu 
4代表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 level
}
RGBTRIPLE ;
这样排列色彩对照表以便DIB中最重要的颜色首先显示,我们将在下一章说明原因。
WINGDI.H表头文件也定义了下面的结构:
typedef struct tagBITMAPCOREINFO // bmci
{
BITMAPCOREHEADER bmciHeader ; // core-header structure
RGBTRIPLE bmciColors[1] ; // color table array
}
BITMAPCOREINFO, * PBITMAPCOREINFO ;
这个结构把信息表头与色彩对照表结合起来。虽然在这个结构中RGBTRIPLE结构的数量等于1,但在DIB文件内您绝对不会发现只有一个RGBTRIPLE。根据每个图素的位数,色彩对照表的大小始终是2、16或256个RGBTRIPLE结构。如果需要为8位DIB配置PBITMAPCOREINFO结构,您可以这样做:
pbmci = malloc (sizeof (BITMAPCOREINFO) + 255 * sizeof (RGBTRIPLE)) ;
然后可以这样存取RGBTRIPLE结构:
整理编撰:Defoe.Tu 
pbmci->bmciColors[i]
因为RGBTRIPLE结构的长度是3字节,许多RGBTRIPLE结构可能在DIB中以奇数地址开始。然而,因为在DIB文件内始终有偶数个的RGBTRIPLE结构,所以紧跟在色彩对照表数组后的数据块总是以WORD地址边界开始。
紧跟在色彩对照表(24位DIB中是信息表头)后的数据是图素位本身。
由下而上
像大多数位图格式一样,DIB中的图素位是以水平行组织的,用视讯显示器硬件的术语称作「扫描线」。行数等于BITMAPCOREHEADER结构的bcHeight字段。然而,与大多数位图格式不同的是,DIB从图像的底行开始,往上表示图像。
在此应定义一些术语,当我们说「顶行」和「底行」时,指的是当其正确显示在显示器或打印机的页面上时出现在虚拟图像的顶部和底部。就好像肖像的顶行是头发,底行是下巴,在DIB文件中的「第一行」指的是DIB文件的色彩对照表后的图素行,「最后行」指的是文件最末端的图素行。
因此,在DIB中,图像的底行是文件的第一行,图像的顶行是文件的最后一行。这称之为由下而上的组织。因为这种组织和直觉相反,您可能会问:为什么要这么做?
好,现在我们回到OS/2的Presentation Manager。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 ;
如果需要,可通过在右边补充行(通常是用零)来完成长度。图素数据的总字节数等于
整理编撰:Defoe.Tu 
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没有色彩对照表。