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 it is loaded, both the ImageSource's Width
and Height
are equal to 16,002.
Other images each of them are loading incorrectly & it looks blurred (or smoothly), because system stretches it from 16x16 to 21x21.
- correct image :
- incorrect image :
What is causing this? If the problem in source image files, how can I change ImageSource.Wi开发者_运维问答dth
to desired size in order to use this files?
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;
}
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
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:
- Modify the DPI using e.g XnView. Set it to 96.
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" />
精彩评论