Reputation: 35584
I've encountered a problem with bitmap images in WPF. When the image container starts on a position which is not a whole number, the image seems to not respect the value of SnapsToDevicePixels
.
Example code:
<Window x:Class="BlurryImage.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="110" Width="200">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Button SnapsToDevicePixels="True">
<Image SnapsToDevicePixels="True" Source="i16.png" Stretch="None"/>
</Button>
<Button SnapsToDevicePixels="True" Margin="10.333333,0,0,0">
<Image SnapsToDevicePixels="True" Source="i16.png" Stretch="None"/>
</Button>
</StackPanel>
</Window>
(Note the value of the left margin: 10.333333.)
Here the image i16.png
is a simple 16x16 bitmap in 96 DPI resolution with thin vertical lines: . (My system resolution is 96 DPI, Windows XP, .NET 4)
When I run the program, the first image is sharp, whereas the second one is blurry:
Different sources, including some here on stackoverflow, suggest different workarounds. (For example, these posts: [1], [2] and [3].) I tried the workarounds, and them seem to work. Using UseLayoutRounding="true"
on the main window makes both images sharp. Using RenderOptions.BitmapScalingMode="NearestNeighbor"
on the image makes it sharp, too.
The question is, why doesn't SnapsToDevicePixels="True"
work without workarounds? Is it a bug in WPF or I am using it in a wrong way?
Upvotes: 6
Views: 1258
Reputation: 41393
From this blog entry:
SnapsToDevicePixels
WPF anticipated that there would be cases where people wanted to align with the pixel grid instead of using sub-pixel precision. You can set the SnapsToDevicePixels property on any UIElement. This will cause us to try and render to the pixel grid, but there are quite a few cases that don't work - including images. We will be looking to improve this in the future.
So it's just a known limitation of what SnapsToDevicePixels can do.
Upvotes: 5