Изображение в приложении WPF отображается меньше, чем при просмотре во внешней программе просмотра - PullRequest
6 голосов
/ 13 марта 2009

Когда я отображаю JPEG в своем приложении WPF (используя следующий код), он отображается значительно меньше, чем при открытии JPEG в средстве просмотра изображений Windows в реальном размере.

Я углубился в свойства моего ImageSource во время выполнения, и у моего изображения:

  • DPI 219
  • Высота 238,02739726027397
  • Ширина 312,54794520547944
  • Пиксельная высота 543
  • и ширина пикселя 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 ]

8 голосов
/ 14 марта 2009

Спасибо, Марк! Я провел поиск в Google на основе вашей информации и нашел эту статью , которая предоставила решение для получения желаемого результата. Это начинает иметь смысл сейчас ...

Редактировать: Линкрот. Вставка критического текста из статьи сюда для справки ....

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

Здесь мы установили для Stretch значение Uniform и привязали ширину и высоту к PixelWidth и> PixelHeight источника, фактически игнорируя DPI. Изображение, тем не менее, не будет пиксельным> идеальным, даже при использовании SnapToDevicePixels (который просто фиксирует границы, а не пиксели> внутри изображения). Однако WPF в 3.5 SP1 будет поддерживать NearestNeighbor> BitmapScalingMode, что должно исправить это.

4 голосов
/ 13 марта 2009

Используйте DPI 96. WPF масштабирует изображение на основе размера в дюймах, в то время как средство просмотра изображений отображает пиксели. В большинстве систем Windows разрешение экрана принимается равным 96 DPI, поэтому его использование в изображении приведет к переводу один на один.

3 голосов
/ 21 июня 2011

Кроме того, вы можете расширить 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>

Недостатки вышеуказанного кода (о котором я знаю):

  • игнорирует растяжение
  • Предполагается, что источник является BitmapImage

=== Редактировать - комментарий Уилла предполагает, что он хотел бы знать, что находится в 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;
    }
1 голос
/ 13 марта 2009

Это результат того, что сам файл .jpg указывает DPI - WPF просто подчиняется. Вот сообщение на форуме , детализирующее проблему с некоторыми решениями:

...