关于BMP

来源:互联网 发布:淘宝店铺如何找回 编辑:程序博客网 时间:2024/05/06 12:54

BMP资料  

 
根据VC5联机帮助中有关Bitmap的资料翻译而成  

 


 
    目录


  绪言  
  关于位图  
      位图类型  
      位图、设备描述表、和绘图表面  
      位图旋转  
      位图伸缩  
      用于画刷的位图  
      位图存储  
  使用位图  
      捕捉图像  
      拉伸或压缩一幅图像  
      保存一幅图像  
  附录:与位图相关的函数及结构  
 


●   绪言返回目录


位图在Windows系统平台中是一种很常见的图像格式,如果从保存图像的性能上来讲它不是最好的,JPG、GIF格式都超过它,但是由于它是微软公司制定的标准,并且已嵌入了操作系统,所以它就显得很重要了。以下的内容是我根据VC5.0的联机帮助翻译而来的,有些地方我加入了自己的观点(都已用括号表明),因为我对位图的知识掌握的也不是太深,所以可能有些地方翻译的不是太准确,甚至是错误,如果哪位高手发现了,请不吝赐教。同时,我也希望这份资料能对那些想了解位图的朋友有所帮助,那是我编译这份资料的最大愿望!  


●   关于位图   (About   Bitmap)返回目录


位图是能被选入设备描述表(DC)的七种目标之一,其余的六种目标是:笔(pen)、刷(brush)、字体(font)、区域(region)、逻辑调色板(logical   palette)、和路径(path)。在微软Win32应用程序界面(API)中,控制面板应用程序就是一种使用位图的程序,当用户为桌面选择壁纸的时候,实质上他选择的就是位图,Windows系统将根据这张位图来绘制桌面。从用户的角度来看,位图只是一个矩形的图像,而在开发者的眼中,位图则是一个结构的集合体。它可能包含以下的一些元素:  

*   一个描述图像信息的结构,比如图像的大小(宽、高)、位数组的尺寸、创建这张图片的设备的分辩率,等等。  
*   一个逻辑调色板  
*   一个位数组,它定义了像素值与逻辑调色板的关系(译者注:如果该图片有逻辑调色板的话,如果没有调色板,位数组中的像素值将直接代表各像素的颜色分量)。  

下面的图例可用于说明一个位图的真实位数组内容:  

 
在前面这个范例中,图像是创建于一个VGA的显示器,这种设备使用了一个16色的调色板,而一个16色的调色板至少需要4位的索引值才能表示(2^4),所以,在位图的位数组中,每个像素都是用4位(半个字节)来表示索引值的。  
注意:在上面的位图的中,Windows系统映射索引值到像素时是先从底扫描行开始,到顶扫描行结束的(扫描行是图像中水平方向的一个单行的所有像素)。比如,位数组中的第一行(row   0)对应于图像的最底行。这是因为上面这张位图是一张底到上型(bottom-up)的DIB(设备无关)位图,这也是一种很普通的位图。对于顶到下型的DIB以及DDB位图来说,Windows系统映射索引值到像素时则是从顶扫描行开始的。  

●   位图的类型   (Bitmap   Types)返回目录


位图一共有两种类型,即:设备相关位图(DDB)和设备无关位图(DIB)。DDB位图在早期的Windows系统(Windows   3.0以前)中是很普遍的,事实上它也是唯一的。然而,随着显示器制造技术的进步,以及显示设备的多样化,DDB位图的一些固有的问题开始浮现出来了。比如,它不能够存储(或者说获取)创建这张图片的原始设备的分辩率,这样,应用程序就不能快速的判断客户机的显示设备是否适合显示这张图片。为了解决这一难题,微软创建了DIB位图格式。  

设备无关位图   (Device-Independent   Bitmap)  

DIB位图包含下列的颜色和尺寸信息:  
*   原始设备(即创建图片的设备)的颜色格式。
*   原始设备的分辩率。
*   原始设备的调色板
*   一个位数组,由红、绿、蓝(RGB)三个值代表一个像素。
*   一个数组压缩标志,用于表明数据的压缩方案(如果需要的话)。


