Pixel Snapping in WPF Applications
The WPF graphics system uses device-independent units to enable resolution and device independence. Each device independent pixel automatically scales with the system's pontos por polegada (dpi) setting. This provides WPF applications proper scaling for different dpi settings and makes the application automatically dpi-aware.
No entanto, esse dpi Independência pode criar borda irregular renderização devido a suavização de serrilhado. Esses artefatos, normalmente vistos sistema autônomo bordas indefinidas ou semitransparentes, podem ocorrer quando o local de uma borda fica no meio de um pixel de dispositivo em vez de entre pixels de dispositivo. To address this issue, WPF provides a way for object edges in a visual tree to snap, or become fixed, to device pixels through pixel snapping, eliminating the semi-transparent edges produced by anti-aliasing.
Pixel snapping is a means to suppress these visual artifacts by applying small offsets to the geometry of the visual to align the geometry to device pixels.
Este tópico contém as seguintes seções.
- Pixel Snapping for Anti-aliased Rendering
- Diretrizes
- Bitmap Images
- Tópicos relacionados
Pixel Snapping for Anti-aliased Rendering
Sharp Lines
Without pixel snapping, anti-aliased rendered lines may appear semi-transparent if the edge does not fall between device pixels. The following illustration shows the output of a single pixel width anti-aliased line that falls in the middle of a device pixel (left) and a single pixel width line that falls between device pixels (right).
Anti-aliased line rendering.
With pixel snapping, anti-aliased lines snap, or become fixed, to the device pixels and appear sharp, eliminating semi-transparent line rendering. The following example demonstrates the affect that the SnapsToDevicePixels property has on a single pixel line. Slowly resizing the window shows the visual artifacts on an unsnapped line (left), and the fixed size of the snapped line (right) as their position change.
<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>
Observação: |
---|
SnapsToDevicePixels only affects elements that run through the layout pass. Guidelines can be set on a Drawing using the DrawingGroup object's GuidelineSet property. To manually set the guidelines of a Visual, create new guidelines using the VisualYSnappingGuidelines and VisualXSnappingGuidelines properties. |
Pixel snapping only sharpens horizontal and vertical lines and does not affect diagonal lines.
Adjoining Objects
Anti-aliasing can also cause visual artifacts when the edges between objects abut and the adjoining edge is not exactly aligned between a row or a column of device pixels. The anti-aliased scene may soften the edge using the underlying background color producing a seeping effect in which the edge between each object appears transparent in color. The following illustration demonstrates this seeping effect.
Abutting objects with seeping effect.
With pixel snapping enabled, abutting edges are snapped to the device pixels to remove the seeping effect. The following example demonstrates the affect of the SnapsToDevicePixels property on abutting objects. Slowly resizing the window demonstrates the seeping issue on the unsnapped rectangles (left) while the snapped rectangles (right) stay together with no visual irregularities.
<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>
Note that the snapped rectangles do not explicitly set a value for the SnapsToDevicePixels property. The property only needs to be set to true on the root to enable the behavior on all child elements.
Texto
Windows Presentation Foundation (WPF) always generates anti-aliased text, and if the text is static, the text will be pixel snapped. This helps sharpen the look of anti-aliased text by placing the glyphs directly on the pixel grid, providing clearer text. However, when Windows Presentation Foundation (WPF) detects any animation-like movement, such as scrolling, scaling, or animated translation, pixel snapping is turned off until the movement is complete. Once the animation or scrolling is movement is finished, pixel snapping is slowly animated back on.
Diretrizes
At its core, pixel snapping is controlled by guidelines. Guidelines assist in adjusting geometries to a device pixel grid. In most cases, pixel snapping using the SnapsToDevicePixels property will provide the desired outcome. However, this property isn't always available especially when using Drawing objects or dealing directly with a DrawingContext so guidelines must be set to achieve the desired sharpness pixel snapping provides.
To set guidelines on Drawing and DrawingContext objects, the GuidelineSet class is used. This class allows you to create horizontal and vertical guidelines that can be applied to a DrawingGroup or be pushed onto a DrawingContext for subsequent drawing commands. The guidelines instruct the drawing which lines should be snapped to a device pixel. For a detailed example of GuidelineSet usage, see Como: Apply a GuidelineSet to a Drawing.
Guidelines can also be set at the Visual level by changing the horizontal and vertical guideline collections. These are accessible through the VisualYSnappingGuidelines and VisualXSnappingGuidelines properties.
Bitmap Images
Because of the dpi independent nature of WPF, bitmap based UI can have undesired presentation results. Suavização de serrilhado cenas podem Desfoque uma imagem devido a problemas de alinhamento de pixel fracionária. Isso é especialmente verdadeiro para imagens que contêm alterações de alta freqüência, sistema autônomo linhas único pixel com contrastantes elementos adjacentes (tais sistema autônomo linhas em preto e branco alternadas). The following illustration demonstrates the image quality differences of an aligned image (left) and an image offset to not align with device pixels (right).
Image alignment to device pixels.
A common scenario for images in UI is to center an image representing an icon within another object. Because icons are typically small images with high frequency changes, adjustments to the application's layout may need to be made to avoid the visual artifacts produced by anti-aliasing.
To properly center an image, the container should have an even width, height if the image's pixel width, height are even. If the image has an odd pixel width, height, the containing element should also have an odd width, height.
The following example creates a two Border objects that contain an Image. The top border has an even width and height to match that of the image. The bottom border has an odd width and height.
The following illustration shows the output from the example and the affect the container size has on image.
<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>
Unfortunately, simply adjusting the container object's size does not guarantee device pixel alignment. The entire layout of an application can have an affect on the alignment of the image. The display pontos por polegada (dpi) also affects image alignment. No exemplo acima, o alinhamento da imagem só funcionará se a exibição é conjunto para 96 pontos por polegada (dpi). Em qualquer outra conjunto seletiva, o layout precisa ser ajustada para acomodar o vídeo conjunto tings. High frequency images should be avoided whenever possible in Windows Presentation Foundation (WPF) applications.