delphi – Alphablend和TransparentBlt
发布时间:2020-12-15 04:17:44 所属栏目:大数据 来源:网络整理
导读:这个问题与我关于SO的 earlier question有关. 我想结合两个alpha层,只应用于源层的特定部分.我试过的一种方法是将SourceConstantAlpha设置为$ff(并让函数使用源图层中的alpha通道). 这种作品 – 尽管速度很慢(我想我可以通过使用ScanLines来加快速度),但这部
这个问题与我关于SO的
earlier question有关.
我想结合两个alpha层,只应用于源层的特定部分.我试过的一种方法是将SourceConstantAlpha设置为$ff(并让函数使用源图层中的alpha通道). 这种作品 – 尽管速度很慢(我想我可以通过使用ScanLines来加快速度),但这部分是因为我无法弄清楚将alpha通道设置为什么.文档表明计算是: st.Red = Src.Red + (1 - Src.Alpha) * Dst.Red 我通过猜测工作尝试了一些不同的值,但我的第一个问题是:我如何计算alpha值? 在阅读了其他几个SO问题后,我遇到了TransparentBlt函数,它可以很好地屏蔽(和快速)但不透明,有没有办法结合 unit MainWnd; interface uses Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,ExtCtrls,ControlsEx; type {------------------------------------------------------------------------------} TfrmMain = class(TForm) PaintBox1: TPaintBox; procedure PaintBox1Paint(Sender: TObject); private { Private declarations } public { Public declarations } end; var frmMain: TfrmMain; implementation {$R *.dfm} {..............................................................................} procedure copyToAlpha(const in_bitmap : TBitmap; const in_transparentColor : TColor; const in_transparency : integer); var x : integer; y : integer; p : integer; begin ASSERT(in_bitmap.PixelFormat = pf32bit); for x := 0 to in_bitmap.Width - 1 do begin for y := 0 to in_bitmap.Height - 1 do begin p := in_bitmap.Canvas.Pixels[x,y]; if TColor(p) <> in_transparentColor then begin in_bitmap.Canvas.Pixels[x,y] := p or (in_transparency shl 24); end else in_bitmap.Canvas.Pixels[x,y] := p or ($ff shl 24); end; end; end; {..............................................................................} procedure alphaBlendTest( const in_target : TCanvas; const in_width : integer; const in_height : integer); const BARSIZE = 30; var bitmap : TBitmap; r : TRect; blendFn : BLENDFUNCTION; ret : Boolean; begin blendFn.BlendOp := AC_SRC_OVER; blendFn.SourceConstantAlpha := $ff; blendFn.BlendFlags := 0; blendFn.alphaFormat := AC_SRC_ALPHA; bitmap := TBitmap.Create; try bitmap.Width := in_width; bitmap.Height := in_height; bitmap.PixelFormat := pf32bit; bitmap.HandleType := bmDIB; bitmap.TransparentColor := clFuchsia; bitmap.Transparent := true; bitmap.Canvas.Brush.Color := clFuchsia; bitmap.Canvas.FillRect(Bounds(0,in_width,in_height)); bitmap.Canvas.Brush.Color := clGreen; r := Bounds( in_width div 2 - (in_width div 3) div 2,(in_width div 3) + 1,BARSIZE + 1); bitmap.Canvas.Rectangle(r); // done drawing //copyToAlpha(bitmap,clFuchsia,1); ret := Windows.TransparentBlt( in_target.Handle,in_height,bitmap.Canvas.Handle,clFuchsia); //blendFn); ASSERT(ret); finally bitmap.Free; end; end; {..............................................................................} procedure TfrmMain.PaintBox1Paint(Sender: TObject); var r: TRect; begin PaintBox1.Canvas.Brush.Color := clBlue; r := Bounds(0,PaintBox1.ClientWidth,PaintBox1.ClientHeight); PaintBox1.Canvas.FillRect(r); PaintBox1.Canvas.Brush.Color := clRed; PaintBox1.Canvas.Ellipse(0,PaintBox1.ClientHeight); alphaBlendTest(PaintBox1.Canvas,PaintBox1.ClientHeight); end; end. 解决方法
技巧:以任何比例混合相同的颜色会产生相同的颜色.
因此,最简单的方法(也许也是最有效的方法)是首先将透明结果绘制到临时位图,然后在目标画布上绘制位图的alphablend. 在绘图期间访问目标画布: procedure TfrmMain.PaintBox1Paint(Sender: TObject); const BarSize = 30; var R: TRect; Bmp: TBitmap; BlendFunc: TBlendFunction; begin with PaintBox1 do begin R := ClientRect; Canvas.Brush.Color := clBlue; Canvas.FillRect(R); Canvas.Brush.Color := clRed; Canvas.Ellipse(R); Bmp := TBitmap.Create; try Bmp.Width := Width; Bmp.Height := Height; BitBlt(Bmp.Canvas.Handle,Width,Height,Canvas.Handle,SRCCOPY); Bmp.Canvas.Brush.Color := clGreen; R := Bounds(Width div 3,Width div 3 + 1,BarSize + 1); Bmp.Canvas.Rectangle(R); BlendFunc.BlendOp := AC_SRC_OVER; BlendFunc.BlendFlags := 0; BlendFunc.SourceConstantAlpha := 80; BlendFunc.AlphaFormat := 0; Windows.AlphaBlend(Canvas.Handle,Bmp.Canvas.Handle,BlendFunc); finally Bmp.Free; end; end; end; 并且在绘图期间无法访问目标画布: procedure GetRemoteBitmap(Bmp: TBitmap; Width,Height: Integer); const BarSize = 30; var R: TRect; begin Bmp.Canvas.Brush.Color := clFuchsia; Bmp.Width := Width; Bmp.Height := Height; Bmp.TransparentColor := clFuchsia; Bmp.Transparent := True; Bmp.Canvas.Brush.Color := clGreen; R := Bounds(Width div 3,BarSize + 1); Bmp.Canvas.Rectangle(R); end; procedure TfrmMain.PaintBox1Paint(Sender: TObject); var R: TRect; Bmp: TBitmap; Tmp: TBitmap; BlendFunc: TBlendFunction; begin with PaintBox1 do begin R := ClientRect; Canvas.Brush.Color := clBlue; Canvas.FillRect(R); Canvas.Brush.Color := clRed; Canvas.Ellipse(R); Bmp := TBitmap.Create; Tmp := TBitmap.Create; try GetRemoteBitmap(Bmp,Height); Tmp.Width := Width; Tmp.Height := Height; BitBlt(Tmp.Canvas.Handle,SRCCOPY); TransparentBlt(Tmp.Canvas.Handle,ColorToRGB(clFuchsia)); BlendFunc.BlendOp := AC_SRC_OVER; BlendFunc.BlendFlags := 0; BlendFunc.SourceConstantAlpha := 80; BlendFunc.AlphaFormat := 0; Windows.AlphaBlend(Canvas.Handle,Tmp.Canvas.Handle,BlendFunc); finally Tmp.Free; Bmp.Free; end; end; end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |