我怎么能写一个System.Drawing.Bitmap转换为字节数组的扩展方法? [英] How can I write an extension method that converts a System.Drawing.Bitmap to a byte array?

查看:486
本文介绍了我怎么能写一个System.Drawing.Bitmap转换为字节数组的扩展方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怎么能写一个System.Drawing.Bitmap转换为字节数组的扩展方法?为什么不:

 <扩展()> _
公共职能的toByteArray(BYVAL形象System.Drawing.Bitmap)为字节()
    使用MS =新的MemoryStream()
        image.Save(MS,image.RawFormat)
        返回ms.ToArray()
    结束使用
端功能
 

然而,当我用,我得到:从保存()操作抛出System.Runtime.InteropServices.ExternalException GDI +中发生一般性错误。我究竟做错了什么?

解决方案

随着别人的状态,这是一个已知的GDI +漏洞。

然而,当你完全看之前已经关闭了图像的来源的流通常出现。只要加载一个新的图像对象将只加载元数据,如宽度,高度,色彩深度等,而不是实际的像素。他们将在以后的时间被延迟加载。

这可以避免复制图像(加载过程中)到在内存中创建一个新的形象。我presume输入流仍然可以在那个时候。一旦你有了新的基于内存的图像类,你可以配置源流的自由。 (另一种解决方案是不关闭/处置源流)。

编辑: 在 KB814675位图和图像的构造函数依赖上述问题一起,提供一种解决方法。

  

创建非索引图像

     

这个方法要求新的图像处于非索引像素格式(超过8位每像素),即使原始图像是在索引的格式。此变通方法使用Graphics.DrawImage()方法将图像复制到一个新位图对象:

     
      
  1. 从流构建原始位图,从存储器,或从该文件。
  2.   
  3. 创建同样大小的新位图,有超过8位 - 每像素(BPP)的像素格式
  4.   
  5. 使用Graphics.FromImage()方法来获取一个图形对象的第二位图。
  6.   
  7. 使用Graphics.DrawImage()绘制第一个位图到第二位图。
  8.   
  9. 使用Graphics.Dispose()来处理图形的。
  10.   
  11. 使用Bitmap.Dispose()处理的第一个位图。
  12.   
     

创建索引图像

     

这个解决办法在索引格式创建一个位图对象:

     
      
  1. 从流构建原始位图,从存储器,或从该文件。
  2.   
  3. 创建一个新的位图具有相同的大小和像素格式为第一位图。
  4.   
  5. 使用Bitmap.LockBits()方法来锁定整个图像在其原生像素格式两个位图对象。
  6.   
  7. 使用任Marshal.Copy函数或另一个内存复制功能从第一位图复制图像位到第二位图。
  8.   
  9. 使用Bitmap.UnlockBits()方法来解开这两个位图对象。
  10.   
  11. 使用Bitmap.Dispose()处理的第一个位图。
  12.   

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

<Extension()> _
Public Function ToByteArray(ByVal image As System.Drawing.Bitmap) As Byte()
    Using ms = New MemoryStream()
        image.Save(ms, image.RawFormat)
        Return ms.ToArray()
    End Using
End Function

Yet when I use that, I get "System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+" thrown from the Save() operation. What am I doing wrong?

解决方案

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.

这篇关于我怎么能写一个System.Drawing.Bitmap转换为字节数组的扩展方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