首页
/
工具
/
Exif 详解
Exif 详解
摘要
一份详细的技术指南,解释 Exif 元数据结构、它如何存储在 JPEG 及其他图像格式中,以及针对处理图像像素数据的开发者的实用注意事项。
暂无内容
查看缓存全文
缓存时间:
2026/06/13 17:16
# 欣赏 Exif | Brent Fitzgerald
来源:https://brentfitzgerald.com/posts/appreciating-exif/
我最近在写一些代码,给一个图像输入应用遮罩。遮罩本身没有 Exif 元数据,但图像有,所以我不得不从 Exif 中读取方向信息来调整。
用库实现并不难,而且我大致知道问题的要点:图像可以包含 Exif,Exif 是可选的,手机和相机用它来记录方向,直接处理像素时需要考虑到这一点。但我对 Exif 在文件中究竟是如何表示的,并没有清晰的心智模型。
我很好奇。我有*问题*:
方向值具体存在哪里?什么时候应该旋转像素而不是保留标签?元数据中还可能隐藏着什么?通常什么时候会被剥离?
所以这是一份关于 Exif 的随机漫游指南。
## 什么是 Exif?
Exif 是 *Exchangeable Image File Format*(可交换图像文件格式)的缩写。现行标准来自 CIPA (https://www.cipa.jp/e/std/std-sec.html),其标题为“数码相机的可交换图像文件格式:Exif 版本 3.1”。¹ (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fn-cipa-pdf) 美国国会图书馆也有一份很好的以保存为导向的摘要 (https://www.loc.gov/preservation/digital/formats/fdd/fdd000618.shtml)。你在相机文档、文件格式块名称和旧论坛帖子中常会看到全大写的 `EXIF`,但标准本身似乎更常用 `Exif` 这种拼写。
它是一种元数据格式,起源于 1995 年的数码相机世界。当时的问题大致是:相机生成了 JPEG,但拍摄时间、快门速度、光圈、焦距、缩略图以及相机是否侧放等信息该放在哪里?
答案就是 Exif。
大多数人通过手机和相机拍摄的图像接触到这些数据。它与 TIFF 的关系也很密切,因为 Exif 的实际负载是一种 TIFF 形状的数据结构,存在于其他文件内部。较新的格式也可以携带 Exif,但每种格式都给它安排了不同的“住处”。² (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fn-containers)
Exif 是可选的。一张图像可以完全没有 Exif。相机拍摄的图像通常会有一些,但经过处理的图像可能已被剥离。合成图像可以包含伪造的 Exif,因为元数据只是有人写入文件的一些数据。
## Exif 存在于何处
对于 JPEG,Exif 通常位于文件开头附近的一个 `APP1` 标记段中。
JPEG 文件以两个字节开头:
```
FF D8
```
这是图像开始标记。之后,JPEG 由一系列标记段组成。每个段以 `FF` 和一个标记字节开头。APP1 是:
```
FF E1
```
如果该 APP1 段包含 Exif,其负载以如下字节开头:
```
45 78 69 66 00 00
```
或者,作为文本:
```
Exif\0\0
```
接下来是基于 TIFF 的部分。它以字节顺序标记开头:
```
II // Intel,小端序
MM // Motorola,大端序
```
然后是 TIFF 的幻数 `42`,接着是到第一个图像文件目录(通常称为 IFD0)的偏移量。IFD 是一系列条目的列表。每个条目有一个标签 ID、一个类型、一个计数,以及一个值或指向值的偏移量。
Exif 方向信息是标签 `0x0112`。它通常位于 IFD0 中。其值是从 1 到 8 的小整数。
这就是整个要点的宏观层面。一个在 JPEG 中查找 Exif 的工具:
- 遍历 JPEG 标记段,找到 APP1,
- 检查 `Exif\\0\\0`,
- 读取 TIFF 头,
- 跟随 IFD 条目,以及
- 查找它关心的标签。
所以“Exif 在哪里?”取决于文件。在 JPEG 中,它通常位于 APP1。在 WebP 中,它是一个 `EXIF` 块。在 HEIC 中,它位于 HEIF 盒子结构内部。如果你想要一份关于 JPEG 布局的可爱旧式介绍,MIT 媒体实验室的 Deep View 项目有一份相关资料 (https://www.media.mit.edu/pia/Research/deepview/exif.html)。
## 一个朴素但经久不衰的标准
我对那些简单且持续有效的标准情有独钟。
Exif 并不像你今天从头设计的那样干净。它包含 TIFF 内部结构。它包含制造商的 MakerNotes。它在 Exif、XMP、IPTC、ICC 配置文件、C2PA 和容器元数据之间存在重复的概念。方向标签看起来很简单,直到你试图解释值 5 和 7。
尽管如此,它一直在解决一个真实的问题:仅仅有像素是不够的。相机需要某个地方来存储图像拍摄时的环境信息,而将这些数据打包在图像中,而不是作为附带文件四处传递,对每个人来说都更简单。
我欣赏它,因为它从其最初的容器中成长起来。在 JPEG 中,Exif 通常位于 APP1。在较新的文件格式(如 HEIC)中,它位于别处。但相同的负载格式仍然适用。2026 年的手机可以用现代容器拍照,但仍然携带着源自数码相机时代的元数据。
## Exif 的用途
常见的用途与你对相机的期望相符:
- 日期和时间
- 相机品牌和型号
- 镜头型号
- 快门速度
- 光圈
- ISO
- 焦距
- 闪光灯
- GPS 位置
- 方向
- 软件
- 色彩空间提示
- 制造商特定的 MakerNotes
缩略图是一种“可能”:Exif 可以携带嵌入式缩略图,通常位于 IFD1 中。³ (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fn-ifd1) 通常是一个小的嵌入式缩略图。较大的预览图则更混乱。有些是 Exif 缩略图,有些是 MakerNotes,有些是 MPF 数据,还有一些位于容器特定的元数据中。
这并非全部,而是通常有用的部分。照片应用程序使用这些数据进行排序、搜索、显示、分组和编辑图像。网站和上传管道使用它(有时是偶然地)来正确旋转图像。摄影师用它来检查拍摄方式。资产管理系统中将其与其他元数据标准(如权利、标题、信用和工作流程状态)一起使用。
颜色是边界模糊的一个好例子。Exif 有一个 `ColorSpace` 标签,但完整的 ICC 颜色配置文件 (https://www.color.org/specification/ICC.1-2022-05.pdf) 是另一种元数据。⁴ (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fn-icc) 如果图像在管道处理后改变了大小、旋转、丢失了颜色或显示方式不同,元数据是我首先会检查的地方之一,但我不会假定问题一定出在 Exif 上。
当然,元数据只是文件中被放入的内容。一个文件可以说它来自一台并非实际来源的相机。时间戳可能是错误的,GPS 可能是伪造的,字符串字段可能包含胡言乱语。
如果你在处理图像元数据方面有任何技术性工作,可以从 `exiftool` (https://exiftool.org/) 开始。
它是 Perl 语言编写的,而且以一种非常好的方式显得古老。它内置了各种关于真实文件中存在的元数据怪癖的知识。
基本命令是:
```
exiftool image.jpg
```
下面是一张真实的 iPhone JPEG 的顶部输出:
```
ExifTool Version Number : 13.55
File Name : image.jpg
Directory : /tmp
File Size : 3.6 MB
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Exif Byte Order : Big-endian (Motorola, MM)
Make : Apple
Camera Model Name : iPhone 13
Orientation : Rotate 90 CW
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Software : 26.3.1
Modify Date : 2026:04:21 20:05:42
Host Computer : iPhone 13
Exposure Time : 1/317
F Number : 1.6
Exposure Program : Program AE
ISO : 50
Exif Version : 0232
Date/Time Original : 2026:04:21 20:05:42
Create Date : 2026:04:21 20:05:42
```
这还只是开始。完整的输出会继续:MakerNotes、GPS、嵌入式缩略图、MPF 数据以及 ICC 配置文件。
为了调试,使用分组和原始标签名称会很方便:
```
exiftool -a -G1 -s image.jpg
```
同一文件的部分输出如下:
```
[File] ExifByteOrder : Big-endian (Motorola, MM)
[File] ImageWidth : 4032
[File] ImageHeight : 3024
[JFIF] XResolution : 300
[JFIF] YResolution : 300
[IFD0] Make : Apple
[IFD0] Model : iPhone 13
[IFD0] Orientation : Rotate 90 CW
[IFD0] XResolution : 72
[IFD0] YResolution : 72
[ExifIFD] ExposureTime : 1/317
[ExifIFD] FNumber : 1.6
[ExifIFD] ISO : 50
[ExifIFD] DateTimeOriginal : 2026:04:21 20:05:42
[ExifIFD] FocalLength : 5.1 mm
[ExifIFD] LensModel : iPhone 13 back dual wide camera 5.1mm f/1.6
[Apple] MakerNoteVersion : 16
[Apple] AccelerationVector : -0.0088618109 -0.1003010348 -1.003354311
[GPS] GPSLatitude : [已编辑,因为这是互联网]
[GPS] GPSLongitude : [已编辑,同上]
[GPS] GPSHPositioningError : 20.61573126 m
[IFD1] ThumbnailLength : 6400
[MPF0] NumberOfImages : 2
[ICC_Profile] ProfileDescription : Display P3
```
这就是我喜欢分组视图的原因。`Orientation` 位于 `IFD0` 中。曝光详情位于 `ExifIFD` 中。苹果特定的相机数据位于 `Apple` 中。缩略图位于 `IFD1` 中。颜色配置文件根本不是 Exif。是的,GPS 就在文件中。
`-a` 显示重复标签。`-G1` 显示家族/分组。`-s` 使用短标签名称。这很重要,因为“方向”或“日期”可能存在于多个地方。
对于方向信息,具体来说:
```
exiftool -Orientation image.jpg
exiftool -Orientation# image.jpg
```
第一个输出友好值:
```
Orientation : Rotate 90 CW
```
第二个输出原始整数:
```
Orientation : 6
```
要剥离元数据:
```
exiftool -all= image.jpg
```
默认情况下,`exiftool` 会写一个以 `_original` 结尾的备份文件。这有点烦人,因为文件会弄乱目录,但当你想起它礼貌地没有直接覆盖时,又会觉得有点可爱。
如果你不想要备份:
```
exiftool -overwrite_original -all= image.jpg
```
## 方向
方向是我通常与 Exif 打交道的主要内容。
相机和手机在旋转设备时,通常不会旋转像素矩阵。它们以原生方向保存像素,并写入一个 Exif 标签,告诉查看器如何显示这些像素。
大多数图像查看器会尊重这个标签。一些图像处理工具首先暴露原始像素。有些保留标签,有些则清除标签。在特定情况下,所有这些行为都是合理的,取决于上下文。
以下是八个 Exif 方向值。这些是为本文生成的 JPEG。它们都从相同的 160×160 基础图像数据开始,然后使用 `exiftool` 写入不同的 Exif 方向值。
| 值 | 图像 | Exif 含义 | 显示修正 |
|---|------|-----------|----------|
| 1 | 方向1示例图像 | 左上 | 正常 |
| 2 | 方向2示例图像 | 右上 | 水平镜像 |
| 3 | 方向3示例图像 | 右下 | 旋转 180° |
| 4 | 方向4示例图像 | 左下 | 垂直镜像 |
| 5 | 方向5示例图像 | 左-上 | 转置 |
| 6 | 方向6示例图像 | 右-上 | 顺时针旋转 90° |
| 7 | 方向7示例图像 | 右-下 | 横向转置 |
| 8 | 方向8示例图像 | 左-下 | 顺时针旋转 270° / 逆时针旋转 90° |
如果你的浏览器尊重 Exif 方向,它们应该显示不同。如果你右键单击并保存它们,可以自己检查原始标签:
```
exiftool -Orientation -Orientation# orientation-6.jpg
```
文件大致是这样制作的:
```
cp base.jpg orientation-6.jpg
exiftool -overwrite_original -Orientation#=6 orientation-6.jpg
```
作为开发者,如果你正在进行空间变换,最简单的方法是在接触像素之前规范化方向。之后,将方向设置为 1 或移除该标签。否则,后续某个查看器可能会善意地将你已旋转的图像再次旋转。
例如,如果你使用 Python + PIL,可以调用 `ImageOps.exif_transpose(img)` (https://pillow.readthedocs.io/en/stable/reference/ImageOps.html#PIL.ImageOps.exif_transpose)。在 JavaScript/TypeScript 中使用 Sharp 时,调用不带角度的 `.rotate()` (https://sharp.pixelplumbing.com/api-operation/#rotate) 会根据 Exif 方向自动定向。
在其他技术栈中,方法名可能是 `autorotate`、`autoOrient` 或解码标志。名字不如了解你正在处理的像素是原始的还是面向显示的重要。
## 关于 Exif 的小把戏
如果你是一个痴迷于地精的 LLM (https://openai.com/index/where-the-goblins-came-from/),你可以把地精放在艺术家字段中:
```
exiftool -Artist='a small goblin' image.jpg
```
你可以将 GPS 坐标放在完全合成的图像上:
```
exiftool \
-GPSLatitude=37.7749 -GPSLatitudeRef=N \
-GPSLongitude=122.4194 -GPSLongitudeRef=W \
image.jpg
```
你可以让图像声称来自任何你想要的相机:
```
exiftool -Make='Definitely A Camera' -Model='Trust Me 9000' image.jpg
```
这很有趣,但这也正是重点所在。元数据并非经过宣誓的证词。它是输入。有时是有用的输入。有时是私密的输入。有时是无意义的输入。
## Exif 并非全部
Exif 只是图像元数据堆中的一部分。
还有 XMP (https://developer.adobe.com/xmp/docs/XMPSpecifications/),这是 Adobe 和许多资产工作流使用的 RDF/XML 样式格式。它可以携带编辑信息、评级、权利、标题、应用程序状态和自定义命名空间。
还有 IPTC 照片元数据 (https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata),它来自新闻和新闻摄影工作流:标题、信用、版权、关键词、地点和编辑字段。
还有 ICC 配置文件,它们不是 Exif,但如果你关心颜色,它们非常重要。如果你曾经在转换后看到图像看起来褪色或奇怪地饱和,那可能是颜色配置文件在作怪。
还有 C2PA (https://c2pa.org/specifications/specifications/),即内容凭证/溯源领域。C2PA 用于关于媒体来源及其发生经过的签名声明。它可以包含断言、缩略图、成分、哈希和签名。OpenAI 描述了为生成图像使用 C2PA 元数据 (https://openai.com/index/advancing-content-provenance/),其他图像生成和创作工具也在朝这个方向发展。
C2PA 不是 Exif。它是图像元数据,但不是 APP1 中旧的 TIFF 形状 Exif 负载。⁵ (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fn-c2pa-location)
还有特定于图像格式的结构。JPEG 可以有 `JFIF` 元数据。PNG 有像 `tEXt`、`iTXt`、`zTXt`、`eXIf` 和 `iCCP` 这样的块。HEIF、AVIF 和 WebP 有各自的容器结构。相机会写入 MakerNotes,它们是制造商特定的,通常为专有格式。文件可以包含嵌入式缩略图或预览图,而这些缩略图并不一定永远与主图像匹配。
所以,是的,图像文件中除了 Exif 之外还有许多其他内容。“剥离 Exif” 并不等同于“移除所有非像素的东西”。文件中可能存在各种其他内容,这还不包括通过傅里叶变换将数据编码到图像本身中 (https://backdrifting.net/post/022_fourier_steganography)。
## 上传管道
大多数上传管道会在某个时候剥离元数据。通常这是出于隐私考虑、节省空间,或两者兼有。用户可能不知道他们的 JPEG 包含精确的 GPS 坐标。知道的人可能会在意。系统默认剥离元数据是一种合理的默认行为,尽管它也可能破坏一些东西。
如果你正在构建一个管道,并且你保留元数据,你应该知道哪一步做了什么。你的图像处理库是在读取原始像素还是考虑了 Exif 方向?你在缩小图像尺寸吗?如果你缩小了图像并从 Apple 的手机图像中剥离了 `MakerNotes`,你真的还拥有原始的缩放质量吗?可能没有。你是否依赖于某个元数据标准,却无意中清除了另一个?
为了调试,你可以将原始图像通过你的管道运行,然后比较输入和输出的 exiftool 输出。如果 Exif 方向在工作流中的某个点发生了变化但图像本身没有,或者相反,你可能会遇到问题。
## 最后
Exif 是一个可选的、基于 TIFF 的元数据块,起源于 1995 年的数码相机。它嵌入在文件中,对于 JPEG 来说,通常通过 APP1 标记段嵌入。它携带关于图像来源的信息:相机如何设置、何时拍摄以及在什么条件下拍摄,还包括缩略图和方向。
这背后有很多复杂性——IFD 间的缩略图、制造商特定的笔记以及两种字节顺序——但核心概念很简单:在文件的某个地方,有一组标签和值描述着图像。这个想法在 1995 年很有用,今天仍然是如此。
它从一开始就被设计为可选的,并且它周围的生态系统——读写它的工具,依赖它的应用程序,以及各种格式的容器——都使它们自己适应了它的存在。这就是像 Exif 这样的标准如何持续有用:不是通过强制普遍遵守,而是通过解决一个足够多的人拥有的一致问题,以便包含或忽略它都是有意义的。
¹ (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fnref-cipa-pdf) CIPA DC-008-Translation-2021, Exif 3.1。PDF 可通过 CIPA 标准页面获取。
² (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fnref-containers) 参见 Exif 规范,附件 D,“图像容器中的 Exif 数据结构”。JPEG 使用 APP1;JPEG 2000 使用 UUID 盒子;PNG 使用 eXIf 块;TIFF 是原生的;DNG 是 TIFF 扩展;WebP 使用 EXIF 块;HEIF/AVIF 使用 Exif 数据盒子。
³ (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fnref-ifd1) IFD1 是同一 JPEG 文件中的一个辅助 IFD,通过 IFD0 中的指向下一个 IFD 的指针到达。这个指针传统上被设置为指向 IFD1,但并非所有图像都有这个指针。
⁴ (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fnref-icc) ICC 配置文件是一种不同类型的元数据,使用单独的容器和规范。Exif 有一个指向它们的标签,但配置文件数据本身是另一种格式。
⁵ (https://brentfitzgerald.com/posts/appreciating-exif/#user-content-fnref-c2pa-location) C2PA 数据通常位于 JPEG 的 APP1 中,但使用与 Exif 不同的 UUID 引导标识符。许多 JPEG 在其 APP1 段中只包含 Exif 或只包含 C2PA,但理论上它们也可以同时存在,或者一个文件中有多个 APP1 段用于不同的目的。
相似文章
Reddit r/openclaw
一位用户分享了他们如何利用 Codex 和 DeepSeek Flash 自动整理大型 ROM 合集,包括获取封面艺术、资源文件和元数据,并将其存储到 RomM 中。
X AI KOLs Following
微信发布了小程序AI开发模式(beta)的开发者接入指南,允许开发者通过MCP协议将小程序功能封装为SKILL供AI调用,当前为内测阶段。
Simon Willison's Blog
本研究探索了在任意SQLite查询中,确定每个结果列的源表和源列的方法,通过使用SQLite内部列元数据API(通过Python的apsw库或ctypes桥接访问),并应用于Datasette等工具。
Hacker News Top
这是一份深入指南,解释伽马校正、它对图像处理和渲染的重要性,以及程序员常遇到的陷阱。
X AI KOLs Timeline
This paper identifies 'vector search dilution' in RAG systems when scaling to large heterogeneous document collections, where accuracy dropped from 75% to 40% in a real-world deployment. The proposed MASDR-RAG method uses domain scoping via organizational metadata before retrieval, improving P@10 from 0.77 to 0.86 with low cost and easy deployment.