in libheif/context.cc [1603:1727]
Error HeifContext::decode_image_planar_for_moov(heif_item_id ID,
std::shared_ptr<HeifPixelImage>& img,
heif_colorspace out_colorspace,
heif_chroma out_chroma,
const struct heif_decoding_options& options, bool alphaImage) const
{
std::shared_ptr<Image> imginfo;
if (m_all_images.find(ID) != m_all_images.end()) {
imginfo = m_all_images.find(ID)->second;
}
assert(imginfo);
Error error;
if(m_heif_file->get_hvc1_box())
{
heif_compression_format compression = heif_compression_undefined;
compression = heif_compression_HEVC;
const struct heif_decoder_plugin* decoder_plugin = get_decoder(compression, options.decoder_id);
if (!decoder_plugin) {
return Error(heif_error_Unsupported_feature, heif_suberror_Unsupported_codec);
}
std::vector<uint8_t> data;
error = m_heif_file->get_compressed_image_data_for_moov(ID, &data);
if (error) {
return error;
}
void* decoder;
struct heif_error err = decoder_plugin->new_decoder(&decoder, m_max_decoder_threads);
if (err.code != heif_error_Ok) {
return Error(err.code, err.subcode, err.message);
}
if (decoder_plugin->plugin_api_version >= 2) {
if (decoder_plugin->set_strict_decoding) {
decoder_plugin->set_strict_decoding(decoder, options.strict_decoding );
}
}
err = decoder_plugin->push_data(decoder, data.data(), data.size());
if (err.code != heif_error_Ok) {
decoder_plugin->free_decoder(decoder);
return Error(err.code, err.subcode, err.message);
}
heif_image* decoded_img = nullptr;
err = decoder_plugin->decode_image(decoder, &decoded_img);
if (err.code != heif_error_Ok) {
decoder_plugin->free_decoder(decoder);
return Error(err.code, err.subcode, err.message);
}
if (!decoded_img) {
// TODO(farindk): The plugin should return an error in this case.
decoder_plugin->free_decoder(decoder);
return Error(heif_error_Decoder_plugin_error, heif_suberror_Unspecified);
}
img = std::move(decoded_img->image);
heif_image_release(decoded_img);
decoder_plugin->free_decoder(decoder);
// --- convert to output chroma format
// If there is an NCLX profile in the HEIF/AVIF metadata, use this for the color conversion.
// Otherwise, use the profile that is stored in the image stream itself and then set the
// (non-NCLX) profile later.
auto nclx = imginfo->get_color_profile_nclx();
if (nclx) {
img->set_color_profile_nclx(nclx);
}
auto icc = imginfo->get_color_profile_icc();
if (icc) {
img->set_color_profile_icc(icc);
}
if (alphaImage) {
// no color conversion required
}
else
{
heif_colorspace target_colorspace = (out_colorspace == heif_colorspace_undefined ?
img->get_colorspace() :
out_colorspace);
// if (!alphaImage && target_colorspace == heif_colorspace_YCbCr) {
// target_colorspace = heif_colorspace_RGB;
// }
// heif_chroma target_chroma = (target_colorspace == heif_colorspace_monochrome ?
// heif_chroma_monochrome : heif_chroma_444);
heif_chroma target_chroma = out_chroma == heif_chroma_undefined ? img->get_chroma_format() :
(target_colorspace == heif_colorspace_monochrome ? heif_chroma_monochrome : heif_chroma_444);
bool different_chroma = (target_chroma != img->get_chroma_format());
bool different_colorspace = (target_colorspace != img->get_colorspace());
int bpp = options.convert_hdr_to_8bit ? 8 : 0;
if (different_chroma || different_colorspace) {
if(options.ext_dst && options.ext_dst_enable) {
img->set_image_external_info(true, options.ext_dst, options.ext_dst_len, options.ext_dst_stride);
}
img = convert_colorspace(img, target_colorspace, target_chroma, nullptr, bpp, options.color_conversion_options);
if (!img) {
return Error(heif_error_Unsupported_feature, heif_suberror_Unsupported_color_conversion);
}
}
}
}
else
{
// Should not reach this, was already rejected by "get_image_data".
return Error(heif_error_Unsupported_feature,
heif_suberror_Unsupported_image_type);
}
return Error::Ok;
}