Мои изображения размыты! Почему WPF SnapsToDevicePixels не работает?

165

Я использую некоторые изображения в моем приложении WPF.

XAML:

<Image Name="ImageOrderedList"
       Source="images/OrderedList.png"
       ToolTip="Ordered List"
       Margin="0,0,5,5"
       Width="20"
       Height="20"
       SnapsToDevicePixels="True"
       MouseUp="Image_MouseUp"
       MouseEnter="Image_MouseEnter"
       MouseLeave="Image_MouseLeave" />

Но они кажутся нечеткими.

Почему эта SnapsToDevicePixels="True"линия не предотвращает эту проблему?

Зак Петерсон
источник
4
Ваши ссылки на изображения, кажется, сломаны. Если у вас все еще есть оригинальные изображения, пожалуйста, загрузите их в stack.imgur. Спасибо.
Илмари Каронен
1
Если ни один из приведенных ниже советов не сработал сразу, попробуйте изменить размер изображения в 4 раза по ширине и высоте. Поэтому вместо 179 X 44 попробуйте 176 X 44.
Мартин Лоттеринг

Ответы:

233

Возможно, вы захотите попробовать новое свойство, доступное сейчас в WPF4 . Оставьте RenderOptions.BitmapScalingModeна HighQuality или просто не объявить.

Ближайший сосед работал для меня, за исключением того, что это приводило к резким растровым изображениям при увеличении приложения. Это также, похоже, не исправило каких-либо глюков, когда иконки странным образом изменяли размеры.

На корневом элементе (т.е. главного окна) добавить это свойство: UseLayoutRounding="True".

Свойство, ранее доступное только в Silverlight, теперь исправило все проблемы с размером растрового изображения. :)

Domokun
источник
4
Дополнительную информацию об этом новом свойстве можно найти здесь: blogs.msdn.com/text/archive/2009/08/27/layout-rounding.aspx
Domokun,
5
UseLayoutRendering = "True" - это то, что я использовал - это идеально для решения моих размытых изображений. Спасибо!
Matt DeKrey
25
НУ НАКОНЕЦ ТО!! UseLayoutRounding должен быть установлен по умолчанию. Изображения отображаются так же, как оригинал, и даже текст в некоторых местах (например, ContextMenus, по крайней мере, для меня) отображается четче, чем раньше. Спасибо, Домокун!
грант
3
Я думаю, что те из нас все еще застряли на .NET 3.5 нет вариантов?
jpierson
2
Я обнаружил, что это решает мою проблему, если установить для свойства «Растянуть» значение «Нет» на изображениях, но во всех других сценариях, даже при отключенном рендеринге и псевдонимах изображений HighQuality растяжение изображения по-прежнему отстой в WPF. Но, по крайней мере, это исправило проблему для не растянутых изображений (что не должно было быть проблемой в первую очередь)
Кристиан Финдли
74

Вместо того, чтобы использовать SnapsToDevicePixels, я вместо этого использовал, RenderOptions.BitmapScalingModeи они теперь хороши и четки!

XAML:

<Image Name="ImageOrderedList"
       Source="images/OrderedList.png"
       ToolTip="Ordered List"
       Margin="0,0,5,5"
       Width="20"
       Height="20"
       RenderOptions.BitmapScalingMode="NearestNeighbor"
       MouseUp="Image_MouseUp"
       MouseEnter="Image_MouseEnter"
       MouseLeave="Image_MouseLeave" />
Зак Петерсон
источник
1
Кроме того, если ваше изображение имеет точный размер, указанный в теге <Image>, то оно не должно масштабироваться и должно отображаться четко.
Beardo
1
Я не уверен, что это даст желаемый эффект при другом DPI
Дейв
1
Beardo, исходная графика и <Image> имеют размер 20 на 20 пикселей. Насколько я понимаю, проблема исходит от WPF. Он как бы хочет игнорировать пиксельную сетку монитора, поэтому его логическая сетка обычно не идеально согласуется с физической сеткой.
Зак Петерсон
9
@Zack Width = "20" не означает 20 пикселей. Это означает 20/96 дюйма. Если ваша ОС настроена на работу с разрешением 96 DPI, то она составляет 20 пикселей. Как ваш ближайший сосед будет выглядеть на хорошем мониторе, например, на 160 DPI? И как это будет выглядеть при печати с разрешением 300 DPI? Вы не должны оптимизировать для вашей машины.
Фрэнк Крюгер
2
Я также обнаружил, что для изображений размером в пиксель NearestNeighbor намного лучше, чем HighQuality, особенно если вы комбинируете его с img.Width = imgSource.PixelWidth; img.Height = imgSource.PixelHeight. Мой клиент предоставил некоторые изображения с разными сумасшедшими значениями DPI, и я не мог попросить клиента конвертировать их все, поэтому мне пришлось использовать этот хак.
JustAMartin
23

+1 для Зака ​​Петерсона

