Загрузите Jpg/Gif/Bitmap и конвертируйте в Bitmap

Мне нужно загрузить изображение из файла XML. В файле XML нет информации о том, является ли изображение JPG/GIF/BMP. После загрузки изображения мне нужно преобразовать его в Bitmap.

Кто-нибудь знает, как конвертировать изображения в Bitmap, не зная фактического формата файла? Я использую Delphi 2007/2009

Спасибо.

Ответы

Ответ 1

Я нашел более простой способ! Он автоматически загружает файлы JPG/GIF/BMP и т.д., Даже не зная/не проверяя формат файла и не конвертирует его соответствующим образом. Он отлично работал у меня.

Поделиться здесь:)

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

Delphi 2009 поставляется со встроенной поддержкой JPEG, BMP, GIF и PNG.

Для более ранних версий Delphi вам может потребоваться найти сторонние реализации для PNG и GIF, но в Delphi 2009 вы просто добавляете единицы Jpeg, pngimage и GIFImg к вашему предложению uses.

Если файл имеет расширение, вы можете использовать следующий код, как отмечают другие, TPicture.LoadFromFile просматривает расширения, зарегистрированные унаследованными классами, чтобы определить, какое изображение загрузить.

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;

Если расширение файла неизвестно, один метод должен посмотреть первые несколько байтов, чтобы определить тип изображения.

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;

Ответ 3

Вы не можете использовать TPicture.LoadFromFile, если вы не знаете, какой формат имеет графический файл, так как этот метод использует расширение файла, чтобы определить, какой из зарегистрированных графических форматов необходимо загрузить. Причина в том, что нет подходящего метода TPicture.LoadFromStream.

Лучшим решением будет внешняя библиотека, которая может проверять данные и определять графический формат во время выполнения. Вы можете использовать efg page как отправную точку своего исследования.

Быстрое и грязное решение - попробовать несколько форматов, которые вам нужно обработать, пока не получится:

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:

Библиотека GraphicEx имеет пример преобразования, который использует

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

чтобы определить графический формат. Это похоже на VB6-способ сделать это, о котором вы упоминаете. Возможно, вы можете использовать эту библиотеку для своей цели.

Ответ 4

У меня нет Delphi 2007 или 2009, чтобы увидеть, будет ли это работать в любой из этих версий. Однако в XE2 существует еще один класс в Vcl.Graphics, называемый TWICImage, который обрабатывает изображения, поддерживаемые компонентом Microsoft Imaging, включая BMP, GIF, ICO, JPEG, PNG, TIF и Windows Media Photo, Он способен обнаруживать тип изображения из потока. Предполагая, что у вас есть TImage в форме с именем 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;

Он работает без добавления PNGImage, GIFImg или JPEG в оператор uses.

Другие ответы показывают, как преобразовать TImage в BMP, поэтому я не включаю это здесь. Я просто показываю другой способ загрузки различных графических типов в TImage, не зная заранее тип изображения или расширение файла...