用System.Drawing.Image读取GPS坐标会失败,因其默认不解析GPS子IFD,推荐使用MetadataExtractor库;它能正确遍历IFD0、ExifIFD、GPSInfoIFD三层结构,通过GpsDirectory.GetGeoLocation()安全获取经纬度。

用 System.Drawing.Image 读取 GPS 坐标会失败
因为 System.Drawing.Image(尤其是 .NET Core/.NET 5+ 中的实现)默认不解析 GPS 子 IFD,即使图片里有 GPSInfo 标签,GetPropertyItem(0x8825) 也常返回 null 或抛出异常。
- 仅靠
Image.GetPropertyItem无法安全提取经纬度、海拔、方向等 GPS 字段 - 原生 GDI+ 解析逻辑不完整,且在 Linux/macOS 上行为不稳定
- 推荐改用专门处理 Exif 的库,比如
MetadataExtractor
用 MetadataExtractor 提取 GPS 经纬度
这个开源库能正确遍历 IFD0、ExifIFD、GPSInfoIFD 三层结构,是目前 C# 生态中最可靠的 Exif 解析方案。
- 安装包:
Install-Package MetadataExtractor - 关键类型:
JpegDirectory和GpsDirectory - GPS 坐标以度分秒数组形式存在(如
[39, 57, 12.3]),需手动转为十进制度数 - 注意:
GpsDirectory可能为空,必须判空再调用GetGeoLocation()
var directories = ImageMetadataReader.ReadMetadata(filePath);
var gpsDir = directories.OfType<GpsDirectory>().FirstOrDefault();
if (gpsDir?.GetGeoLocation() is { } location)
{
double lat = location.Latitude; // 已转好
double lon = location.Longitude;
}
GetGeoLocation() 返回 null 的常见原因
不是代码写错了,而是图片本身或解析路径出了问题。
- 照片被微信/微博/钉钉等 App 二次压缩过 —— 大概率丢掉整个
GPSInfo段 - 手机设置里关闭了“保存地理位置”,哪怕开了定位,Exif 里也不会写 GPS 标签
- 用
Bitmap.Save()重存过图片,会导致所有 Exif 元数据清空 - 文件扩展名是
.jpg,但实际是 WebP 或 HEIC 格式 ——MetadataExtractor不支持后者
自己解析 0x8825 GPSInfo 标签的风险
有人想绕过第三方库,直接读取原始字节数组。这条路理论上可行,但极易出错。
-
0x8825的值不是坐标,而是指向 GPS 子 IFD 的偏移量,需要二次跳转解析 - 不同厂商对 GPS 标签的排列顺序、单位(度分秒 vs 十进制)、符号位(N/S/E/W)处理不一致
- Android 和 iOS 写入的 GPS 方向标签(
0x0011)含义相反,硬解容易把正北当成正南 - 没有健壮的异常边界检查,一张损坏的 Exif 就会让整个解析流程崩溃
除非你真在做图像元数据底层工具,否则别碰裸字节解析 —— MetadataExtractor 已经覆盖了 99% 的真实设备输出差异。


















