Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
615 views
in Technique[技术] by (71.8m points)

performance - How can I make displaying images on WPF more “snappy”?

I’m writing a WPF image viewer, displaying a grid of images. I’m baffled because of the sluggish performance: Displaying even an 11 x 11 grid makes a VM unresponsive, slow and sluggish for long durations of times. Even on the powerful host the performance in non-snappy.

The program is based on the design in SO WPF: arranging collection items in a grid: An ItemsControl is bound to Items, an ObservableCollection. Each Item contains has a file-system absolute URI. The ItemsControl‘s DataTemplate contains an Image element whose Source is bound to the URI.

It seems the problem can’t be the disk (SSD), the memory (8GB VM, 24GB host), or CPU (i750). Moreover, most of the work is done by WPF, so it’s not even as if I could locate a problem in my code: My code simply loads URIs (i.e. the paths to the images, not the images) to the collection and quickly returns. Then there is a wait, and WPF displays the images.

The only problem I could think about is image processing – down scaling by WPF. But even on the host, which has a "good-enough" 5850 ATI Radeon HD card, the performance is not snappy.

So, my question is: How can I make displaying images on WPF more “snappy”?

Edit: The images are 1920x1080 22 bit HD JPEGs captured from HD m2ts video. I tried pre-scaling them (using FFmpeg) to 'ega' 640x350. There was a performance improvement but FFmpeg's scaled-down images looks much worse than WPF's.

Edit: Thanks to David Osborne the code now runs as x64. Still sluggish.

Edit What really improved the situation is what Matěj Zábsky called scalling the images: reducing the resolution. For the benefit of future readers:

            fullPath = new Uri(path, UriKind.Absolute);


            BitmapImage smallerBitmapImage = new BitmapImage();
            smallerBitmapImage.BeginInit();
            smallerBitmapImage.DecodePixelWidth = (int) (theWidthOfTheGrid / theNumberOfColumns);
            smallerBitmapImage.UriSource = fullPath;
            smallerBitmapImage.EndInit();

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

            this.ImageSource = formatConvertedBitmap;
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I have been in similar position (I had to display thumbnail versions of large images in real-time).

If you are using data binding to display the images, you can try two things:

  • Make the binding OneWay (this helped me the most).
  • Try making the binding async.

The only other thing is to prescale the images - preferably separate thread. Possibly you could even prescale images which could be potentially used in the future while the processor is idle - for example if you are developing a map-like application, you could prescale images in areas to which the user is most likely to move.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...