WebP Encoding: VP8, VP8L, and Compression Techniques
Explore the VP8 lossy and VP8L lossless encoding pipelines in WebP, their compression techniques, and how to tune quality, method, and threading flags.
Understanding WebP’s encoding pipeline lets you make informed decisions about quality settings, compression effort, and when each codec applies. Whether you are optimising images for a high-traffic web application or archiving photos losslessly, knowing what happens inside the encoder helps you choose the right flags and avoid common traps like over-compression or unnecessarily slow build pipelines.
Lossy Encoding with VP8 #
WebP’s lossy codec is derived directly from the VP8 video codec’s intra-frame (keyframe) encoding mode. Because it was originally designed for video keyframes, VP8 already had highly optimised spatial-prediction and transform machinery — WebP simply removes the inter-frame prediction layer and applies the rest of the pipeline to still images.
- Macroblock partitioning — The encoder divides the image into rectangular macroblocks of either 4×4 or 16×16 pixels. Smaller block sizes capture fine detail at the cost of more overhead; the encoder chooses adaptively based on local texture complexity.
- Predictive coding — For each macroblock, the encoder selects a prediction mode that exploits spatial correlation with already-encoded neighbouring blocks (above and to the left). It computes a predicted block and then encodes only the residual — the difference between the prediction and the actual values. This delta is far smaller than the raw pixels.
- DCT transform — The residual block is passed through a Discrete Cosine Transform (DCT), converting spatial differences into frequency coefficients. Most image energy concentrates in low-frequency coefficients, allowing high-frequency coefficients to be discarded with minimal visible impact.
- Quantization — Each frequency coefficient is divided by a quantization step size. The
-qflag (0–100) controls these step sizes: a higher quality value uses smaller steps, preserving more coefficients and producing larger files with fewer artefacts. Quantization is the primary lossy step and is irreversible. - Arithmetic entropy coding — The quantized coefficients are losslessly compressed using arithmetic coding, a highly efficient binary entropy coder. The resulting bitstream is written into the
VP8chunk payload.
The -m flag (method, 0–6) controls how much effort the encoder spends searching for the optimal macroblock partition and prediction modes. Higher values explore more candidates and produce smaller files, but take significantly longer.
Lossless Encoding with VP8L #
VP8L is a purpose-built lossless codec created specifically for WebP. It treats the image as a 2D array of 32-bit ARGB values and applies a sequence of reversible transforms before entropy coding, with the goal of maximising redundancy removal.
Predictor Transform #
The predictor transform applies spatial prediction across the image: each pixel is predicted from its neighbours (above, left, above-left, etc.), and only the residual (prediction error) is stored. The image is divided into blocks, and the best predictor mode for each block is chosen and stored in a small header. This transform is especially effective on photographic gradients and smooth colour fields.
Colour Transform #
The colour transform decorrelates the R, G, and B channels. Because natural images typically have high correlation between channels (a bright red pixel usually has elevated G and B too), removing that correlation reduces the entropy of each channel independently, making subsequent compression more effective.
Subtract Green Transform #
The subtract green transform subtracts the green channel value from both the red and blue channels before entropy coding. This is a fast, fixed decorrelation step that complements the colour transform for images with a strong green bias (common in outdoor photography).
Colour Indexing Transform #
When the image contains a small number of distinct colours (up to 256), the colour indexing transform replaces pixel values with palette indices. This dramatically reduces the data size before entropy coding and is the primary mechanism for efficiently encoding PNG-style images with limited palettes.
After applying the enabled transforms, VP8L compresses the residual data using LZ77 backward references (a sliding-window dictionary coder) combined with Huffman entropy coding over the resulting symbol stream. The -z flag (0–9) or -m flag controls how exhaustively the encoder searches for LZ77 back-references.
Quality vs Speed Tradeoff #
Choose your encoding method based on your pipeline’s latency budget and the criticality of file size:
- Method 0 — Very fast encode, largest file size. Real-time pipelines, previews.
- Method 3 — Moderate encode time, medium file size. General web use.
- Method 4 (default) — Moderate encode time, good file size. Recommended for most projects.
- Method 6 — Slow encode, smallest file size. Archival / batch overnight.
Stick with -m 4 (the default) for everyday web workflows — it delivers an excellent size-to-speed ratio without configuration. Reserve -m 6 for offline batch jobs where encoding time is not a constraint, such as nightly image pipeline runs or archival processing.
Code Examples #
Use the following cwebp invocations as starting points for your own pipeline:
# Default (method 4) — balanced quality and speed
cwebp -q 80 input.jpg -o output.webp
# Fast encoding (method 0) — fastest encode, larger files
cwebp -q 80 -m 0 input.jpg -o output.webp
# Best compression (method 6) — slowest encode, smallest files
cwebp -q 80 -m 6 input.jpg -o output.webp
# Multi-threaded encoding for faster processing on multi-core machines
cwebp -q 80 -mt input.jpg -o output.webp
Multi-Threading #
Pass the -mt flag to cwebp to enable multi-threaded encoding. When active, the encoder distributes work across available CPU cores, which significantly reduces wall-clock time for large images or high-resolution batch jobs. Combine -mt with -m 6 in overnight pipelines to get the best compression without blocking your daytime workflow:
# Best compression with multi-threading — ideal for overnight batch runs
cwebp -q 80 -m 6 -mt input.jpg -o output.webp
Multi-threading does not change the output file’s quality or compression ratio — it only affects how quickly the encoder finishes. The resulting .webp file is bit-identical to a single-threaded encode with the same flags.
