Ottimizzare animazioni, contenuti multimediali e immagini

Crea app UWP con animazioni uniformi, frequenza dei fotogrammi elevata e acquisizione e riproduzione di contenuti multimediali ad alte prestazioni.

Creare animazioni fluide

Un aspetto fondamentale delle app UWP è l'uniformità delle interazioni, tra cui le modifiche rapide tramite tocco, le transizioni e le animazioni uniformi e piccoli movimenti che forniscono il feedback dell'input. Nel framework XAML è presente un thread, denominato thread di composizione, dedicato alla composizione e all'animazione degli elementi visivi di un'app. Poiché il thread di composizione è diverso dal thread dell'interfaccia utente, ovvero quello che esegue il framework e il codice dello sviluppatore, le app possono realizzare una frequenza dei fotogrammi coerenti e animazioni uniformi indipendentemente dai calcoli complessi del layout o dai calcoli estesi. Questa sezione mostra come usare il thread di composizione per mantenere le animazioni di un'app eccezionalmente uniformi. Per altre informazioni sulle animazioni, vedi Panoramica delle animazioni. Per informazioni su come migliorare la velocità di risposta di un'app durante l'esecuzione di calcoli complessi, vedi Mantenere reattivo il thread dell'interfaccia utente.

Usare animazioni indipendenti anziché dipendenti

Le animazioni indipendenti possono essere calcolate dall'inizio alla fine al momento della creazione, perché le modifiche apportate alle proprietà da animare non influiscono sul resto degli oggetti in una scena. Di conseguenza, le animazioni indipendenti possono essere eseguite nel thread di composizione invece che nel thread dell'interfaccia utente. In questo modo, le animazioni restano uniformi, perché il thread di composizione viene aggiornato regolarmente.

Tutti questi tipi di animazione sono garantiti come indipendenti:

Le animazioni dipendenti influiscono sul layout e di conseguenza non possono essere calcolate senza input aggiuntivo del thread dell'interfaccia utente. Queste animazioni includono modifiche a proprietà come Width e Height. Per impostazione predefinita, le animazioni dipendenti non vengono eseguite e richiedono il consenso esplicito dello sviluppatore dell'app. Quando sono abilitate, vengono eseguite in modo uniforme se il thread dell'interfaccia utente resta sbloccato, ma iniziano a essere irregolari se il framework o l'app esegue molte altre operazioni nel thread dell'interfaccia utente.

Quasi tutte le animazioni nel framework XAML sono indipendenti per impostazione predefinita, ma puoi disabilitare questa ottimizzazione con alcune semplici azioni. In particolare, fai attenzione a questi scenari:

  • Se imposti la proprietà EnableDependentAnimation per permettere l'esecuzione di un'animazione dipendente nel thread dell'interfaccia utente. Converti queste animazioni in una versione indipendente. Anima ad esempio ScaleTransform.ScaleX e ScaleTransform.ScaleY anziché Width e Height per un oggetto. Non avere paura di ridimensionare oggetti come immagini e testo. Il framework applica la scala bilineare solo durante l'animazione di ScaleTransform. La rasterizzazione del testo o dell'immagine alle dimensioni finali verrà ripetuta per assicurare la chiarezza.
  • Se esegui aggiornamenti di un fotogramma alla volta, che in realtà sono animazioni dipendenti. Un esempio è l'applicazione di trasformazioni nel gestore dell'evento CompositonTarget.Rendering.
  • Se esegui un'animazione considerata indipendente in un elemento con la proprietà CacheMode impostata su BitmapCache. Questa animazione è considerata dipendente perché è necessario ripetere la rasterizzazione della cache per ogni fotogramma.

Non animare un controllo WebView o MediaPlayerElement

Il rendering di contenuto Web in un controllo WebView non viene eseguito direttamente dal framework XAML e richiede ulteriori operazioni di composizione con il resto della scena. Questo lavoro viene eseguito quando si anima il controllo intorno alla schermata e potrebbe causare problemi di sincronizzazione, ad esempio spostamento non in sincronia del contenuto HTML rispetto al resto del contenuto XAML nella pagina. Se vuoi animare un controllo WebView, scambialo con WebViewBrush per la durata dell'animazione.

