in libheif/codecs/uncompressed_image.cc [1203:1341]
Error UncompressedImageCodec::encode_uncompressed_image(const std::shared_ptr<HeifFile>& heif_file,
const std::shared_ptr<HeifPixelImage>& src_image,
void* encoder_struct,
const struct heif_encoding_options& options,
std::shared_ptr<HeifContext::Image>& out_image)
{
std::shared_ptr<Box_uncC> uncC = std::make_shared<Box_uncC>();
if (options.prefer_uncC_short_form) {
maybe_make_minimised_uncC(uncC, src_image);
}
if (uncC->get_version() == 1) {
heif_file->add_property(out_image->get_id(), uncC, true);
} else {
std::shared_ptr<Box_cmpd> cmpd = std::make_shared<Box_cmpd>();
Error error = fill_cmpd_and_uncC(cmpd, uncC, src_image);
if (error) {
return error;
}
heif_file->add_property(out_image->get_id(), cmpd, true);
heif_file->add_property(out_image->get_id(), uncC, true);
}
std::vector<uint8_t> data;
if (src_image->get_colorspace() == heif_colorspace_YCbCr)
{
uint64_t offset = 0;
for (heif_channel channel : {heif_channel_Y, heif_channel_Cb, heif_channel_Cr})
{
int src_stride;
uint8_t* src_data = src_image->get_plane(channel, &src_stride);
uint64_t out_size = src_image->get_height() * src_image->get_width();
data.resize(data.size() + out_size);
for (int y = 0; y < src_image->get_height(); y++) {
memcpy(data.data() + offset + y * src_image->get_width(), src_data + src_stride * y, src_image->get_width());
}
offset += out_size;
}
heif_file->append_iloc_data(out_image->get_id(), data, 0);
}
else if (src_image->get_colorspace() == heif_colorspace_RGB)
{
if (src_image->get_chroma_format() == heif_chroma_444)
{
uint64_t offset = 0;
std::vector<heif_channel> channels = {heif_channel_R, heif_channel_G, heif_channel_B};
if (src_image->has_channel(heif_channel_Alpha))
{
channels.push_back(heif_channel_Alpha);
}
for (heif_channel channel : channels)
{
int src_stride;
uint8_t* src_data = src_image->get_plane(channel, &src_stride);
uint64_t out_size = src_image->get_height() * src_stride;
data.resize(data.size() + out_size);
memcpy(data.data() + offset, src_data, out_size);
offset += out_size;
}
heif_file->append_iloc_data(out_image->get_id(), data, 0);
}
else if ((src_image->get_chroma_format() == heif_chroma_interleaved_RGB) ||
(src_image->get_chroma_format() == heif_chroma_interleaved_RGBA) ||
(src_image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_BE) ||
(src_image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_LE) ||
(src_image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_BE) ||
(src_image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_LE))
{
int bytes_per_pixel = 0;
switch (src_image->get_chroma_format()) {
case heif_chroma_interleaved_RGB:
bytes_per_pixel=3;
break;
case heif_chroma_interleaved_RGBA:
bytes_per_pixel=4;
break;
case heif_chroma_interleaved_RRGGBB_BE:
case heif_chroma_interleaved_RRGGBB_LE:
bytes_per_pixel=6;
break;
case heif_chroma_interleaved_RRGGBBAA_BE:
case heif_chroma_interleaved_RRGGBBAA_LE:
bytes_per_pixel=8;
break;
default:
assert(false);
}
int src_stride;
uint8_t* src_data = src_image->get_plane(heif_channel_interleaved, &src_stride);
uint64_t out_size = src_image->get_height() * src_image->get_width() * bytes_per_pixel;
data.resize(out_size);
for (int y = 0; y < src_image->get_height(); y++) {
memcpy(data.data() + y * src_image->get_width() * bytes_per_pixel, src_data + src_stride * y, src_image->get_width() * bytes_per_pixel);
}
heif_file->append_iloc_data(out_image->get_id(), data, 0);
}
else
{
return Error(heif_error_Unsupported_feature,
heif_suberror_Unsupported_data_version,
"Unsupported RGB chroma");
}
}
else if (src_image->get_colorspace() == heif_colorspace_monochrome)
{
uint64_t offset = 0;
std::vector<heif_channel> channels;
if (src_image->has_channel(heif_channel_Alpha))
{
channels = {heif_channel_Y, heif_channel_Alpha};
}
else
{
channels = {heif_channel_Y};
}
for (heif_channel channel : channels)
{
int src_stride;
uint8_t* src_data = src_image->get_plane(channel, &src_stride);
uint64_t out_size = src_image->get_height() * src_stride;
data.resize(data.size() + out_size);
memcpy(data.data() + offset, src_data, out_size);
offset += out_size;
}
heif_file->append_iloc_data(out_image->get_id(), data, 0);
}
else
{
return Error(heif_error_Unsupported_feature,
heif_suberror_Unsupported_data_version,
"Unsupported colourspace");
}
// We need to ensure ispe is essential for the uncompressed case
std::shared_ptr<Box_ispe> ispe = std::make_shared<Box_ispe>();
ispe->set_size(src_image->get_width(), src_image->get_height());
heif_file->add_property(out_image->get_id(), ispe, true);
return Error::Ok;
}