Pixelausrichtung in WPF-Anwendungen

Aktualisiert: November 2007

Das WPF-Grafiksystem verwendet geräteunabhängige Einheiten, um Auflösungs- und Geräteunabhängigkeit zu ermöglichen. Jedes geräteunabhängige Pixel wird automatisch mit der Punkte pro Zoll (dots per inch, dpi)-Einstellung des Systems skaliert. Dies ermöglicht WPF-Anwendungen eine ordnungsgemäße Skalierung für unterschiedliche dpi-Einstellungen und bewirkt, dass die Anwendung automatisch dpi-Einstellungen berücksichtigt.

Die dpi-Unabhängigkeit kann jedoch zu einem unregelmäßigen Rendern von Rändern aufgrund von Antialiasing führen. Diese im Allgemeinen als verschwommene oder halbtransparente Ränder wahrgenommenen Artefakte können auftreten, wenn ein Rand in der Mitte eines Gerätepixels und nicht zwischen Gerätepixeln liegt. Um dieses Problem zu beheben, stellt WPF ein Verfahren bereit, mit dem Objektränder in einer visuellen Struktur durch Pixelausrichtung an den Gerätepixeln ausgerichtet und die durch Antialiasing erzeugten halbtransparenten Ränder beseitigt werden.

Bei der Pixelausrichtung werden diese visuellen Artefakte unterdrückt, indem kleine Offsets auf die Geometrie des visuellen Elements angewendet werden, um die Geometrie an den Gerätepixeln auszurichten.

Dieses Thema enthält folgende Abschnitte.

  • Pixelausrichtung für Antialiasing-Rendering
  • Richtlinien
  • Bitmapbilder
  • Verwandte Abschnitte

Pixelausrichtung für Antialiasing-Rendering

Scharfe Linien

Ohne Pixelausrichtung werden mit Antialiasing gerenderte Linien möglicherweise halbtransparent angezeigt, wenn der Rand nicht zwischen Gerätepixeln liegt. Die folgende Abbildung zeigt die Ausgabe einer einen Pixel breiten Linie mit Antialiasing, die in der Mitte eines Gerätepixels liegt (links), und einer einen Pixel breiten Linie mit Antialiasing, die zwischen Gerätepixeln liegt (rechts).

Mit Antialiasing gerenderte Linie

Zeile mit Antialiasing verglichen mit Einzelpixelzeile

Mit Pixelausrichtung werden Linien mit Antialiasing an den Gerätepixeln ausgerichtet oder fixiert und scharf dargestellt. Dabei wird das halbtransparente Linienrendering eliminiert. Im folgenden Beispiel werden die Auswirkungen der SnapsToDevicePixels-Eigenschaft auf eine ein Pixel breite Linie veranschaulicht. Bei einer langsamen Größenänderung des Fensters werden die visuellen Artefakte auf einer nicht ausgerichteten Linie (links) und die feste Größe der ausgerichteten Linie (rechts) angezeigt, wenn sich ihre Positionen ändern.

<Page x:Class="PixelSnapping.Lines"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Lines" Name="linesPage"
    >
  <StackPanel Width="150"  Margin="7" Orientation="Horizontal">
    <!-- Single pixel line with pixel snapping turned OFF.-->
    <Rectangle SnapsToDevicePixels="False"
       Width="45.5" Margin="10" Height="1" Fill="Red"/>
    <!-- Single pixel line with pixel snapping turned ON.-->
    <Rectangle SnapsToDevicePixels="True"
      Width="45.5" Margin="10" Height="1" Fill="Red"/>
  </StackPanel>
  <!-- Background Grid -->
  <Page.Background>
    <DrawingBrush  Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
      <DrawingBrush.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="White">
            <GeometryDrawing.Geometry>
              <RectangleGeometry Rect="0,0,1,1" />
            </GeometryDrawing.Geometry>
          </GeometryDrawing>
          <GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
          <GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
        </DrawingGroup>
      </DrawingBrush.Drawing>
    </DrawingBrush>
  </Page.Background>
</Page>

Tipp

SnapsToDevicePixels beeinflusst nur Elemente, die das Layout durchlaufen. Führungslinien können für eine Drawing mit der GuidelineSet-Eigenschaft des DrawingGroup-Objekts festgelegt werden. Um die Führungslinien für ein Visual manuell festzulegen, erstellen Sie mit den Eigenschaften VisualYSnappingGuidelines und VisualXSnappingGuidelines neue Führungslinien.

Die Pixelausrichtung erhöht nur die Schärfe horizontaler und vertikaler Linien. Sie hat keine Auswirkungen auf diagonale Linien.

Benachbarte Objekte

