高性能Windows图形开发库WinG
摘 要 该文首先概述高性能Windows图形开发库WinG,然后讲解WinG的一些特点及充分发挥WinG性能所必须遵循的十条原则,最后举例说明其开发方法。
一、概述
在Windows下,由于其GDI设备无关性、窗口环境、缺乏通用图形库等限制影响了图形速度。图形速度慢成为选择Windows作为游戏平台的最大障碍。
Windows 95在保留Windows的最大优点—设备无关性的同时,在Win32 API中新增一个32位调用CreateDIBSection,使得图形速度得到很大提高。Microsoft公司意识到图形速度对于高质量软件的重要性,提
供了WinG(发音"Win Gee",其中"G"代表游戏(Game))图形库。
WinG 是为Windows3.1、Windows for Workgroups 3.11、Windows95和Windows NT设计的一种优化的高性能图形库,运行于386以上的处理器。WinG能在Windows环境中提供与DOS环境相当的游戏图形性能。程序员可以直接将内存中的设备无关位图(DIB)传送到屏幕,并且提供抖动(halftoning)API,利用标准Microsoft抖动调色板支持对真彩色的仿真。
二、WinGDC和API
WinG提供一种新型设备描述表WinGDC,其用法类似于其它设备描述表,不同的是,程序员可以获取直接指向WinGDC绘图面、BITMAPINFOHEADER和颜色表的指针,还可以创建和选择新的绘图面或修改现有绘图面的颜色表。应用程序可以创建一个WinGDC和创建一个或多个WinGBitmap用于绘图。一旦当前帧绘图、DIB组织、Sprite(精灵)组织完成后,就可将WinGDC缓冲区拷贝到屏幕。这种双缓冲区结构减少了闪烁,使屏幕更新更平滑。
WinG API包含如附表所示的函数和类型。
附表
WinGDC不是调色板设备,是RGB设备。使用WinGSetDIBColorTable,而不是SelectPalette修改设备的颜色表。
三、WinG调色板管理
Windows调色板管理器用于管理多个应用程序对同一个系统调色板的使用请求。它给每个应用程序分配一个虚拟256色的逻辑调色板,并在必要时将逻辑调色板中的颜色转换为系统调色板中的颜色。
所谓对等(Identify)调色板,就是一个与当前系统调色板精确(1:1)匹配的逻辑调色板。它不需要进行调色板转换,因此将WinGDC传送到屏幕上时使用对等调色板能大大提高传送速度。
抖动调色板是一个对等调色板,其中包含的颜色是经过精心挑选的,并进行了优化使得在8位设备上通过抖动模拟真彩色。应用程序可选取该调色板并在显示设备描述表中实现,以便利用WinG提供的抖动技术。WinG图形库提供两个支持抖动的API:WinGCreateHalftonePalette和 WinGCreateHalftoneBrush,利用它们可在8位设备上仿真出24位真彩色。
四、WinG的DIB方向
1.自下而上DIB
Windows DIB的标准类型是自下而上的DIB,即DIB总是指向内存中最底层的扫描线。坐标(0,0)对应于图像的左下角,而Windows将(0,0)对应于显示器和设备相关位图(DDB)的左上角,即自下而上DIB的y轴被颠倒了。
对于8位自下而上DIB,屏幕上像素(X,Y)在内存中的地址计算如下:
//计算每扫描线实际比特数 DibWidthBits = (UINT)lpBmiHe
ader->biWidth * (UINT) lpBmiHeader->biBitCount
//按32比特边界对齐
DibWidthBytes = ((DibWidthBits+31) & (~31)) / 8;
pPixelXY = DibAddr + (DibHeight-1-Y)*DibWidthBytes + X;
2.自上而下DIB
其保存方向与大多数DIB相同,内存中的第一扫描线对应于图像的第一行。此时BITMAPINFOHEADER结构的成员biHeight为负值。
对于8位自上而下DIB,屏幕上像素(X,Y)在内存中的地址计算为:
pPixelXY = DibAddr + Y*DibWidthBytes + X.
五、充分发挥WinG性能方法
为了最大限度地发挥Windows环境下的WinG的块传送性能,要求:
·取出单色图形调试卡和拆接网络连接器;
·保存WinGBitmap表面指针和BITMAPINFO;
·避免重复GDI调用;
·专用函数可能比GDI函数执行速度快;
·对任何函数都要测试其执行速度;
·不要缩放位图;
·不要进行块传递;
·不要进行剪切操作;
·使用对等调色板;
·使用推荐的DIB格式。
六、应用实例
下面的例子讲解如何利用WinG图形库在Windows95下显示真彩色位图(24位)。利用Visual C++ 2.0编程。首先创建项目文件wing32.mak,设置Link加wing32.lib库。具体WinG图形库和本例子完整源程序可与作者联系。
首先选择Tools|Options...菜单项,再选择Directories命令。在Show Directories for下拉框中选择Include files,增加目录c:\wing\include;选择Library files,增加目录c:\wing\lib;选择Executable files,增加目录c:\wing\bin。
选择Project|Settings...菜单项,再选择Link命令。在Object/L
ibrary Modules编辑框中加入连接库wing32.lib。
struct{
BITMAPINFOHEADER Header;
RGBQUAD aColors[256];
} Info;
CWing32View::CWing32View()
{
Info.Header.biSize =
sizeof(BITMAPINFOHEADER);
Info.Header.biWidth = 176;
Info.Header.biHeight = 144;
Info.Header.biPlanes = 1L;
Info.Header.biBitCount = 24L;
Info.Header.biCompression = 0L;
Info.Header.biSizeImage =
(long)(176L*144L*3L);
Info.Header.biXPelsPerMeter = 0;
Info.Header.biYPelsPerMeter = 0;
Info.Header.biClrUsed = 0;
Info.Header.biClrImportant = 0;
hBitsSrc = ::GlobalAlloc(GHND,
(long)(176L*144L*3L));
pBitsSrc =
(LPSTR)::GlobalLock(hBitsSrc);
}
CWing32View::~CWing32View()
{
::GlobalUnlock( hBitsSrc );
::GlobalFree( hBitsSrc );
}
void CWing32View::OnPaint()
{
CPaintDC dc(this);
void far *pBits;
hpalApp = WinGCreateHalftonePalette();
PDIB pCurrentDIB =
DibOpenFile("miss256.bmp");
HDC WinGDC = WinGCreateDC();
Info.Header.biSize =
sizeof(BITMAPINFOHEADER);
Info.Header.biWidth =
DibWidth(pCurrentDIB);
Info.Header.biHeight =
DibHeight(pCurrentDIB);
HBITMAP WinGBitmap =
WinGCreateBitmap(WinGDC,
(BITMAPINFO far *)&Info,&pBits);
WinGBitmap =
SelectBitmap(WinGDC,WinGBitmap);
HPALETTE OldPalette =
::SelectPalette(dc.m-hDC,hpalApp,FALSE);
::RealizePalette(dc.m-hDC);
HPALETTE WinGPalette =
WinGCreateHalftonePalette();
HPALETTE OldWinGPalette =
::SelectPalette(WinGDC,WinGPalette,FALSE);
::RealizePalette(WinGDC);
::StretchDIBits(WinGDC,0,0,DibWidth(
pCurrentDIB),DibHeight(pCurrentDIB),
0,0,DibWidth(pCurrentDIB),DibHeight(
pCurrentDIB),DibPtr(pCurrentDIB),
DibInfo(pCurrentDIB),
DIB-RGB-COLORS,SRCCOPY);
::SelectPalette(WinGDC,OldWinGPalette,FALSE);
::DeleteObject(WinGPalette);
int Width = DibWidth(pCurrentDIB);
int Height = DibHeight(pCurrentDIB);
WinGStretchBlt(dc.m-hDC,0,0,Width,
Height, WinGDC,0,0,
DibWidth(pCurrentDIB),
DibHeight(pCurrentDIB));
::SelectPalette(dc.m-hDC,OldPalette,FALSE);
::SelectPalette(WinGDC,OldPalette,FALSE);
::DeleteObject(SelectBitmap(WinGDC,WinGBitmap));
::DeleteDC(WinGDC);
}
注意,在Windows 95下执行WinG安装程序Setup.exe,然后就可执行Wing32.exe。
用Visual C++ 2.0编译源程序,必须将WinG图形库Wing31.lib连接(link)到可执行文件Wing32.exe中(见文中所述)。