2010-09-19 108 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圖像,我打算在我的應用程序的UI中使用。不幸的是,它們每個都加載不正確&看起來模糊(或光滑),因爲系統將其從16x16擴展到21x21。

  • 正確的圖像:Correct Image
  • 不正確的圖像:Incorrect Image

你願意爲這麼好心來解釋這個問題的可能的解決方案?如果源圖像文件存在問題,我如何將ImageSource.Width更改爲所需的大小以便使用此文件?

回答

11

您需要將圖像分辨率設置爲96 DPI(目前對於不正確的png,它是71.12)。

您可以使用免費的paint.net程序(http://getpaint.net)從圖像菜單中選擇畫布大小做到這一點,並設置了「分辨率」字段96

6

這是因爲圖像的DPI。 WPF呈現96 dpi的默認值。如果您查看不正確的png圖像的dpi。您會看到它被設置爲72.這會導致WPF將圖像縮放到96 DPI並保持原始大小。

有兩種解決方案。 您可以:

  1. 使用例如XnView修改DPI。將它設置爲96
  2. 設置寬度和高度屬性爲16,拉伸性能,以統一

    <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

也謝謝你,hkon。 :) – JSP 2010-09-19 15:58:49

+0

第二種解決方案根本不會改變DPI,它只會將原始圖像拉伸(均勻)填充容器,從而導致模糊的圖像。 – 2017-11-09 18:13:31

+0

事實上,對於這個問題中的例子,我認爲它沒有什麼區別。 – hkon 2017-11-25 21:38:01

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 /身高正確的價值觀,你可以做一些像我一樣:

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

和r像這樣調整它:

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方法,謝謝。爲了還款,一個錯誤修正(原始不起作用,例如,與黑白tifs)。 – Will 2014-02-21 14:46:30