Перейти к содержанию
Fire Monkey от А до Я
  • 0

Как правильно использовать MultiresBitmap в TImageList?


xenon54

Вопрос

Есть ImageList, в нем есть Source Images и List of images. В source images добавляю итем, в него загружаю 3 картинки для разных скейлов (1,2,3). В list of images создаю итем и указываю источником тот самый первый итем из source images, далее делаю так:

image1.Bitmap.Assign(imagelist1.Bitmap(TSizeF.Create(258, 344),0));

Картинка появляется, но всегда берется первый из MultiresBitmap независимо от скейла реального устройства. К примеру на Iphone 6plus scale=3 и картинка должна браться соответствующая, но берется первая со скейлом 1. Что я делаю не так?

Изменено пользователем xenon54
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Нашел решение, но не уверен что идеальное:

var
ScreenScale : Single;

procedure TForm1.FormShow(Sender: TObject);
var
  ScreenSvc: IFMXScreenService;
begin
    if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenSvc)) then
    begin
      ScreenScale := ScreenSvc.GetScreenScale;
    end;
end;

function TForm1.GetImageFromImageListByScale(indx: Integer): TBitmap;
var
  i : Integer;
  arr : TArray<Single>;
begin
  Result := nil;
  arr := ImageList1.Source.Items[indx].MultiResBitmap.ScaleArray(False);
  for I := 0 to Length(arr)-1 do
  begin
    if SameValue(arr[i], ScreenScale) then
      Result := ImageList1.Source.Items[indx].MultiResBitmap.ItemByScale(ScreenScale,False,true).Bitmap as TBitmap;

  end;

  if Result <> nil then
    exit;

  Result := ImageList1.Source.Items[indx].MultiResBitmap.ItemByScale(1,False,true).Bitmap as TBitmap;


end;




Изменено пользователем xenon54
Ссылка на комментарий
  • 0

image1.Bitmap.Assign(imagelist1.Bitmap(TSizeF.Create(258, 344),0));

Imagelist1 ни чего не знает о масштабе. Просто согласно указанного размера выбирается наиболее подходящая картинка и растягивается таким образом, чтобы вписаться в размеры. Т.е. в данном случае будет выбираться картинка с размерами наиболее близкими к 258, 344. Тут надо самостоятельно определять масштаб и умножать на него размеры.

  Scale := Canvas.Scale;
  Image1.Bitmap.Assign(imagelist1.Bitmap(TSizeF.Create(258 * Scale, 344 * Scale),0));

Если хотите лишить себя удовольствия разбираться с масштабами, то воспользуйтесь компонентом TGlyph, который сам рисует учитывая свои размеры и масштаб.

См. также маленький пример.TestScaledImageList.zip

Изменено пользователем RoschinSpb
Ссылка на комментарий
  • 0

Спасибо за объяснения и за пример :)

2 вопроса сразу возникли попутных:

1. Когда использую устройство со скейлом равным двум, image1.MultiResBitmap.Count = 2. Значит ли это что в память загружаются обе картинки со скейлом 1 и 2?

2. Если в ImageList будут картинки со скейлами (1,2,3), а устройство имеет скейл 1.3, то какая картинка подставится (читал что у ведра бывает скейл 1.3, просто нечем проверить) ? Если возьмется картинка с меньшим скейлом, т.е. 1, то будет потеря качества картинки на экране, а если возьмется со скейлом 2, то это получается перерасход памяти :) Хотя конечно если ответ на первый вопрос утвердительный, то про память вопрос отлетает.

Изменено пользователем xenon54
Ссылка на комментарий
  • 0

image1.MultiResBitmap.Count = 2 Да, в памяти обе картинки. Чтобы добавить ложку меда, они хранятся в png-формате до первого обращение непосредственно к TBitmap. По этой причине если к примеру нужно узнать ширину картинки, то лучше обращаться к элементу коллекции

W := Image1.MultiResBitmap[I].Width; // остается в запакованном виде

чем к битмапу

W := Image1.MultiResBitmap[I].Bitmap.Width; // распаковываем картинку, хотя она не нужна.

А вообще говоря по этой причине лучше не использовать TImage для хранения изображений в fmx-файлах.

Как я писал в статье что если мы захотим в Run-Time динамически формировать большое количество контролов с картинками (например, пункты TListBox), то мы будем иметь множество копий одних и тех же графических данных. При использовании TImageList каждый пункт будет содержать только номер изображаемой картинки.

 

Нет, 1.3 не бывает. У моего Nexus 7: Scale = 1.33125  :mellow: Картинки в основном сжимаются. Только если картинка чуть-чуть (1/5) меньше чем надо, то она растягивается. 

Т.е. если есть картинки в масштабе 1 и 2 и требуемый масштаб 1.2, то будет использована картинка в масштабе 1. Если требуемый масштаб 1.21 то будет использована картинка в масштабе 2.
 

Ссылка на комментарий
  • 0

Спасибо за ответы. Не могу все таки не спросить: зачем загружается в память картинка для скейла 1 и 2, если скейл устройства = 3? Даже если он в памяти в запакованном виде.

Ссылка на комментарий
  • 0

Спасибо за ответы. Не могу все таки не спросить: зачем загружается в память картинка для скейла 1 и 2, если скейл устройства = 3? Даже если он в памяти в запакованном виде.

Ну такой механизм работы компонентной модели. Загружается вся форма целиком из файла fmx или dfm. Там, если посмотреть текст, есть все варианты картинок. А пока не начали рисовать масштаб неизвестен. Гипотетически может быть несколько мониторов с разным масштабом.

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...