Freigeben über


DPI und DIPs

In diesem Artikel wird der Unterschied zwischen physischen Pixeln und geräteunabhängigen Pixeln (DIPs) und der Verarbeitung von DPI (Dots per Inch) in Win2D erläutert.

Win2D ist so konzipiert, dass viele Apps diese Unterscheidung ignorieren können, da sie vernünftige Standardverhalten bereitstellt, die bei der Ausführung auf Geräten mit geringem und hohem DPI-Wert das Richtige tun. Wenn Ihre App speziellere Anforderungen hat oder wenn Sie eine andere Meinung darüber haben, was "vernünftige Standard" bedeutet, lesen Sie weiter für die Gory-Details...

Was ist DPI?

DPI steht für "Punkte pro Zoll". Dies ist ein ungefähres Maß für die Pixeldichte einer Ausgabeanzeige, z. B. eines Computermonitors oder eines Telefonbildschirms. Je höher der DPI-Wert ist, desto kleinerer punkte bilden die Anzeige.

DPI ist nur eine ungefähre Messung, da nicht alle Anzeigehardware verwendet werden kann, um genaue Informationen zu melden. Einige Computermonitore melden überhaupt keinen DPI-Wert an das Betriebssystem, oder der Benutzer hat sein System möglicherweise so konfiguriert, dass er mit einem anderen DPI-Wert als der tatsächlichen Hardware gerendert wird (z. B. um die Größe von UI-Textelementen zu ändern). Anwendungen können dpi verwenden, um auszuwählen, wie groß dinge gezeichnet werden sollen, aber nicht als genaue physische Messung der Anzeigegröße.

Ein DPI-Wert von 96 wird als neutraler Standardwert betrachtet.

Was ist ein Pixel?

Ein Pixel ist ein einzelner farbiger Punkt. Bilder in Computergrafiken bestehen aus vielen Pixeln, die in einem zweidimensionalen Raster angeordnet sind. Sie können sich Pixel als Atome vorstellen, aus denen alle Bilder erstellt werden.

Die physische Größe eines Pixels kann stark von einer Anzeige zu einer anderen variieren. Wenn ein Computer mit einem großen, aber niedrigen Monitor oder einer externen Anzeige verbunden ist, können Pixel ziemlich groß sein, aber auf einem Smartphone mit einer Anzeige von 1080p sind nur wenige Zoll breit, Pixel sind winzig.

Wenn in Win2D eine API angezeigt wird, die eine Position oder Größe mit ganzzahligen Datentypen angibt (oder eine Struktur wie BitmapSize, die ganze Zahlen enthält), bedeutet dies, dass die API in Pixeleinheiten ausgeführt wird.

Die meisten Win2D-APIs funktionieren mit DIPs und nicht mit Pixeln.

Was ist ein DIP?

DIP steht für "Geräteunabhängiges Pixel". Dies ist eine virtualisierte Einheit, die mit einem physischen Pixel identisch sein kann, größer oder kleiner als ein physisches Pixel ist.

Das Verhältnis zwischen Pixeln und DIPs wird durch DPI bestimmt:

pixels = dips * dpi / 96

Wenn DPI 96 beträgt, sind Pixel und DIPs identisch. Bei Verwendung höherer DPI-Werte kann ein einzelnes DIP mehr als ein Pixel (oder Teile von Pixeln in der Regel entsprechen, wenn DPI kein genaues Vielfaches von 96 ist).

Die meisten Windows-Runtime-APIs, einschließlich Win2D, verwenden DIPs anstelle von Pixeln. Dies hat den Vorteil, dass Grafiken ungefähr die gleiche physische Größe aufweisen, unabhängig davon, auf welcher Anzeige eine App ausgeführt wird. Wenn eine App beispielsweise angibt, dass eine Schaltfläche 100 DIPs breit ist, wird diese Schaltfläche automatisch skaliert, wenn sie auf einem Gerät mit hohem DPI-Wert ausgeführt wird, z. B. auf einem Smartphone oder einem 4k-Monitor, automatisch auf mehr als 100 Pixel breite skaliert werden, sodass sie eine sinnvolle Größe bleibt, auf die der Benutzer klicken kann. Wenn die Schaltflächengröße in Pixeln angegeben wurde, würde sie andererseits auf dieser Art von hoher DPI-Anzeige lächerlich klein erscheinen, sodass die App mehr Arbeit tun müsste, um Layouts für jede Art von Bildschirm unterschiedlich anzupassen.

Wenn in Win2D eine API angezeigt wird, die eine Position oder Größe mithilfe von Gleitkommadatentypen angibt (oder Strukturen wie Vector2 oder Size, die Gleitkommawerte enthalten), bedeutet dies, dass die API in DIPs ausgeführt wird.

Um zwischen DIPs und Pixeln zu konvertieren, verwenden Sie die Methoden ConvertDipsToPixels(Single, CanvasDpiRounding) und ConvertPixelsToDips(Int32).

Win2D-Ressourcen mit DPI-Werten

