跳转到内容

JPEG 编码、色度抽样(Subsampling)与 MozJPEG 优化

复制本页

JPEG 依然是兼容性最广的有损图像格式。在生产管线中导出 JPEG 时,仅调整 Quality 远远不够:**色度抽样(Chroma Subsampling)**决定了红蓝文字边缘是否发虚,**渐进式扫描(Progressive / Interlace)与霍夫曼表优化(OptimizeCoding)**决定了在相同画质下能否再缩减 5%~15% 的文件体积。

编码控制项 govips JpegExportParams sharp .jpeg(options) pyvips / vips CLI jpegsave 生产推荐值与说明
质量因子 Quality(默认 80/75) quality(默认 80) Q=82 / --Q 82 Web 摄影图常用 78 ~ 85
色度抽样 SubsampleMode chromaSubsampling subsample_mode 摄影图用 auto(4:2:0);含锐利彩色文字/图标时改用 off(4:4:4)
渐进式扫描 Interlace: true progressive: true interlace=True 大于 10KB 的图片推荐开启,改善首屏加载感知并减小体积
霍夫曼表优化 OptimizeCoding: true optimiseCoding: true(默认开启) optimize_coding=True 无损减小体积,建议始终开启
网格量化与去振铃 TrellisQuant、OvershootDeringing、OptimizeScans、QuantTable mozjpeg: true(一键启用组合) trellis_quant、overshoot_deringing、optimize_scans、quant_table=3 在链接了 MozJPEG 的环境显著降低码率,但编码 CPU 耗时增加
剥离元数据 StripMetadata: true 默认剥离(保留需 .keepMetadata()) keep="none"(或 strip=True) 移除相机 EXIF 缩略图可节省数 KB 至数十 KB

下面的示例展示了如何在四个入口中开启 Quality = 82、渐进式扫描(Progressive)以及霍夫曼编码优化:

package main
import (
"fmt"
"os"
"github.com/davidbyttow/govips/v2/vips"
)
func main() {
if err := vips.Startup(nil); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer vips.Shutdown()
image, err := vips.NewImageFromFile("input.jpg")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer image.Close()
// JPEG 不支持透明通道:若输入可能含 Alpha,导出前必须先 Flatten
if image.HasAlpha() {
if err := image.Flatten(&vips.Color{R: 255, G: 255, B: 255}); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
params := vips.NewJpegExportParams()
params.Quality = 82
params.Interlace = true
params.OptimizeCoding = true
params.SubsampleMode = vips.VipsForeignSubsampleAuto
params.StripMetadata = true
// 若底层 libjpeg 由 MozJPEG 提供,可按需开启以下高级量化项:
params.TrellisQuant = true
params.OvershootDeringing = true
params.OptimizeScans = true
params.QuantTable = 3
data, _, err := image.ExportJpeg(params)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if err := os.WriteFile("output.jpg", data, 0o644); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

色度抽样:4:2:0 与 4:4:4 的选择边界

Section titled “色度抽样:4:2:0 与 4:4:4 的选择边界”

人眼对亮度(Y)细节比对色度(Cb/Cr)敏感得多。默认情况下(SubsampleMode = Auto):

  • 当 Q < 90 时,libvips 使用 4:2:0 色度抽样(每 2 × 2 像素块共享一组色度值),将色度通道体积减半;
  • 当 Q >= 90 时,libvips 自动切换为 4:4:4 不抽样(每个像素保留完整色度)。

如果你在 Q = 82 下导出包含深底红字、商品促销标签或 UI 截图的图像,建议显式关闭色度抽样(vips.VipsForeignSubsampleOff / chromaSubsampling: '4:4:4' / subsample_mode="off"),以消除彩色文字边缘的模糊色块。