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 Bitmap.
Does anyone have any clue how to convert images to Bitmap without knowing the actual file format? I'm using Delphi 2007/2009
Thank you.
BMP (Bitmap) GIF (Graphics Interchange Format) TIFF (or TIF, for the file extension; Tagged Image File Format)
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;
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;
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With