2013-03-12 98 views
13

我有一个TreeView,在数据模板中显示小图标。我试图使用RenderTargetBitmap将Treeview保存为PNG。WPF RenderTargetBitmap缺少元素

图像在小数据集上正确保存。但是,如果数据集太大,某些图标将从最终图像中排除。神奇的数字似乎是200项。如果树是深的或宽的,在200个项目之后,图标不被渲染似乎并不重要。

添加的代码

因此,这里是我的代码,我使用创建的图像。

 RenderTargetBitmap targetBitmap = new RenderTargetBitmap(
      (int)_treeView.ActualWidth, 
      (int)_treeView.ActualHeight, 
      96, 96, PixelFormats.Default); 

     targetBitmap.Render(_treeView); 

新增屏幕截图

通知在树的右侧缺少的图标的方式结束了。 Screen shot of missing icons

现在,如果我折叠了几个分支,从而隐藏了一些其他图标,那么这些图标就包含在内。这几乎就像RenderTargetBitmap.Render无法渲染所有图标。或者它可能与虚拟面板有关。 Screen shot of included icons

这里仔细看看。 enter image description here

+0

您可以为我尝试一些东西;只需将所有图像设置为2x2图像。你仍然得到200项限制? – 2013-03-15 21:55:03

+0

@MeirionHughes哇!有趣。在2×2时,没有图标被渲染。我增加了一些尺寸,然后只有几个图标,比如10个。所以当我问这个问题时,模板被设置为100x100,所以我将它改为150x150,并且所有图标都被渲染了!那么,究竟发生了什么? – 2013-03-18 16:04:39

+1

不知道......非常奇怪,我很想说你在虚拟化和缓存方面有一些问题。你没有对图像做任何事情,比如将所有的图像存储在相同的位图中或什么东西? – 2013-03-18 16:15:26

回答

4

我立即注意到你有巨大的形象。宽度12000.我感到很惊讶,你甚至得到了这一点。

正如MSDN所述,纹理宽度/高度受到DirectX纹理限制的限制。

XAML可视化树的最大渲染大小受Microsoft DirectX纹理的最大尺寸限制;欲了解更多信息,请参阅资源限制(Direct3D)。此限制可能因应用程序运行的硬件而异。非常大的内容超过此限制可能会缩放以适合。如果以这种方式应用缩放限制,则可以使用PixelWidth和PixelHeight属性来查询缩放后的渲染大小。例如,10000乘10000像素的XAML可视化树可能会缩放到4096乘4096像素,这是应用程序运行时硬件强制的特定限制的示例。 http://msdn.microsoft.com/library/windows/apps/dn298548

我怀疑这些东西:

  • 虚拟化切断了一些事情 - 我已经在过去的DataGrid中的确切的问题,而问题是虚拟化。你的情况似乎并不像一个。
  • 纹理太大会导致未定义的行为。

您可以尝试禁用硬件加速。这件事导致了很少的核心错误。 http://msdn.microsoft.com/en-us/library/system.windows.media.renderoptions.processrendermode.aspx

除此之外 - 这将是非常棘手,但我敢肯定,这将做工精美:

1)先从根对象,并递归遍历根对象儿童,直到找到对象即小于1000 x 1000.使用RenderTargetBitmap(BMP)拍摄照片并将其合并到IN-MEMORY-BMP中。为每个孩子做。

你应该能够计算所有这些东西。

+0

这可能是解决方案,但我需要几天才能测试。尽管如此,这是一个非常好的提示! – 2013-12-02 01:45:00

+0

正如我的评论中提到的,这与虚拟化无关:尽管原始海报可能使用了虚拟化,但我确实没有。我也怀疑这与硬件加速有关,因为RenderTargetBitmap不使用硬件加速。这不是来自RenderTargetBitmap MSDN页面,而是来自MSDN上其他人的抱怨RenderTargetBitmap速度的帖子。 – 2013-12-02 16:06:26

+0

关于'RenderTargetBitmap'的资源限制;如果我的目标是'64位'处理器,我可以成功生成一个'15000x15000' png图像。尝试保存png时尝试使用'30000x30000'图像会产生内存错误。在32位处理器上试用'30000x30000'会在创建'RenderTargetBitmap'时产生内存错误。调用'Render()'时,尝试使用'60000x60000'图像会产生错误。尝试保存时,某些设置组合会生成“一般GDI +错误”。我的观点:**来自资源限制的错误并未被悄悄吞噬** - 所以我不认为这是资源错误。 – 2013-12-02 16:22:53

0

对于记录:有一个解决方法。

不是直接使用RenderTargetBitmap呈现Visual,而是使用临时DrawingVisual。使用VisualBrush将您的Visual绘制到DrawingVisual中,然后在DrawingVisual中使用RenderTargetBitmap。

像这样:

public BitmapSource RenderVisualToBitmap(Visual visual) 
    { 
     var contentBounds = VisualTreeHelper.GetContentBounds(visual); 

     var drawingVisual = new DrawingVisual(); 
     using (var drawingContext = drawingVisual.RenderOpen()) 
     { 
      var visualBrush = new VisualBrush(visual); 
      drawingContext.DrawRectangle(visualBrush, null, contentBounds); 
     } 

     var renderTargetBitmap = new RenderTargetBitmap((int)contentBounds.Width, (int)contentBounds.Height, 96, 96, PixelFormats.Default); 
     renderTargetBitmap.Render(drawingVisual); 

     return renderTargetBitmap; 
    } 

不过请注意,由于您的VisualBrush变大(高DPI渲染时)所产生的图像变得越来越模糊。要解决此问题,请使用以下所述的一系列较小的VisualBrush“切片”: https://srndolha.wordpress.com/2012/10/16/exported-drawingvisual-quality-when-using-visualbrush/