为什么照片一上传就转了方向
转动相机时,照片本身几乎不会跟着转。传感器固定在机身里,无论你怎么拿,它记录的都是同一个长方形;相机会在文件里写下一个方向标签,说明显示时该往哪边转。之后每一个把图片显示给你看的程序,都会自行决定要不要听这个标签。当两个程序的决定不一致时,其中一个就会把你的照片显示成横躺的。
相机不转照片,只留下一张便条
JPEG 或 HEIC 文件的 EXIF 元数据里有一个叫 Orientation 的字段,定义了八个取值。其中一个表示文件已经是正的,另外三个是 90 度、180 度和 270 度的单纯旋转,剩下四个则是旋转加上左右镜像的组合。
所以手机拍出的竖构图照片,通常是一张横向图像外加一句「请转四分之一圈」的便条。存下来的像素确实是横躺的,任何把它显示成正的查看器,都是在绘制时应用了这个标签。
为什么有的程序听便条,有的完全不理
浏览器在显示普通图片时会应用这个标签,如今这已是默认行为。但凡是把文件解码到原始像素的处理,看到的都是横躺的那一版,因为到那一步,标签只是留在文件头里的一个数字。
上传会把照片转过来的原因就在这里:网站并没有「看」你的文件,而是重新编码了它。缩小尺寸、剥掉元数据、转成 WebP,写回去的结果上已经没有那张便条了。脚本里也一样:图像库只在你要求时旋转,除非你明确让它先应用方向,否则它不会自己动手。
转两次是真实存在的故障
反过来的错误同样常见。某个工具把像素摆正了,却把标签留在「请转四分之一圈」的状态,于是下一个遵守标签的查看器又把这张已经正确的照片转了一次,结果是往另一边躺倒的照片。
当照片和应有的方向差了九十度时,有用的问题是:错的是哪一半,像素还是便条?两者是彼此独立的信息,一个文件完全可能自相矛盾。
文件里写的宽高属于传感器,不属于照片
用一千两百万像素的手机拍的竖照片,会把自己报成 4032 × 3024,也就是横向。文件头里的尺寸描述的是保存下来的像素,让它在屏幕上变成竖向的是方向标签。
任何按这些数字预留空间的布局,或者在绘制之前就判断图片是不是横向的检查,遇到竖照片都会出错。相册里莫名其妙留出空隙,多半是这个原因,而不是 CSS 的问题。
镜像的自拍是同一套机制
八个方向取值中有四个包含左右镜像,它们的存在是因为前置摄像头给你看的是镜像预览。有的应用在保存前把像素翻转过来,有的则原样保存传感器图像,把翻转记在标签里。
看得见的症状在文字上。衣服上的标志或你身后的白板,在一个程序里是反着的、在另一个程序里是正的,这说明翻转在标签里而不在像素里。
缩略图可能和照片对不上
EXIF 里还可以放一张相机在拍摄时写入的小缩略图。文件管理器和照片应用经常直接显示这张缩略图,因为读它比读整张图快得多。
但编辑软件并不总会更新它。裁剪或旋转改变了照片,旧缩略图却原封不动,就会出现预览和打开后的文件显示不同内容这种怪事;更不容易察觉的是,你以为已经裁掉的部分,可能还留在缩略图里。
怎样做出一张不会被读错的照片
动手之前先把标签读一遍,你才知道遇到的是旋转问题还是镜像问题,以及这个文件到底有没有在要求被旋转。如果照片是横躺的、标签却已经写着正向,那就是上游某个环节以不可逆的方式转过了像素。
长久的解决办法是把旋转写进像素,然后把标签设为正向,或者干脆去掉元数据,让后面任何程序都无法再转它一次。要在上传之前做,而不是之后,因为网站一旦重新编码并剥掉元数据,那张本来会告诉它该怎么转的便条就已经不在了。