Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the fastest GDI+ rendering settings?

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 :

  • 1650 call to DrawLine
  • 6600 call to FillEllipse
like image 627
Cyril Gandon Avatar asked Nov 30 '11 14:11

Cyril Gandon


People also ask

Is GDI+ faster than GDI?

Unfortunately, it is slower than GDI. It's very powerful though.

Is GDI+ fast?

Everyone knows GDI+ is generally slow in rendering, what is not so obvious is what combination of settings is the fastest. I have an app which renders a lot of items, which may be drawn or are bitmap-sourced 'sprites', onto a full page (usually 1024x768). The first attempts ran at around 3...

What is GDI render?

GDI renders opaque, aliased geometries such as polygons, ellipses and lines. It renders aliased and ClearType text, and it can support transparency blending through the AlphaBlend API.

Is GDI still used?

GDI isn't going anywhere, so if you need something rock-solid that is guaranteed to be supported anywhere and everywhere, that's what I would go with. If you need a bit more 2D capabilities than GDI offers (e.g., alpha channel transparency), then you could consider using GDI+.


2 Answers

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)

like image 64
Jason Williams Avatar answered Oct 12 '22 06:10

Jason Williams


For drawing images, turn to low quality:

img = new Bitmap(img, w / 2, h / 2);
like image 39
isaque Avatar answered Oct 12 '22 08:10

isaque