I'm using Delphi XE2 (Update 3) and GR32. I am unable to use TBitmap32.LoadFromStream()
to load the image data. It raises the following exception:
Project MyApp.exe raised exception class EInvalidGraphic with message 'Bitmap image is not valid'.
uses GR32, GifImg, PngImage, Vcl.Graphics;
var
pic: TBitmap32;
bs: TBytesStream;
begin
bs := TBytesStream.Create(TClientDataSet(cds).FieldByName('filedata').AsBytes);
try
pic := TBitmap32.Create;
try
// bs.SaveToFile('c:\delme.png');
// pic.LoadFromFile('c:\delme.png');
pic.LoadFromStream(bs); // <- EInvalidGraphic exception
// do something with 'pic'
finally
FreeAndNil(pic);
end;
finally
FreeAndNil(bs);
end;
end;
If I comment the LoadFromStream()
code and uncomment the prior two lines, it works -- so it is able to determine the image format when loading it from a file. In this example, bs
contains a valid PNG image. However, sometimes it may be a GIF, JPG, BMP or another graphic format.
I also know that I can use an intermediate object (e.g., TPNGImage
, TJPEGImage
, etc.), load the image data using LoadFromStream()
into the intermediate object, and then Assign()
it to the TBitmap32
. However, it would be better if TBitmap32
could handle any type of image without an intermediate object, which I thought it could...
Does anyone know how to use TBitmap32.LoadFromStream()
to load the image and have it auto-recognize the image format without saving the image to the HDD (even temporarily), or using an intermediate object?
This is the code for LoadFromFile
:
procedure TCustomBitmap32.LoadFromFile(const FileName: string);
var
FileStream: TFileStream;
Header: TBmpHeader;
P: TPicture;
begin
FileStream := TFileStream.Create(Filename, fmOpenRead);
try
FileStream.ReadBuffer(Header, SizeOf(TBmpHeader));
// Check for Windows bitmap magic bytes...
if Header.bfType = $4D42 then
begin
// if it is, use our stream read method...
FileStream.Seek(-SizeOf(TBmpHeader), soFromCurrent);
LoadFromStream(FileStream);
Exit;
end
finally
FileStream.Free;
end;
// if we got here, use the fallback approach via TPicture...
P := TPicture.Create;
try
P.LoadFromFile(FileName);
Assign(P);
finally
P.Free;
end;
end;
As you can see, the code checks to see if the file is a Windows bitmap. If so then it loads it directly by calling LoadFromStream
.
If not then it loads into a TPicture
and then assigns to this instance.
The point is that LoadFromStream
only understands Windows bitmaps. It does not understand any other file format. And you are trying to load a PNG. So, there's no way to do what you need without using an intermediate object.
The solution for you is to:
TPNGImage
object.LoadFromStream
on that instance.Assign
on the TBitmap32
instance passing the TPNGImage
instance.