PNG有关iDOT块的笔记

iDOT 块简述

这是 Apple 为了 PNG 解码速度而做的一个优化 。苹果为了让 PNG 格式的图片可以并行解码并且兼容原本的 PNG 标准,把图片内容分为前半后半两部分,并把像素流分为多个 IDAT 块,然后在 PNG 文件里添加了一个 iDOT 辅助块,其中记录了前半后半的分隔位置(后半数据相对 iDOT 块的偏移值)和解压后的像素高度,这样用 Apple 的 PNG 编码器编码的 PNG 图片用 Apple 自家的 PNG 解码器解码就可以分为 2 个并行的过程,以此充分利用多核性能,同时这样的 PNG 图片也能被普通解码器解码。

在不同设备上显示不同

如果说我们让顺序解压的数据与并行解压后把数据拼一起的内容不一样,那么就可能出现在不同设备上显示不同的结果。

实现的原理非常的巧妙,就是通过利用 zlib 的非压缩块特性:非压缩块标识可以在压缩数据中指定一块区域在解压时忽略掉它。如果把非压缩块标识放到上半的末尾,而把被标记的数据放到下半的起始,当单独解压下半时数据不会被忽略,而上半下半连在一起解压时,这些数据就会被忽略,这样就可以让数据在并行压缩被用到而顺序压缩时被忽略。

这个技巧相当的巧妙以至于 Apple 也没有想到,在 Apple 系统(MacOS、iOS)只要利用了系统的 PNG 解码器的软件都会受到影响(MacOS 上 Chrome 浏览器自带 PNG 解码器所以不受影响)。

我们可以使用 https://github.com/DavidBuchanan314/ambiguous-png-packer 来生成显示不同的图片。

在现实生成网站:https://moonvy.com/apps/PNGemini/

当然,如果想要查看不同设备的图片,那么最好的方法当然是拥有一部苹果手机

特征:会出现一些杂乱无章的像素线条,这不是技术问题,而是因为原理上是拼接和不解压数据,所以只要是这种构造的图片,都会出现一些像素线条。

如下图:

男神

可以使用在线网站ICC+ 功能导出 IDOT 块隐藏的内容。