Libavif Chroma Subsampling: 4:4:4, 4:2:2, and 4:2:0
This article explains how the libavif library manages
chroma subsampling formats, specifically 4:4:4, 4:2:2, and 4:2:0, during
the image encoding and decoding processes. It covers how
libavif maps RGB data to different YUV configurations, the
downsampling and upsampling algorithms utilized to preserve image
quality, and how developers can configure these formats within the API
to balance file size and visual fidelity.
Understanding Chroma Subsampling in AVIF
Chroma subsampling is a compression technique that reduces color resolution (chrominance) while preserving brightness resolution (luminance). Because the human eye is more sensitive to variations in light than color, this technique significantly reduces file sizes with minimal perceived loss in quality.
The AV1 video codec, which underlies the AVIF image format, natively
supports several YUV color spaces. The libavif library
handles these spaces using specific pixel format identifiers:
- YUV 4:4:4 (
AVIF_PIXEL_FORMAT_YUV444): No subsampling occurs. The chroma channels (U and V) are stored at the same resolution as the luma channel (Y). This preserves maximum color detail and prevents color bleeding, making it ideal for graphics, text, and screen shares. - YUV 4:2:2 (
AVIF_PIXEL_FORMAT_YUV422): Chroma channels are subsampled horizontally by half, but remain at full vertical resolution. - YUV 4:2:0 (
AVIF_PIXEL_FORMAT_YUV420): Chroma channels are subsampled by half both horizontally and vertically. This is the most common format for photographic images and video, offering the highest compression rates.
How libavif Manages the Encoding Process (RGB to YUV)
To encode an input image (typically in RGB format) into an AVIF file,
libavif must convert the RGB pixels into YUV. This process
is handled via the avifImageRGBToYUV() function.
During this conversion, libavif manages subsampling
through the following mechanisms:
1. Format Selection
The developer specifies the target subsampling format by setting the
yuvFormat member of the avifImage struct to
one of the library’s predefined enums (e.g.,
AVIF_PIXEL_FORMAT_YUV420).
2. Downsampling Filters
When converting to 4:2:2 or 4:2:0, libavif must discard
chroma pixels. To do this without introducing aliasing or color
artifacts, it uses downsampling filters. * Standard Bilinear/Box
Filtering: By default, average neighboring pixels are
calculated to create the lower-resolution chroma maps. * Sharp
YUV (libsharpyuv): libavif integrates Google’s
Sharp YUV algorithm (originally developed for WebP). Sharp YUV analyzes
the luminance channel to adjust the downsampled chroma values,
drastically reducing color bleeding and keeping sharp text boundaries
legible even at 4:2:0 subsampling.
How libavif Manages the Decoding Process (YUV to RGB)
When opening and rendering an AVIF image, libavif
reverses the process by decoding the compressed AV1 bitstream back into
YUV, and then converting YUV back to RGB using
avifImageYUVToRGB().
For subsampled formats like 4:2:2 and 4:2:0, the chroma channels must be upscaled (upsampled) to match the resolution of the luma channel before RGB conversion can take place.
1. Upsampling Algorithms
To reconstruct the missing color data, libavif utilizes
upsampling filters: * Nearest Neighbor: Fast but can
result in blocky, pixelated color edges. * Bilinear
Filtering: Blends adjacent chroma pixels to create a smoother,
more natural transition. This is the default behavior for most decoding
paths to ensure high visual quality.
2. Chrominance Positioning (Chroma Siting)
Different video standards define where subsampled chroma samples sit
relative to luma samples. libavif reads the chroma sample
position metadata (vertical/horizontal offsets) from the AV1 sequence
header. It respects configurations like “Center” or “Left” (colocated)
to ensure that colors align perfectly with their corresponding
brightness boundaries during reconstruction, avoiding alignment offsets
or “color shifting.”
API Implementation and Range Configurations
Developers interacting with the libavif API control
these behaviors through two main structures: avifImage and
avifRGBImage.
// Example configuration for encoding 4:2:0
avifImage * image = avifImageCreate(width, height, depth, AVIF_PIXEL_FORMAT_YUV420);
image->yuvRange = AVIF_RANGE_FULL; // Or AVIF_RANGE_LIMITED- Color Range (Full vs. Limited):
libavifhandles both full-range YUV (0-255 for 8-bit) and limited-range YUV (standard broadcast range, e.g., 16-235). The library adjusts the mathematical coefficients used during RGB/YUV conversion depending on theyuvRangesetting. - Monochrome (
AVIF_PIXEL_FORMAT_YUV400): For black-and-white images,libavifcompletely discards the U and V channels, saving substantial file space by only encoding the Y (luma) channel.