Bagikan melalui


DPI dan DIP

Artikel ini menjelaskan perbedaan antara piksel fisik dan piksel independen perangkat (DIP), dan bagaimana DPI (titik per inci) ditangani di Win2D.

Win2D dirancang sedih sehingga banyak aplikasi dapat mengabaikan perbedaan ini, karena memberikan perilaku default yang masuk akal yang akan melakukan hal yang benar saat dijalankan pada perangkat DPI rendah dan tinggi. Jika aplikasi Anda memiliki kebutuhan yang lebih khusus, atau jika Anda memiliki pendapat yang berbeda tentang arti "default yang masuk akal", baca detail gory...

Apa itu DPI?

DPI adalah singkatan dari "titik per inci". Ini adalah perkiraan ukuran kepadatan piksel tampilan output seperti monitor komputer atau layar telepon. Semakin tinggi DPI, semakin banyak titik kecil yang membentuk layar.

DPI hanya perkiraan ukuran karena tidak semua perangkat keras tampilan dapat diandalkan untuk melaporkan informasi yang akurat. Beberapa monitor komputer tidak melaporkan DPI ke sistem operasi sama sekali, atau pengguna mungkin telah mengonfigurasi sistem mereka untuk merender menggunakan DPI yang berbeda dari perangkat keras aktual (misalnya untuk mengubah ukuran elemen teks UI). Aplikasi dapat menggunakan DPI untuk memilih seberapa besar hal-hal yang harus digambar, tetapi tidak boleh mengandalkannya sebagai pengukuran fisik yang tepat dari ukuran tampilan.

Nilai DPI 96 dianggap sebagai default netral.

Apa itu piksel?

Piksel adalah titik berwarna tunggal. Gambar dalam grafik komputer terdiri dari banyak piksel yang disusun dalam kisi dua dimensi. Anda dapat menganggap piksel sebagai atom di mana semua gambar dibangun.

Ukuran fisik piksel dapat sangat bervariasi dari satu tampilan ke layar lainnya. Ketika komputer terhubung ke monitor beresolusi besar tetapi rendah atau layar eksternal, piksel bisa sangat besar, tetapi pada ponsel dengan layar 1080p hanya beberapa inci di seluruh, piksel kecil.

Di Win2D, setiap kali Anda melihat API yang menentukan posisi atau ukuran menggunakan jenis data bilangan bulat (atau struktur seperti BitmapSize yang berisi bilangan bulat), ini berarti API beroperasi dalam unit piksel.

Sebagian besar API Win2D berfungsi dengan DIP daripada piksel.

Apa itu DIP?

DIP adalah singkatan dari "piksel independen perangkat". Ini adalah unit virtual yang mungkin sama dengan, lebih besar, atau lebih kecil dari piksel fisik.

Rasio antara piksel dan DIP ditentukan oleh DPI:

pixels = dips * dpi / 96

Saat DPI adalah 96, piksel dan DIP sama. Saat menggunakan DPI yang lebih tinggi, satu DIP mungkin sesuai dengan lebih dari satu piksel (atau bagian piksel dalam kasus umum di mana DPI bukan kelipatan yang tepat dari 96).

Sebagian besar WINDOWS Runtime API, termasuk Win2D, menggunakan DIP daripada piksel. Ini memiliki keuntungan menjaga grafik dengan ukuran fisik yang hampir sama terlepas dari tampilan apa pun yang dijalankan aplikasi. Misalnya jika aplikasi menentukan bahwa tombol memiliki lebar 100 DIP, saat dijalankan pada perangkat DPI tinggi seperti ponsel atau monitor 4k, tombol ini akan secara otomatis menskalakan menjadi lebar lebih dari 100 piksel, sehingga tetap menjadi ukuran yang masuk akal yang memungkinkan pengguna untuk mengklik. Jika ukuran tombol ditentukan dalam piksel, di sisi lain, itu akan tampak sangat kecil pada jenis tampilan DPI tinggi ini, sehingga aplikasi harus melakukan lebih banyak pekerjaan untuk menyesuaikan tata letak secara berbeda untuk setiap jenis layar.

Di Win2D, setiap kali Anda melihat API yang menentukan posisi atau ukuran menggunakan jenis data floating point (atau struct seperti Vector2 atau Size yang berisi nilai floating point), ini berarti API beroperasi di DIP.

Untuk mengonversi antara DIP dan piksel, gunakan metode ConvertDipsToPixels(Single, CanvasDpiRounding) dan ConvertPixelsToDips(Int32).

Sumber daya Win2D yang memiliki DPI

