图片 EXIF 读取器 — 打开一张照片,看相机在里面写了什么

选一个 JPEG、PNG、WebP 或 TIFF 文件,把相机留在里面的元数据读出来:机型、曝光参数、方向、时间戳和 GPS 坐标。解析在你的浏览器里逐字节完成,文件不会离开这台设备。

读了哪些字段,从哪读

读的是哪些东西,从哪儿读

EXIF 是一段藏在图片文件里的 TIFF 目录,而每种容器藏法不一样。常见的四种都走一遍:

  • JPEG —— 从 FFD8 之后的段按顺序一段一段走过去,一直走到压缩图像数据开始。正文以 Exif\0\0 开头的 APP1 段就是装目录的那一个。SOF 段也要读,因为真实的像素尺寸写在那里;EXIF 自己的 ExifImageWidth/Height 经常是过期的或者干脆没有。
  • PNG —— PNG 1.5 才加进来的 eXIf 数据块。大多数 PNG 从来没听说过它。
  • WebP —— RIFF 列表里的 EXIF 数据块。
  • TIFF —— 文件本身就是那个目录,所以从第 0 个字节开始读。

往里走的时候,先读 IFD0,再顺着它指过去的 Exif 和 GPS 子目录,最后读 IFD1 —— 相机那份小预览图就存在那里。如果那份预览图确实是 JPEG,就把它显示出来;这是唯一会解码的一点点图像数据。

宁可空着,也不猜的字段

  • MakerNote 不解。 每家厂商都在里面自己发明了一套格式,而猜错的值和猜对的值长得一模一样。你只能看到这个标签和它的字节数。
  • HEIC/HEIF/AVIF 直接拒绝,而不是糊弄。 它们的元数据在 ISO-BMFF 属性项里,不是 TIFF 块,半吊子地解析只会产出自信的胡说。
  • 坏掉的指针照实报告,不修补。 目录声称的条目数比文件装得下的多时,会照实说清楚,然后只读出真在那儿的那些。
  • 不编时间戳。 EXIF 里有 DateTime、DateTimeOriginal、DateTimeDigitized 和 GPS 时间戳,它们对不上的情况多得惊人 —— 所以摘要会标明印出来的是哪一个。

那个方向数字

Orientation 不是一张转好了的图,它是给显示者的一条指令。值 1 表示像素行本来就是从上往下。值 6 表示"顺时针转 90 度才正",这正是浏览器开始遵守 image-orientation: from-image 之前大多数手机写的值 —— 也解释了为什么同一份字节在一个应用里看着正、在另一个里是躺着的。上面的表把数字和那句人话都印出来。

为什么照片可能是空的

聊天软件、社交网站和大多数"发送原图以外"的路径都会删掉 EXIF,一方面为了缩小上传体积,另一方面因为共享照片里的 GPS 是实打实的隐私问题。截图从来没有相机数据。编辑器重新导出的文件只保留编辑器自己写的那些。一个文件没有 EXIF 块是正常结果,不是错误,这一点会直说,而不是摆出一张空表。

问答

Q:图片会被上传吗? 不会。字节由浏览器自己的文件读取器读进这个标签页,再由这里的循环解析:图片不进请求体,没有服务器见过它,也不会离开这台设备。

Q:GPS 显示的是一个我没去过的地方。 坐标是从度分秒的有理数按原样解成 WGS84 十进制度的。如果手机写的是个大概位置,或者某个工具写了一个假位置,显示出来的就是那个值,而不是编出来的 —— 所以标的是"WGS84 十进制度",而不是一枚地图图钉。

Q:照片那么大,为什么分辨率是 72 dpi? XResolution 配上 ResolutionUnit = 2 是相机报告打印密度时的写法,仅此而已。它跟像素尺寸没有关系,像素尺寸是从 SOF 段读的。

Q:我想要的标签在表里,但值是括号里的一句话。 那是老实承认读不了:MakerNote、非 ASCII 的 UserComment、指向块外的指针、声称了装不下的条目数,都是这种情况。数字和字节数照样列出来,好让你拿去比对原始文件。

微信
微信
支付宝
支付宝