DrawingVisual上的位图缓存具有模糊部分

时间:2014-10-01 09:23:27

标签: c# caching bitmap geometry drawingvisual

最近我切换到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行),但是当我打开位图缓存时,图形的某些部分有时会变得模糊。

blurry lines

有谁知道如何解决这个问题?我尝试更改RenderAtScale的{​​{1}}或关闭DrawingVisual设置,但这没有帮助。

编辑:省略画笔填充几何图形以避免混淆,因为它与此处无关。

1 个答案:

答案 0 :(得分:1)

如果您决定在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的blitting。您调用InvalidateVisual()重绘图表。注意GC个问题,它们是必须的(特别是如果图形经常被重新绘制,则定期进行垃圾收集)。

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