Skip to content

WebP lossy, lossless, near-lossless, and effort tuning

Copy page

WebP combines VP8 intra-frame lossy compression and LZ77 + entropy lossless compression in one container, supporting an 8-bit alpha channel and multi-frame animation in both modes.

1938×1292 Gate of the Orient night photograph used for WebP encoding
Input: JPEG1938 × 1292, 610,191 bytes
1938×1292 WebP output encoded at Quality 82
Lossy WebP (Q=82): WebP1938 × 1292, 402,162 bytes (34.1% smaller than the input JPEG, with source ICC)

Beyond standard Quality and Lossless, libvips exposes near-lossless mode (NearLossless), which is particularly effective on UI screenshots, charts, and icons:

  • Lossy mode (Lossless = false): Quality controls VP8 quantization (default 75; 78–85 is typical for web photography).
  • Pure lossless mode (Lossless = true): preserves exact pixel values; Quality controls compression search effort rather than visual loss.
  • Near-lossless mode (NearLossless = true): uses the lossless VP8L encoder after gently quantizing pixel deltas to improve LZ77 repeatability (Quality sets the preprocessing precision, such as 60 or 80), frequently cutting UI screenshot sizes by 30%–50% with negligible visual change.
Setting govips WebpExportParams sharp .webp(options) pyvips / vips CLI webpsave Notes
Quality / preprocessing Quality (0..100) quality (default 80) Q=82 / --Q 82 Controls quantization in lossy mode or delta rounding in near-lossless mode
Pure lossless Lossless: true lossless: true lossless=True / --lossless Enables exact VP8L lossless compression
Near-lossless NearLossless: true nearLossless: true near_lossless=True / --near-lossless Pre-smooths pixels before lossless encoding; ideal for UI graphics
CPU effort ReductionEffort (0..6, default 4) effort (0..6, default 4) effort=4 / --effort 4 0 is fastest; 4 is the production default; 6 is slowest
Alpha quality — (does not expose alpha_q; default 100) alphaQuality (0..100) alpha_q=90 / --alpha-q 90 Setting 85–90 on lossy RGBA WebP shrinks translucent masks significantly
Smart chroma subsampling — (uses libwebp default or Preset) smartSubsample: true smart_subsample=True Higher-quality YUV 4:2:0 chroma downsampling at extra CPU cost
Metadata retention Keep (ForeignKeep*) .keepIccProfile() etc. keep="icc" / --keep icc Defaults differ by binding; govips v2.20 combines ICC, EXIF, XMP, IPTC, and other flags
Target byte size TargetSize (bytes) — target_size / --target-size Version-sensitive: requires libvips >= 8.17.4

1. Lossy photography vs near-lossless UI graphics

Section titled “1. Lossy photography vs near-lossless UI graphics”
// Case A: Lossy WebP for photographs (govips v2.20.0 does not expose alpha_q; alpha uses default 100)
lossy := vips.NewWebpExportParams()
lossy.Quality = 82
lossy.ReductionEffort = 4
lossy.StripMetadata = true
data, _, err := image.ExportWebp(lossy)
// Case B: Near-lossless WebP for UI screenshots, diagrams, and badges
nearLossless := vips.NewWebpExportParams()
nearLossless.NearLossless = true
nearLossless.Quality = 60 // 60 applies moderate pixel preprocessing for higher lossless compression
nearLossless.ReductionEffort = 4
nlData, _, err := image.ExportWebp(nearLossless)

WebpExportParams.Keep is a metadata bitmask. Zero means unset, so StripMetadata still decides whether metadata is stripped; an explicit Keep takes precedence:

params := vips.NewWebpExportParams()
params.StripMetadata = true
params.Keep = vips.ForeignKeepIcc
data, _, err := image.ExportWebp(params)

On the current v2.20.0/libvips 8.17.3 baseline, default WebP output retains the source ICC. ForeignKeepNone removes all metadata, while ForeignKeepIcc preserves ICC even with strip enabled. ForeignKeepGainmap requires libvips 8.18, so this baseline does not retain gain maps. Treat sharp, pyvips, and CLI switches and defaults independently.

3. TargetSize version boundary (libvips 8.17.4+)

Section titled “3. TargetSize version boundary (libvips 8.17.4+)”

govips v2.19.0 adds TargetSize int to WebpExportParams (mapping to target_size in vips_webpsave) so libwebp can run multi-pass encoding to approach a target byte budget.