2009-06-06 14 views
15

Je dois charger une image à partir d'un fichier XML. Il n'y a pas d'information dans le fichier XML indiquant si l'image est JPG/GIF/BMP. Après le chargement de l'image, j'ai besoin de le convertir en Bitmap.Charger Jpg/Gif/Bitmap et convertir en Bitmap

Est-ce que quelqu'un a la moindre idée de la façon de convertir des images en Bitmap sans connaître le format de fichier réel? J'utilise Delphi 2007/2009

Merci.

Répondre

13

J'ai trouvé un moyen plus simple! Il charge automatiquement les fichiers JPG/GIF/BMP etc. sans même connaître/vérifier le format de fichier, et le convertit en conséquence. Cela a fonctionné pour moi parfaitement.

Partage ici :)

Uses 
Classes, ExtCtrls, Graphics, axCtrls; 

Procedure TForm1.Button1Click(Sender: TObject); 
Var 
    OleGraphic    : TOleGraphic; 
    fs      : TFileStream; 
    Source     : TImage; 
    BMP      : TBitmap; 
Begin 
    Try 
      OleGraphic := TOleGraphic.Create; {The magic class!} 

      fs := TFileStream.Create('c:\testjpg.dat', fmOpenRead Or fmSharedenyNone); 
      OleGraphic.LoadFromStream(fs); 

      Source := Timage.Create(Nil); 
      Source.Picture.Assign(OleGraphic); 

      BMP := TBitmap.Create; {Converting to Bitmap} 
      bmp.Width := Source.Picture.Width; 
      bmp.Height := source.Picture.Height; 
      bmp.Canvas.Draw(0, 0, source.Picture.Graphic); 

      image1.Picture.Bitmap := bmp; {Show the bitmap on form} 
    Finally 
      fs.Free; 
      OleGraphic.Free; 
      Source.Free; 
      bmp.Free; 
    End; 
End; 
+2

FYI - Juste essayé ceci. Cela a fonctionné pour les JPG mais pas pour les PNG. –

32

Delphi 2009 est livré avec un support intégré pour JPEG, BMP, GIF et PNG.

Pour les versions antérieures de Delphi, vous devrez peut-être trouver des implémentations de tiers pour PNG et GIF, mais dans Delphi 2009 vous suffit d'ajouter les Jpeg, pngimage et GIFImg unités à votre clause uses.

Si le fichier a une extension, vous pouvez utiliser le code suivant, comme indiqué par d'autres TPicture.LoadFromFile examine les extensions enregistrées par les classes héritées pour déterminer quelle image charger.

uses 
    Graphics, Jpeg, pngimage, GIFImg; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Picture: TPicture; 
    Bitmap: TBitmap; 
begin 
    Picture := TPicture.Create; 
    try 
    Picture.LoadFromFile('C:\imagedata.dat'); 
    Bitmap := TBitmap.Create; 
    try 
     Bitmap.Width := Picture.Width; 
     Bitmap.Height := Picture.Height; 
     Bitmap.Canvas.Draw(0, 0, Picture.Graphic); 
     Bitmap.SaveToFile('C:\test.bmp'); 
    finally 
     Bitmap.Free; 
    end; 
    finally 
    Picture.Free; 
    end; 
end; 

Si l'extension de fichier n'est pas connue, une méthode consiste à regarder les premiers octets pour déterminer le type d'image.

procedure DetectImage(const InputFileName: string; BM: TBitmap); 
var 
    FS: TFileStream; 
    FirstBytes: AnsiString; 
    Graphic: TGraphic; 
begin 
    Graphic := nil; 
    FS := TFileStream.Create(InputFileName, fmOpenRead); 
    try 
    SetLength(FirstBytes, 8); 
    FS.Read(FirstBytes[1], 8); 
    if Copy(FirstBytes, 1, 2) = 'BM' then 
    begin 
     Graphic := TBitmap.Create; 
    end else 
    if FirstBytes = #137'PNG'#13#10#26#10 then 
    begin 
     Graphic := TPngImage.Create; 
    end else 
    if Copy(FirstBytes, 1, 3) = 'GIF' then 
    begin 
     Graphic := TGIFImage.Create; 
    end else 
    if Copy(FirstBytes, 1, 2) = #$FF#$D8 then 
    begin 
     Graphic := TJPEGImage.Create; 
    end; 
    if Assigned(Graphic) then 
    begin 
     try 
     FS.Seek(0, soFromBeginning); 
     Graphic.LoadFromStream(FS); 
     BM.Assign(Graphic); 
     except 
     end; 
     Graphic.Free; 
    end; 
    finally 
    FS.Free; 
    end; 
end; 
+0

Est-ce si facile? Merci beaucoup! Oui, les données d'image se trouvent dans la section CDATA du fichier xml. BTW, Delphi 2007 ne prend-il pas en charge Gif? Je n'ai pas besoin de png suppor. –

+0

Jpeg a été autour depuis un certain temps. Je ne suis pas sûr de GIF. J'ai toujours utilisé Jedi dans le passé pour le support GIF. –

9

Vous ne pouvez pas utiliser TPicture.LoadFromFile si vous ne savez pas quel format graphique a, comme cette méthode utilise l'extension de fichier pour déterminer lequel des formats graphiques enregistrés doit être chargé. Il y a une raison pour laquelle il n'y a pas de méthode TPicture.LoadFromStream correspondante.

Une bibliothèque externe qui peut examiner les données et déterminer le format graphique lors de l'exécution serait la meilleure solution. Vous pouvez utiliser le efg page comme point de départ de votre recherche.

Une solution rapide et sale est d'essayer les quelques formats dont vous avez besoin pour gérer jusqu'à réussite:

function TryLoadPicture(const AFileName: string; APicture: TPicture): boolean; 
const 
    GraphicClasses: array[0..3] of TGraphicClass = (
    TBitmap, TJPEGImage, TGIFImage, TPngImage); 
var 
    FileStr, MemStr: TStream; 
    ClassIndex: integer; 
    Graphic: TGraphic; 
begin 
    Assert(APicture <> nil); 
    FileStr := TFileStream.Create('D:\Temp\img.dat', fmOpenRead); 
    try 
    MemStr := TMemoryStream.Create; 
    try 
     MemStr.CopyFrom(FileStr, FileStr.Size); 
     // try various 
     for ClassIndex := Low(GraphicClasses) to High(GraphicClasses) do begin 
     Graphic := GraphicClasses[ClassIndex].Create; 
     try 
      try 
      MemStr.Seek(0, soFromBeginning); 
      Graphic.LoadFromStream(MemStr); 
      APicture.Assign(Graphic); 
      Result := TRUE; 
      exit; 
      except 
      end; 
     finally 
      Graphic.Free; 
     end; 
     end; 
    finally 
     MemStr.Free; 
    end; 
    finally 
    FileStr.Free; 
    end; 
    Result := FALSE; 
end; 

Edit:

Le GraphicEx library a un exemple convertir qui utilise

GraphicClass := FileFormatList.GraphicFromContent(...); 

pour déterminer le format graphique. Cela semble très similaire à la façon de faire VB6 que vous mentionnez. Peut-être que vous pouvez utiliser cette bibliothèque pour votre usage.

+0

Merci, à la fois pour votre solution et de clarifier la réponse ci-dessus. Votre code semble intéressant, mais comme vous l'avez mentionné, il s'agit en fait d'une approche rapide et sale. Je cherche quelque chose comme la fonction VB 6 LoadPicture qui fonctionne pour l'image prise en charge quelle que soit l'extension du nom de fichier. –

5

Je n'ai pas Delphi 2007 ou 2009 pour voir si cela va fonctionner dans l'une de ces versions. Toutefois, dans XE2, il existe une autre classe Vcl.Graphics appelée TWICImage qui gère les images prises en charge par le composant Microsoft Imaging, y compris BMP, GIF, ICO, JPEG, PNG, TIF et Windows Media Photo. Il est capable de détecter le type d'image d'un flux.En supposant que vous avez un TImage sur le formulaire appelé Image1:

procedure LoadImageFromStream(Stream: TStream; Image: TImage); 
var 
    wic: TWICImage; 
begin 
    Stream.Position := 0; 
    wic := TWICImage.Create; 
    try 
    wic.LoadFromStream(Stream); 
    Image.Picture.Assign(wic); 
    finally 
    wic.Free; 
    end; 
end; 

procedure RenderImage(const Filename: string); 
var 
    fs: TFileStream; 
begin 
    fs := TFileStream.Create(Filename, fmOpenRead); 
    try 
    LoadImageFromStream(fs, Image1); 
    finally 
    fs.Free; 
    end; 
end; 

Il fonctionne sans ajouter PNGImage, GIFImg ou JPEG à votre déclaration uses.

Les autres réponses montrent comment convertir le TImage en BMP, donc je ne l'inclut pas ici. Je montre juste une autre façon de charger différents types graphiques dans un TImage sans savoir au préalable le type d'image, ou l'extension de fichier ...

+0

Fonctionne parfaitement dans C++ Builder XE5 –

+0

'TPicture :: Assign' copie-t-il les données d'image dans l'image? (Je me méfie d'un pointeur dangling après 'wic.Free') –

+1

@MattMcNabb - Oui, il le copie (http://docwiki.embarcadero.com/Libraries/XE5/fr/Vcl.Graphics.TPicture.Assign) , qui est vérifiée en traçant à travers le code VCL. –