以上这些信息保存在BITMAPINFO结构中,该结构由BITMAPINFOHEADER结构和两个或更多个RGBQUAD结构所组成。BITMAPINFOHEADER结构所包含的成员表明了图像的尺寸、原始设备的颜色格式、以及数据压缩方案等信息。RGBQUAD结构标识了像素所用到的颜色数据。  

DIB位图也有两种形式,即:底到上型DIB(bottom-up),和顶到下型DIB(top-down)。底到上型DIB的原点(origin)在图像的左下角,而顶到下型DIB的原点在图像的左上角。如果DIB的高度值(由BITMAPINFOHEADER结构中的biHeight成员标识)是一个正值,那么就表明这个DIB是一个底到上型DIB,如果高度值是一个负值,那么它就是一个顶到下型DIB。注意:顶到下型的DIB位图是不能被压缩的。  

位图的颜色格式是通过颜色面板值(planes)和颜色位值(bitcount)计算得来的,颜色面板值永远是1,而颜色位值则可以是1、4、8、16、24、32其中的一个。如果它是1,则表示位图是一张单色位图(译者注:通常是黑白位图,只有黑和白两种颜色,当然它也可以是任意两种指定的颜色),如果它是4,则表示这是一张VGA位图,如果它是8、16、24、或是32,则表示该位图是其他设备所产生的位图。如果应用程序想获取当前显示设备(或打印机)的颜色位值(或称位深度),可调用API函数GetDeviceCaps(),并将第二个参数设为BITSPIXEL即可。  
显示设备的分辩率是以每米多少个像素来表明的,应用程序可以通过以下三个步骤来获取显示设备或打印机的水平分辩率:  
1.   调用GetDeviceCaps()函数,指定第二个参数为HORZRES。
2.   再次调用GetDeviceCaps()函数,指定第二个参数为HORZSIZE。
3.   用第一个返回值除以第二个返回值。即:DetDeviceCaps(hDC,HORZRES)/GetDeviceCaps(hDC,HORZSIZE);

应用程序也可以使用相同的三个步骤来获取设备的垂直分辩率,不同之处只是要将HORZRES替换为VERTRES,把HORZSIZE替换为VERTSIZE,即可。  

调色板是被保存在一个RGBQUAD结构的数组中,该结构指出了每一种颜色的红、绿、蓝的分量值。位数组中的每一个索引都对应于一个调色板项(即一个RGBQUAD结构),应用程序将根据这种对应关系,将像素索引值转换为像素RGB值(真实的像素颜色)。应用程序也可以通过调用GetDeviceCaps()函数来获取当前显示设备的调色板尺寸(将该函数的第二个参数设为NUMCOLORS即可)。  

Win32   API支持位数据的压缩(只对8位和4位的底到上型DIB位图)。压缩方法是采用运行长度编码方案(RLE),RLE使用两个字节来描述一个句法,第一个字节表示重复像素的个数,第二个字节表示重复像素的索引值。有关压缩位图的详细信息请参见对BITMAPINFOHEADER结构的解释。  

应用程序可以从一个DDB位图创建出一个DIB位图,步骤是,先初始化一些必要的结构,然后再调用GetDIBits()函数。不过,有些显示设备有可能不支持这个函数,你可以通过调用GetDeviceCaps()函数来确定一下(GetDeviceCaps()函数在调用时指定RC_DI_BITMAP作为RASTERCAPS的标志)。  

应用程序可以用DIB去设置显示设备上的像素(译者注:也就是显示DIB),方法是调用SetDIBitsToDevice()函数或调用StretchDIBits()函数。同样,有些显示设备也有可能不支持以上这两个函数,这时你可以指定RC_DIBTODEV作为RASTERCAPS标志,然后调用GetDeviceCaps()函数来判断该设备是否支持SetDIBitsToDevice()函数。也可以指定RC_STRETCHDIB作为RASTERCAPS标志来调用GetDeviceCaps()函数,来判断该设备是否支持StretchDIBits()函数。  

