WPF3种不同绘图方式性能比对


前言

WPF;绘图;GDI+;WritableBitmap;DrawingVisual;Cancas


WPF新手,需要用WPF绘图,考虑到性能,到网上搜了一些文章,发现有3种绘图方式,比对了一下性能,记录在此。

1.WPF

代码如下(示例):

void Draw()
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    width = (int)root.ActualWidth;
    height = (int)root.ActualHeight;
    Random rand = new Random();
    for (int i = 0; i < 100000; i++)
    {
        int x1 = rand.Next(width);
        int x2 = rand.Next(width);
        int y1 = rand.Next(height);
        int y2 = rand.Next(height);
        root.Children.Add(new Line()
        {
            X1 = x1,
            Y1 = y1,
            X2 = x2,
            Y2 = y2,
            Stroke = Brushes.Red,
            StrokeThickness = 1,
        });
    }
    stopwatch.Stop();
    label.Content = stopwatch.ElapsedMilliseconds + "ms";
}

2.WritableBitmap & GDI+

private void Draw()
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    width = (int)OutCanvas.ActualWidth;
    height = (int)OutCanvas.ActualHeight;
    if (width > 0 && height > 0)
    {
        DisplayImage.Width = width;
        DisplayImage.Height = height;

        wBitmap = new WriteableBitmap(width, height, 72, 72, PixelFormats.Bgr24, null);
        DisplayImage.Source = wBitmap;
    }
    wBitmap.Lock();

    Bitmap backBitmap = new Bitmap(width, height, wBitmap.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, wBitmap.BackBuffer);

    Graphics graphics = Graphics.FromImage(backBitmap);
    graphics.Clear(System.Drawing.Color.White);
    Random rand = new Random();
    for (int i = 0; i < 100000; i++)
    {
        int x1 = rand.Next(width);
        int x2 = rand.Next(width);
        int y1 = rand.Next(height);
        int y2 = rand.Next(height);
        graphics.DrawLine(Pens.Red, x1, y1, x2, y2);
    }

    graphics.Flush();
    graphics.Dispose();
    graphics = null;

    backBitmap.Dispose();
    backBitmap = null;

    wBitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
    wBitmap.Unlock();
    stopwatch.Stop();
    label.Content = stopwatch.ElapsedMilliseconds + "ms";
}

2.WritableBitmap & GDI+

private void Draw()
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    this.AddVisualChild(_drawingVisual);
    width = (int)ActualWidth;
    height = (int)ActualHeight;
    var dc = _drawingVisual.RenderOpen();
    PathFigure pthFigure = new PathFigure();
    pthFigure.IsClosed = false;
    pthFigure.IsFilled = false; 
    pthFigure.StartPoint = new Point(10, 100);
    PolyLineSegment plineSeg = new PolyLineSegment();
    Random rand = new Random();
    Pen pen = new Pen(Brushes.White, 1);
    pen.Freeze();
    for (int i = 0; i < 100000; i++)
    {
        int x1 = rand.Next(width);
        int x2 = rand.Next(width);
        int y1 = rand.Next(height);
        int y2 = rand.Next(height);
        dc.DrawLine(pen, new Point(x1, y1), new Point(x2, y2));
    }
    dc.Close();
    stopwatch.Stop();
    label.Content = stopwatch.ElapsedMilliseconds + "ms";
}
//必须重载这两个方法,不然是画不出来的
// 重载自己的VisualTree的孩子的个数,由于只有一个DrawingVisual,返回1
protected override int VisualChildrenCount
{
    get { return 1; }
}

private void Grid_Loaded(object sender, RoutedEventArgs e)
{
    Draw();
}

// 重载当WPF框架向自己要孩子的时候,返回返回DrawingVisual
protected override Visual GetVisualChild(int index)
{
    if (index == 0)
        return _drawingVisual;

    throw new IndexOutOfRangeException();
}

总结

  • 代码中的StopWatch计时结果:
    在这里插入图片描述

  • 界面渲染速度:2远大于1大于3

  • 界面流畅程度:2非常流畅,1和3在进行窗口操作(移动、最大化、最小化)时卡顿

  • 综合比对,使用WritableBitmap & GDI+绘图渲染流畅度最好

参考

https://blog.csdn.net/lweiyue/article/details/89879028
https://blog.csdn.net/wcc27857285/article/details/52584166

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
WPF是一基于向量图形的绘图方式,它能够让用户以较小的开销生成高质量的图形。为了实现WPF高性能绘图,我们需要采取以下几个方法: 1. 使用硬件加速:在WPF中,硬件加速是默认开启的。利用现代GPU进行绘制,可以大幅提高绘制速度。因此,我们可以使用硬件加速来优化WPF绘图性能。 2. 双缓冲:WPF的UI元素在绘制时,会自动进行双缓冲,即先将图像绘制到一个后台缓冲区,然后再将其绘制到前台缓冲区。双缓冲可以防止图像闪烁,也可以提高绘图速度。 3. 利用可视化子系统:WPF的可视化子系统支持多绘图API,包括DrawingContext、RenderTargetBitmap和WriteableBitmap等。我们可以根据需要选择合适的API来进行绘图,以达到最优的绘图效果。 4. 缓存可重用的图形:WPF的可视化元素支持缓存,我们可以将可重复使用的UI元素进行缓存,以便将来直接调用缓存元素进行渲染,避免重复绘制,提升绘图效率。 5. 优化绘图算法:在一些复杂的绘图场景下,使用优化的绘图算法可以大幅提高绘图速度。例如,在绘制大量点时,我们可以将点集合并为一个多边形进行绘制,而不是一个个点逐个绘制。 总的来说,WPF高性能绘图需要综合考虑多个方面。我们需要充分利用硬件加速、双缓冲、可视化子系统、元素缓存等技术手段,同时优化渲染算法,才能在实际应用中获得最优的绘图效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值