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;
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
