2009-06-06 24 views
15

Tengo que cargar una imagen desde un archivo XML. No hay información en el archivo XML sobre si la imagen es JPG/GIF/BMP. Después de cargar la imagen, necesito convertirla a Bitmap.Cargar Jpg/Gif/Mapa de bits y convertir a mapa de bits

¿Alguien tiene alguna pista sobre cómo convertir imágenes a Bitmap sin conocer el formato de archivo real? Estoy usando Delphi 2007/2009

Gracias.

Respuesta

13

¡He encontrado una manera más simple! Carga archivos JPG/GIF/BMP, etc. sin siquiera saber/verificar el formato del archivo, y convertir eso en consecuencia. Me funcionó a la perfección.

compartir aquí :)

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 - Acabo de probar esto. Funcionó para JPG pero no para PNG. –

32

Delphi 2009 viene con soporte incorporado para JPEG, BMP, GIF y PNG.

Para versiones anteriores de Delphi que pueda necesitar para encontrar las implementaciones de terceros para PNG y GIF, pero en Delphi 2009 sólo tiene que añadir las unidades Jpeg, pngimage y GIFImg a su cláusula de usos.

Si el archivo tiene una extensión, puede usar el siguiente código, como notaron otros, el TPicture.LoadFromFile examina las extensiones registradas por las clases heredadas para determinar qué imagen cargar.

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 la extensión del archivo no se conoce, un método es mirar los primeros bytes para determinar el tipo de imagen.

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

¿Es eso tan fácil? Muchas gracias! Sí, los datos de la imagen están en la sección CDATA en el archivo xml. Por cierto, ¿Delphi 2007 no es compatible con Gif? No necesito png suppor. –

+0

Jpeg ha estado por un tiempo. No estoy seguro acerca de GIF. Siempre usé Jedi en el pasado para el soporte de GIF. –

9

No puede utilizar TPicture.LoadFromFile si no saber qué formato tiene la gráfica, ya que este método utiliza la extensión de archivo para determinar cuál de los formatos gráficos registrados necesita ser cargado. Hay una razón por la que no hay un método TPicture.LoadFromStream que coincida.

Una biblioteca externa que pueda examinar datos y determinar el formato gráfico en tiempo de ejecución sería la mejor solución. Puede usar el efg page como punto de partida de su investigación.

Una solución rápida y sucia es tratar los pocos formatos que usted necesita para manejar hasta que uno tiene éxito:

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; 

Editar:

El GraphicEx library tiene un ejemplo convertir que utiliza

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

para determinar el formato gráfico. Esto parece muy similar a la forma VB6 de hacer esto que mencionas. Tal vez puedas usar esta biblioteca para tu propósito.

+0

Gracias, tanto por su solución como por aclarar la respuesta anterior. Tu código parece interesante, pero como has mencionado, en realidad es un enfoque rápido y sucio. Estoy buscando algo así como la función VB 6 LoadPicture que funciona para la imagen admitida independientemente de la extensión del nombre de archivo. –

5

no tengo Delphi 2007 o 2009 para ver si esto va a funcionar en cualquiera de esas versiones. Sin embargo, en XE2, hay otra clase de Vcl.Graphics llamada TWICImage capaz de manejar imágenes que admite el componente Microsoft Imaging , incluyendo BMP, GIF, ICO, JPEG, PNG, TIF y Windows Media Photo. Es capaz de detectar el tipo de imagen de una secuencia.Asumiendo que tiene un TImage en la forma llamada 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; 

Funciona sin añadir PNGImage, GIFImg o JPEG a su declaración uses.

Las otras respuestas muestran cómo convertir el TImage en un BMP, por lo que no lo incluyo aquí. Solo estoy mostrando otra forma de cargar varios tipos de gráficos en un TImage sin saber de antemano el tipo de imagen, o la extensión de archivo ...

+0

Funciona perfectamente en C++ Builder XE5 –

+0

¿'TPicture :: Assign' copia los datos de imagen en la imagen? (Tengo cuidado con un puntero colgante después de 'wic.Free') –

+1

@MattMcNabb - Sí, lo copia (http://docwiki.embarcadero.com/Libraries/XE5/en/Vcl.Graphics.TPicture.Assign) , que se verifica mediante el seguimiento a través del código VCL. –

Cuestiones relacionadas