Commit 2ce7b8f9 for libheif

commit 2ce7b8f9458e96451229c5653aad3ba152da5ee5
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Sun Feb 8 14:12:03 2026 +0100

    unci: remove old, obsolete unci writing

diff --git a/libheif/codecs/uncompressed/unc_encoder.cc b/libheif/codecs/uncompressed/unc_encoder.cc
index bd9b2fc4..5a357d3b 100644
--- a/libheif/codecs/uncompressed/unc_encoder.cc
+++ b/libheif/codecs/uncompressed/unc_encoder.cc
@@ -89,267 +89,6 @@ heif_uncompressed_component_format to_unc_component_format(const std::shared_ptr
 }


-Error fill_cmpd_and_uncC(std::shared_ptr<Box_cmpd>& cmpd,
-                         std::shared_ptr<Box_uncC>& uncC,
-                         const std::shared_ptr<const HeifPixelImage>& image,
-                         const heif_unci_image_parameters* parameters,
-                         bool save_alpha_channel)
-{
-  uint32_t nTileColumns = parameters->image_width / parameters->tile_width;
-  uint32_t nTileRows = parameters->image_height / parameters->tile_height;
-
-  const heif_colorspace colourspace = image->get_colorspace();
-  if (colourspace == heif_colorspace_YCbCr) {
-    if (!(image->has_channel(heif_channel_Y) && image->has_channel(heif_channel_Cb) && image->has_channel(heif_channel_Cr))) {
-      return Error(heif_error_Unsupported_feature,
-                   heif_suberror_Unsupported_data_version,
-                   "Invalid colourspace / channel combination - YCbCr");
-    }
-    Box_cmpd::Component yComponent = {component_type_Y};
-    cmpd->add_component(yComponent);
-    Box_cmpd::Component cbComponent = {component_type_Cb};
-    cmpd->add_component(cbComponent);
-    Box_cmpd::Component crComponent = {component_type_Cr};
-    cmpd->add_component(crComponent);
-    uint8_t bpp_y = image->get_bits_per_pixel(heif_channel_Y);
-    Box_uncC::Component component0 = {0, bpp_y, component_format_unsigned, 0};
-    uncC->add_component(component0);
-    uint8_t bpp_cb = image->get_bits_per_pixel(heif_channel_Cb);
-    Box_uncC::Component component1 = {1, bpp_cb, component_format_unsigned, 0};
-    uncC->add_component(component1);
-    uint8_t bpp_cr = image->get_bits_per_pixel(heif_channel_Cr);
-    Box_uncC::Component component2 = {2, bpp_cr, component_format_unsigned, 0};
-    uncC->add_component(component2);
-    if (image->get_chroma_format() == heif_chroma_444) {
-      uncC->set_sampling_type(sampling_mode_no_subsampling);
-    }
-    else if (image->get_chroma_format() == heif_chroma_422) {
-      uncC->set_sampling_type(sampling_mode_422);
-    }
-    else if (image->get_chroma_format() == heif_chroma_420) {
-      uncC->set_sampling_type(sampling_mode_420);
-    }
-    else {
-      return Error(heif_error_Unsupported_feature,
-                   heif_suberror_Unsupported_data_version,
-                   "Unsupported YCbCr sub-sampling type");
-    }
-    uncC->set_interleave_type(interleave_mode_component);
-    uncC->set_block_size(0);
-    uncC->set_components_little_endian(false);
-    uncC->set_block_pad_lsb(false);
-    uncC->set_block_little_endian(false);
-    uncC->set_block_reversed(false);
-    uncC->set_pad_unknown(false);
-    uncC->set_pixel_size(0);
-    uncC->set_row_align_size(0);
-    uncC->set_tile_align_size(0);
-    uncC->set_number_of_tile_columns(nTileColumns);
-    uncC->set_number_of_tile_rows(nTileRows);
-  }
-  else if (colourspace == heif_colorspace_RGB) {
-    if (!((image->get_chroma_format() == heif_chroma_444) ||
-          (image->get_chroma_format() == heif_chroma_interleaved_RGB) ||
-          (image->get_chroma_format() == heif_chroma_interleaved_RGBA) ||
-          (image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_BE) ||
-          (image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_LE) ||
-          (image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_BE) ||
-          (image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_LE))) {
-      return Error(heif_error_Unsupported_feature,
-                   heif_suberror_Unsupported_data_version,
-                   "Unsupported colourspace / chroma combination - RGB");
-    }
-
-    Box_cmpd::Component rComponent = {component_type_red};
-    cmpd->add_component(rComponent);
-    Box_cmpd::Component gComponent = {component_type_green};
-    cmpd->add_component(gComponent);
-    Box_cmpd::Component bComponent = {component_type_blue};
-    cmpd->add_component(bComponent);
-
-    if (save_alpha_channel &&
-        (image->get_chroma_format() == heif_chroma_interleaved_RGBA ||
-         image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_BE ||
-         image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_LE ||
-         image->has_channel(heif_channel_Alpha))) {
-      Box_cmpd::Component alphaComponent = {component_type_alpha};
-      cmpd->add_component(alphaComponent);
-    }
-
-    if (image->get_chroma_format() == heif_chroma_interleaved_RGB ||
-        image->get_chroma_format() == heif_chroma_interleaved_RGBA ||
-        image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_BE ||
-        image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_LE ||
-        image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_BE ||
-        image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_LE) {
-      uncC->set_interleave_type(interleave_mode_pixel);
-      int bpp = image->get_bits_per_pixel(heif_channel_interleaved);
-      uint8_t component_align = 1;
-      if (bpp == 8) {
-        component_align = 0;
-      }
-      else if (bpp > 8) {
-        component_align = 2;
-      }
-
-      Box_uncC::Component component0 = {0, (uint8_t) (bpp), component_format_unsigned, component_align};
-      uncC->add_component(component0);
-      Box_uncC::Component component1 = {1, (uint8_t) (bpp), component_format_unsigned, component_align};
-      uncC->add_component(component1);
-      Box_uncC::Component component2 = {2, (uint8_t) (bpp), component_format_unsigned, component_align};
-      uncC->add_component(component2);
-
-      if (save_alpha_channel &&
-          (image->get_chroma_format() == heif_chroma_interleaved_RGBA ||
-           image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_BE ||
-           image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_LE)) {
-        Box_uncC::Component component3 = {
-            3, (uint8_t) (bpp), component_format_unsigned, component_align};
-        uncC->add_component(component3);
-      }
-    }
-    else {
-      uncC->set_interleave_type(interleave_mode_component);
-
-      int bpp_red = image->get_bits_per_pixel(heif_channel_R);
-      Box_uncC::Component component0 = {0, (uint8_t) (bpp_red), component_format_unsigned, 0};
-      uncC->add_component(component0);
-
-      int bpp_green = image->get_bits_per_pixel(heif_channel_G);
-      Box_uncC::Component component1 = {1, (uint8_t) (bpp_green), component_format_unsigned, 0};
-      uncC->add_component(component1);
-
-      int bpp_blue = image->get_bits_per_pixel(heif_channel_B);
-      Box_uncC::Component component2 = {2, (uint8_t) (bpp_blue), component_format_unsigned, 0};
-      uncC->add_component(component2);
-
-      if (save_alpha_channel && image->has_channel(heif_channel_Alpha)) {
-        int bpp_alpha = image->get_bits_per_pixel(heif_channel_Alpha);
-        Box_uncC::Component component3 = {3, (uint8_t) (bpp_alpha), component_format_unsigned, 0};
-        uncC->add_component(component3);
-      }
-    }
-
-    uncC->set_sampling_type(sampling_mode_no_subsampling);
-    uncC->set_block_size(0);
-
-    if ((image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_LE) ||
-        (image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_LE)) {
-      uncC->set_components_little_endian(true);
-    }
-    else {
-      uncC->set_components_little_endian(false);
-    }
-
-    uncC->set_block_pad_lsb(false);
-    uncC->set_block_little_endian(false);
-    uncC->set_block_reversed(false);
-    uncC->set_pad_unknown(false);
-    uncC->set_pixel_size(0);
-    uncC->set_row_align_size(0);
-    uncC->set_tile_align_size(0);
-    uncC->set_number_of_tile_columns(nTileColumns);
-    uncC->set_number_of_tile_rows(nTileRows);
-  }
-  else if (colourspace == heif_colorspace_monochrome) {
-    Box_cmpd::Component monoComponent = {component_type_monochrome};
-    cmpd->add_component(monoComponent);
-
-    if (save_alpha_channel && image->has_channel(heif_channel_Alpha)) {
-      Box_cmpd::Component alphaComponent = {component_type_alpha};
-      cmpd->add_component(alphaComponent);
-    }
-
-    int bpp = image->get_bits_per_pixel(heif_channel_Y);
-    heif_uncompressed_component_format format = to_unc_component_format(image, heif_channel_Y);
-    Box_uncC::Component component0 = {0, (uint8_t) (bpp), (uint8_t) format, 0};
-    uncC->add_component(component0);
-
-    if (save_alpha_channel && image->has_channel(heif_channel_Alpha)) {
-      heif_uncompressed_component_format format_alpha = to_unc_component_format(image, heif_channel_Alpha);
-      bpp = image->get_bits_per_pixel(heif_channel_Alpha);
-      Box_uncC::Component component1 = {1, (uint8_t) (bpp), (uint8_t) format_alpha, 0};
-      uncC->add_component(component1);
-    }
-
-    uncC->set_sampling_type(sampling_mode_no_subsampling);
-    uncC->set_interleave_type(interleave_mode_component);
-    uncC->set_block_size(0);
-    uncC->set_components_little_endian(false);
-    uncC->set_block_pad_lsb(false);
-    uncC->set_block_little_endian(false);
-    uncC->set_block_reversed(false);
-    uncC->set_pad_unknown(false);
-    uncC->set_pixel_size(0);
-    uncC->set_row_align_size(0);
-    uncC->set_tile_align_size(0);
-    uncC->set_number_of_tile_columns(nTileColumns);
-    uncC->set_number_of_tile_rows(nTileRows);
-  }
-  else {
-    return Error(heif_error_Unsupported_feature,
-                 heif_suberror_Unsupported_data_version,
-                 "Unsupported colourspace");
-  }
-  return Error::Ok;
-}
-
-
-
-static void maybe_make_minimised_uncC(std::shared_ptr<Box_uncC>& uncC, const std::shared_ptr<const HeifPixelImage>& image)
-{
-  uncC->set_version(0);
-  if (image->get_colorspace() != heif_colorspace_RGB) {
-    return;
-  }
-  if (!((image->get_chroma_format() == heif_chroma_interleaved_RGB) || (image->get_chroma_format() == heif_chroma_interleaved_RGBA))) {
-    return;
-  }
-  if (image->get_bits_per_pixel(heif_channel_interleaved) != 8) {
-    return;
-  }
-  if (image->get_chroma_format() == heif_chroma_interleaved_RGBA) {
-    uncC->set_profile(fourcc("rgba"));
-  } else {
-    uncC->set_profile(fourcc("rgb3"));
-  }
-  uncC->set_version(1);
-}
-
-
-
-Result<unciHeaders> generate_headers(const std::shared_ptr<const HeifPixelImage>& src_image,
-                                     const heif_unci_image_parameters* parameters,
-                                     const heif_encoding_options& options)
-{
-  unciHeaders headers;
-
-  bool uses_tiles = (parameters->tile_width != parameters->image_width ||
-                     parameters->tile_height != parameters->image_height);
-
-  std::shared_ptr<Box_uncC> uncC = std::make_shared<Box_uncC>();
-  if (options.prefer_uncC_short_form && !uses_tiles) {
-    maybe_make_minimised_uncC(uncC, src_image);
-  }
-
-  if (uncC->get_version() == 1) {
-    headers.uncC = std::move(uncC);
-  } else {
-    std::shared_ptr<Box_cmpd> cmpd = std::make_shared<Box_cmpd>();
-
-    Error error = fill_cmpd_and_uncC(cmpd, uncC, src_image, parameters, options.save_alpha_channel);
-    if (error) {
-      return error;
-    }
-
-    headers.cmpd = std::move(cmpd);
-    headers.uncC = std::move(uncC);
-  }
-
-  return headers;
-}
-
-
 Result<Encoder::CodedImageData> unc_encoder::encode_full_image(const std::shared_ptr<const HeifPixelImage>& src_image,
                                                          const heif_encoding_options& options)
 {
@@ -408,190 +147,3 @@ Result<Encoder::CodedImageData> unc_encoder::encode_static(const std::shared_ptr
 }


-
-
-Result<std::vector<uint8_t>> encode_image_tile(const std::shared_ptr<const HeifPixelImage>& src_image, bool save_alpha)
-{
-  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})
-    {
-      if (src_image->get_bits_per_pixel(channel) != 8) {
-        return Error(heif_error_Unsupported_feature,
-                     heif_suberror_Unsupported_data_version,
-                     "Unsupported colourspace");
-      }
-
-      size_t src_stride;
-      uint32_t src_width = src_image->get_width(channel);
-      uint32_t src_height = src_image->get_height(channel);
-      const uint8_t* src_data = src_image->get_plane(channel, &src_stride);
-      uint64_t out_size = src_width * uint64_t{src_height};
-      data.resize(data.size() + out_size);
-      for (uint32_t y = 0; y < src_height; y++) {
-        memcpy(data.data() + offset + y * src_width, src_data + src_stride * y, src_width);
-      }
-      offset += out_size;
-    }
-
-    return data;
-  }
-  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)
-      {
-        size_t src_stride;
-        const uint8_t* src_data = src_image->get_plane(channel, &src_stride);
-        uint64_t out_size = static_cast<uint64_t>(src_image->get_height()) * src_image->get_width();
-
-        data.resize(data.size() + out_size);
-        for (uint32_t y = 0; y < src_image->get_height(); y++) {
-          memcpy(data.data() + offset + y * src_image->get_width(), src_data + y * src_stride, src_image->get_width());
-        }
-
-        offset += out_size;
-      }
-
-      return data;
-    }
-    else if ((save_alpha && (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))
-             ||
-             (!save_alpha && (src_image->get_chroma_format() == heif_chroma_interleaved_RGB ||
-                              src_image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_BE ||
-                              src_image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_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);
-      }
-
-      size_t src_stride;
-      const uint8_t* src_data = src_image->get_plane(heif_channel_interleaved, &src_stride);
-      uint64_t out_size = static_cast<uint64_t>(src_image->get_height()) * src_image->get_width() * bytes_per_pixel;
-      data.resize(out_size);
-      for (uint32_t 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);
-      }
-
-      return data;
-    }
-    else
-    if (!save_alpha && (src_image->get_chroma_format() == heif_chroma_interleaved_RGBA ||
-                        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_RGBA:
-          bytes_per_pixel = 3;
-          break;
-        case heif_chroma_interleaved_RRGGBBAA_BE:
-        case heif_chroma_interleaved_RRGGBBAA_LE:
-          bytes_per_pixel = 6;
-          break;
-        default:
-          assert(false);
-      }
-
-      size_t src_stride;
-      const uint8_t* src_data = src_image->get_plane(heif_channel_interleaved, &src_stride);
-      uint64_t out_size = static_cast<uint64_t>(src_image->get_height()) * src_image->get_width() * bytes_per_pixel;
-      data.resize(out_size);
-
-      if (src_image->get_chroma_format() == heif_chroma_interleaved_RGBA) {
-        for (uint32_t y = 0; y < src_image->get_height(); y++) {
-          for (uint32_t x = 0; x < src_image->get_width(); x++) {
-            data[y * src_image->get_width() * bytes_per_pixel + 3 * x + 0] = src_data[src_stride * y + 4 * x + 0];
-            data[y * src_image->get_width() * bytes_per_pixel + 3 * x + 1] = src_data[src_stride * y + 4 * x + 1];
-            data[y * src_image->get_width() * bytes_per_pixel + 3 * x + 2] = src_data[src_stride * y + 4 * x + 2];
-          }
-        }
-      }
-      else {
-        for (uint32_t y = 0; y < src_image->get_height(); y++) {
-          for (uint32_t x = 0; x < src_image->get_width(); x++) {
-            for (int i = 0; i < 6; i++) {
-              data[y * src_image->get_width() * bytes_per_pixel + 6 * x + i] = src_data[src_stride * y + 8 * x + i];
-            }
-          }
-        }
-      }
-
-      return data;
-    }
-    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)
-    {
-      if (src_image->get_bits_per_pixel(channel) != 8) {
-        return Error(heif_error_Unsupported_feature,
-                     heif_suberror_Unsupported_data_version,
-                     "Unsupported colourspace");
-      }
-
-      size_t src_stride;
-      const uint8_t* src_data = src_image->get_plane(channel, &src_stride);
-      uint64_t out_size = static_cast<uint64_t>(src_image->get_height()) * src_stride;
-      data.resize(data.size() + out_size);
-      memcpy(data.data() + offset, src_data, out_size);
-      offset += out_size;
-    }
-
-    return data;
-  }
-  else
-  {
-    return Error(heif_error_Unsupported_feature,
-                 heif_suberror_Unsupported_data_version,
-                 "Unsupported colourspace");
-  }
-}
-
-
diff --git a/libheif/codecs/uncompressed/unc_encoder.h b/libheif/codecs/uncompressed/unc_encoder.h
index 657aaffd..11ba02bd 100644
--- a/libheif/codecs/uncompressed/unc_encoder.h
+++ b/libheif/codecs/uncompressed/unc_encoder.h
@@ -58,15 +58,4 @@ public:
                                                            const heif_encoding_options& options);
 };

