Mengoptimalkan animasi, media, dan gambar

Buat aplikasi WinUI dengan animasi halus, kecepatan bingkai tinggi, dan pengambilan dan pemutaran media berkinerja tinggi.

Membuat animasi menjadi halus

Aspek utama dari aplikasi WinUI adalah interaksi yang lancar. Ini termasuk manipulasi sentuh yang "menempel pada jari Anda," transisi dan animasi halus, dan gerakan kecil yang memberikan umpan balik input. Dalam kerangka kerja XAML ada utas yang disebut utas komposisi yang didedikasikan untuk komposisi dan animasi elemen visual aplikasi. Karena utas komposisi terpisah dari utas UI (utas yang menjalankan kerangka kerja dan kode pengembang), aplikasi dapat mencapai tingkat bingkai yang konsisten dan animasi yang lancar meskipun ada tata letak yang rumit atau perhitungan yang panjang. Bagian ini menunjukkan cara menggunakan utas komposisi untuk menjaga animasi aplikasi tetap sangat halus dan lancar. Untuk informasi selengkapnya tentang animasi, lihat Gambaran umum Animasi. Untuk mempelajari tentang meningkatkan responsivitas aplikasi saat melakukan komputasi intensif, lihat Menjaga utas UI tetap responsif.

Gunakan animasi independen alih-alih dependen

Animasi independen dapat dihitung dari awal hingga akhir pada saat pembuatan karena perubahan pada properti yang dianimasikan tidak memengaruhi objek lainnya dalam adegan. Oleh karena itu, animasi independen dapat berjalan pada utas komposisi alih-alih utas UI. Ini menjamin bahwa mereka tetap lancar karena utas komposisi diperbarui pada irama yang konsisten.

Semua jenis animasi ini dijamin independen:

Animasi dependen memengaruhi tata letak, sehingga tidak dapat dihitung tanpa input tambahan dari thread UI. Animasi dependen mencakup modifikasi pada properti seperti Lebar dan Tinggi. Secara default, animasi dependen tidak dijalankan dan memerlukan keikutsertaan dari pengembang aplikasi. Saat diaktifkan, proses tersebut berjalan dengan lancar jika utas UI tetap tidak diblokir, tetapi mulai terganggu jika kerangka kerja atau aplikasi melakukan banyak pekerjaan lain di utas UI.

Hampir semua animasi dalam kerangka kerja XAML independen secara default, tetapi ada beberapa tindakan yang dapat Anda ambil untuk menonaktifkan pengoptimalan ini. Waspadalah terhadap skenario ini terutama:

  • Mengatur properti EnableDependentAnimation untuk memungkinkan animasi dependen berjalan pada utas UI. Konversikan animasi ini menjadi versi independen. Misalnya animasikan ScaleTransform.ScaleX dan ScaleTransform.ScaleY alih-alih Lebar dan Tinggi objek. Jangan takut untuk menskalakan objek seperti gambar dan teks. Kerangka kerja hanya menerapkan penskalaan bilinear saat ScaleTransform sedang dianimasikan. Gambar/teks akan diraster ulang pada ukuran akhir untuk memastikannya selalu jelas.
  • Membuat pembaruan per bingkai, yang secara efektif bergantung pada animasi. Contohnya adalah menerapkan transformasi dalam handler peristiwa CompositionTarget.Rendering .
  • Menjalankan animasi apa pun yang dianggap independen dalam elemen dengan properti CacheMode diatur ke BitmapCache. Ini dianggap tergantung karena cache harus diraster ulang untuk setiap frame.

Jangan animasikan WebView2 atau MediaPlayerElement

Konten web yang dihosting dalam kontrol WebView2 tidak dirender langsung oleh kerangka kerja XAML, sehingga menyusunnya dengan adegan lainnya memerlukan pekerjaan tambahan. Overhead itu bertambah ketika Anda menganimasikan kontrol di sekitar layar dan dapat memperkenalkan masalah sinkronisasi, misalnya jika konten web tampaknya tidak sinkron dengan XAML sekitarnya. Jika Anda membutuhkan gerakan seputar konten web, animasikan chrome WinUI di sekitarnya daripada permukaan WebView2 itu sendiri. Panduan sebelumnya mungkin menyebutkan WebViewBrush; di aplikasi WinUI modern, WebView2 adalah kontrol hosting web yang didukung dan tidak ada penggantian WebViewBrush langsung.

