如何在Delphi中使用Alpha透明度绘制透明图形?

9
我想使用带有alpha透明矩形和alpha透明图像的复杂图像。 Mitov的GDI+包装器,但它似乎不支持32位BMP文件,而且会重新缩放它们,文档也很糟糕。BMP比PNG快得多,所以我想使用它们。GDI +的SynGDI包装器,但它似乎非常基本,并且没有为其编写文档。还有这个GDI的技巧:
procedure DrawAlphaAPI(Source: TBitmap; Destination: TCanvas;
  const X, Y: Integer; const Opacity: Byte = 255);
var  BlendFunc: TBlendFunction;
begin
  BlendFunc.BlendOp := AC_SRC_OVER;
  BlendFunc.BlendFlags := 0;
  BlendFunc.SourceConstantAlpha := Opacity;

  if Source.PixelFormat = pf32bit then
    BlendFunc.AlphaFormat := AC_SRC_ALPHA
  else
    BlendFunc.AlphaFormat := 0;

  Windows.AlphaBlend(Destination.Handle, X, Y, Source.Width, Source.Height,
  Source.Canvas.Handle, 0, 0, Source.Width, Source.Height, BlendFunc);
end;

但是当我将Opacity设置为255时,它不能正确地绘制32位图像(在应该完全不透明的地方会有一些半透明的效果)。我不想使用Scanline来使像素透明,因为这样绘制所有透明矩形会太复杂。另外,我认为GDI+在现代计算机上应该更快,我是对的吗?
所以问题是:如何轻松地绘制alpha透明的矩形和位图(不需要大量代码)?
首选Delphi版本:7。我也有2005和XE3,但由于7是速度恶魔,我最希望的是从7开始向上工作的东西。

1
如果您可以使用支持Delphi 2009及以上版本的此包装器,您可以编写如下代码,看起来相当复杂,但您需要知道您可以使用该颜色矩阵修改颜色调整,而我正在加载一个文件以进行Alpha混合(例如,您可以从传递的TBitmap对象创建GPBitmap)。 - TLama
@TLama 谢谢,这个 GDI+ 到目前为止似乎是最好的。其他的都很糟糕。Progdigy 的一个在 (7、2005 或 XE3) 上无法编译,Mitov 的一个在绘制图像后会破坏它们,Synopse 的一个则不完整。 - Tom
1
顺便说一句:我发现这些文章非常有趣。这里是链接。 - Uli Gerhardt
@UliGerhardt 很有趣,确实。谢谢! - Tom
1个回答

14

如果您准备好普通的TBitmap,可以使用任何GDI +实现,只需分配bmp.Canvas.Handle。 编译时出现问题可能是由于文件夹中旧的DirctDraw版本引起的,请将其删除。

implementation

uses GDIPAPI, GDIPOBJ;
{$R *.dfm}

Procedure PrepareBMP(bmp: TBitmap; Width, Height: Integer);
var
  p: Pointer;
begin
  bmp.PixelFormat := pf32Bit;
  bmp.Width := Width;
  bmp.Height := Height;
  bmp.HandleType := bmDIB;
  bmp.ignorepalette := true;
  bmp.alphaformat := afPremultiplied;
  // clear all Scanlines
  p := bmp.ScanLine[Height - 1];
  ZeroMemory(p, Width * Height * 4);
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  bmp: TBitmap;
  G: TGPGRaphics;
  B: TGPSolidBrush;
begin
  bmp := TBitmap.Create;
  try
    PrepareBMP(bmp, 300, 300);
    G := TGPGRaphics.Create(bmp.Canvas.Handle);
    B := TGPSolidBrush.Create(MakeColor(100, 255, 0, 0));
    try
      G.SetSmoothingMode(SmoothingModeHighQuality);
      G.FillEllipse(B, MakeRect(0.0, 0, 300, 300));
      B.SetColor(MakeColor(100, 0, 255, 128));
      G.FillEllipse(B, MakeRect(40.0, 40, 260, 260));
    finally
      B.Free;
      G.Free;
    end;
    // draw overlapping in Form Canvas to display transparency
    Canvas.Draw(0, 0, bmp);
    Canvas.Draw(100, 100, bmp);
  finally
    bmp.Free;
  end;
end;

演示


谢谢你,bummi!我之前不知道bmp.AlphaFormat这个属性,因为在我购买XE3之前,我一直在使用旧版的Delphi,那时候还没有这个属性。但现在,当我设置bmp.AlphaFormat := afDefined;后,我可以正常地加载32位的位图并使用Canvas.Draw()方法绘制它们了! - Tom
我还删除了DirectDraw.pas和Progdidy的GDI编译也很好(至少在XE3中),谢谢! - Tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接