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