Image.Width/Height可直接获取像素尺寸,但需先成功加载图片并用try/catch捕获OutOfMemoryException;超大图需用Bitmap或元数据解析;WebP/HEIC需注册解码器;轻量方案可读文件头,但损坏文件仍需兜底加载。

用 Image.Width 和 Image.Height 读取像素尺寸最直接
只要图片已成功加载为 Image 对象(比如通过 Image.FromFile),它的 Width 和 Height 属性就是原始像素宽高,无需解码额外信息。
常见错误是拿到路径就直接访问属性,却没检查加载是否失败——Image.FromFile 在文件被占用、格式不支持或权限不足时会抛 OutOfMemoryException(没错,这个异常名有误导性),不是 FileNotFoundException。
- 务必用
try/catch包住Image.FromFile,别假设文件一定可读 - 如果只是想查尺寸而不长期持有图像资源,记得调用
image.Dispose(),否则可能引发 GDI 句柄泄漏 -
Width/Height返回的是int,对超大图(如 >32767 像素)可能截断——这时得换Bitmap并读取Size或用Image.GetPropertyItem解析原生元数据
处理 WebP、HEIC 等非内置格式要先注册解码器
.NET 5+ 默认不支持 WebP 或 HEIC,直接 Image.FromFile 会抛 NotSupportedException。这不是尺寸读不出来,是根本加载失败。
解决方式不是换库,而是补上对应解码器:
- WebP:安装
System.Drawing.Common+Microsoft.Win32.SystemEvents(Windows)或启用libgdiplus(Linux/macOS),再调用ImageCodecInfo.GetImageDecoders()确认mime是否含image/webp - HEIC:Windows 10/11 需单独安装“HEIF Image Extensions”系统组件;.NET 自身不提供 HEIC 解码逻辑
- 绕过加载的轻量方案:用
System.IO.File.ReadAllBytes读头几十字节,按格式规范解析宽高(例如 PNG 的 IHDR 块、JPEG 的 SOF0 标记)——但需自行处理字节序和标记偏移,容易出错
Bitmap 构造后立即读 Width/Height 更可靠
某些场景下,Image.FromFile 返回的对象类型其实是 Bitmap,但类型擦除后访问 Width 仍有效;而显式转成 Bitmap 能确保你拿到的是可预测行为的实例。
注意两点:
-
new Bitmap(path)和Image.FromFile(path)底层行为一致,但前者在构造失败时抛ArgumentException,后者是OutOfMemoryException,异常类型不同,捕获逻辑得分开写 - 如果图片带旋转 EXIF(比如手机竖拍照片),
Bitmap.Width/Height返回的是**原始传感器尺寸**,不是人眼看到的“正确朝向”的宽高——要按PropertyItem中 ID=274 的值做逻辑翻转,否则 UI 显示会拉伸 - 从流创建
Bitmap时,流必须保持打开状态直到Bitmap被释放,否则后续读Width可能崩溃
用 ImageDescriptor 或原生 API 避免内存分配(高级场景)
如果你只关心尺寸、且图片体积很大(比如百兆 TIFF),每次 Image.FromFile 都会把整张图解码进内存,浪费且慢。
更高效的做法是跳过解码,只解析文件头:
- Windows 上可用
WIC(Windows Imaging Component)的IWICBitmapDecoder接口,调用GetSize方法——它不分配像素内存,只读元数据 - C# 封装较麻烦,推荐用
Microsoft.WindowsAPICodePack-Core(注意 NuGet 包已归档,仅限 Windows) - 跨平台方案:用
ImageSharp的Image.IdentifyAsync,返回IImageInfo,含Width/Height,且默认不加载像素数据
这种做法省内存也快,但多一个依赖或平台限制——多数业务场景用不到,除非你写的是批量图片分析工具。
真正容易被忽略的是:所有基于文件头的方案,都依赖格式规范严格。遇到被裁剪损坏的 JPEG(缺失 SOF0)、或手工拼接的 PNG(IHDR 不在开头),依然会失败。这时候,老老实实走 Image.FromFile + 异常兜底,反而是最稳的选择。










