A generic error occurred in GDI+, JPEG Image to MemoryStream

This seems to be a bit of an infamous error all over the web. So much so that I have been unable to find an answer to my problem as my scenario doesn't fit. An exception gets thrown when I save the image to the stream.

Weirdly this works perfectly with a png but gives the above error with jpg and gif which is rather confusing.

Most similar problem out there relate to saving images to files without permissions. Ironically the solution is to use a memory stream as I am doing....

public static byte[] ConvertImageToByteArray(Image imageToConvert)
{
    using (var ms = new MemoryStream())
    {
        ImageFormat format;
        switch (imageToConvert.MimeType())
        {
            case "image/png":
                format = ImageFormat.Png;
                break;
            case "image/gif":
                format = ImageFormat.Gif;
                break;
            default:
                format = ImageFormat.Jpeg;
                break;
        }

        imageToConvert.Save(ms, format);
        return ms.ToArray();
    }
}

More detail to the exception. The reason this causes so many issues is the lack of explanation :(

System.Runtime.InteropServices.ExternalException was unhandled by user code
Message="A generic error occurred in GDI+."
Source="System.Drawing"
ErrorCode=-2147467259
StackTrace:
   at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters    encoderParams)
   at System.Drawing.Image.Save(Stream stream, ImageFormat format)
   at Caldoo.Infrastructure.PhotoEditor.ConvertImageToByteArray(Image imageToConvert) in C:UsersIanSVNCaldooCaldoo.CoordinatorPhotoEditor.cs:line 139
   at Caldoo.Web.Controllers.PictureController.Croppable() in C:UsersIanSVNCaldooCaldoo.WebControllersPictureController.cs:line 132
   at lambda_method(ExecutionScope , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
 InnerException: 

OK things I have tried so far.

  • Cloning the image and working on that.
  • Retrieving the encoder for that MIME passing that with jpeg quality setting.

  • OK I seem to have found the cause just by sheer luck and its nothing wrong with that particular method, it's further back up the call stack.

    Earlier I resize the image and as part of that method I return the resized object as follows. I have inserted two calls to the above method and a direct save to a file.

    // At this point the new bitmap has no MimeType
    // Need to output to memory stream
    using (var m = new MemoryStream())
    {
           dst.Save(m, format);
    
           var img = Image.FromStream(m);
    
           //TEST
           img.Save("C:test.jpg");
           var bytes = PhotoEditor.ConvertImageToByteArray(img);
    
    
           return img;
     }
    

    It appears that the memory stream that the object was created on has to be open at the time the object is saved. I am not sure why this is. Is anyone able to enlighten me and how I can get around this.

    I only return from a stream because after using the resize code similar to this the destination file has an unknown mime type (img.RawFormat.Guid) and Id like the Mime type to be correct on all image objects as it makes it hard write generic handling code otherwise.

    EDIT

    This didn't come up in my initial search but here's the answer from Jon Skeet


    If you are getting that error , then I can say that your application doesn't have a write permission on some directory.

    For example, if you are trying to save the Image from the memory stream to the file system , you may get that error.

    Please if you are using XP, make sure to add write permission for the aspnet account on that folder.

    If you are using windows server (2003,2008) or Vista, make sure that add write permission for the Network service account.

    Hope it help some one.


    I'll add this cause of the error as well in hopes it helps some future internet traveler. :)

    GDI+ limits the maximum height of an image to 65500

    We do some basic image resizing, but in resizing we try to maintain aspect ratio. We have a QA guy who's a little too good at this job; he decided to test this with a ONE pixel wide photo that was 480 pixels tall. When the image was scaled to meet our dimensions, the height was north of 68,000 pixels and our app exploded with A generic error occurred in GDI+ .

    You can verify this yourself with test:

      int width = 480;
      var height = UInt16.MaxValue - 36; //succeeds at 65499, 65500
      try
      {
        while(true)
        {
          var image = new Bitmap(width, height);
          using(MemoryStream ms = new MemoryStream())
          {
            //error will throw from here
            image.Save(ms, ImageFormat.Jpeg);
          }
          height += 1;
        }
      }
      catch(Exception ex)
      {
        //explodes at 65501 with "A generic error occurred in GDI+."
      }
    

    It's too bad there's not a friendly .net ArgumentException thrown in the constructor of Bitmap .

    链接地址: http://www.djcxy.com/p/50288.html

    上一篇: 在.NET中使用GDI调整图像大小会降低饱和度

    下一篇: 在GDI +,JPEG Image到MemoryStream中发生了一般性错误