Menganimasikan MediaPlayerElement adalah ide yang sama buruknya. Di luar performa yang merugikan, itu dapat menyebabkan merobek atau artefak lain dalam konten video yang diputar.

Gunakan animasi tak terbatas dengan hemat

Sebagian besar animasi dijalankan untuk jumlah waktu tertentu, tetapi mengatur properti Timeline.Duration ke Selamanya memungkinkan animasi berjalan tanpa batas waktu. Sebaiknya minimalkan penggunaan animasi tak terbatas karena terus mengonsumsi sumber daya CPU dan dapat mencegah CPU masuk ke status daya rendah atau menganggur, menyebabkan kehabisan daya dengan lebih cepat.

Menambahkan handler untuk CompositionTarget.Rendering mirip dengan menjalankan animasi tak terbatas. Biasanya, utas UI hanya aktif ketika ada pekerjaan yang harus dilakukan, tetapi menambahkan handler untuk peristiwa ini memaksanya untuk berjalan di setiap frame. Hapus handler ketika tidak ada pekerjaan yang harus dilakukan dan daftarkan ulang ketika diperlukan lagi.

Menggunakan pustaka animasi

Namespace Microsoft.UI.Xaml.Media.Animation mencakup pustaka animasi berkinerja tinggi dan halus yang memiliki tampilan dan nuansa konsisten dengan animasi Windows lainnya. Kelas yang relevan memiliki "Tema" dalam namanya, dan dijelaskan dalam gambaran umum Animasi. Pustaka ini mendukung banyak skenario animasi umum, seperti menganimasikan tampilan pertama aplikasi dan membuat transisi status dan konten. Sebaiknya gunakan pustaka animasi ini jika memungkinkan untuk meningkatkan performa dan konsistensi untuk aplikasi WinUI.

Catatan Pustaka animasi tidak dapat menganimasikan semua properti yang mungkin. Untuk skenario XAML di mana pustaka animasi tidak berlaku, lihat Animasi Berpapan Cerita.

Menganimasikan properti CompositeTransform3D secara independen

Anda dapat menganimasikan setiap properti CompositeTransform3D secara independen, jadi hanya terapkan animasi yang Anda butuhkan. Untuk contoh dan info selengkapnya, lihat UIElement.Transform3D. Untuk informasi selengkapnya tentang menganimasikan transformasi, lihat Animasi storyboarded dan Animasi key-frame dan fungsi easing.

Mengoptimalkan sumber daya media

Audio, video, dan gambar adalah bentuk konten yang menarik yang digunakan sebagian besar aplikasi. Ketika tingkat penangkapan media meningkat dan konten berpindah dari definisi standar ke definisi tinggi, jumlah sumber daya yang diperlukan untuk menyimpan, mendekode, dan memutar kembali konten ini meningkat. Kerangka kerja XAML dibangun pada infrastruktur media Windows modern, sehingga aplikasi WinUI mewarisi banyak peningkatan ini secara otomatis. Berikut adalah beberapa trik tambahan yang membantu Anda mendapatkan hasil maksimal dari media di aplikasi WinUI Anda.

Merilis aliran media

File media adalah salah satu sumber daya yang paling umum dan mahal yang biasanya digunakan oleh aplikasi. Karena sumber daya file media dapat sangat meningkatkan ukuran jejak memori aplikasi, Anda harus ingat untuk segera melepaskan handle ke media setelah aplikasi selesai menggunakannya.

Misalnya, jika aplikasi Anda bekerja dengan RandomAccessStream atau objek IInputStream , pastikan untuk memanggil metode tutup pada objek saat aplikasi Anda selesai menggunakannya, untuk merilis objek yang mendasar.

Tampilkan pemutaran video layar penuh jika memungkinkan

Di aplikasi WinUI, selalu gunakan properti IsFullWindow di MediaPlayerElement untuk mengaktifkan dan menonaktifkan penyajian jendela penuh. Ini memastikan pengoptimalan tingkat sistem digunakan selama pemutaran media.