Semua sumber daya Win2D yang berisi gambar bitmap juga memiliki properti DPI terkait:

Semua jenis sumber daya lainnya tidak bergantung pada DPI. Misalnya satu CanvasDevice instans dapat digunakan untuk menggambar ke kontrol atau rendertarget dari banyak DPI yang berbeda, oleh karena itu perangkat tidak memiliki DPI sendiri.

Demikian pula, CanvasCommandList tidak memiliki DPI, karena berisi instruksi gambar vektor daripada gambar bitmap. DPI hanya mulai bermain selama proses rasterisasi, ketika daftar perintah digambar ke rendertarget atau kontrol (yang memiliki DPI).

Kontrol DPI

Kontrol Win2D (CanvasControl, CanvasVirtualControl dan CanvasAnimatedControl) secara otomatis menggunakan DPI yang sama dengan tampilan yang dijalankan aplikasi. Ini cocok dengan sistem koordinat yang digunakan oleh XAML, CoreWindow, dan API Windows Runtime lainnya.

Jika DPI berubah (misalnya jika aplikasi dipindahkan ke tampilan yang berbeda), kontrol akan menaikkan CreateResources peristiwa dan meneruskan CanvasCreateResourcesReason .DpiChanged Aplikasi harus merespons peristiwa ini dengan membuat ulang sumber daya apa pun (seperti rendertarget) yang bergantung pada DPI kontrol.

Rendertarget DPI

Hal-hal yang dapat digambar ke (yang tidak hanya CanvasRenderTarget mencakup tetapi juga jenis CanvasSwapChain seperti rendertarget dan CanvasImageSource) memiliki DPI sendiri, tetapi tidak seperti kontrol jenis ini tidak terhubung langsung ke layar, sehingga Win2D tidak dapat secara otomatis menentukan apa yang seharusnya DPI. Jika Anda menggambar ke rendertarget yang nantinya akan disalin ke layar, Anda mungkin ingin rendertarget tersebut menggunakan DPI yang sama dengan layar, tetapi jika Anda menggambar untuk beberapa tujuan lain (misalnya, menghasilkan gambar untuk diunggah ke situs web) 96 DPI default akan lebih tepat.

Untuk mempermudah kedua pola penggunaan ini, Win2D menyediakan dua jenis kelebihan konstruktor:

CanvasRenderTarget(ICanvasResourceCreator, width, height, dpi)
CanvasRenderTarget(ICanvasResourceCreatorWithDpi, width, height)

Antarmuka ICanvasResourceCreator diimplementasikan oleh CanvasDevice serta kontrol Win2D. Karena perangkat tidak memiliki DPI tertentu sendiri, Anda harus secara eksplisit menentukan DPI saat membuat rendertarget dari satu.

Misalnya untuk membuat rendertarget DPI default di mana DIP dan piksel akan selalu menjadi hal yang sama:

const float defaultDpi = 96;
var rtWithFixedDpi = new CanvasRenderTarget(canvasDevice, width, height, defaultDpi);

ICanvasResourceCreatorWithDpiICanvasResourceCreator memperluas dengan menambahkan properti DPI. Antarmuka ini diimplementasikan oleh kontrol Win2D, dan memudahkan untuk membuat rendertarget yang akan secara otomatis mewarisi DPI yang sama dengan kontrol yang dibuat dari:

var rtWithSameDpiAsDisplay = new CanvasRenderTarget(canvasControl, width, height);

Bitmap DPI

CanvasBitmap, tidak seperti rendertarget, tidak secara otomatis mewarisi DPI dari kontrol. Metode untuk membuat dan memuat bitmap mencakup kelebihan beban untuk secara eksplisit menentukan DPI, tetapi jika Anda membiarkannya, bitmap DPI default ke 96 terlepas dari konfigurasi tampilan saat ini.

Alasan bitmap berbeda dengan jenis lain adalah bahwa mereka adalah sumber data input, bukan output yang akan digambar ke dalamnya. Jadi hal penting untuk bitmap bukanlah DPI di mana output tersebut akan berakhir, tetapi DPI gambar sumber, yang sepenuhnya tidak terkait dengan pengaturan tampilan saat ini.

Jika Anda memuat katakanlah bitmap DPI default 100x100 dan kemudian menggambarnya ke rendertarget, bitmap akan diskalakan dari 100 DIP pada 96 DPI (yaitu 100 piksel) hingga 100 DIP di DPI rendertarget tujuan (yang bisa menjadi jumlah piksel yang lebih besar jika merupakan rendertarget DPI tinggi). Gambar yang dihasilkan akan selalu berukuran 100 DIP (sehingga tidak akan ada kejutan tata letak yang tidak menyenangkan), tetapi mungkin mengalami keburaman jika bitmap sumber DPI rendah diskalakan hingga tujuan DPI yang lebih tinggi.

