Condividi tramite


Blocco dei pixel nelle applicazioni WPF

Aggiornamento: novembre 2007

Il sistema grafico WPF utilizza unità indipendenti dal dispositivo per attivare l'indipendenza dalla risoluzione e dal dispositivo. Ciascun pixel indipendente dal dispositivo viene automaticamente ridimensionato con l'impostazione punti per pollice (dpi, dots per inch) del sistema. In questo modo, le applicazioni WPF vengono ridimensionate correttamente per diverse impostazioni dpi e l'applicazione rileva automaticamente i dpi.

Tuttavia, questa indipendenza dai dpi può determinare un rendering irregolare dei bordi a causa dell'anti-aliasing. Questi elementi, generalmente visibili sotto forma di bordi sfuocati o semitrasparenti, può verificarsi quando un bordo si trova in corrispondenza del centro di un pixel, anziché tra i pixel del dispositivo. Per risolvere questo problema, in WPF, i bordi degli oggetti di una struttura ad albero visuale possono essere bloccati o resi fissi in base ai pixel del dispositivo attraverso il blocco dei pixel, eliminando i bordi semitrasparenti generati dall'anti-aliasing.

Il blocco dei pixel rappresenta un modo per non visualizzare questi elementi visivi applicando piccoli offset alla geometria dell'elemento visivo al fine di allineare la geometria ai pixel del dispositivo.

Nel presente argomento sono contenute le seguenti sezioni.

  • Blocco dei pixel per un rendering con anti-aliasing
  • Linee guida
  • Immagini bitmap
  • Argomenti correlati

Blocco dei pixel per un rendering con anti-aliasing

Righe nitide

Senza il blocco dei pixel, le righe per cui è stato eseguito il rendering con anti-aliasing appaiono semitrasparenti, se il bordo non si trova tra i pixel del dispositivo. Nell'immagine seguente viene mostrato l'output di una riga con anti-aliasing con una larghezza pari a un pixel singolo che si trova al centro di un pixel del dispositivo (sinistra) e una riga con una larghezza pari a un pixel singolo che si trova tra i pixel del dispositivo (destra).

Rendering della riga con anti-aliasing.

Linea con anti-aliasing confrontata con linea a pixel singolo

Con il blocco dei pixel, le righe con anti-aliasing vengono bloccate, o rese fisse, sui pixel del dispositivo e vengono visualizzate nitide, eliminando il rendering semitrasparente della riga. Nell'esempio seguente viene illustrato l'effetto della proprietà SnapsToDevicePixels su una riga a pixel singolo. Ridimensionando lentamente la finestra, vengono visualizzati gli elementi visivi su una riga non bloccata (sinistra) e la dimensione fissa della riga bloccata (destra), durante la modifica della posizione.

<Page x:Class="PixelSnapping.Lines"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://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>

Nota

SnapsToDevicePixels influisce solo sugli elementi eseguiti tramite il passaggio di layout. Le linee guida possono essere impostate su Drawing utilizzando la proprietà GuidelineSet dell'oggetto DrawingGroup. Per impostare manualmente le linee guida di Visual, creare nuove linee guida utilizzando le proprietà VisualYSnappingGuidelines e VisualXSnappingGuidelines.

Il blocco dei pixel aumenta la nitidezza solo delle righe orizzontali e verticali e non influisce su quelle diagonali.

Oggetti adiacenti

L'anti-aliasing può comportare elementi visivi anche quando i bordi tra gli oggetti confinano e il bordo adiacente non è perfettamente allineato tra una riga o una colonna dei pixel del dispositivo. La scena con anti-aliasing può sfumare il bordo utilizzando il colore di sfondo sottostante che produce un effetto sfumato in cui il bordo tra ciascun oggetto appare trasparente. Nell'immagine seguente viene illustrato l'effetto sfumato.

Oggetti adiacenti con effetto sfumato.

Sfondo sfumato tra oggetti adiacenti

Se il blocco dei pixel è attivato, i bordi adiacenti vengono bloccati sui pixel del dispositivo per rimuovere l'effetto sfumato. Nell'esempio seguente viene illustrato l'effetto della proprietà SnapsToDevicePixels sugli oggetti adiacenti. Ridimensionando lentamente la finestra, è possibile visualizzare il problema dell'effetto sfumato sui rettangoli non bloccati (sinistra), mentre quelli bloccati (destra) rimangono uniti senza irregolarità visive.

<Page x:Class="PixelSnapping.Seeping"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://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>

Notare che i rettangoli bloccati non impostano in modo esplicito un valore per la proprietà SnapsToDevicePixels. La proprietà deve essere solo impostata su true nella radice per attivare il comportamento su tutti gli elementi figlio.

Testo