Kerangka kerja XAML dapat mengoptimalkan tampilan konten video ketika itu adalah satu-satunya hal yang dirender, menghasilkan pengalaman yang menggunakan lebih sedikit daya dan menghasilkan kecepatan bingkai yang lebih tinggi. Untuk pemutaran media yang paling efisien, atur ukuran MediaPlayerElement menjadi lebar dan tinggi layar dan jangan tampilkan elemen XAML lainnya.

Ada alasan yang sah untuk melapisi elemen XAML pada MediaPlayerElement yang mengambil lebar dan tinggi layar penuh, misalnya teks tertutup atau kontrol transportasi sesaat. Pastikan untuk menyembunyikan elemen-elemen ini (diatur Visibility="Collapsed") ketika tidak diperlukan untuk menempatkan pemutaran media kembali ke status yang paling efisien.

Penonaktifan layar dan penghematan daya

Untuk mencegah tampilan dinonaktifkan saat tindakan pengguna tidak lagi terdeteksi, seperti saat aplikasi memutar video, Anda dapat memanggil DisplayRequest.RequestActive.

Untuk menghemat daya dan masa pakai baterai, Anda harus memanggil DisplayRequest.RequestRelease untuk melepaskan permintaan tampilan segera setelah tidak lagi diperlukan.

Berikut adalah beberapa situasi ketika Anda harus merilis permintaan tampilan:

  • Pemutaran video dijeda, misalnya oleh tindakan pengguna, buffering, atau penyesuaian karena bandwidth terbatas.
  • Pemutaran berhenti. Misalnya, video selesai diputar atau presentasi selesai.
  • Terjadi kesalahan pemutaran. Misalnya, masalah konektivitas jaringan atau file yang rusak.

Letakkan elemen lain di samping video yang disematkan

Seringkali aplikasi menawarkan tampilan yang disematkan di mana video diputar dalam halaman. Sekarang Anda jelas kehilangan pengoptimalan layar penuh karena MediaPlayerElement tidak memenuhi seluruh halaman dan ada objek XAML lain yang ditampilkan. Waspadalah terhadap masuknya mode ini secara tidak sengaja dengan menggambar batas di sekitar MediaPlayerElement.

Jangan gambar elemen XAML di atas video saat dalam mode tersemat. Jika Anda melakukannya, kerangka kerja dipaksa untuk melakukan sedikit pekerjaan ekstra untuk menyusun adegan. Menempatkan kontrol transportasi di bawah elemen media yang disematkan alih-alih di atas video adalah contoh yang baik untuk mengoptimalkan situasi ini. Dalam gambar ini, bilah merah menunjukkan serangkaian kontrol transportasi (putar, jeda, hentikan, dan sebagainya).

MediaPlayerElement dengan elemen yang menumpuk

Jangan letakkan kontrol ini di atas media yang tidak layar penuh. Sebagai gantinya, letakkan kontrol transportasi di lokasi yang berada di luar area tempat media sedang diputar. Pada gambar berikutnya, kontrol ditempatkan di bawah media.

MediaPlayerElement dengan elemen yang berdekatan

Penundaan pengaturan sumber untuk MediaPlayerElement

Mesin media adalah objek mahal dan kerangka kerja XAML menunda pemuatan DLL dan membuat objek besar selama mungkin. MediaPlayerElement dipaksa untuk melakukan pekerjaan ini setelah sumbernya diatur melalui properti Sumber. Mengatur ini ketika pengguna benar-benar siap untuk memutar media menunda sebagian besar biaya yang terkait dengan MediaPlayerElement selama mungkin.

Atur PosterSource dari MediaPlayerElement

Mengatur MediaPlayerElement.PosterSource memungkinkan XAML merilis beberapa sumber daya GPU yang seharusnya digunakan. API ini memungkinkan aplikasi untuk menggunakan memori sesedikitan mungkin.

Meningkatkan penelusuran media

Scrubbing selalu merupakan tugas yang berat bagi platform media agar benar-benar responsif. Umumnya orang menyelesaikan ini dengan mengubah nilai Slider. Berikut adalah beberapa tips tentang cara membuat ini seefisien mungkin:

  • Perbarui nilai Slider berdasarkan timer yang meminta Posisi pada MediaPlayerElement.MediaPlayer. Pastikan untuk menggunakan frekuensi pembaruan yang wajar untuk timer Anda. Properti Posisi hanya memperbarui setiap 250 milidetik selama pemutaran.
  • Ukuran frekuensi langkah pada Penggeser harus diskalakan dengan panjang video.
  • Berlangganan ke peristiwa PointerPressed, PointerMoved, PointerReleased pada slider untuk mengatur properti PlaybackRate ke 0 saat pengguna menyeret jempol slider.
  • Di penanganan aktivitas PointerReleased , atur posisi media secara manual ke nilai posisi penggeser untuk mencapai jempol yang optimal saat menggosok.

