代码之家  ›  专栏  ›  技术社区  ›  AZ.

使用GDI+快速绘制不同颜色线条的方法?

  •  4
  • AZ.  · 技术社区  · 16 年前

    我有一个点的动态列表,可以随时添加新点。我想用不同的颜色画线来连接它们。颜色基于这些点的索引。代码如下:

        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]);
            }
        }
    

    我发现当我有新的点以高速进入时,这种方法不够快。有没有办法让它更快?我做了一些研究,有人说使用GraphicsPath可能会更快,但怎么做呢?

    1. 使用GrahpicsPath, Original Question
    2. 更改图形质量(例如SmoothingMode/PixelOffsetMode…),也可以调用SetClip指定要渲染的唯一必要区域。
    7 回复  |  直到 9 年前
        1
  •  5
  •   Jason Williams    16 年前

    使用路径的想法是将许多(在您的示例中为20)行批处理到单个方法调用中,而不是调用DrawLine 20次。只有在可以将输入数据排列为绘图例程的正确点列表格式时,这才会对您有所帮助。否则,您将不得不将点复制到正确的数据结构中,这将浪费大量通过批处理到路径中获得的时间。在DrawPath的情况下,可能必须从点阵列创建GraphicsPath,这可能不会节省时间。但是,如果您必须多次绘制同一条路径,您可以缓存它,然后您可能会看到一个净好处。

    如果将新点添加到列表中,但未删除旧点(即,您始终只是将新线添加到显示中),则可以使用屏幕外位图来存储迄今为止渲染的线。这样,每次添加一个点时,您都可以进行绘制 线,而不是每次都画80条线。

    这完全取决于你想做什么。

        2
  •  2
  •   Oliver    16 年前

    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]);
    }
    
        3
  •  1
  •   codekaizen    16 年前

    这与System.Drawing的速度差不多。您可能会看到使用 Graphics.DrawLines() ,但您需要以不同的格式设置数据,以获得使用同一支笔同时绘制一组线的优势。我很怀疑 GraphicsPath 会更快。

    提高速度的一个可靠方法是降低输出的质量。设置 Graphics.InterpolationMode InterpolationMode.Low , Graphics.CompositingQuality CompositingQuality.HighSpeed , Graphics.SmoothingMode SmoothingMode.HighSpeed , Graphics.PixelOffsetMode PixelOffsetMode.HighSpeed Graphics.CompositingMode CompositingMode.SourceCopy

    我记得有一次速度测试,有人在GDI例程中比较了图形和P/Invoke,并对更快的P/Invoke速度感到非常惊讶。你可以去看看。我看看能不能找到那个比较。。。 显然,这是为紧凑型框架设计的,所以它可能不适用于PC。

    另一种方法是使用Direct2D,如果您有合适的硬件,它可以比GDI更快。

        4
  •  1
  •   user446264    15 年前

    我创建了一个小型库GLGDI+,它使用类似(但不是完全/相等)的GDI+语法,在OpenTK上运行: http://code.google.com/p/glgdiplus/

    我不确定它的稳定性,它在DrawString方面有一些问题(OpenTK的文本打印问题)。但是,如果您的实用程序需要性能提升(就像我的例子中的level editor),它可以是一个解决方案。

        5
  •  0
  •   John Leidegren    16 年前

    您可能想查看画笔对象,确实GDI+程序无法获得接近实时的性能,但只要对象的几何体和数量保持在合理的范围内,您就可以轻松地保持良好的fps。至于画线,我不明白为什么不行。

    但是如果你达到了你认为最理想的程度,那就是画线。。你应该考虑一个不同的图形栈,如果你喜欢.NET,但是与OpenGL和DirectX之类的非托管API有问题,去WPF或Silverlight,它是非常强大的。

    无论如何,您可以尝试设置System.Drawing.Drawing2D.GraphicsPath,然后使用System.Drawing.Drawing2D.PathGradientBrush以这种方式应用颜色。这是一个单缓冲draw调用,如果您不能从中获得足够的性能。你将不得不完全使用GDI以外的东西+

        6
  •  0
  •   peSHIr    16 年前

    根本不是GDI(+),但解决这个问题的一种完全不同的方法可能是使用一块内存,在其中画线,将其转换为 Bitmap 对象立即绘制需要显示线条的位置。

    当然,这在很大程度上取决于快速实现目标的方法

    • 在内存中绘制给定颜色的线表示选择和
    • 将其转换为 位图 展示。

    我想不是在.NET框架中,而是在第三方库中?不是有一个 bitmap writer

    至少这可能是一种开箱即用的方法。希望能有帮助。

        7
  •  0
  •   prashant    16 年前

    还有一件事,如果在onPaint()中编写绘图线代码会更好。

     just override onPaint() method it support better drawing and fast too.
    
    推荐文章