收藏 分享(赏)

【Visual C 】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类.doc

上传人:dreamzhangning 文档编号:3013900 上传时间:2018-10-01 格式:DOC 页数:11 大小:265KB
下载 相关 举报
【Visual C  】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类.doc_第1页
第1页 / 共11页
【Visual C  】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类.doc_第2页
第2页 / 共11页
【Visual C  】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类.doc_第3页
第3页 / 共11页
【Visual C  】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类.doc_第4页
第4页 / 共11页
【Visual C  】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类.doc_第5页
第5页 / 共11页
点击查看更多>>
资源描述

1、 【Visual C+】游戏开发笔记十四 游戏画面绘图(四) 华丽的 CImage 类本系列文章由 zhmxy555 编写,转载请注明出处。 http:/ 邮箱: 欢迎邮件交流编程心得我们知道,Visual C+中的 CBitmap 类的功能简直太弱小了,这曾经让 Visual C+在图像处理方面的功能比较尴尬。之前笔记里面,我们采用的 CBitmap 配合 GDI 进行透明图像的处理有些晦涩繁琐,而且受到图像素材的限制,可以说是有些落后,不是太实用。为了解决这个问题,这节笔记我们将系统的学习 MFC 和 ATL 中新增一个图像处理的类,它就是华丽而强大的CImage 类。由于本节笔记是对

2、CImage 类的一个非常系统近乎完全的介绍,我尽量让它涵盖到了 CImage 类的所有的属性和类成员,所以篇幅也许比以往的笔记内容都长,里面的不少内容是用到的时候才需要掌握或者查阅的,并不用强行记忆。一,概念讲解部分1.CImage 类的定位和概述首先,我们简单介绍一下 CImage 类的定位。CImage 是 MFC 和 ATL 共享的新类,它提供了增强的位图支持,包括加载、保存和转换JPEG,BMP,GIF,PNG 图像格式的能力。可以说是微软意识到了 CBitmap 的不足,然后推出了一个CBitmap 的增强版。使用 CImage 类,需在代码头部加入包含 atlimage.h 文件

3、,即添加代码#include “atlimage.h“。由于 CImage 拥有功能强大的类成员函数的支持,它便具有了下列四个比较出彩的特性: 1、 AlphaBlend 支持像素级的颜色混合,从而实现透明和半透明的效果。 2、 PlgBlt 能使一个矩形区域的位图映射到一个平行四边形区域中,而且还可能使用位屏蔽操作。 3、 TransparentBlt 在目标区域中产生透明图像4、 MaskBlt 在目标区域中产生源位图与屏蔽位图合成的效果。2.以 CImage 类做媒,让 CBitmap 类也能处理丰富的图片格式解决的思路比较明朗,我们采用 CImage 类的 Load 函数加载图片,之后

4、用 Detch 取得 HBITMAP 的句柄,然后再将此句柄附加给 CBitmap 的对象就行了。这样就实现了让 CBitmap 类也可以操作 JPG/JPEG/GIF/PNG 格式的图片。具体代码如下:cpp view plaincopyprint?1. #include “atlimage.h“ 2. CImage image; /定义一个 CBitmap 类 3. image.Load(“filename”); /filename 为要加载的文件地址 4. HBITMAP hBitmap=image.Detach(); /返回被分离的图片的句柄 5. CBitmap bmp; / 定义一

5、个 bitmap 6. bmp.Attach(hBitmap); /进行句柄的附加 然后就可以用 CBitmap 进行余下的操作了。3.CImage 额外的一些性质CImage 类对于 DIB(device-independent bitmap)设备无关位图文件和非 DIB 都可以处理。我们可以通过Create 函数或者 CImage:Load 来处理 DIB 部分,用 Attach 函数来将非 DIB 部分附加到一个 CImage 对象上。对于以下函数,只支持 DIB 部分的位图文件,他们是:GetBitsGetColorTable,GetMaxColorTableEntries,GetPi

6、tch,GetPixelAddress ,IsIndexed,SetColorTable。我们可以通过 CImage 类中的 IsDIBSection()函数来帮助我们判断一个位图文件是否为 DIB 部分,其定义如下:cpp view plaincopyprint?1. bool IsDIBSection( ) const throw( ); /如果返回值为 true,则该文件为 DIB;返回 flase 则不是 DIB 文件 我们需要注意的是,CImage 不能被选到一个新的 CDC( class of device-context 设备描述表的类),CImage 会为图像创建自己的 HDC

