Set Color Space and ICC Profile in libavif
This article explains how to configure the color space (CICP) and
assign an ICC profile to an image using the libavif library
before encoding. You will learn the specific struct members and API
functions required to ensure your AVIF images retain accurate color
representation across different devices and platforms.
Setting the Color Space (CICP)
In libavif, the color space is defined using CICP
(Coding-Independent Code Points) values, which specify the color
primaries, transfer characteristics, and matrix coefficients. These
properties are set directly on the avifImage structure
before passing it to the encoder.
The following members of the avifImage struct are used
to define the color space:
colorPrimaries: Specifies the color primaries (e.g., sRGB/BT.709, BT.2020).transferCharacteristics: Specifies the transfer function (e.g., sRGB, linear, PQ, HLG).matrixCoefficients: Specifies the matrix coefficients used to derive luma and chroma signals from red, green, and blue primaries.
Code Example: Configuring CICP
#include "avif/avif.h"
void configure_color_space(avifImage * image) {
// Set the color space to sRGB (BT.709)
image->colorPrimaries = AVIF_COLOR_PRIMARIES_BT709;
image->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_SRGB;
image->matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_BT709;
// Set the YUV range (typically AVIF_RANGE_LIMITED or AVIF_RANGE_FULL)
image->yuvRange = AVIF_RANGE_FULL;
}Setting the ICC Profile
While CICP values are highly efficient, some workflows require an ICC
(International Color Consortium) profile for precise color management.
libavif allows you to attach raw ICC profile payload data
to the avifImage structure.
The primary function used to set the ICC profile is:
avifImageSetProfileICC
void avifImageSetProfileICC(avifImage * image, const uint8_t * icc, size_t iccSize);image: A pointer to theavifImagestructure being prepared for encoding.icc: A pointer to the buffer containing the raw ICC profile data.iccSize: The size of the ICC profile buffer in bytes.
Calling this function copies the provided ICC data into the
avifImage structure, which the encoder will then embed in
the output AVIF container.
Code Example: Attaching an ICC Profile
#include "avif/avif.h"
void attach_icc_profile(avifImage * image, const uint8_t * icc_data, size_t icc_data_size) {
// Copy the ICC profile data into the avifImage structure
avifImageSetProfileICC(image, icc_data, icc_data_size);
}Integration into the Encoding Pipeline
To apply these settings, configure the avifImage
properties and call the ICC profile function after allocating the image
but before passing it to the encoder.
// 1. Allocate the image
avifImage * image = avifImageCreate(width, height, depth, AVIF_PIXEL_FORMAT_YUV420);
// 2. Set pixel data (omitted for brevity)
// 3. Set Color Space (CICP)
image->colorPrimaries = AVIF_COLOR_PRIMARIES_BT2020;
image->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_PQ;
image->matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_BT2020;
// 4. Set ICC Profile (Optional)
avifImageSetProfileICC(image, raw_icc_buffer, icc_buffer_size);
// 5. Encode the image
avifEncoder * encoder = avifEncoderCreate();
avifRWData raw_avif = AVIF_RAW_DATA_EMPTY;
avifResult result = avifEncoderWrite(encoder, image, &raw_avif);
if (result == AVIF_RESULT_OK) {
// AVIF data successfully encoded with color metadata
}
// Cleanup
avifEncoderDestroy(encoder);
avifImageDestroy(image);
avifRWDataFree(&raw_avif);