Я использую .Net 3.5 sp1, и это выглядит как самое простое решение для большого количества нечетких изображений. Нет ничего сложного в том, чтобы указать RenderOptions на месте, но для сторонних компонентов имеет смысл стиль в ресурсе уровня приложения:

 <Style TargetType="{x:Type Image}">
    <Setter
        Property="RenderOptions.BitmapScalingMode"
        Value="NearestNeighbor" />
 </Style>

Хорошо работало, когда AvalonDock начал рендерить размытые иконки.

DK.
источник
1
AvalonDock также вызывает у меня такие же головные боли ... и я до сих пор с .Net 3.5
Игнасио Солер Гарсия
9

Использование UseLayoutRounding="True"корневого окна работает во многих случаях, но я столкнулся с проблемой при использовании элемента управления ленты WPF . Мое приложение использует контекстные вкладки, которые отображаются в зависимости от того, что делает пользователь, и когда я установил UseLayoutRoundingдля True, контекстная вкладка не будет отображаться, и изображение RibbonButton также не будет отображаться. Также приложение зависает на много секунд и вентилятор процессора начинает петь.

Использование RenderOptions.BitmapScalingMode="NearestNeighbor"на моем изображении исправило проблемы рендеринга изображения (размытое и обрезанное изображение) и полностью совместимо с использованием контекстных вкладок ленты.

Омид Б.
источник
1
UseLayoutRounding = "True" работал для меня. Спасибо. mikecroteau.wordpress.com/2013/01/20/wpf-net-xaml-blurry-images
mcroteau
6

RenderOptions.BitmapScalingMode = "NearestNeighbor" работает хорошо большую часть времени. Тем не менее, время от времени вы будете получать графические сбои (в моем случае 4 из 5 изображений выглядели нормально, но у пятого были небольшие искажения на правом краю). Я исправил это, увеличив правое поле элемента управления изображением на 1.

Если это по-прежнему не помогает, попробуйте элемент управления Bitmap, о котором упоминает EugeneZ. Это замена для управления изображением, и до сих пор он работал довольно хорошо для меня. См. Http://blogs.msdn.com/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx


источник
5

Убедитесь, что вы сохранили изображение в том же DPI, в котором работает ваше приложение WPF, в некоторых форматах изображения эта информация хранится в виде метаданных. Я не знаю, решает ли это проблему, но у меня есть некоторые проблемы из-за этого, когда изображения, размер которых увеличен до 100%, стали больше или меньше, чем ожидалось.

Может быть что-то похожее.


источник
5

используйте UseLayoutRounding = True для самого верхнего элемента в вашем приложении

Varatharaj
источник
3

Я обнаружил, что RenderOptions.BitmapScalingMode = "NearestNeighbor" не работает для меня. Я использую Windows XP x32 с DirectX 9.0c. Поскольку фактический рендеринг для WPF выполняется с помощью DirectX, это может оказать влияние. У меня действительно включено сглаживание для XP со следующими записями реестра:

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Avalon.Graphics] "MaxMultisampleType" = dword: 00000004 "EnableDebugControl" = dword: 00000001

Однако отключение с этими настройками не влияет на изображения. Я думаю, что это влияет только на 3D Viewports.

Наконец, я обнаружил, что размытие происходит как с текстом TextBlocks, так и с изображениями. И размывание происходит только для некоторых текстовых блоков и изображений, а не для всех.

скоро
источник
3

Я обнаружил, что никакая комбинация предложенных обходных путей не излечит мою, казалось бы, случайную проблему с размытым изображением. Я, как и многие другие, не могу перейти на .net 4, чтобы использоватьUseLayoutRendering свойство.

Что я нашел для работы:

  • Убедитесь, что размеры вашего [оригинального] изображения кратны 2. Это, кажется, предотвращает некоторые странные проблемы с масштабированием изображения.
  • Иногда я также обнаружил, что настройка полей на пикселях или 2 может предотвратить проблему.
Jahhai
источник
1

Когда я прочитал вопрос, моей первой мыслью было то, что вы слишком сильно взорвали изображение, но, похоже, это не тот случай, когда вы смотрите на изображение вашего приложения.

Вторая мысль - это цветовая палитра, но с черным как один из цветов, который не отображается правильно, это не так вероятно.

Если вы можете полностью исключить два выше, я в настоящее время в тупике.

В качестве эксперимента вы можете попробовать другие графические форматы, но PNG должен быть в порядке. Мне придется еще немного подумать, чтобы придумать лучший ответ.

Грегори Бимер
источник
1
+1, чтобы отвести необоснованные отрицательные голоса, так как я думаю, что вы предложили несколько разумных предложений и только пытались помочь, и самое главное, что в ваших предложениях не было ничего неправильного.
jpierson
1

Я пытался использовать RenderOptions.BitmapScalingMode = HighQuality, похоже, это вызывает некоторые проблемы в Windows 8.1, поэтому я попытался запустить их через инструмент под названием PngOut.exe

http://advsys.net/ken/utils.htm

Что уменьшает заголовок png, а также уменьшает размер, но без изменения качества изображения.

И теперь все мои изображения идеальны! :-)

MMM
источник