Cocokkan resolusi video dengan resolusi perangkat

Video decoding membutuhkan banyak siklus memori dan GPU, jadi pilih format video yang dekat dengan resolusi yang akan ditampilkan. Tidak ada gunanya menggunakan sumber daya untuk mendekode video 1080 jika akan diturunkan skalanya ke ukuran yang jauh lebih kecil. Banyak aplikasi tidak memiliki video yang sama yang dikodekan dalam resolusi berbeda; tetapi jika tersedia, gunakan pengodean yang mendekati resolusi tempat video akan ditampilkan.

Pemilihan format media dapat menjadi topik sensitif dan sering didorong oleh keputusan bisnis. Dari perspektif performa SDK Aplikasi Windows, kami merekomendasikan video H.264 sebagai format video utama dan AAC dan MP3 sebagai format audio pilihan. Untuk pemutaran file lokal, MP4 adalah kontainer file pilihan untuk konten video. Decoding H.264 dipercepat melalui perangkat keras grafis terbaru. Selain itu, meskipun akselerasi perangkat keras untuk dekoding VC-1 tersedia secara luas, untuk sekumpulan besar perangkat keras grafis di pasar, akselerasinya dalam banyak kasus terbatas pada tingkat akselerasi parsial (atau tingkat IDCT), alih-alih pelepasan perangkat keras aliran penuh (yaitu, mode VLD).

Jika Anda memiliki kontrol penuh atas proses pembuatan konten video, Anda harus mencari tahu cara menjaga keseimbangan yang baik antara efisiensi kompresi dan struktur GOP. Ukuran GOP yang relatif lebih kecil dengan gambar B dapat meningkatkan performa dalam mode pencarian atau mode trik.

Ketika menyertakan efek audio latensi rendah yang pendek, misalnya dalam game, gunakan file WAV dengan data PCM yang tidak dikompresi untuk mengurangi overhead pemrosesan yang khas untuk format audio terkompresi.

Mengoptimalkan sumber daya gambar

Menskalakan gambar ke ukuran yang sesuai

Gambar diambil pada resolusi yang sangat tinggi, yang dapat menyebabkan aplikasi menggunakan lebih banyak CPU saat mendekode data gambar dan lebih banyak memori setelah dimuat dari disk. Tetapi tidak ada gunanya mendekode dan menyimpan gambar resolusi tinggi dalam memori hanya untuk menampilkannya lebih kecil dari ukuran aslinya. Sebagai gantinya, buat versi gambar pada ukuran yang tepat akan digambar di layar menggunakan properti DecodePixelWidth dan DecodePixelHeight .

Jangan lakukan ini:

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

Sebagai gantinya, lakukan ini:

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

Unit untuk DecodePixelWidth dan DecodePixelHeight adalah piksel fisik default. Properti DecodePixelType dapat digunakan untuk mengubah perilaku ini: menetapkan DecodePixelType ke Logical akan menyebabkan ukuran dekode secara otomatis memperhitungkan faktor skala sistem saat ini, mirip dengan konten XAML lainnya. Oleh karena itu, umumnya akan sesuai untuk mengatur DecodePixelType ke Logical jika, misalnya, Anda ingin DecodePixelWidth dan DecodePixelHeight cocok dengan properti Tinggi dan Lebar dari kontrol Gambar tempat gambar akan ditampilkan. Dengan perilaku default menggunakan piksel fisik, Anda harus memperhitungkan sendiri faktor skala sistem saat ini; dan Anda harus mendengarkan pemberitahuan perubahan skala jika pengguna mengubah preferensi tampilan mereka.

Jika DecodePixelWidth/Height secara eksplisit diatur lebih besar dari ukuran gambar saat ditampilkan di layar, maka aplikasi akan menggunakan memori tambahan yang tidak perlu—hingga 4 byte per piksel—yang dengan cepat menjadi beban biaya untuk gambar besar. Gambar juga akan diskalakan ke bawah menggunakan penskalaan bilinear yang dapat menyebabkannya tampak buram untuk faktor skala besar.

