翻一下硬盘里的图片,扩展名大概能凑出十几种:.bmp、.gif、.png、.jpg、.webp、.avif、.heic、.tif、.tga、.psd、.exr、.dng……如果做前端或者写文档,还见过 .svg、.ico、.apng。它们不是同一层次的东西:有的只是「外壳」,里面装的压缩算法可以换;有的本身就是算法。
这篇文章把两件事分开讲清楚:图片的文件格式(容器)有哪些,以及压缩格式(编解码器)有哪些、各自靠什么算法压。文中出现的每个数字与年份都来自规范原文或厂商官方文档,出处列在文末,正文里也尽量就近给了链接。
一、先分清「文件格式」和「压缩格式」
举个最直观的例子。同样是 .heic 后缀,里面可以是 HEVC 帧内编码,也可以是 AVC,标准的容器还能装别的编码器;同样是 .tif,可以是完全未压缩的位图,也可以是 LZW、PackBits、Deflate 或 JPEG 压出来的;.webp 这个后缀底下藏着三种东西——有损的 VP8、无损的 VP8L,以及用来描述动画/透明/元数据的扩展块 VP8X。
所以在术语上得分两层:
| 层 | 名称 | 职责 | 例子 |
|---|---|---|---|
| 外层 | 容器 / 文件格式(container, file format) | 组织元数据、色彩信息、多帧、多分辨率、alpha、EXIF/XMP;定义魔数与块结构 | BMP、GIF、PNG、TIFF、JP2、RIFF(WebP)、ISOBMFF(HEIF/AVIF)、OpenEXR、ICO |
| 内层 | 压缩格式 / 编解码器(codec, compression scheme) | 真正把像素变成比特流:变换、预测、量化、熵编码 | LZW、DEFLATE、PackBits、RLE、JPEG(DCT+Huffman)、JPEG 2000(小波+MQ)、VP8/VP8L、AV1、HEVC、VarDCT/Modular |
搞混这两层的后果很实际:看到工具报「不支持 .heic」,多半是不支持里面的 HEVC 解码而不是容器解析不了;说「PNG 是无损格式」,严格讲是PNG 容器只能用 DEFLATE 做无损压缩(PNG 规范里压缩方法字段只定义了 0 = deflate),而不是 PNG 这个后缀决定了无损。
有一类格式干脆没有容器:JPEG 2000 的裸码流(J2K/J2C)就是纯编码数据,套上 JP2 盒子才是完整文件;JPEG 的 .jpg 严格说也是「裸 bitstream + JFIF/EXIF 这样的外壳约定」——JFIF 本身是在官方文件格式出现之前先流行起来的事实标准(美国国会图书馆格式档案里就是这么描述的)。
二、位图的六个基本变量
后面每个格式的差异,基本都能归结到这六个变量上。
① 分辨率与像素网格。 位图是二维采样:宽 × 高 × 每通道位数。矢量图(SVG、EPS)存的是几何描述,放大不糊,代价是不适合照片——这篇文章讲的压缩格式几乎全是为位图服务的。
② 位深(每通道位数)。 常见 1(黑白)、2、4、8、10、12、16 位整数,以及 16/32 位浮点(EXR 的 HALF/FLOAT)。位深决定渐变会不会出现「色阶断层」:8 位每通道 256 级,做天空渐变容易出条带;10 位是 1024 级,HDR 与宽色域内容的起点。
③ 通道与 alpha。 灰度、灰度+alpha、RGB、RGBA 是最常见的组合。透明有三种形态,别混:GIF 的1 位透明(只有一个索引值被标成透明,边缘是硬的)、PNG 的 8/16 位 alpha 通道、以及「有损 RGB + 单独一套 alpha 平面」的 WebP/AVIF 方案。JPEG 本身没有 alpha,.jpg 要透明只能另开文件。
④ 调色板(索引色)。 GIF 与 PNG-8 把颜色存成「索引 → 调色板条目」,最多 256 色。照片上这招必然失真,但界面截图、图标、纯色图形能压得很小。GIF 规范里那句「所有 256 个字符码都必须能传输」,说的就是 8 位调色板数据流的基本假设。
⑤ 色彩空间与色彩管理。 像素值本身不带颜色含义,要有 sRGB / Display P3 / Rec.2020 这类定义,或者嵌入 ICC profile。JPEG 的 JFIF 把 YCbCr + sRGB 定成默认,EXIF/ICC 携带更多信息;HEIF/AVIF 把 ICC 与 HDR 元数据都进了容器。
⑥ 扫描顺序。 从上到下逐行,还是隔行/渐进。这直接影响首屏体验:GIF 的隔行、PNG 的 Adam7、JPEG 的渐进式,都是先给一张模糊的整图,再逐轮补细节。
三、无损格式逐个说
BMP:还在服役的老古董
Windows 位图,前两个字节固定是 BM(OS/2 时代还出现过 BA、CI、IC、CP、PT)。它的问题是「太老实」:国会图书馆的格式档案里对 BMP 5 的描述是——虽然支持压缩,但大多数 BMP 图像根本没有压缩;而且没有嵌入元数据的能力,头部只有渲染图像所必需的技术信息。文件头来自微软的 BITMAPFILEHEADER / BITMAPCOREHEADER 结构。
所以 BMP 的用途基本只剩下:Windows 里的临时位图、某些老程序写死的输入格式、以及「先存个不折腾的格式再说」。
PNG:为替代 GIF 而生,规范到今天还在更新
PNG 1.0 由独立的 PNG 开发组制定,1996 年 10 月 1 日由 W3C 发布——这是 W3C 的第一个 Recommendation;1997 年 1 月 15 日又以 RFC 2083 的形式由 IETF 发布,1998 年 12 月 31 日更新到 1.1 版(加入了跨平台颜色等新块)。今天的权威文本是 W3C 的 PNG Specification (Third Edition)。
几个必须记住的点:
- 魔数是 8 字节:
89 50 4E 47 0D 0A 1A 0A。这串字节设计得很讲究,高位置 1 可以检测出「文本模式传输把高位吃掉了」这类老问题。 - 只有一种压缩方法:DEFLATE(也就是 zlib 包着 LZ77 + Huffman)。规范里写了压缩方法字段,但只定义了 0 = deflate。
- 压缩前先做逐行滤波:每行前面有一个滤波类型字节,参与压缩但不属于图像数据。五种滤波(None / Sub / Up / Average / Paeth)是 PNG 相对 GIF 在同一张图上榨出体积的关键之一。
- 隔行是 Adam7:七趟扫描,先粗后细。
- 颜色类型与位深是组合:灰度、真彩、索引色、灰度+alpha、真彩+alpha,索引色还可配 1/2/4/8 位。
tRNS块在灰度/真彩上提供单色透明,而在灰度+alpha、真彩+alpha 上被禁止——因为已经有完整 alpha 通道了。 - APNG 已经转正:2022 年被合并进 PNG 规范;第三版明确声明
image/png与image/apng两个媒体类型。
PNG 为什么是截图首选:它的滤波 + DEFLATE 对「大片同色 + 规则线条」的图形极其有效,而且完全无损、没有专利问题(国会图书馆对 PNG 的许可标注是 None)。
GIF:LZW 撑起来的动图帝国
CompuServe 1987 年推出 GIF,目的是给自家文件下载区提供一个彩色图像格式,用来替代它更早的、只支持黑白的 RLE 格式。它流行起来的原因是用了 LZW——比 PCX、MacPaint 那类 RLE 效率高得多。
格式本身的限制很硬:调色板最多 256 色,透明只有 1 位(Graphic Control Extension 里的 Transparent Color Index),动画帧延迟以 1/100 秒为单位(Delay Time 字段,"hundredths (1/100) of a second"),隔行是四趟扫描。魔数 GIF89a(87a 是更早版本)。
真正把 GIF 推上风口浪尖的是专利:1994 年 Unisys 开始就 LZW 收取授权费,这件事在当年引发了著名的「Burn All GIFs」运动。国会图书馆的 TIFF 条目里对此有一句总结:LZW 专利通常被认为在美国于 2003 年到期、在欧洲和日本于 2004 年到期。今天 GIF 已无专利障碍,但技术上的劣势(256 色、1 位透明、体积)让它在长动图场景里被 WebP/AVIF 挤掉不少。
TIFF:标签驱动的万能容器
TIFF 是 Aldus 联合 Microsoft 为 PostScript 打印做的格式,1986 年出了第一版规范(很多人把那一版称作 "version 3"),其中就包含推动桌面扫描仪生态的动机;1988 年 10 月的 5.0 版加入了调色板彩色与 LZW 压缩。被广泛引用的 6.0 版定稿于 1992 年 6 月 3 日。
它的结构是一棵树状的「标签」:每个标签有编号、类型、值。压缩就是一个标签:
| Compression tag 值 | 含义 |
|---|---|
| 1 | 不压缩 |
| 2 | CCITT Group 3 一维 Modified Huffman 行程编码 |
| 5 | LZW |
| 6 / 7 | 老式 JPEG / 新式 JPEG |
| 32773 | PackBits,一种简单的面向字节的行程编码 |
规范还专门定义了 Predictor(tag 317):在压缩前先对像素做差分,显著改善某些图像的压缩率——思路和 PNG 的滤波、WebP 无损的预测变换是一脉相承的。
TIFF 能活到今天的原因是它什么都能装:无损(LZW/Deflate/PackBits)、有损(JPEG)、CMYK、多页、多分辨率金字塔、浮点、BigTIFF 突破 4GB 限制。博物馆、图书馆、印刷厂的归档主文件基本都选它。代价是解析器复杂、互操作坑多——同一个 .tif 换个软件就可能读不出来。
TGA 与 PCX:RLE 时代的两兄弟
1990 年代的绘图与游戏生态里,这两个是常客。它们都建立在行程编码(RLE)上:连续相同的像素用「重复次数 + 像素值」表示。RLE 对纯色块、渐变线稿很有效,对照片几乎无效(相邻像素很少完全相同)。
TGA(Truevision)2.0 版支持 alpha 通道,游戏里当贴图用过很久;PCX 更老,是早期 DOS 绘图程序的事实格式。国会图书馆对这两者都有单独的格式描述条目。
PNM / farbfeld:极简到可以当脚本的中间格式
Netpbm 家族的 PBM/PGM/PPM/PAM 是「可读的」位图格式:头部是 ASCII 文本(P6 表示二进制真彩,后面跟宽、高、最大像素值),后面直接跟原始像素字节。它的价值不在省空间,而在当管道里的中间格式——pngtopnm | pnmscale | pnmtopng 这种老式命令行流水线至今还能跑。
farbfeld 是 suckless 出的同类东西,官方描述是「一种易于解析、易于管道处理、易于压缩的无损图像格式」,16 位 RGBA、固定头,总共不到一页规范。
QOI:2021 年的「够用就好」
QOI(Quite OK Image Format)是 2021 年 11 月由 Dominic Szablewski 发布的,设计目标单一:O(n) 时间、几十行代码就能实现。文件结构是 14 字节头 + 若干数据块 + 8 字节结束标记,魔数是 qoif。
它的取舍非常坦率:体积和 PNG 差不多,但压缩快 20~50 倍、解压快 3~4 倍,且实现复杂度极低。代价是压缩率上限明显低于 PNG(不能和 WebP 无损、JXL 比),适合游戏运行时资产、构建管线里的中间格式这类「CPU 时间比磁盘空间贵」的场景。
ICO / CUR:一个容器装多个尺寸
Windows 图标文件不是一种图像编码,而是多张图的打包:ICONDIR 后跟 ICONDIRENTRY 数组,每项指向一张 16×16、32×32、256×256 之类的图像,每张可以是 DIB(带 AND/XOR 掩码的老式位图)或者一个完整的 PNG。
历史上:Windows 3.0 引入图标格式,Windows 95 支持更大尺寸和更高色深,Windows Vista 加入 256×256 与 PNG 压缩。所以一个现代 .ico 里往往同时躺着未压缩的 16×16(保证兼容性)和 PNG 压过的 256×256(控制体积)。
OpenEXR:为电影后期设计的高动态范围格式
OpenEXR 是工业光魔的格式,现在由 Academy Software Foundation 维护。它的定位很明确:HDR、多通道(深度、法线、运动矢量都能各占一路通道)、half-float(16 位浮点)与 32 位浮点。
压缩方式可挑,官方技术文档里列得很清楚:
| 方法 | 类型 | 特点 |
|---|---|---|
| NONE / RLE / ZIPS / ZIP | 无损 | ZIP 系按扫描线块做,ZIPS 块更小 |
| PIZ | 无损 | 小波式,适合噪点少的高动态范围图 |
| PXR24 | 有损(部分) | HALF/UINT 通道精确无损,FLOAT 数据的相对误差约 3×10⁻⁵;适合深度缓冲 |
| B44 / B44A | 有损 | HALF 通道按 4×4 像素(32 字节)分块,每块打包成 14 字节,压到原始大小的 44%;B44A 在有大片均匀区域时更小 |
| DWAA / DWAB | 有损 | 对 RGB 做 DCT 分量量化,分别按 32 / 256 扫描线分块;DWAB 体积更小、整帧解码更快 |
| HTJ2K32 / HTJ2K256 | 无损 | 用 JPEG 2000 Part 15(High-throughput JPEG 2000,ITU-T T.814)压缩 HALF/FLOAT/UINT |
EXR 还有按层存多分辨率(每级宽高各减半)的能力,这是「同一张图给不同精度」的标准做法。
相机 RAW 与 DNG:不是一种格式,是一堆格式
各家相机的 RAW(CR2/CR3、NEF、ARW、RAF……)本质上是传感器原始数据 + 厂商私有结构,很多基于 TIFF/EP(TIFF 的一个扩展)但互不兼容,因为里面写了各家自己的传感器校正信息。Adobe 的 DNG 想做统一封装,Apple 的 ProRAW 是另一条路。国会图书馆把它们归到 CAM_RAW / DNG / Apple_ProRAW 三个条目里——注意这已经不只是「图像格式」,而是「成像数据 + 处理参数」。
SVG 顺带说一句
SVG 是矢量格式,不是压缩格式:文件是 XML 文本,体积取决于路径描述的复杂度,压缩靠 HTTP 层的 gzip/brotli(.svgz 就是 gzip 后的 SVG)。它能无损缩放,但照片没法「矢量化」而不丢东西。
四、有损格式逐个说
JPEG:三十年不倒的基线
JPEG 的核心标准是 ISO/IEC 10918-1(1994)= ITU-T Rec. T.81(1992),流程是:色彩空间转 YCbCr → 8×8 分块 DCT → 量化 → Zigzag 扫描 → Huffman(或算术)编码。
几个容易踩坑的点:
- baseline 与 progressive 是同一标准里的两种编码档位,靠 SOF 标记区分:baseline 用
FF C0,progressive 用FF C2。渐进式把系数分成多轮发送,首屏体验更好,体积通常差不多。浏览器都懂,但某些老工具只写 baseline。 - 色度子采样是体积的大头。4:2:0 表示色度平面宽高各减半(色度样本数是亮度的 1/4),人眼对色度不敏感,所以画质损失很小、体积省很多;要抠图和纯色边缘的内容就该用 4:4:4。
- 算术编码在标准里是可选的,当年因为专利顾虑,编码端普遍只实现 Huffman,这也是「JPEG 有压缩率天花板」的原因之一。
.jpg里的元数据经常比图像还重要:JFIF(魔数FF D8 FF E0 ... JFIF)定义基本的色彩与密度信息,EXIF(FF D8 FF E1 ... Exif)装相机参数、GPS、方向。JFIF 在官方文件格式出现前先流行,直接成了事实标准——这也是为什么最早的一批 JPEG 文件严格来说「不是标准格式,是 JFIF」。- 专利风波:2002 年 Forgent Networks 发起诉讼,2006 年被美国专利商标局判定专利无效;2007 年起 Global Patent Holdings 的另一批主张在 2009 年被驳回。今天 JPEG 可以放心用。
JPEG-LS:为无损/近无损专门做的标准
JPEG-LS(ISO/IEC 14495-1 = ITU-T T.87)和上面那个 JPEG 完全是两套东西。它的算法叫 LOCO-I(HP Labs 技术报告 HPL-98-193,1998 年 11 月),核心是 MED 中值边缘预测器加上针对平坦区域的 run 模式,再用 Golomb 码编码预测残差——不做 DCT,复杂度低到能塞进扫描仪固件。
它有个别的格式少见的模式:近无损(near-lossless),允许编码器设定最大绝对误差上限,在「必须保证误差不超过 N 个灰阶」的医学/遥感场景里非常合适。SOF 标记是 FF F7(JHOVE 记为 JPG7/SOF55)与 FF F9。
JPEG 2000:小波 + 可分级
JPEG 2000 的核心编码系统是 ISO/IEC 15444-1,用离散小波变换取代 DCT,熵编码用 EBCOT + MQ 算术编码器。相比 JPEG 的关键优势不是「同画质更小」这么简单,而是:
- 有损无损同一套框架:可逆的 5/3 小波给出数学无损;不可逆的 9-7 小波给出有损(HEIC 的格式档案在横向对比各编码器时,就点明 JPEG 2000 有损用的是「不可逆的浮点 9-7 小波变换」)。
- 一次压缩、多种用法:码流按分辨率与质量分层,可以只解出低分辨率缩略图,也可以只取某个 ROI(感兴趣区域)。
- 容器与码流分离:
.j2k/.j2c是裸码流,.jp2是带色彩与元数据的完整文件(魔数里含ftyp jp2的盒子结构)。
它的代价是计算复杂、生态工具少,所以在医学影像(DICOM)与数字影院这类「标准强制」的领域活得很好,在网页上基本没戏。
JPEG XR:微软 HD Photo 的转正
JPEG XR 的前身是微软的 HD Photo。2007 年 7 月微软宣布把它提交 JPEG 标准化,暂名 JPEG XR;首发标准是 ITU-T T.832 / ISO/IEC 29199-2(2009)。技术上它用 lapped transform(重叠变换),一个块跨到相邻块,减少了 DCT 那种块边界伪影,同时支持无损和有损。
它没能流行起来,但许可条件其实很好:微软当年承诺「对实现该标准所需的专利提供免版税授权」,2010 年 8 月起纳入 Microsoft Community Promise。
WebP:Google 给 Web 的折中答案
WebP 最初是 On2 Technologies 的私有格式,Google 在 2010 年收购 On2 之后把它开放出来。它不是一个编码器,而是三种:
| 结构 | 用途 | 说明 |
|---|---|---|
VP8 |
有损 | 复用 VP8 视频帧内编码,块尺寸 4×4~16×16,支持 alpha(单独一套 alpha 平面) |
VP8L |
无损 | 色变换 + 预测 + LZ77 + 颜色缓存 + 前缀码 |
VP8X |
扩展 | 标记动画、alpha、ICC/EXIF/XMP 的存在,文件仍是 RIFF 容器(魔数 RIFF....WEBPVP8) |
Google 官方给出的数字是:无损 WebP 比 PNG 小 26%;有损 WebP 在相同 SSIM 质量指数下比 JPEG 小 25%~34%;无损模式下带透明只多花 22% 的字节;动图比 GIF/APNG 更小且同时支持有损、无损、透明。
无损部分的实现细节可以在 RFC 9649(WebP 无损比特流,2024 年成为 IETF 文档)里逐条看到:变换阶段有 Predictor Transform、Color Transform、Subtract Green、Color Indexing,图像数据用前缀码字面量 + LZ77 反向引用 + 颜色缓存,收尾用前缀码(Huffman 系)做熵编码。这是「一种容器、三种算法」最典型的例子。
AVIF:AV1 帧内 + ISOBMFF
AV1 编解码器 2018 年 3 月正式发布,2018 年 9 月就有了 AVIF 规范的第一版(aomediacodec.github.io/av1-avif)。它把 AV1 的帧内编码装进 ISOBMFF(就是 MP4 那一套盒子结构),品牌是 avif(静态)和 avis(序列/动画)。
能力上:8/10/12 位、HDR 与宽色域、alpha、动画、无损模式,ICC/EXIF/XMP 都能带。授权条件是它的一个大卖点——国会图书馆的条目写着 AVIF 免版税(royalty free),以 BSD 2-Clause 许可。
效果上的公开数字:AOMedia 称动画 AVIF 平均比原始 GIF 小 78%;Netflix 在博客里说 AVIF 编码「即使体积只有 JPEG 编码的三分之一,看起来也更干净」。浏览器侧 Chrome 85+、Edge 118+ 已支持。
HEIF / HEIC:容器与编码器分离的教科书案例
HEIF 就是 ISO/IEC 23008-12(MPEG-H Part 12)。它基于 2001 年定下的 ISO Base Media File Format(MP4 与 JPEG 2000 共享的那部分),2013 年前后开始制定,规范 2017 年首次发布;苹果同年在 iOS 11 里启用 HEIC 作为相机默认格式。
关键点在于:HEIF 只规定容器,编码器可以是 HEVC(H.265)、AVC(H.264),标准还允许 VP8/VP9、JPEG 2000、JPEG XR、WebP 等;heic/heix 这些品牌指的是「这个文件里用的是 HEVC 帧内编码」。HEVC 规范 2013 年首发,2014 年的更新专门加了面向静态图的 profile(更高位深、宽色域)。
真正的麻烦是钱:国会图书馆直接写道,底层的 HEVC 编码「heavily encumbered with patents」,按 HEVC Advance 2020 年 3 月的新闻稿,相关专利约 17000 项,且有多个专利池分别授权。这解释了一个日常现象:Windows 和部分桌面软件要么不读 .heic,要么得额外装解码包。
JPEG XL:目前技术上最强,命运最曲折
JPEG 委员会 2018 年启动「下一代图像压缩」活动,正式名 JPEG XL,目标是比 JPEG 小 60% 以上,同时解决 JPEG 三十年积累的功能债。标准是 ISO/IEC 18181,参考实现 Apache 2.0 许可。
按官方白皮书,它有两种编码模式:
- VarDCT:面向照片的有损模式(8×8 及可变尺寸变换块),强调人眼感知;也可用于无损转码已有 JPEG。
- Modular:数学无损模式,或通用的有损模式;VarDCT 的 LF 层与颜色相关控制字段也用 Modular 存。
白皮书给出的性能数字很有说服力:
- 无损 JPEG 转码能把 JPEG 体积减小约 16%~22%(也就是说,把现有
.jpg换成.jxl,画质不变、体积直接少两成)。这是别的格式做不到的——AVIF/WebP 都得重新编码、必然有损。 - 从像素做无损压缩,8 位图比优化过的 PNG 小约 35%。
- 熵编码支持 ANS(Asymmetric Numeral Systems) 与 Huffman 两种,且带 LZ77。
- 支持渐进解码(按分辨率与精度)、动画、alpha、图层、缩略图、宽色域与 HDR。
浏览器支持是它最大的坎:Chrome 曾在 2022 年短暂上线后又移除 JPEG XL,此后三年一直是「标准很好、生态卡住」的典型;到 Chrome 145,JPEG XL 又回到了浏览器里。所以今天写前端,JXL 的正确用法是当作增益选项:<picture> 里放 <source type="image/jxl">,让支持的浏览器吃掉它,其余回落到 WebP/JPEG。
JPEG XS:为「几乎无损 + 极低延迟」而生
JPEG XS(ISO/IEC 21122)的目标和上面所有格式都不一样:它不要高压缩比,只要 2:1 到 6:1,换来的是极低延迟与浅帧内(每帧独立、几行即可开始编码/解码),而且能跑在 FPGA/低功耗芯片上。
用途因此很明确:专业视频链路的中间传输(SDI over IP、ST 2110)、远程制作、影院母版链路。文件魔数是 00 00 00 0C 4A 58 53 20 0D 0A 87 0A,元数据(色空间、mastering display metadata、EXIF)由 ISO/IEC 21122-3 定义。
JPEG XT:HDR 时代的补丁
JPEG XT 的标准是 ISO/IEC 18477(分九个部分,官方全称是 "Scalable compression and coding of continuous-tone still images"),想解决的是「如何让 HDR 图像在 JPEG 生态里兼容地表示」:把基础层做成普通 JPEG(老软件照样能看),扩展层携带 HDR 残差(ISO/IEC 18477-7 定义了三种重建 HDR 的算法档位)。它在 HDR 显示普及前是有意义的过渡方案,如今被 JXL/AVIF 的原生 HDR 支持盖过。
五、容器 → 可用编码器 对照表
把这一层理清,工具报错时才知道该查什么。下表「编码器」列的是该容器/后缀实际会用到的压缩方式。
| 文件格式(容器) | 典型扩展名 | 可用的压缩/编码 | 有损? | alpha | 动画 |
|---|---|---|---|---|---|
| BMP | .bmp、.dib |
无压缩、RLE8/RLE4、BITFIELDS | 否 | 有(32 位) | 否 |
| GIF | .gif |
LZW | 否(但限 256 色) | 1 位 | 是 |
| PNG | .png、.apng |
DEFLATE(+ 5 种滤波、Adam7) | 否 | 8/16 位 | APNG |
| TIFF | .tif、.tiff |
无、CCITT G3/G4、PackBits、LZW、Deflate、JPEG | 都可以 | 有 | 多页(非动画) |
| TGA | .tga |
无、RLE | 否 | 有 | 否 |
| PCX | .pcx |
RLE | 否 | 有(1 位) | 否 |
| PNM/PAM | .pbm/.pgm/.ppm/.pam |
无(可整文件 gzip) | 否 | PAM 有 | 否 |
| farbfeld | .ff |
无(设计上交给管道压缩) | 否 | 有(16 位) | 否 |
| QOI | .qoi |
QOI 自有算法(O(n) 行程/差分/索引) | 否 | 有 | 否 |
| ICO/CUR | .ico、.cur |
DIB(可 RLE)+ 内嵌 PNG | 混合 | 有(1 位/PNG) | 否 |
| OpenEXR | .exr |
ZIP/ZIPS/PIZ/PXR24/B44/DWA/HTJ2K | 都有 | 有 | 序列 |
| HEIF/HEIC | .heic、.heif、.avif |
HEVC、AVC,规范还允许 VP8/VP9、JPEG 2000、JPEG XR、WebP;AVIF 品牌固定用 AV1 | 都有 | 有 | 是 |
| JPEG | .jpg、.jpeg |
DCT + Huffman/算术;baseline/progressive;容器侧 JFIF、EXIF、SPIFF | 是(JPEG-LS 例外) | 无 | 否 |
| JPEG 2000 | .jp2、.j2k、.j2c、.jpx |
小波 + EBCOT/MQ | 都有 | 有 | 是(.mj2) |
| JPEG XR | .jxr、.wdp |
lapped transform | 都有 | 有 | 否 |
| JPEG XL | .jxl |
VarDCT(有损,可无损转码 JPEG)、Modular(数学无损) | 都有 | 有 | 是 |
| JPEG XS | .jxs |
浅帧内小波/DCT 混合,2:1~6:1 | 是(近无损) | 有 | 序列 |
| SVG | .svg、.svgz |
文本 + gzip(.svgz) |
否 | 有 | 是 |
六、压缩格式到底怎么压
所有图像压缩,拆开看都是「减少冗余的手段 → 熵编码收尾」。区别只在用了哪几种减少冗余的手段。
6.1 熵编码:把统计规律换成更短的码字
熵编码是无损压缩的收尾环节,前面无论是 DCT 系数还是预测残差,最终都要变成比特流。
- Huffman / 前缀码:用整数个比特表示符号,高频符号短、低频长。JPEG baseline 必须支持它;WebP 无损的收尾同样是前缀码(RFC 9649 里叫 Prefix Codes);DEFLATE 的另一半就是 Huffman。
- 算术编码 / 区间编码:用分数比特逼近理论熵,通常比 Huffman 再省几个百分点。JPEG 标准里有它,但因为早期专利顾虑,编码端普遍不用;JPEG 2000 用的是 MQ 算术编码器(EBCOT 的一部分)。
- ANS(Asymmetric Numeral Systems):算术编码的现代变体,接近算术编码的压缩率、接近 Huffman 的速度。JPEG XL 明确支持 ANS 与 Huffman 两种(白皮书原文:"Entropy coding is LZ77-enabled and can use both Asymmetric Numeral Systems and Huffman")。
- Golomb 码:为几何分布残差设计的简单变长码,JPEG-LS 用它编码 MED 预测的残差。
- LZ77/LZ78/LZW:字典式压缩,把「之前出现过的字节串」用「距离 + 长度」代替。DEFLATE = LZ77 + Huffman;GIF 与 TIFF-LZW 用 LZW;WebP 无损里的「LZ77 反向引用」也是同一思路,专门用来消除图像的重复纹理。
6.2 变换:把空间相关变成频域稀疏
DCT(离散余弦变换)是主流。JPEG 把图切成 8×8 块做 DCT,能量集中到低频少数系数上,高频系数大量接近零,量化后容易压。代价是块边界会出现「块效应」,低码率下尤其明显。WebP 有损走的 VP8 帧内编码用 4×4 到 16×16 的块;HEVC/AV1(也就是 HEIC/AVIF 的内核)用的是更大、更灵活的块划分,加上方向性预测,效率比老 JPEG 高一大截。
小波变换用在 JPEG 2000:5/3 可逆小波对应数学无损,9/7 不可逆小波对应有损。它不做块划分,所以低码率时不是块效应而是整体变模糊,且天然支持按分辨率分层解码。
Lapped transform(重叠变换)是 JPEG XR 的选择:每个块跨到相邻块,牺牲一点复杂度换来更少的块边界伪影。
VarDCT 是 JPEG XL 对传统 DCT 的现代化改造:变换块尺寸可变,配合感知量化;同时它还保留了 Modular 这条纯整数路径做无损。
6.3 预测:用邻居猜自己,只存误差
这类手段对「平滑、渐变、大片同色」的图像特别有效,而且完全无损。
- PNG 的逐行滤波:每行像素在压缩前,先减去左边(Sub)、上边(Up)、两者的平均(Average)或 Paeth 预测值,选最优的那种并把类型写在行首。
- TIFF 的 Predictor(tag 317):官方规范里写着「显著改善某些图像的压缩率」,思路就是先差分再压缩。
- WebP 无损的 Predictor Transform:在像素预测之外,还能做颜色变换、Subtract Green、颜色索引化(RFC 9649 的 3.5 节把这些变换逐个定义)。
- JPEG-LS 的 MED 中值边缘预测器:在边缘处按梯度选预测方向,在平坦区走 run 模式,这是 LOCO-I 算法的核心。
6.4 调色板量化:256 色的取舍
GIF 与 PNG-8 把真彩量化到最多 256 个调色板条目,再用索引存像素,体积能压得很小。代价是照片出现色带,需要用抖动(dithering)把误差打散成噪点来掩盖——这也是老 GIF 照片那种颗粒感的来源。
6.5 色度子采样:砍掉人眼不敏感的部分
人眼对亮度分辨率敏感、对色度分辨率迟钝,所以先把 RGB 转成 Y'CbCr,再降低色度平面的采样率:
| 采样 | 含义 | 相对数据量 |
|---|---|---|
| 4:4:4 | 色度不抽样 | 100% |
| 4:2:2 | 水平方向色度减半 | 色度 50% |
| 4:2:0 | 水平与垂直都减半 | 色度 25% |
JPEG 默认多半是 4:2:0。要注意的是它不是无损:红字、纯色边缘、需要抠图的素材上,4:2:0 会带来明显的色彩渗出,这类内容应该用 4:4:4,或者干脆换成 PNG/WebP 无损。
6.6 量化与「质量」到底指什么
量化的本质是「除以一个步长再取整」,是 JPEG 系有损压缩真正丢信息的地方。质量参数(-q 80、quality=85)只是映射到量化表的快捷方式,同一数字在不同编码器里含义并不相同。
所以比较压缩效果时不能靠肉眼,要用指标:
- SSIM 是比较常用的结构相似度指标。Google 官方给出的 WebP 对比数据就是「在相同 SSIM 质量指数下比 JPEG 小 25%~34%」,可以看出厂商自己也用指标来对齐。
- 感知类指标(如 butteraugli / SSIMULACRA2 这类)被现代编码器用来做「感知优化」的目标函数,JPEG XL 白皮书把「perceptually optimized reference」列为设计目标之一。
实践建议:同一张图、同一指标、同一目标分数下比体积;换指标或换目标分数,结论就会变。
6.7 渐进、隔行与首屏
- JPEG progressive 把系数分多轮发送,浏览器先渲染低频,用户先看到整体轮廓。SOF 标记
FF C2(baseline 是FF C0)。 - PNG Adam7 把图像分成 7 趟,按 1/64 → 1/32 → … → 1/1 的密度补完。
- GIF 隔行是四趟扫描(规范附录 E)。
- JPEG XL 支持按分辨率与精度渐进解码,理论上同一份码流能直接服务缩略图与全尺寸。
6.8 alpha 怎么压
- GIF:1 位透明,边缘是硬的。
- PNG:完整 alpha 通道,跟着 DEFLATE 一起无损压。
- WebP:有损模式把 alpha 单独存成一路(可以有损或无损处理),官方称无损支持下带透明只多 22% 字节。
- AVIF/HEIF/JXL:alpha 作为独立通道或独立图像项编码,HDR 与宽色域元数据同样在容器里。
6.9 元数据与色彩管理:不能只看像素
JPEG 的 EXIF 里装着拍摄参数、方向、GPS;ICC profile 决定像素值该显示成什么颜色;XMP 装着编辑历史。压缩工具经常默认剥掉这些(--strip 类选项),批量处理素材前务必确认:方向标记没了,照片就会横过来;ICC 没了,颜色就会偏。
七、怎么选:按场景的决策表
| 场景 | 首选 | 备选 | 理由 |
|---|---|---|---|
| 摄影作品、网页大图 | AVIF | WebP、JPEG(兼容兜底) | 同质量下体积最小,浏览器支持已铺开 |
| 需要「画质不变、体积变小」的存量 JPEG | JPEG XL 无损转码 | — | 官方数据:体积减 16%~22%,画质零损失 |
| 界面截图、图表、带文字的图 | PNG | WebP 无损、JXL Modular | 无损 + 滤波/DEFLATE 对规则图形效率高,文字不糊 |
| 图标、favicon | PNG / ICO(多尺寸) | WebP | 需要 alpha 与无损,且要兼容老浏览器 |
| 动图 | AVIF / WebP | GIF(兼容) | AOMedia 实测动画 AVIF 平均比 GIF 小 78% |
| 需要透明背景的摄影图 | WebP 有损 + alpha / AVIF | PNG(体积大) | JPEG 没有 alpha,PNG 太占空间 |
| HDR / 宽色域 / 10 位以上 | AVIF、JPEG XL | HEIC(苹果生态) | 原生 10/12 位与 HDR 元数据 |
| 电影后期、多通道中间格式 | OpenEXR | DPX、TIFF | half/float、多通道、可选无损或有损 |
| 印刷与档案归档主文件 | TIFF(无损) | PNG、JPEG 2000 | 无损、标签可扩展、生态广 |
| 医学影像、遥感 | JPEG 2000、JPEG-LS | PNG | 可分级 + 无损/近无损 + 误差上限可指定 |
| 专业视频链路传输 | JPEG XS | 无压缩 | 低延迟、浅帧内、2:1~6:1 |
| 运行时资产、构建管线中间格式 | QOI | PNG | O(n) 编解码,速度快 1~2 个数量级 |
三个常见误区:
- 「无损就一定大」。 不一定。PNG 的无损对界面截图很小,而 JPEG 对截图反而又大又糊(DCT 对锐利边缘最不友好)。
- 「换成新格式一定更小」。 取决于内容和参数。同一张照片,JPEG 用 4:4:4 高质量重存可能比 WebP 默认参数还大。要比就同指标比。
- 「文件名后缀代表压缩方式」。
.heic里不一定是 HEVC,.webp里可能是无损也可能是 VP8 有损——判断压缩方式要看码流结构(magic + 块类型),不只看后缀。
八、命令行实战:识别、转码、验体积
以下命令都属于常见发行版仓库或官方工具链,参数以其官方文档为准。
先认清手里的是什么(file 读魔数库,比看后缀可靠):
file -i icon.ico shot.heic pic.webp # MIME + 类型判断
magick identify -verbose pic.webp | head -30 # 位深/色彩空间/压缩类型/alpha
exiftool -s -FileType -Compression -BitsPerSample pic.tif转码与优化(下面的命令各做一件事,注意不要在没备份时覆盖原图):
# PNG 无损优化(找最优滤波/zlib 参数)
oxipng -o 4 --strip safe shot.png
# PNG 有损量化(256 色),比 oxipng 激进得多
pngquant --quality=70-90 shot.png
# 转 WebP:有损与无损两条路
cwebp -q 80 shot.png -o shot.webp # 有损
cwebp -lossless -z 9 shot.png -o shot-lossless.webp
# 转 AVIF(libavif 官方的 avifenc)
avifenc -q 60 --jobs all shot.png shot.avif
avifenc --lossless shot.png shot-lossless.avif
# 转 JPEG XL(libjxl 的 cjxl;无损转码存量 JPEG 用 -j 0 等参数见官方文档)
cjxl shot.png shot.jxl -d 1
cjxl existing.jpg existing.jxl # 无损重压 JPEG(体积可减 16%~22%)
# ImageMagick 一把梭(依赖上面这些库是否编进 delegate)
magick shot.png -quality 82 shot.avif比体积、比画质(把「感觉小了」变成数字):
ls -l shot.png shot.webp shot.avif
magick compare -metric SSIM shot.png shot.webp null: 2>&1 # 结构相似度,越接近 1 越好
magick compare -metric PSNR shot.png shot.webp null: 2>&1 # 数值越高越接近一个容易忽略的动作:确认元数据还在。批量转换后抽查 EXIF/ICC:
exiftool -a -G1 -s shot-original.jpg | grep -iE 'icc|profile|exif'
exiftool -a -G1 -s shot.avif | grep -iE 'icc|profile|exif'九、Windows 批量转换脚本(不需要管理员权限)
下面两个脚本做同一件事:把指定目录里的 PNG/JPG 批量转成 WebP 与 AVIF,保留原图、逐文件容错、结尾打印体积对比。之所以不做管理员权限检查——转换图片不需要管理员权限,硬要提权反而会带来不必要的风险;脚本需要的是「对应的命令行工具在 PATH 里」,所以第一步就是检测工具。
工具来源(任选其一即可):Google 的 libwebp(cwebp.exe)、libavif 的 avifenc、或 ImageMagick 的 magick.exe。用 winget/scoop 装也行,脚本只检查能不能调用。
9.1 PowerShell 版(convert-to-webp.ps1)
<#
批量把 PNG/JPG 转成 WebP 与 AVIF。特点:
- 不改动原图,输出到 <源目录>\converted\
- 先检测外部工具,缺工具就明确报错并给出安装提示
- 逐文件 try/catch,单个失败不影响整批;结尾汇总成功/失败与体积对比
用法:
.\convert-to-webp.ps1 -SourceDir "D:\pics" -Quality 82
.\convert-to-webp.ps1 -SourceDir "D:\pics" -WhatIfOnly # 只列出会做什么
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)][string]$SourceDir,
[ValidateRange(1, 100)][int]$Quality = 82,
[switch]$WhatIfOnly
)
function Get-ToolPath([string]$Name) {
$c = Get-Command $Name -ErrorAction SilentlyContinue
if ($c) { return $c.Source }
return $null
}
$cwebp = Get-ToolPath 'cwebp'
$avifenc = Get-ToolPath 'avifenc'
$magick = Get-ToolPath 'magick'
if (-not (Test-Path -LiteralPath $SourceDir)) {
Write-Host "❌ 目录不存在:$SourceDir" -ForegroundColor Red; exit 2
}
if (-not $cwebp -and -not $avifenc -and -not $magick) {
Write-Host "❌ 没找到任何转换工具。请先安装其中任意一个并确保在 PATH 中:" -ForegroundColor Red
Write-Host " - libwebp : https://developers.google.com/speed/webp/download"
Write-Host " - libavif : https://github.com/AOMediaCodec/libavif/releases"
Write-Host " - ImageMagick: https://imagemagick.org/script/download.php"
exit 3
}
$outDir = Join-Path $SourceDir 'converted'
if (-not $WhatIfOnly) { New-Item -ItemType Directory -Force -Path $outDir | Out-Null }
$files = Get-ChildItem -LiteralPath $SourceDir -File |
Where-Object { $_.Extension -match '^\.(png|jpe?g)$' -and $_.Name -ne 'converted' }
if (-not $files) { Write-Host "⚠️ 目录里没有 PNG/JPG 文件:$SourceDir"; exit 0 }
Write-Host ("发现 {0} 个文件,输出目录:{1}" -f $files.Count, $outDir)
$ok = 0; $fail = 0; $rows = @()
foreach ($f in $files) {
$base = [IO.Path]::GetFileNameWithoutExtension($f.Name)
if ($WhatIfOnly) { Write-Host (" [预览] {0} -> {1}.webp / {1}.avif" -f $f.Name, $base); continue }
$made = @()
# WebP
if ($cwebp) {
$out = Join-Path $outDir "$base.webp"
try { & $cwebp -quiet -q $Quality $f.FullName -o $out; if ($LASTEXITCODE -eq 0 -and (Test-Path $out)) { $made += $out } }
catch { Write-Host (" ⚠️ WebP 失败:{0}" -f $f.Name) -ForegroundColor Yellow }
} elseif ($magick) {
$out = Join-Path $outDir "$base.webp"
try { & $magick $f.FullName -quality $Quality $out; if (Test-Path $out) { $made += $out } }
catch { Write-Host (" ⚠️ WebP 失败:{0}" -f $f.Name) -ForegroundColor Yellow }
}
# AVIF
if ($avifenc) {
$out = Join-Path $outDir "$base.avif"
try { & $avifenc -q $Quality -j all $f.FullName $out | Out-Null; if ($LASTEXITCODE -eq 0 -and (Test-Path $out)) { $made += $out } }
catch { Write-Host (" ⚠️ AVIF 失败:{0}" -f $f.Name) -ForegroundColor Yellow }
}
if (-not $made) { $fail++; Write-Host (" ❌ 全部失败:{0}" -f $f.Name) -ForegroundColor Red; continue }
$ok++
foreach ($m in $made) {
$rows += [pscustomobject]@{
文件 = $f.Name
输出 = [IO.Path]::GetFileName($m)
原始KB = [math]::Round($f.Length / 1KB, 1)
新KB = [math]::Round((Get-Item $m).Length / 1KB, 1)
}
}
}
if (-not $WhatIfOnly) {
Write-Host "`n体积对比(越小越好):" -ForegroundColor Cyan
$rows | Format-Table -AutoSize | Out-String | Write-Host
Write-Host ("完成:成功 {0} 个文件,失败 {1} 个。原图未改动,新文件在 {2}" -f $ok, $fail, $outDir) -ForegroundColor Green
}9.2 批处理版(convert-to-webp.bat)
批处理没有异常处理,所以容错靠「每个文件先判断工具是否可用 + 判断输出文件是否真的生成」:
@echo off
setlocal enabledelayedexpansion
chcp 65001 >nul
rem 用法: convert-to-webp.bat "D:\pics" 82
if "%~1"=="" (
echo 用法: convert-to-webp.bat "图片目录" [质量1-100]
exit /b 2
)
set "SRC=%~1"
set "Q=%~2"
if "%Q%"=="" set "Q=82"
if not exist "%SRC%\" (
echo ❌ 目录不存在: %SRC%
exit /b 2
)
set "CWEBP="
where cwebp >nul 2>nul && set "CWEBP=cwebp"
if "%CWEBP%"=="" (
echo ❌ 没找到 cwebp.exe。请安装 libwebp 并加入 PATH:
echo https://developers.google.com/speed/webp/download
echo.
echo 提示:本脚本不做管理员权限检查 —— 转换图片不需要管理员权限。
exit /b 3
)
set "OUT=%SRC%\converted"
if not exist "%OUT%" mkdir "%OUT%"
set /a OK=0
set /a FAIL=0
for %%F in ("%SRC%\*.png" "%SRC%\*.jpg" "%SRC%\*.jpeg") do (
if exist "%%~fF" (
cwebp -quiet -q %Q% "%%~fF" -o "%OUT%\%%~nF.webp" >nul 2>nul
if exist "%OUT%\%%~nF.webp" (
for %%A in ("%%~fF") do set /a OLD=%%~zA/1024
for %%B in ("%OUT%\%%~nF.webp") do set /a NEW=%%~zB/1024
echo [OK] %%~nxF !OLD!KB -^> !NEW!KB
set /a OK+=1
) else (
echo [FAIL] %%~nxF 转换失败(原图已保留)
set /a FAIL+=1
)
)
)
echo.
echo 完成:成功 !OK! 个,失败 !FAIL! 个。原图未改动,新文件在 %OUT%
echo 抽查建议:随便打开一个 webp 看是否正常显示;有需要再删原图。
endlocal两个脚本都刻意做了三件事:先检测工具再动手(避免跑一半才发现 cwebp 不存在)、绝不覆盖原图(新文件进 converted\)、逐文件容错并汇总(一个失败不拖垮整批)。批量处理前建议先拿一个子目录试跑,确认体积与画质符合预期再全量执行。
十、参考资料
官方规范与权威文档(本文所有数字、年份、魔数均出自这些来源):
- W3C PNG Specification (Third Edition) —— PNG 现行规范,含 APNG 与
image/apng - RFC 2083: PNG (Portable Network Graphics) Specification Version 1.0 —— 滤波、颜色类型、DEFLATE、IDAT 的原始定义
- CompuServe GIF89a Specification —— LZW、调色板、透明索引、Delay Time(1/100 秒)、四趟隔行
- TIFF Revision 6.0(1992-06-03) —— Compression tag 取值、PackBits、Predictor(tag 317)、LZW 章节
- ITU-T Rec. T.81 / ISO/IEC 10918-1 —— JPEG 核心(DCT、量化、Huffman/算术、baseline 与 progressive)
- ITU-T Rec. T.87 / ISO/IEC 14495-1(JPEG-LS) —— 无损与近无损,LOCO-I 算法族
- jpeg.org:JPEG 2000 与 JPEG XL 官方页面
- JPEG XL 白皮书(jpeg.org) —— VarDCT/Modular、ANS+Huffman、无损 JPEG 转码 16%~22%、无损比优化 PNG 小约 35%
- WebP 官方文档 与 WebP 压缩技术 —— 26%/25%~34%/22% 等官方数字
- RFC 9649: WebP Lossless Bitstream —— Predictor/Color/Subtract Green/颜色索引变换、LZ77、颜色缓存、前缀码
- AV1 Image File Format (AVIF) 规范 —— 容器、品牌、位深、profiles
- OpenEXR Technical Introduction —— ZIP/PIZ/PXR24/B44/DWA/HTJ2K 与各自的数据量
- QOI 规范 —— 14 字节头、
qoif魔数、8 字节结束标记 - farbfeld(5) 手册页 —— suckless 无损格式定义
- Microsoft:图标文件格式(ICONDIR/ICONIMAGE)、DDS 头结构、块压缩(BC)
- Khronos KTX 2.0 规范 —— Basis Universal 与 supercompression
- caniuse: AVIF / WebP / JPEG XL —— 浏览器支持现状(随时会变,以该站为准)
- 美国国会图书馆「Sustainability of Digital Formats」格式档案(静止图像索引):GIF89a、PNG、APNG、BMP 5、JPEG 家族、JPEG-LS、JPEG 2000、JPEG XR、JPEG XL、JPEG XS、TIFF、PCX、TGA、WebP、AVIF、HEIF/HEIC、DNG、Camera RAW 等条目,本文的魔数、年份、专利情况多引自这里
总结一句话
「图片格式」这一堆后缀里,真正决定画质与体积的是内层的压缩方式——DCT 还是小波、Huffman 还是 ANS、调色板还是真彩、4:4:4 还是 4:2:0;外层容器负责装下 alpha、动画、HDR 与元数据。选型时先看场景(截图/照片/动图/HDR/归档),再按「同指标比体积」的规矩实测,别按后缀名猜。