Minhas imagens estão tremidas! Por que o SnapsToDevicePixels do WPF não está funcionando?

165

Estou usando algumas imagens no meu aplicativo 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" />

Mas, eles parecem confusos.

Por que essa SnapsToDevicePixels="True"linha não impede esse problema?

Zack Peterson
fonte
4
Os links da sua imagem parecem ter quebrado. Se você ainda possui as imagens originais, reenvie-as para stack.imgur. Obrigado.
Ilmari Karonen
1
Se nenhuma das dicas abaixo funcionar imediatamente, tente também alterar o tamanho da sua imagem para um fator de 4 em largura e altura. Então, ao invés de 179 X 44, tente 176 X 44.
Martin Lottering

Respostas:

233

Você pode considerar tentar uma nova propriedade disponível agora no WPF4 . Deixe o itemRenderOptions.BitmapScalingMode para HighQuality ou simplesmente não o declare.

O NearestNeighbor funcionou para mim, exceto que levou a bitmaps irregulares ao ampliar o aplicativo. Também não pareceu corrigir nenhuma falha em que os ícones eram dimensionados de maneiras estranhas.

No seu elemento raiz (ou seja, a sua janela principal) adicionar essa propriedade: UseLayoutRounding="True".

Uma propriedade anteriormente disponível apenas no Silverlight agora corrigiu todos os problemas de dimensionamento de bitmap. :)

Domokun
fonte
4
Mais informações sobre esta nova propriedade encontradas aqui: blogs.msdn.com/text/archive/2009/08/27/layout-rounding.aspx
Domokun 29/04/10
5
UseLayoutRendering = "True" é o que eu usei - isso é perfeito para resolver minhas imagens tremidas. Obrigado!
Matt DeKrey
25
FINALMENTE!! UseLayoutRounding deve ser definido por padrão. As imagens aparecem exatamente como o texto original e até mesmo em alguns lugares (como ContextMenus, pelo menos para mim) aparece mais nítido do que antes. Obrigado, Domokun!
conceder
3
Eu acho que aqueles de nós ainda presos no .NET 3.5 não têm opções?
jpierson
2
Estou descobrindo que isso corrige o meu problema se eu definir a propriedade Esticar como Nenhum nas imagens, mas em todos os outros cenários, mesmo com a renderização e o aliasing de imagens HighQuality desativados, o alongamento de imagens ainda é um problema no WPF. Mas, pelo menos, este fixou o problema para imagens não esticado (que não deve ter sido um problema em primeiro lugar)
Christian Findlay
74

Em vez de usar SnapsToDevicePixels, eu usei RenderOptions.BitmapScalingModee agora eles são legais e crocantes!

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" />
Zack Peterson
fonte
1
Além disso, se a sua imagem tiver o tamanho exato especificado na tag <Image>, não será necessário dimensioná-la e deve renderizá-la com clareza.
22269 Beardo
1
Eu não estou certo de que este terá o efeito desejado em um DPI diferente
Dave
1
Beardo, o gráfico de origem e a <Imagem> são ambos 20 pixels por 20 pixels. Pelo que entendi, a questão vem do WPF. Ele meio que quer desconsiderar a grade de pixels do monitor, por isso a grade lógica geralmente não se alinha perfeitamente com a grade física.
Zack Peterson
9
@Zack Width = "20" não significa 20 pixels. Significa 20/96 de polegada. Se o seu sistema operacional estiver configurado para executar em 96 DPI, serão 20 pixels. Agora, como o seu vizinho mais próximo ficará em um bom monitor, 160 DPI por exemplo? E como ficará quando você imprimir em 300 DPI? Você não deve otimizar para sua máquina de desenvolvimento.
Frank Krueger
2
Também descobri que, para imagens em tamanho de pixel, NearestNeighbor é muito melhor que HighQuality, especialmente se você a combinar com img.Width = imgSource.PixelWidth; img.Height = imgSource.PixelHeight. Meu cliente forneceu algumas imagens com diferentes valores de DPI malucos e eu não podia pedir ao cliente para convertê-las todas, então tive que usar esse hack.
JustAMartin
23

+1 para Zack Peterson

Estou usando o .Net 3.5 sp1 e parece a solução mais simples para um grande número de imagens difusas. Não é muito importante especificar RenderOptions no local, mas para componentes de terceiros faz sentido um estilo no recurso no nível do aplicativo:

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

Funcionou bem quando o AvalonDock começou a renderizar ícones embaçados.

DK.
fonte
1
AvalonDock também está me dando as mesmas dores de cabeça ... e eu ainda estou com Net 3.5
Ignacio Soler Garcia
9