Alle Win2D-Ressourcen, die ein Bitmapbild enthalten, weisen auch eine zugeordnete DPI-Eigenschaft auf:

Alle anderen Ressourcentypen sind unabhängig von DPI. Beispielsweise kann eine einzelne CanvasDevice Instanz zum Zeichnen auf Steuerelemente oder Rendertargets vieler verschiedener DPIs verwendet werden, daher verfügt das Gerät über keinen eigenen DPI-Wert.

CanvasCommandList Ebenso verfügt er nicht über einen DPI-Wert, da er Vektorzeichnungsanweisungen anstelle eines Bitmapbilds enthält. DPI wird nur während des Rasterungsprozesses wiedergegeben, wenn die Befehlsliste auf ein Rendertarget oder Steuerelement gezeichnet wird (die DPI-Werte aufweisen).

DPI-Werte steuern

Die Win2D-Steuerelemente (CanvasControlCanvasVirtualControlund CanvasAnimatedControl) verwenden automatisch denselben DPI-Wert wie die Anzeige, auf der die App ausgeführt wird. Dies entspricht dem Koordinatensystem, das von XAML, CoreWindow und anderen Windows-Runtime APIs verwendet wird.

Wenn sich der DPI-Wert ändert (z. B. wenn die App in eine andere Anzeige verschoben wird), löst das Steuerelement das CreateResources Ereignis aus und übergibt eine CanvasCreateResourcesReason von DpiChanged. Apps sollten auf dieses Ereignis reagieren, indem alle Ressourcen (z. B. Rendertargets) neu gerechnet werden, die vom DPI-Wert des Steuerelements abhängen.

Rendertarget-DPI

Dinge, auf die gezeichnet werden kann (die nicht nur CanvasRenderTarget , sondern auch die rendertarget-ähnlichen Typen CanvasSwapChain enthalten und CanvasImageSource) einen DPI-Wert besitzen, aber im Gegensatz zu den Steuerelementen sind diese Typen nicht direkt mit einer Anzeige verbunden, sodass Win2D nicht automatisch bestimmen kann, was der DPI-Wert sein soll. Wenn Sie auf ein Rendertarget zeichnen, das später auf den Bildschirm kopiert wird, möchten Sie wahrscheinlich, dass dieses Rendertarget denselben DPI-Wert wie der Bildschirm verwendet, aber wenn Sie zu einem anderen Zweck zeichnen (z. B. Das Generieren von Bildern für den Upload auf eine Website), wäre ein Standardmäßiger DPI-Wert von 96 besser geeignet.

Um beide Verwendungsmuster einfach zu machen, bietet Win2D zwei Arten von Konstruktorüberladung:

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

Die ICanvasResourceCreator Schnittstelle wird sowohl von CanvasDevice win2D-Steuerelementen implementiert. Da ein Gerät keinen spezifischen DPI-Wert besitzt, müssen Sie beim Erstellen eines Rendertargets explizit den DPI-Wert angeben.

Beispielsweise zum Erstellen eines standardmäßigen DPI-Rendertargets, bei dem DIPs und Pixel immer gleich sind:

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

ICanvasResourceCreatorWithDpi erweitert ICanvasResourceCreator durch Hinzufügen einer DPI-Eigenschaft. Diese Schnittstelle wird von den Win2D-Steuerelementen implementiert und erleichtert das Erstellen eines Rendertargets, das automatisch denselben DPI-Wert erbt wie das Steuerelement, von dem sie erstellt wurde:

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

Bitmap-DPI

CanvasBitmap, im Gegensatz zu einem Rendertarget, erbt nicht automatisch DPI von einem Steuerelement. Die Methoden zum Erstellen und Laden von Bitmaps umfassen Überladungen, um explizit DPI anzugeben. Wenn Sie dies jedoch verlassen, wird Bitmap-DPI-Standardwert unabhängig von der aktuellen Anzeigekonfiguration auf 96 festgelegt.

Der Grund, warum Bitmaps sich von anderen Typen unterscheiden, besteht darin, dass sie eine Quelle von Eingabedaten sind, anstatt eine Ausgabe, auf die gezeichnet wird. Daher ist die wichtige Sache für Bitmaps nicht der DPI-Wert, an dem diese Ausgabe enden wird, sondern der DPI-Wert des Quellbilds, der vollständig nicht mit den aktuellen Anzeigeeinstellungen verknüpft ist.

Wenn Sie eine 100x100-Standard-DPI-Bitmap laden und dann auf ein Rendertarget zeichnen, wird die Bitmap von 100 DIPs mit 96 DPI (was 100 Pixel ist) auf 100 DIPs bei der DPI des Zielrendertargets skaliert (dies kann eine größere Anzahl von Pixeln sein, wenn es sich um einen hohen DPI-Rendertarget handelt). Das resultierende Bild ist immer 100 DIPs groß (daher gibt es keine unangenehmen Layout-Überraschungen), aber es kann etwas verschwommen sein, wenn eine Bitmap mit niedriger DPI-Quelle auf ein höheres DPI-Ziel skaliert wurde.

