Page 1 of 3

listicon gadget speed (with large images, 2000+ items)

Posted: Fri Feb 29, 2008 8:52 pm
by Heathen
I'm having a little problem. In my program I am using a listicon with large images, but I'm finding that on some computers it goes EXTREMELY slow after about 2,000 items. Basically, it would freeze the program. This doesn't happen on my computer as it has pretty high specs, but it happens on slower computers, such as my buddy's laptop. It's really important that I can support a very large list. I was wondering if it's possible to do some sort of optimizations to perhaps load each image in the list on the fly? Or something to that extent? Also, has anyone else bumped into this problem?


Thanks in advance.

Posted: Fri Feb 29, 2008 9:06 pm
by Rook Zimbabwe
The smaller the image the less the problem.

What is the memory and graphics processor of your buddys laptop?
What CPU )pII, pIII etc( ?
8)

Also what size are the image files? Are they consistent?
What format the image files?

Any info would be helpful.

Posted: Fri Feb 29, 2008 9:39 pm
by rsts
Have you watched memory usage?

cheers

Posted: Fri Feb 29, 2008 9:50 pm
by Heathen
Yes, I have watched memory usage, it has worried me a bit, it doesn't rise above 50 megs though.. yet.... The image sizes are all identical size (32x32). What I was thinking was perhaps using a window callback to load only the visible icons and unload the non visible icons, perhaps I can also do the same for the text following the icon. Just not sure how I would do this.
What is the memory and graphics processor of your buddys laptop?
What CPU )pII, pIII etc( ?
Not sure of the specs, I'll ask him later
Also what size are the image files? Are they consistent?
Yes, 32x32
What format the image files?
Not sure why that matters, but they are grabbed from a larger tileset, which is PNG.


Thanks for the responses :)

Posted: Fri Feb 29, 2008 10:17 pm
by rsts
I believe rendering 2000+ images from scratch would be a little time comsuming. When I open a directory of lots of images in preview mode, it takes a little while for them all to be available.

Where are they coming from? I wouldn't think disk would be a problem, but on an older slower machine it could have an impact.

You might consider rendering in a thread?

I'm sure the real experts will have some tips. Good luck :)

cheers,

Posted: Fri Feb 29, 2008 10:32 pm
by Fluid Byte
You could use the loading style like in Windows for folders with thumbnail view. The 2000+ items are added right from the beginning. So you have two options now:

1.) Thread Rendering:

In order that the GUI won't freeze and still reacts on user input load all images in the background till it's done and destroy the thread.

2.) Onthefly Rendering:

You calculate how many and wich items are currently in the clipping rect of the gadget and then load the images acordingly.

Posted: Fri Feb 29, 2008 10:34 pm
by Rook Zimbabwe
OK so I ask questions... these are PNG, nice format... lossless...
I am thinking you have an ALPHA layer for transparency maybe?

Have you considered JPG?

I know a 32X32 png on my system with NO ALPHA is 1.93k and the exact same JPG is 2.1k... Hmmmm let me cut the PNG to 256 colors and see that as well...

256color PNG at 32X32 is 1.71k... slight savings...

so 2000 of those would take up 3420k more or less.

3.42mb? I must have dropped a 0 somewhere! :D

Also are all the images the same? As I read this it seems to me the answer must be yes.

You could just load one image and copy it to all new images.

:D

You know this would be a good time to query srod if his esGrid can handle your tasks!

http://www.purebasic.fr/english/viewtopic.php?t=26647

Posted: Fri Feb 29, 2008 11:05 pm
by Heathen
Fluid Byte wrote:You could use the loading style like in Windows for folders with thumbnail view. The 2000+ items are added right from the beginning. So you have two options now:

1.) Thread Rendering:

In order that the GUI won't freeze and still reacts on user input load all images in the background till it's done and destroy the thread.

2.) Onthefly Rendering:

You calculate how many and wich items are currently in the clipping rect of the gadget and then load the images acordingly.
Thanks again for the responses guys. I'm probably going to go with #2 to load and unload the images on the fly, I'm going to fiddle with my code and see if I can figure it out.

Posted: Sat Mar 01, 2008 6:32 am
by Heathen
Can someone tell me how I could get the range of items which are currently visible?

Posted: Sat Mar 01, 2008 6:52 am
by Rook Zimbabwe
Well you should be able to see which items are currently selected, but I have been having problems keeping the ListIconGadget set on the last line entered, can't even make that work.

Only thing I can think of is to add 1 to the listicongadget with SetGadgetItemData() by keeping tabs on the #PB_EventType_Change in Event... then you have to assume that is the number of the gadget at the TOP of the ListIconGadget... and ADD your lines displayed from there and display with: SetGadgetItemState() with that number as your new index start...

But I am probably wrong

Quick Question:

