What are the fastest GDI+ rendering settings?

Cyril Gandon picture Cyril Gandon · Nov 30, 2011 · Viewed 8.5k times · Source

There is quite a lot of post about rendering high quality graphics, like this one

High Quality Image Scaling Library

I need to render about 6k+ object (line and ellipse) in a graphics with GDI+, at a framerate of around 10fps. So I need the lowest quality property possible for my graphics.

Here is what I have done :

public static class GraphicsExtensions
{
    public static void ToHighQuality(this Graphics graphics)
    {
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
    }

    public static void ToLowQuality(this Graphics graphics)
    {
        graphics.InterpolationMode = InterpolationMode.Low;
        graphics.CompositingQuality = CompositingQuality.HighSpeed;
        graphics.SmoothingMode = SmoothingMode.HighSpeed;
        graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
        graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
    }
}

Did I forgot something, or is this the best possible extremum for the property of Graphics?
I'm drawing at 5fps (202ms/image) with the lower mode, and 3fps (330ms/image) with higher mode.
I don't feel there is a big difference, but I have reduce my performance problem to drawing only...

Some Numbers :

Answer

Jason Williams picture Jason Williams · Nov 30, 2011

GDI+ is not a high performance rendering solution. p/invoke to GDI or use DirectX directly if you want better raw performance. However, getting a 2x speed-up is usually quite achievable by just optimising the redraw a bit:

Do you really need to draw all that much? Would the image still work ok with some elements removed?

Are you creating and destroying lots of pens and brushes, or are you reusing a few predefined ones? Is there any processing you're doing to build or transform the shapes that you can do in a preprocessing step so that it isn't repeated unnecessarily during the redraw?

Are you drawing anything unnecessary? Cull (discard) anything that is offscreen. If a lot of overdrawing is occurring (very likely with 6000 objects), it may be possible to detect and discard shapes that are wholly obscured by things in front of them.

Can you combine many lines into a single polyline? Every function call adds overhead, so if you can draw several shapes or lines with a single function call, it'll run faster.

Do you have to use ellipses? If they're small you may get better performance with an 8 or 12-sided polygon without noticeable drop in the quality of the shape - worth trying to see.

Optimise repetition. If the shapes are regular (e.g. you're drawing lots of 10-pixel circles in the same colour) then draw one to a bitmap and then blit the copies. If there's a regular pattern (e.g. a checkerboard) then draw a small section of it to a bitmap and blit the section to repeat it across your image. (Just make sure you draw the bitmaps unscaled and that they match the screen (dpi and bpp) so you get the fastest type of blit and don't end up with a slow bilinear-filtered blurry mess)

If there are many colour changes, might you be able to batch them together so that you draw all the red things then all the blue things etc - this avoids switching between pens/brushes a lot.

Sometimes you can gain by avoiding clipping - e.g. if you're drawing text and you know it'll all be visible, you can draw with clipping disabled. (This used to provide a performance benefit - it may not help with hardware accelerated rendering, but it's worth a try)

Lastly, remember that with hardware acceleration, you may not gain by disabling some rendering features. If the graphics card is capable of drawing 10,000 ellipses at 500 frames per second but you are only seeing 10 fps, then disabling antialiasing probably won't help your frame rate - the bottleneck is more likely to be your code and GDI+ taking a long time to tell the graphics card what to render rather than the graphics rendering itself being slow. (YMMV - this will depend on what you are rendering, how GDI+ handles it, whether it is hardware accelerated, what the graphics driver does with it, and how powerful your graphics card is)