Загрузка изображения в 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", когда Я загружаю его таким же образом, как Ширина изображения, так и Высота равны 16 002.
У меня есть большой пакет полезных изображений PNG 16x16 32bpp, которые я намерен использовать в пользовательских интерфейсах моих приложений. К сожалению, каждая из них загружается неправильно и выглядит размытой (или сглаженной), потому что система растягивает ее с 16x16 до 21x21.
- правильное изображение:
![Исправить изображение]()
- неправильное изображение:
![Неправильное изображение]()
Хотелось бы так любезно объяснить возможное решение этой проблемы? Если проблема в исходных файлах изображений, как я могу изменить ImageSource.Width на нужный размер, чтобы использовать эти файлы?
Ответы
Ответ 1
Вам необходимо установить разрешение изображения на 96 DPI (в настоящее время это 71.12 для неправильного png).
Вы можете сделать это, используя бесплатную программу paint.net(http://getpaint.net) в меню "Изображение" выберите "Размер холста" и установите "разрешение" "поле до 96
Ответ 2
Если вы не хотите изменять 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/Height, вы можете сделать что-то вроде:
this.myImage.Tag = new double[] { bitmapImage.DpiX, bitmapImage.DpiY };
this.myImage.Source = bitmapImage;
и измените его размер так:
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;
}
Ответ 3
Это происходит из-за DPI изображений. WPF отображает значение по умолчанию с разрешением 96 точек на дюйм. Если вы посмотрите на dpi с неправильным изображением png. Вы увидите, что установлено значение 72. Это заставляет WPF масштабировать изображение до 96 DPI и сохранять исходный размер.
Существует два решения.
Вы можете:
- Измените DPI, например, XnView. Установите его на 96.
-
Задайте свойства Ширина и Высота до 16, а свойство Stretch - 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" />