Reputation: 8033
I'm currently working on an app that allows the user to play (automatically scroll) through a series of local images. Usually there will be five or six on screen at once.
The major bottleneck at the moment seems to be the actual loading of the image data from disk. A timer thread calls for the images to be updated every 1/6 of a second and the app is struggling to keep up with that speed. Each image is around 25Kb.
I tried creating a rolling cache to try and preload images but this was also getting caught up with itself so ended up slowing down just as much.
Every beat of the timer, I'm looping through the six image placeholders loading the next image using the standard
Image img = Image.FromFile("filename");
method but thought someone might know of a faster way to get the images off disk.
There are between 500 and 20,000 images in each of the six sets so it's too large to load the whole thing into memory at the start.
If anyone has suggestions for a faster way to pull these images through, it would be greatly appreciated.
Edit to add some more detail of application flow.
Okay, this is what's happening:
User hits 'play' button. Timer thread starts with 1/6 second timeout.
Timer callback:
Update image index (_index++)
for each viewer in list of visible viewers (the forms to display images)
{
get the filename from the id stored in the viewer
check to see if the file exists
if it does exist,
create new bitmap from image
and return that image
otherwise return null
if returned image isn't null, display it on screen
}
That's obviously going across a few layers - the image loading goes on in the services layer and then passes this through to presentation and then to the UI but that's the gist of what's happening.
Upvotes: 9
Views: 11305
Reputation: 6310
I came across this page which describes how to use the GDI+ API directly to load images. Very simple to use:
ImageFast.FromFile(@"C:\MyPhoto.JPG");
Added to show speed of ImageFast over Image From File method
This uses the source code found here. The code was copied and pasted and required no changes.
Stopwatch watch = Stopwatch.StartNew();
string filePath = @"C:\TestImage25k.png";
Image fromFile = Image.FromFile(filePath);
watch.Stop();
Console.WriteLine("Image.FromFile Ticks = {0:n}", watch.ElapsedTicks);
long fromFileTicks = watch.ElapsedTicks;
watch.Reset();
watch.Start();
Image fastImage = ImageFast.FromFile(filePath);
watch.Stop();
long fastFileTicks = watch.ElapsedTicks;
Console.WriteLine("ImageFast.FromFile Ticks = {0:n}", watch.ElapsedTicks);
Console.WriteLine("fromFileTicks - fastFileTicks = {0:n}", fromFileTicks - fastFileTicks);
The console output was
Image.FromFile Ticks = 19,281,605.00 ImageFast.FromFile Ticks = 7,557,403.00 fromFileTicks - fastFileTicks = 11,724,202.00
You can see the impact of the ImageFast. Over time those 11 million saved ticks will add up.
Upvotes: 11
Reputation: 71
I think concept of double buffering will be useful. Set "Double Buffer" property of the form to True. This will help you little bit. Following links may be useful to you
Upvotes: 1
Reputation: 47751
Check out the concept of double buffering. What you want to be doing is have a second thread that can be loading the next set of images while you are displaying the first set. Once the 1/6 time gate hits, you switch the one set of images out and start loading the next set.
Upvotes: 1
Reputation: 35721
i would probably create a background thread to continously fetch all the images from disk (keeps the ui responsive) and then publish each newly loaded image via an event
Upvotes: 0
Reputation: 456
If you have 6 images displayed at once, and you change them all every 1/6 of a second, you should be running into performance issues. Loading 150 kb from disk should be a trivial activity even without caching. It sounds like you may be overdoing the file loads. Are you sure you are only loading 6 images at a time? Are you reading images from disk that are not displayed?
If you can you provide a little more detail of the application flow, I may be able to be a little more helpful.
Upvotes: 0
Reputation: 200
Easiest might be to put a 'next' and 'previous' button to limit the number of images and preload.
Upvotes: 1