Search code examples
c#asp.netimage-uploading

Saving Image to MemoryStream- Generic GDI+ Error


Overview of my application: On the client side, a series of snapshots are taken with a webcam. On submit, I want the images to be converted to a byte array, and have that byte array sent to a service I have written.

My problem: I'm trying to save a single image to a MemoryStream, but it continues to break, spitting out the message, "A generic error occured in GDI+." When I dig deeper, I see that the exception is thrown when the MemoryStream's buffer position is at 54. Unfortunately, it's a 1.2 mb photo. Here's the block of code:

// Create array of MemoryStreams
var imageStreams = new MemoryStream[SelectedImages.Count];
for (int i = 0; i < this.SelectedImages.Count; i++)
{   
    System.Drawing.Image image = BitmapFromSource(this.SelectedImages[i]);
    imageStreams[i] = new MemoryStream();
    image.Save(imageStreams[i], ImageFormat.Bmp); /* Error is thrown here! */
}

// Combine MemoryStreams into a single byte array (Threw this 
// in in case somebody has a better approach)
byte[] bytes = new byte[imageStreams.Sum(s => s.Length)];
for(int i = 0; i < imageStreams.Length; i++)
{
    bytes.Concat(imageStreams[i].ToArray());
}

And here is my BitmapFromSource method

// Converts a BitmapSource object to a Bitmap object
private System.Drawing.Image BitmapFromSource(BitmapSource source)
{
    System.Drawing.Image bitmap;

    using (MemoryStream ms = new MemoryStream())
    {
        BitmapEncoder encoder = new BmpBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(source));
        encoder.Save(ms);
        bitmap = new System.Drawing.Bitmap(ms);
    }
    return bitmap;
}

A lot of what I have read about the Generic GDI+ Error points to a permissions issue, but I don't see how that would apply here, considering I'm not saving to the file system. Also, I've seen that this error can arise due to the MemoryStream closing before the image is being saved, but I also don't see how this would apply considering I create the MemoryStream immediately before I save the image. Any insight would be greatly appreciated.


Solution

  • I think your problem actually lies in your BitmapFromSource method.

    You're creating a stream, then creating a bitmap from that stream, then throwing the stream away, then trying to save the bitmap to another stream. However, the documentation for the Bitmap class says:

    You must keep the stream open for the lifetime of the Bitmap.

    By the time you come to save that bitmap, the bitmap is already corrupted because you've thrown the original stream away.

    See: http://msdn.microsoft.com/en-us/library/z7ha67kw

    To fix this (bearing in mind I've not written the code let alone tested it), create the MemoryStream inside the first for loop in your first block of code, and pass that memory stream to your BitmapFromSource method as a second parameter.