Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image.Save crashing: {"Value cannot be null.\r\nParameter name: encoder"}

Tags:

c#

exception

I am trying to save an image into a MemoryStream but it is failing under certain conditions.

Here is the code:

The following code succeeds:

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

The following code fails:

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.

Notice that the second snippet is using an image created using Image.GetThumbnailImage.

What is the difference? Does anyone have any idea why is it failing?

like image 997
agarcian Avatar asked Jan 31 '12 02:01

agarcian


1 Answers

I believe the problem has to do with this part of the GetThumbnailImage documentation:

If the Image contains an embedded thumbnail image, this method retrieves the embedded thumbnail and scales it to the requested size. If the Image does not contain an embedded thumbnail image, this method creates a thumbnail image by scaling the main image.

This probably accounts for the intermittent behaviour (AKA "certain conditions"). The explanation is in the following Microsoft Connect ticket:

The underlying API is not able to locate an encoder for the MemoryBmp image type. We will need to investigate this will the GDI+ team. In the meantime, you should be able to simply change your ImageFormat to ImageFormat.Bmp rather than ImageFormat.MemoryBmp and it should work. It will still be saved to the MemoryStream using the BMP format.

In all likelihood, if there is no embedded thumbnail, the new thumbnail generated by the GetThumbnailImage API is in fact going to have a RawFormat of MemoryBmp which has no associated encoder - thus the specific error message you're seeing.

Just don't use thumb.RawFormat; since you know it's a bitmap anyway, use ImageFormat.Bmp instead.

P.S. Please note that although I deleted my earlier answer because it turned out to not to be relevant to this particular issue, it is still important to use the GetThumbnailImage API properly as the documentation specifies; you must pass a valid delegate for the callback parameter instead of null, otherwise it can fail, and you still need to be wrapping disposables in using clauses.

like image 145
Aaronaught Avatar answered Sep 28 '22 08:09

Aaronaught