Jika DecodePixelWidth/DecodePixelHeight secara eksplisit diatur lebih kecil daripada ukuran tampilan gambar di layar, gambar tersebut akan diperbesar skalanya dan dapat terlihat pecah.

Dalam beberapa kasus di mana ukuran dekode yang tepat tidak dapat ditentukan sebelumnya, Anda sebaiknya mengandalkan dekoding ukuran tepat otomatis XAML, yang akan berupaya sebaik mungkin untuk mendekode gambar pada ukuran yang sesuai jika DecodePixelWidth/DecodePixelHeight tidak ditentukan secara jelas.

Anda harus mengatur ukuran dekode eksplisit jika Anda mengetahui ukuran konten gambar sebelumnya. Anda juga harus secara bersamaan mengatur DecodePixelType ke Logical jika ukuran dekode yang disediakan relatif terhadap ukuran elemen XAML lainnya. Misalnya, jika Anda secara eksplisit mengatur ukuran konten dengan Image.Width dan Image.Height, Anda dapat mengatur DecodePixelType ke DecodePixelType.Logical untuk menggunakan dimensi piksel logis yang sama sebagai kontrol Gambar dan kemudian secara eksplisit menggunakan BitmapImage.DecodePixelWidth dan/atau BitmapImage.DecodePixelHeight untuk mengontrol ukuran gambar untuk mencapai penghematan memori yang berpotensi besar.

Perhatikan bahwa Image.Stretch harus dipertimbangkan saat menentukan ukuran konten yang didekodekan.

Decoding berukuran tepat

Jika Anda tidak mengatur ukuran dekode eksplisit, XAML akan melakukan upaya terbaik untuk menyimpan memori dengan mendekode gambar ke ukuran yang tepat yang akan muncul di layar sesuai dengan tata letak awal halaman yang berisi. Anda disarankan untuk menulis aplikasi Anda sedemikian rupa agar dapat menggunakan fitur ini jika memungkinkan. Fitur ini akan dinonaktifkan jika salah satu kondisi berikut terpenuhi.

  • BitmapImage terhubung ke pohon XAML langsung setelah mengatur konten dengan SetSourceAsync atau UriSource.
  • Gambar didekode menggunakan decoding sinkron seperti SetSource.
  • Gambar disembunyikan melalui pengaturan Opacity ke 0 atau Visibility untuk Diciutkan pada elemen gambar host atau kuas atau elemen induk apa pun.
  • Kontrol gambar atau kuas menggunakan Stretch of None.
  • Gambar digunakan sebagai NineGrid.
  • CacheMode="BitmapCache" diatur pada elemen gambar atau pada elemen induk apa pun.
  • Kuas gambar tidak persegi panjang (seperti saat diterapkan ke bentuk atau ke teks).

Dalam skenario di atas, mengatur ukuran dekode eksplisit adalah satu-satunya cara untuk mencapai penghematan memori.

Anda harus selalu melampirkan BitmapImage ke pohon visual sebelum mengatur sumber. Setiap kali elemen gambar atau kuas ditentukan dalam markup, ini akan secara otomatis terjadi. Contoh disediakan di bawah judul "Contoh pohon langsung". Anda harus selalu menghindari penggunaan SetSource dan sebagai gantinya menggunakan SetSourceAsync saat mengatur sumber aliran. Dan ada baiknya untuk menghindari menyembunyikan konten gambar (baik dengan opasitas nol atau dengan visibilitas yang diciutkan) sambil menunggu peristiwa ImageOpened dinaikkan. Melakukan ini adalah keputusan berdasarkan pertimbangan: Anda tidak akan mendapat manfaat dari decoding ukuran yang tepat otomatis jika dilakukan. Jika aplikasi Anda harus menyembunyikan konten gambar pada awalnya, aplikasi juga harus mengatur ukuran dekode secara eksplisit jika memungkinkan.

Contoh pohon aktif

Contoh 1 (baik)—Pengidentifikasi Sumber Daya Seragam (URI) yang ditentukan dalam markup.

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

Contoh 2 markup: URI yang ditentukan dalam kode di belakang.

<Image x:Name="myImage"/>

Contoh 2 code-behind (baik)—menyambungkan BitmapImage ke pohon sebelum mengatur UriSource-nya.

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

