特殊说明:版权归个人所有,请勿转载,谢谢合作。
位图对于在日常应用中,使用较为频繁,很多界面丰富、美观的程序,大部分以位图方式拼凑出来的,本章节通过位图的应用,了解位图的基本原理与使用方法。
在计算机中显示的图形一般可以分为两大类:矢量图和位图。
矢量图使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等,它们都是通过数学公式计算获得的。例如一幅花的矢量图形实际上是由线段形成外框轮廓,由外框的颜色以及外框所封闭的颜色决定花显示出的颜色。由于矢量图形可通过公式计算获得,所以矢量图形文件体积一般较小。矢量图形最大的优点是无论放大、缩小或旋转等不会失真。最大的缺点是难以表现色彩层次丰富的图像效果。
位图,又称光栅图,一般用于照片品质的图像处理,是由许多像小方块一样的像素组成的图形。由像素的位置与颜色值表示,能表现出颜色阴影的变化。简单说,位图就是以无数的色彩点组成的图案,当无限放大时会看到一块一块的像素色块,效果会失真。
位图是一个图形对象,例如照片、图片和绘画。可以把它们绘制到一个窗口或对话框中去。如图9.1所示。
- 图9.1 位图的应用
计算机视频系统的核心是内存。内存中包含的数据,代表显示器上出现的图案。称这个内存为视图内存。位图代表类似视频内存RAM区域,位图内存不可见,视频内存是可见的。位图分配的RAM代表一个矩形区域,这个区域的内存句柄被称为HBITMAP。如果将位图内存加载到视频内存中,在显示器上将出现图形。通常情况下,Win32 SDK使用CreateBitmap函数或CreateCompatibleBitmap函数来实现位图的创建,使用LoadBitmap函数实现加载。CreateBitmap函数原型如下:
HBITMAP CreateBitmap( int nWidth, // bitmap width, in pixels int nHeight, // bitmap height, in pixels UINT cPlanes, // number of color planes used by device UINT cBitsPerPel, // number of bits required to identify a color CONST VOID *lpvBits // pointer to array containing color data );
参数nWidth,指定位图的宽度,单位为像素。
参数nHeight,指定位图的高度,单位为像素。
参数cPlanes,指定该设备使用的颜色位面数目。
参数cBitsPerPel,指定用来区分单个像素点颜色的位数(比特数目)。
参数lpvBits,指向颜色数据数组指针。这些颜色数据用来设置矩形区域内像素的颜色。矩形区域中的每一扫描线必须是双字节的整数倍(不足部分以0填充)。如果该参数为NULL,将不对新生成的位图进行初始化。
如果函数成功,那么返回值是位图的句柄;如果失败,那么返回值为NULL。若想获取更多错误信息,请调用GetLastError函数。在创建完位图之后,可以通过使用SelectObject函数把它选入到设备环境中。尽管函数CreateBitmap可以用来创建彩色位图,但由于性能方面的原因,应用程序使用CreateBitmap函数来创建单位色位图,创建彩色位图应该使用函数CreateCompatibleBitmap。当由CreateBitmap创建而返回的彩色位图被选入到设备环境时,系统必须确保选入进去的设备环境格式与位图匹配。由于函数CreateComapatbleBitmap获取设备环境,所以它返回的位图与指定的设备环境有相同的格式。由于这个原因,对SelectObject的后续调用都要比从CreateBitmap函数创建返回的彩色位图调用快。如果位图是单色的,那么对于目标设备环境而言,0表示前景颜色,而1表示背景颜色。
CreateCompatibleBitmap函数创建与指定的设备环境相关的设备兼容的位图,函数原型如下:
HBITMAP CreateCompatibleBitmap( HDC hdc, // handle to device context int nWidth, // width of bitmap, in pixels int nHeight // height of bitmap, in pixels );
参数hdc,设备环境句柄。
参数nWidth,指定位图的宽度,单位为像素。
参数nHeight,指定位图的高度,单位为像素。
如果函数执行成功,那么返回值是位图的句柄;如果函数执行失败,那么返回值为NULL。若想获取更多错误信息,请调用GetLastError。由CreateCompatibleBitmap函数创建的位图的颜色格式与由参数hdc标识的设备的颜色格式匹配。该位图可以选入任意一个与原设备兼容的内存设备环境中。由于内存设备环境允许彩色和单色两种位图。因此当指定的设备环境是内存设备环境时,由CreateCompatibleBitmap函数返回的位图格式不一定相同。然而为非内存设备环境创建的兼容位图通常拥有相同的颜色格式,并且使用与指定的设备环境一样的色彩调色板。当不再需要这个位图的时候,调用DeleteObject删除它。
LoadBitmap函数从应用程序的的可执行文件中加载指定的位图资源。函数原型如下:
HBITMAP LoadBitmap( HINSTANCE hInstance, // handle to application instance LPCTSTR lpBitmapName // address of bitmap resource name );
参数hInstance,指向模块实例的句柄。该模块的可执行文件包含了要加载的位图。
参数lpBitmapName,指向字符串(以NULL结束)指针。该字符串包含了要加载的位图资源名称。另外一种方式就是该参数可以由低位字是资源标识符、高位字为0位形式组成。可以使用宏MAKEINTRESOURCE来创建这个参数值。
如果函数执行成功,则返回值是指向指定位图的句柄。如果函数执行失败,那么返回值是NULL。
位图加载成功后,还需要使用BitBlt函数来实现位图的绘制,该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境。函数原型如下:
BOOL BitBlt( HDC hdcDest, // handle to destination device context int nXDest, // x-coordinate of destination rectangle's upper-left // corner int nYDest, // y-coordinate of destination rectangle's upper-left // corner int nWidth, // width of destination rectangle int nHeight, // height of destination rectangle HDC hdcSrc, // handle to source device context int nXSrc, // x-coordinate of source rectangle's upper-left // corner int nYSrc, // y-coordinate of source rectangle's upper-left // corner DWORD dwRop // raster operation code );
参数hdcDest,指向目标设备环境的句柄。
参数nXDest,指定目标矩形区域左上角的X轴逻辑坐标。
参数nYDest,指定目标矩形区域左上角的Y轴逻辑坐标。
参数nWidth,指定源和目标矩形区域的逻辑宽度。
参数nHeight,指定源和目标矩形区域的逻辑高度。
参数hdcSrc,指向源设备环境的句柄。
参数nXSrc,指定源矩形区域左上角的X轴逻辑坐标。
参数nYSrc,指定源矩形区域左上角的Y轴逻辑坐标。
参数dwRop,指定光栅操作代码。这些代码将定义源矩形区域的颜色数据,如何与目标矩形区域的颜色数据组合以完成最后的颜色。表9.1所示,为常见的光栅操作代码。
- 表9.1 光栅操作代码
值 | 描述 |
BLACKNESS | 表示使用与物理调色板的索引0相关的色彩来填充目标矩形区域(对缺省的物理调色板而言,该颜色为黑色) |
DSTINVERT | 目标矩形区域颜色取反操作 |
MERGECOPY | 将源位图和模板执行与操作 |
MERGEPAINT | 将源位图和模板执行或操作 |
NOTSRCCOPY | 在复制之前将源位图执行取反操作 |
NOTSRCERASE | 将源位图和目标位图执行或操作后,再执行取反操作 |
PATCOPY | 将特定的模板拷贝到目标位图上 |
PATINVERT | 将模板和目标位图执行异或操作 |
PATPAINT | 通过使用布尔OR(或)操作符将源矩形区域取反后的颜色值与特定模板的颜色合并。然后使用OR(或)操作符将该操作的结果与目标矩形区域内的颜色合并 |
SRCAND | 将源位图与目标位图执行与操作 |
SRCCOPY | 将源位图原样复制到目标位图 |
SRCERASE | 将目标位图取反操作后,再与源位图执行与操作 |
SRCINVERT | 将源位图与目标位图执行异或操作 |
SRCPAINT | 将源位图与目标位图执行或操作 |
WHITENESS | 使用与物理调色板中索引1有关的颜色填充目标矩形区域(对于缺省物理调色板来说,这个颜色就是白色) |
在使用BitBlt函数时,要用到兼容DC。兼容的DC指的不是具体的图形设备,而是虚拟的设备,可以在兼容DC中执行绘图操作,通过图形拷贝函数快速拷贝到HDC中,实现图像的高速显示。显示位图需要六个步骤:
- 创建兼容DC;
- 加载位图;
- 选入位图;
- 执行BitBlt函数,将兼容DC中的图形拷贝到当前设备环境中;
- 选出位图;
- 删除位图。
【例9-1】实现了位图的加载,在位图加载之前,需要将位图以资源的方式加入到工程中。在资源界面中选择【Bitmap】项,点击【Import…】按钮,导入位图。如图9.2所示。
- 图9.2 选择位图
在导入资源目录选择界面,首先,点击【文件类型】处,选择“所有文件(*.*)”;其次,在【查找范围】处选择位图存放位置,以桌面“inputbmp.bmp”为例;点击【Import】按钮导入。如图9.3所示。
- 图9.3 选择导入文件
导入后,会出现一个提示,点击【确定】按钮即可。出现这个提示的原因是,导入的位图大于256色,VC6.0不能对它进行编辑,所弹出的提示信息。如图9.4所示。
- 图9.4 提示信息(位图大于256色)
导入完成后,更改位置的ID。更改后的ID为“IDB_FACE_BMP”。如图9.5所示。
- 图9.5 修改位图ID
位图也是绘图的一种,通常将绘制代码写在WM_PAINT消息中的BeginPaint函数与EndPaint函数之前。代码如下所示。
// 图形绘制事件 case WM_PAINT: hdc = BeginPaint(hWnd, &ps); { HBITMAP hOldbmp,hbmp = NULL; HDC hmdc =CreateCompatibleDC(hdc); hbmp = LoadBitmap(g_hIns, MAKEINTRESOURCE(IDB_FACE_BMP)); hOldbmp = (HBITMAP)::SelectObject(hmdc ,hbmp); ::BitBlt(hdc,0,0,283,195,hmdc, 0,0,SRCCOPY); ::SelectObject(hmdc,hOldbmp); DeleteDC(hmdc); } EndPaint(hWnd, &ps); break;
首先,CreateCompatibleDC函数通过当前的hdc,创建新的兼容DC,并通过LoadBitmap函数将刚刚加入到工程中的位图资源IDB_FACE_BMP进行加载;
其次,使用SelectObject函数选入位图;
现次,使用BitBlt函数将位图原样复制到当前DC中(位置的大小为283×195);
最后,使用SelectObject函数还原系统位图,并使用DeleteDC函数删除创建的兼容DC。