Recent

Author Topic: TImageList - where are the docs?  (Read 3366 times)

ArminLinder

  • Sr. Member
  • ****
  • Posts: 316
  • Keep it simple.
TImageList - where are the docs?
« on: December 18, 2023, 08:58:38 am »
Hi all,

is there anyone knowledgeable who would please finish the documentaion fragment found here (https://wiki.freepascal.org/TImageList) about this monster-dialog of TImgeList? It is not Delphi compatible, so simply pointing anyones nose to the delphi docs doesn't help this time.

It seems to be a mysterious blend of list editor and picture previewer, having quite strict ideas about clipping pictures, and it is obviously meant to support different resolutions (or sizes ...?) of bitmaps, where another mysterious piece of built-in code returns the "optimal" picture for a given size and screen pixel density?

Starting at an empty dialog, most of the buttons (including the one that says "Help") do nothing. I found and used some "try this - it works for me, though I don't know how and why" step-by-step instructions, and got some results, but they never persist. It seems that blindly entering "Sizes/Resolutions" (WTF? Which of both??? What format? How related to the Pixel size of the imported pictures?) does somehow "prepare" the dialog, because afterwards I can drag in exactly as many icons as I have entred "Sizes/Resolutions".

The whole thing breaks apart as soon as I change the Windows screen settings, and/or move the source to Linux and back. This may be a problem of me not having fully understood the image-list, or the button settings, or form settings (scaled= property), or all of them. Because of the sparse documentation, I cannot even find out where to look and what I do need to learn.

Fact is, I sank hours and hours of valuable time into this topic and still don't reliably get the results I need.

Anyone help me, please.

I'd also, like usual, volunteer to add the missing docs, as good as I can, but I need in-depth informations about the inner workings of all this from someone who knows before I can do that.

Thnx, Armin.

« Last Edit: December 18, 2023, 09:00:41 am by ArminLinder »
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

wp

  • Hero Member
  • *****
  • Posts: 12864
Re: TImageList - where are the docs?
« Reply #1 on: December 18, 2023, 11:58:17 am »
I agree that the article is a bit confusing because it seems to be just a collection of single unrelated topics without a clear structure. I rearranged the chapters so that the more elemental description is at the top. It's still far from perfect, though...

But basically, everything is already there, in particular if you know the Delphi TImageList. The article mainly describes the differences introduced for supporting images on high-DPI monitors.

ArminLinder

  • Sr. Member
  • ****
  • Posts: 316
  • Keep it simple.
Re: TImageList - where are the docs?
« Reply #2 on: December 18, 2023, 11:09:03 pm »
Thanks for your efforts, but it didn't help me much, but it served well as a start to investigate further.

To start somewhere ... I checked the properties of a TSpeedButton. There is TSpeedButton.ImageWidth. Hm. After some seeking I found, that if this property is set to 0 (the default) it is ignored, and the properties under TSpeedButton.Images are used. We have TSpeedButton.Images.Height and TSpeedButton.Image.Width. I suppose this is the height and width of the image in pixels at 96 ppi. Per default, a newly created TImageList sets both to 16, which is probably why 16 is contained in almost all code samples and screenshots.

Doing advanced math one can find out, that a 16 pixels image scaled by 125%, 150%, 175% and 200% leads to the pixel sizes 16, 20, 24, 28 and 32. Three of those (16,24 and 32) are indeed shown in the sample screenshots of the doc, and those are also contained in Roland Hahns ingenious set of ready-made glyphs. 20 and 28 are - for some mysterious reason - missing.

Handling-wise I tried to open the TImageList editor, and import pictures. Regardless of what size a picture file I load from disk has, it is always listed as "Images.Height x Images.Width". If I select more than one picture, all but the first one are ignored. What finally worked, was to "blindly" add 24 and 32 using the "New Size/Resolution" button. After this I could select three pictures, and I got them - again regardless of their physical size - listed as 16 x 16, 24 x 24 and 32 x 32. If I mistakedly select more or less images than I have (blindly!) entered resolutions, only the first picture is added, and the missing resolutions are coarsly upscaled versions of that one image.

Once done not falling into any of these traps, I got indeed three nice images displayed on the left side of the list. The right side of the dialog ("Selected Image") seems to show the same images as the list of the left, but vertically arranged. It does also sometimes fail to follow the list on the left, e.g. if you empty the list, the last previewed icon is still displayed there.

Not quite intuitive, I'd say. This is where the documentation should kick in. If you agree, I'd change the text of this post to sound more neutral than frustrated, update the images, and add all this into the wiki.

What do you say? It is what I had expected from a documentation, do you agree?

Armin

« Last Edit: December 18, 2023, 11:15:25 pm by ArminLinder »
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

dsiders

  • Hero Member
  • *****
  • Posts: 1431
Re: TImageList - where are the docs?
« Reply #3 on: December 19, 2023, 12:05:17 am »
Thanks for your efforts, but it didn't help me much, but it served well as a start to investigate further.

To start somewhere ... I checked the properties of a TSpeedButton. There is TSpeedButton.ImageWidth. Hm. After some seeking I found, that if this property is set to 0 (the default) it is ignored, and the properties under TSpeedButton.Images are used. We have TSpeedButton.Images.Height and TSpeedButton.Image.Width. I suppose this is the height and width of the image in pixels at 96 ppi. Per default, a newly created TImageList sets both to 16, which is probably why 16 is contained in almost all code samples and screenshots.

Doing advanced math one can find out, that a 16 pixels image scaled by 125%, 150%, 175% and 200% leads to the pixel sizes 16, 20, 24, 28 and 32. Three of those (16,24 and 32) are indeed shown in the sample screenshots of the doc, and those are also contained in Roland Hahns ingenious set of ready-made glyphs. 20 and 28 are - for some mysterious reason - missing.

Handling-wise I tried to open the TImageList editor, and import pictures. Regardless of what size a picture file I load from disk has, it is always listed as "Images.Height x Images.Width". If I select more than one picture, all but the first one are ignored. What finally worked, was to "blindly" add 24 and 32 using the "New Size/Resolution" button. After this I could select three pictures, and I got them - again regardless of their physical size - listed as 16 x 16, 24 x 24 and 32 x 32. If I mistakedly select more or less images than I have (blindly!) entered resolutions, only the first picture is added, and the missing resolutions are coarsly upscaled versions of that one image.

Once done not falling into any of these traps, I got indeed three nice images displayed on the left side of the list. The right side of the dialog ("Selected Image") seems to show the same images as the list of the left, but vertically arranged. It does also sometimes fail to follow the list on the left, e.g. if you empty the list, the last previewed icon is still displayed there.

Not quite intuitive, I'd say. This is where the documentation should kick in. If you agree, I'd change the text of this post to sound more neutral than frustrated, update the images, and add all this into the wiki.

What do you say? It is what I had expected from a documentation, do you agree?

Armin

So was the actual documentation any help?

https://lazarus-ccr.sourceforge.io/docs/lcl/imglist/tcustomimagelist.html
https://lazarus-ccr.sourceforge.io/docs/lcl/controls/timagelist.html


Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

wp

  • Hero Member
  • *****
  • Posts: 12864
Re: TImageList - where are the docs?
« Reply #4 on: December 19, 2023, 12:31:31 am »
To start somewhere ... I checked the properties of a TSpeedButton. There is TSpeedButton.ImageWidth.
TSpeedButton.ImageWidth is the image width used by the associated Imagelist, when the system is at 96ppi. The default value 0 means: take the value specified at TImageList.Width.

This may sound over-complicated, but the concept is quite ingenious. Take a TListView. It needs two ImageLists, SmallImages and LargeImages. The SmallImages usually are 16x16, the LargeImages are 32x32. While in Delphi you really must provide two separate imagelists (and suffer from issues keeping both in sync), in Lazarus you only need one. For supporting 96ppi (100%), 144ppi (150%) and 192ppi (200%) monitor resolutions, add images at size 16, 24 and 32 (for the small images) and 32, 48, 64 (for the large images). In order to distinguish between both cases set TImageList.SmallImagesWidth to 16 and .LargeImagesWidth to 32, and the ListView will use the 16,24,32 images for the SmallImages and the 32,48,64 images for the LargeImages.

Doing advanced math one can find out, that a 16 pixels image scaled by 125%, 150%, 175% and 200% leads to the pixel sizes 16, 20, 24, 28 and 32. Three of those (16,24 and 32) are indeed shown in the sample screenshots of the doc
A screenshot is a "shot", a moment, it does not show what happened before... In this case, the ImageList was prepared to hold these three sizes. When you drop a TImageList on the form it has Width=16 and Height=16 - the default in most cases for 96 ppi. On a screen with 150% resolution (144ppi) you also need 24x24 - click on "New Resolution" and enter the value "24". Likewise for 200% (192 ppi) where you enter "32". This is what had happend with the screenshot before taking it. Of course you can also add intermediate values like 20 and 28 that you mention. But of course, this increases the file size accordingly. In many cases, 100%, 150% 200% is a good compromise. If a system really runs at intermediate resolutions, such as 175% (168 ppi), the next smaller size is displayed, and this probably is tolerable. (But I think it should also be possible to create an imagelist at runtime with all five resolutions and add the images from the original imagelist to it - during this process the missing images are scaled down from the next larger size).

Handling-wise I tried to open the TImageList editor, and import pictures. Regardless of what size a picture file I load from disk has, it is always listed as "Images.Height x Images.Width". If I select more than one picture, all but the first one are ignored. What finally worked, was to "blindly" add 24 and 32 using the "New Size/Resolution" button. After this I could select three pictures, and I got them - again regardless of their physical size - listed as 16 x 16, 24 x 24 and 32 x 32. If I mistakedly select more or less images than I have (blindly!) entered resolutions, only the first picture is added, and the missing resolutions are coarsly upscaled versions of that one image.
I cannot follow what you are doing here... These are the correct steps:
  • Decide which will be the "base size" of the images, the size at 96ppi (usually 16x16)
  • Drop a TImageList on the form. Set its Width to the "base size", Height to the same value since icons usually are square (or adjust Height to keep the aspect ratio)
  • Double-click on the ImageList icon to open the ImageList editor
  • Decide which monitor resolutions you want to support and calculate the corresponding image width from the "base size". For each image size, click on "New resolution" and enter the width value. Do not do this for the "base size" itself since it is already known.
  • To add images you should have all images sizes in the same directory (like in Roland's "general-purpose" folder). In this case, click on "Add more resolutions", scroll to the motive that you need and select all required sizes by CTRL-click. This loads all sizes in one take. If you don't have all images at the same place, click on "Add" to select only a single image (still the missing images will appear in the imagelist editor because their size will be interpolated from the added one); then you will have to navigate to the folder with the next size, and click "Replace" to replace the interpolated images by the image in that folder.
  • Repeat with all images.
  • In order to activate scaling set ImageList.Scaled to true, and check the "Use LCL scaling" box in the project options (and in case of Windows, one of the "DPI awareness" "on" settings).

if you empty the list, the last previewed icon is still displayed there.
Your problem means a bug which has been fixed in v3.0.

add all this into the wiki.
Go ahead.

wp

  • Hero Member
  • *****
  • Posts: 12864
Re: TImageList - where are the docs?
« Reply #5 on: December 19, 2023, 12:40:14 am »
So was the actual documentation any help?

https://lazarus-ccr.sourceforge.io/docs/lcl/imglist/tcustomimagelist.html
https://lazarus-ccr.sourceforge.io/docs/lcl/controls/timagelist.html

I am not sure whether the "Scaled" property is correctly described. Here is a screenshot collage of a toolbar with three buttons taken at 96ppi, 120ppi, 144ppi and 168 ppi (100%, 125%, 150%, 175%); the imagelist has been set up to hold the images of 16 /100%), 24 (150%) and 32 (200%), and the Scaled property is set to true. As you can see the toolbutton sizes scale correctly, but the icons have the same sizes for 96ppi and 120ppi, and for 144ppi and 168 ppi - according to your description the intermediate sizes should be interpolated when Scaled is true.

In my experience Scaled = true is needed for automatic switching between the next predefined image sizes when screen resolution changes, and this behaviour is turned off when Scaled is false (sometimes people don't want this).

Or maybe your description is correct, and we have a bug here?

Please contact Ondrej and ask him about this, he's the author of the scaled imagelist.

dsiders

  • Hero Member
  • *****
  • Posts: 1431
Re: TImageList - where are the docs?
« Reply #6 on: December 19, 2023, 03:24:17 am »
So was the actual documentation any help?

https://lazarus-ccr.sourceforge.io/docs/lcl/imglist/tcustomimagelist.html
https://lazarus-ccr.sourceforge.io/docs/lcl/controls/timagelist.html

I am not sure whether the "Scaled" property is correctly described. Here is a screenshot collage of a toolbar with three buttons taken at 96ppi, 120ppi, 144ppi and 168 ppi (100%, 125%, 150%, 175%); the imagelist has been set up to hold the images of 16 /100%), 24 (150%) and 32 (200%), and the Scaled property is set to true. As you can see the toolbutton sizes scale correctly, but the icons have the same sizes for 96ppi and 120ppi, and for 144ppi and 168 ppi - according to your description the intermediate sizes should be interpolated when Scaled is true.

In my experience Scaled = true is needed for automatic switching between the next predefined image sizes when screen resolution changes, and this behaviour is turned off when Scaled is false (sometimes people don't want this).

Or maybe your description is correct, and we have a bug here?

Please contact Ondrej and ask him about this, he's the author of the scaled imagelist.

I'll have a look at the topic(s) again. If I have questions, I'll contact Ondrej. Thanks Werner.
Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

dsiders

  • Hero Member
  • *****
  • Posts: 1431
Re: TImageList - where are the docs?
« Reply #7 on: December 19, 2023, 10:29:59 am »
So was the actual documentation any help?

https://lazarus-ccr.sourceforge.io/docs/lcl/imglist/tcustomimagelist.html
https://lazarus-ccr.sourceforge.io/docs/lcl/controls/timagelist.html

I am not sure whether the "Scaled" property is correctly described. Here is a screenshot collage of a toolbar with three buttons taken at 96ppi, 120ppi, 144ppi and 168 ppi (100%, 125%, 150%, 175%); the imagelist has been set up to hold the images of 16 /100%), 24 (150%) and 32 (200%), and the Scaled property is set to true. As you can see the toolbutton sizes scale correctly, but the icons have the same sizes for 96ppi and 120ppi, and for 144ppi and 168 ppi - according to your description the intermediate sizes should be interpolated when Scaled is true.

In my experience Scaled = true is needed for automatic switching between the next predefined image sizes when screen resolution changes, and this behaviour is turned off when Scaled is false (sometimes people don't want this).

Or maybe your description is correct, and we have a bug here?

First, my description of Scaled is not very good. I'll address that. But it may be a little of both.

I believe the icon sizes are being determined accurately based on the logic implemented in TCustomImageList.GetWidthForPPI. If it does not find a resolution using the pixel width for the requested DPI, it uses the scaling factors to derive the image size. In the case of 120 DPI that would be a 20 pixel image -  and that width is not in the resolutions. So it uses 100% (no scaling) for 96-120 DPI. The issue is similar for 168 DPI. That would be a 28 pixel image (also not in the resolutions), so it uses 150% for 144-168 DPI. 200% and higher does not kick in until 169+ DPI

Perhaps those thresholds are incorrect, but that is what is implemented in the method. Do you feel the logic in GetWidthForPPI is wrong?

I'm going to rework the description for Scaled though.
Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

dsiders

  • Hero Member
  • *****
  • Posts: 1431
Re: TImageList - where are the docs?
« Reply #8 on: December 20, 2023, 12:32:07 am »
I'm going to rework the description for Scaled though.

And here is the latest attempt. Does thismore accurately reflect its usage?

Code: Text  [Select][+][-]
  1. Summary
  2.  
  3. Controls whether image sizes are automatically scaled for different display
  4. density (Pixels per Inch) settings.
  5.  
  6. Description
  7.  
  8. Scaled is a Boolean property used to enable or disable automatic scaling of
  9. image sizes for different resolutions (Pixels per Inch).
  10.  
  11. When Scaled is True, images in the list are dynamically scaled from the
  12. Width and Height used in the image list to the size needed for a given display
  13. density (Pixels per Inch). If the scaled image size is one of the Resolutions
  14. found in the image list, the images in the Resolution are used. If an image
  15. size is needed that does not exist in Resolutions, the size for the scaled
  16. resolution is determined using the WidthForPPI property and a specified PPI
  17. setting. The ResolutionForPPI property provides access to an image list using  
  18. the scaled image size.
  19.  
  20. See TCustomImageList.WidthForPPI for information about use of the pixels per
  21. inch setting to derive the scaling factor and the resulting size for images.
  22.  
  23. When Scaled is False, images are not dynamically scaled. The Width and Height
  24. specified in the image list are used.
  25.  
  26. The default value for the property is <b>False</b> and disables automatic
  27.  
  28. At design-time, use the image list property editor to maintain images or
  29. resolutions used in the image list. At run-time, use the methods provided in
  30. the class instance to maintain the image list.
  31.  
  32. Use the OnGetWidthForPPI event handler to override or substitute the
  33. image size used for a given display density (PPI).
  34.  
  35. Scaled is used in the implementation of the GetResolutionForPPI and GetWidthForPPI
  36. methods which implement the ResolutionForPPI and WidthForPPI properties (respectively).
  37.  
Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

wp

  • Hero Member
  • *****
  • Posts: 12864
Re: TImageList - where are the docs?
« Reply #9 on: December 20, 2023, 12:56:04 am »
Code: [Select]
If an image size is needed that does not exist in Resolutions, the size for the scaled
resolution is determined using the WidthForPPI property and a specified PPI
setting. The ResolutionForPPI property provides access to an image list using 
the scaled image size.
Tiny change:
Code: [Select]
If an image size is needed that does not exist in Resolutions, the next smaller size
is selected from the predefined images by using the WidthForPPI property and a specified PPI
setting. The ResolutionForPPI property provides access to an image list using the scaled image size.

Code: [Select]
The default value for the property is <b>False</b> and disables automatic
End of the sentence missing, probably "scaling"

dsiders

  • Hero Member
  • *****
  • Posts: 1431
Re: TImageList - where are the docs?
« Reply #10 on: December 20, 2023, 01:24:38 am »
Tiny change:
Code: [Select]
If an image size is needed that does not exist in Resolutions, the next smaller size
is selected from the predefined images by using the WidthForPPI property and a specified PPI
setting. The ResolutionForPPI property provides access to an image list using the scaled image size.

Noted and incorporated. Thanks.

End of the sentence missing, probably "scaling"

Yes, bad copy/paste on my part.

Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

ArminLinder

  • Sr. Member
  • ****
  • Posts: 316
  • Keep it simple.
Re: TImageList - where are the docs?
« Reply #11 on: December 20, 2023, 01:20:22 pm »
I cannot follow what you are doing here... These are the correct steps:

If you look closely, you are describing my findings, using other words :-) This is exactly the instructions I would have expected to find in the wiki, except, probably, that I think using the term "resolution" is misleading, when we need to enter the actual size of a picture.

I think, your text is clearer --> if you agree, I use it to update the wiki.

The catch is, that one needs to insert the required Size/Resolutions beforehand, the current docs don't tell this, and there isn't any visual feedback. It's just that the list doesn't work if one fails to do that "properly", and there isn't an intuitive way to get a list of already entered resolutions to check the "properlyness".

Once one has been told how the concept works, things fall well into place.

Also very interesting: your description about "scaled". This should IMHO be added to the wiki page about DPI-awareness, and referenced in the wiki about TImageList.

Armin
« Last Edit: December 20, 2023, 07:44:36 pm by ArminLinder »
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

wp

  • Hero Member
  • *****
  • Posts: 12864
Re: TImageList - where are the docs?
« Reply #12 on: December 22, 2023, 02:26:21 pm »
@dsiders: I contacted Ondrej about the Scaled property. Basically scaling is done in steps according to the predefined image size - just as you wrote in the modificed docs. But there is an option for scaling to intermediate resolution by providing a handler for the ImageList's OnGetWidthForPPI event:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ImageList1GetWidthForPPI(Sender: TCustomImageList;
  2.   AImageWidth, APPI: Integer; var AResultWidth: Integer);
  3. begin
  4.   AResultWidth := AImageWidth * APPI div 96;
  5. end;
