探究 DIB:
DIB 除了这种格式:
- 文件头
- 信息头
- RGB 颜色表(有时可能没有)
- 位图像素位
还有下面的格式(紧凑 DIB 格式):
- 信息头
- RGB 颜色表(有时可能没有)
- 位图像素位
注意:①紧凑DIB在内存中是连续的,即整个DIB存在单个内存块中
②DIB载入内存时,像素位与信息头可以分别存在两个内存块,即内存不连续。
Windows 扩展 DIB
该扩展格式增加了一点小的变动,我们可以再看看 扩展DIB 文件的结构体!
typedef struct tagBITMAPINFOHEADER { DWORD biSize; // 结构体大小 = 40 LONG biWidth; // 以像素计的图像的宽度 LONG biHeight; // 以像素计的图像的高度 WORD biPlanes; // = 1 WORD biBitCount; // 每个像素的位数(1,4,8,16,24,32) 自己测试发现 只有16位以上的才是彩色的。 DWORD biCompression; // 压缩编码 通常为 BI_RGB DWORD biSizeImage; // 图像的字节数 LONG biXPelsPerMeter; // 水平分辨率,通常为 0 LONG biYPelsPerMeter; // 垂直分辨率,通常为 0 DWORD biClrUsed; // 用到的颜色数,(1,4,8 的情况下)0 或 2^biClrUsed 都为最大值。 DWORD biClrImportant; // 重要颜色的数目,通常为 0 或 biClrUsed 的值 } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
RGBQUAD 结构体
typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; // = 0; } RGBQUAD;
BITMAPINFO 结构体
typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1]; } BITMAPINFO;
通过剪贴板传输 DIB 时就需要紧凑 DIB 格式,从 DIB 创建一个画刷也同样需要这种格式。
这种格式能使 DIB 方便地存储在内存种,因为整个 DIB 被单个指针引用。
上次我们说了有些函数可以使 DIB 文件紧密的联系起来,现在就来介绍一下:
这两个函数放在 WM_PAINT 消息下面就可以显示图像。
SetDIBitsToDevice() 介绍:
功能:使用 DIB、JPEG 或 PNG 图像中的颜色数据来设置与目标设备上下文关联的设备上指定矩形中的像素。
函数原型:int SetDIBitsToDevice(
HDC hdc, // 设备环境句柄。
int xDest, //指定目标矩形左上角的X轴坐标,按逻辑单位表示坐标。
int yDest, // 指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。
DWORD w, // 指定DIB的宽度,按逻辑单位表示宽度。
DWORD h, // 指定DIB的高度,按逻辑单位表示高度。
int xSrc, //指定DIB 位图左下角的X轴坐标,按逻辑单位表示坐标。通常为 0.
int ySrc,// 指定DIB 位图左下角的Y轴坐标,按逻辑单位表示坐标。通常为 0.
UINT StartScan,// 指定DIB中的起始扫描线。通常为 0.
UINT cLines,//指定参数lpvBits指向的数组中包含的DIB扫描线数目。
CONST VOID *lpvBits, // 指向存储DIB颜色数据的字节类型数组的指针。
CONST BITMAPINFO *lpbmi, //指向BITMAPINFO结构的指针。
UINT ColorUse // 指向BITMAPINFO结构中的成员bmiColors是否包含明确的RGB值或对调色板进行索引的值。
);
参数
ColorUse
StretchDIBits() 介绍:
功能:将 DIB、JPEG 或 PNG 图像中的像素矩形的颜色数据复制到指定的目标矩形。
如果目标矩形大于源矩形, 则此函数将拉伸颜色数据的行和列以适应目标矩形。
如果目标矩形小于源矩形, 则此函数使用指定的光栅操作压缩行和列。
函数原型:int StretchDIBits(
HDC hdc, // 指向目标设备环境的句柄。
int xDest, // 指定目标矩形左上角位置的X轴坐标,按逻辑单位来表示坐标。
int yDest, // 指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。
int DestWidth, // 指定目标矩形的宽度。
int DestHeight,// 指定目标矩形的高度。
int xSrc, // 指定DIB中源矩形(左上角)的X轴坐标,坐标以像素点表示。
int ySrc, // 指定DIB中源矩形(左上角)的Y轴坐标,坐标以像素点表示。
int SrcWidth, // 按像素点指定DIB中源矩形的宽度。
int SrcHeight, // 按像素点指定DIB中源矩形的高度。
CONST VOID *lpBits, // 指向 DIB 位的指针。
CONST BITMAPINFO *lpbmi, // 指向BITMAPINFO结构的指针。
UINT iUsage, // 表示是否提供了BITMAPINFO结构中的成员bmiColors。同上面一样。
DWORD rop // 指定源像素点、目标设备环境的当前刷子和目标像素点是如何组合形成新的图像。
);
返回值:如果函数执行成功,那么返回值是拷贝的扫描线数目,如果函数执行失败,那么返回值是GDI_ERROR。
CreateDIBitmap() 介绍:
功能:从 DIB 创建兼容位图 (DDB), 并可选地设置位图位。
函数原型:HBITMAP CreateDIBitmap(
HDC hdc, // 设备环境句柄。
CONST BITMAPINFOHEADER *pbmih, // 指向位图信息头结构的指针。
DWORD flInit, // 位标识集。它指定系统如何对位图的位进行初始化。
CONST VOID *pjBits, // 指向包含初始的位图数据的字节类型数组。
CONST BITMAPINFO *pbmi, // 指向BITMAPINFO结构的指针。
UINT iUsage // 表示BITMAPINFO结构的成员bmiColors是否初始化过。
);
参数
Fdwlnit
CBM_INIT:如果设置了该标志,那么系统将使用lpblnit和lpbmi两个参数指向的数据来对位图中的位进行初始化。
如果没有该标志,那么表示上述两个参数指向的数据无效。如果fdwlnit为0,那么系统不会对位图的位进行初始化。
iUsage
SetDIBits() 介绍:
功能:使用指定的DIB位图中发现的颜色数据来设置位图中的像素。
函数原型:int SetDIBits(
HDC hdc, // 指向设备环境中的句柄。
HBITMAP hbm, // 指向位图的句柄。
UINT start, // 为参数lpvBits指向的数组中的、与设备无关的颜色数据指定起始扫描线。
UINT cLines, // 为包含与设备无关的颜色数据的数组指定扫描线数目。
CONST VOID *lpBits, // 指向DIB颜色数据的指针。
CONST BITMAPINFO *lpbmi, // 指向BITMAPINFO数据结构的指针
UINT ColorUse // 同上。
);
返回值:如果函数成功,那么返回值就是复制的扫描线数;如果函数失败,那么返回值是0。
CreateDIBSection() 介绍:
功能:创建一个 DIB, 应用程序可以直接写入。该函数提供指向位图位值位置的指针。
您可以提供该函数将用于创建位图的文件映射对象的句柄, 也可以让系统为位图分配内存。
函数原型:HBITMAP CreateDIBSection(
HDC hdc, // 设备环境句柄。
CONST BITMAPINFO *pbmi, // 指向BITMAPINFO结构的指针。
UINT usage, // 同上。如果该参数为为 0,则 hdc 为 NULL。
VOID **ppvBits, // 指向一个指针变量的指针,该变量接收一个指向DIB位数据值的指针。
HANDLE hSection, // 件映射对象的句柄。函数将使用该对象来创建DIB。该参数可以是NULL。
DWORD offset // 指定从hSection引用的文件映射对象开始处算起的偏移量。
);
参数
hSection
现在介绍怎么使用吧!
当我们有一个 DIB 时,便可以用 CreateCompatibleBitmap() 来创建一个 GDI 位图对象。
然后再把这个位图对象选入内存设备环境中,最后调用 SetDIBitsToDevice() 在这个内存设备环境上绘图。或者也可以用 CreateDIBitmap() 分几步完成同样的事情。
对于 CreateDIBSection() 返回的位图句柄,我们应该用 DIBSECTION 结构来调用 GetObject()。
DIBSECTION 结构体:
typedef struct tagDIBSECTION { BITMAP dsBm; // BITMAP 结构 BITMAPINFOHEADER dsBmih; // DIB 信息头 DWORD dsBitfields[3]; // 颜色遮罩 HANDLE dshSection; // 文件映射对象句柄 DWORD dsOffset; // 像素位数据的位移 } DIBSECTION,*PDIBSECTION;
例如:GetObject(hBitmap, sizeof(DIBSECTION), &DIBSecion) ;
DIBSECTION 结构体告诉了你很多有关位图的信息,但是不包括颜色表。
在把 DIB 区块位图句柄选入一个内存设备环境之后,可以用 GetDIBColorTable() 来获得颜色表;
类似地,还可以用 SetDIBColorTable() 来设置颜色表中的数据。
SetDIBColorTable() 介绍:
功能:用来对目前进入指定 DIB 颜色表中的项设置RGB颜色值。
函数原型:UINT SetDIBColorTable(
HDC hdc, // 设备上下文。必须将 DIB 选择到此设备上下文中。
UINT iStart, // 一个从零开始的颜色表索引, 它指定要设置的第一个颜色表项。
UINT cEntries, // 要设置的颜色表项的数目。
CONST RGBQUAD *prgbq // 指向包含 DIB 颜色表的新颜色信息的 RGBQUAD 结构数组的指针。
);
返回值:如果函数执行成功,那么返回值就是该函数设置的颜色表项的数目;如果函数执行失败,那么返回值为0。
GetDIBColorTable() 介绍:
功能:从DIB位图的颜色表中检索RGB颜色值,此DIB位图是当前选入指定设备环境中的位图。
函数原型:UINT GetDIBColorTable(
HDC hdc, // 设备上下文的句柄。必须将 DIB 节位图选择到此设备上下文中。
UINT iStart, // 一个从零开始的颜色表索引, 它指定要检索的第一个颜色表项。
UINT cEntries, // 要检索的颜色表项的数目。
RGBQUAD *prgbq // 一个指向缓冲区的指针, 它接收包含 DIB 颜色表中的颜色信息的 RGBQUAD 数据结构数组。
);
返回值:返回值:如果函数执行成功,那么返回值就是函数检索到的颜色表项的数目;如果函数执行失败,那么返回值为0。