Configuring Dither, Filter, and Range in FFmpeg zscale
The zscale filter in FFmpeg uses the zimg
library to perform high-precision video scaling, pixel format
conversion, and colorspace modifications. This article provides a
direct, practical guide on how to configure the filter
(scaling algorithm), dither (quantization error diffusion),
and range (color dynamic range) parameters inside FFmpeg's
zscale filter to achieve optimal video quality and prevent
common artifacts like banding or incorrect contrast.
Understanding the Parameters
When using zscale, multiple parameters are chained
together using colons (:) within the filter graph:
filter: Sets the resampling algorithm used for scaling image dimensions.dither: Controls the dithering algorithm applied when reducing color bit-depth, preventing color banding.range/rangein: Controls the output and input quantization ranges (limited vs. full range).
Configuring the Scaling
filter
The filter parameter dictates which interpolation
algorithm calculates pixel values during resizing.
Common Values:
bicubic(Default: balanced sharpness and speed)bilinear(Faster, but softer)lanczos(High sharpness, ideal for downscaling)spline16/spline36(Smooth, minimizes ringing artifacts)point(Nearest-neighbor, useful for pixel art)
Syntax Example:
zscale=w=1920:h=1080:filter=spline36Configuring the
dither Parameter
Dithering introduces subtle noise to mask quantization errors when lowering bit-depth (for instance, converting 10-bit HDR content down to standard 8-bit SDR).
Available Options:
none: Disables dithering (fastest, but may cause visible color banding).ordered: Applies ordered spatial dithering.random: Adds uniform random noise.error_diffusion: Uses Floyd-Steinberg error diffusion (highest quality for color transitions and gradients).
Syntax Example:
zscale=dither=error_diffusionConfiguring the Color
range
The range parameter defines the dynamic range
(quantization range) for luminance and chrominance values. It prevents
crushed shadows or washed-out highlights caused by mismatched
full/limited range tags.
Values:
input/unspecified: Keeps the detected input range.limited(ortv): Studio range (Y: 16–235, Cb/Cr: 16–240 in 8-bit). Standard for broadcast and standard SDR/HDR video.full(orpc): Full range (0–255 in 8-bit). Common for PC monitors, photography, and JPEG images.
You can set both the expected input range (rangein) and
the target output range (range):
Syntax Example:
zscale=rangein=full:range=limitedCombining Filter, Dither, and Range in a Complete Command
To scale a video down to 1080p, apply a Spline36 algorithm, convert from full range to limited range, and apply error diffusion dithering, configure the command as follows:
ffmpeg -i input.mp4 -vf "zscale=w=1920:h=1080:filter=spline36:rangein=full:range=limited:dither=error_diffusion" -c:v libx264 -crf 18 output.mp4In this pipeline:
w=1920:h=1080sets the target frame size.filter=spline36sharpens the image cleanly with low ringing.rangein=full:range=limitedremaps 0–255 levels down to 16–235 levels correctly.dither=error_diffusionensures smooth gradients across areas like skies or shadows where banding typically occurs.