How libavif Ensures Color Accuracy in Bit Conversion
This article explains how the libavif library maintains
precise color representation when converting image files between 8-bit,
10-bit, and 12-bit formats. It covers the underlying mechanisms of
high-precision math, color space metadata preservation, and chroma
subsampling handling that prevent color degradation during the encoding
and decoding processes.
High-Precision Intermediate Processing
When converting between different bit depths, simple integer division
or bit-shifting can introduce rounding errors, leading to visible
banding or color shifts. To prevent this, libavif performs
its internal color conversions and matrix multiplications using
higher-precision math.
During conversion, pixel data is scaled up to a 16-bit integer or a
floating-point representation. By processing the colors in a higher bit
depth than the source or target format, libavif minimizes
truncation errors. The final rounding down to the target bit depth (such
as 8-bit) occurs only at the very end of the pipeline, using rounding
algorithms that preserve color integrity.
Strict Adherence to CICP Metadata
Color accuracy is heavily dependent on how color channels are
interpreted. libavif relies on Coding-Independent Code
Points (CICP) metadata, which is defined in the AV1 specification. CICP
explicitly defines three critical parameters: * Color
Primaries: The exact coordinates of red, green, and blue. *
Transfer Characteristics: The opto-electronic transfer
function (gamma curve) used to encode the luminance. * Matrix
Coefficients: The formula used to convert between YUV
(luma/chroma) and RGB color spaces.
When converting between bit depths, libavif references
these CICP parameters to apply the mathematically correct transformation
matrices. This ensures that a color defined in a 10-bit BT.2020 wide
color gamut is accurately mapped to its closest equivalent in an 8-bit
sRGB gamut, or vice versa, without unexpected shifts in hue or
saturation.
Advanced Chroma Upsampling and Downsampling
AVIF images often use chroma subsampling (such as YUV 4:2:0 or 4:2:2) to reduce file size. Converting these images to RGB (which is always YUV 4:4:4 equivalent) requires scaling the color channels.
libavif ensures color accuracy during this phase by
utilizing high-quality interpolation filters (such as bilinear or
Lanczos) rather than nearest-neighbor scaling. When changing bit depths
alongside chroma scaling, the library performs the spatial interpolation
in the higher-precision domain. This prevents color bleeding and ensures
that transitions between contrasting colors remain sharp and
mathematically accurate.
Dithering to Prevent Banding
Going from a higher bit depth (10-bit or 12-bit) to a lower one
(8-bit) naturally results in a loss of color information, which can
cause color banding in smooth gradients. To mitigate this,
libavif can utilize dithering. Dithering adds a controlled
amount of noise to the image before quantization. This visual trick
fools the human eye into perceiving smoother gradients and highly
accurate colors, effectively preserving the visual depth of the original
high-bit-depth source even within an 8-bit container.