Contoh 2 code-behind (buruk)—mengatur UriSource BitmapImage sebelum menyambungkannya ke pohon.

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

Optimasi penyimpanan sementara

Pengoptimalan cache tersedia untuk gambar yang menggunakan UriSource untuk memuat konten dari paket aplikasi atau Web. WinUI dapat menggunakan kembali data gambar internal dan sumber daya perenderan untuk URI yang telah di-resolve yang sama pada berbagai instans BitmapImage dan kontrol Image. WinUI menyimpan sumber daya internal ini, bukan objek publik itu sendiri.

Saat resource yang kompatibel masih tersedia, cache hit dapat menghindari pengambilan atau mendekode ulang gambar. Jika URI yang sama memerlukan dimensi dekode fisik yang berbeda, WinUI mungkin membuat versi lain yang didekodekan untuk dimensi tersebut sambil menggunakan kembali data lain yang tersedia. Penggunaan ulang tidak dijamin, jadi kembali ke URI tersebut setelah navigasi dapat memerlukan pengambilan atau pendekodean ulang.

Gunakan UriSource saat gambar memiliki URI dan Anda ingin WinUI mengidentifikasi beban berulang sebagai sumber daya yang sama. Gambar yang diinisialisasi dari aliran terpisah dengan SetSourceAsync tidak memiliki identitas URI bersama, sehingga WinUI mendekode setiap aliran secara independen.

Untuk URI jarak jauh, BitmapImage tidak menentukan apakah pengambilan menggunakan memori atau cache disk, mengirim permintaan kondisional, atau mengunduh konten dari server asal. Penangan URI, tumpukan jaringan, respons server, dan kebijakan cache menentukan perilaku tersebut.

WinUI tidak menyediakan masa aktif, ukuran maksimum, urutan penghapusan, atau operasi untuk mengosongkan cache gambar. Masa pakai cache tidak dijamin sesuai dengan masa pakai aplikasi atau masa pakai kontrol tertentu. Saat Anda menghapus Gambar dari pohon visual dan merilis referensi ke BitmapImage-nya, sumber daya terkait menjadi memenuhi syarat untuk rilis, tetapi WinUI tidak menjamin dengan tepat kapan memori dikembalikan (misalnya, permukaan perangkat keras dapat dirilis segera setelah penghapusan sementara data gambar cache mungkin bertahan lebih lama). Menyimpan instans BitmapImage dapat menyebabkan sumber daya gambar yang terkait tetap tersimpan.

Dimensi dekode yang berbeda dapat memerlukan sumber daya yang didekodekan terpisah dan meningkatkan penggunaan memori. Untuk mengurangi penggunaan memori, skalakan gambar ke ukuran yang sesuai dan gunakan panel virtual untuk koleksi gambar.

Muat ulang gambar pada URI yang sama

Jika konten di URI dapat berubah, atur CreateOptions ke BitmapCreateOptions.IgnoreImageCache sebelum Anda mengatur UriSource. Pengaturan ini mengabaikan entri cache gambar WinUI yang ada untuk pemuatan tersebut dan menyebabkan WinUI mendekode ulang konten yang diambil.

using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Imaging;

private static void RefreshImage(Image image, Uri uri)
{
    var bitmapImage = new BitmapImage
    {
        CreateOptions = BitmapCreateOptions.IgnoreImageCache
    };

    image.Source = bitmapImage;
    bitmapImage.UriSource = uri;
}

IgnoreImageCache mengontrol cache gambar WinUI, bukan semua cache yang terlibat dalam mengambil sumber daya jarak jauh. Jangan mengandalkan opsi ini untuk menjamin bahwa setiap beban menghubungi server asal atau mentransfer respons penuh. Gunakan ini hanya saat konten berubah meskipun URI-nya tetap sama, karena tidak menggunakan kembali menambah beban pengambilan dan pendekodean.

Gambar di panel virtual (ListView, misalnya)

Jika gambar dihapus dari pohon—karena aplikasi secara eksplisit menghapusnya, atau karena berada di panel virtual modern dan secara implisit dihapus saat digulir keluar dari tampilan—maka XAML akan mengoptimalkan penggunaan memori dengan merilis sumber daya perangkat keras untuk gambar karena tidak lagi diperlukan. Memori tidak segera dirilis, melainkan dirilis selama pembaruan bingkai yang terjadi setelah satu detik elemen gambar tidak lagi berada di pohon.

