问题描述
我必须从图像中获取 BitmapSource,为此我使用了这样的扩展方法:
public static BitmapSource ToBitmapSource(this Image image)
{
LogEx.FunctionEnter();
if (image == null)
throw new ArgumentNullException("image");
BitmapImage bitmapImage = null;
using (MemoryStream memory = new MemoryStream())
{
image.Save(memory,ImageFormat.Jpeg);
memory.Position = 0;
bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
}
LogEx.FunctionLeave("Rendered image as BitmapSource");
return bitmapImage;
}
如果我现在释放它的句柄并处理原始图像,它会保留在内存中,即使在多次手动调用 GC 之后也是如此。我测试使用文件而不是流与这段代码:
string filename = $"c:\\temp\\{page}.jpg";
if (File.Exists(filename))
{
File.Delete(filename);
}
_highResPageImages[page].Save(filename,ImageFormat.Jpeg);
Uri uri = new Uri(filename);
BitmapImage source = new BitmapImage();
source.BeginInit();
source.UriSource = uri;
source.CacheOption = BitmapCacheOption.OnLoad;
source.EndInit();
Document.PageImage = source;
// Ducument.PageImage = _highResPageImages[page].ToBitmapSource();
即使还有一个 OnLoad,它也会在释放句柄时被销毁。所以它必须与MemoryStream有关。但是什么?我尝试了在其他地方找到的这个 WrapperStream 并使用了 BitmapImage 的 Freeze() 方法,但都无济于事。问题是,我无法在客户的驱动器上缓存图像(即使这样做不会花费大量时间)并且我从另一个 DLL 获取图像,因此我无法事先更改它。有其他人的想法吗?
编辑:我使用 WPF 并且句柄的值正在用于显示的绑定中。也许这在某种程度上很重要。或者我在 Binding 和 handle 中使用 BitmapSource 而不是原始 BitmapImage。
解决方法
在 keep_this and_this also_this
中试试这个:
ToBitmapSource