views:

653

answers:

3

I have a winforms ImageList which contains 200 256x256 images.

When I add the images, 1 by one, half of the programs time spent on the Add method according to ANTS .NET profiler.

So the program takes 10 secs to launch and 5 is spent there. That is very slow in my opinion.

I implemented the same thing using ImageList.Images.AddRange. The result did not change.

Does anyone know any alternatives or optimizations to solve this? Is the WPF ImageList any faster? Is there a faster winforms ImageList?


EDIT:

foreach (string imageFile in images)
{
    imageList.Images.Add(Image.FromFile(imageFile)); // takes pretty much all of program's execution time.
}
+1  A: 

Are you using a ListView for the UI part using that ImageList?

The general solution to these kind of problems is to only load some of the images, because only some of them are shown at a time, and then load the other as needed. ListView has a VirtualMode property for this kind of scenarios.

Loading and adding 200 images at once may be too much to do, you could load the first shown images and then use a background thread to load the others. Have a look at how Win7 display images, it shows some placeholder when you scroll and then, when the image is loaded it shows the real picture. Be warned that this is not a simple thing to do.

Aleris
Thanks. The only thing that concerns me is I want a smooth scroll, so no placeholders popping up. I know the count can't be more than 500. So one will be able to quickly browse the images there. But it wuld work if it worked like picasa where you don't see placeholder images but yet it doesn't load all at once, when you scroll.
Joan Venge
Picasa uses prebuilded index with scaled and optimized images, so if you want to achieve similar results, you must use similar methods.
arbiter
+2  A: 

Have a look at the album and list views in PhotoSuru, one of Microsoft's WPF sample applications. They have a couple different thumbnail view screens that load pretty quickly (all the images are loaded asynchronously, and only the images necessary are loaded). And there's full source code to get you started if it's what you are looking for.

It not precisely like Picasa (they decided only to show full rows of photos instead of a partially covered row like Picasa), but by implementing your own virtualizing IScrollInfo panel (reasonably straightforward, and Ben Constable has a great series of posts on it), you should be able to get the performance you're looking for and the behaviour you want.

A final note: You might be doing this already (are your images stored as 256x256 pixel images?), but whenever you're trying to display image thumbnails, you'll want to avoid loading the full image. Reading 2 MB+ image files off of the disk just to render an entire screenful of 256x256 pixel thumbnails always has a bigger performance hit than reading an appropriately sized small thumbnail image instead. If you can, cache the thumbnails somewhere (like Windows and Picasa do), or at the very least, try to use the embedded thumbnails in any JPEG files you encounter.

Nicholas Armstrong
Thanks Nicholas. You mean I prescale images by hand? Is there a way to say "load this 2K image as a 256x256 in .net?
Joan Venge
No, you don't need to do it by hand. Image.GetThumbnailImage should be able to do it for you.
Nicholas Armstrong
A: 

try my code here to scale-down your image and make a thumbnail out of it.

murasaki5