Non è nemmeno consigliabile animare un controllo MediaPlayerElement. Oltre a incidere negativamente sulle prestazioni, questa scelta può produrre l'effetto di tagli (tearing) o altri artefatti nel contenuto video che viene riprodotto.

Nota I consigli di questo articolo per MediaPlayerElement si applicano anche a MediaElement. MediaPlayerElement è disponibile solo in Windows 10, versione 1607, quindi, se devi creare un'app per una versione precedente di Windows, devi usare MediaElement.

Usare le animazioni a ciclo infinito con moderazione

La maggior parte delle animazioni viene eseguita per un periodo di tempo specifico, ma se imposti la proprietà Timeline.Duration su Forever, l'animazione viene eseguita all'infinito. Consigliamo di ridurre al minimo l'utilizzo di animazioni a ciclo infinito perché comportano un consumo costante di risorse della CPU e possono impedire alla CPU di passare in modalità a basso consumo o in stato d'inattività, accelerando l'esaurimento delle batterie.

L'aggiunta di un gestore per CompositionTarget.Rendering è simile all'esecuzione di un'animazione a ciclo infinito. Il thread dell'interfaccia utente in genere è attivo solo quando sono presenti operazioni da eseguire, ma, se aggiungi un gestore per questo evento, eseguito a ogni fotogramma. Rimuovi il gestore quando non sono presenti operazioni da eseguire e registralo nuovamente quando è di nuovo necessario.

Utilizzare la libreria delle animazioni

Lo spazio dei nomi Windows.UI.Xaml.Media.Animation include una libreria di animazioni a prestazioni elevate con un aspetto coerente con quelle di altre animazioni di Windows. Le classi rilevanti, il cui nome contiene il termine "Theme", sono descritte in Panoramica delle animazioni. Questa libreria supporta molti scenari di animazione comuni, come l'animazione della prima visualizzazione dell'app e la creazione di transizioni di stato e contenuto. Ti consigliamo di usare questa libreria ogni volta che puoi per migliorare le prestazioni e la coerenza dell'interfaccia utente per la piattaforma UWP.

Nota Tale libreria non è in grado di animare tutte le proprietà possibili. Per gli scenari XAML in cui non può essere applicata la libreria di animazioni, vedi Animazioni con storyboard.

Animare in modo indipendente proprietà CompositeTransform3D

Puoi animare le singole proprietà di una trasformazione CompositeTransform3D in modo indipendente, quindi applica solo le animazioni necessarie. Per altre info ed esempi, vedi UIElement.Transform3D. Per altre info sull'animazione di trasformazioni, vedi Animazioni con storyboard e Animazioni con fotogrammi chiave e con funzioni di interpolazione.

Ottimizzare le risorse multimediali

I contenuti audio e video e le immagini sono forme di contenuto accattivanti usate nella maggior parte delle app. Con l'aumento della velocità di acquisizione dei contenuti multimediali e il passaggio dei contenuti dalla definizione standard all'alta definizione, aumenta anche la quantità di risorse necessarie per archiviare, decodificare e riprodurre questi contenuti. Poiché il framework XAML si basa sulle funzionalità più recenti aggiunte ai motori multimediali della piattaforma UWP, le app usufruiscono gratuitamente di questi miglioramenti. Ecco alcuni suggerimenti aggiuntivi che ti permettono di ottenere il massimo dai contenuti multimediali nella tua app UWP.

Rilasciare flussi multimediali

I file multimediali rappresentano alcune delle app di risorse più comuni e dispendiose solitamente utilizzate. Poiché le risorse dei file multimediali possono aumentare enormemente la dimensione del footprint di memoria dell'app, devi ricordarti di rilasciare l'handle sui contenuti multimediali non appena l'app ha terminato di usarli.

Se, ad esempio, la tua app usa un oggetto RandomAccessStream o IInputStream, devi assicurarti di chiamare il metodo close su tale oggetto quando l'app ha finito di usarlo, in modo da rilasciare l'oggetto sottostante.

Visualizzare la riproduzione dei video a schermo intero quando possibile

