2013-03-12 16 views
13

Ho una vista ad albero con piccole icone visualizzate nel modello dati. Sto cercando di salvare la visualizzazione struttura come PNG utilizzando RenderTargetBitmap.WPF RenderTargetBitmap Elementi mancanti

L'immagine viene salvata correttamente su insiemi di dati di piccole dimensioni. Tuttavia, se il set di dati diventa troppo grande, alcune icone vengono escluse dall'immagine finale. Il numero magico sembra essere di 200 articoli. Non sembra importare se l'albero è profondo o largo, dopo 200 elementi, le icone non sono renderizzate.

Aggiunto Codice

ecco il mio codice che sto usando per creare un'immagine.

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

     targetBitmap.Render(_treeView); 

Aggiunto Screen Shot

Avviso le icone mancanti modo più sul lato destro della struttura. Screen shot of missing icons

Ora se crollo alcuni rami, nascondendo alcune delle altre icone, queste icone sono incluse. È quasi come RenderTargetBitmap.Render non ha il potere di rendere tutte le icone. Oppure potrebbe avere qualcosa a che fare con i pannelli virtuali. Screen shot of included icons

Ecco uno sguardo più da vicino. enter image description here

+0

Puoi provare qualcosa per me; Basta impostare tutte le immagini su un'immagine 2x2. Hai ancora il limite di 200 articoli? –

+0

@MeirionHughes Whoa! Interessante. A 2x2, non sono state visualizzate le icone. Ho aumentato le dimensioni un po 'e poi solo poche icone, come 10. Quindi, quando ho posto la domanda, il modello è stato impostato su 100x100, quindi l'ho modificato in 150x150 e tutte le icone sono state renderizzate! Quindi cosa diavolo sta succedendo ?? –

+1

Nessuna idea ... Molto strano, sono tentato di dire che hai qualche problema con la virtualizzazione e il caching. Non stai facendo nulla con le immagini, ad esempio memorizza tutto nella stessa bitmap o qualcosa del genere? –

risposta

4

Quello che ho subito notato che hai un'immagine ENORME. Larghezza 12000. Sono sorpreso che tu ti sia avvicinato così tanto.

Come indicato da MSDN, la larghezza/altezza della trama è limitata dai limiti di trama di DirectX.

La dimensione massima di rendering di un albero visivo XAML è limitata dalle dimensioni massime di una trama Microsoft DirectX; per maggiori informazioni vedi Limiti di risorse (Direct3D). Questo limite può variare a seconda dell'hardware in cui viene eseguita l'app. Il contenuto molto grande che supera questo limite potrebbe essere ridimensionato per adattarsi. Se i limiti di ridimensionamento vengono applicati in questo modo, è possibile interrogare le dimensioni renderizzate dopo il ridimensionamento utilizzando le proprietà PixelWidth e PixelHeight. Ad esempio, una struttura ad albero XAML da 10000 a 10.000 pixel può essere ridimensionata a 4096 per 4096 pixel, un esempio di un limite particolare come forzato dall'hardware in cui viene eseguita l'app. http://msdn.microsoft.com/library/windows/apps/dn298548

ho il sospetto queste cose:

  • virtualizzazione tagliando fuori alcune cose - ho avuto il problema esatto in passato con DataGrid, e il problema era di virtualizzazione. Il tuo caso non sembra però uno.
  • Una trama troppo grande può causare un comportamento non definito.

È possibile provare a disattivare l'accelerazione hardware. La cosa causa pochissimi bug hardcore. http://msdn.microsoft.com/en-us/library/system.windows.media.renderoptions.processrendermode.aspx

Oltre a questo - sarà difficile, ma sono abbastanza sicuro che funzionerà in modo bello:

1) Iniziamo con l'oggetto principale, e attraversare i bambini oggetto radice ricorsivamente, fino a trovare un oggetto è inferiore a 1000 x 1000. Scatta una foto usando RenderTargetBitmap (BMP) e uniscilo a IN-MEMORY-BMP. Fallo per ogni bambino.

Dovresti essere in grado di calcolare tutto questo.

+0

Questa potrebbe essere la soluzione, ma ho bisogno di alcuni giorni per testare. Tuttavia, è un ottimo consiglio! –

+0

Come accennato nel mio commento questo non è correlato alla virtualizzazione: sebbene il poster originale abbia probabilmente usato la virtualizzazione, non l'ho fatto in modo definitivo. Dubito anche che questo sia legato all'accelerazione hardware poiché RenderTargetBitmap non utilizza l'accelerazione hardware. Questo non proviene dalla pagina MSDN RenderTargetBitmap ma da altri post su MSDN dove le persone si lamentavano della velocità di RenderTargetBitmap. –

+0

Informazioni sui limiti delle risorse per 'RenderTargetBitmap'; Se scelgo come target il processore '64bit' posso generare correttamente un'immagine png' 15000x15000'. Provare un'immagine '30000x30000' produce un errore di memoria quando si tenta di salvare il png. Provare il '30000x30000' su un processore a 32 bit produce un errore di memoria durante la creazione di' RenderTargetBitmap'. Provare un'immagine '60000x60000' produce un errore quando si chiama' Render() '. Alcune combinazioni di impostazioni generano un 'errore GDI + generale quando si tenta di salvare.Il mio punto: ** errori da limiti di risorse non vengono silenziosamente ingoiati ** - quindi non penso che questo sia un errore di risorse. –

0

Per i record: c'è una soluzione alternativa.

Invece di rendere il Visual direttamente con RenderTargetBitmap, utilizzare un DrawingVisual provvisorio. Dipingi il tuo Visual in DrawingVisual usando un VisualBrush e poi usa RenderTargetBitmap con DrawingVisual.

Ti piace questa:

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; 
    } 

Nota, tuttavia, che il tuo VisualBrush diventa più grande l'immagine risultante diventa sempre più sfocata (durante il rendering ad alta DPI). Per ovviare a questo problema, utilizzare una serie di "tiles" VisualBrush più piccole come descritto qui: https://srndolha.wordpress.com/2012/10/16/exported-drawingvisual-quality-when-using-visualbrush/