I have a problem in a Windows Forms application with Bitmap.Save failing when I save to a MemoryStream. The problem only seems to occur intermittently on one machine (so far) and the bad news it is at a customer site. I can’t debug on the machine, but I got a stack trace that narrowed the problem down to a single line of code.
Here’s a condensed version of my code:
byte[] ConvertPixelsToBytes() { // imagine a picture class that creates a 24 bbp image, and has // a method to get an unmanaged pixel buffer. // imagine it also has methods for getting the width, // height, pitch // I suppose this line could return a bad address, but // I would have expected that the Bitmap constructor would have // failed if it was System.IntPtr pPixels = picture.GetPixelData(); System.Drawing.Bitmap bmp = new System.Drawing.Bitmap( picture.width(), picture.height(), picture.pitch(), System.Drawing.Imaging.PixelFormat.Format24bppRgb, pPixels ); // This line doesn't actually free the memory, but it could be freed in a // background thread // (2) picture.releasePixelData(pPixels); System.IO.MemoryStream memStream = new System.IO.MemoryStream(); try { // I don't see how this line could fail, but it does // (3) bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Bmp); return memStream.ToArray(); } catch(System.Runtime.InteropServices.ExternalException e) { // e.Message is the very helpful ' A generic error occurred in GDI+.' } finally { memStream.Dispose(); } return new byte[0]; }
Any idea what might be going on? I’m pretty sure my pixel buffer is right, it always works on our dev/test machines and at other customer sites.
My thoughts on possible reasons for failure are
a. The bitmap constructor doesn’t copy the pixel data, but keeps a reference to it, and the Save fails because the memory is released. I don’t find the MSDN docs clear on this point, but I assume that the Bitmap copies the pixel data rather than assume it is locked.
b. The pixel data is invalid, and causes the Save method to fail. I doubt this since my pixel data is 24 Bits per pixel, so as far as I know it should not be invalid.
c. There’s a problem with the .NET framework.
I would appreciate any thoughts on other possible failure reasons so I can add extra checks and logging information to my app so I can send something out into the field.
The MSDN docs for that Bitmap constructor leave no doubt whatsoever: