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 ピクセルの行) なしでグラフがきれいに描画されますが、ビットマップ キャッシュを有効にすると、グラフの一部がすべてぼやけてしまうことがあります。

ぼやけた線

これを修正する方法を知っている人はいますか?の設定を変更したり、設定をオフにしたりしてみRenderAtScaleましDrawingVisualEdgeModeが、解決しません。

編集:ここでは関係ないため、混乱を避けるためにブラシ塗りつぶしジオメトリを省略しました。

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レンダリングはなく、最終的なブリットのみですimage)。InvalidateVisual()グラフを再描画するために呼び出します。注意GCしてください、それらは必須です (特に、グラフが頻繁に再描画される場合の定期的なガベージ コレクション)。

私のコードFiguresには、非ビジュアル (単純なクラス、GDI レンダリングも実装) のリストがあります。そして、あなたには視覚的な子供がいます。それはあなたが解決するために私が残した問題です。利点は非常に高いパフォーマンスです。

于 2014-10-01T10:08:55.547 に答える