【发布时间】:2017-01-13 16:23:08
【问题描述】:
我正在尝试显示大约 9,000 x 9,000 像素的图像。图像存储在文件中。我加载图像:
BitmapImage image = new BitmapImage(new Uri(dialog.FileName));
在那句话之后我冻结了图像。从那里,图像在内部存储/作为 BitmapSource/BitmapImage 传递给程序中的方法。
我已经编写了尝试使用 MemoryStream 对象(我将其放入 using 语句和所有内容)来调整图像大小/重新缩放图像的方法。例如,一种这样的方法以以下语句开头。
using(MemoryStream stream = new MemoryStream())
{
PngBitmapEncoder e = new PngBitmapEncoder(); //BmpBitmapEncoder();
e.Frames.Add(BitmapFrame.Create(image));
e.Save(stream);
...
}
我经常会在该函数的 e.Save(stream) 行上得到 System.OutOfMemoryException()。如果我不尝试调整图像大小,我将在创建使用 Image 控件显示图像的 Window 时收到 System.OutOfMemoryException()。
<Image Source="{Binding Image}" HorizontalAlignment="Left" VerticalAlignment="Top"
Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" />
现在,我了解到 OutOfMemory 异常可能是模棱两可的,因为它们并不一定意味着程序已经用尽了它可以访问的 RAM 量。有时,程序会设法显示图像(尽管不久之后它会抛出 OutOfMemoryException),所以我不认为有问题的文件已损坏/具有无效格式或任何东西。
在 WPF/.NET 中处理大型图像文件是否有更好的方法?任何建议将不胜感激!
编辑:我现在更改了冻结图像的方式(我创建的是冻结副本而不是冻结原件)。
【问题讨论】:
-
确保您的程序没有选择“首选 32 位”。如果由于池碎片而导致 OOM,那将有所帮助。还要确保你没有在任何地方泄露图像的副本。
-
我做了一些内存分析,分析的结果并不表明有任何碎片发生。另外——我的程序必须在 32 位机器上运行,所以如果我有一个适用于 64 位机器而不是 32 位机器的工作解决方案,那么不幸的是,这还不够。有其他选择吗?
-
为什么要创建冻结副本而不是冻结原始图像?
-
我不确定为什么会这样。我看不出有任何理由创建冻结副本,所以我将冻结原件。很好的收获,谢谢!