L'image au sein d'une application WPF s'affiche plus petit que lorsque visualisé dans un visualiseur externe

StackOverflow https://stackoverflow.com/questions/644526

  •  22-07-2019
  •  | 
  •  

Question

Lorsque j'affiche un fichier JPEG dans mon application WPF (à l'aide du code suivant), il est nettement plus petit que si j'ouvre le fichier JPEG dans la visionneuse d'images Windows à la taille réelle.

J'ai exploré les propriétés de mon ImageSource au moment de l'exécution et mon image a:

  • un DPI de 219
  • une hauteur de 238.02739726027397
  • une largeur de 312.54794520547944
  • une hauteur de pixel de 543
  • et une largeur en pixels de 713

Lorsque j'utilise une règle d'écran pour mesurer l'affichage WPF de l'image, je reçois env. 313x240 pixels (ce qui, si je pouvais parfaitement positionner la règle, serait probablement égal à la largeur et à la hauteur rapportées par ImageSource.).

Mon instinct me dit que cela a quelque chose à voir avec l'utilisation par WPF d'unités indépendantes du périphérique (au lieu de pixels), mais je ne peux pas en comprendre le sens et j'ai toujours besoin de savoir comment afficher l'image au réel. taille de 543x713 dans mon application.

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="300" Width="300">
    <StackPanel>
        <Image Source="Image15.jpg" Stretch="None" />
    </StackPanel>
</Window>
Était-ce utile?

La solution

Utilisez une résolution de 96. WPF redimensionne votre image en fonction de la taille en pouces, alors que la visionneuse d’images affiche des pixels. Sur la plupart des systèmes Windows, la résolution de l'écran est supposée être de 96 ppp. Par conséquent, si vous utilisez cette image dans votre image, vous obtiendrez une traduction personnalisée.

Autres conseils

Merci Marc! J'ai fait quelques recherches sur Google en fonction de vos informations et trouvé cet article. qui fournissait une solution pour obtenir le résultat souhaité. Cela commence à avoir un sens maintenant ...

Modifier: Linkrot. Coller le texte critique de l'article ici pour référence ....

<Image Source=”{Binding …}”
       Stretch=”Uniform”
       Width=”{Binding Source.PixelWidth,RelativeSource={RelativeSource Self}}”
       Height=”{Binding Source.PixelHeight,RelativeSource={RelativeSource Self}}” />
  

Ici, nous avons défini l'option Étirer sur Uniforme et lié la largeur et la hauteur à PixelWidth et à > PixelHeight de la source, en ignorant effectivement le DPI. Toutefois, l’image ne sera pas parfaite, même si vous utilisez SnapToDevicePixels (qui capture simplement les bordures et non les pixels de l’image). Cependant, WPF dans la version 3.5 SP1 prend en charge un > BitmapScalingMode NearestNeighbor, qui devrait corriger cela.

Vous pouvez également étendre Image et implémenter MeasureOverride et ArrangeOverride pour modifier l'effet du DPI de l'image:

class DpiAgnosticImage : Image
{
    protected override Size MeasureOverride(Size constraint)
    {
        var bitmapImage = Source as BitmapImage;

        var desiredSize = bitmapImage == null 
            ? base.MeasureOverride(constraint) 
            : new Size(bitmapImage.PixelWidth, bitmapImage.PixelHeight);

        var dpiScale = MiscUtil.GetDpiScale(this);
        desiredSize = new Size(desiredSize.Width / dpiScale.Width, desiredSize.Height / dpiScale.Height);

        desiredSize = ImageUtilities.ConstrainWithoutDistorting(desiredSize, constraint);

        if (UseLayoutRounding)
        {
            desiredSize.Width = Math.Round(desiredSize.Width);
            desiredSize.Height= Math.Round(desiredSize.Height);
        }

        return desiredSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        return new Size(Math.Round(DesiredSize.Width), Math.Round(DesiredSize.Height));
    }
}

Utilisez-le dans xaml comme s'il s'agissait d'une image:

<Grid>
  <local:DpiAgnosticImage
    Stretch="None"
    Source="{Binding ViewImage}">
    <Image.RenderTransform>
      <ScaleTransform
        x:Name="SomeName"/>
    </Image.RenderTransform>
  </local:DpiAgnosticImage>
</Grid>

Défauts du code ci-dessus (à ma connaissance):

  • ignore l'étirement
  • Suppose que la source est une image bitmap

=== Edit - Le commentaire de Will suggère qu'il aimerait savoir ce qu'il y a dans GetDpiScale ()

    public static Size GetDpiScale(Visual visual)
    {
        var source = PresentationSource.FromVisual(visual);

        var dpiScale = new Size(
            source.CompositionTarget.TransformToDevice.M11,
            source.CompositionTarget.TransformToDevice.M22);

        return dpiScale;
    }

C’est le résultat du fichier .jpg lui-même, spécifiant que le DPI - WPF obéit simplement. Voici un post sur le forum détaillant le problème avec quelques solutions:

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top