如前所述,执行此操作的 WPF“标准”方式不会为您提供所需的性能。在尝试了几种不同的免费和商业产品但没有得到我需要的东西后,我开始尝试以下方法:
- 使用 WPF 几何。
- 使用 Direct2D。
他们两个都没有表现。
我知道的一件事是 WPF 擅长渲染图像(BitmapSource),所以我决定朝那个方向前进并使用 WriteableBitmapEx 在 WriteableBitmap 上绘制图形,然后将其传递给...
WriteableBitmapEx 库的一个问题是它没有很多绘图功能,例如 GDI。那么为什么不直接使用 GDI 呢?如果你做对了,没有区别。
例子:
public void BeginDraw()
{
_writeable_bitmap = new WriteableBitmap((int)Math.Max(_size.Width, 1),
(int)Math.Max(_size.Height, 1), 96.0, 96.0, PixelFormats.Pbgra32, null);
_gdi_bitmap = new System.Drawing.Bitmap(_writeable_bitmap.PixelWidth,
_writeable_bitmap.PixelHeight,_writeable_bitmap.BackBufferStride,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb,
_writeable_bitmap.BackBuffer);
_writeable_bitmap.Lock();
_g = System.Drawing.Graphics.FromImage(_gdi_bitmap);
_g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
_g.Clear(System.Drawing.Color.Transparent);
}
public void DrawSeries(IEnumerable<System.Drawing.PointF> points)
{
_g.DrawCurve(dataSeries.GdiPen, points.ToArray());
}
public void EndDraw()
{
_writeable_bitmap.AddDirtyRect(new Int32Rect(0, 0,
_writeable_bitmap.PixelWidth, _writeable_bitmap.PixelHeight));
_writeable_bitmap.Unlock();
var cloned = _writeable_bitmap.Clone();
cloned.Freeze();
Dispatcher.BeginInvoke(new Action((() =>
{
Image = cloned;
})));
_g.Dispose();
}
如您所见,我正在使用“特殊技巧”将图形直接绘制到使用 GDI 的本机 WPF BitmapSource。
我不确定这是不是正确的测量方法,但使用这种方法我已经设法获得了一些非常不错的结果:
- 超过 10 亿个数据点。
- 刷新率为5FPS。
- 以 100hz 推送 10,000 个新数据点。
- i7 Core 笔记本电脑 10% 的 CPU。
- WPF UI 和渲染线程完全可以自由地执行其他操作。
我正是这样做的开源库 RealTimeGraphX(用于 WPF 和 UWP)的作者。
https://github.com/royben/RealTimeGraphX
除实际线系列外,其余图形组件均使用标准 WPF 控件和形状制作,因此可以轻松自定义和操作。