Load Jpg/Gif/Bitmap and convert to Bitmap

前端 未结 4 2016
谎友^
谎友^ 2020-11-30 01:09

I have to load an image from an XML file. There is no information in the XML file about whether the image is JPG/GIF/BMP. After loading the image, I need to convert it to Bi

相关标签:
4条回答
  • 2020-11-30 01:59

    I've found a simpler way! It loads JPG/GIF/BMP etc. files automatically without even knowing/checking the file format, and convert that accordingly. It worked for me perfectly.

    Sharing it here :)

    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;
    
    0 讨论(0)
  • 2020-11-30 01:59

    I don't have Delphi 2007 or 2009 to see if this will work in either of those versions. However, in XE2, there is another class in Vcl.Graphics called TWICImage that handles images supported by the Microsoft Imaging Component, including BMP, GIF, ICO, JPEG, PNG, TIF and Windows Media Photo. It is capable of detecting the image type from a stream. Assuming you have a TImage on the form called 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;
    

    It works without adding PNGImage, GIFImg, or JPEG to your uses statement.

    The other answers show how to convert the TImage to a BMP, so I'm not including that here. I'm just showing another way to load various graphic types into a TImage without knowing beforehand the image type, or the file extension...

    0 讨论(0)
  • 2020-11-30 02:02

    Delphi 2009 comes with built in support for JPEG, BMP, GIF and PNG.

    For earlier versions of Delphi you may need to find third party implementations for PNG and GIF, but in Delphi 2009 you simply add the Jpeg, pngimage and GIFImg units to your uses clause.

    If the file has an extension you can use the following code, as noted by others the TPicture.LoadFromFile looks at the extensions registered by the inherited classes to determine which image to load.

    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;
    

    If the file extension is not known one method is to look at the first few bytes to determine the image type.

    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 讨论(0)
  • 2020-11-30 02:04

    You can't use TPicture.LoadFromFile if you don't know what format the graphic has, as this method uses the file extension to determine which of the registered graphic formats needs to be loaded. There's a reason that there is no matching TPicture.LoadFromStream method.

    An external library which can examine data and determine the graphic format at runtime would be the best solution. You could use the efg page as a starting point of your research.

    A quick and dirty solution is to try the few formats you need to handle until one succeeds:

    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:

    The GraphicEx library has an example convert that uses

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

    to determine the graphic format. This seems very similar to the VB6 way of doing this that you mention. Maybe you can use this library for your purpose.

    0 讨论(0)
提交回复
热议问题