{Information header chunk} TChunkIHDR = class(TChunk) protected // *** ajouté //private // *** mis en commentaire {Current image} ImageHandle: HBitmap; ImageDC: HDC; ImagePalette: HPalette; {Output windows bitmap} HasPalette: Boolean; BitmapInfo: TMaxBitmapInfo; {Stores the image bytes} {$IFDEF Store16bits}ExtraImageData: Pointer;{$ENDIF} ImageData: pointer; ImageAlpha: Pointer; {Contains all the ihdr data} IHDRData: TIHDRData; // protected // *** mis en commentaire BytesPerRow: Integer;
unit UPng2Bmp32; interface uses Windows, SysUtils, Graphics, PngImage; procedure PartialTransPng2Bmp32(aPNGImage: TPNGImage; aBMP: TBitmap); implementation type // l'astuce qui permet d'avoir accès à la section Protected // de la classe TChunckIHDR THackChunkIHDR = class(TChunkIHDR); {Copy a PNG to a BMP32 using partial transparency Original code grabed from PngImage.pas: procedure TPngImage.DrawPartialTrans(DC: HDC; Rect: TRect); adapted by Cirec} procedure PartialTransPng2Bmp32(aPNGImage: TPNGImage; aBMP: TBitmap); type {Access to pixels} TPixelLine = Array[Word] of TRGBQuad; pPixelLine = ^TPixelLine; var Header: THackChunkIHDR; {Transparency/palette chunks} TransparencyChunk: TChunktRNS; PaletteChunk: TChunkPLTE; PaletteIndex: Byte; CurBit: Integer; Data: PByte; {Buffer bitmap modification} BytesPerRowDest, BytesPerRowSrc, BytesPerRowAlpha: Integer; ImageSource, ImageSourceOrg, AlphaSource : pByteArray; ImageData : pPixelLine; i, j, i2, j2 : Integer; {For bitmap stretching} W, H : Cardinal; Stretch : Boolean; FactorX, FactorY: Double; begin if not Assigned(aBMP) then Exit; aBMP.PixelFormat := pf32bit; W := aBMP.Width; H := aBMP.Height; Header := THackChunkIHDR(aPNGImage.Header); {Fast access to header} Stretch := (W <> Header.Width) or (H <> Header.Height); if Stretch then FactorX := W / Header.Width else FactorX := 1; if Stretch then FactorY := H / Header.Height else FactorY := 1; {Obtain number of bytes for each row} BytesPerRowAlpha := Header.Width; BytesPerRowDest := (((32 * W) + 31) and not 31) div 8; {Number of bytes for each image row in destination} BytesPerRowSrc := (((Header.BitmapInfo.bmiHeader.biBitCount * Header.Width) + 31) and not 31) div 8; {Number of bytes for each image row in source} {Obtains image pointers} ImageData := aBMP.ScanLine[0]; AlphaSource := Header.ImageAlpha; Longint(ImageSource) := Longint(Header.ImageData) + Header.BytesPerRow * Longint(Header.Height - 1); ImageSourceOrg := ImageSource; case Header.BitmapInfo.bmiHeader.biBitCount of {R, G, B images} 24: FOR j := 1 TO H DO begin {Process all the pixels in this line} FOR i := 0 TO W - 1 DO begin if Stretch then i2 := trunc(i / FactorX) else i2 := i; pRGBTriple(@ImageData[i])^ := pRGBTriple(@ImageSource[i2 * 3])^; ImageData[i].rgbReserved := AlphaSource[i2]; end; {Move pointers} Dec(Longint(ImageData), BytesPerRowDest); if Stretch then j2 := trunc(j / FactorY) else j2 := j; Longint(ImageSource) := Longint(ImageSourceOrg) - BytesPerRowSrc * j2; Longint(AlphaSource) := Longint(Header.ImageAlpha) + BytesPerRowAlpha * j2; end; {Palette images with 1 byte for each pixel} 1,4,8: if Header.ColorType = COLOR_GRAYSCALEALPHA then FOR j := 1 TO H DO begin {Process all the pixels in this line} FOR i := 0 TO W - 1 DO with ImageData[i], Header.BitmapInfo do begin if Stretch then i2 := trunc(i / FactorX) else i2 := i; rgbRed := ImageSource[i2]; rgbGreen := ImageSource[i2]; rgbBlue := ImageSource[i2]; rgbReserved := AlphaSource[i2]; end; {Move pointers} Longint(ImageData) := Longint(ImageData) - BytesPerRowDest; if Stretch then j2 := trunc(j / FactorY) else j2 := j; Longint(ImageSource) := Longint(ImageSourceOrg) - BytesPerRowSrc * j2; Longint(AlphaSource) := Longint(Header.ImageAlpha) + BytesPerRowAlpha * j2; end else {Palette images} begin//****************** {Obtain pointer to the transparency chunk} TransparencyChunk := TChunktRNS(aPNGImage.Chunks.ItemFromClass(TChunktRNS)); PaletteChunk := TChunkPLTE(aPNGImage.Chunks.ItemFromClass(TChunkPLTE)); FOR j := 1 TO H DO begin {Process all the pixels in this line} i := 0; repeat CurBit := 0; if Stretch then i2 := trunc(i / FactorX) else i2 := i; Data := @ImageSource[i2]; repeat {Obtains the palette index} case Header.BitDepth of 1: PaletteIndex := (Data^ shr (7-(I Mod 8))) and 1; 2,4: PaletteIndex := (Data^ shr ((1-(I Mod 2))*4)) and $0F; else PaletteIndex := Data^; end; {Updates the image with the new pixel} with ImageData[i] do begin rgbReserved := TransparencyChunk.PaletteValues[PaletteIndex]; rgbRed := PaletteChunk.Item[PaletteIndex].rgbRed; rgbGreen := PaletteChunk.Item[PaletteIndex].rgbGreen; rgbBlue := PaletteChunk.Item[PaletteIndex].rgbBlue; end; {Move to next data} inc(i); inc(CurBit, Header.BitmapInfo.bmiHeader.biBitCount); until CurBit >= 8; until i >= Integer(W); {Move pointers ********} Longint(ImageData) := Longint(ImageData) - BytesPerRowDest; if Stretch then j2 := trunc(j / FactorY) else j2 := j; Longint(ImageSource) := Longint(ImageSourceOrg) - BytesPerRowSrc * j2; end end {Palette images **********} end {case Header.BitmapInfo.bmiHeader.biBitCount}; end; end.
... var Form1: TForm1; aPng: TPngImage; implementation {$R *.dfm} uses UPng2Bmp32; procedure TForm1.FormCreate(Sender: TObject); begin aPng := TPngImage.Create; aPng.LoadFromFile('Output_0001.png'); Image1.Picture.Assign(aPng); end; procedure TForm1.FormDestroy(Sender: TObject); begin aPng.Free; end; procedure TForm1.Button1Click(Sender: TObject); var aBMP: TBitmap; begin aBMP := TBitmap.Create; try aBMP.Width := aPNG.Width; // aPNG.Width div 2; aBMP.Height := aPNG.Height; // aPNG.Height div 2; aBMP.PixelFormat := pf32bit; if aPng.TransparencyMode = ptmPartial then PartialTransPng2Bmp32(aPNG, aBMP); aBMP.SaveToFile('Png2BMP32.bmp'); aBMP.AlphaFormat := afPremultiplied; Image2.Picture.Assign(aBMP); finally aBMP.Free; end; end; end.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionunit UBmp32ToPng; interface uses Windows, SysUtils, Graphics, PngImage; function Bmp32ToPng(SrcBmp: TBitmap): TPngImage; implementation function Bmp32ToPng(SrcBmp: TBitmap): TPngImage; var X, Y : Integer; SrcPixLine, DestPixLine : Pointer; PSrcPixLine : PRGBQuad absolute SrcPixLine; PDestPixLine : PRGBTriple absolute DestPixLine; IsPremultiplied : Boolean; begin if not assigned(SrcBmp) or (SrcBmp.PixelFormat <> pf32Bit) or (SrcBmp.Empty) or ((SrcBmp.Width <= 0) or (SrcBmp.Height <= 0)) then raise EInvalidGraphicOperation.Create('Bitmap invalide. Impossible à convertir') ; Result := TPNGImage.CreateBlank(COLOR_RGBALPHA, 8, SrcBmp.Width, SrcBmp.Height); with Result do try IsPremultiplied := SrcBmp.AlphaFormat = afPremultiplied; if IsPremultiplied then SrcBmp.AlphaFormat := afIgnored; // on sélectionne tous les filtres pour une meilleur compression Filters := [pfNone, pfSub, pfUp, pfAverage, pfPaeth]; for Y := 0 to SrcBmp.Height - 1 do begin SrcPixLine := SrcBmp.ScanLine[Y]; DestPixLine := Scanline[Y]; for X := 0 to SrcBmp.Width - 1 do begin PDestPixLine^ := PRGBTriple(PSrcPixLine)^; AlphaScanline[Y]^[X] := PSrcPixLine^.rgbReserved; Inc(PSrcPixLine); Inc(PDestPixLine); end; end; finally if IsPremultiplied then SrcBmp.AlphaFormat := afPremultiplied; end; end; end.
with Bmp32ToPng(aBMP2) do try SaveToFile('Cirec.png'); finally Free; end;
var aNewPng: TPNGImage; begin aNewPng := Bmp32ToPng(aBMP2); if Assigned(aNewPng) then try aNewPng.SaveToFile('Cirec.png'); finally aNewPng.Free; end; end;
20 mai 2014 à 13:31
Effectivement le fichier est un PNG8 mais je ne sais pas comment je peux le traiter sous Delphi XE2.
20 mai 2014 à 14:13
"le fichier png fourni en exemple est bien disponible en téléchargement"
1°) C'est vrai, avec Chrome et IE.
Mais pas sous Firefox 28.0 avec Adblock...
2°) Mais là n'est pas vraiment la question, n'est-il pas ?
Et là, je cède la place au spécialiste ;-)