Image.GetThumbnailImage抛出OutOfMemoryException

时间:2015-03-30 07:45:16

标签: c# winforms

以下C#3.5代码在GetThumbnailImage中抛出异常:

Image img = null;
Image scaledImg = null;

byte[] imageData = File.ReadAllBytes("11001.jpg");
MemoryStream stream = new MemoryStream(imageData);
img = Image.FromStream(stream);
stream.Close();
stream.Dispose();

scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);

问题在于处理流。如果我删除Close()和Dispose()语句,一切正常。有谁知道为什么抛出这个异常?使用回调而不是null作为参数不会改变行为。

我不需要解决方案,我可以使用新的Bitmap(img,新的尺寸(宽度,高度)进行缩放。这可能更好,并且从一开始就使用了。

编辑:对不起,我忘了提到异常只发生在WindowsXP中。 Win7和Win8似乎正好处理上面的代码。

3 个答案:

答案 0 :(得分:0)

我认为GetThumbnailImage使用流来完成它的工作,因此需要它才能打开。你可以这样做:

Image img = null;
Image scaledImg = null;

byte[] imageData = File.ReadAllBytes("11001.jpg");
using(MemoryStream stream = new MemoryStream(imageData))
{
img = Image.FromStream(stream);
scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);
}

using关闭并处理MemoryStream,但它也处理异常情况以避免内存泄漏)

答案 1 :(得分:0)

GetThumbnailImage是一种原生方法,使用您在创建Image时传递的相同流。只有.NET方法使用流中的实际数据(它是从流中创建图像时最后加载的)。

这是一个非常典型的漏洞抽象。您以为您有一个Image对象已加载其数据,但数据仅加载在.NET部分中。任何直接与GDI +图像句柄一起工作的方法仍然需要流存在。

同一问题的另一个例子是尝试以不同的格式保存图像。当您尝试使用相同的格式进行保存时,.NET只会保存它在内存中的字节数据,这很简单。如果相同,它将使用GDI +方法SaveImageToFile,这又需要保留原始流。

如果你不介意让这个流存活,你可以在用你从该流产生的图像做的所有事情之后移动Dispose

using (var stream = new MemoryStream(imageData))
{
  var img = Image.FromStream(stream);
  var scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);

  scaledImg.Save(...);
}

如果你介意的话,最简单的事情是:

var bmp = new Bitmap(Image.FromStream(stream));

Bitmap构造函数将复制图像数据,您不再需要保留流。

答案 2 :(得分:0)

Image对象使用延迟评估。由于您已经关闭了流,当它实际上尝试读取图像以获取缩略图时,它不再存在。因此错误。