8

I'm trying to understand why my images are not snappy, so I built a sample to test WPF performance. I used a timer to calculate how long my "display images" event handler executed, and used a stop watch to measure how long it took the images to appear on the screen. The bottom line: when displaying 100, 1600, 2500 and 3600 images, WPF took 2, 9, 12 and 16 seconds after my code had finished to display the images on the screen. So I feel helpless: It seems I can't improve my code to make the images appear faster - I need to do something with WPF!

So my question is: What do I need to do differently to make the images display faster?


The test setup is simple:

The window contains a Grid. After the "test" button is clicked, row and column definitions are added.Then an Image is added to each cell of the grid as follows:

            var image = new Image();
            image.BeginInit();
            image.Name = ImageNameFromCell(theRow, theColumn);
            image.Stretch = Stretch.None;
            image.HorizontalAlignment = HorizontalAlignment.Center;
            image.VerticalAlignment = VerticalAlignment.Center;
            RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.LowQuality);
            image.EndInit();

            theGrid.Children.Add(image);

Finally, the Source of each image is set to a bitmap:a gray-scale image already scaled down to the estimated screen size. The bitmap is generated as follows:

            var smallerBitmapImage = new BitmapImage();
            smallerBitmapImage.BeginInit();
            smallerBitmapImage.DecodePixelWidth = (int)(theImageWidth);
            smallerBitmapImage.UriSource = theUri;
            smallerBitmapImage.CacheOption = BitmapCacheOption.None;
            smallerBitmapImage.EndInit();

            //BitmapFrame bitmapFrame = BitmapFrame.Create(this.FullPath);

            var convertedBitmap = new FormatConvertedBitmap();
            convertedBitmap.BeginInit();
            convertedBitmap.Source = smallerBitmapImage;
            convertedBitmap.DestinationFormat = PixelFormats.Gray16;
            convertedBitmap.EndInit();
            convertedBitmap.Freeze();

So, I'm at my wits end. The images appear with a noticeable delay, and it seems to be out of my control. What can I do?

Avi
  • 15,696
  • 9
  • 39
  • 54

2 Answers2

4

What appears to have made the difference is setting the image's cache option to OnLoad

smallerBitmapImage.CacheOption = BitmapCacheOption.OnLoad;

This moved the work to my event handler, so now I can use pre-fetching to do this at the background.

Avi
  • 15,696
  • 9
  • 39
  • 54
3

Do you actually see all those images at the same time? If not you can use some ItemsControl with a virtualizing panel so only images in view are displayed. (Speaking of panels, your current setup could also be replaced with an ItemsControl which uses a UniformGrid as panel)

You could also try to write a better decoder, which probably is a wasted effort.

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Thank you for your answer, H.B. Yes, I do wish to see all of those images at the same time. The 1600, 2500 and 3600 cases were for the testing, so I could measure WPF's delay easily with a watch's seconds hand, but I'd say that 400 images is a number I'd like to support. And re the "better decoder" sugestion, I thought decoding was already done in the "smallerBitmapImage" code above, i.e. in my code and not during the time WPF does whatever it does after my event handler returns, which is the time I'm trying to shorten... – Avi Feb 13 '12 at 21:36
  • 1
    @Avi: Oh right, as the files presumably are local the decoding may happen synchronously but i am not sure about the internals; given that the conversion does not throw exceptions that assumption seems viable though. If this comes down to pure rendering time you really might be in a bind as you already seem to do everything that could speed things up from decoding to a smaller size to preventing scaling. Don't know what else you could do here :( – H.B. Feb 13 '12 at 22:24