Nelle app UWP usa sempre la proprietà IsFullWindow in MediaPlayerElement per abilitare e disabilitare il rendering a finestra intera. In questo modo, puoi assicurarti che durante la riproduzione dei contenuti multimediali vengano applicate le ottimizzazioni a livello di sistema.

Il framework XAML può ottimizzare la visualizzazione di un contenuto video quando si tratta dell'unico elemento sottoposto a rendering, con il risultato di richiedere una minore quantità di energia e garantire una maggiore frequenza dei fotogrammi. Per rendere più efficiente la riproduzione dei contenuti multimediali, imposta le dimensioni di un elemento MediaPlayerElement sulla larghezza e altezza dello schermo e non visualizzare altri elementi XAML.

Esistono motivi validi per sovrapporre elementi XAML a un oggetto MediaPlayerElement che occupa l'intera larghezza e altezza dello schermo, come nel caso dei sottotitoli o dei controlli del trasporto momentanei. Assicurati di nascondere questi elementi (imposta Visibility="Collapsed") quando non sono necessari per riportare la riproduzione multimediale alla massima efficienza possibile.

Disattivazione del display e risparmio energetico

Per impedire la disattivazione del display quando non vengono più rilevate azioni utente, ad esempio durante la riproduzione di video, puoi chiamare DisplayRequest.RequestActive.

Per risparmiare energia e aumentare la durata della batteria, ti consigliamo di chiamare DisplayRequest.RequestRelease per rilasciare la richiesta sullo schermo quando non è più necessaria.

Ecco alcune situazioni in cui è consigliabile rilasciare la richiesta sullo schermo:

  • La riproduzione video è in pausa, ad esempio per intervento dell'utente, per il buffering o per regolazioni dovute alla larghezza di banda limitata.
  • La riproduzione viene interrotta. Ad esempio, il video o la presentazione è terminato.
  • Si è verificato un errore di riproduzione. Ad esempio, si sono riscontrati problemi di connessione alla rete oppure il file è danneggiato.

Posizionare altri elementi lateralmente al video incorporato

Spesso le app offrono una visualizzazione incorporata in cui il video viene riprodotto all'interno di una pagina. In questi casi, si perde ovviamente l'ottimizzazione dello schermo intero in quanto l'oggetto MediaPlayerElement non ha le dimensioni della pagina e inoltre sono disegnati altri oggetti XAML. Presta attenzione a non attivare casualmente questa modalità disegnando un bordo intorno a un MediaPlayerElement.

Non disegnare elementi XAML al di sopra del contenuto video quando si trova nella modalità incorporata. In caso contrario, si costringerà il framework a eseguire un piccolo lavoro aggiuntivo per comporre la scena. L'inserimento dei controlli di trasporto al di sotto di un elemento multimediale incorporato, anziché al di sopra del video, rappresenta un buon esempio di ottimizzazione di questa situazione. In questa immagine la barra rossa indica una serie di controlli di trasporto (riproduzione, pausa, interruzione e così via).

MediaPlayerElement with overlaying elements

Non inserire questi controlli al di sopra di un contenuto multimediale che non occupi lo schermo intero. Collocali piuttosto in un punto esterno all'area in cui viene eseguito il rendering del contenuto multimediale. Nell'immagine successiva i controlli vengono posizionati al di sotto del contenuto multimediale.

MediaPlayerElement with neighboring elements

Ritardare l'impostazione dell'origine di un MediaPlayerElement

Poiché i motori multimediali sono oggetti costosi, il framework XAML ritarda il caricamento delle DLL e la creazione di oggetti di grandi dimensioni per quanto possibile. L'elemento MediaPlayerElement è costretto a eseguire queste operazioni dopo che la relativa origine è stata impostata tramite la proprietà Source. La configurazione di questa impostazione quando l'utente è realmente pronto a riprodurre i contenuti multimediali consente di ritardare la maggior parte dei costi associati all'elemento MediaPlayerElement per quanto possibile.

Impostare MediaPlayerElement.PosterSource

L'impostazione di MediaPlayerElement.PosterSource consente a XAML di rilasciare alcune risorse GPU che altrimenti sarebbero state usate. Questa API consente di usare la minore quantità possibile di memoria in un'app.

Migliorare lo scrubbing di contenuti multimediali

