100M">

C#图片与byte数组转换 C#如何将图片文件转为字节流

来源:这里教程网 时间:2026-02-21 17:41:40 作者:

File.ReadAllBytes
最快读取图片为
byte[]

如果只是把磁盘上已存在的图片文件(如

"logo.png"
)转成字节数组,
File.ReadAllBytes
是最直接、安全且性能最好的方式。它自动处理文件打开、读取、关闭全过程,无需手动管理流。

适用于 JPG、PNG、BMP 等所有二进制图片格式,不关心编码或像素数据 注意:该方法会将整个文件一次性加载到内存,大图(如 >100MB)可能触发
OutOfMemoryException
路径错误时抛出
FileNotFoundException
,建议加
File.Exists
判断或 try-catch

示例:

string imagePath = @"C:\assets\icon.jpg";
if (File.Exists(imagePath))
{
    byte[] imageData = File.ReadAllBytes(imagePath);
    // 后续可存入数据库、上传、加密等
}

Image.Save
+
MemoryStream
System.Drawing.Image
对象导出字节流

当你已经用

Image.FromFile
Image.FromStream
或 GDI+ 绘图后得到一个
Image
实例,又需要把它“保存为某种格式的字节”,就得走
MemoryStream
这条路。这里的关键是:必须显式指定图像格式(如
ImageFormat.Png
),否则默认行为不可靠。

不指定格式时,
image.RawFormat
可能是未知或不支持的编码,导致保存失败或乱码
使用
using
确保
MemoryStream
Image
正确释放,尤其在服务端高频调用时避免 GDI 句柄泄漏
若原图是 JPEG,但用
ImageFormat.Png
保存,会真正执行一次编码转换——不是简单复制字节

示例:

using (var image = Image.FromFile(@"C:\temp\photo.jpg"))
using (var ms = new MemoryStream())
{
    image.Save(ms, ImageFormat.Jpeg); // 必须明确指定格式
    byte[] jpegBytes = ms.ToArray();
}

Bitmap.LockBits
获取原始像素字节(仅限位图操作场景)

当你要做图像处理(如灰度化、卷积滤波、OCR 预处理),需要直接访问每个像素的 RGB 值,就不能用上面两种“文件级”转换方式。

LockBits
提供的是未经压缩的、按扫描线排列的原始像素内存指针,返回的是真正的图像数据本体,而非文件容器(BMP 头、JPG Huffman 表等)。

只适用于
Bitmap
类型;
Image
抽象类不支持
LockBits
返回的
byte[]
不含任何文件头,长度 = 宽 × 高 × 每像素字节数(如 24 位 RGB 就是 ×3)
必须配对调用
UnlockBits
,否则资源泄露;且不能跨线程访问同一块锁定内存
常见误用:把
LockBits
得到的字节数组直接当 JPEG 文件写入磁盘——结果打不开

注意
byte[]
→ 图片反向转换时的格式陷阱

把字节数组还原成可用图片时,最常踩的坑是忽略来源格式。比如你用

File.ReadAllBytes("a.jpg")
得到的
byte[]
,必须用
Image.FromStream(new MemoryStream(data))
加载,而不能直接传给
Bitmap
构造函数(后者只接受原始像素布局,不识别 JPEG 头)。

Image.FromStream
能自动识别 PNG/JPEG/GIF/BMP 等格式头,是最通用的选择
如果字节数组来自网络响应(如
HttpClient.GetByteArrayAsync
),确保响应内容类型正确,且未被 gzip 压缩(否则需先解压)
从数据库读出的
byte[]
若无法显示,优先检查是否在存入前被意外 Base64 编码过,或传输中截断

真正容易被忽略的是:不同 .NET 版本对图像编解码器的支持有差异。.NET 6+ 默认禁用某些旧格式(如 TIFF),需手动注册 —— 如果你发现某张 TIFF 图片在新项目里加载失败,不是代码问题,而是缺了

System.Drawing.Common
的额外配置。

相关推荐