Antialiasing kann auch visuelle Artefakte verursachen, wenn die Ränder zwischen Objekten aneinander grenzen und der benachbarte Rand nicht exakt zwischen einer Zeile oder Spalte von Gerätepixeln ausgerichtet ist. Die Szene mit Antialiasing kann den Rand möglicherweise mithilfe der zugrunde liegenden Hintergrundfarbe weicher machen und dabei ein Verlaufen erzeugen, in dem die Farbe des Rands zwischen den einzelnen Objekten transparent zu sein scheint. In der folgenden Abbildung wird dieses Verlaufen veranschaulicht.

Aneinander grenzende Objekte mit verlaufenden Rändern

Durchscheinender Hintergrund zwischen angrenzenden Objekten

Bei aktivierter Pixelausrichtung werden aneinander grenzende Ränder an den Gerätepixeln ausgerichtet, um das Verlaufen zu entfernen. Im folgenden Beispiel werden die Auswirkungen der SnapsToDevicePixels-Eigenschaft auf aneinander grenzende Objekte veranschaulicht. Bei einer langsamen Größenänderung des Fensters wird das Verlaufen bei nicht ausgerichteten Rechtecken (links) veranschaulicht, während die ausgerichteten Rechtecke (rechts) ohne visuelle Unregelmäßigkeiten zusammen bleiben.

<Page x:Class="PixelSnapping.Seeping"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Seeping"
    >
  <StackPanel Orientation="Horizontal" Height="100">
    <Border  
      SnapsToDevicePixels="False"
      Margin="10" BorderThickness="1" BorderBrush="Black" Height="80" Background="White">
      <StackPanel Height="100.0">
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
      </StackPanel>
    </Border>
    <Border
      SnapsToDevicePixels="True"
        Margin="10" BorderThickness="1" BorderBrush="Black" Height="80" Background="White">
      <StackPanel Height="100.0">
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
      </StackPanel>
    </Border>
  </StackPanel>
  <!-- Background Grid -->
  <Page.Background>
    <DrawingBrush  Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
      <DrawingBrush.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="White">
            <GeometryDrawing.Geometry>
              <RectangleGeometry Rect="0,0,1,1" />
            </GeometryDrawing.Geometry>
          </GeometryDrawing>
          <GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
          <GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
        </DrawingGroup>
      </DrawingBrush.Drawing>
    </DrawingBrush>
  </Page.Background>
</Page>

Beachten Sie, dass die ausgerichteten Rechtecke für die SnapsToDevicePixels-Eigenschaft keinen Wert explizit festlegen. Die Eigenschaft muss nur im Stamm auf true festgelegt werden, um das Verhalten für alle untergeordneten Elemente zu aktivieren.

Text

Windows Presentation Foundation (WPF) generiert immer Text mit Antialiasing. Wenn es sich um statischen Text handelt, wird der Text an den Pixeln ausgerichtet. Auf diese Weise wird das Aussehen des Texts mit Antialiasing geschärft, indem Sie die Symbole direkt auf dem Pixelraster platzieren und deutlicheren Text bereitstellen. Wenn Windows Presentation Foundation (WPF) jedoch eine animationsähnliche Bewegung wie Bildlauf, Skalierung oder animierte Übersetzung entdeckt, wird die Pixelausrichtung deaktiviert, bis die Bewegung beendet ist. Sobald die Animation oder der Bildlauf beendet ist, wird die Pixelausrichtung langsam wieder animiert.

Richtlinien

Im Kern wird die Pixelausrichtung von Führungslinien gesteuert. Führungslinien bieten Unterstützung bei der Anpassung von Geometrien an ein Gerätepixelraster. In den meisten Fällen stellt die Pixelausrichtung mithilfe der SnapsToDevicePixels-Eigenschaft das gewünschte Ergebnis bereit. Diese Eigenschaft ist jedoch nicht immer verfügbar. Dies ist besonders bei der Verwendung von Drawing-Objekten oder dem direkten Umgang mit einem DrawingContext der Fall. Deshalb müssen Führungslinien festgelegt werden, um die gewünschte Schärfe zu erzielen, die durch die Pixelausrichtung bereitgestellt wird.

Um Führungslinien für Drawing-Objekte und DrawingContext-Objekte festzulegen, wird die GuidelineSet-Klasse verwendet. Mit dieser Klasse können Sie horizontale und vertikale Führungslinien erstellen, die auf eine DrawingGroup angewendet oder für nachfolgende Zeichnungsbefehle auf einen DrawingContext verschoben werden. Die Führungslinien geben der Zeichnung Anweisungen, welche Linien an einem Gerätepixel ausgerichtet werden sollen. Ein ausführliches Beispiel zur GuidelineSet-Verwendung finden Sie unter Gewusst wie: Anwenden eines Führungsliniensatzes auf eine Zeichnung.