Lo scrubbing risulta sempre essere un'attività che le piattaforme trovano difficile rendere realmente reattiva. In genere, viene eseguita modificando il valore di un controllo Slider. Ecco alcuni suggerimenti per rendere quanto più efficiente possibile questa operazione:

  • Aggiorna il valore di Slider in base a un timer che effettua una query di Position in MediaPlayerElement.MediaPlayer. Assicurati di usare una frequenza di aggiornamento accettabile per il timer. La proprietà Position viene aggiornata solo ogni 250 millisecondi durante la riproduzione.
  • La dimensione della frequenza dei passaggi sul controllo Slider deve adattarsi alla lunghezza del video.
  • Sottoscrivi gli eventi PointerPressed, PointerMoved, PointerReleased sul controllo Slider per impostare la proprietà PlaybackRate su 0 quando l'utente trascina il cursore del dispositivo di scorrimento.
  • Nel gestore dell'evento PointerReleased imposta manualmente la posizione dell'elemento multimediale sul valore della posizione del controllo Slider in modo da ottenere uno snapping ottimale durante lo scrubbing.

Far corrispondere la risoluzione del video a quella del dispositivo

La decodifica di un video richiede molta memoria e un numero elevato di cicli GPU. Scegli pertanto un formato video che abbia una risoluzione simile a quella che verrà visualizzata. Non ha senso usare le risorse per decodificare un video ad alta definizione (1080) se questo verrà scalato a una dimensione notevolmente inferiore. Molte app non prevedono la codifica dello stesso video a risoluzioni diverse, ma se disponibile, usa una codifica vicina alla risoluzione con cui verrà visualizzato.

La scelta del formato multimediale può essere un argomento delicato e condizionato da decisioni aziendali. Da un punto di vista delle prestazioni della piattaforma UWP, consigliamo il formato video H.264 come formato principale e AAC e MP3 come formati audio preferiti. Per la riproduzione di file locali, MP4 è il contenitore file preferito per i contenuti video. La decodifica H.264 viene accelerata tramite l'hardware grafico più recente. Inoltre, sebbene l'accelerazione hardware per la decodifica VC-1 sia ampiamente disponibile, per una vasta serie di hardware grafico sul mercato l'accelerazione è limitata in molti casi a un livello di accelerazione parziale (o livello IDCT), piuttosto che a un offload hardware a livello full-steam (vale a dire modalità VLD).

Se disponi di controllo completo sul processo di generazione dei contenuti video, prova a immaginare in che modo mantenere un buon equilibrio tra efficienza della compressione e struttura GOP. Dimensioni GOP relativamente inferiori con immagini B possono migliorare le prestazioni nelle modalità di ricerca e riavvolgimento rapido.

Se includi effetti audio brevi a bassa latenza, ad esempio nei giochi, usa file WAV con dati PCM non compressi per ridurre l'overhead di elaborazione tipico dei formati audio compressi.

Ottimizzare le risorse immagine

Scalare le immagini alle dimensioni appropriate

Le immagini vengono acquisite a risoluzioni molto alte. Ciò fa sì che le app usino una gran quantità di CPU quando decodificano i dati delle immagini e una maggiore quantità di memoria dopo averli caricati dal disco. Non ha alcun senso decodificare e salvare in memoria un'immagine a elevata risoluzione se verrà visualizzata con una dimensione più bassa rispetto a quella nativa. Crea invece una versione dell'immagine con le dimensioni esatte con cui verrà visualizzata sullo schermo usando le proprietà DecodePixelWidth e DecodePixelHeight.

Non eseguire la seguente operazione:

<Image Source="ms-appx:///Assets/highresCar.jpg"
       Width="300" Height="200"/>    <!-- BAD CODE DO NOT USE.-->

Al contrario, eseguire questa operazione:

<Image>
    <Image.Source>
    <BitmapImage UriSource="ms-appx:///Assets/highresCar.jpg"
                 DecodePixelWidth="300" DecodePixelHeight="200"/>
    </Image.Source>
</Image>

