从文件或者字节数组中读取和复制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));
这避免了与希望其源流保持打开的位图相关的问题,以及导致源文件保持锁定的一些建议的解决方法。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具