> this works fine for me...
Ooh sorry - this version has a bug and edit lines are brocken!
Attached you'll find the corrected version and a transparent PNG example ... ;-)
//******************************************************************* // // UNIT: G r 3 2 _ P N G 15.Jan.2005, 19. March 2010 // // PNG Graphic Unit for graphics32 library v1.7.x and higher // to load and save PNG images (Portable Network Graphics) // Tested with graphics32 v1.9.0 2010-03-08 // // needs TPNGImage component from Gustavo Daud (✉uol.com.br) // http://pngdelphi.sourceforge.net/ // // Tested with: graphics32 v1.9.0 2010-03-08 // PNGImage v1.564 2006-07-25. // // FAQ: // Q: Is there a PNG library for GR32 which supports loading and saving // an image and its alpha channel at the same time? // // A: Yes, you need TPNGImage component from Gustavo Daud // and this unit to load and save PNG images. // // LoadPNGintoBitmap32 code taken from // http://graphics32.org/wiki/pub/page/FAQ/ImageFormatRelated // // note: if you use standard picture file dialogs of type TOpenPictureDialog // or TSavePictureDialog to load or save PNG pictures, you have to add // string "Portable Network Graphics (*.png)" and "*.png" // to filter property ! // // --- functions and procedures --- // // LoadPNGintoBitmap32 load PNG image file into Bitmap32 // SaveBitmap32ToPNG save Bitmap32 to PNG image file // // Bitmap32ToPNG convert Bitmap32 to PNG object // //******************************************************************* {$I comp_opt.inc}
unit Gr32_PNG;
INTERFACE
uses SysUtils, Classes, Graphics, GR32, PNGImage;
function LoadPNGintoBitmap32 (destBitmap: TBitmap32; srcStream: TStream; out transparent: Boolean): boolean; overload;
function LoadPNGintoBitmap32 (destBitmap: TBitmap32; filename: String; out transparent: Boolean): boolean; overload;
function SaveBitmap32ToPNG (sourceBitmap: TBitmap32; transparent: Boolean; bgColor32: TColor32; filename: String; compressionLevel: TCompressionLevel = 9;
function Bitmap32ToPNG (sourceBitmap: TBitmap32; paletted, transparent: Boolean; bgColor: TColor; compressionLevel: TCompressionLevel = 9; interlaceMethod: TInterlaceMethod = imNone): tPNGObject;
IMPLEMENTATION
//********************************************************* // load PNG image from source stream // input: destBitmap: TBitmap32; destination bitmap // srcStream: TStream; source stream // output: transparent: boolean; =true: alpha channel used // return: boolean; =true: png image file loaded // destBitmap: TBitmap32; destination bitmap data //--------------------------------------------------------- function LoadPNGintoBitmap32 (destBitmap: TBitmap32; srcStream: TStream; out transparent: Boolean): boolean; var PNGObject: TPNGObject; TransparentColor: TColor32; PixelPtr: PColor32; AlphaPtr: PByte; X, Y: Integer; begin PNGObject := nil; try result := false; // if two images with same size are loaded and 2nd has transparent pixel // the color value are not cleared -> this is a BUG destBitmap.Clear($FF000000); // bug correction! PNGObject := TPngObject.Create; PNGObject.LoadFromStream(srcStream);
destBitmap.Assign(PNGObject); // destBitmap.ResetAlpha; // bug correction!
case PNGObject.TransparencyMode of ptmPartial: begin if (PNGObject.Header.ColorType = COLOR_GRAYSCALEALPHA) or (PNGObject.Header.ColorType = COLOR_RGBALPHA) then begin PixelPtr := PColor32(@destBitmap.Bits[0]); for Y := 0 to destBitmap.Height - 1 do begin AlphaPtr := PByte(PNGObject.AlphaScanline[Y]); for X := 0 to destBitmap.Width - 1 do begin
end; transparent := True; end; end; ptmBit: begin TransparentColor := Color32(PNGObject.TransparentColor); PixelPtr := PColor32(@destBitmap.Bits[0]); for X := 0 to (destBitmap.Height - 1) * (destBitmap.Width - 1) do begin if PixelPtr^ = TransparentColor then PixelPtr^ := PixelPtr^ and $00FFFFFF; Inc(PixelPtr); end; transparent := True; end; ptmNone: transparent := False; end; result := true; finally if Assigned(PNGObject) then PNGObject.Free; end; end; //********************************************************* // load PNG image file into Bitmap32 // input: destBitmap: TBitmap32; destination bitmap // filename: String; name of PNG image file // output: transparent: boolean; =true: alpha channel used // return: boolean; =true: png image file loaded //--------------------------------------------------------- function LoadPNGintoBitmap32 (destBitmap: TBitmap32; filename: String; out transparent: boolean): boolean; var FileStream: TFileStream; begin result := false; try FileStream := TFileStream.Create(filename, fmOpenRead); try result := LoadPNGintoBitmap32(destBitmap, FileStream, transparent); finally FileStream.Free; end; except end; end;
//********************************************************* // convert Bitmap32 to PNG image // input: sourceBitmap source bitmap 32 bit // paletted =true: PixelFormat is pf8bit // transparent =true: transparent pixels // bgColor background color // compressionLevel compression level, range 0..9, default = 9 // interlaceMethod interlaced method, use imNone or imAdam7 // return: tPNGObject PNG image object //--------------------------------------------------------- function Bitmap32ToPNG (sourceBitmap: TBitmap32; paletted, transparent: Boolean; bgColor: TColor; compressionLevel: TCompressionLevel = 9; interlaceMethod: TInterlaceMethod = imNone): tPNGObject; var bm: TBitmap; png: TPngObject; TRNS: TCHUNKtRNS; p: pngImage.PByteArray; x, y: Integer; begin Result := nil; png := TPngObject.Create; try bm := TBitmap.Create; try bm.Assign (sourceBitmap); // convert data into bitmap // force paletted on TBitmap, transparent for the web must be 8bit if paletted then bm.PixelFormat := pf8bit; png.interlaceMethod := interlaceMethod; png.compressionLevel := compressionLevel; png.Assign(bm); // convert bitmap into PNG finally FreeAndNil(bm); end; if transparent then begin if png.Header.ColorType in [COLOR_PALETTE] then begin if (png.Chunks.ItemFromClass(TChunktRNS) = nil) then png.CreateAlpha; TRNS := png.Chunks.ItemFromClass(TChunktRNS) as TChunktRNS; if Assigned(TRNS) then TRNS.TransparentColor := bgColor; end;
begin for y := 0 to png.Header.Height - 1 do begin p := png.AlphaScanline[y]; for x := 0 to png.Header.Width - 1
end; end; end; Result := png; except png.Free; end; end;
//********************************************************* // save Bitmap32 to PNG image file // input: srcBitmap source bitmap // transparent =true: transparent pixels // bgColor32 background color 32 bit // compressionLevel compression level, range 0..9, default = 9 // interlaceMethod interlaced method, use imNone or imAdam7 // return: boolean =true: bitmap saved as PNG image file //--------------------------------------------------------- function SaveBitmap32ToPNG (sourceBitmap: TBitmap32; transparent: Boolean; bgColor32: TColor32; filename: String; compressionLevel: TCompressionLevel = 9;
var png: tPNGObject; begin result := false; try png := Bitmap32ToPNG (sourceBitmap, false, transparent, WinColor(bgColor32), compressionLevel, interlaceMethod); try png.SaveToFile (filename); result := true; finally png.Free; end; except end; end; //--------------------------------------------------------- // file stream variant to save bitmap32 as PNG picture file //--------------------------------------------------------- (* function xSaveBitmap32ToPNG (sourceBitmap: TBitmap32; transparent: Boolean; bgColor32: TColor32; filename: String; compressionLevel: TCompressionLevel = 9;
var png: tPNGObject; FileStream: TFileStream; begin result := false; try FileStream := TFileStream.Create(filename, fmCreate); try
try png.SaveToStream (FileStream); result := true; finally png.Free; end; finally FileStream.Free; end; except end; end; *)
//********************************************************* // code example of loading and saving a PNG image file //--------------------------------------------------------- procedure PNGExample; var transparent: boolean; myBitmap: tBitmap32; begin myBitmap := TBitmap32.Create; transparent := true; if LoadPNGintoBitmap32 (MyBitmap, 'example1.png', transparent) then begin if transparent then // add anything else that should be on transparent PNG image... MyBitmap.DrawMode := dmBlend else MyBitmap.DrawMode := dmOpaque;
SaveBitmap32ToPNG (myBitmap, transparent, clBlack, 'savetest.png', 5); end; myBitmap.Free; end;
begin // PNGExample; // delete comment to test loading and saving PNG image end.
Message source