33

Exception:

A generic error occurred in GDI+. at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) at System.Drawing.Image.Save(String filename, ImageFormat format) at System.Drawing.Image.Save(String filename)

Code:

byte[] bitmapData = new byte[imageText.Length];
MemoryStream streamBitmap;
bitmapData = Convert.FromBase64String(imageText);
streamBitmap = new MemoryStream(bitmapData);
System.Drawing.Image img = Image.FromStream(streamBitmap);
img.Save(path);

We convert a base64 string into a MemoryStream and then create a System.Drawing.Image (Image.FromStream(streamBitmap)). At the end the image is saved in a temp file.

The strange thing is that the problem seems to occur when the activity (number of concurrent users) is high on the web server and the problem is solved temporarily after an IISRESET or an application pool recycle...

==> Garbage collector issue ?

I already checked the permission of the TEMP folder...

Razor
  • 1,385
  • 4
  • 18
  • 28

7 Answers7

32

When you are loading an imagefrom a Stream, You have to keep the stream open for the lifetime of the image, see this MSDN Image.FromStream.

I think the exception is caused because the memory stream gets closed even before the image gets disposed. You can change your code like this:

byte[] bitmapData = new byte[imageText.Length];
bitmapData = Convert.FromBase64String(imageText);

  using (var streamBitmap = new MemoryStream(bitmapData))
  {
      using (img = Image.FromStream(streamBitmap))
      { 
         img.Save(path);
      }
  }

Here are some links to threads discussing similar problems:

gdi+ error saving image from webpage

When drawing an image: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI

Suresh Kumar Veluswamy
  • 4,193
  • 2
  • 20
  • 35
  • Good point, thank you ! I will implement this change and do some further test. – Razor Mar 28 '14 at 15:09
  • 3
    Adding this comment because someone deleted my supplemental answer which related to this accepted answer. If you're seeing that the GDI error is thrown after a while, here is how to confirm that it's leaking GDI memory which is causing the exception. After the program has leaked 10,000 handles Windows won't give it anymore. You can diagnose these kind of leaks with TaskMgr.exe Click on Processes tab Right click on the columns and Select Columns to add the columns for GDI Objects. If GDI Objects is the one that's steadily increasing - then you have a GDI memory leak. – rboy Oct 19 '18 at 18:07
18

Make sure that the path you specified is valid. Using the previous answer (with the usings on the memory stream) you may still get this exact error "Generic Error in GDI+" if the file path does not exist. The file will be created, the directory path must exist.

mminneman
  • 426
  • 3
  • 7
3

I encountered the same exception message when saving an image. It turned out my code was fine and doing what it was supposed to do.

The problem was that the hard drive was full, thus the new image couldn't be created. I only noticed this when trying to save the project I was working on, as it didn't have space to save.

Molay
  • 43
  • 4
2

In my case, Below snippet works fine where ConvertedImageString is Base64Image string received from API and I convert that into a related image with a format and will save it to a physical file folder on Server.

Edit: The above error occurs might be because of wrong file path on which you are trying to Save image

string converted = ConvertedImageString.Replace('-', '+');
converted = converted.Replace('_', '/');
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(ConvertedImageString)))
{
    using (Bitmap bm1 = new Bitmap(ms))
    {
        newFileName =  id + ".jpg";
        newFileName = CleanFileName(newFileName);
        newFileName = newFileName.Replace(" ", "_");

        Path = Path + newFileName;

        bm1.Save(Path, ImageFormat.Jpeg);
    }
}
Prashant Pimpale
  • 10,349
  • 9
  • 44
  • 84
1

When you call "Image.FromFile" or "Image.Save" the image object will hold a lock on the file until it is explicitly disposed. If you perform another "Image.Save" or "Image.FromFile" on the same filename, you may get the "generic error" exception. It depends on whether the garbage collector has disposed the image, so the results are inconsistent.

If you don't need the image after a "Save" action, you should immediately dispose it. If you do need the image, Image.Clone will make a copy which does not hold a lock on the source file.

I have experienced this problem in an Image Library Editing application, and this was a solution.

Mike Pettigrew
  • 156
  • 1
  • 8
1

I was getting this error because the folder I was trying to save the image to, did not exist. And image.Save(string path), does not create the folder automatically. So this is something you have to create the folder programatically

if (Directory.Exists(folderToUpload) == false)
{
    Directory.CreateDirectory(folderToUpload);
}

Then you should be able to save the image to desired location.

Amit Sharma
  • 133
  • 8
0

This error is due to the image is already in use. Wherever you use the image convert the image into string base 64 format and use it. This will resolve the error.

Swati
  • 234
  • 2
  • 10