【问题标题】:Delphi: GR32 draw a PNG with alpha onto a TBitmap32 without clearing its contentDelphi:GR32 将带有 alpha 的 PNG 绘制到 TBitmap32 上而不清除其内容
【发布时间】:2023-12-20 20:48:01
【问题描述】:

在解决了其他几个相关问题后,我无法为此提供有效的代码,因此请保留“重复问题”标签。

给定一个具有每像素 Alpha 通道或单色透明度的 PNG 图像,我需要代码将其绘制到已经包含图像的 TBitmap32 上(一些绘图在 PNG 部分之前进行)。所以假设我的 TBitmap32 是 200x200,我在上面画了一些图,然后我想在其当前内容之上插入一个较小的透明 PNG 图像,根据 PNG 的 alpha 通道数据或单色 alpha 透明地插入。

Uses pngimage, GR32;

procedure TForm1.Button1Click(Sender: TObject);
Var b: TBitmap;
    b32: TBitmap32;
    p: TPngImage;
begin
  b   := TBitmap.Create;
  b32 := TBitmap32.Create;
  p   := TPngImage.Create;

  // 50x50 PNG
  p.LoadFromFile('z:\test2.png');

  b.Width    := 200;
  b.Height   := 200;
  b32.Width  := 200;
  b32.Height := 200;
  // some drawing happens on the b32~

  // insert code here to draw the png onto the b32, on top of
  // what's already drawn, and at specific coordinates i.e 10,10


  /////////////////////////////

  b32.DrawTo(b.Canvas.Handle,0,0);
  Canvas.Draw(0,0,b);

  p.Free;
  b32.Free;
  b.Free;
end;

原始PNG:

目前的结果:

【问题讨论】:

  • 那么有什么不符合您的预期?我看到绿色图片很好地融入了黑色背景,因此保持了 PNG alpha 透明度。是黑色背景的问题吗?如果是,您是否在对其进行任何绘图之前用透明颜色填充了整个 bm32 位图。我假设新位图的默认颜色可能是黑色或白色,并且可能完全不透明。
  • 黑色区域应该是透明的,混合在下面的另一个bitmap32上(红色)
  • Nvm it.. 我很愚蠢,最明显和最简单的步骤意外地完成了这项工作:p.Draw(b32.Canvas,Rect(50,100,150,200)); Delphi Seattle 的 TPngImage 版本完美地完成了这项工作:i.imgur.com/yb56ezN.png

标签: delphi png transparent alpha


【解决方案1】:

有两种处理透明 PNG 文件的方法:

  1. 将它们加载到中间 TBitmap32 位图中,然后操作这些 TBitmap32 位图。
  2. 正如您所指出的,直接在目标 Canvas 上使用 TPngImage.Draw(在具有 Delphi XE2 及更高版本的 Vcl.Imaging.pngimage 中实现)。

在透明度方面,第二种方法更可取,因为您可能会发现将 PNG 加载到 TBitmap32 的代码可能无法正常工作。以下是最常使用的错误代码的两个示例:

(1) “LoadPNGintoBitmap32”来自http://graphics32.org/wiki/FAQ/ImageFormatRelated - 它应用了两次透明度,因此 alpha 值不是 0 或 255 的图像看起来与其他软件中的不同(在具有玻璃效果的半透明图像上最为明显)。此代码将首先将 alpha 应用于 RGB,然后设置 alpha,因此当您感到疼痛时,将再次应用 alpha。您可以在此处找到有关此问题的更多信息:Delphi, GR32 + PngObject: converting to Bitmap32 doesn't work as expected .除此之外,它不会正确地将调色板图像的透明度转换为 TBitmap32 的 alpha 层,例如,所有白色像素都变成透明的。

(2) 来自 gr32ex 库的“LoadBitmap32FromPNG”:https://code.google.com/archive/p/gr32ex/ - 与 (1) 相同算法的实现略有不同,并且与 (1) 具有相同的问题。

如果您仍然喜欢使用 TBitmap32,请执行以下步骤:

  1. 确保您的代码正确地将 PNG 转换为 TBitmap32。
  2. 请勿使用带有透明图像的 TBitmap32 直接在 HDC、Canvas 或 TBitmap 上绘制。使用 dmBlend 和 DrawTo 或 BlockTransfer() 在另一个 TBitmap32 上绘图。例如,要在 TBitmap 上透明绘制,请创建中间缓存 TBitmap32:
    1. 将图像从TBitmap复制到缓存TBitmap32;
    2. 使用 DrawTo 或 BlockTransfer() 将透明图像应用到缓存 TBitmap32,避免使用 Canvas 或 HDC 混合两个图像,因为它们会丢失 alpha 层信息;
    3. 将图像从缓存 TBitmap32 复制回您的 TBitmap。

【讨论】:

    最近更新 更多