Usar a UseLayoutRounding="True"janela raiz funciona em muitos casos, mas encontrei um problema ao usar o controle WPF Ribbon . Meu aplicativo depende de guias contextuais que aparecem de acordo com o que o usuário está fazendo e quando eu definir o UseLayoutRoundingque True, a guia contextual não iria aparecer e imagem do RibbonButton nenhum dos dois. Além disso, o aplicativo congela por muitos segundos e o ventilador da CPU começa a cantar.

O uso RenderOptions.BitmapScalingMode="NearestNeighbor"da minha imagem corrigiu os problemas de renderização da imagem (imagem difusa e cortada) e é totalmente compatível com o uso das guias contextuais da faixa de opções.

Omid B.
fonte
1
UseLayoutRounding = "True" funcionou para mim. Obrigado. mikecroteau.wordpress.com/2013/01/20/wpf-net-xaml-blurry-images
mcroteau
6

RenderOptions.BitmapScalingMode = "NearestNeighbor" funciona bem na maioria das vezes. No entanto, ocasionalmente você obtém falhas gráficas (no meu caso, 4 de 5 imagens apareceram bem, mas a quinta teve uma leve distorção na borda direita). Eu o corrigi aumentando a margem direita do controle Image em 1.

Se isso ainda não resolver, tente o controle de classe Bitmap acima mencionado pelo EugeneZ. É um substituto para o controle de imagem e, até agora, funcionou muito bem para mim. Consulte http://blogs.msdn.com/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx


fonte
5

Salve a imagem no mesmo DPI em que seu aplicativo WPF está trabalhando. Alguns formatos de imagem têm essas informações armazenadas como metadados. Não sei se isso resolve o problema, mas já tive alguns problemas por causa disso, onde as imagens redimensionadas para 100% ficaram maiores ou menores que o esperado.

Pode ser algo semelhante.


fonte
5

use UseLayoutRounding = True para o elemento mais alto em seu aplicativo

Varatharaj
fonte
3

Eu acredito que isso é um bug (ou pelo menos era). Confira esta página de troca de email de suporte da Microsoft para obter algumas idéias para corrigi-lo.

Bip Bip
fonte
3

Eu descobri que o RenderOptions.BitmapScalingMode = "NearestNeighbor" não funciona para mim. Estou usando o Windows XP x32 com o DirectX 9.0c. Como a renderização real do WPF é feita com o DirectX, isso pode ter um efeito. Eu tenho anti-aliasing ativado para XP com as seguintes entradas do Registro:

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

No entanto, desativar um aa com essas configurações não afeta as imagens. Eu acho que isso afeta apenas as viewports 3D.

Por fim, descobri que o desfoque ocorre com o texto dos TextBlocks e com as imagens. E o desfoque ocorre apenas em alguns blocos de texto e imagens, nem todos.

anon
fonte
3

Descobri que nenhuma combinação das soluções sugeridas curaria meu problema de imagem embaçada aparentemente aleatória. Eu gosto de muitos outros que não podem atualizar para .net 4 para usar a UseLayoutRenderingpropriedade.

O que eu encontrei para trabalhar:

  • Certifique-se de que as dimensões da sua imagem [original] sejam múltiplas de 2. Isso parece evitar alguns dos problemas de escala da imagem.
  • Às vezes, também descobri que o ajuste das margens nas imagens por um pixel ou 2 pode impedir o problema.
Jahhai
fonte
1

Meu primeiro pensamento, ao ler a pergunta, foi que você estava explodindo demais a imagem, mas esse não parece ser o caso da imagem que você tem do aplicativo.

O segundo pensamento é a paleta de cores, mas com o preto como uma das cores que não está renderizando corretamente, isso não é tão provável.

Se você pode descartar completamente os dois acima, estou perplexo.

Como um experimento, você pode tentar outros formatos gráficos, mas o PNG deve ficar bem. Vou ter que pensar um pouco mais para encontrar uma resposta melhor.

Gregory A Beamer
fonte
1
+1 para afastar votos negativos injustificados, pois acho que você ofereceu algumas sugestões razoáveis ​​e estava apenas tentando ajudar e, o mais importante, não havia nada de errado com suas sugestões.
jpierson
1

Eu tentei usar o RenderOptions.BitmapScalingMode = HighQuality, parece que causa alguns problemas no Windows 8.1, então o que eu fiz foi executá-los através da ferramenta chamada PngOut.exe

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

O que reduz o cabeçalho do png e também reduz o tamanho, mas sem alterar a qualidade da imagem.

E agora todas as minhas imagens são perfeitas! :-)

MMM
fonte