Delphi 2006:将PNG运行时分配给TImage会失去alpha透明度

时间:2011-03-21 00:14:48

标签: delphi png delphi-2006 timage alpha-transparency

Delphi 2006的TImage并不完全支持PNG。为了在我的表单上具有alpha透明度的图像,我必须在运行时加载它们。我可以在设计时加载它们但它们不能存活,我认为因为PNG没有保存在DFM文件中。我确信这在最新的Delphi中都是笨拙的,但我现在无法升级。

无论如何,我在运行时加载它们:

Image1.Picture.Assign (PngImageCollection1.Items [0].PNGImage) ;

PNGImageCollection组件包含各种大小的PNG(这些PNG在设计时创建和加载),我将它们分配给FormCreate事件中的相应TImages。

这个工作正常,直到我遇到问题,我试图在表单上使用它之后在其他地方重用其中一个图像。我发现分配TPicture的行为已将其设置为由于Assign而导致的空图像。这发生在例程TPicture.ForceType中,AFAICT检查FGraphic的类型,如果它不是所需类型,它将释放FGraphic并创建所请求类型的新实例。

行。因此,经过一番搔痒,我发现也许我应该这样做:

Image1.Picture.Bitmap.Assign (PngImageCollection1.Items [0].PNGImage) ; 

这就是诀窍,因为Assign没有破坏图像,但现在图像显示半透明位不透明,即:

TImage when assigned with Image1.Picture.Bitmap.Assign

而不是:

TImage when assigned with Image1.Picture.Assign

如何让此图像正确显示Alpha透明位? (和补充问题:是Image1.Picture.Bitmap.Assign正确的方法吗?)。

以下是更详细的代码:

在我遇到“重用”TImage问题的代码中,序列是:
在表单上创建:

LogoImage.Picture.Assign (PngImageCollection1.Items [0].PNGImage) ; 

(PNGIMage是公司徽标,LogoImage1在主窗体上)。

打印报告标题:

procedure PrintLogo (Report : TBaseReport) ;

var
    X1, Y1, LogoHeightMM    : Double ;

begin
with Report do
    begin
    LogoHeightMM  := CalcGraphicHeight (LogoWidthMM, MainForm.LogoImage.Picture.Graphic) ;
    X1            := PageWidth - MarginRight - LogoWidthMM ;
    Y1            := SectionBottom - LogoHeightMM ;
    PrintBitmapRect (X1, Y1, X1 + LogoWidthMM, Y1 + LogoHeightMM, MainForm.LogoImage.Picture.Bitmap) ;
    end ;
end ;

第一次打印徽标的例程被调用时,它会毫无错误地执行,但在调用PrintBitmapRect之后,LogoImage .Picture会被清除。下次调用打印头例程时,对CalcGraphicHeight的调用失败,因为图像的宽度和高度为零。

将Picture.Assign更改为Picture.Bitmap.Assign修复了标题打印例程中的RTE,但是当我将相同的“修复”移植到从PNG分配的其他静态图像(如上面的齿轮)时,我丢失了aplha渠道。

1 个答案:

答案 0 :(得分:5)

您没有展示代码中真正相关的部分:如何重新使用会导致其具有特定类型的图像。

为TImage分配TPngObject时,图像的图形包含png对象。只有当您特别请求位图时,它才会强制其图形为位图类型。例如,这个,

  Bmp.Assign(Image1.Picture.Bitmap);

会强制Image1有一个位图图形,如果它的图形是一个png对象,它将被释放。虽然如此,

  Bmp.Assign(Image1.Picture.Graphic);

不会强制Image1有位图图形,png对象将执行赋值并保留在那里。

Delphi的位图(至少是最新版本)不支持alpha通道,所以你不应该使用Image1.Picture.Bitmap.Assign(..来表示部分透明的图像。


顺便说一句,您可以使用png图像集中的图像作为源,而不是重新使用图像中的图形。