在 Delphi 中无法通过 GraphicEx 正确绘制 PNG
Can't get how to draw PNG properly via GraphicEx in Delphi
我对 PNG 格式有点问题。为了读取和显示 PNG 文件,我使用了 Mike Lischke (got it there) 的 GraphicEx
库。在我决定绘制具有透明背景的 PNG 文件之前,一切都很好。
我使用此代码在表单 canvas:
上加载和绘制 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;
我得到的你可以在下面的图片上看到:
在 Internet 上搜索了几个小时后,我发现我应该使用多个 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 文件。
P.S.
位图 属性 透明无法正常工作 - 图片上仍然是黑色背景。
感谢大家给我提意见!
编辑
当我设置 PixelFormat = pf32bit
时,它在视觉上使位图 'broken'。
下图展示了这种效果:
问题是 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中的class)。它完全支持使用 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 成像组件 (WIC) 添加到 Delphi。但在 Delphi 5 中,我自己翻译了 headers,并创建了一个 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;
它也能正确绘制:
GDI+
还有 GDI+。我也不知道 Borland 何时将对 GDI+ 的支持添加到 Delphi。但是在 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;
它也能正确绘制:
但要回答你的问题:你不能。并非没有 re-writing Mike 的 TPNGGraphic
来支持 alpha 通道。
我对 PNG 格式有点问题。为了读取和显示 PNG 文件,我使用了 Mike Lischke (got it there) 的 GraphicEx
库。在我决定绘制具有透明背景的 PNG 文件之前,一切都很好。
我使用此代码在表单 canvas:
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;
我得到的你可以在下面的图片上看到:
在 Internet 上搜索了几个小时后,我发现我应该使用多个 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 文件。
P.S.
位图 属性 透明无法正常工作 - 图片上仍然是黑色背景。
感谢大家给我提意见!
编辑
当我设置 PixelFormat = pf32bit
时,它在视觉上使位图 'broken'。
下图展示了这种效果:
问题是 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中的class)。它完全支持使用 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 成像组件 (WIC) 添加到 Delphi。但在 Delphi 5 中,我自己翻译了 headers,并创建了一个 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;
它也能正确绘制:
GDI+
还有 GDI+。我也不知道 Borland 何时将对 GDI+ 的支持添加到 Delphi。但是在 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;
它也能正确绘制:
但要回答你的问题:你不能。并非没有 re-writing Mike 的 TPNGGraphic
来支持 alpha 通道。