如果应用程序只是要简单的显示一个已经存在的DIB位图,那么它只要调用SetDIBitsToDevice()函数就可以。比如一个电子表格软件,它可以打开一个图表文件,在窗口中简单的调用SetDIBitsToDevice()函数,将图形显示在窗口中。但如果应用程序要重复的绘制位图的话,则应该使用BitBlt()函数,因为BitBlt()函数的执行速度要比SetDIBitsToDevice()函数快很多。  


设备相关位图   (Device-Dependent   Bitmaps)  

设备相关位图(DDB)之所以现在还被系统支持,只是为了兼容旧的Windows   3.0软件,如果程序员现在要开发一个与位图有关的程序,则应该尽量使用或生成DIB格式的位图。  

DDB位图是被一个单个结构BITMAP所描述,这个结构的成员标明了该位图的宽度、高度、设备的颜色格式等信息。  

DDB位图也有两种类型,即:可废弃的(discardable)DDB和不可废弃的(nondiscardable)DDB。可废弃的DDB位图就是一种当系统内存缺乏,并且该位图也没有被选入设备描述表(DC)的时候,系统就会把该DDB位图从内存中清除(即废弃)。不可废弃的DDB则是无论系统内存多少都不会被系统清除的DDB。API函数CreateDiscardableBitmap()函数可用于创建可废弃位图。而函数CreateBitmap()、CreateCompatibleBitmap()、和CreateBitmapIndirect()可用于创建不可废弃的位图。  

应用程序可以通过一个DIB位图而创建一个DDB位图,只要先初始化一些必要的结构,然后再调用CreateDIBitmap()函数就可以。如果在调用该函数时指定了CBM_INIT标志,那么这一次调用就等价于先调用CreateCompatibleBitmap()创建当前设备格式的DDB位图,然后又调用SetDIBits()函数转换DIB格式到DDB格式。(可能有些设备并不支持SetDIBits()函数,你可以指定RC_DI_BITMAP作为RASTERCAPS的标志,然后调用GetDeviceCaps()函数来判断一下)。    

 

位图、设备描述表、和绘图表面   (Bitmaps,   Device   Contexts,   and   Drawing   Surfaces)   返回目录


设备描述表(DC)是一个定义图形目标的数据结构,包括图形的属性、映射模式等信息。应用程序可以调用CreateDC()函数来创建一个DC,它也可以调用GetDC()函数来获取一个窗口的DC。  

绘图表面  

在应用程序获得一个DC句柄之前,窗口将先选择一个“绘图表面”到DC中。如果应用程序是在一个VGA的显示设备上调用的CreateDC()函数,那么它获得的DC绘图表面尺寸就是640×480像素。如果应用程序是调用的GetDC()函数,则绘图表面的尺寸就等于窗口客户区的尺寸。  

当应用程序使用由CreateDC()函数或GetDC()函数返回的DC句柄来进行绘图操作时(即用这个DC来调用绘图函数,如LineTo()函数),被请求的操作将出现在已选入该DC的绘图表面上。  


兼容设备描述表   (Compatible   Device   Contexts)  

先将图形在内存中画好,再一次性的输出到真实的显示设备上要比多次向显示设备上输出图形要快,并且程序更容易设计。为此,微软专门提供了一种特殊的设备描述表,称为兼容设备描述表(Compatible   Device   Context)(译者注:也叫作内存设备描述表)。Windows系统把兼容DC视为一种存在于内存中的虚拟设备。实质上兼容DC就是内存中的一个数组,应用程序可以把位图的颜色数据(即像素)保存于兼容DC中。  

