2014-10-01 21 views
1

最近,我切换到DrawingVisuals以提高趋势图(尤其是缩放和平移)的性能。DrawingVisual上的位图缓存具有模糊部分

这里是我的代码:

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

有谁知道我怎么能解决这个问题?我尝试更改DrawingVisualRenderAtScale或关闭EdgeMode设置,但这没有帮助。

编辑:遗漏了刷子填充几何图形以避免混淆,因为它在这里不相关。

+0

您正在使用'BitmapCache'(请参阅[my](http://stackoverflow.com/q/25507861/1997232)问题),它看起来像使用jpg-compession的位图。也许你可以实现自己的'BitmapCache'(这不会是一个JPG)?顺便说一句,要有一个非常高性能的图表,我必须在wpf中使用'GDI +'。 – Sinatr 2014-10-01 09:42:57

+0

你有没有使用GDI +的例子,我将如何从代码示例开始呢? – 2014-10-01 09:48:25

回答

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)。您可以拨打InvalidateVisual()重新绘制图形。注意GC这些东西,它们是必须的(特别是如果图经常重绘的话定期垃圾回收)。

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

+0

我曾经在每次平移或缩放时重绘的画布顶部都有几何图形。这更像吗? – 2014-10-01 10:24:15

+0

不好,因为visuals和'wpf'很慢。你在'xaml'中设置了视觉效果吗?或者说,否则,图形数字(线条,背景等)**必须是视觉?如果答案是“否”,那么将它们替换为非视觉效果,这些非视觉效果只知道如何将自己渲染到父“Graph”中。 – Sinatr 2014-10-01 10:27:24

+0

我曾经有过路径,而不是视觉效果。这些路径具有几何图形并被添加到画布上。 – 2014-10-01 10:28:37