Um maximale Klarheit bei hohem DPI-Wert zu erzielen, möchten einige Anwendungen möglicherweise mehrere Bitmapbilder mit unterschiedlichen Auflösungen bereitstellen und zum Ladezeitpunkt auswählen, welche Version am ehesten mit dem DPI-Wert des Zielsteuerelements übereinstimmt. Andere Apps möchten möglicherweise nur Bitmaps mit hohem DPI-Wert versenden und win2D diese verkleinern lassen, wenn sie auf niedrigeren DPI-Displays ausgeführt werden (die Skalierung nach unten kann häufig besser aussehen als die Skalierung nach oben). In beiden Fällen kann der Bitmap-DPI-Wert als Parameter angegeben werden.LoadAsync(ICanvasResourceCreator, String, Single)

Beachten Sie, dass einige Bitmapdateiformate eigene DPI-Metadaten enthalten, aber Win2D ignoriert dies, da sie häufig falsch festgelegt ist. Stattdessen muss DPI beim Laden der Bitmap explizit angegeben werden.

CanvasDrawingSession DPI

CanvasDrawingSession erbt seinen DPI-Wert von dem Steuerelement, rendertarget, Swapchain usw., auf dem er gezeichnet wird.

Standardmäßig werden alle Zeichnungsvorgänge in DIPs ausgeführt. Wenn Sie lieber in Pixeln arbeiten möchten, kann dies über die Units Eigenschaft geändert werden.

Effekt-DPI

Die Bildeffektpipeline erbt ihren DPI-Wert von dem, auf den CanvasDrawingSession ein Effekt gezeichnet wird. Intern funktioniert die Effektverarbeitung immer in Pixeln. Parameterwerte wie Größen oder Positionen werden in DIPs angegeben, diese Einheiten werden jedoch in Pixel konvertiert, bevor eine tatsächliche Bildbearbeitung stattfindet.

Wenn eine Bitmap mit unterschiedlichem DPI-Wert als die Zielzeichnungssitzung als Effektquellbild verwendet wird, wird automatisch ein internes DpiCompensationEffect Element zwischen der Bitmap und dem Effekt eingefügt. Dadurch wird die Bitmap so skaliert, dass sie dem Dpi-Wert des Ziels entspricht. Dies ist in der Regel der gewünschte Wert. Wenn sie nicht ihren Vorstellungen entspricht, können Sie Ihre eigene Instanz DpiCompensationEffect einfügen, um das Verhalten anzupassen.

Hinweis

Wenn Sie einen benutzerdefinierten Effekt implementieren, sollten Sie ein entsprechendes DPI-Behandlungsschema anwenden, um ein einheitliches Verhalten sicherzustellen, wenn es zusammen mit integrierten Win2D-Effekten verwendet wird.

Kompositions-API

Die Microsoft.Graphics.Canvas.Composition APIs arbeiten auf einer niedrigeren Ebene als Win2D-XAML-Steuerelemente, sodass sie nicht versuchen, DPI in Ihrem Auftrag automatisch zu verarbeiten. Es liegt an Ihnen, zu entscheiden, in welchen Einheiten Sie arbeiten möchten, und festlegen, welche Transformationen erforderlich sind, um dies als Teil der visuellen Kompositionsstruktur zu erreichen.

Windows.UI.Composition APIs wie z CreateDrawingSurface . B. immer Größen in Pixeleinheiten angeben. Wenn Sie Win2D zum Zeichnen auf einer Kompositionsoberfläche verwenden, können Sie angeben, welchen DPI-Wert Sie beim Aufrufen CreateDrawingSession(CompositionDrawingSurface, Rect, Single)verwenden möchten. Alle durch die zurückgegebenen Zeichen ausgeführten CanvasDrawingSession Zeichnung werden entsprechend nach oben oder unten skaliert.

So testen Sie die DPI-Behandlung

Die einfachste Möglichkeit, zu testen, dass Ihre App als Reaktion auf das Ändern des Anzeige-DPI-Werts das Richtige tut, besteht darin, unter Windows 10 oder Windows 11 ausgeführte Anzeigeeinstellungen auszuführen und anzeigeeinstellungen zu ändern, während die App ausgeführt wird:

  • Klicken Sie mit der rechten Maustaste auf den Desktophintergrund, und wählen Sie "Anzeigeeinstellungen" aus.
  • Verschieben des Schiebereglers mit der Bezeichnung "Ändern der Größe von Text, Apps und anderen Elementen"
  • Klicken Sie auf die Schaltfläche "Übernehmen".
  • Wählen Sie "Später abmelden" aus.

Wenn Sie nicht über Windows 10 oder Windows 11 verfügen, können Sie auch den Windows Simulator testen. Ändern Sie in der Visual Studio-Symbolleiste die Einstellung "Lokaler Computer" in "Simulator", und verwenden Sie dann das Symbol "Auflösung ändern", um die simulierte Anzeige zwischen:

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