应用程序可以调用CreateCompatibleDC()函数来创建一个兼容设备描述表,该函数将返回一个DC句柄,你可以象使用真实设备DC一样来使用这个兼容DC。Windows系统在创建这种DC时,附加的也创建了一个1位的位图(即单色位图),并在CreateCompatibleDC()函数返回之前将该位图选入兼容DC中。所以应用程序在使用这个兼容DC之前,应先替换掉这个1位的位图。方法是,先调用CreateBitmap()、CreateBitmapIndirect()、或CreateCompatibleBitmap()函数来创建一个你所需要的位图(由你指定位图的尺寸及位深度),并获得一个位图句柄,然后调用SelectObject()函数将这个位图句柄选入兼容DC。在位图句柄被选入兼容DC之后,Windows系统将用一个足够大的位数组来替换掉原来的1位位图的位数组(译者注:请注意保存这个1位的位图,在绘图操作结束后还要选回)。此时,你就可以用该兼容DC来进行绘图操作了(比如:直线、曲线、文本、区域等操作),绘制的结果将被保存在兼容DC中的位数组中。但这个时候,这些结果你并不能马上看到,你应该调用BitBlt()函数将保存于兼容DC位数组中的图像拷贝到真实设备的绘图表面上(请注意,在调用BitBlt()函数时,要将兼容DC作为源DC,而将真实设备DC作为目标DC来调用)。  

当你显示一个有调色板的DIB或DDB时(原始设备具有调色板),你可以通过适当的安排系统调色板来加快图像的显示速度。首先用NUMRESERVED作参数调用GetDeviceCaps()函数,来获取系统中保留的颜色个数。然后调用GetSystemPaletteEntries()函数,并用相应的系统颜色填充逻辑调色板开头和结尾的NUMRESERVED/2个调色板项。比如NUMRESERVED的返回值是20,则你必需用系统颜色填充逻辑调色板开头和结尾各10个项的调色板数据。然后再用位图的调色板来填充剩余的调色板项(这种调色板项必需设置PC_NOCOLLAPSE标志)。有关调色板和颜色的资料请参阅VC联机帮助中Colors一节。  


●   位图的旋转   (Bitmap   Rotation)   返回目录


Windows提供了一个函数,用于将矩形的位图拷贝到一个平行四边形中,这个函数就是PlgBlt()。在转换时,要将矩形位图DC作为源DC,而将平行四边形DC作为目标DC。有关旋转和World   units(译者注:这个词未译出)的资料请参见VC联机帮助中Coordinate   Spaces   和   Transformations   中的内容。  


●   位图的比例缩放   (Bitmap   Scaling)   返回目录


Win32   API也提供了一个按比例缩放位图的函数,它就是StretchBlt()。它可以将源设备描述表(DC)中的矩形位图传送到目标设备描述表中。但不同于BitBlt()函数,StretchBlt()允许应用程序指定源、目标位图的尺寸。如果应用程序指定的目标位图尺寸比源位图尺寸小,则系统将压缩源位图以符合目标位图尺寸。同时,你也可以指定该函数的压缩方式,使用SetStretchBitMode()函数。当目标位图的尺寸大于源位图时,系统将拉伸源位图(即扩大像素的颜色范围)以符合要求。  


●   作为画刷的位图   (Bitmaps   as   Brushes)   返回目录


Win32   API中有几个函数是使用已选入DC中的画刷来进行位图操作的,比如:PatBlt()函数可在窗口的一个矩形区域中复制画刷,而FloodFill()函数则可以在窗口的一个非矩形区域中复制画刷(这个非矩形区域可以用指定颜色来圈定)。  

PatBlt()函数的名字其实是一个缩写,全称应该是“图样块传送”(PATtern   BLock   Transfer,   缩写后就是PatBlt),从这个名字上看,它好像只是简单的复制画刷(或叫图样),直到填充完指定的矩形之后就结束了,其实这个函数可没有这么简单,它在复制画刷之前,将根据光珊操作码(raster   operation,缩写是ROP)来组合图样中的像素与目标DC中相同位置上的像素而形成最终的图像。光珊操作码(ROP)在组合的过程中起到了非常重要的作用,实质上ROP是一种位操作符,一共有256种,PatBlt()函数可以接受那些需要图样和目标位图的ROP。下面的表格列出了该函数经常用到的5个ROP:  


ROP 描述

PATCOPY 拷贝图样到目标位图中
PATINVERT 用图样的像素或(即位操作OR)目标位图
DSTINVERT 将目标位图的像素值取反(即非目标图的像素值)
BLACKNESS 将所有的输出都设为二进制的0
WHITENESS 将所有的输出都设为二进制的1


不同于PatBlt()函数,FloodFill()函数只是将选入DC的画刷简单的重复复制到一个由用户用指定颜色圈定的不规则区域中(填充满为止)。它不接受ROP命令。  


●   位图的存储   (Bitmap   Storage)   返回目录


如果用户想将位图保存到一个文件中,那么应用程序必需为该文件取一个以.BMP为后缀的扩展名,然后将位图以Windows位图文件格式保存到该文件当中。Windows位图文件格式由几部分组成,下表说明:  

 
其中第一个结构BITMAPFILEHEADER包括了一些对位图文件的大致说明,比如:位图文件的标志“BM”、位图文件的尺寸、位数组的偏移等信息。第二个结构BITMAPINFOHEADER则指明了位图图像的宽度、高度、颜色格式(位面数,位深度)、压缩标志、原始设备分辩率等信息。再接下来的是RGBQUAD结构数组,它里面放置的是位图的调色板数据,每一个结构描述一个调色板项(包括红、绿、蓝的分量值)。(译者注:有些位图没有这个RGBQUAD数组,比如16位、24位、32位位图。而且有些位图文件将该数组所占空间移做它用,如16位、32位位图的BI_BITFIELD格式就将该空间作为三色掩码的存放处,编程时应注意区别)。  

下面的表显示了一个BMP文件的实际内容:  

0000   42   4d   76   02   00   00   00   00   00   00   76   00   00   00   28   00  
0010   00   00   20   00   00   00   20   00   00   00   01   00   04   00   00   00  
0020   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00  
0030   00   00   00   00   00   00   00   00   00   00   00   00   80   00   00   80  
0040   00   00   00   80   80   00   80   00   00   00   80   00   80   00   80   80  
0050   00   00   80   80   80   00   c0   c0   c0   00   00   00   ff   00   00   ff  
0060   00   00   00   ff   ff   00   ff   00   00   00   ff   00   ff   00   ff   ff  
0070   00   00   ff   ff   ff   00   00   00   00   00   00   00   00   00   00   00  
0080   00   00   00   00   00   00   00   00   00   00   00   00   00   00   09   00  
0090   00   00   00   00   00   00   11   11   01   19   11   01   10   10   09   09  
00a0   01   09   11   11   01   90   11   01   19   09   09   91   11   10   09   11  
00b0   09   11   19   10   90   11   19   01   19   19   10   10   11   10   09   01  
00c0   91   10   91   09   10   10   90   99   11   11   11   11   19   00   09   01  
00d0   91   01   01   19   00   99   11   10   11   91   99   11   09   90   09   91  
00e0   01   11   11   11   91   10   09   19   01   00   11   90   91   10   09   01  
00f0   11   99   10   01   11   11   91   11   11   19   10   11   99   10   09   10  
0100   01   11   11   11   19   10   11   09   09   10   19   10   10   10   09   01  
0110   11   19   00   01   10   19   10   11   11   01   99   01   11   90   09   19  
0120   11   91   11   91   01   11   19   10   99   00   01   19   09   10   09   19  
0130   10   91   11   01   11   11   91   01   91   19   11   00   99   90   09   01  
0140   01   99   19   01   91   10   19   91   91   09   11   99   11   10   09   91  
0150   11   10   11   91   99   10   90   11   01   11   11   19   11   90   09   11  
0160   00   19   10   11   01   11   99   99   99   99   99   99   99   99   09   99  
0170   99   99   99   99   99   99   00   00   00   00   00   00   00   00   00   00  
0180   00   00   00   00   00   00   90   00   00   00   00   00   00   00   00   00  
0190   00   00   00   00   00   00   99   11   11   11   19   10   19   19   11   09  
01a0   10   90   91   90   91   00   91   19   19   09   01   10   09   01   11   11  
01b0   91   11   11   11   10   00   91   11   01   19   10   11   10   01   01   11  
01c0   90   11   11   11   91   00   99   09   19   10   11   90   09   90   91   01  
01d0   19   09   91   11   01   00   90   10   19   11   00   11   11   00   10   11  
01e0   01   10   11   19   11   00   90   19   10   91   01   90   19   99   00   11  
01f0   91   01   11   01   91   00   99   09   09   01   10   11   91   01   10   91  
0200   99   11   10   90   91   00   91   11   00   10   11   01   10   19   19   09  
0210   10   00   99   01   01   00   91   01   19   91   19   91   11   09   10   11  
0220   00   91   00   10   90   00   99   01   11   10   09   10   10   19   09   01  
0230   91   90   11   09   11   00   90   99   11   11   11   90   19   01   19   01  
0240   91   01   01   19   09   00   91   10   11   91   99   09   09   90   11   91  
0250   01   19   11   11   91   00   91   19   01   00   11   00   91   10   11   01  
0260   11   11   10   01   11   00   99   99   99   99   99   99   99   99   99   99  
0270   99   99   99   99   99   90  


