je dois dessiner un PNG (dans un TPicture) sur une toile avec les exigences suivantes:Dessiner un PNG formated TPicture sur une toile sans utiliser GDI +
- Il doit être très rapide (en raison de l'ordinateur cible courir un processeur lent).
- Il ne devrait pas nécessiter de bibliothèques supplémentaires qui augmenteront la taille de l'exe (en raison de la mise à jour automatique du PC cible sur une connexion mobile 2G).
Le code ci-dessous est le travail, mais utilise GDI + et:
- est beaucoup plus lent que le dessin d'un simple bitmap non transparent à l'aide
BitBlt
. Sur un processeur rapide, le temps de tirage passe de 1ms à 16ms. Sur un processeur lent, il passe de 100ms à 900ms. - Augmente la taille de l'exe d'environ 0,5 Mo.
Voici le code GDI +. Il est conçu pour revenir à un BitBlt standard si le:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
ComCtrls, ExtCtrls,
GDIPObj, GDIPAPI;
...
procedure DrawPictureToBitmap(Bitmap: TBitmap; X, Y: Integer; Picture: TPicture);
function PictureToGPBitmap(Picture: TPicture): TGPBitmap;
var
MemStream: TMemoryStream;
begin
MemStream := TMemoryStream.Create;
try
Picture.Graphic.SaveToStream(MemStream);
MemStream.Position := 0;
Result := TGPBitmap.Create(TStreamAdapter.Create(MemStream));
finally
FreeAndNil(MemStream);
end;
end;
var
GDICanvas: TGPGraphics;
GPImage: TGPImage;
begin
GDICanvas := TGPGraphics.Create(Bitmap.Canvas.Handle);
try
GPImage := PictureToGPBitmap(Picture);
try
GDICanvas.DrawImage(GPImage, X, Y);
// Did the draw succeed?
if GDICanvas.GetLastStatus <> Ok then
begin
// No, try a BitBlt!
BitBlt(Bitmap.Canvas.Handle, X, Y, Bitmap.Height, Bitmap.Width, Picture.Bitmap.Canvas.Handle, 0, 0, SRCCOPY);
end;
finally
FreeAndNil(GPImage);
end;
finally
FreeAndNil(GDICanvas);
end;
end;
Update 1
En utilisant la suggestion de David j'ai réussi à se débarrasser de GDI + en utilisant un support intégré PNG de Delphi.
procedure DrawPictureToBitmap(Bitmap: TBitmap; X, Y: Integer; Picture: TPicture);
var
PNG: TPngImage;
MemStream: TMemoryStream;
begin
PNG := TPngImage.Create;
try
MemStream := TMemoryStream.Create;
try
Picture.Graphic.SaveToStream(MemStream);
MemStream.Position := 0;
PNG.LoadFromStream(MemStream);
finally
FreeAndNil(MemStream);
end;
PNG.Draw(Bitmap.Canvas, Rect(X, Y, X + Picture.Width, Y + Picture.Height));
finally
FreeAndNil(PNG);
end;
end;
Malheureusement, le temps de tirage est exactement le même que celui de la méthode GDI +. Y a-t-il un moyen de l'optimiser?
@DavidHeffernan - Bonne idée. Cela permet de se débarrasser de la dépendance GDI +, mais le temps de tirage ne s'améliore pas. Voir ma mise à jour ci-dessus. – norgepaul
Pourquoi ne pas simplement DestinationCanvas.Draw (X, Y, Image1.Picture.Graphic); – bummi