WPF:使用ValueConverter为ImageSource创建BitmapImage的内存含义

我在使用图像时遇到问题,并提供了一个右键单击上下文菜单来删除图像。

最初我绑定了绝对文件路径:

 

其中ImageFileName类似于C:\myapp\images\001.png

我收到错误, The process cannot access the file 'X' because it is being used by another process 。 经过大量的研究,我发现了必要的代码更改。

我使用了Stackoverflow的答案: 删除另一个进程正在使用的文件 ,并将代码放入ValueConverter

XAML:

  

价值转换器:

 public class PathToImageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { try { String fileName = value as String; if (fileName != null) { BitmapImage image = new BitmapImage(); image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.UriSource = new Uri(fileName); image.EndInit(); return image; } return new BitmapImage(); } catch { return new BitmapImage(); } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 
  1. 我关心的是内存使用情况。 当我向我的容器添加图像时,我看到内存增加。 但是,当我删除图像,并删除基础文件时,我没有看到任何内存被释放。

  2. 我也一直认为Bitmaps是一种非常低效的文件格式,因为它们是未压缩的,并且与JPEG或PNG文件相比往往是巨大的。 System.Windows.Media.Imaging.BitmapSource类是否真的从我的PNG中创建了一个未压缩的图像?

首先十分感谢!

菲利普

从URI加载图像时,WPF最多可缓存300个 ImageSource对象(使用弱引用)。 要避免这种情况,请设置BitmapCreateOptions.IgnoreImageCache选项使用FileStream来加载图像。

请注意,这可能会对应用程序的性能产生负面影响,尤其是在您在虚拟化ListBox滚动和加载图像的情况下。 但是如果你要加载非常大的图像,你可能想要避免它。

在转换器中使用以下代码( image.Freeze请注意添加的image.Freeze调用,它通过使对象成为只读和与线程无关来提高性能):

 using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { BitmapImage image = new BitmapImage(); image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.StreamSource = fs; image.EndInit(); image.Freeze(); return image; } 

另一种可能的性能优化是将DecodePixelWidth设置为缩小图像。

关于您对格式的关注 – 位图是基于像素的图像的通用名称(与基于矢量的图像相反)。 您提到的文件格式(PNG,JPEG)也是位图,它们只是编码 (可能有一些压缩)。 BitmapImage类使用WIC对它们进行解码,以便可以在屏幕上呈现它们。

试试这个..

  public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return Convert(new[] { value }, targetType, parameter, culture); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { try { string imageUri = String.Format((parameter ?? "{0}").ToString(), values); return new BitmapImage(new Uri(imageUri, UriKind.RelativeOrAbsolute)); } catch { return null; } } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); }