Moje obrazy są zamazane! Dlaczego SnapsToDevicePixels WPF nie działa?


165

Używam niektórych obrazów w mojej aplikacji 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" />

Ale wydają się niewyraźne.

Dlaczego ta SnapsToDevicePixels="True"linia nie zapobiega temu problemowi?



4
Wydaje się, że linki do Twoich zdjęć są uszkodzone. Jeśli nadal masz oryginalne obrazy, prześlij je ponownie do stack.imgur. Dzięki.
Ilmari Karonen

1
Jeśli żadna z poniższych wskazówek nie zadziała od razu, spróbuj również zmienić rozmiar obrazu na 4-krotny współczynnik szerokości i wysokości. Więc zamiast 179 X 44, spróbuj 176 X 44.
Martin Lottering

Odpowiedzi:


233

Możesz rozważyć wypróbowanie nowej właściwości dostępnej teraz w WPF4 . Pozostawić RenderOptions.BitmapScalingModedo HighQuality lub po prostu nie objawi.

NearestNeighbor działał dla mnie, z wyjątkiem tego, że prowadził do postrzępionych bitmap podczas powiększania aplikacji. Wydawało się również, że nie naprawiono żadnych usterek, w których ikony zmieniały się w dziwny sposób.

Na elemencie głównym (czyli głównego okna) dodać tę właściwość: UseLayoutRounding="True".

Właściwość wcześniej dostępna tylko w Silverlight rozwiązała teraz wszystkie problemy z rozmiarami Bitmap. :)


4
Więcej informacji na temat tej nowej nieruchomości można znaleźć tutaj: blogs.msdn.com/text/archive/2009/08/27/layout-rounding.aspx
Domokun

5
UseLayoutRendering = "True" jest tym, czego użyłem - jest to idealne rozwiązanie do rozwiązywania moich rozmytych obrazów. Dzięki!
Matt DeKrey,

25
WRESZCIE!! UseLayoutRounding powinno być ustawione domyślnie. Obrazy pojawiają się tak samo jak oryginał, a nawet tekst w niektórych miejscach (na przykład ContextMenus, przynajmniej dla mnie) jest wyraźniejszy niż wcześniej. Dzięki, Domokun!
przyznaj

3
Myślę, że ci z nas, którzy wciąż tkwią w .NET 3.5, nie mają żadnych opcji?
jpierson

2
Stwierdzam, że to rozwiązuje mój problem, jeśli ustawię właściwość Rozciągnij na Brak na obrazach, ale we wszystkich innych scenariuszach, nawet przy wyłączonym renderowaniu obrazu HighQuality i aliasingu, rozciąganie obrazu nadal jest do niczego w WPF. Ale przynajmniej rozwiązało to problem z nierozciągniętymi obrazami (co nie powinno być problemem w pierwszej kolejności)
Christian Findlay

74

Zamiast używać SnapsToDevicePixels, zamiast tego użyłem RenderOptions.BitmapScalingModei są teraz ładne i ostre!

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
Ponadto, jeśli obraz miał dokładnie taki rozmiar, jak określono w tagu <Image>, nie musiałby go skalować i powinien być wyraźny.
Beardo

1
Nie jestem pewien, czy przyniesie to pożądany efekt przy innym DPI
Dave,

1
Beardo, zarówno grafika źródłowa, jak i <Image> mają wymiary 20 na 20 pikseli. Jak rozumiem, problem pochodzi z WPF. W pewnym sensie chce zignorować siatkę pikseli monitora, więc jego logiczna siatka zwykle nie jest idealnie dopasowana do fizycznej siatki.
Zack Peterson

9
@Zack Width = „20” nie oznacza 20 pikseli. Oznacza to 20/96 cala. Jeśli Twój system operacyjny jest skonfigurowany do działania w 96 DPI, to jest to 20 pikseli. Jak teraz twój najbliższy sąsiad będzie wyglądał na dobrym monitorze, na przykład 160 DPI? A jak to będzie wyglądać przy drukowaniu z rozdzielczością 300 DPI? Nie powinieneś optymalizować swojej maszyny deweloperskiej.
Frank Krueger

2
Odkryłem również, że w przypadku obrazów o rozmiarze piksela NearestNeighbor jest znacznie lepszy niż HighQuality, zwłaszcza jeśli połączysz go z img.Width = imgSource.PixelWidth; img.Height = imgSource.PixelHeight. Mój klient dostarczył kilka obrazów z różnymi szalonymi wartościami DPI i nie mogłem poprosić klienta o konwersję wszystkich, więc musiałem użyć tego hacka.
JustAMartin

23

+1 dla Zacka Petersona

Używam .Net 3.5 sp1 i wygląda na to, że jest to najprostsze rozwiązanie dla dużej liczby rozmytych obrazów. Określanie opcji RenderOptions w miejscu nie jest skomplikowane, ale w przypadku komponentów innych firm styl w zasobach na poziomie aplikacji ma sens:

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

Działało dobrze, gdy AvalonDock zaczął renderować rozmyte ikony.


