Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Bitmap performance

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?

like image 737
Avi Avatar asked Feb 13 '12 18:02

Avi


Video Answer


2 Answers

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.

like image 76
H.B. Avatar answered Oct 06 '22 11:10

H.B.


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.

like image 45
Avi Avatar answered Oct 06 '22 11:10

Avi