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. Таким образом, нет способа сделать то, что вам нужно, без использования промежуточного объекта.

Решение для вас:

  1. Создать TPNGImage объект.
  2. Вызов LoadFromStream в этом случае.
  3. Вызов 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 заявление.

Другие вопросы по тегам