屏幕在16位色的情况下,alphablend函数是不是无效? 我的程序使用alphablend函数将内存中创建的HDC叠加至屏幕时,在屏幕32位色的情况下正常,但当屏幕颜色改为16位色时程序就不显示了,请问是怎么回事,用Bitblt正常,是不是屏幕在16位色的情况下,alphablend函数无效? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 void DrawAlphaBlend_cpp( WORD * dstAddr, // 目标图的起始地址 WORD * srcAddr, // 源图的起始地址 DWORD cntX, // 横轴要处理的宽度 DWORD cntY, // 纵轴要处理的高度 DWORD dstSkipBytes, // 目标地址在处理完横向宽度最后一个点后要跳过多少个字节 DWORD srcSkipBytes, // 源地址在处理完横向宽度最后一个点后要跳过多少个字节 DWORD srcAlphaLevel )// Alpha级数 0 ~ 32{ DWORD srcColor; // 源点颜色 DWORD dstColor; // 目标点颜色 // 此值要根据你所需要处理的像素格式而定,这里仅指 16 位色 555模式 RGB顺序 DWORD Mask32 = 0x3E07C1F; WORD xCnt = cntX; // 暂存宽度值,以便循环运算 for( ;cntY>0; --cntY, cntX = xCnt ) { for( ; cntX>0; --cntX ) { srcColor = *srcAddr | (*srcAddr<<16); //扩宽到32位 srcColor &= Mask32; // 通过掩码得到正确的扩宽颜色值 dstColor = *dstAddr | (*dstAddr<<16); dstColor &= Mask32; srcColor = (srcColor - dstColor) * srcAlphaLevel / 32 + dstColor; srcColor &= Mask32; // 通过掩码把结果的其它无用数据去掉 // 还原到正确的16位颜色值 srcColor = (srcColor & 0xffff0000)>>16 | (srcColor & 0x0000ffff ); // 改变目标图的点为结果点,这样直接显示目标图即可知道整个结果 *dstAddr = srcColor; ++dstAddr; ++srcAddr; } dstAddr = (WORD*)((BYTE*)dstAddr + dstSkipBytes); srcAddr = (WORD*)((BYTE*)srcAddr + srcSkipBytes); }} 详情请见:http://blog.csdn.net/starofrainnight/archive/2007/03/19/1533617.aspx16位色AlphaBlend深度探索 有效的,关键是看你创建这个位图用的API,一定要是CreateDIBSection,并且一定要指明32位,不能用CreateCompatibleBitmap或者CreateDIBitmap to 各位: 下面是我的delphi源码,用alphablend叠加带透明通道的图片,在屏幕色深32bits时正常,在此16位色时不显示,请帮我看看procedure TForm1.FormCreate(Sender: TObject);var GPImage: TGPImage;begin Self.DoubleBuffered := True; BorderStyle := bsNone; m_Blend.BlendOp := AC_SRC_OVER; m_Blend.BlendFlags := 0; m_Blend.AlphaFormat := AC_SRC_ALPHA; m_Blend.SourceConstantAlpha := 255; GPImage := TGPImage.Create('backend.png'); Width := GPImage.GetWidth; Height := GPImage.GetHeight; GPImage.Free; ptWinPos.X := 20; ptWinPos.Y := 20; sizeWindow.cx := Width; sizeWindow.cy := Height; ptSrc.x := 0; ptSrc.y := 0; W; ReDraw;end;procedure Tform1.W;var GPGraph: TGPGraphics; hdcTemp: HDC; hBMP: HBITMAP; GPImage: TGPImage;begin hdcTemp := CreateDC('DISPLAY', nil, nil, nil); w_memory := CreateCompatibleDC(hdcTemp); hBMP := CreateCompatibleBitmap(hdcTemp, Width, Height); GPImage := TGPImage.Create('w\12.png'); SelectObject(w_memory, hBMP); GPGraph := TGPGraphics.Create(w_memory); GPGraph.DrawImage(GPImage, 0, 0, GPImage.GetWidth(), GPImage.GetHeight()); GPImage.Free; GPGraph.ReleaseHDC(w_memory); GPGraph.Free; DeleteObject(hBMP); ReleaseDC(0, hdcTemp); DeleteDC(hdcTemp);end;procedure Tform1.ReDraw;var hDC, hdcScreen, m_hdcMemory, hOldHandle: THandle; hBMP: HBITMAP; GPGraph: TGPGraphics; GPImage: TGPImage;begin hdc := GetDC(0); hdcScreen := GetDC(0); GPImage := TGPImage.Create('backend.png'); m_hdcMemory := CreateCompatibleDC(hDC); hBMP := CreateCompatibleBitmap(hdc, Width, Height); hOldHandle := SelectObject(m_hdcMemory, hBMP); GPGraph := TGPGraphics.Create(m_hdcMemory); GPGraph.DrawImage(GPImage, 0, 0, GPImage.GetWidth, GPImage.GetHeight); DeleteObject(hBMP); try Windows.AlphaBlend(m_hdcMemory, 0, 0, Width, Height, w_memory, 0, 0, Width, Height, m_Blend); SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED); UpdateLayeredWindow(Handle, hdcScreen, @ptWinPos, @sizeWindow, m_hdcMemory, @ptSrc, 0, @m_Blend, 2); finally GPImage.Free; GPGraph.ReleaseHDC(m_hdcMemory); GPGraph.Free; SelectObject(m_hdcMemory, hOldHandle); ReleaseDC(0, hDC); ReleaseDC(0, hdcScreen); DeleteDC(m_hdcMemory); end; OldStyle := GetWindowLong(Handle, GWL_EXSTYLE);end; procedure Tform1.W;var GPGraph: TGPGraphics; hdcTemp: HDC; hBMP: HBITMAP; GPImage: TGPImage;begin hdcTemp := CreateDC('DISPLAY', nil, nil, nil); w_memory := CreateCompatibleDC(hdcTemp); hBMP := CreateCompatibleBitmap(hdcTemp, Width, Height); GPImage := TGPImage.Create('w\12.png'); SelectObject(w_memory, hBMP); GPGraph := TGPGraphics.Create(w_memory); GPGraph.DrawImage(GPImage, 0, 0, GPImage.GetWidth(), GPImage.GetHeight()); GPImage.Free; GPGraph.ReleaseHDC(w_memory); GPGraph.Free; DeleteObject(hBMP); ReleaseDC(0, hdcTemp); DeleteDC(hdcTemp);end;这个函数可能有问题, w_memory := CreateCompatibleDC(hdcTemp);要改成w_memory := CreateCompatibleDC(0);否则位图可能选不进去。可能已经有人说过了,位图能否选进一个DC,是有规则的:1. 兼容DC只能选兼容位图,即位图格式和DC中的位图格式完全一样;2. 内存DC可以选入任何设备无关位图;hBMP := CreateCompatibleBitmap(hdcTemp, Width, Height);这也有问题,虽然这样创建是兼容了,但是在屏幕是16位色的情况下,你的位图也是16位的了,就没有alpha通道了。应当改成用CreateDIBSection函数来创建。 我想问问叠加后的结果输出成jpg图片 恭喜阿泰 如何把ADOQuery的数据集反向返回数据库表?? DLL菜单的事件响应 在线求解一些小问题 哎,贵州的菜鸟被delphi牛人欺负了哈 报表大侠,有经验的高手救我 新版简直是垃圾! 强烈建议大家发EMAIL给版主要求改回原版 !! 怎样得到上个月今天的日期date型 请问大家什么样的软件安装程序制作工具比较不错 请各位帮忙:TClientSocket向TServerSocket连接,第一次不成功,再连一次... delphi treeview控件 修改节点名的问题 求查找文件代码
WORD * dstAddr, // 目标图的起始地址
WORD * srcAddr, // 源图的起始地址
DWORD cntX, // 横轴要处理的宽度
DWORD cntY, // 纵轴要处理的高度
DWORD dstSkipBytes, // 目标地址在处理完横向宽度最后一个点后要跳过多少个字节
DWORD srcSkipBytes, // 源地址在处理完横向宽度最后一个点后要跳过多少个字节
DWORD srcAlphaLevel )// Alpha级数 0 ~ 32
{
DWORD srcColor; // 源点颜色
DWORD dstColor; // 目标点颜色
// 此值要根据你所需要处理的像素格式而定,这里仅指 16 位色 555模式 RGB顺序
DWORD Mask32 = 0x3E07C1F;
WORD xCnt = cntX; // 暂存宽度值,以便循环运算
for( ;cntY>0; --cntY, cntX = xCnt )
{
for( ; cntX>0; --cntX )
{
srcColor = *srcAddr | (*srcAddr<<16); //扩宽到32位
srcColor &= Mask32; // 通过掩码得到正确的扩宽颜色值
dstColor = *dstAddr | (*dstAddr<<16);
dstColor &= Mask32;
srcColor = (srcColor - dstColor) * srcAlphaLevel / 32 + dstColor;
srcColor &= Mask32; // 通过掩码把结果的其它无用数据去掉
// 还原到正确的16位颜色值
srcColor = (srcColor & 0xffff0000)>>16 | (srcColor & 0x0000ffff );
// 改变目标图的点为结果点,这样直接显示目标图即可知道整个结果
*dstAddr = srcColor;
++dstAddr;
++srcAddr;
}
dstAddr = (WORD*)((BYTE*)dstAddr + dstSkipBytes);
srcAddr = (WORD*)((BYTE*)srcAddr + srcSkipBytes);
}
}
16位色AlphaBlend深度探索
下面是我的delphi源码,用alphablend叠加带透明通道的图片,在屏幕色深32bits时正常,在此16位色时不显示,请帮我看看procedure TForm1.FormCreate(Sender: TObject);
var GPImage: TGPImage;
begin
Self.DoubleBuffered := True;
BorderStyle := bsNone;
m_Blend.BlendOp := AC_SRC_OVER;
m_Blend.BlendFlags := 0;
m_Blend.AlphaFormat := AC_SRC_ALPHA;
m_Blend.SourceConstantAlpha := 255;
GPImage := TGPImage.Create('backend.png');
Width := GPImage.GetWidth;
Height := GPImage.GetHeight;
GPImage.Free; ptWinPos.X := 20;
ptWinPos.Y := 20;
sizeWindow.cx := Width;
sizeWindow.cy := Height;
ptSrc.x := 0;
ptSrc.y := 0;
W;
ReDraw;
end;procedure Tform1.W;
var GPGraph: TGPGraphics;
hdcTemp: HDC;
hBMP: HBITMAP;
GPImage: TGPImage;
begin
hdcTemp := CreateDC('DISPLAY', nil, nil, nil);
w_memory := CreateCompatibleDC(hdcTemp);
hBMP := CreateCompatibleBitmap(hdcTemp, Width, Height);
GPImage := TGPImage.Create('w\12.png');
SelectObject(w_memory, hBMP);
GPGraph := TGPGraphics.Create(w_memory);
GPGraph.DrawImage(GPImage, 0, 0, GPImage.GetWidth(), GPImage.GetHeight());
GPImage.Free;
GPGraph.ReleaseHDC(w_memory);
GPGraph.Free;
DeleteObject(hBMP);
ReleaseDC(0, hdcTemp);
DeleteDC(hdcTemp);
end;procedure Tform1.ReDraw;
var hDC, hdcScreen, m_hdcMemory, hOldHandle: THandle;
hBMP: HBITMAP;
GPGraph: TGPGraphics;
GPImage: TGPImage;
begin
hdc := GetDC(0);
hdcScreen := GetDC(0);
GPImage := TGPImage.Create('backend.png');
m_hdcMemory := CreateCompatibleDC(hDC);
hBMP := CreateCompatibleBitmap(hdc, Width, Height);
hOldHandle := SelectObject(m_hdcMemory, hBMP);
GPGraph := TGPGraphics.Create(m_hdcMemory);
GPGraph.DrawImage(GPImage, 0, 0, GPImage.GetWidth, GPImage.GetHeight);
DeleteObject(hBMP); try
Windows.AlphaBlend(m_hdcMemory, 0, 0, Width, Height, w_memory, 0, 0, Width, Height, m_Blend);
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
UpdateLayeredWindow(Handle, hdcScreen, @ptWinPos, @sizeWindow, m_hdcMemory, @ptSrc, 0, @m_Blend, 2);
finally
GPImage.Free;
GPGraph.ReleaseHDC(m_hdcMemory);
GPGraph.Free;
SelectObject(m_hdcMemory, hOldHandle);
ReleaseDC(0, hDC);
ReleaseDC(0, hdcScreen);
DeleteDC(m_hdcMemory);
end;
OldStyle := GetWindowLong(Handle, GWL_EXSTYLE);
end;
var GPGraph: TGPGraphics;
hdcTemp: HDC;
hBMP: HBITMAP;
GPImage: TGPImage;
begin
hdcTemp := CreateDC('DISPLAY', nil, nil, nil);
w_memory := CreateCompatibleDC(hdcTemp);
hBMP := CreateCompatibleBitmap(hdcTemp, Width, Height);
GPImage := TGPImage.Create('w\12.png');
SelectObject(w_memory, hBMP);
GPGraph := TGPGraphics.Create(w_memory);
GPGraph.DrawImage(GPImage, 0, 0, GPImage.GetWidth(), GPImage.GetHeight());
GPImage.Free;
GPGraph.ReleaseHDC(w_memory);
GPGraph.Free;
DeleteObject(hBMP);
ReleaseDC(0, hdcTemp);
DeleteDC(hdcTemp);
end;这个函数可能有问题, w_memory := CreateCompatibleDC(hdcTemp);要改成w_memory := CreateCompatibleDC(0);否则位图可能选不进去。
可能已经有人说过了,位图能否选进一个DC,是有规则的:
1. 兼容DC只能选兼容位图,即位图格式和DC中的位图格式完全一样;
2. 内存DC可以选入任何设备无关位图;
hBMP := CreateCompatibleBitmap(hdcTemp, Width, Height);
这也有问题,虽然这样创建是兼容了,但是在屏幕是16位色的情况下,你的位图也是16位的了,就没有alpha通道了。应当改成用CreateDIBSection函数来创建。