我正在使用GR32绘制多个半透明PNG图像.
到目前为止,我一直在使用以下方法:
到目前为止,我一直在使用以下方法:
png:= TPNGObject.Create; png.LoadFromFile(...); PaintBox321.Buffer.Canvas.Draw(120,20,png);
但是我想切换到GR32网站(http://graphics32.org/wiki/FAQ/ImageFormatRelated)上提出的方法:
tmp:= TBitmap32.Create; LoadpnGintoBitmap32(tmp,...,foo); tmp.DrawMode:= dmBlend; PaintBox321.Buffer.Draw(Rect(20,20+ tmp.Width,20+tmp.Height),tmp.ClipRect,tmp);
虽然第一种方法完全正常,但第二种方法 – 应该给出相同的结果 – 会导致alpha通道出现非常奇怪的问题,请参阅图像(这也显示了与Paint.NET中“排列”相同的图像的比较 – 背景和图标在编辑层上打开了).该图像描绘了Bitmap32正确加载或绘制.有小费吗?
– 11月22日增加
我发现它不是关于绘图,而是关于将PNG加载到BMP32.从BMP32保存回PNG会生成错误的“白化”(左侧的那个)PNG图像.
解决方法
原因似乎是当加载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 { ... }
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 { ... }
上述解决方案效率低,因为它读取图像两次.但它显示了为什么你的第二种方法产生更透明的图像.
对于灰色:原始代码中还有一个问题:destBitmap.Assign首先使用clWhite32填充背景,然后将图像透明地绘制到其上.然后LoadpnGintoBitmap32来了,并在其上添加了另一层透明度.