Are you using CatchImage(#PB_Any, MemoryAddress) to create copies of this image?

Here I used 3000 48X48 jpg images... works well...

Code: Select all

   ; Shows possible flags of ListIconGadget in action...
  UseJPEGImageDecoder()
      If LoadImage(0, "resQ0.jpg")     ; change path/filename to your own 32x32 pixel image
      EndIf
      
  If OpenWindow(0, 0, 0, 640, 300, "ListIconGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
    ; left column
        ListIconGadget(5, 10, 10, 620, 165, "", 200,#PB_ListIcon_GridLines)
    ; Here we change the ListIcon display to large icons and show an image

      ChangeListIconGadgetDisplay(5, 0)
      ; AddGadgetItem(5, 1, "Picture 1", ImageID(0))
      For X = 0 To 3000 ; change number to test start with 100, then 500, then 1000, then 1500, 2000 3000 etc
      AddGadgetItem(5, x, "Picture "+Str(x), ImageID(0))
     Next X 

    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf
8) Change the number where indicated and maybe compile different versions of this and test your buddies computer with different image number versions.

Posted: Sat Mar 01, 2008 7:22 am
by Rook Zimbabwe
A slightly more complex way:

Code: Select all

Enumeration
#Window_0
#Text_Selected
#LI_0
EndEnumeration

Global Window_0, ListIcon_0, Text_0, Button_0

Structure VisualDesignerGadgets
  Gadget.l
  EventFunction.l
EndStructure

Global NewList EventProcedures.VisualDesignerGadgets()

  UseJPEGImageDecoder()
      If LoadImage(0, "resQ0.jpg")     ; change path/filename to your own 32x32 pixel image
      EndIf

Procedure LI_0_Event(Window, Event, Gadget, Type)
  Debug "#LI_0"
  SetGadgetText(#Text_Selected, "")
    Result = GetGadgetState(#LI_0)
      parsley$ = GetGadgetItemText(#LI_0, Result,0)
        SetGadgetText(#Text_Selected, parsley$)
EndProcedure


Procedure RegisterGadgetEvent(Gadget, *Function)
  
  If IsGadget(Gadget)
    AddElement(EventProcedures())
    EventProcedures()\Gadget        = Gadget
    EventProcedures()\EventFunction = *Function
  EndIf
  
EndProcedure

Procedure CallEventFunction(Window, Event, Gadget, Type)
  
  ForEach EventProcedures()
    If EventProcedures()\Gadget = Gadget
      CallFunctionFast(EventProcedures()\EventFunction, Window, Event, Gadget, Type)
      LastElement(EventProcedures())
    EndIf
  Next
  
EndProcedure

Procedure Open_Window_0()
  
  Window_0 = OpenWindow(#Window_0, 5, 5, 400, 408, "Window 0",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
  If Window_0
    If CreateGadgetList(WindowID(#Window_0))
      ListIconGadget(#LI_0, 10, 10, 370, 290, "Column1", 100, #PB_ListIcon_GridLines)
      RegisterGadgetEvent(#LI_0, @LI_0_Event()) 
      ChangeListIconGadgetDisplay(#LI_0, 0)
      TextGadget(#Text_Selected, 10, 310, 370, 20, "", #PB_Text_Center | #PB_Text_Border)
      ButtonGadget(#PB_Any, 10, 340, 370, 40, "BIG FAKE BUTTON")
      
    EndIf
  EndIf
EndProcedure

Open_Window_0()

      For X = 0 To 3006 ; change number to test start with 100, then 500, then 1000, then 1500, 2000 3000 etc
      AddGadgetItem(#LI_0, x, "Picture "+Str(x), ImageID(0))
     Next X 
     
Repeat

  
  Event  = WaitWindowEvent()
  Gadget = EventGadget()
  Type   = EventType()
  Window = EventWindow()
  
  Select Event
    Case #PB_Event_Gadget
      CallEventFunction(Window, Event, Gadget, Type)
      
  EndSelect
  
Until Event = #PB_Event_CloseWindow

End
Well thats all I got on that! You can reference the selected to open a file or do something etc.

8)

Posted: Sat Mar 01, 2008 7:49 am
by Heathen
What I'm hoping for is an elegant solution using #LVM messages in order to get the top visible item. The only solution I have found is #LVM_GETTOPINDEX, but that supposedly only works when not using icons.

Posted: Sat Mar 01, 2008 3:06 pm
by Rook Zimbabwe
Well you can store a value in the Gadget (like the position, and retrieve it as well... It will never show to the user.

Let me monkey with my code a second or two...
8)
Well I think you have discovered a new feature request.

I did this to my LI_0 procedure

Code: Select all

Procedure LI_0_Event(Window, Event, Gadget, Type)

Select Type
      Case #PB_EventType_Change
      value = value + 3
        Debug "VALUE: "+Str(value) 
EndSelect

  SetGadgetText(#Text_Selected, "")
    Result = GetGadgetState(#LI_0)
      parsley$ = GetGadgetItemText(#LI_0, Result,0)
        SetGadgetText(#Text_Selected, parsley$)

            SetGadgetItemData(#LI_0, 1, Value)

EndProcedure
The Select Type section does work, but ONLY if an item is clicked on by the user... Apparently just dragging the scrollbar is not enough to trigger a change.

So the List is one giant entity.

I suppose the feature request woudl be a way to get the TOP line and the BOTTOM line of a ListIcon_Gadget that are displayed.

@srod! Does eGrid tell you that?

If he doesn't answer you might ask him on the eGrid thread!
8)

Posted: Sat Mar 01, 2008 5:35 pm
by srod
EsGRID is a listicon in report mode, so I don't think it would help out here.

Posted: Sat Mar 01, 2008 7:37 pm
by Fluid Byte
By the way, do you disable redrawing before you add the items?