透明PNG到TBitmap32

Transparent Png to TBitmap32

我有一个 png,我想将其加载到 TBitmap32 中。

加载位图后调用:

Bitmap.DrawMode   := dmTransparent;
Bitmap.OuterColor := Bitmap.PixelS[0,0];

但是所有的白色像素都是透明的。我怎样才能只对 png 图像的透明部分执行此操作?这是我的图像,图像边缘周围的 alpha 透明度以标准方式指示。

这是实际图像:

似乎 TBitmap32 在加载 PNG 图像时可能会丢失 alpha 信息。

您可以考虑使用 GR32PNG library 文档摘录如下:

. . .
since reading and writing utilizes an intermediate TBitmap object, unnecessary additional memory is required to store the bitmap data. Also by converting data to and from the TBitmap format additional information might get lost or handled wrong.
. . .
To handle PNG files natively by Graphics32 the thirdparty library GR32 PNG Library can be used. This library use the native PNG format as intermediate storage. By assigning a TBitmap32 object the data is encoded/decoded to/from PNG on the fly. Using this library it is also possible to access additional information, which is stored in the PNG file.

Graphics32 project page


本机的代码使用示例可根据您的需要更改如下:

var
  AlphaChannelUsed: Boolean;
begin
  LoadBitmap32FromPNG(Bitmap, <your path to the PNG image>, AlphaChannelUsed);

  if AlphaChannelUsed then
    Bitmap.DrawMode := dmBlend
  else
    Bitmap.DrawMode := dmOpaque;
end;

其中 Bitmap 是一个 TBitmap32 对象。


结果图像以 TImage32 组件内的表单加载:

问题可能是 PNG 错误地转换为 TBitmap32,在传输过程中丢失了透明度信息。这是带有调色板的 PNG 图像的常见情况。否则,您将不必使用“Bitmap.DrawMode := dmTransparent”和“OuterColor”。如果来自 PNG 的透明信息已正确传输到 TBitmpa32,则 DrawMode := dmBlend 将起作用,而无需设置 OuterColor。

最重要的是你是如何将 PNG 加载到 TBitmap32 中的。来自 Vcl.Imaging.pngimage 单元的 TPngImage(在 Delphi XE2 及更高版本中实现)可以在位图上透明绘制,保留位图上的内容,使用 PNG alpha 层组合颜色等,但它不允许轻松地将各种格式的 PNG 透明度(包括调色板)转换为 TBitmap32 每个像素的 alpha 组件。一旦 TPngImage 绘制了图像,您将获得每个像素的组合 RGB,但 alpha 分量不会传输到目标位图。

有可用的帮助例程尝试将 PNG 加载到 TBitmap32 中,但它们有缺点:

(1) 来自 http://graphics32.org/wiki/FAQ/ImageFormatRelated 的“LoadPNGintoBitmap32” - 它应用了两次透明度,因此 alpha 值不是 0 或 255 的图像看起来与在其他软件中不同(在具有玻璃效果的半透明图像上最明显)。此代码将首先将 alpha 应用于 RGB,然后将 alpha 设置为单独的层,因此当您绘制时,将再次应用 alpha。您可以在此处找到有关此问题的更多信息:Delphi, GR32 + PngObject: converting to Bitmap32 doesn't work as expected .除此之外,它不能正确地将调色板图像的透明度转换为 TBitmap32 的 alpha 层。他们为输出位图(渲染为 RGB)的特定颜色的像素手动设置 alpha 透明度,而不是在渲染为 RGB 之前这样做,因此当所有白色像素都是透明时,实际透明度会像示例图像一样丢失。

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

所以,解决方案是:

  1. 不要使用TBitmap32;使用 Vcl.Imaging.pngimage.TPngImage 直接在目标位图(屏幕等)上绘制 – 这是正确处理各种 PNG 格式的最兼容方式。
  2. 使用辅助路由将透明度信息从 Vcl.Imaging.pngimage.TPngImage 传输到 TBitmap32.
  3. 使用 GR32 PNG 库 https://sourceforge.net/projects/gr32pnglibrary/

既然你现在已经掌握了关于这个问题的所有信息,你可以选择适合你的解决方案。