Ho trovato diversi modelli per l'ottimizzazione della gestione di bitmap in WPF. Tuttavia, non capisco quando utilizzare ciascun modello. Poiché penso che questo sia un problema comune, ho riassunto ciò che ho capito e ciò che immagino e chiedo il tuo aiuto. Se è possibile aggiungere modelli, spiega come si differenziano, spiegare se usano la CPU o la GPU, e insegnare quando utilizzare ogni e come combinarli, sarebbe di grande aiuto !Pattern di ottimizzazione delle prestazioni bitmap
Contesto - Le immagini Scenario "Grid":
La mia applicazione deve visualizzare molte immagini bitmap. Le immagini vengono visualizzate sullo schermo in un'organizzazione simile a una griglia di righe e colonne (non necessariamente le classi Grid o UniformGrid, si pensi alla vista Album di Windows Media Player). Le immagini potrebbero spostarsi tra diverse celle della griglia. Alcune immagini su celle arbitrarie possono essere sostituite da altre. Le immagini dovrebbero essere selezionabili, dovrebbero fornire un menu contestuale, dovrebbero essere selezionabili, resistenti al trascinamento ecc. In altre parole, "combinare i piccoli buggers in una grande bitmap" non è applicabile, almeno non in modo ingenuo.
Modello 0: La Hack
Combino il piccolo maledice in una bitmap, e utilizzare questo come sfondo (come disegno contesto??). Sovrapponi questo con immagini con contenuti vuoti che gestiranno hit, menu contestuali, eventi, ecc.
Il vantaggio è che stiamo parlando solo di due bitmap qui: quello attualmente visualizzato e quello che dovrebbe sostituirlo. Questo dovrebbe essere molto veloce. Tuttavia, i miei anni di esperienza sollevano la bandiera rossa del pericolo. I tuoi commenti?
Motivo 1: ridurre la dimensione dell'immagine
Questo è un gioco da ragazzi quando si conosce in anticipo le dimensioni dell'immagine per ridimensionare, e quando si è disposti a perdere i dettagli (colore) per le prestazioni:
- Ridurre la dimensione del bitmap utilizzando BitmapImage.DecodePixelWidth
- Ridurre le informazioni sul colore utilizzando FormatConvertedBitmap.DestinationFormat
- impostare il comportamento di scala del controllo s etting Image.Stretch to Stretch.None
- Imposta il SetBitmapScalingMode per l'immagine su LowQuality.
- congelare il bastardo
vedi codice here.
Campione 2: Background pre-fetch
Questo modello è applicabile quando si pensa di poter usufruire degli utenti a guardare le immagini sullo schermo, e preparare in anticipo le prossime immagini da visualizzare. Gli svantaggi per il tuo progetto, oltre al sovraccarico della memoria, è che deve supportare l'obiettivo .Net Framework 4 e non solo il profilo del client, in modo che possa incorrere in un'installazione sul client. Tu stesso dovrai soffrire il dolore asincrono della programmazione.
In questo modello si crea esattamente il numero richiesto di controlli Immagine. Quando le bitmap devono essere aggiunte, spostate o eliminate, si modificano solo le risorse Bitmap dei controlli immagine. Un'attività di BackgroundWorker è responsabile della prelettura delle risorse Bitmap (possibilmente utilizzando il modello "Riduci dimensioni immagine" sopra) e di inserirle in MemoryCache.
Per far funzionare questo, è necessario impostare CacheOption di BitmapImage su OnLoad, in modo che il lavoro venga scaricato sull'operatore in background.
Motivo 3: Disegno Contesto
Questo è stato suggerito da Sheldon Ziao da Microsoft Support sul forum MSDN WPF here. Vedi pagina 494, Capitolo 15 "Grafica 2D" in Adam Nathan WPF 4 Unleashed per una descrizione di DrawingContext. Non posso dire di aver capito. Secondo la risposta here, suppongo che ciò migliorerebbe la gestione dei disegni Geometry, non delle bitmap. Successivamente, non penso che questo supporterà i requisiti di messa a fuoco e di eventi per le immagini (il mio male per non spiegare meglio i requisiti al forum) Inoltre, sono preoccupato dalla frase di riepilogo del libro: "Notare che l'uso di DrawingContext non cambia il fatto che stai operando all'interno di un sistema in modalità permanente. Il disegno specificato non si verifica immediatamente; i comandi sono mantenuti da WPF fino a quando non sono necessari. "Ciò significa che una volta che il nostro gestore pari non riusciamo a sfruttare il parallelismo come in" Sfondo pre-fetch ".
Schema 4: scrivibili bitmap
La documentazione MSDN here descrive come un sistema a doppio buffer: Your thread UI aggiorna il buffer; il thread di rendering di WPF lo sposta nella memoria video.
L'utilizzo previsto (vedere here) è per bitmap che cambiano molto come in un film video come display. Non ne sono sicuro, ma è possibile che ciò possa essere compromesso e combinato con il pattern Pre-prelettura in background e utilizzato nello scenario della griglia.
modello 5: bitmap memorizzata nella cache
Non molto informazioni sul MSDN (here). Nell'archivio del forum WPF (here) viene spiegato che "L'API BitmapCache è progettata per memorizzare nella cache il contenuto (durante il rendering in hardware) nella memoria video, il che significa che rimane residente sulla GPU. Questo ti fa risparmiare il costo di ripetere il rendering di quel contenuto quando lo si disegna sullo schermo. "Questa sembra una grande idea. Non sono sicuro, tuttavia, quali sono le insidie e come usarlo.
Motivo 6: RenderTargetBitmap
Il RenderTargetBitmap converte un illustrato in bitmap. Non sono sicuro se è rilevante qui. Vedi here.
Modifica: Per quanto riguarda la domanda di Paul Hoenecke: Ho scritto che "La mia applicazione deve visualizzare molti tipi di bitmap". Ho omesso di menzionare che ho bisogno di visualizzare circa 800 immagini contemporaneamente.
Si può leggere sui problemi di prestazioni coinvolti a mie domande in modo WPF Bitmap performance e How can I make displaying images on WPF more “snappy”?
Ho modificato la descrizione del modello 1 per evidenziare il concetto che i controlli di immagine non vengono creati o eliminati (a meno che non vogliamo per visualizzare una griglia più grande o più piccola). Solo le Sorgenti sono impostate su BitmapSources differenti, nuove o nulle.
Edit: This question as posted on the WPF support forum, con alcune risposte da personale MS.
Quante immagini stai anticipando? Ho creato un'app che mostra una griglia di migliaia di immagini prima. Abbiamo usato una casella di riepilogo in modalità virtuale; mentre l'utente scorre verso il basso, le immagini vengono caricate in un thread in background, congelate e impostate sulla Sorgente dell'immagine. Chiaramente, ci hai messo un sacco di pensiero in questo ... ma forse sapere di più su quello che vuoi ottenere sarebbe meglio. Ad esempio, quali problemi hai avuto che rendono l'ottimizzazione di una tale priorità? –
@PaulHoenecke Ciao Paul, grazie per la tua risposta. Le raccolte virtuali ti aiutano quando vuoi visualizzare un piccolo numero di elementi fuori da una grande collezione. Qui, voglio visualizzare circa 1K articoli contemporaneamente. Inoltre, non sono sicuro che esista una griglia di virtualizzazione. Infine, il pattern 1 è essenzialmente virtualizzato - aggiungerò en edit. – Avi
Avi, la tua domanda sembra inappropriata per il problema descritto. Potresti voler migliorare il rapporto di compressione per qualche motivo, ma poi devi sapere esattamente che tipo di immagini stai visualizzando. Oppure, dall'altra parte, potresti dare all'utente un'impressione di tutte le immagini disponibili, quindi potresti definire alcuni set e visualizzare miniature o simili. Ma entrambe le cose non hanno necessariamente a che fare l'una con l'altra. Forse vuoi qualcosa di simile a una metrica di similarità per definire insiemi di immagini simili? –