无法通过Delphi中的GraphicEx正确绘制PNG

时间:2016-07-29 14:30:38

标签: image delphi png graphicex

PNG格式有点问题。为了阅读和显示PNG文件,我使用Mike Lischke的GraphicEx库(got it there)。在我决定使用透明背景绘制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;

我得到的你可以在下面的图片中看到:
png without premultiplied alpha

在互联网上搜索了几个小时后,我发现我应该有多个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;

使用这段代码我得到了一个奇怪的结果:
enter image description here

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

在下面的图片中,您可以看到原始的PNGimage:
enter image description here

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

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

P.S。
位图属性透明无法正常工作 - 黑色背景仍在图片上。

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

修改
当我设置PixelFormat = pf32bit时,它会使位图在视觉上“破碎” 下图说明了这种效果:
Artifacts on a bitmap

1 个答案:

答案 0 :(得分: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通道的情况下出现:

enter image description here

TPNGObject

对于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;

它绘制正确:

enter image description here

Windows Imaging Component

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

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;

它也画得正确:

enter image description here

GDI +

还有GDI +。我也不知道Borland何时向德尔福添加了对GDI +的支持。但在Delphi 5中,我自己翻译了GDI +并创建了一个 TGraphic ,它使用GDI +进行所有工作,TGDIPlusGraphic

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;

它也正确绘制:

enter image description here

但要回答你的问题:你做不到。并非没有重写Mike的TPNGGraphic来支持alpha通道。