一张35K的jpg为什么会动?揭开文件魔数、FF D9与WebP伪装的真相

前言:一张35K的jpg居然能动,背后藏着JPEG文件FF D9后拼接视频、改后缀名伪装、微信视频号WebP压缩等真相。用JarkViewer读取文件魔数,几行Python代码就能扒掉它的伪装,看清数字世界里后缀名与真实身份的缝隙。

一张35K的jpg,凭什么会动

前两天刷到一个挺有意思的事。

有人在网上发了一张图,后缀是.jpg,35K大小,看着就是一张普普通通的静态图片。但用JarkViewer打开之后,这玩意儿居然动起来了。

我当时就愣了一下。

jpg不是静态图吗?35K能装下一段视频?这俩信息放一块儿,怎么看怎么矛盾。

我寻思了一下没寻思明白,就顺手去扒了扒,结果发现这事儿还挺有意思的,比我想的深。

一张jpg,凭什么会动
一张jpg,凭什么会动

先说第一个问题,jpg为什么会动。

坦率的讲,jpg这个格式从娘胎里出来就是干静态图这活的,它压根不支持动画。你拿任何标准JPEG解码器去解,出来的就是一帧。所以如果一张.jpg能动,只有一种可能,它压根不是jpg。

它只是披着jpg的外衣。

这里面有两种情况最常见。

第一种,实况照片。就是你现在手机上拍的那种”动态照片””实况照片”,苹果叫Live Photo,华为小米叫法不一样但意思差不多。你拍完导出来,文件后缀还是.jpg,但这个文件里其实塞了两样东西,前面是一张标准的静态JPEG图像,后面偷偷追加了一小段MP4视频。两个东西硬拼在一个文件里。

那为什么有的软件能放,有的不能?

因为普通的看图软件,比如Windows自带那个照片查看器,它读到JPEG的结束符,也就是十六进制的FF D9,就停了。它觉得”哦图读完了”,后面那截视频数据它根本不看,直接忽略。但JarkViewer不一样,它会主动去扫FF D9之后还有没有东西,发现后面藏着视频流,就给你播出来了。

FF D9之后,还藏着一整个视频
FF D9之后,还藏着一整个视频

这就像你收到一个快递箱子,普通快递员只看最上面那层就走了,但有个较真的快递员把箱子翻了个底朝天,发现底下还垫着一层货。

第二种情况更简单粗暴,就是有人把动图改了后缀名。

一张GIF,或者动态WebP,或者AVIF动画,本来后缀是.gif或者.webp,被人或者系统改成了.jpg。很多老的看图软件是”认后缀名”的,看到.jpg就强制调用静态图片解码器,动图就变成静图了。但JarkViewer不这么干,它是直接去读文件头部的”魔数”,也就是Magic Number,来判断这个文件到底是个什么东西。

魔数这玩意儿,你可以理解成每个文件格式自带的”身份证号”。GIF的文件头一定是GIF8,WebP的文件头一定是RIFF开头后面跟着WEBP,MP4的文件头里有ftyp这几个字符。这些标记是写在文件最开头的二进制数据里的,改后缀名改不掉它们。JarkViewer就是靠这个识破了伪装。

说到这儿,第一个问题算是搞清楚了。jpg能动,要么是后面藏了视频,要么是压根不是jpg只是改了名。

但第二个问题更有意思。

35K。

你想想看,35K能装什么?

一张手机拍的实况照片,静态图部分通常2到4MB,视频部分哪怕用HEVC这种狠压缩也得1到3MB,加一块儿怎么也得3到7MB。35K连一帧高清画面都装不下,更别说视频了。

所以这个文件99%不是真正的实况照片。

那它到底是什么?

35K的秘密,藏在文件头里
35K的秘密,藏在文件头里

后来得知这张图是从微信视频号的动态封面上扒下来的,一切就都说得通了。

微信生态里,视频号的封面为了在用户刷信息流的时候一瞬间抓住眼球,同时又不想把CDN带宽费用搞到天上去,用了非常激进的压缩策略。当创作者上传视频之后,腾讯的转码服务器会自动截取视频开头1到3秒的内容,剥离音频,降低分辨率,降低帧率到10到15fps,然后用WebP这种现代编码格式压成动图。

