WPF应用程序中的图像显示小于在外部查看器中查看时的图像

时间:2009-03-13 20:34:37

标签: wpf image sizing

当我在WPF应用程序中显示JPEG时(使用下面的代码),它显示的显着小于我在Windows Picture Viewer中以实际大小打开JPEG的时间。

我已经在运行时钻进了我的ImageSource的属性,我的图像有:

  • DPI为219
  • 高度238.02739726027397
  • 宽度312.54794520547944
  • PixelHeight为543
  • 和PixelWidth为713

当我使用屏幕标尺测量图像的WPF显示时,我得到约。 313x240像素(如果我能完美地定位标尺,可能会等于ImageSource报告的宽度和高度。)。

我的直觉告诉我这与WPF使用独立于设备的单元(而不是像素)有关,但我无法理解它,我仍然需要知道如何在'实际'显示图像在我的申请中大小为543x713。

<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>

4 个答案:

答案 0 :(得分:8)

谢谢马克!我根据您的信息做了一些谷歌搜索,发现this article提供了一个解决方案,以获得我想要的结果。现在开始变得有意义......

编辑:Linkrot。粘贴文章中的关键文本以供参考....

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

这里我们将Stretch设置为Uniform并将Width和Height绑定到PixelWidth和&gt; Source的PixelHeight,实际上忽略了DPI。然而,即使使用SnapToDevicePixels(其仅简单地捕捉边界而不是图像内的像素),图像将不是像素>完美的。但是,3.5 SP1中的WPF将支持NearestNeighbor&gt; BitmapScalingMode,它应该纠正这个。

答案 1 :(得分:4)

使用DPI为96. WPF根据英寸大小缩放图像,而图像查看器显示像素。在大多数Windows系统上,屏幕分辨率假定为96 DPI,因此在图像中使用它将导致一对一的翻译。

答案 2 :(得分:3)

或者,你可以扩展Image并实现MeasureOverride和ArrangeOverride来改变图像DPI的效果:

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));
    }
}

在xaml中使用它,就好像它是一个Image:

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

以上代码的缺陷(我知道):

  • 忽略拉伸
  • 假设Source是BitmapImage

===编辑 - Will的评论表明他想知道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;
    }

答案 3 :(得分:1)

这是.jpg文件本身指定DPI的结果 - WPF只是服从。 Here is a forum post通过一些解决方案详细说明问题: