/* * HEIF codec. * Copyright (c) 2017-2023 Dirk Farin * * This file is part of libheif. * * libheif is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * libheif is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libheif. If not, see . */ #ifndef LIBHEIF_HEIF_COLOR_H #define LIBHEIF_HEIF_COLOR_H #ifdef __cplusplus extern "C" { #endif #include // forward declaration from other header files typedef struct heif_image heif_image; typedef enum heif_chroma_downsampling_algorithm { heif_chroma_downsampling_nearest_neighbor = 1, heif_chroma_downsampling_average = 2, // Combine with 'heif_chroma_upsampling_bilinear' for best quality. // Makes edges look sharper when using YUV 420 with bilinear chroma upsampling. heif_chroma_downsampling_sharp_yuv = 3 } heif_chroma_downsampling_algorithm; typedef enum heif_chroma_upsampling_algorithm { heif_chroma_upsampling_nearest_neighbor = 1, heif_chroma_upsampling_bilinear = 2 } heif_chroma_upsampling_algorithm; typedef struct heif_color_conversion_options { // 'version' must be 1. uint8_t version; // --- version 1 options heif_chroma_downsampling_algorithm preferred_chroma_downsampling_algorithm; heif_chroma_upsampling_algorithm preferred_chroma_upsampling_algorithm; // When set to 'false' libheif may also use a different algorithm if the preferred one is not available // or using a different algorithm is computationally less complex. Note that currently (v1.17.0) this // means that for RGB input it will usually choose nearest-neighbor sampling because this is computationally // the simplest. // Set this field to 'true' if you want to make sure that the specified algorithm is used even // at the cost of slightly higher computation times. uint8_t only_use_preferred_chroma_algorithm; // --- Note that we cannot extend this struct because it is embedded in // other structs (heif_decoding_options and heif_encoding_options). } heif_color_conversion_options; typedef enum heif_alpha_composition_mode { heif_alpha_composition_mode_none, heif_alpha_composition_mode_solid_color, heif_alpha_composition_mode_checkerboard, } heif_alpha_composition_mode; typedef struct heif_color_conversion_options_ext { uint8_t version; // --- version 1 options heif_alpha_composition_mode alpha_composition_mode; // color values should be specified in the range [0, 65535] uint16_t background_red, background_green, background_blue; uint16_t secondary_background_red, secondary_background_green, secondary_background_blue; uint16_t checkerboard_square_size; } heif_color_conversion_options_ext; // Assumes that it is a version=1 struct. LIBHEIF_API void heif_color_conversion_options_set_defaults(heif_color_conversion_options*); LIBHEIF_API heif_color_conversion_options_ext* heif_color_conversion_options_ext_alloc(void); LIBHEIF_API void heif_color_conversion_options_ext_copy(heif_color_conversion_options_ext* dst, const heif_color_conversion_options_ext* src); LIBHEIF_API void heif_color_conversion_options_ext_free(heif_color_conversion_options_ext*); // ------------------------- color profiles ------------------------- typedef enum heif_color_profile_type { heif_color_profile_type_not_present = 0, heif_color_profile_type_nclx = heif_fourcc('n', 'c', 'l', 'x'), heif_color_profile_type_rICC = heif_fourcc('r', 'I', 'C', 'C'), heif_color_profile_type_prof = heif_fourcc('p', 'r', 'o', 'f') } heif_color_profile_type; // Returns 'heif_color_profile_type_not_present' if there is no color profile. // If there is an ICC profile and an NCLX profile, the ICC profile is returned. // TODO: we need a new API for this function as images can contain both NCLX and ICC at the same time. // However, you can still use heif_image_handle_get_raw_color_profile() and // heif_image_handle_get_nclx_color_profile() to access both profiles. LIBHEIF_API heif_color_profile_type heif_image_handle_get_color_profile_type(const heif_image_handle* handle); LIBHEIF_API size_t heif_image_handle_get_raw_color_profile_size(const heif_image_handle* handle); // Returns 'heif_error_Color_profile_does_not_exist' when there is no ICC profile. LIBHEIF_API struct heif_error heif_image_handle_get_raw_color_profile(const heif_image_handle* handle, void* out_data); typedef enum heif_color_primaries { heif_color_primaries_ITU_R_BT_709_5 = 1, // g=0.3;0.6, b=0.15;0.06, r=0.64;0.33, w=0.3127,0.3290 heif_color_primaries_unspecified = 2, heif_color_primaries_ITU_R_BT_470_6_System_M = 4, heif_color_primaries_ITU_R_BT_470_6_System_B_G = 5, heif_color_primaries_ITU_R_BT_601_6 = 6, heif_color_primaries_SMPTE_240M = 7, heif_color_primaries_generic_film = 8, heif_color_primaries_ITU_R_BT_2020_2_and_2100_0 = 9, heif_color_primaries_SMPTE_ST_428_1 = 10, heif_color_primaries_SMPTE_RP_431_2 = 11, heif_color_primaries_SMPTE_EG_432_1 = 12, heif_color_primaries_EBU_Tech_3213_E = 22 } heif_color_primaries; typedef enum heif_transfer_characteristics { heif_transfer_characteristic_ITU_R_BT_709_5 = 1, heif_transfer_characteristic_unspecified = 2, heif_transfer_characteristic_ITU_R_BT_470_6_System_M = 4, heif_transfer_characteristic_ITU_R_BT_470_6_System_B_G = 5, heif_transfer_characteristic_ITU_R_BT_601_6 = 6, heif_transfer_characteristic_SMPTE_240M = 7, heif_transfer_characteristic_linear = 8, heif_transfer_characteristic_logarithmic_100 = 9, heif_transfer_characteristic_logarithmic_100_sqrt10 = 10, heif_transfer_characteristic_IEC_61966_2_4 = 11, heif_transfer_characteristic_ITU_R_BT_1361 = 12, heif_transfer_characteristic_IEC_61966_2_1 = 13, heif_transfer_characteristic_ITU_R_BT_2020_2_10bit = 14, heif_transfer_characteristic_ITU_R_BT_2020_2_12bit = 15, heif_transfer_characteristic_ITU_R_BT_2100_0_PQ = 16, heif_transfer_characteristic_SMPTE_ST_428_1 = 17, heif_transfer_characteristic_ITU_R_BT_2100_0_HLG = 18 } heif_transfer_characteristics; typedef enum heif_matrix_coefficients { heif_matrix_coefficients_RGB_GBR = 0, heif_matrix_coefficients_ITU_R_BT_709_5 = 1, // TODO: or 709-6 according to h.273 heif_matrix_coefficients_unspecified = 2, heif_matrix_coefficients_US_FCC_T47 = 4, heif_matrix_coefficients_ITU_R_BT_470_6_System_B_G = 5, heif_matrix_coefficients_ITU_R_BT_601_6 = 6, // TODO: or 601-7 according to h.273 heif_matrix_coefficients_SMPTE_240M = 7, heif_matrix_coefficients_YCgCo = 8, heif_matrix_coefficients_ITU_R_BT_2020_2_non_constant_luminance = 9, heif_matrix_coefficients_ITU_R_BT_2020_2_constant_luminance = 10, heif_matrix_coefficients_SMPTE_ST_2085 = 11, heif_matrix_coefficients_chromaticity_derived_non_constant_luminance = 12, heif_matrix_coefficients_chromaticity_derived_constant_luminance = 13, heif_matrix_coefficients_ICtCp = 14 } heif_matrix_coefficients; typedef struct heif_color_profile_nclx { // === version 1 fields uint8_t version; heif_color_primaries color_primaries; heif_transfer_characteristics transfer_characteristics; heif_matrix_coefficients matrix_coefficients; uint8_t full_range_flag; // --- decoded values (not used when saving nclx) float color_primary_red_x, color_primary_red_y; float color_primary_green_x, color_primary_green_y; float color_primary_blue_x, color_primary_blue_y; float color_primary_white_x, color_primary_white_y; } heif_color_profile_nclx; LIBHEIF_API heif_error heif_nclx_color_profile_set_color_primaries(heif_color_profile_nclx* nclx, uint16_t cp); LIBHEIF_API heif_error heif_nclx_color_profile_set_transfer_characteristics(heif_color_profile_nclx* nclx, uint16_t transfer_characteristics); LIBHEIF_API heif_error heif_nclx_color_profile_set_matrix_coefficients(heif_color_profile_nclx* nclx, uint16_t matrix_coefficients); // Returns 'heif_error_Color_profile_does_not_exist' when there is no NCLX profile. // TODO: This function does currently not return an NCLX profile if it is stored in the image bitstream. // Only NCLX profiles stored as colr boxes are returned. This may change in the future. LIBHEIF_API heif_error heif_image_handle_get_nclx_color_profile(const heif_image_handle* handle, heif_color_profile_nclx** out_data); // Returned color profile has 'version' field set to the maximum allowed. // Do not fill values for higher versions as these might be outside the allocated structure size. // May return NULL. LIBHEIF_API heif_color_profile_nclx* heif_nclx_color_profile_alloc(void); LIBHEIF_API void heif_nclx_color_profile_free(heif_color_profile_nclx* nclx_profile); // Note: in early versions of HEIF, there could only be one color profile per image. However, this has been changed. // This function will now return ICC if one is present and NCLX only if there is no ICC. // You may better avoid this function and simply query for NCLX and ICC directly. LIBHEIF_API heif_color_profile_type heif_image_get_color_profile_type(const heif_image* image); // Returns the size of the ICC profile if one is assigned to the image. Otherwise, it returns 0. LIBHEIF_API size_t heif_image_get_raw_color_profile_size(const heif_image* image); // Returns the ICC profile if one is assigned to the image. Otherwise, it returns an error. LIBHEIF_API heif_error heif_image_get_raw_color_profile(const heif_image* image, void* out_data); LIBHEIF_API heif_error heif_image_get_nclx_color_profile(const heif_image* image, heif_color_profile_nclx** out_data); // The color profile is not attached to the image handle because we might need it // for color space transform and encoding. LIBHEIF_API heif_error heif_image_set_raw_color_profile(heif_image* image, const char* profile_type_fourcc_string, const void* profile_data, const size_t profile_size); LIBHEIF_API heif_error heif_image_set_nclx_color_profile(heif_image* image, const heif_color_profile_nclx* color_profile); // TODO: this function does not make any sense yet, since we currently cannot modify existing HEIF files. //LIBHEIF_API //void heif_image_remove_color_profile(struct heif_image* image); // --- content light level --- // Semantics follow the H.265 'Content light level information' SEI message // (ITU-T H.265 Annex D.3.35). Identifies upper bounds for the nominal // target brightness light level of the pictures. The bounds are defined // against samples in a 4:4:4 RGB representation in the linear light domain, // in units of candelas per square metre (cd/m^2 = nits). A field value // of 0 means "no upper bound indicated" (i.e. undefined). typedef struct heif_content_light_level { // Upper bound on the maximum light level among all individual linear-light // 4:4:4 RGB samples across the sequence, in cd/m^2 (= field). // Also called MaxCLL. uint16_t max_content_light_level; // Upper bound on the maximum per-picture average light level among the // linear-light 4:4:4 RGB samples (averaged over any individual picture), // in cd/m^2 (= field). Also called MaxFALL (or MaxPALL). // For letterboxed content the average is expected to be taken only over // the visually relevant region (H.265 D.3.35 NOTE 3). uint16_t max_pic_average_light_level; } heif_content_light_level; LIBHEIF_API int heif_image_has_content_light_level(const heif_image*); LIBHEIF_API int heif_image_handle_has_content_light_level(const heif_image_handle*); // TODO: this function should also return 'int' to be consistent to heif_image_handle_get_content_light_level. LIBHEIF_API void heif_image_get_content_light_level(const heif_image*, heif_content_light_level* out); // Returns whether the image has 'content light level' information. If 0 is returned, the output is not filled. LIBHEIF_API int heif_image_handle_get_content_light_level(const heif_image_handle*, heif_content_light_level* out); LIBHEIF_API void heif_image_set_content_light_level(const heif_image*, const heif_content_light_level* in); LIBHEIF_API void heif_image_handle_set_content_light_level(const heif_image_handle*, const heif_content_light_level* in); // --- mastering display colour volume --- // Semantics follow the H.265 'Mastering display colour volume' SEI message // (ITU-T H.265 Annex D.3.28) and SMPTE ST 2086. Identifies the colour // volume (primaries, white point, luminance range) of the mastering display // for the associated content. CIE 1931 chromaticity coordinates are defined // by ISO 11664-1 (see also ISO 11664-3 and CIE 15). // // For RGB mastering displays, H.265 suggests the index order // [0]=green, [1]=blue, [2]=red // (see H.265 Annex E, Table E.3). typedef struct heif_mastering_display_colour_volume { // CIE 1931 chromaticity coordinates of the three colour primaries, in // normalized increments of 0.00002 (CIE value = field / 50000). // Valid ranges per H.265: x in 5..37000, y in 5..42000 inclusive; values // outside indicate "unknown / unspecified". // Note: SMPTE ST 2086 uses four-decimal-place coordinates, i.e. multiples // of 5 in this encoding. uint16_t display_primaries_x[3]; uint16_t display_primaries_y[3]; // CIE 1931 chromaticity coordinates of the mastering display's white // point, in normalized increments of 0.00002. Valid ranges as for the // primaries (x in 5..37000, y in 5..42000). // Note: ANSI/CTA 861-G uses (0,0) to indicate that the white point // chromaticity is unknown. uint16_t white_point_x; uint16_t white_point_y; // Nominal maximum / minimum display luminance of the mastering display, // in units of 0.0001 candelas per square metre (cd/m^2 = field / 10000). // Valid ranges per H.265: // max in 50000..100000000 (5..10000 cd/m^2) // min in 1..50000 (0.0001..5 cd/m^2) // When max == 50000, min shall not equal 50000. // Note: ANSI/CTA 861-G uses 0 to indicate "unknown". // Note: SMPTE ST 2086 (2018) specifies max as a multiple of 1 cd/m^2, i.e. // a multiple of 10000 in this encoding. uint32_t max_display_mastering_luminance; uint32_t min_display_mastering_luminance; } heif_mastering_display_colour_volume; // The units for max_display_mastering_luminance and min_display_mastering_luminance is Candelas per square meter. typedef struct heif_decoded_mastering_display_colour_volume { float display_primaries_x[3]; float display_primaries_y[3]; float white_point_x; float white_point_y; double max_display_mastering_luminance; double min_display_mastering_luminance; } heif_decoded_mastering_display_colour_volume; // Semantics follow the H.265 'Ambient viewing environment' SEI message // (ITU-T H.265 Annex D.3.39). Identifies the nominal ambient viewing // environment intended for display of the associated content. typedef struct heif_ambient_viewing_environment { // Environmental illuminance of the ambient viewing environment, in units // of 0.0001 lux (i.e. lux = value / 10000). In H.265 this field is called // 'ambient_illuminance' and is required to be non-zero; 0 is treated here // as "undefined". uint32_t ambient_illumination; // Normalized CIE 1931 chromaticity coordinates of the environmental // ambient light, in units of 0.00002 (i.e. CIE x = value / 50000). // Valid range per H.265 is 0..50000 inclusive. CIE 1931 x/y are defined // by ISO 11664-1 (see also ISO 11664-3 and CIE 15). // // Example (Rec. ITU-R BT.2035, D65 background): ambient_illumination=100000, // ambient_light_x=15635, ambient_light_y=16450. uint16_t ambient_light_x; uint16_t ambient_light_y; } heif_ambient_viewing_environment; LIBHEIF_API int heif_image_has_mastering_display_colour_volume(const heif_image*); LIBHEIF_API int heif_image_handle_has_mastering_display_colour_volume(const heif_image_handle*); LIBHEIF_API void heif_image_get_mastering_display_colour_volume(const heif_image*, heif_mastering_display_colour_volume* out); // Returns whether the image has 'mastering display colour volume' information. If 0 is returned, the output is not filled. LIBHEIF_API int heif_image_handle_get_mastering_display_colour_volume(const heif_image_handle*, heif_mastering_display_colour_volume* out); LIBHEIF_API void heif_image_set_mastering_display_colour_volume(const heif_image*, const heif_mastering_display_colour_volume* in); LIBHEIF_API void heif_image_handle_set_mastering_display_colour_volume(const heif_image_handle*, const heif_mastering_display_colour_volume* in); // --- ambient viewing environment --- LIBHEIF_API int heif_image_has_ambient_viewing_environment(const heif_image*); LIBHEIF_API int heif_image_handle_has_ambient_viewing_environment(const heif_image_handle*); // Returns whether the image has 'ambient viewing environment' information. If 0 is returned, the output is not filled. LIBHEIF_API int heif_image_get_ambient_viewing_environment(const heif_image*, heif_ambient_viewing_environment* out); // Returns whether the image has 'ambient viewing environment' information. If 0 is returned, the output is not filled. LIBHEIF_API int heif_image_handle_get_ambient_viewing_environment(const heif_image_handle*, heif_ambient_viewing_environment* out); LIBHEIF_API void heif_image_set_ambient_viewing_environment(const heif_image*, const heif_ambient_viewing_environment* in); LIBHEIF_API void heif_image_handle_set_ambient_viewing_environment(const heif_image_handle*, const heif_ambient_viewing_environment* in); // --- nominal diffuse white --- // Nominal diffuse white luminance (ISO/IEC 23008-12 'ndwt' box). The luminance // is given in units of 0.0001 candelas per square metre. A value of 0 is valid // and selects the default definition of ISO/TS 22028-5. // If the image has no 'nominal diffuse white' information, the getter returns 0, // which is indistinguishable from a stored luminance of 0. Use the has_ function // to disambiguate. LIBHEIF_API int heif_image_has_nominal_diffuse_white_luminance(const heif_image*); LIBHEIF_API uint32_t heif_image_get_nominal_diffuse_white_luminance(const heif_image*); LIBHEIF_API void heif_image_set_nominal_diffuse_white_luminance(const heif_image*, uint32_t luminance); LIBHEIF_API int heif_image_handle_has_nominal_diffuse_white_luminance(const heif_image_handle*); LIBHEIF_API uint32_t heif_image_handle_get_nominal_diffuse_white_luminance(const heif_image_handle*); LIBHEIF_API void heif_image_handle_set_nominal_diffuse_white_luminance(const heif_image_handle*, uint32_t luminance); // Converts the internal numeric representation of heif_mastering_display_colour_volume to the // normalized values, collected in heif_decoded_mastering_display_colour_volume. // Values that are out-of-range are decoded to 0, indicating an undefined value (as specified in ISO/IEC 23008-2). LIBHEIF_API struct heif_error heif_mastering_display_colour_volume_decode(const heif_mastering_display_colour_volume* in, heif_decoded_mastering_display_colour_volume* out); #ifdef __cplusplus } #endif #endif