TBitmap32.LoadFromStream() Автоопределение формата изображения
Я использую Delphi XE2 (обновление 3) и GR32. Я не могу использовать TBitmap32.LoadFromStream()
загрузить данные изображения. Возникает следующее исключение:
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;
Обход (ы)
Если я прокомментирую LoadFromStream()
код и раскомментируйте две предыдущие строки, это работает - так что он может определить формат изображения при загрузке его из файла. В этом примере bs
содержит действительное изображение PNG. Однако иногда это может быть GIF, JPG, BMP или другой графический формат.
Я также знаю, что я могу использовать промежуточный объект (например, TPNGImage
, TJPEGImage
и т. д.), загрузите данные изображения, используя LoadFromStream()
в промежуточный объект, а затем Assign()
это к TBitmap32
, Однако было бы лучше, если TBitmap32
может обрабатывать изображения любого типа без промежуточного объекта, который, как я думал, мог бы...
Вопрос
Кто-нибудь знает, как использовать TBitmap32.LoadFromStream()
загрузить изображение и автоматически распознавать формат изображения, не сохраняя изображение на жестком диске (даже временно) или не используя промежуточный объект?
2 ответа
Это код для 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;
Как видите, код проверяет, является ли файл растровым изображением Windows. Если так, то он загружает его напрямую, вызывая LoadFromStream
,
Если нет, то он загружается в TPicture
а затем назначает этому экземпляру.
Дело в том, что LoadFromStream
понимает только растровые изображения Windows. Он не понимает любой другой формат файла. И вы пытаетесь загрузить PNG. Таким образом, нет способа сделать то, что вам нужно, без использования промежуточного объекта.
Решение для вас:
- Создать
TPNGImage
объект. - Вызов
LoadFromStream
в этом случае. - Вызов
Assign
наTBitmap32
экземпляр прохожденияTPNGImage
пример.
Delphi XE2 включает в себя класс в Vcl.Graphics
называется TWICImage
он обрабатывает изображения, поддерживаемые компонентом обработки изображений Windows, включая BMP, GIF, ICO, JPEG, PNG, TIF и Windows Media Photo. Это означает, что вы можете загрузить любой из поддерживаемых типов изображений непосредственно из потока, и он автоматически определит тип изображения и загрузит его. Затем загруженное изображение может быть назначено TBitmap32
компонент (или TImage
или TImage32
, так далее.).
uses GR32, Vcl.Graphics;
var
pic: TBitmap32;
wic: TWICImage;
bs: TBytesStream;
begin
bs := TBytesStream.Create(TClientDataSet(cds).FieldByName('filedata').AsBytes);
try
pic := TBitmap32.Create;
try
wic := TWICImage.Create;
try
bs.Position := 0;
wic.LoadFromStream(bs);
pic.Assign(wic);
finally
FreeAndNil(wic);
end;
finally
FreeAndNil(pic);
end;
finally
FreeAndNil(bs);
end;
end;
Работает без добавления PNGImage
, GIFImg
, или же JPEG
на ваш uses
заявление.