Per impostazione predefinita, le unità per le proprietà DecodePixelWidth e DecodePixelHeight sono i pixel fisici. La proprietà DecodePixelType può essere usata per cambiare questo comportamento: impostando DecodePixelType su Logical, le dimensioni della decodifica usano automaticamente il fattore di scala corrente del sistema, in modo analogo a quanto accade con altri contenuti XAML. In linea generale, sarebbe pertanto opportuno impostare DecodePixelType su Logical se, ad esempio, vuoi che le proprietà DecodePixelWidth e DecodePixelHeight corrispondano alle proprietà Height e Width del controllo immagine in cui verrà visualizzata l'immagine. Dato il comportamento predefinito derivante dall'uso di pixel fisici, devi autonomamente considerare il fattore di scala corrente del sistema, nonché valutare le notifiche relative alle variazioni di scala nel caso in cui gli utenti modifichino le proprie preferenze di visualizzazione.

Se le proprietà DecodePixelWidth/DecodePixelHeight vengono impostate su un valore maggiore rispetto all'immagine visualizzata sullo schermo, l'app userà inutilmente una quantità aggiuntiva di memoria (fino a 4 byte per pixel) e ciò risulta dispendioso a livello di risorse in caso di immagini di grandi dimensioni. L'immagine verrà inoltre ridotta in base a una scala bilineare che potrebbe causare una visualizzazione poco nitida con fattori di scala elevati.

Se le proprietà DecodePixelWidth/DecodePixelHeight sono impostate in modo esplicito su un valore più piccolo rispetto all'immagine visualizzata sullo schermo, l'immagine verrà ingrandita e potrebbe apparire con effetto pixel.

In alcuni casi, dove risulta impossibile determinare in anticipo le dimensioni della decodifica appropriate, dovresti usare la decodifica automatica in base alle dimensioni appropriate disponibile in XAML. Questa funzionalità effettuerà il miglior tentativo possibile di decodifica dell'immagine alla dimensione corretta se non sono state impostate in modo esplicito le proprietà DecodePixelWidth/DecodePixelHeight.

Ti consigliamo di impostare una dimensione di decodifica esplicita se conosci le dimensioni del contenuto dell'immagine. Parallelamente, dovresti impostare anche DecodePixelType su Logical se le dimensioni della decodifica fornite sono relative ad altre dimensioni di elementi XAML. Ad esempio, se imposti in modo esplicito le dimensioni del contenuto tramite Image.Width e Image.Height, puoi impostare DecodePixelType su DecodePixelType.Logical per usare le stesse dimensioni di pixel logici del controllo immagine e quindi usare in modo esplicito BitmapImage.DecodePixelWidth e/o BitmapImage.DecodePixelHeight per controllare le dimensioni dell'immagine in modo da ottenere un risparmio potenzialmente elevato a livello di memoria.

Tieni presente che dovresti considerare l'uso di Image.Stretch quando determini le dimensioni del contenuto decodificato.

Decodifica in base alle dimensioni appropriate

Se non imposti un valore esplicito per le dimensioni di decodifica, XAML effettuerà il miglior tentativo possibile di risparmiare memoria decodificando un'immagine in base alla dimensione esatta con cui verrà visualizzata sullo schermo usando il layout della pagina iniziale della pagina contenitore. Ti consigliamo di scrivere l'applicazione in modo tale da usare, quando possibile, questa funzionalità. Questa funzionalità verrà disattivata se viene soddisfatta una delle condizioni seguenti.

  • La classe BitmapImage è connessa all'albero XAML dinamico dopo aver impostato il contenuto tramite SetSourceAsync o UriSource.
  • L'immagine viene decodificata usando la decodifica sincrona, ad esempio SetSource.
  • L'immagine è nascosta tramite l'impostazione di Opacity su 0 o di Visibility su Collapsed nell'elemento immagine host, nel pennello immagine o in qualsiasi elemento padre.
  • Il controllo immagine o il pennello immagine usa l'enumerazione Stretch impostata su None.
  • L'immagine viene usata come NineGrid.
  • CacheMode="BitmapCache" è impostato sull'elemento immagine o su qualsiasi elemento padre.
  • Il pennello immagine non è rettangolare, ad esempio quando è applicato a una forma o al testo.

