1

我对PNG格式有一点问题。为了读取和显示 PNG 文件,我使用GraphicExMike Lischke 的库(在那儿找到了)。在我决定用透明背景绘制 PNG 文件之前,一切都很好。
我使用此代码在表单的画布上加载和绘制 PNG:

procedure TForm1.aButton1Click(Sender: TObject);
var
  PNGGraph: GraphicEx.TPNGGraphic;
begin
  PNGGraph := GraphicEx.TPNGGraphic.Create;

  PNGGraph.PixelFormat := pf32bit; - added code line

  PNGGraph.LoadFromFile('demo.png');
  Form1.Canvas.Draw(10, 10, PNGGraph);
  PNGGraph.Free;
end;

我得到的你可以在下面的图片中看到:
没有预乘 alpha 的 png

在互联网上搜索了几个小时后,我发现我应该使用多个 alpha 通道。我从这里得到一些代码(Mike Sutton 的回答):Fade in an alpha-blended PNG form in Delphi

procedure PreMultiplyBitmap(Bitmap: TBitmap);
var
  Row, Col: integer;
  p: PRGBQuad;
  PreMult: array[byte, byte] of byte;
begin
  // precalculate all possible values of a*b
  for Row := 0 to 255 do
    for Col := Row to 255 do
    begin
      PreMult[Row, Col] := Row*Col div 255;
      if (Row <> Col) then
        PreMult[Col, Row] := PreMult[Row, Col]; // a*b = b*a
    end;

  for Row := 0 to Bitmap.Height-1 do
  begin
    Col := Bitmap.Width;
    p := Bitmap.ScanLine[Row];
    while (Col > 0) do
    begin
      p.rgbBlue := PreMult[p.rgbReserved, p.rgbBlue];
      p.rgbGreen := PreMult[p.rgbReserved, p.rgbGreen];
      p.rgbRed := PreMult[p.rgbReserved, p.rgbRed];
      inc(p);
      dec(Col);
    end;
  end;
end;

使用这段代码,我得到了一个有点奇怪的结果:
在此处输入图像描述

上面的图片有黑色背景,同时看起来几乎是原始图像。

在下面的图片中,您可以看到原始 PNG 图像:
在此处输入图像描述

所以,我的问题是:如何正确绘制具有透明度且没有黑色背景的 PNG 文件?

我查看了 GraphicEx 的单位,但无法获得有关我的问题的足够信息。不敢相信像GraphicEx这样严肃的图形库不能毫无问题地绘制PNG文件。

PS
位图属性透明无法正常工作 - 图片上仍然有黑色背景。

感谢所有能给我建议的人!

编辑
当我设置PixelFormat = pf32bit时,它会使位图在视觉上“破碎”。
下图展示了这种效果:
位图上的伪影

4

1 回答 1

2

问题是 Mike 的 PNG 图形不支持绘制透明度。

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
    g: TGraphic;
begin
    g := TPNGGraphic.Create;
    g.LoadFromFile('D:\Temp\FolderOpen_48x48_72.png');
    PaintBox1.Canvas.Draw(0, 0, g);
end;

在没有考虑 alpha 通道的情况下出来:

在此处输入图像描述

TPNG对象

对于 Delphi 2005,可以使用 Gustavo Daud 的pngdelphi库(它是后来被 Delphi 吸收的类)。它完全支持带有 alpha 混合的绘图:

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
    g: TGraphic;
begin
//  g := TPNGGraphic.Create;
    g := TPNGObject.Create;
    g.LoadFromFile('D:\Temp\FolderOpen_48x48_72.png');
    PaintBox1.Canvas.Draw(0, 0, g);
end;

它正确绘制:

在此处输入图像描述

Windows 映像组件

我不知道Borland 何时将Windows Imaging Component (WIC) 添加到Delphi。但在 Delphi 5 中,我自己翻译了标题,并创建了一个使用 WIC 执行所有工作的TGraphicTWicGraphic::

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
    g: TGraphic;
begin
//  g := TPNGGraphic.Create;
//  g := TPNGObject.Create;
    g := TWicGraphic.Create;
    g.LoadFromFile('D:\Temp\FolderOpen_48x48_72.png');
    PaintBox1.Canvas.Draw(0, 0, g);
end;

它也正确绘制:

在此处输入图像描述

GDI+

还有 GDI+。我也不知道 Borland 什么时候在 Delphi 中增加了对 GDI+ 的支持。但在 Delphi 5 中,我自己翻译了 GDI+,并创建了一个使用 GDI+ 完成所有工作的TGraphicTGDIPlusGraphic

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
    g: TGraphic;
begin
//  g := TPNGGraphic.Create;
//  g := TPNGObject.Create;
//  g := TWicGraphic.Create;
    g := TGDIPlusGraphic.Create;
    g.LoadFromFile('D:\Temp\FolderOpen_48x48_72.png');
    PaintBox1.Canvas.Draw(0, 0, g);
end;

它也正确绘制:

在此处输入图像描述


但要回答你的问题:你不能。并非没有重写 Mike'sTPNGGraphic以支持 alpha 通道。

于 2016-08-16T15:05:35.010 回答