位图(二)

探究 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

DIB_PAL_COLORS:表示颜色表由16位的索引值数组组成,利用这些值可对当前选中的逻辑调色板进行索引。
DIB_RGB_COLORS:表示颜色表包含原义的RGB值。该参数的值为 0。
返回值:如果函数执行成功,那么返回值是设置的扫描线数目;如果函数失败,那么返回值为0。

 

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

如果是,那么bmiColors是否包含明确的红、绿、蓝(RGB)值或调色板索引。
参数fuUsage必须取下列值中的一个,这些值的含义为:
DIB_PAL_COLORS:表示提供一个颜色表,并且该表由位图要选入的设备环境的逻辑调色板的16位索引值数组组成。
DIB_RGB_COLORS:表示提供一个颜色表,并且表中包含了原义的RGB值。
返回值:如果执行成功,返回值则是创建的位图的句柄;如果函数执行失败,那么返回值为NULL。

 

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

如果hSection不是NULL,那么它一定是文件映射对象的句柄。
该对象是通过调用带有PAGE_READWRITE或PAGE_WRITECOPY标志的CreateFileMapping函数创建的。
如果hSection不是NULL,那么函数CreateDIBSection将在hSection引用的文件映射对象中偏移量为dwOffset处获取位图的位数据值。
应用程序可以在以后通过调用GetObject函数来检索hSection句柄,其中GetObject函数使用了GreateDIBSection函数返回的GBITMAP类型的对象。
如果hSection为NULL,那么系统将为与设备无关位图(DIB)分配内存。
在这种情况下,函数CreateDIBSection将忽略参数dwOffset,应用程序无法在以后获取指向内存的句柄。
通过调用GetObject函数来填充的DIBSECTION结构成员dshSection也将成为NULL。
offset
指定从hSection引用的文件映射对象开始处算起的偏移量。超过这个偏移量的地方就是位图的位数据值开始存放的地方。
在hSection为NULL时忽略该值。位图的位数据值是以DWORD为单位计算的。
返回值:如果函数执行成功,那么返回值是一个指向刚刚创建的与设备无关位图的句柄,并且**ppvBits指向该位图的位数据值;
               如果函数执行失败,那么返回值为NULL,并且**ppvBit也为NULL。
 
 

现在介绍怎么使用吧!

当我们有一个 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。

 

posted @ 2018-08-11 08:26  M-Anonymous  阅读(452)  评论(0编辑  收藏  举报