Negli scenari descritti in precedenza, impostare un valore esplicito per le dimensioni della decodifica è l'unico modo per ottenere un risparmio a livello di memoria.

Devi sempre collegare BitmapImage all'albero dinamico prima di impostare l'origine. Ogni volta che un elemento immagine o un pennello immagine è specificato nel markup, sarà automaticamente valido questo scenario. Gli esempi vengono forniti nella sezione "Esempi di albero dinamico". Ti consigliamo di evitare di usare SetSource e invece usare SetSourceAsync quando imposti un'origine del flusso. Ti consigliamo inoltre di non nascondere il contenuto dell'immagine (con opacità pari a zero o con visibilità compressa) durante l'attesa dell'evento ImageOpened. La scelta di operare in questo modo è una decisione del tutto discrezionale. Non potrai tuttavia avvalerti dei vantaggi della decodifica automatica in base alle dimensioni appropriate se usi questa funzionalità. Se la tua app deve inizialmente nascondere il contenuto dell'immagine, dovrà anche impostare le dimensioni della decodifica in modo esplicito, se possibile.

Esempi di albero dinamico

Esempio 1 (corretto): Uniform Resource Identifier (URI) specificato nel markup.

<Image x:Name="myImage" UriSource="Assets/cool-image.png"/>

Esempio 2 (markup): URI specificato nel file code-behind.

<Image x:Name="myImage"/>

Esempio 2 (code-behind) (corretto): connessione di BitmapImage all'albero prima di impostare il relativo valore di UriSource.

var bitmapImage = new BitmapImage();
myImage.Source = bitmapImage;
bitmapImage.UriSource = new URI("ms-appx:///Assets/cool-image.png", UriKind.RelativeOrAbsolute);

Esempio 2 (code-behind) (errato): impostazione di UriSource per BitmapImage prima della relativa connessione all'albero.

var bitmapImage = new BitmapImage();
bitmapImage.UriSource = new URI("ms-appx:///Assets/cool-image.png", UriKind.RelativeOrAbsolute);
myImage.Source = bitmapImage;

Ottimizzazioni della memorizzazione nella cache

Le ottimizzazioni della memorizzazione nella cache sono valide per le immagini che usano UriSource per caricare il contenuto da un pacchetto dell'app o dal web. L'URI viene usato per identificare in modo univoco il contenuto sottostante; internamente il framework XAML non scaricherà o decodificherà il contenuto più volte. Al contrario, userà le risorse hardware o software memorizzate nella cache per visualizzare il contenuto più volte.

L'eccezione a questo tipo di ottimizzazione è nel caso in cui l'immagine viene visualizzata più volte a risoluzioni diverse (ciò può essere specificato in modo esplicito oppure mediante la decodifica automatica in base alle dimensioni appropriate). Ogni voce della cache memorizza anche la risoluzione dell'immagine e se XAML non riesce a trovare un'immagine con un URI di origine corrispondente alla risoluzione richiesta, verrà decodificata una nuova versione con tali dimensioni. Non verranno tuttavia scaricati di nuovo i dati dell'immagine codificata.

Di conseguenza, dovresti usare UriSource quando carichi immagini da un pacchetto dell'app ed evitare l'uso di un flusso di file e SetSourceAsync quando non è richiesto.

Immagini nei pannelli virtualizzati (ad esempio, ListView)