Akibatnya, Anda harus berusaha untuk menggunakan panel virtual modern untuk menghosting daftar konten gambar.

Gambar dirasterisasi secara perangkat lunak

Ketika gambar digunakan untuk kuas non-persegi panjang atau untuk NineGrid, gambar akan menggunakan jalur rasterisasi perangkat lunak, yang tidak akan menskalakan gambar sama sekali. Selain itu, ia harus menyimpan salinan gambar di memori perangkat lunak dan perangkat keras. Misalnya, jika gambar digunakan sebagai kuas untuk elips, gambar penuh yang berpotensi besar akan disimpan dua kali secara internal. Saat menggunakan NineGrid atau kuas non-persegi panjang, aplikasi Anda harus melakukan pra-skala gambarnya ke ukuran yang akan dirender.

Pemuatan gambar utas latar belakang

XAML memiliki pengoptimalan internal yang memungkinkannya untuk mendekode konten gambar secara asinkron ke permukaan dalam memori perangkat keras tanpa memerlukan permukaan menengah dalam memori perangkat lunak. Ini mengurangi penggunaan memori puncak dan latensi penyajian. Fitur ini akan dinonaktifkan jika salah satu kondisi berikut terpenuhi.

  • Gambar digunakan sebagai NineGrid.
  • CacheMode="BitmapCache" diatur pada elemen gambar atau pada elemen induk apa pun.
  • Kuas gambar tidak persegi panjang (seperti saat diterapkan ke bentuk atau ke teks).

SoftwareBitmapSource

Kelas SoftwareBitmapSource bertukar gambar yang tidak dikompresi yang dapat dioperasikan antara namespace WinRT yang berbeda seperti BitmapDecoder, API kamera, dan XAML. Kelas ini menghilangkan kebutuhan untuk proses menyalin tambahan yang biasanya diperlukan saat menggunakan WriteableBitmap, yang dapat membantu dalam mengurangi penggunaan memori puncak dan latensi dari sumber ke layar.

SoftwareBitmap yang menyediakan informasi sumber juga dapat dikonfigurasi untuk menggunakan IWICBitmap kustom untuk menyediakan penyimpanan backing yang dapat dimuat ulang yang memungkinkan aplikasi memetakan ulang memori sesuai keinginan. Ini adalah kasus penggunaan C++ tingkat lanjut.

Aplikasi Anda harus menggunakan SoftwareBitmap dan SoftwareBitmapSource untuk beroperasi dengan API WinRT lainnya yang menghasilkan dan menggunakan gambar. Dan aplikasi Anda harus menggunakan SoftwareBitmapSource saat memuat data gambar yang tidak dikompresi alih-alih menggunakan WriteableBitmap.

Gunakan GetThumbnailAsync untuk gambar mini

Satu kasus penggunaan untuk menskalakan gambar adalah membuat gambar mini. Meskipun Anda dapat menggunakan DecodePixelWidth dan DecodePixelHeight untuk menyediakan versi gambar yang kecil, Windows menyediakan API yang lebih efisien untuk mengambil gambar mini. GetThumbnailAsync menyediakan gambar mini untuk gambar yang memiliki sistem file yang sudah di-cache. Ini memberikan performa yang lebih baik daripada API XAML karena gambar tidak perlu dibuka atau didekodekan.

Di aplikasi SDK Aplikasi Windows, inisialisasi pemilih dengan handle jendela aplikasi Anda—misalnya, dengan menyimpan jendela utama sebagai App.MainWindow.

FileOpenPicker picker = new FileOpenPicker();
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
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();
await bmp.SetSourceAsync(fileThumbnail);

Image img = new Image();
img.Source = bmp;

Dekode gambar sekali

Untuk mencegah gambar didekode lebih dari sekali, tetapkan properti Image.Source dari Uri daripada menggunakan aliran memori. Kerangka kerja XAML dapat mengaitkan Uri yang sama di beberapa tempat dengan satu gambar yang didekodekan, tetapi tidak dapat melakukan hal yang sama untuk beberapa aliran memori yang berisi data yang sama dan membuat gambar yang didekodekan yang berbeda untuk setiap aliran memori.