How can I write an extension method that converts a System.Drawing.Bitmap to a byte array?

依然范特西╮ 提交于 2019-11-28 14:14:16

As someone else state, this is a known GDI+ bug.

However, it usually appear when you've closed the source stream of the image before reading it completely. Just loading a new Image object will only load metadata, like width, height, color depth, etc, not the actual pixels. They will be lazily loaded at a later time.

This can be avoided by copying your image (during loading) into a new Image created in memory. I presume that the input stream is still available at that time. Once you have the new memory-based Image class you can dispose of the source stream freely. (Another solution would be not to close/dispose the source stream).

Edit: Problem described in KB814675 Bitmap and Image constructor dependencies together with a workaround.

Create a Non-Indexed Image

This approach requires that the new image be in a non-indexed pixel format (more than 8 bits-per-pixel), even if the original image was in an indexed format. This workaround uses the Graphics.DrawImage() method to copy the image to a new Bitmap object:

  1. Construct the original Bitmap from the stream, from the memory, or from the file.
  2. Create a new Bitmap of the same size, with a pixel format of more than 8 bits-per-pixel (BPP).
  3. Use the Graphics.FromImage() method to obtain a Graphics object for the second Bitmap.
  4. Use Graphics.DrawImage() to draw the first Bitmap onto the second Bitmap.
  5. Use Graphics.Dispose() to dispose of the Graphics.
  6. Use Bitmap.Dispose() to dispose of the first Bitmap.

Create an Indexed Image

This workaround creates a Bitmap object in an indexed format:

  1. Construct the original Bitmap from the stream, from the memory, or from the file.
  2. Create a new Bitmap with the same size and pixel format as the first Bitmap.
  3. Use the Bitmap.LockBits() method to lock the whole image for both Bitmap objects in their native pixel format.
  4. Use either the Marshal.Copy function or another memory copying function to copy the image bits from the first Bitmap to the second Bitmap.
  5. Use the Bitmap.UnlockBits() method to unlock both Bitmap objects.
  6. Use Bitmap.Dispose() to dispose of the first Bitmap.

Known GDI+ bug.

You can't close the MemoryStream straight away.

Copy the output array to another byte array, then close the stream.

Try changing image.RawFormat to something like JPEG or PNG. It's possible for some images to be openable by a Bitmap but not saveable (at least in the original format).

According to this thread, I using following code and it work correctly:

using (var ms = new MemoryStream(bytes))
{
    using (var bitmap = new Bitmap(ms))
    {
        var bitmapCopy = new Bitmap(bitmap, bitmap.Width, bitmap.Height);
        return bitmapCopy;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!