How libavif Signals Full vs Studio Range Color
This article explains how the libavif library manages
and flags color range metadata, detailing how it distinguishes between
full range (0–255 for 8-bit) and studio/limited range (16–235 for 8-bit)
color. It covers the library’s internal API representations, how this
data is written into the ISOBMFF container, and how it is signaled
within the AV1 compressed bitstream.
At the software level, libavif utilizes the
avifImage structure to store image properties. Within this
structure, the color range is defined by the yuvRange
member, which accepts values from the avifRange
enumeration. This enum contains two primary constants:
AVIF_RANGE_LIMITED (representing studio range) and
AVIF_RANGE_FULL (representing full range). When preparing
an image for encoding, setting this variable tells libavif
how to interpret the input YUV coordinates and how to configure the
output metadata.
AVIF files are based on the ISO Base Media File Format (ISOBMFF). To
signal color properties at the container level, libavif
writes a Color Information (colr) box of type
nclx (on-screen colors) into the file metadata. Within the
nclx payload, there is a dedicated 1-bit field named
full_range_flag. When avifImage->yuvRange
is set to AVIF_RANGE_FULL, libavif sets this
flag to 1. Conversely, if the range is limited, the flag is
set to 0. This allows media parsers to quickly identify the
color range without needing to decode the underlying AV1 video
bitstream.
Because AVIF wraps an AV1 video frame, color range must also be
defined within the compressed image payload. During the encoding
process, libavif passes the range configuration to the AV1
encoder (such as aom or rav1e). The encoder
writes this information into the AV1 Sequence Header OBU (Open Bitstream
Unit), specifically inside the color_config() syntax
element. Here, the color_range bit is set to 1
for full range and 0 for studio/limited range.
When decoding an AVIF file, libavif extracts the range
information from both the container’s colr box and the AV1
bitstream to ensure consistency. The library uses this range state to
perform accurate color space conversion. If full range is signaled, the
YUV values are mapped directly from 0 to 2^depth - 1. If limited range
is signaled, the library scales the YUV values using the standard studio
range coefficients (e.g., scaling Y between 16 and 235 in 8-bit depth)
to prevent color clipping and ensure accurate RGB reconstruction on the
display.