2010-09-19 30 views
15

Mon problème est que le chargement de l'image ne semble pas correctement provenir des ressources de l'application. Ceci est du code:Chargement de l'image dans ImageSource - largeur et hauteur incorrectes

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; 

fichier image "16x16_incorrect.png" est un fichier PNG 16x16 32bpp, mais après l'exécution de code ci-dessus, s.Width = s.Height = 21,59729 .... J'ai aussi un autre fichier - "16x16_correct.png", quand je le charge de la même manière, la largeur et la hauteur de ImageSource sont égales à 16.002.

J'ai un grand paquet d'images utiles PNG 16x16 32bpp, que j'ai l'intention d'utiliser dans l'interface utilisateur de mes applications. Malheureusement, chacun d'entre eux chargeant incorrectement & semble flou (ou lisse), car le système l'étend de 16x16 à 21x21.

  • image correcte: Correct Image
  • l'image incorrecte: Incorrect Image

Voulez-vous pour être si bien vouloir expliquer la solution de ce problème? Si le problème dans les fichiers image source, comment puis-je changer ImageSource.Width à la taille désirée afin d'utiliser ces fichiers?

Répondre

11

Vous devez définir la résolution d'image à 96 DPI (actuellement c'est 71,12 pour le png incorrect).

Vous pouvez le faire en utilisant le programme paint.net libre (http://getpaint.net) dans le menu Image, sélectionnez la taille de toile et définir le champ « résolution » à 96

6

Ceci est dû au DPI des images. WPF restitue par défaut avec 96 dpi. Si vous regardez la dpi de l'image png incorrecte. Vous verrez qu'il est réglé sur 72. Cela amène WPF à redimensionner l'image à 96 DPI et conserver la taille d'origine.

Il existe deux solutions. Vous pouvez:

  1. Modifiez le DPI à l'aide, par exemple, de XnView. Réglez-le à 96.
  2. Définissez les propriétés Largeur et hauteur à 16, et la propriété extensible à uniforme

    <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

Merci aussi, hkon. :) – JSP

+0

La deuxième solution ne change pas du tout le DPI, il suffit d'étirer l'image originale pour remplir (uniformément) le conteneur qui peut conduire à une image floue. –

+0

En effet, pour l'exemple de la question, je pense que cela ferait peu de différence. – hkon

17

Si vous ne voulez pas changer DPI vous pouvez l'extérieur le faire avec ceci:

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

Si vous avez juste besoin de valeurs correctes dans Image.Source.Width/hauteur, vous pouvez faire quelque chose comme je l'ai fait:

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

et r esize comme ça:

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

Emprunté votre méthode DPI, merci. Pour le remboursement, un bugfix (original ne fonctionnerait pas, par exemple, avec tifs b/w). – Will