下面的表格说明各结构在上面的位图中所占的位置,可对照查看:


结构 对应的字节范围

BITMAPFILEHEADER   0x00   -   0x0D  
  BITMAPINFOHEADER   0x0E   -   0x31  
  RGBQUAD   array   0x32   -   0x75  
  Color-index   array   0x76   -   0x275  

(译者注:Color-index   array实际上就是位图的位数组)

 

●   存储一幅图像   (Storing   an   Image)   返回目录


很多应用程序都需要将图像保存到文件当中,比如绘图程序要保存用户所画的图片,电子表格程序要保存用户的图表,CAD软件要保存图形,等等。  

如果你的应用程序想以位映射的方式保存图像的话,你可以采用Windows操作系统的位图格式来保存。步骤是,先初始化BITMAPINFO结构(由BITMAPINFOHEADER结构和RGBQUAD结构数组组成),然后填写适当的数据用以说明待保存图像的各种参数。最后将BITMAPFILEHEADER结构及BITMAPINFO结构和位数组写入文件当中。  
下面的范例代码演示了怎样初始化并填写BITMAPINFOHEADER结构:  
PBITMAPINFO   CreateBitmapInfoStruct(HWND   hwnd,   HBITMAP   hBmp)  
{
        BITMAP   bmp;  
        PBITMAPINFO   pbmi;
        WORD         cClrBits;    

        /*   Retrieve   the   bitmap 's   color   format,   width,   and   height.   */    
        if   (!GetObject(hBmp,   sizeof(BITMAP),   (LPSTR)&bmp))  
                errhandler( "GetObject ",   hwnd);      

        /*   Convert   the   color   format   to   a   count   of   bits.   */    
        cClrBits   =   (WORD)(bmp.bmPlanes   *   bmp.bmBitsPixel);

        if   (cClrBits   ==   1)  
                cClrBits   =   1;
        else   if   (cClrBits   <=   4)
                cClrBits   =   4;  
        else   if   (cClrBits   <=   8)  
                cClrBits   =   8;
        else   if   (cClrBits   <=   16)  
                cClrBits   =   16;
        else   if   (cClrBits   <=   24)  
                cClrBits   =   24;  
        else  
                cClrBits   =   32;            

        /*  
          *   Allocate   memory   for   the   BITMAPINFO   structure.   (This   structure  
          *   contains   a   BITMAPINFOHEADER   structure   and   an   array   of   RGBQUAD   data  
          *   structures.)            
          */            
        if   (cClrBits   !=   24)  
                pbmi   =   (PBITMAPINFO)   LocalAlloc(LPTR,  
                                        sizeof(BITMAPINFOHEADER)   +  
                                        sizeof(RGBQUAD)   *   (2^cClrBits));            
        /*     There   is   no   RGBQUAD   array   for   the   24-bit-per-pixel   format.   */    
        else  
                pbmi   =   (PBITMAPINFO)   LocalAlloc(LPTR,  
                                        sizeof(BITMAPINFOHEADER));        

        /*   Initialize   the   fields   in   the   BITMAPINFO   structure.   */    
        pbmi-> bmiHeader.biSize   =   sizeof(BITMAPINFOHEADER);  
        pbmi-> bmiHeader.biWidth   =   bmp.bmWidth;  
        pbmi-> bmiHeader.biHeight   =   bmp.bmHeight;  
        pbmi-> bmiHeader.biPlanes   =   bmp.bmPlanes;  
        pbmi-> bmiHeader.biBitCount   =   bmp.bmBitsPixel;
        if   (cClrBits   <   24)  
                pbmi-> bmiHeader.biClrUsed   =   2^cClrBits;      

        /*   If   the   bitmap   is   not   compressed,   set   the   BI_RGB   flag.   */    
        pbmi-> bmiHeader.biCompression   =   BI_RGB;            

        /*  
          *   Compute   the   number   of   bytes   in   the   array   of   color  
          *   indices   and   store   the   result   in   biSizeImage.
          */    
        pbmi-> bmiHeader.biSizeImage   =   (pbmi-> bmiHeader.biWidth   +   7)   /8  
                                                                    *   pbmi-> bmiHeader.biHeight  
                                                                    *   cClrBits;            
        /*  
          *   Set   biClrImportant   to   0,   indicating   that   all   of   the  
          *   device   colors   are   important.
          */    
        pbmi-> bmiHeader.biClrImportant   =   0;
        return   pbmi;    
}  
下面的范例将演示怎样打开一个文件,并拷贝数组、获取调色板索引、初始化保留结构、关闭文件等操作:  
void   CreateBMPFile(HWND   hwnd,   LPTSTR   pszFile,   PBITMAPINFO   pbi,  
                                    HBITMAP   hBMP,   HDC   hDC)  
  {  
 
        HANDLE   hf;                                     /*   file   handle   */  
        BITMAPFILEHEADER   hdr;               /*   bitmap   file-header   */  
        PBITMAPINFOHEADER   pbih;           /*   bitmap   info-header   */  
        LPBYTE   lpBits;                             /*   memory   pointer   */  
        DWORD   dwTotal;                             /*   total   count   of   bytes   */  
        DWORD   cb;                                       /*   incremental   count   of   bytes   */  
        BYTE   *hp;                                       /*   byte   pointer   */  
        DWORD   dwTmp;  
        pbih   =   (PBITMAPINFOHEADER)   pbi;  
        lpBits   =   (LPBYTE)   GlobalAlloc(GMEM_FIXED,   pbih-> biSizeImage);         if   (!lpBits)  
                  errhandler( "GlobalAlloc ",   hwnd);  
 
        /*  
          *   Retrieve   the   color   table   (RGBQUAD   array)   and   the   bits  
          *   (array   of   palette   indices)   from   the   DIB.  
          */  
 
        if   (!GetDIBits(hDC,   hBMP,   0,   (WORD)   pbih-> biHeight,  
                                      lpBits,   pbi,   DIB_RGB_COLORS))  
                errhandler( "GetDIBits ",   hwnd);  
 
        /*   Create   the   .BMP   file.   */  
 
        hf   =   CreateFile(pszFile,  
                                      GENERIC_READ   |   GENERIC_WRITE,  
                                      (DWORD)   0,  
                                      (LPSECURITY_ATTRIBUTES)   NULL,  
                                      CREATE_ALWAYS,  
                                      FILE_ATTRIBUTE_NORMAL,  
                                      (HANDLE)   NULL);  
 
        if   (hf   ==   INVALID_HANDLE_VALUE)  
                errhandler( "CreateFile ",   hwnd);  
 
        hdr.bfType   =   0x4d42;                 /*   0x42   =   "B "   0x4d   =   "M "   */  
 
        /*   Compute   the   size   of   the   entire   file.   */  
 
        hdr.bfSize   =   (DWORD)   (sizeof(BITMAPFILEHEADER)   +  
                                  pbih-> biSize   +   pbih-> biClrUsed  
                                  *   sizeof(RGBQUAD)   +   pbih-> biSizeImage);  
 
        hdr.bfReserved1   =   0;  
        hdr.bfReserved2   =   0;  
 
        /*   Compute   the   offset   to   the   array   of   color   indices.   */  
 
        hdr.bfOffBits   =   (DWORD)   sizeof(BITMAPFILEHEADER)   +  
                                        pbih-> biSize   +   pbih-> biClrUsed  
                                        *   sizeof   (RGBQUAD);  
 
        /*   Copy   the   BITMAPFILEHEADER   into   the   .BMP   file.   */  
 
        if   (!WriteFile(hf,   (LPVOID)   &hdr,   sizeof(BITMAPFILEHEADER),  
              (LPDWORD)   &dwTmp,   (LPOVERLAPPED)   NULL))  
              errhandler( "WriteFile ",   hwnd);  
 
        /*   Copy   the   BITMAPINFOHEADER   and   RGBQUAD   array   into   the   file.   */  
 
        if   (!WriteFile(hf,   (LPVOID)   pbih,   sizeof(BITMAPINFOHEADER)  
                                    +   pbih-> biClrUsed   *   sizeof   (RGBQUAD),  
                                    (LPDWORD)   &dwTmp,   (LPOVERLAPPED)   NULL))  
              errhandler( "WriteFile ",   hwnd);  
 
        /*   Copy   the   array   of   color   indices   into   the   .BMP   file.   */  
 
        dwTotal   =   cb   =   pbih-> biSizeImage;  
        hp   =   lpBits;  
        while   (cb   >   MAXWRITE)     {  
                        if   (!WriteFile(hf,   (LPSTR)   hp,   (int)   MAXWRITE,  
                                                    (LPDWORD)   &dwTmp,   (LPOVERLAPPED)   NULL))  
                                errhandler( "WriteFile ",   hwnd);  
                        cb-=   MAXWRITE;  
                        hp   +=   MAXWRITE;  
        }  
        if   (!WriteFile(hf,   (LPSTR)   hp,   (int)   cb,  
                  (LPDWORD)   &dwTmp,   (LPOVERLAPPED)   NULL))  
                      errhandler( "WriteFile ",   hwnd);  
 
        /*   Close   the   .BMP   file.   */  
 
        if   (!CloseHandle(hf))  
                      errhandler( "CloseHandle ",   hwnd);  
 
        /*   Free   memory.   */         GlobalFree((HGLOBAL)lpBits);
}  


●   位图操作函数列表   (Bitmap   functions)   返回目录
下面是操作位图的各种函数,有兴趣的朋友可查看Win32   API手册。  
BitBlt()
CreateBitmap()
CreateBitmapIndirect()
CreateCompatibleBitmap()
CreateDIBitmap()
CreateDIBSection()
CreateDiscardableBitmap()
ExtFloodFill()
FloodFill()
GetBitmapBits()
GetBitmapDimensionEx()
GetDIBColorTable()
GetDIBits()
GetPixel()
GetStretchBltMode()
LoadBitmap()
MaskBlt()
PatBlt()
PlgBlt()
SetBitmapBits()
SetBitmapDimensionEx()
SetDIBColorTable()
SetDIBits()
SetDIBitsToDevice()
SetPixel()
SetPixelV()
SetStretchBltMode()
StretchBlt()
StretchDIBits()
与位图相关的结构   (Bitmap   Structures)  
BITMAP
BITMAPCOREHEADER
BITMAPCOREINFO
BITMAPFILEHEADER
BITMAPINFO
BITMAPINFOHEADER
COLORADJUSTMENT
DIBSECTION
RGBQUAD
RGBTRIPLE
SIZE


转自: http://topic.csdn.net/t/20030325/19/1575761.html