Recent

Author Topic: Load tiles into TImageList at runtime  (Read 3054 times)

_N_

  • New Member
  • *
  • Posts: 33
Load tiles into TImageList at runtime
« on: June 25, 2021, 01:32:34 pm »
Hello.
Sorry for a silly question, but I am not sure that I go into right direction.
I have a dozen of png files (some are with transparent background that I need to keep) and each of them contains several (well, form 2 to a few hundreds) square tiles. Tile size differs from file to file.
My task is to load them at runtime and then display on a form (like a tile map editor).
To simplify tiles loading I decided to use TImageList. It is easy to use visual component to load tiles from a file: just set tile size and click on "Add" button. But how can I do this from code:
Code: Pascal  [Select][+][-]
  1. Tiles1 := TImageList.Create(nil);
  2. Tiles1.Width := 32;
  3. Tiles1.Height := 32;
  4. Tiles1. // <- I failed to find a method that will split a big image
  5.  
Another thing is that sometimes I'd like to join images from several source files into single image list (tile size are identical).
Unfortunately I wasn't lucky googling the solution...
Also I am not sure if using TImageList is a correct way to go...
I am not asking for full implementation (however code snippet would be appreciated). I'd like to know the idea, correct way of solving of such task and a hint which methods I should use (full list of TImageList methods didn't give me a clue other than reading a big image and redrawing parts into separate slots - but I feel such approach is not optimal).
Thank you for the help.

loaded

  • Hero Member
  • *****
  • Posts: 825
Re: Load tiles into TImageList at runtime
« Reply #1 on: June 25, 2021, 02:43:50 pm »
Hi, it's easy to view and combine tile-shaped images. First you need to set the dimensions of your current drawing area, then calculate which tile should be placed where. This requires some math.
In my opinion, the best method for this job is to use the Image object.
With this method, I can create 25000*25000 images.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   mtile:TPicture;
  4. begin
  5.   mtile:=TPicture.Create;
  6.   mtile.LoadFromFile('D:\example.png');
  7.   image1.Picture:=nil;
  8.   image1.Picture.Bitmap.SetSize(mtile.Width*2,mtile.Height);
  9.   image1.Canvas.Draw(0,0,mtile.Bitmap);
  10.   image1.Canvas.Draw(mtile.Width,0,mtile.Bitmap);
  11. end;  
  12.  
Check out  loaded on Strava
https://www.strava.com/athletes/109391137

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Load tiles into TImageList at runtime
« Reply #2 on: June 25, 2021, 02:58:38 pm »
TImageList loads its data from TBitmaps or TIcons using any of its Add* or Insert* methods: Add, AddSliced, AddSlices, AddIcon, etc.

All you have to do is to create a TBitmap, load the image(s) and use the proper method of the image list to add it (them) to it.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

wp

  • Hero Member
  • *****
  • Posts: 11912
Re: Load tiles into TImageList at runtime
« Reply #3 on: June 25, 2021, 04:16:46 pm »
Hello.
Code: Pascal  [Select][+][-]
  1. Tiles1. // <- I failed to find a method that will split a big image
  2.  
You probably mean the AddSliced method, it has the horizontal and vertical count of images as parameters. See the attached demo. It uses one of the VirtualTreeView image stripes (25 images wide, 1 image high) and loads it into a TImageList. Using the scrollbar you can display all the generated images. The "Merge" button creates another tiled images, now 5x5 images.

_N_

  • New Member
  • *
  • Posts: 33
Re: Load tiles into TImageList at runtime
« Reply #4 on: June 28, 2021, 10:46:58 am »
Thank you all @loaded, @lucamar, @wp. From each of the answers I've got something useful.
Indeed, AddSliced method was what I searched for. However, I didn't have it on Lazarus 1.8.2, but when upgraded to Lazarus 2.0.6 - it is there and works. Here is simple code to solve the issue:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. const
  3.   TILE_SIZE = 32;
  4. var
  5.   TilesImage: TCustomBitmap;
  6.   TilesList: TImageList;
  7. begin
  8.   TilesImage := TPortableNetworkGraphic.Create();
  9.   try
  10.     TilesImage.LoadFromFile('laz_vt_check_dark_200.png');
  11.  
  12.     TilesList := TImageList.Create(nil);
  13.     TilesList.Width := TILE_SIZE;
  14.     TilesList.Height := TILE_SIZE;
  15.     TilesList.AddSliced(TilesImage, TilesImage.Width div TILE_SIZE, TilesImage.Height div TILE_SIZE);
  16.   finally
  17.     TilesImage.Free();
  18.   end;
  19.  
  20.   TilesList.Draw(Image1.Canvas, 0, 0, 2);
  21.   TilesList.Draw(Image1.Canvas, TILE_SIZE, 0, 8);
  22.   TilesList.Draw(Image1.Canvas, 0, TILE_SIZE, 16);
  23.   TilesList.Draw(Image1.Canvas, TILE_SIZE, TILE_SIZE, 24);
  24.   TilesList.Free();
  25. end;
  26.  

 

TinyPortal © 2005-2018