Posted on 2008-09-19 16:17
没画完的画 阅读(2294)
评论(5) 编辑 收藏 引用 所属分类:
VC
图形学中,Alpha指的是除了颜色的三个分量(RGB)外的第四个分量,透明度
一个真彩色的像素由四个分量组成,RGBA
Alpha 的值在 0 到 1 之间,0表示完全透明,1 表示完全覆盖
图像A 和 图像B 组合而成的图像为 C
A: (R_Value_A, G_Value_A, B_Value_A, Alpha_A)
B: (R_Value_B, G_Value_B, B_Value_B, Alpha_B)
混合后的C 颜色为
R_Value_C = R_Value_A * Alpha_A + R_Value_B * Alpha_B
G_Value_C = G_Value_A * Alpha_A + G_Value_B * Alpha_B
B_Value_C = B_Value_A * Alpha_A + B_Value_B * Alpha_B
具体实现代码:
/**
* alpha 值的范围为 0 ~ 255
*/
inline COLORREF AlphaPixel(UINT alpha, COLORREF clr1, COLORREF clr2)
{
double k = (double)alpha / 256.0;
double reverse_k = 1.0 - k;
BYTE r = BYTE( GetRValue(clr2) * k + GetRValue(clr1) * reverse_k );
BYTE g = BYTE( GetGValue(clr2) * k + GetGValue(clr1) * reverse_k );
BYTE b = BYTE( GetBValue(clr2) * k + GetBValue(clr1) * reverse_k );
return RGB(r, g, b);
}
透明度 50%
for(int i = 0; i < size.cx; i++)
{
for ( int j = 0; j < size.cy; j++ )
{
pDC->SetPixel(i, j, AlphaPixel(255 / 2, RGB(255, 255, 255), dc.GetPixel(i, j)) );
}// for j
}// for i
如此算法,如果是1024 * 768 的图,就很慢了,需要想办法优化
饿了,先去吃饭再研究~
吃完饭,继续
windows已经提供了 实现alpha混合的API
BOOL AlphaBlend(
HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
BLENDFUNCTION blendFunction);
前面十个参数不用说了,主要在最后一个参数
typedef struct _BLENDFUNCTION
{
BYTE BlendOp; // BlendOp字段指明了源混合操作,但只支持AC_SRC_OVER,即根据源alpha值把源图像
叠加到目标图像上
// OpenGL的alpha混合还支持其他的方式,如常量颜色源。
BYTE BlendFlags; // 保留字段,必须是 0
BYTE SourceConstantAlpha; //
BYTE AlphaFormat; // 0表示常量alpha值,AC_SRC_ALPHA表示每个像素有各自的alpha通道。
} BLENDFUNCTION;
BLENDFUNCTION结构控制源和目标位图的混合方式
如果AlphaFormat字段为0,源位图中的所有像素使用同样的常量alpha值,即SourceConstantAlpha字段中的值,该值实际上是0和255
,而不是0和1。这里0表示完
全透明,255表示完全不透明。目标像素以255-SourceConstantAlpha值作为alpha值。
如果AlphaFormat字段的值是AC_SRC_ALPHA,源设备表面的每个像素必须有各自的alpha通道。即,必须是32-bpp的物理设备上下文
,或是选中了32-bpp DDB和DIB
段的内存设备上下文。这些情况下,每个源像素有4个8位通道:红、绿、蓝和alpha。每个像素的alpha通道和SourceConstantAlpha
字段一起用于把源和目标混合
起来。实际用于计算的运算式如下:
Tmp.Red = Src.Red * SourceConstantAlpha / 255;
Tmp.Green = Src.Green * SourceConstantAlpha / 255;
Tmp.Blue = Src.Blue * SourceConstantAlpha / 255;
Tmp.Alpha = Src.Alpha * SourceConstantAlpha / 255;
Beta = 255 – Tmp.alpha;
Dst.Red = Tmp.Red + Round((Beta * Dst.Red )/255);
Dst.Green = Tmp.Green + Round((Beta * Dst.Green)/255);
Dst.Blue = Tmp.Blue + Round((Beta * Dst.Blue )/255);
Dst.Alpha = Tmp.Alpha + Round((Beta * Dst.Alpha)/255);
如果AlphaFormat字段的值是AC_SRC_ALPHA 的情况还没搞懂是什么意思