7、(设备描述表 DC 的句柄)。因为一个 HBITMAP 只能被选入到一个 HDC中一次,也就是说这个与 CImage 相关的 HBITMAP 不能被选到一个其他的 HDC 中。如果需要一个 CDC,我们可以从 CImage 中获取 HDC,然后使用 CDC::FromHandle 函数。4.CImage 兼容性的说明在 CImage 中,有如下兼容性的要求:只支持 Windows NT4.0 以上系统的成员函数:PlgBlt,MaskBlt,AlphaBlend。只支持 Windows 2000,98 以上系统的成员函数: TransparentBlt,Draw其实由于目前都是 Windows

8、 XP 以上的操作系统,这个知识点了解一下就行。5.CImage 类用于贴图的一般的使用方法使用方法不唯一,最常用的方法如下,该方法大致分为三部分:在源文件中添加 CImage 类的包含文件: #include “atlimage.h“定义一个 CImage 类对象,然后调用 CImage:Load 方法装载一个外部图像文件。Load 方法有如下两种重载:cpp view plaincopyprint?1. HRESULT Load( 2. LPCTSTR pszFileName /包含加载文件名的字符串指针 3. ) throw( ); 4. 5. 6. HRESULT Load( 7. I

9、Stream* pStream /指向包含加载文件名的流的指针 8. ) throw(); 调用 CImage:Draw 方法绘制图像。下面重点介绍一下 Draw 方法。CImage:Draw 将一个位图文件从源设备描述表复制到当前设备描述表该函数有如下六种重载:cpp view plaincopyprint?1. BOOL Draw( 2. HDC hDestDC, /目标设备环境 DC 的句柄 3. int xDest, /目的矩形的左上角 X 坐标(逻辑单位) 4. int yDest, /目的矩形的左上角 Y 坐标(逻辑单位) 5. int nDestWidth, /目标矩形的宽度(就

10、是设定贴过去的图片的宽度) 6. int nDestHeight, /目标矩形的高度(就是设定铁锅的图片的高度) 7. int xSrc, /源矩形的左上角 X 坐标 8. int ySrc, /源矩形的左上角 Y 坐标 9. int nSrcWidth, /源矩形的宽度 10. int nSrcHeight /源矩形的高度 11. ) const throw( ); 12. 13. 14. BOOL Draw( 15. HDC hDestDC, /目标环境 DC 的句柄 16. const RECT 19. 20. 21. BOOL Draw( 22. HDC hDestDC, /目标环境

11、DC 的句柄 23. int xDest, /目标矩形的左上角 X 坐标 24. int yDest /目标矩形的左上角 Y 坐标 25. ) const throw( ); / 26. BOOL Draw( 27. HDC hDestDC, /目标环境 DC 的句柄 28. const POINT 30. 31. 32. BOOL Draw( 33. HDC hDestDC, /目标环境 DC 的句柄 34. int xDest, /目标矩形的左上角 X 坐标 35. int yDest, /目标矩形的左上角 Y 坐标 36. int nDestWidth, /目标矩形的宽度 37. int

12、 nDestHeight /目标矩形的宽度 38. ) const throw( ); 39. 40. 41. BOOL Draw( 42. HDC hDestDC, /目标环境 DC 的句柄 43. const RECT 在上面的 Draw 函数的各种重载中,对于没有指定源矩形的版本,则整个源图像就是默认的源矩形。对于没有指定目的矩形尺寸的,则源图片的尺寸就是默认的目的矩形尺寸。需要注意的是,Draw 方法综合了 StretchBlt、TransparentBlt 和 AlphaBlend 函数的功能。通常情况下,Draw()函数作用和 StretchBlt()函数一致。但是当我们的图像中存

13、在透明的颜色和 alpha 通道的时候,Draw()函数作用和 TransparentBlt()或者 AlphaBlend()函数一致。所以,在一般情况下,我们都尽量调用 Draw 方法来绘制图像。6.对 CImage 所有类成员的介绍我将 CImage 类的所有类函数按功能分为了四大类,可以更方面的了解各函数的定位和作用,也方便大家查阅:功能为创建与连接,释放的函数Attach 附加一个 HBITMAP 到 CImage 对象,位图类型 DIB 与否都可以Create 创建一个 DIB 部分的位图,并将其附加到之前创建的 CImage 对象CreateEX 创建一个 DIB 部分的位图(拥有

14、额外的参数),并将其附加到之前 创建的 CImage 对象Destroy 从 CImage 类上分离该位图并进行删除Detach 从 CImage 类里分离该位图ReleaseDC 释放设备描述表中的数据ReleaseGDIPlus 释放 GDI+使用的源功能为输入与输出的函数GetExporterFilterString 返回系统支持的输入文件格式类型及其描述GetImporterFilterString 返回系统支持的输出文件格式类型及其描述LoadFromResource 从指定的源处加载一个图像资源Load 从指定文件处加载一个图像资源IsIndexed 判断一个位图颜色映射到了一个索

15、引调色盘IsNull 判断一个源位图是否被当前载入Save 以指定的类型来保存图像关于位图类型与参数的函数GetBits 返回一个指向该位图实际像素值指针GetBPP 返回该位图每个像素的位GetColorTable 返回颜色表中 RGB 值的范围条目GetDC 返回目前被选择的设备描述表GetExporterFilterString 返回系统支持的输入文件格式类型及其描述GetImporterFilterString 返回系统支持的输出文件格式类型及其描述GetHeight 返回当前图像的像素高度GetMaxColorTableEntries 返回颜色表条目中的最大值GetPitch 返回当

16、前图片的间距(单位为字节),用来决定像素格式的GetTransparentColor 返回颜色表中透明色的位置GetWidth 返回当前图片的宽度(单位为像素)功能为图形绘制与位图块传输相关的函数AlphaBlend 显示一个半透明或者透明像素的位图BitBlt 从源设备描述表复制一个位图文件到当前设备描述表Draw 从源矩形复制一个位图到目的矩形,该函数伸缩或者拉伸位图来适应目标矩 形的尺寸,如果有必要,会处理 Alpha 值和透明颜色。MaskBlt 用指定的掩码和光栅操作来结合颜色数据和目的位图PlgBlt 执行一个从源设备描述表的矩形到目标设备描述表的平行 四边形的块状位图转换SetC

17、olorTabel 在 DIB 的颜色表中设定一系列条目的 RGB 颜色的值SetPixelIndexed 设置在指定坐标处的像素(使用索调色板的索引值)。SetPixelRGB 设置在指定坐标处的像素(使用 RGB 值)SetPixel 在指定坐标处设置像素的颜色SetTransparentColor 设置将被视为透明色的颜色的索引值(只能选取调色板中的 一种颜色)StretchBlt 从源矩形复制一个位图到目的矩形,如果有必要,该函数会 伸缩或者拉伸位图来适应目标矩形的尺寸,TransparentBlt 从源设备描述表中复制一个带有透明色的位图到当前设备 描述表二,实例运用部分运用 CIm

18、age 完成透明贴图的一个完整实例介绍了这么多了,下面我们依然用一个实例来巩固本节笔记的知识。我们知道,CImage 支持透明 PNG 的贴图,下面我们就运用透明 PNG 的贴图,来代替之前的掩码操作贴图。准备两张素材图,一张背景图,一张需要进行透明操作的人物图。这次的选材就很广了,没有之前透明操作需要自己一定的美工功底或者美工童鞋支持的诸多限制了。我选的两张图片素材如下:背景图 bg.bmp 640x444人物图 onion.bmp 130x130(呵呵,可爱的洋葱头 )将人物图 onion.bmp 用 photoshop 等图像处理软件进行抠图操作,除去红黄相间的背景图,并将背景图用透明图

19、层代替,再将图片大小调节成 85x113,用 png 格式输出,效果如下:处理好的人物图 onion.png 85x113将 bg.bmp 以及 onion.png 放到工程目录下,并在源文件写入代码并运行。该代码和笔记六中代码的思路基本相同,只不过,将笔记六中使用掩码操作进行透明化处理的方式换成了 png透明贴图的方式,更加的直观和易懂易用。详细注释的源代码如下cpp view plaincopyprint?1. #include “stdafx.h“ 2. #include “atlimage.h“ 3. /全局变量声明 4. HINSTANCE hInst; 5. HBITMAP bg;

20、 /声明一个位图对象,用于存储背景图 6. HDC mdc; /声明一个内存 DC“mdc“,用来暂存位图 7. /全局函数声明 8. ATOM MyRegisterClass(HINSTANCE hInstance); 9. BOOL InitInstance(HINSTANCE, int); 10. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 11. void MyPaint(HDC hdc); 12. /*Winmain 函数,程序入口点函数* 13. int APIENTRY WinMain(HINSTANCE hInst

21、ance, 14. HINSTANCE hPrevInstance, 15. LPSTR lpCmdLine, 16. int nCmdShow) 17. 18. MSG msg; 19. MyRegisterClass(hInstance); 20. if (!InitInstance (hInstance, nCmdShow) 21. 22. return FALSE; 23. 24. /消息循环 25. while (GetMessage( 28. DispatchMessage( 29. 30. return msg.wParam; 31. 32. /*设计一个窗口类,类似填空题,使用

22、窗口结构体* 33. ATOM MyRegisterClass(HINSTANCE hInstance) 34. 35. WNDCLASSEX wcex; 36. wcex.cbSize = sizeof(WNDCLASSEX); 37. wcex.style = CS_HREDRAW | CS_VREDRAW; 38. wcex.lpfnWndProc = (WNDPROC)WndProc; 39. wcex.cbClsExtra = 0; 40. wcex.cbWndExtra = 0; 41. wcex.hInstance = hInstance; 42. wcex.hIcon = Lo

23、adIcon(NULL,IDI_APPLICATION); 43. wcex.hCursor = NULL; 44. wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 45. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 46. wcex.lpszMenuName = NULL; 47. wcex.lpszClassName = “canvas“; 48. wcex.hIconSm = NULL; 49. return RegisterClassEx( 50. 51. /*初始化函数* 52. / 1.建立与

24、窗口 DC 兼容的内存 DC 53. / 2.从文件加载背景图及透明的洋葱头 54. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 55. 56. HWND hWnd; 57. HDC hdc; 58. hInst = hInstance; 59. hWnd = CreateWindow(“canvas“, “浅墨的绘图窗口“ , WS_OVERLAPPEDWINDOW, 60. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 61. if (!hWn

25、d) 62. 63. return FALSE; 64. 65. MoveWindow(hWnd,10,10,600,444,true); 66. ShowWindow(hWnd, nCmdShow); 67. UpdateWindow(hWnd); 68. hdc = GetDC(hWnd); /获得窗口 DC 69. mdc = CreateCompatibleDC(hdc); /创建与窗口兼容的内存 DC(mdc) 70. bg = (HBITMAP)LoadImage(NULL,“bg.bmp“,IMAGE_BITMAP,600,444,LR_LOADFROMFILE); 71. 72

26、. MyPaint(hdc); 73. ReleaseDC(hWnd,hdc); 74. return TRUE; 75. 76. /*自定义绘图函数* 77. /透明贴图 78. void MyPaint(HDC hdc) 79. 80. SelectObject(mdc,bg); 81. BitBlt(hdc,0,0,600,450,mdc,0,0,SRCCOPY); /先将背景图贴到显示窗口中 82. CImage image; /定义一个 CImage 对象,用于透明贴图 83. CString str; /定义一个 CString 对象,用于存放文件名字符串 84. str=“oni

27、on.png“; /将字符串赋值为文件名 85. image.Load(str); /在 image 中载入图像文件 86. image.Draw(hdc,120,180,85,113,0,0,85,113); /调用 Draw 进行透明贴图 87. /或者为 image.TransparentBlt(hdc, 120, 180, 85, 113,CLR_INVALID );/调用 TransparentBlt 进行透明贴图 88. image.Destroy(); 89. 90. /*消息处理函数* 91. LRESULT CALLBACK WndProc(HWND hWnd, UINT m

28、essage, WPARAM wParam, LPARAM lParam) 92. 93. PAINTSTRUCT ps; 94. HDC hdc; 95. switch (message) 96. 97. case WM_PAINT: /窗口重绘消息 98. hdc = BeginPaint(hWnd, 99. MyPaint(hdc); 100. EndPaint(hWnd, 101. break; 102. case WM_DESTROY: /窗口结束消息 103. DeleteDC(mdc); 104. DeleteObject(bg); 105. PostQuitMessage(0)

29、; 106. break; 107. default: /其他消息 108. return DefWindowProc(hWnd, message, wParam, lParam); 109. 110. return 0; 111. 最后得到的效果图如下:我们可以改变 CImage:Draw 函数的参数值,让 “洋葱头”出现在地图不同的地方。通过这个实例可以发现,用 CImage 类进行透明贴图,实在是方便多了。本节笔记到这里就结束了,由于近期在做一个纯 flash 的网站,更新速度和评论的回复都不像往常那么及时,希望大家能够体谅。本节笔记的源代码请点击这里下载: 【Visual C+】Code_Note_14感谢一直支持【Visual C+】游戏开发笔记系列专栏的朋友们,也请大家继续关注我的专栏,我一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。精通游戏开发的路还很长很长,非常希望能和大家一起交流,共同学习,共同进步。大家看过后觉得值得一看的话,可以顶一下这篇文章,你们的支持是我继续写下去的动力如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨编程相关的问题。最后,谢谢你们一直的支持浅墨于 2012 年 4 月 3 日The end.

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 专业基础教材

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报