In Windows Presentation Foundation (WPF) viene sempre generato un testo con anti-aliasing e se il testo è statico, sarà bloccato con i pixel. In questo modo, è possibile aumentare la nitidezza dell'aspetto del testo con anti-aliasing collocando le icone direttamente sulla griglia in pixel, ottenendo pertanto un testo più chiaro. Tuttavia, se in Windows Presentation Foundation (WPF) viene rilevato un movimento simile a un'animazione, ad esempio uno scorrimento, un ridimensionamento o una traslazione animata, il blocco dei pixel viene disattivato fino al completamento del movimento. Quando il movimento simile a un'animazione o a uno scorrimento viene completato, al blocco dei pixel viene di nuovo aggiunta lentamente un'animazione.

Linee guida

Il blocco dei pixel viene principalmente controllato da linee guida. Queste ultime agevolano la regolazione delle geometrie su una griglia in pixel del dispositivo. Nella maggior parte dei casi, il blocco dei pixel eseguito mediante la proprietà SnapsToDevicePixels fornirà il risultato desiderato. Tuttavia, questa proprietà non è sempre disponibile, in modo particolare quando si utilizzano gli oggetti Drawing o quando si gestisce direttamente DrawingContext, pertanto è necessario impostare le linee guida per raggiungere la nitidezza desiderata, garantita dal blocco dei pixel.

Per impostare le linee guida sugli oggetti Drawing e DrawingContext, viene utilizzata la classe GuidelineSet. Questa classe consente di creare linee guida orizzontali e verticali che possono essere applicate a DrawingGroup o inserite in DrawingContext per comandi di disegno successivi. Le linee guida indicano al disegno quali righe devono essere bloccate su un pixel del dispositivo. Per un esempio dettagliato dell'utilizzo di GuidelineSet, vedere Procedura: applicare un GuidelineSet a un disegno.

Le linee guida possono essere impostate anche a livello di Visual modificando gli insiemi di linee guida orizzontali e verticali. Questi ultimi sono accessibili mediante le proprietà VisualYSnappingGuidelines e VisualXSnappingGuidelines.

Immagini bitmap

A causa della natura indipendente dei dpi di WPF, l'interfaccia utente basata su bitmap può ottenere risultati di presentazione non desiderati. Le scene con anti-aliasing possono sfocare un'immagine a causa di problemi relativi all'allineamento dei pixel frazionari. Questa situazione si verifica soprattutto nelle immagini che contengono modifiche ad alta frequenza, ad esempio righe a pixel singolo con elementi contrastanti adiacenti (ad esempio righe bianche e nere alternate). Nell'immagine seguente vengono illustrate le differenze di qualità tra un'immagine allineata (sinistra) e un offset dell'immagine non allineato con i pixel del dispositivo (destra).

Allineamento dell'immagine ai pixel del dispositivo.

Immagine sfocata a causa del mancato allineamento dei pixel del dispositivo

Uno scenario comune delle immagini dell'interfaccia utente consiste nel centrare un'immagine che rappresenta un'icona con un altro oggetto. Dal momento che le icone sono generalmente immagini piccole con modifiche ad alta frequenza, è necessario eseguire regolazioni del layout dell'applicazione al fine di evitare gli elementi visivi prodotti dall'anti-aliasing.

Per centrare correttamente un'immagine, il contenitore deve avere una larghezza e un'altezza pari, se la larghezza e l'altezza in pixel dell'immagine sono pari. Se l'immagine ha una larghezza e un'altezza in pixel dispari, anche l'elemento contenitore deve avere una larghezza e un'altezza dispari.

Nell'esempio seguente vengono creati due oggetti Border che contengono Image. Il bordo superiore dispone di una larghezza e un'altezza pari affinché corrispondano a quelle dell'immagine. Il bordo inferiore dispone di una larghezza e un'altezza dispari.

Nell'immagine seguente viene mostrato l'output dell'esempio e l'effetto della dimensione del contenitore sull'immagine.

Immagini centrate nei bordi

<Page x:Class="PixelSnapping.Images"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://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>

Purtroppo, la semplice regolazione della dimensione dell'oggetto contenitore non garantisce l'allineamento dei pixel del dispositivo. L'intero layout di un'applicazione può influire sull'allineamento dell'immagine. Anche i punti per pollice (dpi, dots per inch) di visualizzazione possono influire sull'allineamento dell'immagine. Nell'esempio precedente, l'allineamento dell'immagine viene eseguito correttamente solo se la visualizzazione è impostata su 96 punti per pollice (dpi, dots per inch). In caso di impostazioni diverse, è necessario regolare il layout in base alle impostazioni di visualizzazione. Laddove possibile, nelle applicazioni Windows Presentation Foundation (WPF), è necessario evitare le immagini ad alta frequenza.

Vedere anche

Concetti

Sistema di layout

Riferimenti

Image

VisualXSnappingGuidelines

VisualYSnappingGuidelines