半透明AlphaBlend函数简析&SOUI在GDI渲染下text控件不能设置半透明解决方案

来源:互联网 发布:淘宝 电费交不了了 编辑:程序博客网 时间:2024/06/05 02:17

AlphaBlend简析

函数功能:该函数用来显示透明或半透明像素的位图。

函数原型:

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);
参数:
hdcDest:指向目标设备环境的句柄。
nXoriginDest:指定目标矩形区域左上角的X轴坐标,按逻辑单位。
nYOriginDest:指定目标矩形区域左上角的Y轴坐标,按逻辑单位。
nWidthDest:指定目标矩形区域的宽度,按逻辑单位。
hHeghtdest:指向目标矩形区域高度的句柄,按逻辑单位。
hdcSrc:指向源设备环境的句柄。
nXOriginSrc:指定源矩形区域左上角的X轴坐标,按逻辑单位。
nYOriginSrc:指定源矩形区域左上角的Y轴坐标,按逻辑单位。
nWidthSrc:指定源矩形区域的宽度,按逻辑单位。
nHeightSrc:指定源矩形区域的高度,按逻辑单位。
blendFunction:指定用于源位图和目标位图使用的alpha混合功能,用于整个源位图的全局alpha值和格式信息。源和目标混合功能当前只限为AC_SRC_OVER。

BLENDFUNCTION是AlphaBlend用控制透明效果的重要参数.定义如下:
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为完全不透明
The SourceConstantAlpha member of BLENDFUNCTION specifies an alpha transparency value to be used on the entire source bitmap. The SourceConstantAlpha value is combined with any per-pixel alpha values. If SourceConstantAlpha is 0, it is assumed that the image is transparent. Set the SourceConstantAlpha value to 255 (which indicates that the image is opaque) when you only want to use per-pixel alpha values.
AlphaFormat: 可以填两种,一种是0x00,一种是AC_SRC_ALPHA(0x01).填0的话,AlphaBlend据说就和BitBlt一样了,我没有试验过~填1的话,源DC必须是32位的DC不然的话,AlphaBlend会返回参数错误.

计算公式(当SCA不是0xFF时):

  输出像素(R,G,B,A) = 源像素(R,G,B,A) * SCA / 0xFF + 目标像素(R,G,B,A) * (1.0 - SCA / 0xFF)

当SCA是0xFF时,计算公式

  输出像素(R,G,B,A) = 源像素(R,G,B,A) + 目标像素(R,G,B,A) * (1.0 - 源像素(A) / 0xFF)

混合计算公式

   输出像素(R,G,B) = 源像素(R,G,B) * SCA / 0xFF + 目标像素(R,G,B) * (1.0 - 源像素(A) / 0xFF * SCA / 0xFF)

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

AlphaBlend does not support mirroring. If either the width or height of the source or destination is negative, this call will fail.When rendering to a printer, first call GetDeviceCaps with SHADEBLENDCAPS to determine if the printer supports blending with AlphaBlend. Note that, for a display DC, all blending operations are supported and these flags represent whether the operations are accelerated.If the source and destination are the same surfacethat is, they are both the screen or the same memory bitmap and the source and destination rectangles overlap, an error occurs and the function returns FALSE.

SOUI中在GDI渲染下text控件不能设置半透明解决方案

首先在GDI中实现半透明是运用AlphaBlend函数做的,并通过一下公式计算输出的像素的:
计算公式(当SCA不是0xFF时):

  输出像素(R,G,B,A) = 源像素(R,G,B,A) * SCA / 0xFF + 目标像素(R,G,B,A) * (1.0 - SCA / 0xFF)

源区域的像素值加上目标区域的像素值做以上的计算,最终得到正常的半透明状态。如果源像素或者目标像素的值出现偏差的话,最终输出的像素值将会出现错误,导致半透明状态出现异样。
那么为什么SOUI中用GDI渲染时的SStatic控件设设置透明度就会出现如下字体加粗还有锯齿的情况呢?这里写图片描述
这是因为text控件默认是没有背景色的,这样源像素在取值时去到了字体的前景色(这个是正常的),因为没有背景色导致取背景色的时候取到的是整个大窗口的背景色,导致取出的源像素数值有偏差,从而导致经过上述公式的计算后输出的像素值出现偏差,使得半透明状态出现异样。
目前想到的解决这种问题的方法便是给text控件加上背景色(colorBkgnd),这样通过上述公式计算的输出像素值就不会有误差!大家看一下下边修正的效果:
这里写图片描述
第一行为设置透明度也设置了背景色的,渲染出来的字体有半透明的效果而且还是正常的,然而第三行只设置的透明度没有设置背景色,就会出现异常的情况。第二行是正常的text控件,没有设置透明度,作为参考。
记录在此,以备忘!大家有什么更好的解决方案,欢迎评论!

0 0
原创粉丝点击