diff --git a/examples/heif_enc.cc b/examples/heif_enc.cc index 754f566379..01a1193370 100644 --- a/examples/heif_enc.cc +++ b/examples/heif_enc.cc @@ -168,9 +168,9 @@ void show_help(const char* argv0) << " -e, --encoder ID select encoder to use (the IDs can be listed with --list-encoders)\n" << " --plugin-directory DIR load all codec plugins in the directory\n" << " -E, --even-size [deprecated] crop images to even width and height (odd sizes are not decoded correctly by some software)\n" - << " --matrix_coefficients nclx profile: color conversion matrix coefficients, default=6 (see h.273)\n" - << " --colour_primaries nclx profile: color primaries (see h.273)\n" - << " --transfer_characteristic nclx profile: transfer characteristics (see h.273)\n" + << " --colour_primaries nclx profile: color primaries, default: 1 (see h.273)\n" + << " --transfer_characteristic nclx profile: transfer characteristics, default: 13 (see h.273)\n" + << " --matrix_coefficients nclx profile: color conversion matrix coefficients, default: 6 for lossy or 0 for lossless (see h.273)\n" << " --full_range_flag nclx profile: full range flag, default: 1\n" << " --enable-two-colr-boxes will write both an ICC and an nclx color profile if both are present\n" << " --premultiplied-alpha input image has premultiplied alpha\n" @@ -178,13 +178,7 @@ void show_help(const char* argv0) << " -C,--chroma-downsampling ALGO force chroma downsampling algorithm (nn = nearest-neighbor / average / sharp-yuv)\n" << " (sharp-yuv makes edges look sharper when using YUV420 with bilinear chroma upsampling)\n" << " --benchmark measure encoding time, PSNR, and output file size\n" - << " --pitm-description TEXT (EXPERIMENTAL) set user description for primary image\n" - - << "\n" - << "Note: to get lossless encoding, you need this set of options:\n" - << " -L switch encoder to lossless mode\n" - << " -p chroma=444 switch off chroma subsampling\n" - << " --matrix_coefficients=0 encode in RGB color-space\n"; + << " --pitm-description TEXT (EXPERIMENTAL) set user description for primary image\n"; } @@ -509,6 +503,7 @@ int main(int argc, char** argv) break; case 'L': lossless = true; + nclx_matrix_coefficients = 0; break; case 'o': output_filename = optarg; diff --git a/libheif/context.cc b/libheif/context.cc index 0033031259..8d97f1f9e9 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -2429,7 +2429,9 @@ static bool nclx_profile_matches_spec(heif_colorspace colorspace, } -static std::shared_ptr compute_target_nclx_profile(const std::shared_ptr& image, const heif_color_profile_nclx* output_nclx_profile) +static std::shared_ptr compute_target_nclx_profile(const std::shared_ptr& image, + const heif_color_profile_nclx* output_nclx_profile, + bool lossless = false) { auto target_nclx_profile = std::make_shared(); @@ -2446,7 +2448,7 @@ static std::shared_ptr compute_target_nclx_profile(const std target_nclx_profile->set_undefined(); } - target_nclx_profile->replace_undefined_values_with_sRGB_defaults(); + target_nclx_profile->replace_undefined_values_with_sRGB_defaults(lossless); return target_nclx_profile; } @@ -2466,8 +2468,13 @@ Error HeifContext::encode_image_as_hevc(const std::shared_ptr& i heif_colorspace colorspace = image->get_colorspace(); heif_chroma chroma = image->get_chroma_format(); + int lossless = 0; - auto target_nclx_profile = compute_target_nclx_profile(image, options.output_nclx_profile); + if (encoder->plugin->supports_lossless_compression) { + encoder->plugin->get_parameter_lossless(encoder->encoder, &lossless); + } + + auto target_nclx_profile = compute_target_nclx_profile(image, options.output_nclx_profile, static_cast(lossless)); if (encoder->plugin->plugin_api_version >= 2) { encoder->plugin->query_input_colorspace2(encoder->encoder, &colorspace, &chroma); @@ -2688,8 +2695,13 @@ Error HeifContext::encode_image_as_av1(const std::shared_ptr& im heif_colorspace colorspace = image->get_colorspace(); heif_chroma chroma = image->get_chroma_format(); + int lossless = 0; - auto target_nclx_profile = compute_target_nclx_profile(image, options.output_nclx_profile); + if (encoder->plugin->supports_lossless_compression) { + encoder->plugin->get_parameter_lossless(encoder->encoder, &lossless); + } + + auto target_nclx_profile = compute_target_nclx_profile(image, options.output_nclx_profile, static_cast(lossless)); if (encoder->plugin->plugin_api_version >= 2) { encoder->plugin->query_input_colorspace2(encoder->encoder, &colorspace, &chroma); diff --git a/libheif/nclx.cc b/libheif/nclx.cc index 95339f4ed5..65853b70a4 100644 --- a/libheif/nclx.cc +++ b/libheif/nclx.cc @@ -343,10 +343,10 @@ void color_profile_nclx::set_from_heif_color_profile_nclx(const struct heif_colo } -void color_profile_nclx::replace_undefined_values_with_sRGB_defaults() +void color_profile_nclx::replace_undefined_values_with_sRGB_defaults(bool lossless) { if (m_matrix_coefficients == heif_matrix_coefficients_unspecified) { - m_matrix_coefficients = heif_matrix_coefficients_ITU_R_BT_601_6; + m_matrix_coefficients = lossless ? heif_matrix_coefficients_RGB_GBR : heif_matrix_coefficients_ITU_R_BT_601_6; } if (m_colour_primaries == heif_color_primaries_unspecified) { diff --git a/libheif/nclx.h b/libheif/nclx.h index 5779e440e3..56dbcacf17 100644 --- a/libheif/nclx.h +++ b/libheif/nclx.h @@ -159,7 +159,7 @@ class color_profile_nclx : public color_profile void set_from_heif_color_profile_nclx(const struct heif_color_profile_nclx* nclx); - void replace_undefined_values_with_sRGB_defaults(); + void replace_undefined_values_with_sRGB_defaults(bool lossless = false); private: uint16_t m_colour_primaries = heif_color_primaries_unspecified; diff --git a/libheif/plugins/encoder_aom.cc b/libheif/plugins/encoder_aom.cc index 8ccff0d81f..d6cbecc63e 100644 --- a/libheif/plugins/encoder_aom.cc +++ b/libheif/plugins/encoder_aom.cc @@ -430,6 +430,7 @@ struct heif_error aom_set_parameter_lossless(void* encoder_raw, int enable) encoder->alpha_min_q_set = true; encoder->alpha_max_q = 0; encoder->alpha_max_q_set = true; + encoder->chroma = heif_chroma_444; } encoder->lossless = enable; @@ -990,9 +991,9 @@ struct heif_error aom_encode_image(void* encoder_raw, const struct heif_image* i if (nclx && (input_class == heif_image_input_class_normal || input_class == heif_image_input_class_thumbnail)) { - aom_codec_control(&codec, AV1E_SET_COLOR_PRIMARIES, nclx->color_primaries); - aom_codec_control(&codec, AV1E_SET_MATRIX_COEFFICIENTS, nclx->matrix_coefficients); - aom_codec_control(&codec, AV1E_SET_TRANSFER_CHARACTERISTICS, nclx->transfer_characteristics); + aom_codec_control(&codec, AV1E_SET_COLOR_PRIMARIES, static_cast(nclx->color_primaries)); + aom_codec_control(&codec, AV1E_SET_MATRIX_COEFFICIENTS, static_cast(nclx->matrix_coefficients)); + aom_codec_control(&codec, AV1E_SET_TRANSFER_CHARACTERISTICS, static_cast(nclx->transfer_characteristics)); } aom_codec_control(&codec, AOME_SET_TUNING, encoder->tune); diff --git a/libheif/plugins/encoder_rav1e.cc b/libheif/plugins/encoder_rav1e.cc index e14e9f26cc..c986511651 100644 --- a/libheif/plugins/encoder_rav1e.cc +++ b/libheif/plugins/encoder_rav1e.cc @@ -677,7 +677,7 @@ static const struct heif_encoder_plugin encoder_plugin_rav1e /* id_name */ "rav1e", /* priority */ RAV1E_PLUGIN_PRIORITY, /* supports_lossy_compression */ true, - /* supports_lossless_compression */ false, + /* supports_lossless_compression */ false, // https://github.com/xiph/rav1e/issues/151 /* get_plugin_name */ rav1e_plugin_name, /* init_plugin */ rav1e_init_plugin, /* cleanup_plugin */ rav1e_cleanup_plugin, diff --git a/libheif/plugins/encoder_svt.cc b/libheif/plugins/encoder_svt.cc index 036a1fbc0d..aa769efebc 100644 --- a/libheif/plugins/encoder_svt.cc +++ b/libheif/plugins/encoder_svt.cc @@ -859,7 +859,7 @@ static const struct heif_encoder_plugin encoder_plugin_svt /* id_name */ "svt", /* priority */ SVT_PLUGIN_PRIORITY, /* supports_lossy_compression */ true, - /* supports_lossless_compression */ false, + /* supports_lossless_compression */ false, // https://gitlab.com/AOMediaCodec/SVT-AV1/-/issues/1636 /* get_plugin_name */ svt_plugin_name, /* init_plugin */ svt_init_plugin, /* cleanup_plugin */ svt_cleanup_plugin,