8

当我在我的 WPF 应用程序中显示 JPEG 时(使用以下代码),它显示的内容比我在 Windows 图片查看器中以实际大小打开 JPEG 时显示的要小得多。

我在运行时深入研究了 ImageSource 的属性,并且我的图像具有:

  • DPI 为 219
  • 高度为 238.02739726027397
  • 宽度为 312.54794520547944
  • 像素高度为 543
  • 和 713 的 PixelWidth

当我使用屏幕标尺测量图像的 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

4 回答 4

11

谢谢马克!我根据你的信息做了一些谷歌搜索,发现这篇文章提供了一个解决方案来获得我想要的结果。这现在开始有意义了……

编辑:链接。将文章中的关键文本粘贴到此处以供参考....

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

在这里,我们将 Stretch 设置为 Uniform,并将 Width 和 Height 绑定到 Source 的 PixelWidth 和 >PixelHeight,从而有效地忽略了 DPI。然而,即使使用 SnapToDevicePixels(它只是捕捉边界,而不是图像内的像素),图像也不会是像素 > 完美的。但是,3.5 SP1 中的 WPF 将支持 NearestNeighbor >BitmapScalingMode,这应该可以纠正这个问题。

于 2009-03-13T21:01:03.457 回答
6

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

于 2009-03-13T20:47:34.737 回答
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 中使用它,就好像它是一个图像:

<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;
    }
于 2011-06-21T06:29:51.617 回答
1

这是 .jpg 文件本身指定 DPI 的结果 - WPF 只是服从。 这是一个论坛帖子,详细说明了一些解决方案的问题:

于 2009-03-13T20:50:12.050 回答