I have a little problem with PNG format. To read and display PNG files I use GraphicEx
library by Mike Lischke (got it there). All was good before I decided to draw PNG file with transparent background.
I use this code to load and draw PNG on form's 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;
What I get you can see on a picture below:
After hours searching in Internet, I found that I should multiple alpha channel. I get some code from here (Mike Sutton's answer): 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;
Using this code I got a little odd result:
The picture above has black background and in the same time looks almost as an original image.
On a picture below you can see an original PNGimage:
So, my question is: how to draw PNG file correctly with transparency and without black background?
I looked into GraphicEx's units, but can't get enough info about my question. Can't believe that such serious graphic library as GraphicEx is not able to draw PNG files without any troubles.
P.S.
Bitmap property Transparent doesn't work properly - black background still on a picture.
Thanks to everyone who can give me advice!
EDIT
When I set PixelFormat = pf32bit
, it makes bitmap 'broken' visually.
Picture below demonstrates this effect:
The problem is that Mike's PNG graphic doesn't support drawing transparency.
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;
Comes out without the alpha channel being taken into account:
For Delphi 2005 use can use Gustavo Daud's pngdelphi library (It is the class that was later absorbed into Delphi). It fully supported drawing with alpha blending:
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;
It draws correctly:
I don't know when Borland added Windows Imaging Component (WIC) to Delphi. But in Delphi 5 i translated the headers myself, and created a TGraphic that uses WIC to perform all the work: 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;
It also paints correctly:
There's also GDI+. I also don't know when Borland added support for GDI+ to Delphi. But in Delphi 5 i translated GDI+ myself and created a TGraphic that uses GDI+ for all the work, 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;
it also draws correctly:
But to answer your question: You cannot. Not without re-writing Mike's TPNGGraphic
to support the alpha channel.