Se un'immagine viene rimossa dall'albero (perché l'app l'ha rimossa in modo esplicito o perché si trova in un pannello virtualizzato di ultima generazione e l'immagine è stata rimossa in modo implicito quando in seguito allo scorrimento è uscita dalla visualizzazione), XAML ottimizzerà l'uso della memoria rilasciando le risorse hardware per l'immagine dato che non sono più necessarie. La memoria non viene rilasciata immediatamente, ma durante l'aggiornamento dei fotogrammi eseguito un secondo dopo che l'elemento immagine non si trova più nell'albero.

Di conseguenza, ti consigliamo di usare i moderni pannelli virtualizzati per l'hosting degli elenchi dei contenuti delle immagini.

Immagini con rasterizzazione software

Quando viene usata per un pennello immagine non rettangolare o per una proprietà NineGrid, l'immagine userà un percorso di rasterizzazione software, che non eseguirà alcun adattamento delle immagini. Inoltre, dovrà archiviare una copia dell'immagine nella memoria hardware e software. Ad esempio, se un'immagine viene usata come pennello immagine per un'ellisse, l'immagine completa con dimensioni potenzialmente rilevanti verrà archiviata internamente due volte. In caso di uso di NineGrid o di un pennello immagine non rettangolare, la tua app deve adattare preventivamente le relative immagini in base alla dimensione approssimativa con cui tali immagini verranno visualizzate.

Caricamento di immagini in thread in background

XAML dispone di una funzionalità di ottimizzazione interna che consente la decodifica asincrona dei contenuti di un'immagine su una superficie della memoria hardware senza aver bisogno di una superficie intermedia nella memoria software. In questo modo vengono ridotti il picco di uso della memoria e la latenza del rendering. Questa funzionalità verrà disattivata se viene soddisfatta una delle condizioni seguenti.

  • L'immagine viene usata come NineGrid.
  • CacheMode="BitmapCache" è impostato sull'elemento immagine o su qualsiasi elemento padre.
  • Il pennello immagine non è rettangolare, ad esempio quando è applicato a una forma o al testo.

SoftwareBitmapSource

La classe SoftwareBitmapSource effettua lo scambio di immagini non compresse interoperabili tra spazi dei nomi WinRT diversi, ad esempio BitmapDecoder, API delle fotocamere e XAML. Questa classe consente di evitare l'archiviazione della copia aggiuntiva in genere necessaria in caso di uso della classe WriteableBitmap. Ciò consente di ridurre il picco di uso della memoria e la latenza dà origine a schermo.

La classe SoftwareBitmap fornisce le informazioni sull'origine e può essere configurata anche per l'uso di un'interfaccia IWICBitmap personalizzata per fornire un archivio di backup ricaricabile che consente all'app di rimappare la memoria in base alle esigenze. Si tratta di un caso di uso di C++ avanzato.

La tua app deve usare SoftwareBitmap e SoftwareBitmapSource per interagire con altre API WinRT che generano e usano immagini. La tua app deve inoltre usare SoftwareBitmapSource durante il caricamento dei dati di immagini non compressi anziché usare WriteableBitmap.

Usare GetThumbnailAsync per le anteprime

Un caso di uso per il ridimensionamento delle immagini è rappresentato dalla creazione delle anteprime. Benché sia possibile usare DecodePixelWidth e DecodePixelHeight per fornire versioni ridotte delle immagini, la piattaforma UWP offre API ancora più efficienti per il recupero delle anteprime. GetThumbnailAsync fornisce le anteprime per immagini il cui file system è già memorizzato nella cache. In questo modo si ottengono prestazioni anche migliori rispetto alle API di XAML in quanto non è necessario aprire né decodificare l'immagine.

FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".bmp");
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;

StorageFile file = await picker.PickSingleFileAsync();

StorageItemThumbnail fileThumbnail = await file.GetThumbnailAsync(ThumbnailMode.SingleItem, 64);

BitmapImage bmp = new BitmapImage();
bmp.SetSource(fileThumbnail);

Image img = new Image();
img.Source = bmp;
Dim picker As New FileOpenPicker()
picker.FileTypeFilter.Add(".bmp")
picker.FileTypeFilter.Add(".jpg")
picker.FileTypeFilter.Add(".jpeg")
picker.FileTypeFilter.Add(".png")
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary

Dim file As StorageFile = Await picker.PickSingleFileAsync()

Dim fileThumbnail As StorageItemThumbnail = Await file.GetThumbnailAsync(ThumbnailMode.SingleItem, 64)

Dim bmp As New BitmapImage()
bmp.SetSource(fileThumbnail)

Dim img As New Image()
img.Source = bmp

Decodificare le immagini una sola volta

Per evitare che le immagini vengano decodificate più volte, assegna la proprietà Image.Source di un Uri anziché usare i flussi di memoria. Il framework XAML può associare lo stesso Uri in più posizioni a un'immagine decodificata, ma non è in grado di eseguire la stessa operazione per più flussi di memoria contenenti gli stessi dati e crea quindi un'immagine decodificata differente per ogni flusso di memoria.