Функция для загрузки PNG изображения из ResourceStream ничего не возвращает - PullRequest
0 голосов
/ 26 февраля 2020

В Delphi 10.1, Берлин, я пытаюсь изменить изображение в форме, загружая изображение PNG из ресурса. Я следовал этому: Загрузка изображения из встроенного ресурса и использовал TWICImage для автоматической обработки различных возможных форматов изображений. В этом случае я специально хочу использовать PNG для прозрачности.

По какой-то причине созданная мною функция ничего не возвращает. Однако, если я вызываю result.savetofile('test.png') внутри функции, ресурс успешно сохраняется, что подтверждает, что ресурс существует в EXE-файле и найден.

function LoadImageResource(NativeInstance: NativeUInt; ImageResource: string): TWICImage;
var
   Strm: TResourceStream;
   WICImage: TWICImage;

begin

  Strm := TResourceStream.Create(NativeInstance, ImageResource, RT_RCDATA);
  try
    Strm.Position := 0;
    WICImage := TWICImage.Create;
    try
      WICImage.LoadFromStream(Strm);
      result :=  WICImage; //these return empty
      result.savetofile('test.png'); //this succesfully saves the resource to disk
    finally
      WICImage.Free;
    end;
  finally
    Strm.Free;
  end;

end;

За пределами функции, если я пытаюсь назначить образ, вызвав, например, Image1.picture.assign(LoadFromResource(...)) или Image1.picture.graphic := LoadFromResource(...), ничего не присваивается. И если я тогда позвоню Image1.savetofile('test.png'), я получу ошибку нарушения доступа.

Чего мне не хватает?

1 Ответ

3 голосов
/ 26 февраля 2020

Проблема в том, что вы уничтожаете возвращаемое изображение. Важно понимать, что классы являются ссылочными типами в Delphi. Таким образом, после присвоения Result в вашем коде у вас все еще остается только один экземпляр, но две ссылки на этот же единственный экземпляр.

Вам необходимо удалить вызов на Free.

function LoadImageResource(Module: NativeUInt; const ResName: string): TWICImage;
var
  Strm: TResourceStream;
begin
  Strm := TResourceStream.Create(Module, ResName, RT_RCDATA);
  try
    Result := TWICImage.Create;
    Result.LoadFromStream(Strm);
  finally
    Strm.Free;
  end;
end;

Чтобы сделать исключение функции безопасным, требуется небольшая настройка:

function LoadImageResource(Module: NativeUInt; const ResName: string): TWICImage;
var
  Strm: TResourceStream;
begin
  Strm := TResourceStream.Create(Module, ResName, RT_RCDATA);
  try
    Result := TWICImage.Create;
    try
      Result.LoadFromStream(Strm);
    except
      Result.Free;
      raise;
    end;
  finally
    Strm.Free;
  end;
end;

При вызове функция ведет себя как конструктор. Это либо успешно, и возвращает новый экземпляр, передавая право собственности вызывающей стороне. Или это вызывает исключение. Соответственно я бы назвал функцию CreateImageFromResource.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...