从文件或者字节数组中读取和复制Bitmap图像的安全方法
大部分时候,我们使用下面代码来读取和复制bitmap文件
Bitmap bmp = new Bitmap(fullpath);
Bitmap bmpLoad = (Bitmap)bmp.Clone();
Bmp.dispose(); //释放,避免锁定文件
但是,clone会克隆文件流路径,这可能会带来问题。
**********************************************************
如果使用new Bitmap(bmp ),构造函数会使用屏幕dpi和32位PixelFormat来创建Bitmap,分辨率变成默认的96,图像深度会变成32。我们也不能使用memorystream来复制bitmap,因为图像需要在内存中保持数据流不被释放,这会带来内存管理的麻烦。
可以这样写
static Bitmap LoadImage(Stream stream)
{
Bitmap retval = null;
using (Bitmap b = new Bitmap(stream))
{
retval = new Bitmap(b.Width, b.Height, b.PixelFormat); //丢失分辨率,需要额外传参。
using (Graphics g = Graphics.FromImage(retval))
{
g.DrawImage(b, Point.Empty);
g.Flush();
}
}
return retval;
}
**********************************************************
比较安全的方法是使用LockBits+Marshal.Copy从内存中进行复制,这样可以确保深度不变。然后使用SetResolution设置分辨率。代码很长。
参见https://stackoverflow.com/questions/4803935/free-file-locked-by-new-bitmapfilepath/7972963#7972963
也可以试试下面的方法,使用ImageConverter类
**********************************************************
Using System.Drawing;
private static readonly ImageConverter _imageConverter = new ImageConverter();
图像到字节数组:
/// <summary>
/// Method to "convert" an Image object into a byte array, formatted in PNG file format, which
/// provides lossless compression. This can be used together with the GetImageFromByteArray()
/// method to provide a kind of serialization / deserialization.
/// </summary>
/// <param name="theImage">Image object, must be convertable to PNG format</param>
/// <returns>byte array image of a PNG file containing the image</returns>
public static byte[] CopyImageToByteArray(Image theImage)
{
using (MemoryStream memoryStream = new MemoryStream())
{
theImage.Save(memoryStream, ImageFormat.Png); //更换成自己的格式,如果用RawFormat可能会出问题。
return memoryStream.ToArray();
}
}
字节数组到图像:
/// <summary>
/// Method that uses the ImageConverter object in .Net Framework to convert a byte array,
/// presumably containing a JPEG or PNG file image, into a Bitmap object, which can also be
/// used as an Image object.
/// </summary>
/// <param name="byteArray">byte array containing JPEG or PNG file image or similar</param>
/// <returns>Bitmap object if it works, else exception is thrown</returns>
public static Bitmap GetImageFromByteArray(byte[] byteArray)
{
Bitmap bm = (Bitmap)_imageConverter.ConvertFrom(byteArray);
if (bm != null && (bm.HorizontalResolution != (int)bm.HorizontalResolution ||
bm.VerticalResolution != (int)bm.VerticalResolution))
{
// Correct a strange glitch that has been observed in the test program when converting
// from a PNG file image created by CopyImageToByteArray() - the dpi value "drifts"
// slightly away from the nominal integer value
bm.SetResolution((int)(bm.HorizontalResolution + 0.5f), (int)(bm.VerticalResolution + 0.5f));
}
return bm;
}
使用示例:
Bitmap newBitmap = GetImageFromByteArray(File.ReadAllBytes(fileName));
这避免了与希望其源流保持打开的位图相关的问题,以及导致源文件保持锁定的一些建议的解决方法。