在 WPF 中常见的产品列表等功能中,如果一次性加载了大量的原图当缩略图,会特别占内存。比如下面代码中的Sample.jpg
是一张分辨率为 7360 x 4912 的图片。启动后的程序内存占用 534 MB。
<Image Width="200" Source="Sample.jpg"/>
如果是产品列表,那么占用的内存可想而知要有多大。
那么在 WPF 中怎样将图像作为真正意义上的缩略图加载呢?答案是使用 DecodePixelWidth 属性即可,这个属性是 WPF 内置的,可以将 Image 作为缩略图加载以节省应用程序内存。微软官方文档:https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/graphics-multimedia/how-to-load-an-image-as-a-thumbnail?view=netframeworkdesktop-4.8
在 XAML 中设置 DecodePixelWidth 属性
以下示例在 Extensible Application Markup Language (XAML) 中设置 BitmapImage 的 DecodePixelWidth 属性,以减少加载图像所需的内存。
<!-- Simple image rendering. However, rendering an image this way may not
result in the best use of application memory. See markup below which
creates the same end result but using less memory. -->
<Image Width="200" Source="Sample.jpg"/>
<Image Width="200">
<Image.Source>
<!-- To save significant application memory, set the DecodePixelWidth or
DecodePixelHeight of the BitmapImage value of the image source to the desired
height and width of the rendered image. If you don't do this, the application will
cache the image as though it were rendered as its normal size rather than just
the size that is displayed. -->
<!-- Note: In order to preserve aspect ratio, only set either DecodePixelWidth
or DecodePixelHeight but not both. -->
<BitmapImage DecodePixelWidth="200" UriSource="Sample.jpg" />
</Image.Source>
</Image>
在代码中设置 DecodePixelWidth 属性
以下示例在代码中设置 BitmapImage 的 DecodePixelWidth 属性,以减少加载图像所需的内存。
// Create Image Element
Image myImage = new Image();
myImage.Width = 200;
// Create source
BitmapImage myBitmapImage = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"Simple.jpg");
// To save significant application memory, set the DecodePixelWidth or
// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather than just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
//set image source
myImage.Source = myBitmapImage;
可以看到设置 DecodePixelWidth 属性后,同一张图片的内存占用降低为 65 MB,效果非常明显。