Untuk kejelasan maksimum pada DPI tinggi, beberapa aplikasi mungkin ingin menyediakan beberapa set gambar bitmap pada resolusi yang berbeda, dan pada waktu pemuatan pilih versi mana pun yang paling cocok dengan DPI kontrol tujuan. Aplikasi lain mungkin lebih suka hanya mengirim bitmap DPI tinggi, dan membiarkan Win2D menurunkan skala ini saat berjalan pada tampilan DPI yang lebih rendah (penurunan skala sering terlihat lebih baik daripada meningkatkan skala). Dalam kedua kasus, DPI bitmap dapat ditentukan sebagai parameter ke LoadAsync(ICanvasResourceCreator, String, Single).

Perhatikan bahwa beberapa format file bitmap berisi metadata DPI sendiri, tetapi Win2D mengabaikan ini karena sering diatur dengan salah. Sebagai gantinya, DPI harus ditentukan secara eksplisit saat memuat bitmap.

CanvasDrawingSession DPI

CanvasDrawingSession mewarisi DPI-nya dari kontrol apa pun, rendertarget, swapchain, dll, itu menarik ke.

Secara default, semua operasi gambar beroperasi di DIP. Jika Anda lebih suka bekerja dalam piksel, ini dapat diubah melalui Units properti .

Efek DPI

Alur efek gambar mewarisi DPI-nya dari efek apa pun CanvasDrawingSession yang sedang digambar. Secara internal, pemrosesan efek selalu beroperasi dalam piksel. Nilai parameter seperti ukuran atau posisi ditentukan dalam DIP, tetapi unit ini dikonversi ke piksel sebelum manipulasi gambar aktual terjadi.

Ketika bitmap DPI yang berbeda dari sesi gambar target digunakan sebagai gambar sumber efek, internal DpiCompensationEffect secara otomatis dimasukkan di antara bitmap dan efeknya. Ini menskalakan bitmap agar sesuai dengan target DPI, yang biasanya sesuai dengan keinginan Anda. Jika bukan yang Anda inginkan, Anda dapat menyisipkan instans DpiCompensationEffect Anda sendiri untuk menyesuaikan perilaku.

Catatan

Jika menerapkan efek kustom, pertimbangkan untuk menerapkan skema penanganan DPI yang setara untuk memastikan perilaku yang konsisten saat digunakan bersama dengan efek Win2D bawaan.

API Komposisi

Microsoft.Graphics.Canvas.Composition API beroperasi pada tingkat yang lebih rendah daripada kontrol Win2D XAML, sehingga api tidak mencoba menangani DPI secara otomatis atas nama Anda. Terserah Anda untuk memutuskan unit apa yang lebih Anda sukai untuk dioperasikan, dan mengatur transformasi apa pun yang diperlukan untuk mencapainya sebagai bagian dari pohon visual komposisi Anda.

Windows.UI.Composition API seperti CreateDrawingSurface selalu menentukan ukuran dalam unit piksel. Saat menggunakan Win2D untuk menggambar ke permukaan komposisi, Anda dapat menentukan DPI apa pun yang ingin Anda gunakan saat memanggil CreateDrawingSession(CompositionDrawingSurface, Rect, Single). Semua gambar yang dilakukan melalui yang dikembalikan akan ditingkatkan CanvasDrawingSession atau diturunkan sesuai dengan itu.

Cara menguji penanganan DPI

Cara term mudah untuk menguji bahwa aplikasi Anda akan melakukan hal yang benar sebagai respons terhadap perubahan DPI tampilan adalah dengan menjalankan pada Windows 10 atau Windows 11 dan mengubah pengaturan tampilan saat aplikasi sedang berjalan:

  • Klik kanan pada latar belakang desktop dan pilih 'Pengaturan tampilan'
  • Pindahkan slider berlabel 'Ubah ukuran teks, aplikasi, dan item lainnya'
  • Klik tombol 'Terapkan'
  • Pilih 'Keluar nanti'

Jika Anda tidak memiliki Windows 10 atau Windows 11, Anda juga dapat menguji dengan Windows Simulator. Di toolbar Visual Studio, ubah pengaturan "Komputer Lokal" menjadi "Simulator", lalu gunakan ikon Ubah Resolusi untuk mengalihkan tampilan yang disimulasikan antara:

  • 100% (DPI = 96)
  • 140% (DPI = 134,4)
  • 180% (DPI = 172,8)