This is Founder's blog

ASP.NET Image Resizing - out of memory problem

Sep 30 2009 :: by Alex
Another post for ASP.NET developers reading this blog. If you think these posts do not belong here, please leave a comment, and I'll consider moving my development articles to a separate blog.
Any ASP.NET developer who tries to create "on-the-fly" image-thumbnails in his web-application, sooner or later faces this crappy annoying "out of memory" exception, that is thrown when you use Image.FromStream or Image.GetThumbnailImage. Sometimes it is thrown when working with big (>5Mb) images, sometimes it's thrown for all images.

Today we faced it in all three of our web-based projects - the ASP.NET forum application, the web-based help desk and the web-based CRM. I spent hours googling for a solution and found nothing. Actually I did found a million suggestions (and even an article claiming that this is a bug in GDI+) - one suggested using Graphics.DrawImage instead of Image.GetThumbnailImage, another suggested creating a temp file first and then load Image from it...

None worked.

Also I found it strange that the error was thrown only under an IIS server, the Visual Studio's built-in development server worked fine...

Anyway. GDI+ (that WinAPI thing that the .NET imaging classes rely on) appears to have some difficulties when working with images in memory, without an actual file. I found a solution, even though it seems more like black magic to me:

Rule 1: When using the Image.FromStream method keep the stream open for the lifetime of your Image.

Close the stream only after Disposing the image object. Yes, this might require some refactoring, but you really have no choice.

Image img = Image.FromStream(mystream, true, false);
//... some code
Image thumb = img.GetThumbnailImage(w, h, null, IntPtr.Zero);
//... some code

This will help you fight the exception when calling GetThumbnailImage. In case you really need to close that stream while continuing working with the image, consider using Image.Clone(), but I'm not sure this will help...

Rule 2: Important - set validateImageData to false when calling the FromStream method.

Even after fixing your code with "rule 1" you might still get the exception while calling FromStream on large images. This one I actually found on the Microsoft's website - Anyway, here's the code:

//note the third parameter set to "false"!!!
Image img = Image.FromStream(mystream, true, false);