前言
前段时间小米出的水印边框照片模板被大家玩的不亦乐乎,本来想着写一个实现合成各厂商带水印边框照片的工具。这个头脑一热想要开发的工具最终也没有着手实现,不过这里面有一个知识点倒是令我很感兴趣。

这一点就是:合成水印边框通常会自动带上照片的拍摄数据——光圈、快门、感光度、品牌 LOGO,那这些数据都是从哪里获取照片里面又是怎么存储的呢?
在查询了大量资料之后得知,这些参数都来自于 Exif 数据,于是对 Exif 的技术标准、读写 Exif 的 JS 框架做了一些研究,这篇文章就是据此研究总结而来。
最后,笔者还写了一个 Exif 数据编辑的 Vue 组件——exif-edit。

图片格式与 Exif 数据
图像元数据有两种格式:Exif、XMP,而 Exif 就是其中一种。
Exif 全称是可交换图像文件格式(英语:Exchangeable image file format,官方简称 Exif),是用于记录数码照片的属性和拍摄数据的。属性主要是指照片的分辨率大小、缩略图,而拍摄数据主要是指光圈、快门、感光度、焦距、设备型号、镜头、GPS 位置等。
维基百科上给出的 Exif 包含的信息示例如下:

常见图片格式有 JPEG、PNG、GIF、HEIF、DNG、TIFF 等,其中已经明确能够支持写入 Exif 数据的格式有:JPEG、DNG、TIFF、HEIF。
各图片格式对于 Exif 数据支持情况如下:
格式 | JPEG | PNG | GIF | HEIF | DNG | TIFF | BPG | BMP |
---|---|---|---|---|---|---|---|---|
Exif | 支持 | 不支持 | 不支持 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
目前在互联网上最常见的图片格式是 JPEG 格式(文件名后缀 .jpeg
),又称为 JPG 格式(文件名后缀 .jpg
),我们暂且只分析 JPEG 图片中的 Exif 数据。
Exif 格式规范
Exif 数据能够嵌入到不同格式的图片中,那各个格式的图片是如何识别并解析 Exif 数据的呢?这就涉及到 Exif 数据的格式规范了。
可以简要描述为:Exif 信息数据以两个字节长度的特定标记开头,这个标记之后的两个字节记录Exif数据总的字节长度。有了 Exif 标记和所有数据总字节长度,就能知道哪些是 Exif 数据了。
这个标记是 2 字节长的 0xFFE1
,这是十六进制表示,表示的是什么意思呢?且看下文解释。
我们知道计算机世界里一个字节是由 8 个二进制位组成,即 1Byte = 8bit
(bit
可以简写为 B
),8 个二进制位的所有排列组合有 2**8 = 256
种结果;二进制中一个位有 2 种可能结果,而假设一个位有 16 种可能结果的话,8 个二进制位则可以用 2 个 十六进制位表示,因为 2 个 16 进制位所有的排列组合正好有 16**2 = 256
种结果。