I tested this with the project of reply #5 - see attached screenshot which compares the toolbar icons at 175% (top), 150%, 125% and 100% (bottom). Now the intermediate sizes are displayed correctly.

I think this is an interesting detail which should be contained in the official documentation as well (I think you had a similar sentence in your old version).

dsiders

  • Hero Member
  • *****
  • Posts: 1431
Re: TImageList - where are the docs?
« Reply #13 on: December 22, 2023, 04:59:34 pm »
@dsiders: I contacted Ondrej about the Scaled property. Basically scaling is done in steps according to the predefined image size - just as you wrote in the modificed docs. But there is an option for scaling to intermediate resolution by providing a handler for the ImageList's OnGetWidthForPPI event:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ImageList1GetWidthForPPI(Sender: TCustomImageList;
  2.   AImageWidth, APPI: Integer; var AResultWidth: Integer);
  3. begin
  4.   AResultWidth := AImageWidth * APPI div 96;
  5. end;
I tested this with the project of reply #5 - see attached screenshot which compares the toolbar icons at 175% (top), 150%, 125% and 100% (bottom). Now the intermediate sizes are displayed correctly.

I think this is an interesting detail which should be contained in the official documentation as well (I think you had a similar sentence in your old version).

Okay. I am restoring the paragraph about OnGetWidthForPPI that was removed from Scaled in the last commit. I also added your example to the OnGetWidthForPPI topic.

Thanks Werner.
Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

 

TinyPortal © 2005-2018