Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用GDI+;快速绘制不同颜色线条的方法;?_C#_.net_Gdi+ - Fatal编程技术网

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

C# 使用GDI+;快速绘制不同颜色线条的方法;?,c#,.net,gdi+,C#,.net,Gdi+,我有一个点的动态列表,可以随时添加新点。我想用不同的颜色画线来连接它们。颜色基于这些点的索引。代码如下: 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.Blu

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

    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]);
        }
    }
private List\u点;
专用静态笔pen1=新笔(颜色:红色,10);
专用静态笔pen2=新笔(颜色为黄色,10);
专用静态笔pen3=新笔(颜色:蓝色,10);
专用静态笔pen4=新笔(颜色:绿色,10);
私有void Init()
{
//使用固定的80来简化
_点数=新列表(80);
对于(int i=0;i<80;i++)
{
_增加(新点(30+i*10,30));
}
}
专用void DrawLinesNormal(PaintEventArgs e)
{
对于(int i=0;i<_points.Count-1;i++)
{
如果(i<20)
e、 图形.绘制线(pen1,_点[i],_点[i+1]);
否则如果(i<40)
e、 绘图.绘图线(pen2,_点[i],_点[i+1]);
否则,如果(i<60)
e、 图形.绘制线(pen3,_点[i],_点[i+1]);
其他的
e、 图形.绘制线(pen4,_点[i],_点[i+1]);
}
}
我发现当我有新的点以高速进入时,这种方法不够快。有没有办法让它更快?我做了一些研究,有人说使用GraphicsPath可能会更快,但怎么做呢

[更新]我收集了一些可能的优化:

  • 使用GrahpicsPath
  • 更改图形质量(例如SmoothingMode/PixelOffsetMode…),也可以调用SetClip指定要渲染的唯一必要区域

  • 这与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更快。

    您将无法从代码中挤出更多的速度,而不会丢失质量或更改为更快的渲染器(GDI、OpenGL、DirectX)。但GDI通常会快一点(可能是2倍),DirectX/OpenGL可能快得多(可能是10倍),这取决于您正在绘制的图形

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

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


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

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

    但是如果你达到了你认为最理想的程度,那就是画线。。你应该考虑一个不同的图形栈,如果你喜欢.NET,但是与OpenGL和DirectX之类的非托管API有问题,去WPF或Silverlight,它是非常强大的。 无论如何,您可以尝试设置System.Drawing.Drawing2D.GraphicsPath,然后使用System.Drawing.Drawing2D.PathGradientBrush以这种方式应用颜色。这是一个单缓冲draw调用,如果您不能从中获得足够的性能。你必须完全使用GDI+

    而不是GDI(+),但解决这个问题的一种完全不同的方法是使用一块内存,在其中绘制线条,将其转换为一个
    位图
    对象,以便在需要显示线条的地方立即绘制

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

    • 在内存中绘制给定颜色的线表示选择和
    • 将其转换为要显示的
      位图
    我想不是在.NET框架中,而是在第三方库中?Silverlight中没有类似的东西吗?(我自己还不太喜欢Silverlight…)


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

    对提高性能并没有真正的帮助,但我也会把这些笔放在一个列表中,然后写下所有这些行
    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]);
    }
    
     just override onPaint() method it support better drawing and fast too.