WPF绘图性能在大量几何图形时的表现

10

我在WPF绘图性能方面遇到了问题。有许多小的EllipseGeometry对象(例如1024个椭圆),它们被添加到三个不同的前景画刷的GeometryGroups中。最后,我将其全部呈现在简单的Image控件上。代码:

DrawingGroup tmpDrawing = new DrawingGroup();
GeometryGroup onGroup = new GeometryGroup();
GeometryGroup offGroup = new GeometryGroup();
GeometryGroup disabledGroup = new GeometryGroup();

for (int x = 0; x < DisplayWidth; ++x)
{
    for (int y = 0; y < DisplayHeight; ++y)
    {
        if (States[x, y] == true) onGroup.Children.Add(new EllipseGeometry(new Rect((double)x * EDGE, (double)y * EDGE, EDGE, EDGE)));
        else if (States[x, y] == false) offGroup.Children.Add(new EllipseGeometry(new Rect((double)x * EDGE, (double)y * EDGE, EDGE, EDGE)));
        else disabledGroup.Children.Add(new EllipseGeometry(new Rect((double)x * EDGE, (double)y * EDGE, EDGE, EDGE)));
    }
}

tmpDrawing.Children.Add(new GeometryDrawing(OnBrush, null, onGroup));
tmpDrawing.Children.Add(new GeometryDrawing(OffBrush, null, offGroup));
tmpDrawing.Children.Add(new GeometryDrawing(DisabledBrush, null, disabledGroup));
DisplayImage.Source = new DrawingImage(tmpDrawing);

代码能够正常工作,但是在Core 2 Quad上需要>0.5秒,在Pentium 4上需要>2秒。 我需要在每个地方都达到<0.1秒。可以看到,所有的椭圆形都是相等的。控件背景,即我的DisplayImage所在的位置,是纯色的(例如黑色),因此我们可以利用这一事实。我尝试使用1024个椭圆元素代替带有EllipseGeometries的图像,速度提升了很多(~0.5秒),但仍然不够快。如何加速它?

敬礼,Oleg Eremeev

P.S. 对于我的英语表示抱歉。


6
不必为你的英语道歉。 - Mike Dunlavey
你尝试过使用WPF性能套件来查找哪些操作占用了大部分时间吗? - levanovd
谢谢,levanovd,但我知道我的代码是错误的,这已经足够了。我正在询问一个完全不同的方法。 - Alec Mev
2个回答

5

我放弃了旧的渲染方法,但每次创建新的EllipseGeometry对象是个不好的想法,所以我用以下方式进行了优化:

for (int x = 0; x < newWidth; ++x)
{
    for (int y = 0; y < newHeight; ++y)
    {
        States[x, y] = null;
        OnEllipses[x, y] = new EllipseGeometry(new Rect((double)x * EDGE + 0.5f, (double)y * EDGE + 0.5f, EDGE - 1f, EDGE - 1f));
        OffEllipses[x, y] = new EllipseGeometry(new Rect((double)x * EDGE + 0.5f, (double)y * EDGE + 0.5f, EDGE - 1f, EDGE - 1f));
        DisabledEllipses[x, y] = new EllipseGeometry(new Rect((double)x * EDGE + 0.5f, (double)y * EDGE + 0.5f, EDGE - 1f, EDGE - 1f));
    }
}

// . . .

DrawingGroup tmpDrawing = new DrawingGroup();
GeometryGroup onGroup = new GeometryGroup();
GeometryGroup offGroup = new GeometryGroup();
GeometryGroup disabledGroup = new GeometryGroup();

for (int x = 0; x < DisplayWidth; ++x)
{
    for (int y = 0; y < DisplayHeight; ++y)
    {
        if (States[x, y] == true) onGroup.Children.Add(OnEllipses[x, y]);
        else if (States[x, y] == false) offGroup.Children.Add(OffEllipses[x, y]);
        else disabledGroup.Children.Add(DisabledEllipses[x, y]);
    }
}

tmpDrawing.Children.Add(new GeometryDrawing(OnBrush, null, onGroup));
tmpDrawing.Children.Add(new GeometryDrawing(OffBrush, null, offGroup));
tmpDrawing.Children.Add(new GeometryDrawing(DisabledBrush, null, disabledGroup));
DisplayImage.Source = new DrawingImage(tmpDrawing);

对于 x = 128 和 y = 8,即使在 Pentium III 系统上也能快速运行。


2
即使我有点晚:这篇文章由Charles Petzold撰写,对类似的情况非常有帮助。请注意,保留了HTML标记。

感谢您的回答,也许我将来可以在另一个项目中使用它。我的真正解决方案已经很好了,所以我想保持现状。 - Alec Mev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接