2010-09-19 3 views
15

Моя проблема заключается в том, что загрузка изображения выглядит некорректно из ресурсов приложения. Это код:Загрузка изображения в ImageSource - неправильная ширина и высота

BitmapImage bi = new BitmapImage(); 
    bi.BeginInit(); 
    bi.UriSource = new Uri(@"pack://application:,,,/WpfApplication3;component/Resources/Images/16x16_incorrect.png", UriKind.Absolute); 
    bi.EndInit(); 

    ImageSource s = bi; 

файл изображения "16x16_incorrect.png" является 16x16 32bpp PNG-файл, но после выполнения выше кода, s.Width = s.Height = 21,59729 .... У меня есть еще один файл - «16x16_correct.png», когда я загружаю его таким же образом, ширина и высота изображения ImageSource равны 16 002.

У меня есть большой пакет полезных изображений PNG 16x16 32bpp, которые я намерен использовать в пользовательских интерфейсах моих приложений. К сожалению, каждая из них неправильно загружается & выглядит размытой (или сглаженной), потому что система растягивает ее с 16x16 до 21x21.

  • правильное изображение: Correct Image
  • неправильное изображение: Incorrect Image

Вы хотите, чтобы быть столь любезно, чтобы объяснить возможное решение этой проблемы? Если проблема в исходных файлах изображений, как я могу изменить ImageSource.Width на нужный размер, чтобы использовать эти файлы?

ответ

11

Вы должны установить разрешение изображения до 96 DPI (в настоящее время это 71.12 за неправильный png).

Вы можете сделать это с помощью программы бесплатно Paint.NET (http://getpaint.net) из меню Image выбрать размер холста и установите в поле «разрешение» на 96

6

Это из-за DPI изображений. WPF отображает значение по умолчанию с разрешением 96 точек на дюйм. Если вы посмотрите на dpi с неправильным изображением png. Вы увидите, что ему установлено 72. Это заставляет WPF масштабировать изображение до 96 DPI и сохранять исходный размер.

Существует два решения. Вы можете:

  1. Измените DPI, используя, например, XnView. Установите его в 96.
  2. Установите свойства ширины и высоты до 16, а Stretch свойство Uniform

    <Grid> 
    <Grid.RowDefinitions> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
    </Grid.RowDefinitions> 
    <Image x:Name="MyIncorrectImageFixed" Source="http://i.piccy.info/i5/24/41/504124/16x16_incorrect.png" Width="16" Height="16" Stretch="Uniform" /> 
    <Image x:Name="MyIncorrectImage" Source="http://i.piccy.info/i5/24/41/504124/16x16_incorrect.png" Stretch="None" Grid.Row="1" /> 
    <Image x:Name="MyCorrectImage" Source="http://i.piccy.info/i5/22/41/504122/16x16_correct.png" Stretch="None" Grid.Row="2" /> 
    

+1

Thank you тоже, hkon. :) – JSP

+0

Второе решение не меняет DPI вообще, оно просто растягивает исходное изображение (равномерно), заполняя контейнер, что может привести к размытому изображению. –

+0

Действительно, для примера в вопросе, я думаю, это мало изменит. – hkon

17

Если вы не хотите, чтобы внешне изменить DPI вы можете сделайте это с этим:

public static BitmapSource ConvertBitmapTo96DPI(BitmapImage bitmapImage) 
{ 
    double dpi = 96; 
    int width = bitmapImage.PixelWidth; 
    int height = bitmapImage.PixelHeight; 

    int stride = width * bitmapImage.Format.BitsPerPixel; 
    byte[] pixelData = new byte[stride * height]; 
    bitmapImage.CopyPixels(pixelData, stride, 0); 

    return BitmapSource.Create(width, height, dpi, dpi, bitmapImage.Format, null, pixelData, stride); 
} 

Если вам просто нужно правильные значения в Image.Source.Width/Height вы можете сделать что-то, как я сделал:

this.myImage.Tag = new double[] { bitmapImage.DpiX, bitmapImage.DpiY }; 
this.myImage.Source = bitmapImage; 

и г esize его так:

public static void ResizeImage(Image img, double maxWidth, double maxHeight) 
{ 
    if (img == null || img.Source == null) 
     return; 

    double srcWidth = img.Source.Width; 
    double srcHeight = img.Source.Height; 

    // Set your image tag to the sources DPI value for smart resizing if DPI != 96 
    if (img.Tag != null && img.Tag.GetType() == typeof(double[])) 
    { 
     double[] DPI = (double[])img.Tag; 
     srcWidth = srcWidth/(96/DPI[0]); 
     srcHeight = srcHeight/(96/DPI[1]); 
    } 

    double resizedWidth = srcWidth; 
    double resizedHeight = srcHeight; 

    double aspect = srcWidth/srcHeight; 

    if (resizedWidth > maxWidth) 
    { 
     resizedWidth = maxWidth; 
     resizedHeight = resizedWidth/aspect; 
    } 
    if (resizedHeight > maxHeight) 
    { 
     aspect = resizedWidth/resizedHeight; 
     resizedHeight = maxHeight; 
     resizedWidth = resizedHeight * aspect; 
    } 

    img.Width = resizedWidth; 
    img.Height = resizedHeight; 
} 
+4

Заимствовал ваш метод DPI, спасибо. Для погашения исправление (оригинал не будет работать, например, с b/w tifs). – Will