tags:

views:

66

answers:

5

I need to load 101 bitmaps from the filesystem (they can't be built into the app as a resource as they will be changed for each run of the program) into a windows form application picturebox sequentially based on short duration timer events (500ms give or take) .

Essentially it should work like a slow animation but it is critical that every image be shown.

I've roughed out a simple application in C# to do this however it seems that the image loading and displaying is taking longer than the 500ms so some images are never displayed.

Is there some way I can avoid this? Preloading or creating 101 pictureboxes and showing and hiding?

Anybody have any suggestions?

A: 

Populate an array of Bitmap objects before starting the animation.

SLaks
A: 

I don't have a concrete answer for you, but I would approach this by first determining if it's image loading, image display, or both actions that are taking too much time.

I would imagine that image loading is going to be relatively quick, even with pretty large image sizes, provided that the images are local and you have relatively decent hardware. My first attempt would involve loading all images from a thread sequentially so that you application doesn't have to wait for image display to complete before the next image loads.

If image display is taking a long time (and even on my really powerful workstation it's not all that fast for large images), then is it possible for you to scale the images before the application displays everything? Does your application need to deal with full resolution images? With the megapixel cameras these days, I can't image that you'd want to have all of the data present in the image files anyway, since the sizes can easily exceed monitor resolutions by a factor of 6.

Dave
+1  A: 

What's taking the longest? Image loading or displaying? Are you loading each image when it needs displaying? A look at your code would be really valuable.

If you are certain that it will always be exactly 101 images, load them all into an array of System.Drawing.Bitmap first then have an iterator variable that gets incremented on each call of the Tick event of a Timer. Have this Tick event load the image from the array into the PictureBox using PictureBox.Image = myBitmapArray[iterator] If you increment the iterator using ++i%=101; you won't get an OutOfBounds error and the animation will loop.

Origamiguy
A: 

Another thing that may be a concern is the size of the images. If the are all 18 Megapixel Images, I can see it taking either a lot of time or a lot of room.

You may want to resize them to the size of your display area when you initially load them up so that you aren't using 2 gigs of ram or waiting to read off the disk depending on how you implement it.

Blankasaurus
+1  A: 

A couple of options... pick one or combine them:

(1) Use a lock and a counter to guarantee that when the event fires it's loading the next image in line.

(2) Disable the timer in the Tick event, then re-enable it after you've loaded the image. The result is that the images arrive 500ms after the last one is drawn, so if a picture takes one second to load, the images are drawn at t=1000ms, t=1500ms, t=3000ms, etc. All the images are drawn, and 500ms is guaranteed to pass between pictures, but the animation might appear slow.

(3) Do the above, but track the time the event starts, and after the image is drawn, set the next timer tick to be 500 - (Now - eventStart)... so that if the image takes 250ms to draw, the next timer tick will fire in 250ms. If Now - eventStart < 0, the next timer tick should fire immediately. The animation will take the minimum amount of time possible, but images could potentially flash by, appearing only for a few milliseconds.

(4) Use PictureBox.LoadAsync() to give you some multi-threading... the next event can be loading the image while the previous event is drawing. But you'll need a Mutex that you release in the LoadCompleted event that you wait on before calling LoadAsync(), if you need to guarantee the images are all drawn.

(5) I'm not sure if the drawing of the picture falls under the Layout category, but you can try calling SuspendLayout() and ResumeLayout() before/after loading the image

(6) Use an array of images, lock a counter, and use the .Image property of the PictureBox to let you pre-load the images. I believe this was suggested in another answer, also

HTH,
James

James B