使用AlphaBlend函数实现位图半透明绘制

Foooooooood

发布日期: 2018-12-20 12:36:17 浏览量: 1765
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

背景

自己使用VC和VS写过很多小游戏,而且不是用现成的游戏引擎,纯粹是使用GDI函数来进行绘图。所以,积累了一些绘图的经验。

那么,对于位图半透明的绘制,在小游戏中使用也比较多。例如烟雾、光等之类的绘制。在没有了解 AlphaBlend 函数之前,绘制半透明位图都是获取两张图片的RGB数据,然后按指定透明度计算出混合后的RGB的值,再显示出来。这样,需要自己计算的过程,算是麻烦。而现在,AlphaBlend 函数直接封装了这步操作,提供了方便使用的接口。

现在,我们就来介绍使用 AlphaBlend 函数绘制半透明位图,写成文档,分享给大家。

函数介绍

AlphaBlend 函数

该函数用来显示具有指定透明度的图像。

函数声明

  1. AlphaBlend(
  2. HDC hdcDest,
  3. int nXOriginDest,
  4. int nYOriginDest,
  5. int nWidthDest,
  6. int hHeightDest,
  7. HDC hdcSrc,
  8. int nXOriginSrc,
  9. int nYOriginSrc,
  10. int nWidthSrc,
  11. int nHeightSrc,
  12. BLENDFUNCTION blendFunction
  13. );

参数

  • hdcDest:指向目标设备环境的句柄。

  • nXOriginDest:指定目标矩形区域左上角的X轴坐标,按逻辑单位。

  • nYOriginDest:指定目标矩形区域左上角的Y轴坐标,按逻辑单位。

  • nWidthDest:指定目标矩形区域的宽度,按逻辑单位。

  • hHeightdest:指向目标矩形区域的高度,按逻辑单位。

  • hdcSrc:指向源设备环境的句柄。

  • nXOriginSrc:指定源矩形区域左上角的X轴坐标,按逻辑单位。

  • nYOriginSrc:指定源矩形区域左上角的Y轴坐标,按逻辑单位。

  • nWidthSrc:指定源矩形区域的宽度,按逻辑单位。

  • nHeightSrc:指定源矩形区域的高度,按逻辑单位。

  • blendFunction:指定用于源位图和目标位图使用的alpha混合功能,用于整个源位图的全局alpha值和格式信息。最后一个参数blendFunction是一个BLENDFUNCTION结构。

    BLENDFUNCTION结构介绍如下:

    typedef struct _BLENDFUNCTION {
    ​ BYTE BlendOp;
    ​ BYTE BlendFlags;
    ​ BYTE SourceConstantAlpha;
    ​ BYTE AlphaFormat;
    }BLENDFUNCTION, PBLENDFUNCTION, LPBLENDFUNCTION;

    BlendOp: 这个参数必须也只能为AC_SRC_OVER(0x00),意思就是把源图片覆盖到目标之上。

    BlendFlags: 必须为0 。

    SourceConstantAlpha: 简写为SCA,指定源图片的透明度,这个值是会和源图片的Alpha通道值合并计算的;即设置透明度,0为完全透明,255为完全不透明 。

    AlphaFormat: 可以填两种,一种是0x00,一种是AC_SRC_ALPHA (0x01);0表示常量alpha值,AC_SRC_ALPHA表示每个像素有各自的alpha通道。

返回值

  • 如果函数执行成功,那么返回值为TRUE;如果函数执行失败,那么返回值为FALSE。

透明度绘制介绍

下面,我们举例说明,什么是透明度绘制。现在,有两张位图,一张是背景图:

另一张是其它图片:

那么,半透明绘制,就是要将两张图片绘制在一起,实现下面的效果:

实现原理

半透明位图绘制的功能实现,主要是靠 AlphaBlend 函数完成的。AlphaBlend 函数的最后一个参数 BLENDFUNCTION 结构指定用于源位图和目标位图使用的alpha混合功能。

其中,BLENDFUNCTION 结构的 SourceConstantAlpha 变量,指定了源图片的透明度,这个值是会和源图片的 Alpha 通道值合并计算的;即设置透明度,0为完全透明,255为完全不透明 。也就是说,只要我们控制这个变量的值,就控制了位图绘制的透明度。

编码实现

导入库文件

  1. #include <WinGDI.h>
  2. #pragma comment(lib, "Msimg32.lib")

绘制背景位图

  1. BOOL PaintBmp(HWND hWnd)
  2. {
  3. // 获取窗口的客户区域的显示设备上下文环境的句柄
  4. HDC hDC = ::GetDC(hWnd);
  5. // 创建一个与hDC兼容的内存设备上下文环境
  6. HDC hBuf = ::CreateCompatibleDC(hDC);
  7. // 加载位图, 获取位图句柄
  8. HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, "image\\bg.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  9. // 选择位图句柄到hBuf中, 并获取返回的原来位图句柄
  10. HBITMAP hOldBmp = (HBITMAP)::SelectObject(hBuf, hBmp);
  11. // 绘图
  12. ::BitBlt(hDC, 0, 0, 764, 397, hBuf, 0, 0, SRCCOPY);
  13. // 还原位图对象
  14. ::SelectObject(hBuf, hOldBmp);
  15. // 释放位图
  16. ::DeleteObject(hBmp);
  17. // 释放兼容的内存设备上下文环境
  18. ::DeleteDC(hBuf);
  19. // 释放设备上下文环境
  20. ::ReleaseDC(hWnd, hDC);
  21. return TRUE;
  22. }

指定透明度绘制

  1. BOOL PaintAlphaBlendBmp(HWND hWnd)
  2. {
  3. // 获取窗口的客户区域的显示设备上下文环境的句柄
  4. HDC hDC = ::GetDC(hWnd);
  5. // 创建一个与hDC兼容的内存设备上下文环境
  6. HDC hBuf = ::CreateCompatibleDC(hDC);
  7. // 加载位图, 获取位图句柄
  8. HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, "image\\1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  9. // 选择位图句柄到hBuf中, 并获取返回的原来位图句柄
  10. HBITMAP hOldBmp = (HBITMAP)::SelectObject(hBuf, hBmp);
  11. // 设置透明度参数
  12. BLENDFUNCTION ftn = { 0 };
  13. ftn.BlendOp = 0;
  14. ftn.BlendFlags = 0;
  15. ftn.SourceConstantAlpha = 200; // 透明度指定
  16. ftn.AlphaFormat = 0;
  17. // 指定透明度绘制
  18. ::AlphaBlend(hDC, 0, 0, 650, 350, hBuf, 0, 0, 650, 350, ftn);
  19. // 还原位图对象
  20. ::SelectObject(hBuf, hOldBmp);
  21. // 释放位图
  22. ::DeleteObject(hBmp);
  23. // 释放兼容的内存设备上下文环境
  24. ::DeleteDC(hBuf);
  25. // 释放设备上下文环境
  26. ::ReleaseDC(hWnd, hDC);
  27. return TRUE;
  28. }

程序测试

调用上述封装好的函数进行测试,两幅位图成功按照指定的透明度混合显示:

总结

这个小程序重点是要理解 AlphaBlend 函数的使用方式,可以自己更改透明度的值尝试几次,加深理解。这个函数同样支持对位图伸缩绘制,使用起来比较灵活。

上传的附件 cloud_download AlphaBlend_Test.7z ( 333.10kb, 12次下载 )

发送私信

一盏灯,一条路,一个你

14
文章数
27
评论数
最近文章
eject