跳到主要内容
AZ Tools

WebP 文件检查器

.webp 这一个扩展名下藏着三种相当不同的文件,本工具做的第一件事就是把它们区分开。简单有损文件是 RIFF 头后面跟一个 VP8 块,里面装着一个 VP8 关键帧,尺寸写在 9D 01 2A 起始码之后的两个 14 位字段里,旁边就是决定环路滤波的版本号和 show_frame 位。简单无损文件只有一个 VP8L 块,5 字节的头在 0x2F 签名之后塞进了宽度−1、高度−1、透明提示位和 3 位版本号。扩展文件以 VP8X 开头,用两个 24 位的 −1 字段声明画布,并带上 ICC、透明、Exif、XMP、动画的特性位图,其后可以跟 ICCP、ANIM、ANMF、ALPH、EXIF 和 XMP。每个块都会列出 fourcc、偏移、声明大小和填充字节,因为负载长度为奇数的块后面会跟一个不属于负载的字节,忘掉它的读取器会从第一个奇数块之后开始处处错位一个字节。如果是动画,ANIM 块给出按蓝、绿、红、透明顺序存放的背景色和循环次数(0 表示无限),每个 ANMF 给出以一半形式存放的偏移(真实位置是字段的两倍,这是手写读取器最常犯的错)、尺寸、以毫秒计的时长、混合与处置位,以及该帧的负载是有损、无损,还是有损加上一个单独的 ALPH。对不是自己生成的文件,有两个数值值得核对:必须等于文件大小减八的 RIFF 大小字段(下载中断的文件对不上),以及画布——对静止图像,libwebp 要求它与内部图像一致,而不是缩放适配。预览由你的浏览器用同一份字节解码,因此声明的画布和解码出的画布可以并排比较;如果浏览器干脆拒绝了这个文件,这个拒绝本身就是答案。它不会自己解码像素,也不会列出每一个 Exif 标签——元数据只看到大小、字节序和 IFD0 的条目数为止。

使用方法

  1. 把 .webp 文件拖进方框。照片、带透明的贴纸、动画,或者你怀疑已经损坏的文件都可以。
  2. 先看文件形态。简单有损、简单无损和扩展是三种不同的布局,只认识简单形态的解码器会拒绝第三种。
  3. 把声明的画布和本浏览器解码出的尺寸对照一下。二者应当一致;如果浏览器拒绝了文件,发现列表会说明原因。
  4. 打开块表查看布局:fourcc、偏移、声明大小以及后面是否跟着填充字节。调试编码器时就从这些偏移看起。
  5. 若是动画,看帧表——偏移已经从一半的字段还原成实际值——以及各帧时长,其中 0 毫秒的帧在 Chrome 里按 100 毫秒播放。

常见问题

为什么有的 .webp 以 VP8 块开头,有的却是 VP8L 或 VP8X?它们是同一种格式吗?
它们共用容器和扩展名,码流并不相同。简单有损形态包裹一个 VP8 关键帧,也就是 VP8 视频开头的那种帧内帧;简单无损形态包裹的是 VP8L 码流,那是一个完全不同的编解码器,有自己的熵编码和颜色变换。扩展形态把 VP8X 块放在最前面,使文件还能携带放在单独 ALPH 块里的透明通道、ICC 配置文件、Exif、XMP 或动画,然后才是图像数据。这就是老解码器能打开一个 WebP 却拒绝下一个的原因:简单形态出现在 2010 年,扩展形态出现在 2011 年,各家库支持的时间并不一致。决定文件形态的只有第一个块的 fourcc。
动画里的帧偏移看起来只有应有值的一半,为什么?
因为存进去的确实就是一半。ANMF 头把帧的 X 和 Y 存成 24 位的值,等于真实偏移除以二,这也是帧只能放在偶数坐标上的原因。原样打印字段的读取器会把 x=8 的帧显示成 x=4,直接用原始字段合成的程序会把每一帧都画在离画布边缘一半的距离上——这种缺陷看起来像轻微的偏移,而不是明显的损坏。同一个头还把宽高都减一存放,所以宽 32 像素的帧写成 31。本工具在显示前把偏移乘二、把尺寸加一,因此这里的数字与解码器实际绘制的位置一致。
声明时长为 0 毫秒的帧会怎样?
并不会零时间掠过。Chrome 和其他基于 Blink 的浏览器会把时长为 0 的 WebP 帧改按 100 毫秒播放,与它们处理延迟极小的 GIF 帧的做法相同,其假设是 0 属于笔误而不是要求无限快的动画。Firefox 和 Safari 并非一直采取同样的选择,而 ffmpeg 这类命令行工具会保留 0 并得到另一个帧率。实际后果是:声明时长之和并不是文件的播放长度。本工具同时给出两个合计,方便你在依赖时序之前先看清差距。
画布和里面的图像尺寸不一样,浏览器会拉伸还是加黑边?
对静止图像来说,两者都不会。libwebp 要求 VP8X 的画布与其中唯一的 VP8 或 VP8L 帧尺寸相同,不一致就拒绝该文件;而 Chrome、Firefox 和 Safari 都用 libwebp 解码 WebP,所以尺寸对不上的静止图像在任何地方都显示不出来。动画的规则不同,画布确实可以更大:每个 ANMF 帧在自己的偏移处合成,超出画布边缘的部分会被裁掉。因此本工具把静止图像上画布与码流的不一致当作一条发现来报告,并单独提示越出画布的帧。
既然文件照样能显示,RIFF 大小字段为什么还重要?
只有这个字段正确,文件才照样能显示。偏移 4 处的四个字节必须等于文件大小减八——那八字节是 RIFF fourcc 和大小字段本身——libwebp 在解码任何内容之前就会校验它。中途停止的下载保留着原来的大小字段却丢掉了末尾的字节,于是字段偏大,文件被拒绝,除了一个损坏图片图标之外没有任何提示。相反的情况是编码器追加元数据后忘了回头改写这个字段,结果生成的文件有些工具能读、浏览器却不能。本工具把两个数字都打印出来,让你看清属于哪一种,并单独标出最后一个块之后残留的字节。
透明是怎么存的?为什么同一张图有时有 ALPH 块、有时没有?
一共有三种安排。无损文件把透明信息记录在 VP8L 码流内部,只在头里置一个提示位。有损文件做不到,因为 VP8 根本没有透明通道,于是编码器输出扩展文件:一个置了透明标志的 VP8X、一个装着透明平面的 ALPH 块(用无损方式压缩,可选地做水平、垂直或梯度滤波),然后才是装颜色的 VP8 块。动画会逐帧重复这一套,所以有的帧带 ALPH、有的不带。还有一点值得知道:有损编码器通常会丢弃全透明像素的颜色以节省字节,在合成或模糊之前完全看不出来,而 libwebp 的 exact 选项正是用来保留它的。

相关工具