XMP 是 Adobe 定义的一种数字图像元数据标准。如 Adobe Lightroom 处理过的图片中会嵌入 XMP 元数据,可以用 Photoshop 进行查看。
一些摄影应用如 Google 的全景漫游照相机 Photosphere 也会将一些拍摄时的数据使用 XMP 格式嵌入到图片中。我在编写一段脚本的时候想取出这些元数据进行解析,在网上一顿乱搜都没有发现 PIL 有支持读取 XMP 的迹象,倒是可以使用 _getexif() 方法获取图片的 EXIF 元数据。
而其他可以获取元数据的库如 python-xmp-toolkit 等,编译起来还要带上一大坨依赖项。看了网上还有人出馊主意直接以文本方式打开整个文件,然后查找关键字来确定偏移的。一度想过要研究一下 JFIF 标记格式手动解析,比如参考这个 C 语言实现的 jHead:
http://www.sentex.net/~mwandel/jhead/
虽然我最后没有疯狂到用 py 重写 jHead,不过 jHead 的代码倒是给了点启发。去看看 PIL 对 exif 解析的实现,可能还有料。最后在 Github 仓库里扫了一圈 PIL 的代码,终于发现了 JpegImageFile 对象的 applist 属性:
https://github.com/python-pillow/Pillow/blob/8faf299ca04b147580a43df6db3a495f45f97607/PIL/JpegImagePlugin.py#L71
Exif 和 XMP 元数据都保存在 APP1 里。只要用 PIL 打开图像,获得 JpegImageFile 对象之后,遍历其 applist 属性即可读取到元数据 。
下面是完成之后的脚本,处理了一下 PhotoSphere 的标记: