1

最近我切换到DrawingVisuals提高趋势图的性能(尤其是缩放和平移)。

这是我的代码:

blocksToBeRendered = (baseItem as AvgCurve).GetStreamGeometryBlocks(ActualWidth, ActualHeight, _minPoint.X, _maxPoint.X, FixTimeStep ? _timeStep : 0, IsMainChart);

Pen stroke = new Pen((baseItem as AvgCurve).LineBrush, 1);

foreach (GeometryGroup group in blocksToBeRendered)
{
    if (group.Children.Count != 0)
    {
        if (!cachedBlocks[baseItem].Any(x => x.Children[0] == group.Children[0]))
        {
            cachedBlocks[baseItem].Add(group);

            ImprovedDrawingVisual vis = new ImprovedDrawingVisual();

            BitmapCache cache = new BitmapCache() { SnapsToDevicePixels = true };
            vis.CacheMode = cache;

            using (DrawingContext context = vis.RenderOpen())
            {
                RenderOptions.SetEdgeMode(group, EdgeMode.Aliased);
                if (group.Children.Count > 0)
                {
                    context.DrawGeometry(null, stroke, group.Children[0]);
                }
            }

            _host.VisualCollection.Add(vis);
        }
    }
}

这是ImprovedDrawingVisual

public class ImprovedDrawingVisual: DrawingVisual
{
    public ImprovedDrawingVisual()
    {
        VisualEdgeMode = EdgeMode.Aliased;
        VisualBitmapScalingMode = BitmapScalingMode.NearestNeighbor;
    }
}

现在,几何图形确实有Transforms,这可能很重要。

发生的情况是,在没有位图缓存(1 px 线)的情况下,图表绘制得很好,但是当我打开位图缓存时,图表的某些部分有时会变得模糊。

模糊的线条

有谁知道我该如何解决这个问题?我尝试更改RenderAtScaleDrawingVisual关闭EdgeMode设置,但这无济于事。

编辑:省略画笔填充几何图形以避免混淆,因为它在这里不相关。

4

1 回答 1

2

如果您决定尝试GDI+wpf那么绘图将如下所示:

using GDI = System.Drawing;

private int _counter; // count redraws

protected override void OnRender(DrawingContext context)
{
    if (Figures != null && RenderSize.Height > 0 && RenderSize.Width > 0)
        using (var bitmap = new GDI.Bitmap((int)RenderSize.Width, (int)RenderSize.Height))
        {
            using (var graphics = GDI.Graphics.FromImage(bitmap))
                foreach (var figure in Figures)
                    figure.Render(this, graphics);
            // draw image
            var hbitmap = bitmap.GetHbitmap();
            var size = bitmap.Width * bitmap.Height * 4;
            GC.AddMemoryPressure(size);
            var image = Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            image.Freeze();
            context.DrawImage(image, new Rect(RenderSize));
            DeleteObject(hbitmap);
            GC.RemoveMemoryPressure(size);
            // trigger garbage collecting
            if (_counter++ > 10)
                GC.Collect(3);
      }
}

这基本上渲染Graph到位(没有延迟wpf渲染,好吧,只有 final 的blitting image)。您调用InvalidateVisual()以重绘图形。注意GC东西,它们是必须的(特别是如果图形频繁重绘,则定期进行垃圾收集)。

在我的代码Figures中是一个非视觉对象列表(简单的类,也实现了 GDI 渲染)。你有视觉孩子。这是问题,我留给你解决。好处是性能非常高。

于 2014-10-01T10:08:55.547 回答