WPF中的图像变得模糊

43
我正在使用C#和WPF开发应用程序。我将图像放在WrapPanel中,并在一个带有边框的Grid中显示,还在按钮中使用了这些图像。问题是我的图像控件失去了其质量。尽管我使用了SnapsToDevicePixels="True",但它仍然看起来模糊不清。这里分享了一张图片:enter image description here

你是想把图片变得比原来的尺寸更大还是更小? - Øyvind Bråthen
没有,我已经修复了它的原始大小。 - user701677
7个回答

84

我认为Markus说的是解决你问题的一种方法,尝试在每个图像中添加一个属性 RenderOptions.EdgeMode="Aliased"

我认为Markus提到的方法是解决你问题的一种方式,尝试为每个图像添加一个属性RenderOptions.EdgeMode="Aliased"

<Image Source="/LoginPanel;component/Icons/icoLogin.ico"
       RenderOptions.BitmapScalingMode="NearestNeighbor"
       RenderOptions.EdgeMode="Aliased"/>

如果你仍然无法解决问题,那么可以参考这篇文章(模糊位图)创建一个自定义的Bitmap类并将其应用于所有制造问题的图像。

你也可以查看这个Stack Overflow的问题


1
@Turtleneck:我认为这是一个重复的问题,与https://dev59.com/InRB5IYBdhLWcg3wiHz7相同。 - SharpUrBrain
最近邻居帮我解决了这个问题。谢谢! - pyknight202

35

SnapsToDevicePixels似乎不能用于位图。

NearestNeighbor选项实际上会转换位图,并最终得到与原始位图不同的位图。

在WPF 4中,引入了FrameworkElement上的属性“UseLayoutRounding”来解决这个问题。

通过将此属性设置为True,在根元素(如Window)上,将在像素边缘对齐子元素。

<Window UseLayoutRounding="True">...</Window>

这甚至比使用最近邻缩放模式更好,因为它保留了图像的原始像素。谢谢 - helb
1
这对我起作用了,但我发现它并不需要放在根元素上。父元素甚至目标元素也可以实现所需的效果。 - maxp

16

这对我有效

<Image Source="/LoginPanel;component/Icons/icoLogin.ico"
       RenderOptions.BitmapScalingMode="NearestNeighbor"</Image>

为每个图像设置RenderOptions.BitmapScalingMode="NearestNeighbor"。或者参见StackOverflow上的这个问题

编辑:
这是我的示例代码

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="661">
    <WrapPanel>
        <Button VerticalAlignment="Center">
            <Image Source="/WpfApplication1;component/icoChip32x32.ico"
               RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
        </Button>
        <Button VerticalAlignment="Center">
            <Image Source="/WpfApplication1;component/icoChip32x32.ico"
                   RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
        </Button>

        <Button VerticalAlignment="Center">
            <Image Source="/WpfApplication1;component/Presentation-Edit.png"
               RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
        </Button>
        <Button VerticalAlignment="Center">
            <Image Source="/WpfApplication1;component/Presentation-Edit.png"
                   RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
        </Button>
    </WrapPanel>
</Window>

这是我的结果:
...这是我的结果


3
它对于图像来说很完美,但边框却被多个条纹扰乱了,我的意思是边框随着更多的条纹变得模糊不清。如果您不介意的话,能否请分享一下您有的任何样例应用程序? - user701677
3
我看不出我的示例代码有任何问题。也许你可以试着调整一下边距?你能否贴出更多的代码呢? - Markus
1
感谢您的出色回答,我通过使用自定义类来修复了位图的问题 :) - user701677

7
如果您使用图像作为内容,请在父元素上使用UseLayoutRounding="True"属性。在您的情况下,这是按钮。

4

我曾遇到一个模糊的图像背景问题,这是由于缩放引起的。解决方法比您想象的要简单得多。一开始我以为它被缩放为二次幂纹理大小,但实际上缩放匹配了系统 DPI (96) : 图像 DPI (72,这是许多编辑器的默认值) 的比例。如果将图像调整为 96 DPI,则可以在默认 Windows 设置下完美地显示像素。

注:尝试了一个具有高对比度细节的图像,略微变软。


2
WPF不使用具体的像素值来确定大小和位置,这样可以随着DPI的变化而进行缩放。这可能会导致问题,它试图使用与屏幕上离散像素不对应的位置;一些图像像素被渲染到多个屏幕像素上,我们看到了模糊。使用UseLayoutRendering=true和SnapToDevicePixels=false可以解决此问题。您还需要在主窗口级别设置它,以便计算级联到图像级别。您可以通过创建一个简单的WPF应用程序并添加图像来尝试此功能。将图像边距设置为一些愚蠢的东西(如(10.452,0.736,0,0))会导致模糊。这可以通过在图像上使用UseLayoutRendering=true来消除。如果您在InitializeComponent()之后再次设置窗口的边距,则无论您是否在图像上设置UseLayoutRendering=true,它都会变得模糊,因为在将图像移动到与这些像素对齐不匹配的位置之前进行了与屏幕像素对齐的计算。我不完全确定UseLayoutRendering和SnapToDevicePixels之间的区别是什么-我认为它只是计算时间的不同。UseLayoutRendering似乎更适合于图像。从原始大小拉伸/压缩图像也可能导致模糊问题。

非常感谢!您的解决方案是唯一有效的! - wRadion
想留言说一下,这个对我也起作用了。SnapsToDevicePixels="False"和UseLayoutRounding="True"是所有建议中效果最好的。 - Krythic

1
我曾经遇到过同样的问题,但在我的情况下,我下载了图标并发现它们的DPI也都是错误的...110.56、116.xx和95.99等等...

当我将所有图标的DPI更改为96时,一切正常!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接