Question

My problem is that the image loading seems to be uncorrectly from application resources. This is code:

    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;

Image file "16x16_incorrect.png" is 16x16 32bpp PNG file, but after executing above code, s.Width = s.Height = 21,59729.... I also have another file - "16x16_correct.png", when I load it in the same manner, both the ImageSource's Width and Height are equal to 16,002.

I have a big pack of useful PNG 16x16 32bpp images, which I intend to use in UI of my apps. Unfortunately, each of them loading incorrectly & looks blurred (or smoothy), because system stretches it from 16x16 to 21x21.

  • correct image : Correct Image
  • incorrect image : Incorrect Image

Would you like as to be so kindly to explain the possible solution of this problem? If the problem in source image files, how can I change ImageSource.Width to desired size in order to use this files?

Was it helpful?

Solution

You need to set the image resolution to 96 DPI (currently it's 71.12 for the incorrect png).

You can do it using the free paint.net program ( http://getpaint.net ) from the Image menu select Canvas size and set the "resolution" field to 96

OTHER TIPS

If you don't want to change DPI externally you can do it with this:

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

If you just need correct values in Image.Source.Width/Height you can do something like I did:

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

and resize it like so:

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

This is because of the DPI of the images. WPF renders default with 96 dpi. If you look at the dpi of the incorrect png image. You will see that it is set to 72. This causes WPF to scale the image to 96 DPI and keep the original size.

There are two solutions. You can:

  1. Modify the DPI using e.g XnView. Set it to 96.
  2. Set the Width and Height properties to 16, and the Stretch property to 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"  />
    

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top