Як зробити список tbitmap ів

Завантажуватися картинки будуть в OnCreate ().
Через функцію LoadImage ( "name_1", "data / image_1.bmp");
Тобто ім'я та шлях.

Отримувати потрібно через функцію GetImage (Name: string): TBitmap;
Тобто по імені TBitmap.

Поки бачу тільки таке рішення:


type
# XA0; TItem = record
# XA0; # XA0; # XA0; Name: string;
# XA0; # XA0; # XA0; Bitmap: TBitmap;
# XA0; end;

Item.Name:= Name;
Item.Bitmap: = TBitmap;
Item.Bitmap.LoadFromFile ();

Єдиний недолік ЛістовОб'ектов (містять посилання на бітмапами) - втрата гдіхендла. Цього недоліку позбавлений ІмаджЛіст, але він зберігає картинки однакового розміру, в цьому його недолік.
Багато що залежить від конкретних умов завдання. Можна і свій ІмаджЛіст написати, з блекджек. Одна канва, таблиця зсувів і розмірів, метод отримання.

Але в загальному випадку, звичайно СтрінгЛіст краще.

Так, зображення різних розмірів.


> Але в загальному випадку, звичайно СтрінгЛіст краще.

Поки зробив через нього.


> Єдиний недолік ЛістовОб'ектов (містять посилання на бітмапами) -> втрата гдіхендла.

Це як? В якому місці він губиться?

# XA0;
# XA0; Bitmap: TBitmap;
# XA0; Bitmap.LoadFromFile ();

# XA0; S: TStringList;
# XA0; S.AddObject ( "1", Bitmap);

Ось зробив клас, не знаю що робити в разі виключення в AddImage () під час завантаження зображення:


type
# XA0; TListImages = class
# XA0; # XA0; constructor Create ();
# XA0; # XA0; destructor # XA0; Destroy (); override;
# XA0; private
# XA0; # XA0; FList: TStringList;
# XA0; public
# XA0; # XA0; procedure AddImage (const Name: string; const FileName: string);
# XA0; # XA0; function # XA0; GetImage (const Name: string): TBitmap;
# XA0; end;

constructor TListImages.Create ();
begin
# XA0; inherited;
# XA0; FList: = TStringList.Create ();
end;

destructor TListImages.Destroy ();
begin
# XA0; FreeAndNil (FList);
# XA0; inherited;
end;

procedure TListImages.AddImage (const Name: string; const FileName: string);
var
# XA0; Bitmap: TBitmap;
begin
# XA0; Bitmap: = TBitmap.Create ();
# XA0; try
# XA0; # XA0; Bitmap.LoadFromFile (FileName);
# XA0; # XA0; Bitmap.PixelFormat: = pf32bit;

# XA0; # XA0; FList.AddObject (Name, Bitmap);
# XA0; except
# XA0; # XA0; FreeAndNil (Bitmap);
# XA0; end;
end;

function TListImages.GetImage (const Name: string): TBitmap;
var
# XA0; Idx: LongInt;
begin
# XA0; if (FList.Find (Name, Idx))
# XA0; then Result: = (FList.Objects [Idx] as TBitmap)
# XA0; else Result: = nil;
end;

procedure TForm1.Button1Click (Sender: TObject);
var
# XA0; ListImages: TListImages;
# XA0; Bitmap: # XA0; # XA0; TBitmap;
begin
# XA0; ListImages: = TListImages.Create ();
# XA0; try
# XA0; # XA0; ListImages.AddImage ( "image_1", "1.bmp");

# XA0; # XA0; Bitmap: = ListImages.GetImage ( "image_1");

# XA0; # XA0; if (Assigned (Bitmap))
# XA0; # XA0; then Canvas.Draw (25, 25, Bitmap)
# XA0; # XA0; else ShowMessage ( "Error");
# XA0; finally
# XA0; # XA0; FreeAndNil (ListImages);
# XA0; end;
end;

