4

我有一个我想在 TBitmap32 中加载的 png。

加载位图后,我调用:

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

但是所有白色像素都是透明的。我怎么能只为png图像的透明部分做到这一点?这是我的图像,图像边缘周围的 alpha 透明度以标准方式指示。

在此处输入图像描述

这是实际的图像:

在此处输入图像描述

4

2 回答 2

6

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

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

. . .
由于读取和写入使用中间 TBitmap 对象,因此需要不必要的额外内存来存储位图数据。此外,通过将数据与 TBitmap 格式相互转换,其他信息可能会丢失或处理错误。
. . .
要通过 Graphics32 本地处理 PNG 文件,可以使用第三方库 GR32 PNG 库。该库使用原生 PNG 格式作为中间存储。通过分配一个 TBitmap32 对象,数据被即时编码/解码到 PNG 或从 PNG 解码。使用这个库,还可以访问存储在 PNG 文件中的附加信息。

Graphics32 项目页面


该单元的代码使用示例可以更改如下以满足您的需要:

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组件内的表单中:

在此处输入图像描述

于 2015-08-28T11:07:09.687 回答
3

问题可能是 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:转换为 Bitmap32 无法按预期工作 . 除此之外,它不会正确地将调色板图像的透明度转换为 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/

由于您现在拥有有关此问题的所有信息,因此您可以选择适合您的解决方案。

于 2016-10-29T16:42:05.817 回答