in libheif/codecs/uncompressed_image.cc [862:987]
Error UncompressedImageCodec::decode_uncompressed_image(const HeifContext* context,
heif_item_id ID,
std::shared_ptr<HeifPixelImage>& img,
const std::vector<uint8_t>& source_data)
{
if (source_data.empty()) {
return {heif_error_Invalid_input,
heif_suberror_Unspecified,
"Uncompressed image data is empty"};
}
// Get the properties for this item
// We need: ispe, cmpd, uncC
std::vector<std::shared_ptr<Box>> item_properties;
Error error = context->get_heif_file()->get_properties(ID, item_properties);
if (error) {
printf("failed to get properties\n");
return error;
}
uint32_t width = 0;
uint32_t height = 0;
bool found_ispe = false;
std::shared_ptr<Box_cmpd> cmpd;
std::shared_ptr<Box_uncC> uncC;
std::shared_ptr<Box_cmpC> cmpC;
std::shared_ptr<Box_icbr> icbr;
for (const auto& prop : item_properties) {
auto ispe = std::dynamic_pointer_cast<Box_ispe>(prop);
if (ispe) {
width = ispe->get_width();
height = ispe->get_height();
error = context->check_resolution(width, height);
if (error) {
return error;
}
found_ispe = true;
}
auto maybe_cmpd = std::dynamic_pointer_cast<Box_cmpd>(prop);
if (maybe_cmpd) {
cmpd = maybe_cmpd;
}
auto maybe_uncC = std::dynamic_pointer_cast<Box_uncC>(prop);
if (maybe_uncC) {
uncC = maybe_uncC;
}
auto maybe_cmpC = std::dynamic_pointer_cast<Box_cmpC>(prop);
if (maybe_cmpC) {
cmpC = maybe_cmpC;
}
auto maybe_icbr = std::dynamic_pointer_cast<Box_icbr>(prop);
if (maybe_icbr) {
icbr = maybe_icbr;
}
}
// if we miss a required box, show error
if (!found_ispe) {
return Error(heif_error_Unsupported_feature,
heif_suberror_Unsupported_data_version,
"Missing required ispe box for uncompressed codec");
}
if (!uncC) {
return Error(heif_error_Unsupported_feature,
heif_suberror_Unsupported_data_version,
"Missing required uncC box for uncompressed codec");
}
if (!cmpd && (uncC->get_version() !=1)) {
return Error(heif_error_Unsupported_feature,
heif_suberror_Unsupported_data_version,
"Missing required cmpd or uncC version 1 box for uncompressed codec");
}
// check if we support the type of image
error = uncompressed_image_type_is_supported(uncC, cmpd);
if (error) {
printf("unsupported image type\n");
return error;
}
img = std::make_shared<HeifPixelImage>();
heif_chroma chroma;
heif_colorspace colourspace;
error = get_heif_chroma_uncompressed(uncC, cmpd, &chroma, &colourspace);
if (error) {
printf("failed to get chroma uncompressed\n");
return error;
}
img->create(width, height,
colourspace,
chroma);
for (Box_uncC::Component component : uncC->get_components()) {
heif_channel channel;
if (map_uncompressed_component_to_channel(cmpd, uncC, component, &channel)) {
if ((channel == heif_channel_Cb) || (channel == heif_channel_Cr)) {
img->add_plane(channel, (width / chroma_h_subsampling(chroma)), (height / chroma_v_subsampling(chroma)), component.component_bit_depth);
} else {
img->add_plane(channel, width, height, component.component_bit_depth);
}
}
}
AbstractDecoder *decoder = makeDecoder(width, height, cmpd, uncC);
if (decoder != nullptr) {
Error result = decoder->decode(source_data, img);
delete decoder;
return result;
} else {
printf("bad interleave mode - we should have detected this earlier: %d\n", uncC->get_interleave_type());
std::stringstream sstr;
sstr << "Uncompressed interleave_type of " << ((int) uncC->get_interleave_type()) << " is not implemented yet";
return Error(heif_error_Unsupported_feature,
heif_suberror_Unsupported_data_version,
sstr.str());
}
}