-
-struct unciHeaders
-{
-  std::shared_ptr<Box_uncC> uncC;
-  std::shared_ptr<Box_cmpd> cmpd;
-};
-
-Result<unciHeaders> generate_headers(const std::shared_ptr<const HeifPixelImage>& src_image,
-                                     const struct heif_unci_image_parameters* parameters,
-                                     const heif_encoding_options& options);
-
 #endif //LIBHEIF_UNC_ENCODER_H
diff --git a/libheif/image-items/unc_image.cc b/libheif/image-items/unc_image.cc
index 5e9e37f4..8e09644a 100644
--- a/libheif/image-items/unc_image.cc
+++ b/libheif/image-items/unc_image.cc
@@ -140,22 +140,23 @@ Result<std::shared_ptr<ImageItem_uncompressed>> ImageItem_uncompressed::add_unci

   // Generate headers

-  Result<unciHeaders> genHeadersResult = generate_headers(prototype, parameters, *encoding_options);
-  if (!genHeadersResult) {
-    return genHeadersResult.error();
+  // --- generate configuration property boxes
+
+  Result<const unc_encoder*> encoderResult = unc_encoder::get_unc_encoder(prototype, *encoding_options);
+  if (encoderResult.error()) {
+    return encoderResult.error();
   }

-  const unciHeaders& headers = *genHeadersResult;
+  std::shared_ptr<Box_uncC> uncC = std::make_shared<Box_uncC>();
+  std::shared_ptr<Box_cmpd> cmpd = std::make_shared<Box_cmpd>();

-  assert(headers.uncC);
+  (*encoderResult)->fill_cmpd_and_uncC(cmpd, uncC, prototype, *encoding_options);

-  if (headers.uncC) {
-    unci_image->add_property(headers.uncC, true);
+  unci_image->add_property(uncC, true);
+  if (!uncC->is_minimized()) {
+    unci_image->add_property(cmpd, true);
   }

-  if (headers.cmpd) {
-    unci_image->add_property(headers.cmpd, true);
-  }

   // Add `ispe` property

@@ -195,8 +196,9 @@ Result<std::shared_ptr<ImageItem_uncompressed>> ImageItem_uncompressed::add_unci
   // Create empty image. If we use compression, we append the data piece by piece.

   if (parameters->compression == heif_unci_compression_off) {
-    uint64_t tile_size = headers.uncC->compute_tile_data_size_bytes(parameters->image_width / headers.uncC->get_number_of_tile_columns(),
-                                                                    parameters->image_height / headers.uncC->get_number_of_tile_rows());
+    assert(false); // TODO compute_tile_data_size_bytes() is too simplistic
+    uint64_t tile_size = uncC->compute_tile_data_size_bytes(parameters->image_width / uncC->get_number_of_tile_columns(),
+                                                            parameters->image_height / uncC->get_number_of_tile_rows());

     std::vector<uint8_t> dummydata;
     dummydata.resize(tile_size);