Note that there are some explanatory texts on larger screens.

plurals
  1. POBitmap Performance-Optimization Patterns
    primarykey
    data
    text
    <p>I found several patterns for optimizing Bitmaps handling in WPF. I do not, however, understand when to use each patterns. As I think this is a common problem, I summarized what I understand and what I guess and ask for your help. If you can <strong>add patterns</strong>, explain <strong>how they differ</strong>, explain if they use the <strong>CPU or the GPU</strong>, and teach <strong>when to use each</strong> and <strong>how to combine them</strong>, it’d be a tremendous help!</p> <p><strong>Context – the Images "Grid" Scenario:</strong> </p> <p>My application has to display many bitmap images. The images are displayed on the screen in a rows-and-columns grid-like organization (not necessarily the Grid or UniformGrid classes, think Window Media Player’s Album view). Images might move between different grid cells. Some images at arbitrary cells may be replaced by others. Images should be clickable, should provide a context menu, should be selectable, drag-able etc. In other words, “combine the little buggers into one big bitmap” is not applicable, at least not naively.</p> <p><strong>Pattern 0: The Hack</strong></p> <p>Do combine the little buggers into a bitmap (how? drawing context?), and use this as the background. Overlay this with images with empty content that will handle the hits, context menus, events etc.</p> <p>The advantage is that we're only speaking about two bitmaps here: The currently displayed one and the one that should replace it. This should be really fast. However, my years of experience raise the red flag of danger. Your comments?</p> <p><strong>Pattern 1: Reduce Image Size</strong></p> <p>This is a no-brainer when you know in advance the image size to resize to, and when you’re prepared to lose details (color) for performance:</p> <ol> <li>Reduce the bitmap size using BitmapImage.DecodePixelWidth</li> <li>Reduce the color information using FormatConvertedBitmap.DestinationFormat</li> <li>Set the control’s scaling behavior setting Image.Stretch to Stretch.None</li> <li>Set the SetBitmapScalingMode for the image to LowQuality.</li> <li>Freeze the bugger </li> </ol> <p>See code <a href="https://stackoverflow.com/questions/9265725/wpf-bitmap-performance/9265863">here</a>.</p> <p><strong>Pattern 2: Background pre-fetch</strong></p> <p>This pattern is applicable when you think you can take advantage of the user gazing at the images on the screen, and prepare ahead the next images to display. The cons for your project, in addition to the memory overhead, is that it has to support the .Net Framework 4 target and not just the client profile, so it might incur an installation on the client’s. You yourself will have to suffer the async programming pain.</p> <p>In this pattern you create exactly the required number of Image controls. When bitmaps need to be added, moved or deleted you only modify the Image controls' BitmapSource(s). A BackgroundWorker task is responsible for pre-fetching the BitmapSource(s) (possibly using the “Reduce Image Size” pattern above) and inserting them into MemoryCache. </p> <p>For this to work you have to set the BitmapImage’s CacheOption to OnLoad, so that the work is off-loaded to the background worker.</p> <p><strong>Pattern 3: Drawing Context</strong></p> <p>This was suggested by Sheldon Ziao from Microsoft Support on the MSDN WPF forum <a href="http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b9300929-e32f-4c0c-a871-3e5a45fd5841" rel="nofollow noreferrer">here</a>. See page 494, Chapter 15 “2D Graphics” in Adam Nathan’s WPF 4 Unleashed for a description of DrawingContext. I can’t say I understand it. According to the answer <a href="https://stackoverflow.com/questions/2319365/performance-of-drawingvisual-vs-canvas-onrender-for-lots-of-constantly-changing">here</a>, I would assume this would improve handling of Geometry drawings, not bitmaps. Next, I don’t think this will support the focus and events requirements for the images (my bad for not explaining the requirements better at the forum) Moreover, I’m worried by the book’s summary sentence: “Note that the use of DrawingContext doesn’t change the fact that you’re operating within a retained-mode system. The specified drawing doesn’t happen immediately; the commands are persisted by WPF until they are needed.” This means that once our even handler re we can’t take advantage of parallelism as in “Background pre-fetch”.</p> <p><strong>Pattern 4: Writeable Bitmaps</strong></p> <p>The MSDN documentation <a href="http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.aspx" rel="nofollow noreferrer">here</a> describes it as a dual buffer system: Your UI thread updates the buffer; the WPF’s render thread moves this to video memory.</p> <p>The intended usage (see <a href="http://www.i-programmer.info/programming/wpf-workings/527-writeablebitmap.html" rel="nofollow noreferrer">here</a>) is for bitmaps that change a lot such in a video movie like display. I’m not sure, but possible this could be hacked and combined with the Background Pre-fetch pattern and used in the grid scenario.</p> <p><strong>Pattern 5: Cached Bitmap</strong></p> <p>Not much info on the MSDN (<a href="http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.cachedbitmap.aspx" rel="nofollow noreferrer">here</a>). On the WPF forum archive (<a href="http://social.msdn.microsoft.com/Forums/en/wpfprerelease/thread/e2ebf264-e087-4bfe-a69b-24c884675c80" rel="nofollow noreferrer">here</a>) it’s explained that “The BitmapCache API is designed to cache your content (when rendering in hardware) in video memory, meaning it stays resident on your GPU. This saves you the cost of re-rendering that content when drawing it to the screen.” This seems like a great idea. I’m not sure, however, what are the pitfalls and how to use it.</p> <p><strong>Pattern 6: RenderTargetBitmap</strong></p> <p>The RenderTargetBitmap converts a Visual to a bitmap. I’m not sure if it’s relevant here. See <a href="http://blogs.msdn.com/b/jaimer/archive/2009/07/03/rendertargetbitmap-tips.aspx" rel="nofollow noreferrer">here</a>.</p> <p><strong>Edit</strong>: Regarding Paul Hoenecke question: I've written that "My application has to display many bitmap iages". I failed to mentions that I need to display about 800 images <strong>concurrently</strong>.</p> <p>One can read about the performance issues involved at my SO questions <a href="https://stackoverflow.com/questions/9265725/wpf-bitmap-performance">WPF Bitmap performance</a> and <a href="https://stackoverflow.com/questions/8960110/how-can-i-make-displaying-images-on-wpf-more-snappy">How can I make displaying images on WPF more “snappy”?</a></p> <p>I've modified the description of pattern 1 to highlight the concept that the image controls aren't created or deleted (unless we want to display a larger or smaller grid). Only their Sources are set to different, new or null BitmapSources.</p> <p><strong>Edit</strong>: <a href="http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/d4d3f245-fbfd-4d52-944c-1b971c9a5b0f" rel="nofollow noreferrer">This question as posted on the WPF support forum</a>, with some answers from MS personnel.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. COHow many images are you anticipating? I have made an app that shows a grid of thousands of images before. We used a virtual-mode listbox; as the user scrolls down, the images are loaded in a background thread, frozen and set to the Source of the Image. Clearly, you have put a lot of thought into this... but, maybe knowing more about exactly what you want to accomplish would be better. For example, what problems have you had that make optimizing such a priority?
      singulars
    2. CO@PaulHoenecke Hi Paul, thank you for your answer. The virtual collections help you when you want to display a small number of items out of a large collection. Here, I want to display about 1K items concurrently. Additionally, I'm not sure there exists a virtualizing grid. Lastly, pattern 1 is essentially virtualizing - I'll add en edit.
      singulars
    3. COAvi, your question looks inappropriate for the described problem. You may want to improve compression ratio for some reason, but then you need to know exactly what kind of images you are displaying. Or, on the other hand, you may want give the user an impression of all the images available, then you might define some sets and display thumbnails or alike. But both things don't have necessarily to do with each other. Maybe you want something like a similarity metric to define sets of look alike images?
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload