现在我们讲述windows多媒体中最重要,最核心的技术──图形技术。对于Windows的图形图像技术来说,包括基本的GDI绘制对像如点、线、矩形、图像和位图文件,引而广之所有的动画文件都要利用到windows图像图形技术编程。
本章节我们主要讲述Bmp文件实现过程、调色板应用,及一些Bmp图像合成技术,例如:透空技术、Bmp动画技术等。
Bmp文件结构
Bmp文件由以下几个部分组成:文件头、位图信息头、调色板、数据区。下面这张图显示了Bmp文件结构:
Windows位图显示的必要条件:
我们分析一下一个Windows API函数:
int SetDIBitsToDevice(hdc,uXDest,uYDest,uWidth,uHeight,uXSrc,uYSre,
uStartScan,cScanLines,lpvBits,lpbmi,fuColorUse)
请查看这个函数的第十、十一个参数lpvBits,lpbmi。其中lpvBits指明了指向内存中BMP数据的地址,lpbmi指向一个BITMAPINFO的数据结构,只要有了这两个参数,一个BMP位图就被确定了。大家可以看到绝大多数的Windows图形图像浏览软件所能分析的文件格式,例如jpg、gif、pcx、tif等等,都是先在内存中建一个数据缓冲区,再根据图形图像格式建立一个BITMAPINFO的数据结构,再利用SetDIBitsToDevice函数写到屏幕上。我们下面几个实例,也基本上采用这个方式。
Windows的调色板
Windows的显示设备可以显示出成千上万种颜色,但是,在同一个屏幕上能同时显示的颜色数并不是成千上万种,我们把显示设备分为单色、十六色、二百五十六色、增强色、真彩色,或者是按照显示位区分成1bit,4bit,8bit,16bit,24bit。由于Windows的理论显示数和实际显示数并不相符,因此需要一个方案来解决这个问题,这就要用到调色板这个概念。为何要使用调色板我们在此并不作详细讨论,只是有一点要弄明白,只有十六色和二百五十六色位图才需要调色板。
下面是使用调色板的方法
首先要读入一个位图文件,再判断这个位图文件的颜色数,假如这个文件是十六色或是二百五六色,那么这个文件中必会有一个调色板信息,读取这个调色板信息,将这个调色板信息转为一个LOGPALETTE的结构,根据这个结构生成逻辑调色板,然后每次在要显示位图前,使用SelectPalette函数将逻辑调色板选入设备描述表hDC,再使用RealizePalette函数实现这个调色板,当显示完成后再使用SelectPalette函数,将旧的调色板选择回来,一个调色板调用过程就完成了。
构造windows图像处理类库
我们假设这个类库包含以下功能:
- 处理调色板;
- .生成逻辑调色板;
- 实现调色板;
- 处理BMP文件
- 读取BMP图像;
- 显示图像;
- 实现以上“处理调色板”的功能;
- 处理FLC动画
- 读取FLC动画文件;
- 播放参数设置;
- 显示图像;
- 实现以上“处理调色板”的功能;
通过以上假设我们看到要设计的类库有一些公共特点:
1.都要处理调色板;
2.除了“1”以外,“2”和“3”均包含了windows图像显示的必要条件:结构
BITMAPINFO和一块bitmap数据区。
为此我们首先构造一个处理调色板的类,这个类的实现上述“处理调色板”的功能。为什么要单独处理调色板而不让它附属于“处理BMP文件”或是“处理FLC动画”,其原因是:在大规模多媒体编程中,往往有几十或几百个BMP图像或动画,却只需要一两个调色板,过度泛滥的调色板往往造成版面切换过程中的闪烁,并浪费内存空间,因此要单独处理调色板。
其次我们构造一个处理DIB图像的类:在这个类里,核心为两个参数(结构BITMAPINFO和一块bitmap数据区)和一个调用API函数SetDIBitsToDevice()的显示函数Show()。这个类继承于调色板类,因为处理图像文件必须处理调色板。并成为其他图像文件的基类,因为要处理图像文件必须要有这两个结构和函数。
有了这两个基类后,我们再在这两个基类的基础上构造其他类。
// MyBmp.h: interface for the MyBmp class. // // #if !defined(AFX_MYBMP_H__34151075_C57B_11D1_94F8_0000B431BBA1__INCLUDED_) #define AFX_MYBMP_H__34151075_C57B_11D1_94F8_0000B431BBA1__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #define FALSERETURN {_lclose(hFile);return 0;} #define IMAGECOLORS(x,y)(1<<((x)*(y))) //单行BMP数据的字节数 #define DWORD_WBYTES(x)((((x)+31UL)>>5)<<2) #define min(a, b) (((a) < (b)) ? (a) : (b)) #ifdef WIN32 #define BMPDATABYTE #else #define BMPDATABYTE _huge #endif // #include "