1
AvalonDock również przyprawia mnie o te same bóle głowy ... i nadal korzystam z .Net 3.5
Ignacio Soler Garcia

9

Korzystanie z UseLayoutRounding="True"okna głównego działa w wielu przypadkach, ale napotkałem problem podczas korzystania z kontrolki Wstążki WPF . Moja aplikacja opiera się na kontekstowe karty, które pojawiają się zgodnie z tym, co użytkownik robi i kiedy ustawić UseLayoutRoundingsię Truena zakładce kontekstowe nie pojawi się i obrazków RibbonButton za nie. Ponadto aplikacja zawiesza się na wiele sekund, a wentylator procesora zaczyna śpiewać.

Użycie RenderOptions.BitmapScalingMode="NearestNeighbor"na moim obrazie rozwiązało problemy z renderowaniem obrazu (rozmyty i przycięty obraz) i jest w pełni zgodne z użyciem kart kontekstowych wstążki.


1
UseLayoutRounding = "True" zadziałało dla mnie. Dzięki. mikecroteau.wordpress.com/2013/01/20/wpf-net-xaml-blurry-images
mcroteau

6

RenderOptions.BitmapScalingMode = "NearestNeighbor" działa dobrze przez większość czasu. Jednak od czasu do czasu pojawiają się usterki graficzne (w moim przypadku 4 z 5 obrazów pokazały się dobrze, ale piąty miał niewielkie zniekształcenie na prawej krawędzi). Naprawiłem to, zwiększając prawy margines kontroli obrazu o 1.

Jeśli to nadal nie rozwiązuje problemu, wypróbuj kontrolkę klasy Bitmap powyżej, o której wspomina EugeneZ. Jest to zamiennik kontroli obrazu i jak dotąd działał całkiem dobrze. Zobacz http://blogs.msdn.com/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx


5

Upewnij się, że zapisujesz obraz w tym samym DPI, w którym działa aplikacja WPF, niektóre formaty obrazów mają te informacje przechowywane jako metadane. Nie wiem, czy to rozwiązuje problem, ale mam pewne problemy z powodu tego, że obrazy przeskalowane do 100% stały się większe lub mniejsze niż oczekiwano.

Może być coś podobnego.




3

Odkryłem, że RenderOptions.BitmapScalingMode = "NearestNeighbor" nie działa dla mnie. Używam systemu Windows XP x32 z DirectX 9.0c. Ponieważ rzeczywiste renderowanie WPF odbywa się za pomocą DirectX, może to mieć wpływ. Mam włączone antyaliasing dla XP z następującymi wpisami rejestru:

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

Jednak wyłączenie aa przy tych ustawieniach nie ma wpływu na obrazy. Myślę, że dotyczy to tylko rzutni 3D.

W końcu odkryłem, że rozmycie występuje zarówno w tekście TextBlocks, jak i na obrazach. Rozmywanie występuje tylko w przypadku niektórych bloków tekstu i obrazów, a nie wszystkich.


3

Zauważyłem, że żadna kombinacja sugerowanych obejść nie wyleczy mojego pozornie przypadkowego problemu z rozmytym obrazem. Podoba mi się, że wielu innych nie może uaktualnić do .net 4 w celu korzystania z tej UseLayoutRenderingwłaściwości.

Co znalazłem, że działa:

  • Upewnij się, że wymiary [oryginalnego] obrazu są wielokrotnościami 2. Wydaje się, że zapobiega to niektórym dziwacznym problemom ze skalowaniem obrazu.
  • Czasami stwierdziłem również, że dostosowanie marginesów na obrazach o piksel lub 2 może zapobiec problemowi.

1

Moją pierwszą myślą po przeczytaniu pytania było to, że zbyt mocno wysadziłeś obraz, ale nie wydaje się, aby tak było, patrząc na obraz aplikacji, który masz.

Druga myśl to paleta kolorów, ale jeśli czarny jest jednym z kolorów, który nie renderuje się poprawnie, jest to mniej prawdopodobne.

Jeśli możesz w pełni wykluczyć powyższe dwa, jestem obecnie zaskoczony.

W ramach eksperymentu możesz wypróbować inne formaty graficzne, ale PNG powinno wystarczyć. Będę musiał to przemyśleć jeszcze bardziej, aby znaleźć lepszą odpowiedź.


1
+1, aby odeprzeć nieuzasadnione negatywne głosy, ponieważ myślę, że przedstawiłeś kilka rozsądnych sugestii i próbowałeś tylko pomóc, a co najważniejsze, nie było nic złego w twoich sugestiach.
jpierson

1

Próbowałem użyć RenderOptions.BitmapScalingMode = HighQuality, wydaje się, że powoduje to pewne problemy w Windows 8.1, więc to, co zrobiłem, to uruchomienie ich za pomocą narzędzia o nazwie PngOut.exe

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

Co zmniejsza nagłówek png, a także zmniejsza rozmiar, ale bez zmiany jakości obrazu.

A teraz wszystkie moje obrazy są idealne! :-)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.