我怎么能写一个System.Drawing.Bitmap转换为字节数组的扩展方法? [英] How can I write an extension method that converts a System.Drawing.Bitmap to a byte array?
问题描述
我怎么能写一个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()方法将图像复制到一个新位图对象:
- 从流构建原始位图,从存储器,或从该文件。
- 创建同样大小的新位图,有超过8位 - 每像素(BPP)的像素格式
- 使用Graphics.FromImage()方法来获取一个图形对象的第二位图。
- 使用Graphics.DrawImage()绘制第一个位图到第二位图。
- 使用Graphics.Dispose()来处理图形的。
- 使用Bitmap.Dispose()处理的第一个位图。
创建索引图像
这个解决办法在索引格式创建一个位图对象:
- 从流构建原始位图,从存储器,或从该文件。
- 创建一个新的位图具有相同的大小和像素格式为第一位图。
- 使用Bitmap.LockBits()方法来锁定整个图像在其原生像素格式两个位图对象。
- 使用任Marshal.Copy函数或另一个内存复制功能从第一位图复制图像位到第二位图。
- 使用Bitmap.UnlockBits()方法来解开这两个位图对象。
- 使用Bitmap.Dispose()处理的第一个位图。
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:
- Construct the original Bitmap from the stream, from the memory, or from the file.
- Create a new Bitmap of the same size, with a pixel format of more than 8 bits-per-pixel (BPP).
- Use the Graphics.FromImage() method to obtain a Graphics object for the second Bitmap.
- Use Graphics.DrawImage() to draw the first Bitmap onto the second Bitmap.
- Use Graphics.Dispose() to dispose of the Graphics.
- Use Bitmap.Dispose() to dispose of the first Bitmap.
Create an Indexed Image
This workaround creates a Bitmap object in an indexed format:
- Construct the original Bitmap from the stream, from the memory, or from the file.
- Create a new Bitmap with the same size and pixel format as the first Bitmap.
- Use the Bitmap.LockBits() method to lock the whole image for both Bitmap objects in their native pixel format.
- Use either the Marshal.Copy function or another memory copying function to copy the image bits from the first Bitmap to the second Bitmap.
- Use the Bitmap.UnlockBits() method to unlock both Bitmap objects.
- Use Bitmap.Dispose() to dispose of the first Bitmap.
这篇关于我怎么能写一个System.Drawing.Bitmap转换为字节数组的扩展方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!