У методі Адд ти губиш завантажений бітмапами і його більше немає. Прибери фрі.
У деструктор додай очищення бітмапами (в циклі фрі для кожного).
Так метод add имхо повинен повертати бітмапами і до того ж перевіряти чи немає вже з таким ім'ям і повертати його якщо є.

> Це як? В якому місці він губиться?

Поки забий, мені влом пояснювати. Для самоосвіти читай в гуглі GDI handle

Він знищується, якщо відбулося виключення під час LoadFromFile ()
Ось тільки мені не зрозуміло чи правильно так робити.


> В деструктор додай очищення бітмапами (в циклі фрі для кожного).


> Так метод add имхо повинен повертати бітмапами і до того ж перевіряти
> Чи немає вже з таким ім'ям і повертати його якщо є.

Не думаю, що мені це знадобиться.


> Демонстрація кінця ГДВ хендлов

У нашому списку де буде витік?
Адже викликається FreeAndNil ()


> У нашому списку де буде витік?

Це не витік. Просто GDi.Handel це цінний ресурс він обмежений 8-10 тисячами. Використовується для малювання всього на формі. А при створенні TBitmap він витрачається.
Якщо список буде великим порядку 8-10 тис, то програма не зможе коректно працювати.

Не думаю, що стільки бітмапами знадобиться.


> Це не витік. Просто GDi.Handel це цінний ресурс він обмежений 8-10 тисячами.

А Bitmap.Dormant - після "використання" - звільнить GDI дескриптор - до наступної "потреби".

Нафіга взагалі зберігати купу бітмапами? Саме з зав'язкою на Gdi? Якщо вони маленькі краще зберігати одним бітмапами і вирізати звідти потрібні фрагменти, якщо великі то зберігати взагалі на диску і в міру необхідності занурювати, якщо з диска вантажити повільно, то завантажити їх заздалегідь в список стрімів а вже з них вантажити на льоту в бітмапами.

> Саме з зав'язкою на Gdi?

А що багато GDI-ресурсів тягне 1 TBitmap?
По-ідеї це один HBITMAP і DIB-Секція, не багато має бути.

constructor TListImages.Create ();
begin
# XA0; inherited;
# XA0; FList # XA0; # XA0; # XA0; # XA0; # XA0; : = TStringList.Create ();
# XA0; FList.Duplicates: = dupError;
# XA0; FList.Sorted # XA0; # XA0;: = True;
end;

destructor TListImages.Destroy ();
var
# XA0; i: # XA0; # XA0; # XA0; LongInt;
# XA0; Bitmap: TBitmap;
begin
# XA0; for i: = 0 to FList.Count - 1 do // Чи вірно тут зроблено? Сам FList не очиститься посилання?
# XA0; begin
# XA0; # XA0; Bitmap: = (FList.Objects [i] as TBitmap);
# XA0; # XA0; FreeAndNil (Bitmap);
# XA0; end;

function TListImages.AddImage (const Name: string; const FileName: string): boolean;
var
# XA0; Bitmap: TBitmap;
begin
# XA0; Bitmap: = TBitmap.Create ();
# XA0; try
# XA0; # XA0; Bitmap.LoadFromFile (FileName);
# XA0; except # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; # XA0; // Чи правильно так обробляти виключення?
# XA0; # XA0; FreeAndNil (Bitmap);
# XA0; end;

# XA0; if Result then
# XA0; begin
# XA0; # XA0; FList.AddObject (Name, Bitmap);

function TListImages.GetImage (const Name: string): TBitmap;
var
# XA0; Idx: LongInt;
begin
# XA0; if (FList.Find (Name, Idx))
# XA0; then Result: = (FList.Objects [Idx] as TBitmap)
# XA0; else Result: = nil;
end;


> // Чи правильно так обробляти виключення?

Ну як тобі сказати. Формально все правильно, але про те, чому бітмапами не завантажено ти не дізнаєшся. Може бути варто після FreeAndNil (Bitmap); додати raise?

Схожі статті