2010-09-19 11 views
15

Mój problem polega na tym, że ładowanie obrazu wydaje się niepoprawnie z zasobów aplikacji. Jest to kod:Ładowanie obrazu do ImageSource - niepoprawna szerokość i wysokość

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; 

plik obrazu "16x16_incorrect.png" to 16x16 32bpp PNG, ale po wykonaniu powyższego kodu, s.Width = s.Height = 21,59729 .... Mam też inny plik - "16x16_correct.png", kiedy ładuję go w ten sam sposób, zarówno szerokość, jak i szerokość ImageSource są równe 16,002.

Mam dużą paczkę przydatnych obrazów PNG 16x16 32bpp, które zamierzam użyć w interfejsie moich aplikacji. Niestety, każdy z nich ładowanie nieprawidłowo & wygląda niewyraźnie (lub smoothy), ponieważ system rozciąga go od 16x16 do 21x21.

  • poprawny obraz: Correct Image
  • nieprawidłowy obraz: Incorrect Image

Chciałbyś, aby być tak uprzejmie wyjaśnić możliwe rozwiązanie tego problemu? Jeśli problem z plikami obrazów źródłowych, jak mogę zmienić ImageSource.Width na żądany rozmiar, aby móc korzystać z tych plików?

Odpowiedz

11

Musisz ustawić rozdzielczość obrazu do 96 dpi (obecnie to 71,12 dla nieprawidłowego png).

Można to zrobić za pomocą programu Paint.NET darmowe (http://getpaint.net) z menu Obraz wybierz rozmiar płótna i ustawić „Uchwała” pole do 96

6

Wynika to z DPI obrazów. WPF renderuje domyślnie z 96 dpi. Jeśli spojrzysz na rozdzielczość niepoprawnego obrazu png. Zobaczysz, że jest ustawiony na 72. Powoduje to, że WPF przeskaluje obraz do 96 DPI i zachowa oryginalny rozmiar.

Istnieją dwa rozwiązania. Można:

  1. Zmodyfikuj DPI za pomocą np. XnView. Ustaw ją na 96.
  2. ustawić właściwości Szerokość i wysokość do 16, a właściwość Stretch jednolitych

    <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

Dziękuję też, hkon. :) – JSP

+0

Drugie rozwiązanie nie zmienia wcale DPI, wystarczy rozciągnąć oryginalny obraz, aby (jednolicie) wypełnić pojemnik, co może doprowadzić do rozmycia obrazu. –

+0

Rzeczywiście, na przykład w pytaniu uważam, że nie zrobiłoby to dużej różnicy. – hkon

17

Jeśli nie chcesz zmieniać DPI można zewnętrznie Zrób to z tego:

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

Jeśli wystarczy poprawne wartości w Image.Source.Width/wysokość można zrobić coś tak jak ja:

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

i R zmodyfikuj to tak:

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

Pożyczono twoją metodę DPI, dziękuję. W przypadku spłaty, poprawka (oryginał nie zadziałałby, na przykład, z b/w tifs). – Will