上一节讲到显示DIB的显示时需要将文件内容读到内存中(如下图),当使用SetDIBitsToDevice和StretchDIBits函数显示时中间涉及到一系列的转换,这样大大增加了性能消耗,特别是在重复显示的时候,每一次都要重新转换和显示。我们在想能不能找到一种办法减少这种消耗。很自然想到一次转换多处使用这种方法。那么应该将DIB转换成什么呢,观察下图,最后显示的其实就是DDB,我们把DIB转换成DDB,这样以后显示的时候直接使用转换的结果DDB即可。
DIB转DDB使用函数CreateDIBitmap,该函数定义如下
HBITMAP CreateDIBitmap( HDC hdc, // handle to DC CONST BITMAPINFOHEADER *lpbmih, // bitmap data DWORD fdwInit, // initialization option CONST VOID *lpbInit, // initialization data CONST BITMAPINFO *lpbmi, // color-format data UINT fuUsage // color-data usage );
这个函数Petzold给出了一个实现,步骤如下
1.利用lpbmih信息和hdc创建一个兼容DDB
2.如果指定了fdwInit为CBM_INIT,则创建一个hdc兼容DC并选入之前的兼容DDB
3.如果指定了fdwInit为CBM_INIT,利用SetDIBitsToDevice函数在之前的兼容DC上显示,这里使用了DIB的lpbInit、lpbmi、fuUsage参数
注意这里BITMAPINFOHEADER *lpbmih参数只是为了提供创建DDB时的信息(主要是位图大小),BITMAPINFO *lpbmi是作为SetDIBitsToDevice的参数使用的,可能包含有调试板信息。
如果传入的hdc为NULL则创建的是单色DDB,如果传入的是正常设备hdc,则创建的是设备格式DDB。
可以选择fdwInit参数为CBM_INIT在创建DDB时填充数据,也可以不使用CBM_INIT在创建完成后使用SetDIBits填充数据,这时候DIB的lpbInit、lpbmi、fuUsage参数均不需要。
SetDIBits参数定义如下
int SetDIBits( HDC hdc, // handle to DC HBITMAP hbmp, // handle to bitmap UINT uStartScan, // starting scan line UINT cScanLines, // number of scan lines CONST VOID *lpvBits, // array of bitmap bits CONST BITMAPINFO *lpbmi, // bitmap data UINT fuColorUse // type of color indexes to use );显然这个就是在SetDIBitsToDevice函数上修改了一下作为填充数据用,实际上就是上面说的步骤的第三步。但是注意这里的hdc参数并不是在内存DC上显示用的hdc,只是作为DIB向DDB转换时提供调色板信息,当最后一个参数为DIB_PAL_COLORS参数时才需要。
这里只为强调DIB转DDB的使用方法和注意事项,具体的代码这里不再演示,参见Petzold的DIBCONV这个程序足以。
原创,转载请注明来自http://blog.csdn.net/wenzhou1219