Führungslinien können auch auf Visual-Ebene festgelegt werden, indem die horizontalen und vertikalen Führungslinienauflistungen geändert werden. Der Zugriff ist über die Eigenschaften VisualYSnappingGuidelines und VisualXSnappingGuidelines möglich.

Bitmapbilder

Da WPFdpi-unabhängig ist, kann eine bitmapbasierte Benutzeroberfläche zu unerwünschten Darstellungsergebnissen führen. Szenen mit Antialiasing können wegen Problemen bei der Pixelausrichtung im Bruchteilbereich ein Bild weichzeichnen. Dies trifft besonders auf Bilder zu, die häufige Änderungen enthalten, beispielsweise ein Pixel breite Linien mit benachbarten kontrastreichen Elementen (wie abwechselnd schwarze und weiße Linien). In der folgenden Abbildung werden die Unterschiede in der Bildqualität eines ausgerichteten Bilds (links) und eines Bildoffsets veranschaulicht, der nicht an den Gerätepixeln ausgerichtet ist (rechts).

Bildausrichtung an Gerätepixeln

Verschwommenes Bild aufgrund fehlender Ausrichtung der Gerätepixel

Ein häufiges Szenario für Bilder in einer Benutzeroberfläche ist das Zentrieren eines Bilds, das ein Symbol in einem anderen Objekt darstellt. Da es sich bei Symbolen in der Regel um kleine Bilder mit häufigen Änderungen handelt, muss das Anwendungslayout möglicherweise angepasst werden, um die durch Antialiasing erzeugten visuellen Artefakte zu vermeiden.

Um ein Bild ordnungsgemäß zu zentrieren, muss der Container eine gerade Breite und Höhe aufweisen, sofern die Pixelbreite und -höhe des Bilds ebenfalls einen geraden Wert aufweisen. Wenn das Bild eine ungerade Pixelbreite und -höhe aufweist, müssen Breite und Höhe des enthaltenden Containers ebenfalls ungerade sein.

In folgenden Beispiel werden zwei Border-Objekte erstellt, die ein Image enthalten. Der obere Rand hat eine gerade Breite und Höhe, um mit Breite und Höhe des Bilds übereinzustimmen. Der untere Rand hat eine ungerade Breite und Höhe.

In der folgenden Abbildung werden die Ausgabe des Beispiels und die Auswirkungen der Containergröße auf ein Bild angezeigt.

In Rahmen zentrierte Bilder.

<Page x:Class="PixelSnapping.Images"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Images"
    >
  <StackPanel>
    <!-- Image has a pixel dimension of 144x96. -->
    <!-- Because the image has a even width and height, 
         an even border width and height allows the image to proper center. 
    -->
    <Border HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Height="100">
      <Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="sharpness.png" Stretch="None"/>
    </Border>
    <!-- Image has a pixel dimension of 144x96. -->
    <!-- Because the image has a even width and height, 
         an odd border width and height causes the image to soften. 
    -->
    <Border HorizontalAlignment="Left" VerticalAlignment="Top" Width="201" Height="101">
      <Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="sharpness.png" Stretch="None"/>
    </Border>
  </StackPanel>
  <!-- Grid Background -->
  <Page.Background>
    <DrawingBrush  Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
      <DrawingBrush.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="White">
            <GeometryDrawing.Geometry>
              <RectangleGeometry Rect="0,0,1,1" />
            </GeometryDrawing.Geometry>
          </GeometryDrawing>
          <GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
          <GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
        </DrawingGroup>
      </DrawingBrush.Drawing>
    </DrawingBrush>
  </Page.Background>
</Page>

Allerdings wird durch die einfache Anpassung der Größe des Containerobjekts die Gerätepixelausrichtung nicht garantiert. Das ganze Layout einer Anwendung kann Auswirkungen auf die Ausrichtung des Bilds haben. Die Punkte pro Zoll (dots per inch, dpi)-Einstellung der Anzeige wirkt sich ebenfalls auf die Bildausrichtung aus. Im Beispiel oben funktioniert die Bildausrichtung nur, wenn die Anzeige auf 96 Punkte pro Zoll (dots per inch, dpi) eingestellt ist. Bei jeder anderen Einstellung muss das Layout angepasst werden, um den Anzeigeeinstellungen gerecht zu werden. Bilder mit häufigen Änderungen sollte nach Möglichkeit in Windows Presentation Foundation (WPF)-Anwendungen vermieden werden.

Siehe auch

Konzepte

Das Layoutsystem

Referenz

Image

VisualXSnappingGuidelines

VisualYSnappingGuidelines