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

我有一个动态List of Point,可以随时添加新Point。 我想绘制线条以使用不同的颜色连接它们。 颜色基于这些点的索引。 这是代码:

private List _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(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, 原始问题
  2. 更改图形质量(例如SmoothingMode / PixelOffsetMode …),也调用SetClip指定要渲染的唯一必要区域。

在不降低质量或更改为更快的渲染器(GDI,OpenGL,DirectX)的情况下,您将无法从代码中挤出更多的速度。 但是GDI通常会快得多(可能是2倍),而DirectX / OpenGL可以更快(可能是10倍),这取决于你绘制的内容。

使用Path的想法是将许多(在您的示例中为20行)行批处理为单个方法调用,而不是将DrawLine调用20次。 如果您可以将传入数据排列为绘图例程的正确列表格式,这将只会使您受益。 否则,您必须将点复制到正确的数据结构中,这将浪费您通过批处理路径获得的大量时间。 对于DrawPath,您可能必须从点数组创建GraphicsPath,这可能导致没有时间保存。 但是如果你不得不多次绘制相同的路径,你可以缓存它,然后你可以看到净收益。

如果将新点添加到列表中,但未删除旧点(即,您始终只是向显示添加新行),那么您将能够使用屏幕外位图来存储到目前为止渲染的线。 这样,每次添加一个点时,都会绘制一条线,而不是每次都绘制所有80条线。

这完全取决于你正在尝试做什么。

没有真正帮助提高性能,但我会把笔也放到一个列表中并以这种方式写下所有这些行:

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

这与您使用System.Drawing获得的速度差不多。 使用Graphics.DrawLines()可能会看到一些增益,但是您需要以不同方式格式化数据,以便使用相同的笔一次性绘制一堆线。 我严重怀疑GraphicsPath会更快。

提高速度的一个可靠方法是降低输出质量。 设置Graphics.InterpolationModeInterpolationMode.LowGraphics.CompositingQualityCompositingQuality.HighSpeedGraphics.SmoothingModeSmoothingMode.HighSpeedGraphics.PixelOffsetModePixelOffsetMode.HighSpeedGraphics.CompositingModeCompositingMode.SourceCopy

我记得一次速度测试,有人将Graphics与P / Invoke比较为GDI例程,并且对P / Invoke速度更快的速度感到非常惊讶。 你可能会检查出来。 我会看看我是否能找到这种比较…… 显然这是针对Compact Framework的,因此很可能不适用于PC。

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

太晚了,但可能还有人需要解决方案。

我创建了小型库GLGDI +,它具有类似(但不完整/相等)的GDI +语法,可在OpenTK上运行: http : //code.google.com/p/glgdiplus/

我不确定稳定性,它在DrawString方面存在一些问题(来自OpenTK的TextPrint问题)。 但是,如果你需要为你的实用程序提升性能(比如我的情况下的级别编辑器),它可以是解决方案。

您可能希望查看Brush对象,并且您不会接近GDI +程序的实时性能,但只要对象的几何和数量保持在合理的范围内,您就可以轻松地保持适当的fps。 。 至于画线,我不明白为什么不。

但是如果你达到了你认为最佳的点,那就是画线……你应该考虑一个不同的图形堆栈,如果你喜欢.NET但是有非托管API如OpenGL和DirectX的问题,那就去吧使用WPF或Silverlight,它非常强大。

无论如何,您可以尝试设置System.Drawing.Drawing2D.GraphicsPath,然后使用System.Drawing.Drawing2D.PathGradientBrush以这种方式应用颜色。 这是一个单缓冲的绘制调用,如果你无法获得足够的性能。 除了GDI +,你必须完全使用其他东西

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

当然,这取决于快速通道的极端情况

  • 在所选择的内存表示中绘制给定颜色的线条
  • 将其转换为要显示的Bitmap

我想,不是在.NET Framework中,而是在第三方库中? 对于像这样的东西,Silverlight中没有类似的位图编写器吗? (我自己还没有进入Silverlight ……)

至少它可能是开箱即用的方法。 希望能帮助到你。

我认为你必须在绘图后处理笔对象和e.Graphics对象。 如果你在onPaint()中编写drawLine代码,那么还有一件事情。

  just override onPaint() method it support better drawing and fast too.