一段1到2秒、帧率不高、色彩不复杂的动图,用WebP编码完全可以压到30K到50K。35K,刚刚好落在这个区间里。

所以这个文件的真实身份,大概率是一张Animated WebP,动态WebP。只不过在被人通过抓取工具或者浏览器缓存提取出来的时候,抓取脚本没有严格校验HTTP响应头里的Content-Type,或者微信那边为了兼容性直接返回了image/jpeg,保存到本地的时候就被默认加上了.jpg的后缀。

张冠李戴了。

你要验证也简单,用Python写几行代码,以二进制方式打开这个文件,读前12个字节,看文件头。如果是RIFF开头、第8到12字节是WEBP,那就是WebP。如果是GIF8开头,那就是GIF。如果第4到8字节里有ftyp,那就是MP4或者AVIF或者HEIC。

几行代码就能扒掉它的伪装。

读12个字节,真相大白
读12个字节,真相大白

说到这儿,技术层面的事儿基本聊完了。但我顺着这个事儿再想了想,觉得它背后还有一层挺有意思的东西。

你有没有发现,我们在数字世界里看到的一切,都是被”翻译”过的。

你看到一张.jpg,你以为它就是jpg。但其实它可能是WebP,可能是GIF,可能是HEIC,可能是一张静态图后面拖着一段视频。它的真实身份藏在二进制头部,藏在魔数里,藏在FF D9之后那些被大多数软件忽略的字节里。而你看不到这些,你看到的只是软件”选择”给你看的东西。

这事儿细想其实挺赛博朋克的。

尼尔·斯蒂芬森在《雪崩》里构想的元宇宙,每个人在数字世界里都有一个Avatar,一个化身。你看到的那个化身,和真实坐在终端前的那个人,可能完全是两码事。数字世界里的身份和真实身份之间,永远隔着一层翻译层。

文件也是这样。一个WebP穿上.jpg的马甲,大多数软件就被骗过去了。只有那些愿意多看一眼文件头的,才能看到真相。

你想想看,这跟现实世界有什么区别?

你看到一个人的title,看到他的朋友圈,看到他在会议上的表现,你以为那就是他。但这些全是”后缀名”。他真实的文件头是什么,他的魔数是什么,你得真的去读他的二进制才能知道。而大多数人,只看后缀名。

我有时候觉得,互联网发展到今天,越来越像一个巨大的”后缀名骗局”。平台给你看的是它想让你看到的格式,不是文件真实的格式。微信给你看的封面是.jpg,但底下是WebP。短视频平台给你看的是15秒高光,但真实生活是两小时的平淡。电商给你看的是精修主图,但实物是另一回事。

每个平台都是一个”只认后缀名”的看图软件。

而那些能看穿伪装的工具,不管是JarkViewer这种能读魔数的看图软件,还是你自己在生活里培养出来的”读文件头”的能力,都变成了稀缺品。

回到最开始那张35K的jpg。

它其实什么都没做错。它只是被系统改了个后缀名,被平台压成了最小体积,被塞进了一个不属于自己的格式里,然后被一个较真的看图软件识破了真身。

这事儿说大不大,说小也不小。它让我意识到,数字世界里”看起来是什么”和”实际上是什么”之间的缝隙,比我想的要大得多。而大部分时候,我们连这个缝隙的存在都不知道。

下次你打开一张图片,或者打开一个人的主页,或者打开一个产品的介绍页,可以想一想,你看到的到底是后缀名,还是魔数。

磨平一些信息差,有时候就是从多看一眼文件头开始的。

你看到的,是后缀名,还是魔数
你看到的,是后缀名,还是魔数

/ 注意,本项目仅在 SyncMein 的500人小群分享。
/ 谢谢你看完了我的文章,我们下次再见吧。
/ 作者:明察
/ 投稿或爆料,请联系邮箱:mingcha@gqmg.com

关键词:jpg动态图片原理, JarkViewer读取文件魔数, JPEG文件FF D9拼接视频, 微信视频号动态封面WebP压缩, Python检测文件真实格式

– END –

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容