2013-03-12 138 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/