alphablend函数(如何基于纯GDI实现alpha通道的矢量和文字绘制)

本文目录
如何基于纯GDI实现alpha通道的矢量和文字绘制
一个基本的图形引擎要包括几个方面的支持:位图绘制,文字绘制,矢量绘制(如矩形,线条)。
可惜GDI这个20多年前发明的老古董,对这几项的绘制, 除了位图绘制可以通过AlphaBlend支持alpha通道,其他绘制都不支持alpha通道。
那有没有方法让能通过纯GDI让文字和矢量的绘制也支持alpha通道呢?
讨论这个问题之前,我们先看一下用GDI函数在支持alpha通道的DC上绘制会发生什么? 这里 有人讨论过这个问题。
当然我们也可以自己测试,测试结果是GDI函数会把绘制覆盖目标像素的alpha通道改都改成0, 也 就是说如果画一条线条, 线条通过的位置的alpha通道都回被改成0。
实际上我们可以利用系统的这个特性,结合AlphaBlend函数实现alpha通道的文字和矢量图形绘制。
具体做法大概如下:
1. 创建内存DC和一幅32bit的DIB Section, 将位图选入DC
2. 将位图的所有字节全都改成0xFF
3. 在内存DC上用文字和矢量 GDI函数 (如DrawText, Rectangle)绘制东西
4. 遍历所有像素,发现alpha通道为0 (表示该区域被绘制过),则将 alpha通道改成我们需要的alpha值;否则,则将像素的alpha通道改成0 (表示没有内容绘制上去)
5. 最后通过AlphaBlend将生成好的DIB Section合成绘制到目标区域
通过上面这种方法, 我们可以实现带alpha通道的矢量和文字绘制,我猜测GDI+应该也是通过类似这种修改像素的方法实现的。
当然,这种方法因为效率问题, 建议一些简单的绘制可以考虑 (如果不想引入GDI+), 如果大规模应用就要仔细斟酌了。
微软当初引入GDI+,部分原因就是因为GDI不支持alpha通道,可惜GDI+的效率是如此臭名昭著, 大家大部分时候都是尽量避免引入,很多时候我们引入GDI+只是为了使用它的图像编解码功能。
还好技术总是不断进步,如果你的程序不用考虑XP(现在看来还要过几年), Vista之后系统为我们提供了高效的图形支持:
图像编解码可以用WIC,文字操作可以用DirectWrite,图形渲染可以用Direct2D (既支持alpha通道,又支持GPU加速), 实际上IE9之后的浏览器都已采用Direct2D开发。
求API中AlphaBlend函数使用示例
1 AlphaBlend
函数功能:该函数用来显示透明或半透明像素的位图。
函数原型:AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int hHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunction);
参数:
hdcDest:指向目标设备环境的句柄。
nXoriginDest:指定目标矩形区域左上角的X轴坐标,按逻辑单位。
nYOriginDest:指定目标矩形区域左上角的Y轴坐标,按逻辑单位。
nWidthDest:指定目标矩形区域的宽度,按逻辑单位。
hHeghtdest:指向目标矩形区域高度的句柄,按逻辑单位。
hdcSrc:指向源设备环境的句柄。
nXOriginSrc:指定源矩形区域左上角的X轴坐标,按逻辑单位。
nYOriginSrc:指定源矩形区域左上角的Y轴坐标,按逻辑单位。
nWidthSrc:指定源矩形区域的宽度,按逻辑单位。
nHeightSrc:指定源矩形区域的高度,按逻辑单位。
blendFunction:指定用于源位图和目标位图使用的alpha混合功能,用于整个源位图的全局alpha值和格式信息。源和目标混合功能当前只限为AC_SRC_OVER。
返回值:如果函数执行成功,那么返回值为TRUE;如果函数执行失败,那么返回值为FALSE。
Windows NT:若想获取更多错误信息,请调用GetLastError函数。
备注:如果源矩形区域与目标矩形区域大小不一样,那么将缩放源位图与目标矩形区域匹配。如果使用SetStretchBltMode函数,那么iStretchMode的值是BLACKONWHITE和WHITEONBLACK,在本函数中,iStretchMode的值自动转换成COLORONCOLOR。目标坐标使用为目标设备环境当前指定的转换方式进行转换。源坐标则使用为源设备环境指定的当前转换方式进行转换。如果源设备环境标识为增强型图元文件设备环境,那么会出错(并且该函数返回FALSE)。如果目标和源位图的色彩格式不同,那么AlphaBlend将源位图转换以匹配目标位图。
AlphaBlend不支持镜像。如果源或目标区域的宽度或高度为负数,那么调用将失败。
注意添加 #pragma comment(lib,"Msimg32.lib")库
下面是一个例子:
#include 《windows.h》
#pragma comment(lib,"Msimg32.lib")
HINSTANCE g_hIns;
HWND g_hWnd;
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iCmdShow)
{
g_hIns=hInstance;
static TCHAR szAppName=TEXT("HelloWin");
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProc;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName=szAppName;
if(!RegisterClass(&wndClass))
{
MessageBox(NULL,TEXT("error"),szAppName,MB_ICONERROR|MB_OK);
return 0;
}
hWnd=CreateWindow(szAppName,TEXT("The hello program"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
int iReturn;
//也可以放在此
ShowWindow(hWnd,iCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg,hWnd,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static HDC hdc;
static HDC hBitmapDC;
static HBITMAP hBitmap;
static int w=50;
static int h=50;
static BLENDFUNCTION bf;
PAINTSTRUCT ps;
switch (message)
{
case WM_PAINT :
hdc=BeginPaint(hWnd,&ps);
hBitmapDC = CreateCompatibleDC(hdc);
hBitmap = CreateCompatibleBitmap(hdc,w,h);
SelectObject(hBitmapDC,hBitmap);
SetTextColor(hBitmapDC,RGB(0,255,0));
TextOut(hBitmapDC,0,0,TEXT("asdf"),4);
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 50;
AlphaBlend(hdc,0,0,w,h,hBitmapDC,0,0,w,h,bf);
EndPaint (hWnd, &ps) ;
break;
case WM_DESTROY :
PostQuitMessage (0) ;
break ;
default:
return DefWindowProc (hWnd, message, wParam, lParam) ;
}
return 1;
}
VB alpha值是什么
很简单,使用GDI的AlphaBlend函数就可以。可以设置全局Alpha混合系数(0到255),也可以混合带有Alpha通道的32位BMP。
如果要做稍复杂的处理,可以使用GDI+,里面的所有绘图手段都支持Alpha通道。
附AlphaBlend函数在VB中的声明:
Public Type t_BLENDFUNCTION
BlendOp As Byte
BlendFlags As Byte
SourceConstantAlpha As Byte
AlphaFormat As Byte
End Type
Public Declare Function AlphaBlend Lib "msimg32" (ByVal hDestDC As Long, _
ByVal xDest As Long, _
ByVal yDest As Long, _
ByVal nWidthDest As Long, _
ByVal nHeightDest As Long, _
ByVal hSrcDC As Long, _
ByVal xSrc As Long, _
ByVal ySrc As Long, _
ByVal nWidthSrc As Long, _
ByVal nHeightSRC As Long, _
ByVal BLENDFUNCTION As Long) As Long
我发现 WINAPI 里面的 alphablend()函数不能用啊
查了一下MSDN,但是也不知道问题到底是在哪里
The AlphaBlend function displays bitmaps that have transparent or semitransparent pixels.
BOOL AlphaBlend(
HDC hdcDest, // handle to destination DC
int nXOriginDest, // x-coord of upper-left corner
int nYOriginDest, // y-coord of upper-left corner
int nWidthDest, // destination width
int nHeightDest, // destination height
HDC hdcSrc, // handle to source DC
int nXOriginSrc, // x-coord of upper-left corner
int nYOriginSrc, // y-coord of upper-left corner
int nWidthSrc, // source width
int nHeightSrc, // source height
BLENDFUNCTION blendFunction // alpha-blending function
);
Requirements
Windows NT/2000/XP: Included in Windows 2000 and later.
Windows 95/98/Me: Included in Windows 98 and later.
Header: Declared in Wingdi.h; include Windows.h.
Library: Included as a resource in Msimg32.dll.
看Requirements
应该#include Windows.h就可以了。因为你这个是编译错。

更多文章:
海报免费制作app(手机什么软件做海报手机海报制作app哪个好免费)
2025年12月22日 23:45
shell编程用户信息管理(利用Linux系统Shell命令编写脚本实现对用户行为的监控和审计功能. 求大神怎么写啊)
2026年7月27日 00:15
latter与later区别(later和latter有什么不同)
2025年12月6日 19:00
eclipse运行窗口放大(怎么把eclipse的字体调大)
2025年9月7日 12:00
易语言官网为啥下载安装不了(易语言已经下载安装破解补丁,为啥生不成安装软件)
2026年5月5日 04:15
源代码经典台词中英(模仿游戏中比较经典的台词,中英文都要哦)
2025年6月12日 22:15
no such file or directory怎么解决(No such file or directory怎么解决)
2025年8月1日 03:45
java算法视频教程(求实战应用Java算法分析与设计(链表、二叉树、哈夫曼树、图、动态规划、HashTable算法)教学视频)
2025年7月4日 00:15
centos7下载官网(正在安装Linux系统的CentOS 7到这一步了)
2026年3月4日 01:15
微服务必须用docker吗(微服务为什么要选择docker)
2025年7月29日 21:15
onclick可以调用两个方法吗(java脚本中同一按钮当点击时能同时执行两个函数吗)
2025年7月13日 16:15





![在VC++中,tchar[]怎么转成string类型?c++ 关于getchar()函数](/static/images/nopic/16.jpg)



