Delphi,GR32 + PngObject:转换为Bitmap32无法正常工作

mig*_*jek 5 delphi png transparency graphics32

我正在使用GR32绘制多个半透明的PNG图像.到目前为止,我一直在使用以下方法:

  png:= TPNGObject.Create;
  png.LoadFromFile(...);
  PaintBox321.Buffer.Canvas.Draw(120, 20, png);
Run Code Online (Sandbox Code Playgroud)

但我想切换到GR32网站上提出的方法(http://graphics32.org/wiki/FAQ/ImageFormatRelated):

  tmp:= TBitmap32.Create;
  LoadPNGintoBitmap32(tmp, ..., foo);
  tmp.DrawMode:= dmBlend;
  PaintBox321.Buffer.Draw(Rect(20, 20, 20+ tmp.Width, 20+tmp.Height),
   tmp.ClipRect, tmp);
Run Code Online (Sandbox Code Playgroud)

虽然第一种方法完全正常,但第二种方法 - 应该给出相同的结果 - 会导致alpha通道出现非常奇怪的问题,请参阅图像(其中还显示了与Paint.NET中"排列"相同的图像的比较 - 背景和图标在编辑层上打开了).该图像描绘了Bitmap32正确加载或绘制.有小费吗?

TBitmap32 alpha通道出现问题

- 11月22日增加

我发现它不是关于绘图,而是关于将PNG加载到BMP32.从BMP32保存回PNG会生成错误的"白化"(左侧的那个)PNG图像.

Hei*_*cht 9

原因似乎是在加载时将透明度应用于图像两次LoadPNGintoBitmap32,使其看起来更透明和灰色(稍后会详细介绍).

首先是透明度:

这是原始代码LoadPNGintoBitmap32,关键部分标有注释:

 PNGObject := TPngObject.Create;
 PNGObject.LoadFromStream(srcStream);

 destBitmap.Assign(PNGObject);  // <--- paint to destBitmap's canvas with transparency (!)
 destBitmap.ResetAlpha;         

 case PNGObject.TransparencyMode of  // <--- the following code sets the transparency again for the TBitmap32
 { ... }
Run Code Online (Sandbox Code Playgroud)

destBitmap.Assign内部做一样的,你在你以前的方法:它让我们的PNG图像绘制自己的画布.此操作遵循PNG的alpha通道.但这不是必需的,因为alpha通道TBitmap32在第二步中被指定为像素!

现在更改代码如下,关键部分再次标记为注释:

 PNGObject := TPngObject.Create;
 PNGObject.LoadFromStream(srcStream);

 PNGObject.RemoveTransparency;  // <--- paint PNG without any transparency...
 destBitmap.Assign(PNGObject);  // <--- ...here
 destBitmap.ResetAlpha;

 srcStream.Position:=0;
 PNGObject.LoadFromStream(srcStream); // <--- read the image again to get the alpha channel back

 case PNGObject.TransparencyMode of   // <--- this is ok now, the alpha channel now only exists in the TBitmap32
 { ... }
Run Code Online (Sandbox Code Playgroud)

上述解决方案效率低,因为它读取图像两次.但它说明了为什么你的第二种方法产生更透明的图像.

而对于灰色:原始代码还有一个问题:destBitmap.Assign首先填充背景clWhite32,然后将图像透明地绘制到它上面.然后LoadPNGintoBitmap32又来了,并在其上添加了另一层透明度.