Вопрос разработчика, связанный с загрузкой изображений в TImage из TStream, подразумевает необходимость создания универсального класса для отображения изображений в любом формате, при этом изображения хранятся в поле типа BLOB. Описанный в контексте код содержит процедуру LoadFromStream, которая пытается загрузить изображение, перебирая различные типы графических объектов.
Проблема
Проблема заключается в том, что если первый тип изображения в массиве ImageType не соответствует формату загружаемого изображения, то при попытке его использования возникает исключение, даже если следующий тип в массиве является подходящим. Это происходит из-за того, что позиция в потоке TStream не сбрасывается на начало после создания нового графического объекта, что приводит к ошибке при попытке чтения данных из потока.
Подтвержденный ответ
Чтобы решить эту проблему, необходимо добавить инициализацию потока, сбрасывая его позицию на начало перед попыткой загрузки изображения. Это позволит корректно обработать поток данных для каждого типа графического объекта в цикле. Вот исправленный код:
procedure tImageView.LoadFromStream(AStrm: TStream);
var
Ext: string;
NewGraphic: TGraphic;
GraphicClass: TGraphicClass;
i: integer;
IsLoaded: boolean;
begin
IsLoaded := false;
for i := 0 to Length(ImageType) - 1 do
begin
try
GraphicClass := ImageType[i];
NewGraphic := GraphicClass.Create;
Astrm.Position := 0; // Сброс позиции потока на начало
if Astrm.Size <> 0 then
begin
NewGraphic.LoadFromStream(AStrm);
IsLoaded := true;
Break;
end;
except
on E: Exception do
begin
NewGraphic.Free;
raise; // Передача исключения, если оно не обработано
end;
end;
end;
if IsLoaded then
begin
fImg.Picture.Assign(NewGraphic);
NewGraphic.Free;
end
else
begin
raise EInvalidGraphic.Create('Неизвестный формат изображения!');
end;
end;
Альтернативный ответ
Также стоит рассмотреть альтернативный подход, предложенный в комментариях к контексту: проверка заголовка потока для определения типа изображения. Это позволяет избежать перебора всех возможных типов и сразу определить нужный тип, что является более эффективным решением. В этом случае можно использовать следующий код:
uses
System.SysUtils,
System.Classes,
Vcl.Graphics,
Vcl.Imaging;
type
TGraphicSignature = function(const ASignature: array of Byte): Boolean;
const
JPEG_Signature: TGraphicSignature = function(const Signature: array of Byte): Boolean
begin
Result := Signature[0] = $FF and Signature[1] = $D8;
end;
PNG_Signature: TGraphicSignature = function(const Signature: array of Byte): Boolean
begin
Result := Signature[0] = $89;
end;
// Добавьте другие сигнатуры для форматов, которые вы поддерживаете
function GetGraphicType(AStream: TStream): TGraphicClass;
var
Signature: array of Byte;
SignatureSize: Integer;
begin
SignatureSize := Min(8, AStream.Size);
SetLength(Signature, SignatureSize);
AStream.Read(Signature[0], SignatureSize);
AStream.Position := 0; // Сброс позиции потока на начало
if JPEG_Signature(Signature) then
Exit(TJPEGImage);
else if PNG_Signature(Signature) then
Exit(TPNGImage);
// Добавьте другие проверки для форматов, которые вы поддерживаете
Result := nil;
end;
procedure tImageView.LoadFromStream(AStrm: TStream);
var
NewGraphic: TGraphic;
begin
NewGraphic := GetGraphicType(AStrm).Create;
if Assigned(NewGraphic) then
begin
NewGraphic.LoadFromStream(AStrm);
fImg.Picture.Assign(NewGraphic);
NewGraphic.Free;
end
else
begin
raise EInvalidGraphic.Create('Неизвестный формат изображения!');
end;
end;
Заключение
Использование TWICImage для обработки изображений может быть еще одним решением, так как TWICImage способен обрабатывать различные форматы изображений, что позволяет избежать необходимости использования множества различных классов графических объектов. Выбор метода зависит от конкретных требований и предпочтений разработчика.
Разработчик сталкивается с проблемой оптимизации порядка перебора форматов изображений в классе отображения для Delphi, чтобы корректно загружать изображения различных форматов из `TStream`, и необходимо исправить ошибку, связанную с позицией п
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.