GDI编程之 Bitmap

来源:互联网 发布:爱知科技几号发工资 编辑:程序博客网 时间:2024/05/17 07:06

文章出自:http://www.cnblogs.com/whyandinside/articles/1525924.html

 

DIB,全称Device Independent Bitmap,设备无关位图文件,这是一种文件格式,其目的是为了保证用某个应用程序创建的位图图形可以被其它应用程序装载或显示一样。 DIB(Device-indepentent bitmap)的与设备无关性主要体现在以下两个方面:

  • DIB的颜色模式与设备无关。例如,一个256色的DIB即可以在真彩色显示模式下使用,也可以在16色模式下使用。
  • 256色以下(包括256色)的DIB拥有自己的颜色表,像素的颜色独立于系统调色板。

由于DIB不依赖于具体设备,因此可以用来永久性地保存图象。DIB一般是以*.BMP文件的形式保存在磁盘中的,有时也会保存在*.DIB文件中。运行在不同输出设备下的应用程序可以通过DIB来交换图象。

DIB还可以用一种RLE算法来压缩图像数据,但一般来说DIB是不压缩的。 DIB的结构:

在内存中,一个完整的DIB由两部分组成:一个BITMAPINFO结构和一个存储像素阵列的数组。BITMAPINFO描述了位图的大小,颜色模式和调色板等各种属性,其定义为:

typedef struct tagBITMAPINFO {  BITMAPINFOHEADER bmiHeader;  RGBQUAD          bmiColors[1];//颜色表} BITMAPINFO, *PBITMAPINFO;

 

RGBQUAD结构用来描述颜色,其定义为:

typedef struct tagRGBQUAD {  BYTE rgbBlue;  BYTE rgbGreen;  BYTE rgbRed;  BYTE rgbReserved;} RGBQUAD;

 

注意,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。

BITMAPINFOHEADER结构包含了DIB的各种信息,其定义为:

typedef struct tagBITMAPINFOHEADER {  DWORD biSize; //该结构的大小  LONG  biWidth; //位图宽度,以pixel为单位  LONG  biHeight; //位图高度,以pixel为单位  WORD  biPlanes; // 必须为1  WORD  biBitCount; //每个像素的位数(1、4、8、16、24或32)  DWORD biCompression; //压缩方式,一般为0或BI_RGB (未压缩)  DWORD biSizeImage; //以字节为单位的图象大小(仅用于压缩位图)  LONG  biXPelsPerMeter; //以目标设备每米的像素数来说明位图的水平分辨率  LONG  biYPelsPerMeter; //以目标设备每米的像素数来说明位图的垂直分辨率  DWORD biClrUsed; /*颜色表的颜色数,若为0则位图使用由biBitCount指定的最大颜色数*/  DWORD biClrImportant; //重要颜色的数目,若该值为0则所有颜色都重要} BITMAPINFOHEADER, *PBITMAPINFOHEADER;


与DDB不同,DIB的字节数组是从图象的最下面一行开始的逐行向上存储的,也即等于把图象倒过来然后在逐行扫描。另外,字节数组中每个扫描行的字节数必需是4的倍数,如果不足要用0补齐。DIB可以存储在*.BMP或*.DIB文件中。DIB文件是以BITMAPFILEHEADER结构开头的,该结构的定义为:

typedef struct tagBITMAPFILEHEADER {  WORD  bfType; //文件类型,必须是BM  DWORD bfSize; //位图文件的大小,字节为单位  WORD  bfReserved1;// 保留位,必须为0  WORD  bfReserved2;// 保留位,必须为0  DWORD bfOffBits;  // 从该数据结构开头到位图数据的偏移,字节为单位} BITMAPFILEHEADER, *PBITMAPFILEHEADER;


     紧随该结构的是一个BITMAPINFOHEADER结构,然后是RGBQUAD结构组成的颜色表(如果有的话),文件最后存储的是DIB的像素阵列。
      DIB的颜色信息储存在自己的颜色表中,程序一般要根据颜色表为DIB创建逻辑调色板。在输出一幅DIB之前,程序应该将其逻辑调色板选入到相关的设备上下文中并实现到系统调色板中,然后再调用相关的GDI函数(如::SetDIBitsToDevice或::StretchDIBits)输出DIB。在输出过程中,GDI函数会把DIB转换成DDB,这项工作主要包括以下两步:

  1. 将DIB的颜色格式转换成与输出设备相同的颜色格式。例如,在真彩色的显示模式下要显示一个256色的DIB,则应该将其转换成24位的颜色格式。
  2. 将DIB像素的逻辑颜色索引转换成系统调色板索引。
位图信息头BITMAPINFOHEADER,也是一个结构,其定义如下:
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
这个结构的长度是固定的,为40个字节(LONG为32位整数),各个域的说明如下:
biSize
指定这个结构的长度,为40。
biWidth
指定图象的宽度,单位是象素。
biHeight
指定图象的高度,单位是象素。
biPlanes
必须是1,不用考虑。
biBitCount
指定表示颜色时要用到的位数,常用的值为1(黑白二色图), 4(16色图), 8(256色), 24(真彩色图)(新的.bmp格式支持32位色,这里就不做讨论了)。
biCompression
指定位图是否压缩,有效的值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS(都是一些Windows定义好的常量)。要说明的是,Windows位图可以采用RLE4,和RLE8的压缩格式,但用的不多。我们今后所讨论的只有第一种不压缩的情况,即biCompression为BI_RGB的情况。
biSizeImage
指定实际的位图数据占用的字节数,其实也可以从以下的公式中计算出来:
biSizeImage=biWidth’ × biHeight
要注意的是:
上述公式中的biWidth’必须是4的整倍数(所以不是biWidth,而是biWidth’,表示大于或等于biWidth的,最接近4的整倍数。举个例子,如果biWidth=240,则biWidth’=240;如果biWidth=241,biWidth’=244)。
如果biCompression为BI_RGB,则该项可能为零
biXPelsPerMeter
指定目标设备的水平分辨率,单位是每米的象素个数,关于分辨率的概念。
biYPelsPerMeter
指定目标设备的垂直分辨率,单位同上。
biClrUsed
指定本图象实际用到的颜色数,如果该值为零,则用到的颜色数为2biBitCount。
biClrImportant
指定本图象中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。