Image.Save崩溃:{“值不能为空。\ r \ nParameter name:encoder”}

时间:2012-01-31 02:21:41

标签: c# exception

我正在尝试将图片保存到MemoryStream,但在某些情况下会失败。

以下是代码:

以下代码成功:

Image img = Bitmap.FromStream(fileStream);
MemoryStream ms = new MemoryStream();
img.Save(ms, img.RawFormat);  // This succeeds.

以下代码失败:

Image img = Bitmap.FromStream(fileStream);
Image thumb = img.GetThumbnailImage(thumbWidth, thumbHeight, null, System.IntPtr.Zero);

MemoryStream ms = new MemoryStream();
thumb.Save(ms, thumb.RawFormat);  // This fails.

请注意,第二个代码段使用的是使用Image.GetThumbnailImage创建的图片。

有什么区别?有谁知道为什么会失败?

1 个答案:

答案 0 :(得分:23)

我认为问题与GetThumbnailImage documentation的这一部分有关:

  

如果Image包含嵌入的缩略图图像,则此方法会检索嵌入的缩略图并将其缩放到请求的大小。如果Image不包含嵌入的缩略图图像,则此方法通过缩放主图像来创建缩略图图像。

这可能是间歇性行为(AKA“某些条件”)的原因。解释如下Microsoft Connect ticket

  

底层API无法找到MemoryBmp图像类型的编码器。我们需要对GDI +团队进行调查。在此期间,您应该能够简单地将ImageFormat更改为ImageFormat.Bmp而不是ImageFormat.MemoryBmp,它应该可以工作。它仍将使用BMP格式保存到MemoryStream。

很可能,如果没有嵌入式缩略图,GetThumbnailImage API生成的新缩略图实际上会有RawFormat MemoryBmp没有关联的编码器 - 因此你看到的具体错误信息。

不要使用thumb.RawFormat;既然你知道它是一个位图,请改用ImageFormat.Bmp

P.S。请注意,虽然我删除了之前的答案,因为事实证明与此特定问题无关,但正如文档中指定的那样,正确使用GetThumbnailImage API仍然很重要;您必须传递callback参数的有效代理而不是null,否则可能会失败,您仍然需要在using子句中包装一次性用品。