您现在的位置:首页 >> 图形媒体 >> 图形媒体 >> 内容

Delphi中运用Windows的位图Alpha混合技术

时间:2011/9/3 15:01:15 点击:

  核心提示:alpha混合是像素融合算法之一,就是按照'alpha'混合向量的值来混合源像素和目标像素,具体的说就是将源像素和目标像素加权相加的组合(混合)两个图像(源图像和目标图像).源像素的权值通常被称为al...
alpha混合是像素融合算法之一,就是按照"alpha"混合向量的值来混合源像素和目标像素,具体的说就是将源像素和目标像素加权相加的组合(混合)两个图像(源图像和目标图像).源像素的权值通常被称为alpha值,目标像素的权值是(1 alpha),1是最大的颜色值.alpha混合是按颜色通道定义,而不是按位定义的.

2 alpha混合的实现
我们定义alpha为0时表示源像素完全透明,为1时表示完全不透明.假定我们用的是24位色或32位色位图,alpha混合的概念运算式为:
Dst.Red = Src.Red * alpha + (1-alpha) * Dst.Red ;
Dst.Green = Src.Green * alpha + (1-alpha) * Dst.Green;
Dst.Blue = Src.Blue * alpha + (1-alpha) * Dst.Blue ;
Dst.Alpha = Src.Alpha * alpha + (1-alpha) * Dst.Alpha;
根据这个公式我们可以编制alpha混合图像的函数:
// 24位位图的alpha混合. 要求源位图和目标位图大小相等,且像素格式都为24位
procedure AlphaBlend24(BitmapDest, BitmapSrc:TBitmap; Alpha:Byte);
var
  pDest, pSrc : PByteArray;
  X,Y :Integer;
  Beta:Integer;
begin
 Beta := 255 - Alpha;
 for Y := 0 to BitmapDest.Height - 1 do
 begin
  pDest := BitmapDest.ScanLine[Y];
  pSrc := BitmapSrc.ScanLine[Y];
  for X := 0 to BitmapDest.Width - 1 do
  begin
    pDest[0]:= (pSrc[0] * Alpha + pDest[0] * Beta) div 255;
    pDest[1]:= (pSrc[1] * Alpha + pDest[1] * Beta) div 255;
    pDest[2]:= (pSrc[2] * Alpha + pDest[2] * Beta) div 255;
    Inc(Longword(pDest) ,3); // 指向下一个像素
    Inc(Longword(pSrc ) ,3);
  end;
 end;
end;
注意,代码中没有使用浮点数,只是将0到1的alpha值用0到255代替,这是Windows程序的通常做法.以上的代码只实现了24位位图的alpha混合,其它像素类型的alpha混合代码是相似的,所以这里不再给出.

3 ,Windows API的AlphaBlend使用
由于图像的alpha混合技术使用非常广泛,所有图像处理引擎都支持这项操作,如OpenGL和DirectX等.但是这些图像处理引擎都是用来处理复杂图像,而且使用比较复杂,如果我们的程序不是用来处理复杂图像而只需要简单的alpha混合功能,那么使用上述图形引擎就显得没有必要了.实际上在Windows 98和Windows 2000中已经提供了实现alpha混合的API,就是AlphaBlend函数,这个函数是Windows 98和Windows 2000中GDI新加的功能,AlphaBlend函数声明如下:
BOOL AlphaBlend(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
    HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,BLENDFUNCTION blendFunction);
该API函数中使用了一个结构

typedef struct _BLENDFUNCTION
{
  BYTE BlendOp;
  BYTE BlendFlags;
  BYTE SourceConstantAlpha;
  BYTE AlphaFormat;
} BLENDFUNCTION;

AlphaBlend函数的原型看起来和StretchBlt函数非常像,头5个参数指明了目标设备上下文和以逻辑坐标定义的矩形.同样,随后的5个参数指明了源设备上下文和以逻辑坐标定义的源表面的矩形.对源设备上下文也有限制,即源矩形必须在源设备上下文内,源设备上下文不能有剪切和旋转.注意,用到源设备上下文使得AlphaBlend函数不能直接使用DIB(即设备无关位图).
最后一个参数blendFunction是一个BLENDFUNCTION结构.BLENDFUNCTION结构控制源和目标位图的混合方式,它的BlendOp字段指明了源混合操作,但只支持AC_SRC_OVER,即根据源alpha值把源图像叠加到目标图像上.OpenGL的alpha混合还支持其他的方式,如常量颜色源.下一个字段BlendFalgs必须是0,也是为以后的应用保留的.最后一个字段AlphaFormat有两个选择:0表示常量alpha值,AC_SRC_ALPHA表示每个像素有各自的alpha通道.
如果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);

4 程序实例
下面演示AlphaBlend函数的使用,在Delphi 7中新建一工程,在Form1上放置三个Image控件和一个TrackBar控件,再加上一个Label控件和两个RadioButton控件.Image1中调入一个24位位图,Iamge2中调入另外一个24位位图,TrackBar1的Min属性设为0,Max属性设为255,窗体如图1.
图1 窗体示意图

程序的主要代码如下:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Image3.Width := Image1.Width;
  Image3.Height := Image1.Height;
  TrackBar1Change(Self);
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  Label1.Caption := IntToStr(TrackBar1.Position);
  if RadioButton1.Checked then
    AlphaDraw1
  else
    AlphaDraw2;
end;

// 使用AlphaBlend API进行alpha混合
procedure TForm1.AlphaDraw1;
var
 Bmp: TBitmap;
 BF: BLENDFUNCTION;
begin
  Bmp := TBitmap.Create;
  Bmp.Assign(Image1.Picture.Bitmap);
  BF.BlendOp := AC_SRC_OVER;
  BF.BlendFlags := 0;
  BF.SourceConstantAlpha := TrackBar1.Position;
  BF.AlphaFormat := 0;
  Windows.AlphaBlend(Bmp.Canvas.Handle, 0,0,Bmp.Width, Bmp.Height,
  Image2.Picture.Bitmap.Canvas.Handle, 0,0,Bmp.Width, Bmp.Height,BF);
  Image3.Canvas.Draw(0,0,Bmp);
  Bmp.Free;
end;

// 使用自编的AlphaBlend24函数进行alpha混合
procedure TForm1.AlphaDraw2;
var
  Bmp: TBitmap;
begin
  Bmp := TBitmap.Create;
  Bmp.Assign(Image1.Picture.Bitmap);
  AlphaBlend24(Bmp, Image2.Picture.Bitmap, TrackBar1.Position);
  Image3.Canvas.Draw(0,0,Bmp);
  Bmp.Free;
end;

运行时从左到右拖动TrackBar,最下面图像就由第一幅图逐渐变为第二幅图.本程序还演示了自编alpha混合函数的使用,效果与AlphaBlend相同.本示例程序在Delphi 7 和 Windows 2000中文版中运行通过.

作者:网络 来源:转载
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
本类推荐
  • 没有
本类固顶
  • 没有
  • 盒子文章(www.2ccc.com) © 2024 版权所有 All Rights Reserved.
  • 沪ICP备05001939号