Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fast way to draw lines using different Color using GDI+?

Tags:

c#

.net

gdi+

I have an dynamic List of Point, new Point can be added at any time. I want to draw lines to connect them using different color. Color is based on the index of those points. Here is the code:

    private List<Point> _points;
    private static Pen pen1 = new Pen(Color.Red, 10);
    private static Pen pen2 = new Pen(Color.Yellow, 10);
    private static Pen pen3 = new Pen(Color.Blue, 10);
    private static Pen pen4 = new Pen(Color.Green, 10);

    private void Init()
    {
        // use fixed 80 for simpicity
        _points = new List<Point>(80);

        for (int i = 0; i < 80; i++)
        {
            _points.Add(new Point(30 + i * 10, 30));
        }
    }

    private void DrawLinesNormal(PaintEventArgs e)
    {
        for (int i = 0; i < _points.Count-1; i++)
        {
            if (i < 20)
                e.Graphics.DrawLine(pen1, _points[i], _points[i + 1]);
            else if (i < 40)
                e.Graphics.DrawLine(pen2, _points[i], _points[i + 1]);
            else if (i < 60)
                e.Graphics.DrawLine(pen3, _points[i], _points[i + 1]);
            else
                e.Graphics.DrawLine(pen4, _points[i], _points[i + 1]);
        }
    }

I find this method is not fast enough when I have new points coming in at a high speed. Is there any way to make it faster? I did some research and someone said using GraphicsPath could be faster, but how?

[UPDATE] I collect some possible optimizations:

  1. Using GrahpicsPath, Original Question
  2. Change Graphics quality ( such as SmoothingMode/PixelOffsetMode...), also call SetClip to specify the only necessary region to render.
like image 808
AZ. Avatar asked Jan 23 '23 18:01

AZ.


2 Answers

You won't be able to squeeze much more speed out of that code without losing quality or changing to a faster renderer (GDI, OpenGL, DirectX). But GDI will often be quite a bit faster (maybe 2x), and DirectX/OpenGL can be much faster (maybe 10x), depending on what you're drawing.

The idea of using a Path is that you batch many (in your example, 20) lines into a single method call, rather than calling DrawLine 20 times. This will only benefit you if you can arrange the incoming data into the correct list-of-points format for the drawing routine. Otherwise, you will have to copy the points into the correct data structure and this will waste a lot of the time that you are gaining by batching into a path. In the case of DrawPath, you may have to create a GraphicsPath from an array of points, which may result in no time saved. But if you have to draw the same path more than once, you can cache it, and you may then see a net benefit.

If new points are added to the list, but old ones are not removed (i.e. you are always just adding new lines to the display) then you would be able to use an offscreen bitmap to store the lines rendered so far. That way each time a point is added, you draw one line, rather than drawing all 80 lines every time.

It all depends on exactly what you're trying to do.

like image 139
Jason Williams Avatar answered Jan 25 '23 09:01

Jason Williams


Doesn't really help to improve performance, but i would put the pens also into a list and writing all this lines in this way:

int ratio = _points.Count / _pens.Count;

for (int i = 0; i < _points.Count - 1; i++)
{
    e.Graphics.DrawLine(_pens[i / ratio], _points[i], _points[i + 1]);
}
like image 32
Oliver Avatar answered Jan 25 '23 09:01

Oliver