Commit ccf4e565 for libheif

commit ccf4e56546447c559021745669a40aea615103d5
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Sun Feb 8 21:55:16 2026 +0100

    unci: use new get_tile_data_sizes() so that we can remove fetch_tile_data() from each decoder

diff --git a/libheif/codecs/uncompressed/unc_decoder.cc b/libheif/codecs/uncompressed/unc_decoder.cc
index dd461734..cb4295f1 100644
--- a/libheif/codecs/uncompressed/unc_decoder.cc
+++ b/libheif/codecs/uncompressed/unc_decoder.cc
@@ -51,6 +51,46 @@ unc_decoder::unc_decoder(uint32_t width, uint32_t height,
 }


+Error unc_decoder::fetch_tile_data(const DataExtent& dataExtent,
+                                   const UncompressedImageCodec::unci_properties& properties,
+                                   uint32_t tile_x, uint32_t tile_y,
+                                   std::vector<uint8_t>& tile_data)
+{
+  if (m_tile_width == 0 || m_tile_height == 0) {
+    return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder tile dimensions are 0"};
+  }
+
+  auto sizes = get_tile_data_sizes();
+  uint32_t tileIdx = tile_x + tile_y * (m_width / m_tile_width);
+
+  if (sizes.size() == 1) {
+    // Single contiguous read (component, pixel, mixed, row interleave)
+    uint64_t tile_start_offset = sizes[0] * tileIdx;
+    return get_compressed_image_data_uncompressed(dataExtent, properties, &tile_data, tile_start_offset, sizes[0], tileIdx, nullptr);
+  }
+  else {
+    // Scattered per-component reads (tile_component interleave)
+    uint32_t num_tiles = (m_width / m_tile_width) * (m_height / m_tile_height);
+    uint64_t component_offset = 0;
+
+    for (uint64_t size : sizes) {
+      uint64_t tile_start = component_offset + size * tileIdx;
+
+      std::vector<uint8_t> channel_data;
+      Error err = get_compressed_image_data_uncompressed(dataExtent, properties, &channel_data, tile_start, size, tileIdx, nullptr);
+      if (err) {
+        return err;
+      }
+
+      tile_data.insert(tile_data.end(), channel_data.begin(), channel_data.end());
+      component_offset += size * num_tiles;
+    }
+  }
+
+  return Error::Ok;
+}
+
+
 const Error unc_decoder::get_compressed_image_data_uncompressed(const DataExtent& dataExtent,
                                                                  const UncompressedImageCodec::unci_properties& properties,
                                                                  std::vector<uint8_t>* data,
diff --git a/libheif/codecs/uncompressed/unc_decoder.h b/libheif/codecs/uncompressed/unc_decoder.h
index fb47dd34..33cb5250 100644
--- a/libheif/codecs/uncompressed/unc_decoder.h
+++ b/libheif/codecs/uncompressed/unc_decoder.h
@@ -41,10 +41,10 @@ public:

   virtual void ensure_channel_list(std::shared_ptr<HeifPixelImage>& img) {}

-  virtual Error fetch_tile_data(const DataExtent& dataExtent,
-                                const UncompressedImageCodec::unci_properties& properties,
-                                uint32_t tile_x, uint32_t tile_y,
-                                std::vector<uint8_t>& tile_data) = 0;
+  Error fetch_tile_data(const DataExtent& dataExtent,
+                        const UncompressedImageCodec::unci_properties& properties,
+                        uint32_t tile_x, uint32_t tile_y,
+                        std::vector<uint8_t>& tile_data);

   virtual Error decode_tile(const std::vector<uint8_t>& tile_data,
                             std::shared_ptr<HeifPixelImage>& img,
@@ -65,6 +65,8 @@ protected:
               const std::shared_ptr<const Box_cmpd>& cmpd,
               const std::shared_ptr<const Box_uncC>& uncC);

+  virtual std::vector<uint64_t> get_tile_data_sizes() const = 0;
+
   const Error get_compressed_image_data_uncompressed(const DataExtent& dataExtent,
                                                      const UncompressedImageCodec::unci_properties& properties,
                                                      std::vector<uint8_t>* data,
diff --git a/libheif/codecs/uncompressed/unc_decoder_component_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_component_interleave.cc
index a86d3b6a..92dffe26 100644
--- a/libheif/codecs/uncompressed/unc_decoder_component_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_component_interleave.cc
@@ -22,29 +22,51 @@
 #include "context.h"
 #include "error.h"

-#include <cassert>
-#include <map>
 #include <vector>


-Error unc_decoder_component_interleave::fetch_tile_data(const DataExtent& dataExtent,
-                                                         const UncompressedImageCodec::unci_properties& properties,
-                                                         uint32_t tile_x, uint32_t tile_y,
-                                                         std::vector<uint8_t>& tile_data)
+std::vector<uint64_t> unc_decoder_component_interleave::get_tile_data_sizes() const
 {
-  if (m_tile_width == 0) {
-    return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_component_interleave tile_width=0"};
-  }
-
   if (m_uncC->get_interleave_type() == interleave_mode_tile_component) {
-    return fetch_tile_data_tile_component(dataExtent, properties, tile_x, tile_y, tile_data);
-  }
+    // Per-component sizes for scattered reads
+    std::vector<uint64_t> sizes;
+
+    for (const ChannelListEntry& entry : channelList) {
+      uint32_t bits_per_pixel = entry.bits_per_component_sample;
+      if (entry.component_alignment > 0) {
+        uint32_t bytes_per_component = (bits_per_pixel + 7) / 8;
+        skip_to_alignment(bytes_per_component, entry.component_alignment);
+        bits_per_pixel = bytes_per_component * 8;
+      }
+
+      uint32_t bytes_per_row;
+      if (m_uncC->get_pixel_size() != 0) {
+        uint32_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
+        skip_to_alignment(bytes_per_pixel, m_uncC->get_pixel_size());
+        bytes_per_row = bytes_per_pixel * m_tile_width;
+      }
+      else {
+        bytes_per_row = (bits_per_pixel * m_tile_width + 7) / 8;
+      }
+
+      skip_to_alignment(bytes_per_row, m_uncC->get_row_align_size());
+
+      uint64_t component_tile_size = bytes_per_row * static_cast<uint64_t>(m_tile_height);
+
+      if (m_uncC->get_tile_align_size() != 0) {
+        skip_to_alignment(component_tile_size, m_uncC->get_tile_align_size());
+      }

-  // --- interleave_mode_component: single contiguous read
+      sizes.push_back(component_tile_size);
+    }
+
+    return sizes;
+  }

+  // interleave_mode_component: single contiguous block
   uint64_t total_tile_size = 0;

-  for (ChannelListEntry& entry : channelList) {
+  for (const ChannelListEntry& entry : channelList) {
     uint32_t bits_per_component = entry.bits_per_component_sample;
     if (entry.component_alignment > 0) {
       uint32_t bytes_per_component = (bits_per_component + 7) / 8;
@@ -62,78 +84,7 @@ Error unc_decoder_component_interleave::fetch_tile_data(const DataExtent& dataEx
     skip_to_alignment(total_tile_size, m_uncC->get_tile_align_size());
   }

-  assert(m_tile_width > 0);
-  uint32_t tileIdx = tile_x + tile_y * (m_width / m_tile_width);
-  uint64_t tile_start_offset = total_tile_size * tileIdx;
-
-  return get_compressed_image_data_uncompressed(dataExtent, properties, &tile_data, tile_start_offset, total_tile_size, tileIdx, nullptr);
-}
-
-
-Error unc_decoder_component_interleave::fetch_tile_data_tile_component(const DataExtent& dataExtent,
-                                                                        const UncompressedImageCodec::unci_properties& properties,
-                                                                        uint32_t tile_x, uint32_t tile_y,
-                                                                        std::vector<uint8_t>& tile_data)
-{
-  if (m_tile_height == 0) {
-    return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_component_interleave tile_height=0"};
-  }
-
-  // Compute per-channel tile sizes (with per-channel tile alignment)
-  std::map<heif_channel, uint64_t> channel_tile_size;
-
-  for (ChannelListEntry& entry : channelList) {
-    uint32_t bits_per_pixel = entry.bits_per_component_sample;
-    if (entry.component_alignment > 0) {
-      uint32_t bytes_per_component = (bits_per_pixel + 7) / 8;
-      skip_to_alignment(bytes_per_component, entry.component_alignment);
-      bits_per_pixel = bytes_per_component * 8;
-    }
-
-    uint32_t bytes_per_row;
-    if (m_uncC->get_pixel_size() != 0) {
-      uint32_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
-      skip_to_alignment(bytes_per_pixel, m_uncC->get_pixel_size());
-      bytes_per_row = bytes_per_pixel * m_tile_width;
-    }
-    else {
-      bytes_per_row = (bits_per_pixel * m_tile_width + 7) / 8;
-    }
-
-    skip_to_alignment(bytes_per_row, m_uncC->get_row_align_size());
-
-    uint64_t component_tile_size = bytes_per_row * static_cast<uint64_t>(m_tile_height);
-
-    if (m_uncC->get_tile_align_size() != 0) {
-      skip_to_alignment(component_tile_size, m_uncC->get_tile_align_size());
-    }
-
-    channel_tile_size[entry.channel] = component_tile_size;
-  }
-
-  // Read each channel's tile data and concatenate
-  uint64_t component_start_offset = 0;
-  uint32_t num_tiles = (m_width / m_tile_width) * (m_height / m_tile_height);
-  uint32_t tileIdx = tile_x + tile_y * (m_width / m_tile_width);
-
-  assert(m_tile_width > 0);
-  assert(m_tile_height > 0);
-
-  for (ChannelListEntry& entry : channelList) {
-    uint64_t tile_start_offset = component_start_offset + channel_tile_size[entry.channel] * tileIdx;
-
-    std::vector<uint8_t> channel_data;
-    Error err = get_compressed_image_data_uncompressed(dataExtent, properties, &channel_data, tile_start_offset, channel_tile_size[entry.channel], tileIdx, nullptr);
-    if (err) {
-      return err;
-    }
-
-    tile_data.insert(tile_data.end(), channel_data.begin(), channel_data.end());
-
-    component_start_offset += channel_tile_size[entry.channel] * num_tiles;
-  }
-
-  return Error::Ok;
+  return {total_tile_size};
 }


diff --git a/libheif/codecs/uncompressed/unc_decoder_component_interleave.h b/libheif/codecs/uncompressed/unc_decoder_component_interleave.h
index 0d54771d..bd387913 100644
--- a/libheif/codecs/uncompressed/unc_decoder_component_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_component_interleave.h
@@ -34,21 +34,12 @@ public:
                                     std::shared_ptr<const Box_uncC> uncC) :
       unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}

-  Error fetch_tile_data(const DataExtent& dataExtent,
-                        const UncompressedImageCodec::unci_properties& properties,
-                        uint32_t tile_x, uint32_t tile_y,
-                        std::vector<uint8_t>& tile_data) override;
+  std::vector<uint64_t> get_tile_data_sizes() const override;

   Error decode_tile(const std::vector<uint8_t>& tile_data,
                     std::shared_ptr<HeifPixelImage>& img,
                     uint32_t out_x0, uint32_t out_y0,
                     uint32_t tile_x, uint32_t tile_y) override;
-
-private:
-  Error fetch_tile_data_tile_component(const DataExtent& dataExtent,
-                                       const UncompressedImageCodec::unci_properties& properties,
-                                       uint32_t tile_x, uint32_t tile_y,
-                                       std::vector<uint8_t>& tile_data);
 };


diff --git a/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.cc
index 48eca4d0..437d45fe 100644
--- a/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.cc
@@ -23,22 +23,14 @@
 #include "error.h"

 #include <cstring>
-#include <cassert>
 #include <vector>


-Error unc_decoder_mixed_interleave::fetch_tile_data(const DataExtent& dataExtent,
-                                                     const UncompressedImageCodec::unci_properties& properties,
-                                                     uint32_t tile_x, uint32_t tile_y,
-                                                     std::vector<uint8_t>& tile_data)
+std::vector<uint64_t> unc_decoder_mixed_interleave::get_tile_data_sizes() const
 {
-  if (m_tile_width == 0) {
-    return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_mixed_interleave tile_width=0"};
-  }
-
   uint64_t tile_size = 0;

-  for (ChannelListEntry& entry : channelList) {
+  for (const ChannelListEntry& entry : channelList) {
     if (entry.channel == heif_channel_Cb || entry.channel == heif_channel_Cr) {
       uint32_t bits_per_row = entry.bits_per_component_sample * entry.tile_width;
       bits_per_row = (bits_per_row + 7) & ~7U; // align to byte boundary
@@ -64,11 +56,7 @@ Error unc_decoder_mixed_interleave::fetch_tile_data(const DataExtent& dataExtent
     skip_to_alignment(tile_size, m_uncC->get_tile_align_size());
   }

-  assert(m_tile_width > 0);
-  uint32_t tileIdx = tile_x + tile_y * (m_width / m_tile_width);
-  uint64_t tile_start_offset = tile_size * tileIdx;
-
-  return get_compressed_image_data_uncompressed(dataExtent, properties, &tile_data, tile_start_offset, tile_size, tileIdx, nullptr);
+  return {tile_size};
 }


diff --git a/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.h b/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.h
index 7b6b58f5..0b177cce 100644
--- a/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.h
@@ -32,10 +32,7 @@ public:
   unc_decoder_mixed_interleave(uint32_t width, uint32_t height, std::shared_ptr<const Box_cmpd> cmpd, std::shared_ptr<const Box_uncC> uncC) :
       unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}

-  Error fetch_tile_data(const DataExtent& dataExtent,
-                        const UncompressedImageCodec::unci_properties& properties,
-                        uint32_t tile_x, uint32_t tile_y,
-                        std::vector<uint8_t>& tile_data) override;
+  std::vector<uint64_t> get_tile_data_sizes() const override;

   Error decode_tile(const std::vector<uint8_t>& tile_data,
                     std::shared_ptr<HeifPixelImage>& img,
diff --git a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
index 93933ebc..e9d9ed70 100644
--- a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
@@ -22,24 +22,16 @@
 #include "context.h"
 #include "error.h"

-#include <cassert>
 #include <vector>


-Error unc_decoder_pixel_interleave::fetch_tile_data(const DataExtent& dataExtent,
-                                                     const UncompressedImageCodec::unci_properties& properties,
-                                                     uint32_t tile_x, uint32_t tile_y,
-                                                     std::vector<uint8_t>& tile_data)
+std::vector<uint64_t> unc_decoder_pixel_interleave::get_tile_data_sizes() const
 {
-  if (m_tile_width == 0) {
-    return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_pixel_interleave tile_width=0"};
-  }
-
   uint32_t bits_per_row = 0;
   for (uint32_t x = 0; x < m_tile_width; x++) {
     uint32_t bits_per_pixel = 0;

-    for (ChannelListEntry& entry : channelList) {
+    for (const ChannelListEntry& entry : channelList) {
       uint32_t bits_per_component = entry.bits_per_component_sample;
       if (entry.component_alignment > 0) {
         // start at byte boundary
@@ -70,11 +62,7 @@ Error unc_decoder_pixel_interleave::fetch_tile_data(const DataExtent& dataExtent
     skip_to_alignment(total_tile_size, m_uncC->get_tile_align_size());
   }

-  assert(m_tile_width > 0);
-  uint32_t tileIdx = tile_x + tile_y * (m_width / m_tile_width);
-  uint64_t tile_start_offset = total_tile_size * tileIdx;
-
-  return get_compressed_image_data_uncompressed(dataExtent, properties, &tile_data, tile_start_offset, total_tile_size, tileIdx, nullptr);
+  return {total_tile_size};
 }


diff --git a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.h b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.h
index 40eb5d44..370b2e37 100644
--- a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.h
@@ -32,10 +32,7 @@ public:
   unc_decoder_pixel_interleave(uint32_t width, uint32_t height, std::shared_ptr<const Box_cmpd> cmpd, std::shared_ptr<const Box_uncC> uncC) :
       unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}

-  Error fetch_tile_data(const DataExtent& dataExtent,
-                        const UncompressedImageCodec::unci_properties& properties,
-                        uint32_t tile_x, uint32_t tile_y,
-                        std::vector<uint8_t>& tile_data) override;
+  std::vector<uint64_t> get_tile_data_sizes() const override;

   Error decode_tile(const std::vector<uint8_t>& tile_data,
                     std::shared_ptr<HeifPixelImage>& img,
diff --git a/libheif/codecs/uncompressed/unc_decoder_row_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_row_interleave.cc
index f437a1fb..3b03ed9d 100644
--- a/libheif/codecs/uncompressed/unc_decoder_row_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_row_interleave.cc
@@ -22,21 +22,13 @@
 #include "context.h"
 #include "error.h"

-#include <cassert>
 #include <vector>


-Error unc_decoder_row_interleave::fetch_tile_data(const DataExtent& dataExtent,
-                                                   const UncompressedImageCodec::unci_properties& properties,
-                                                   uint32_t tile_x, uint32_t tile_y,
-                                                   std::vector<uint8_t>& tile_data)
+std::vector<uint64_t> unc_decoder_row_interleave::get_tile_data_sizes() const
 {
-  if (m_tile_width == 0) {
-    return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_row_interleave tile_width=0"};
-  }
-
   uint32_t bits_per_row = 0;
-  for (ChannelListEntry& entry : channelList) {
+  for (const ChannelListEntry& entry : channelList) {
     uint32_t bits_per_component = entry.bits_per_component_sample;
     if (entry.component_alignment > 0) {
       // start at byte boundary
@@ -64,18 +56,13 @@ Error unc_decoder_row_interleave::fetch_tile_data(const DataExtent& dataExtent,
     skip_to_alignment(bytes_per_row, m_uncC->get_row_align_size());
   }

-  uint64_t total_tile_size = 0;
-  total_tile_size += bytes_per_row * static_cast<uint64_t>(m_tile_height);
+  uint64_t total_tile_size = bytes_per_row * static_cast<uint64_t>(m_tile_height);

   if (m_uncC->get_tile_align_size() != 0) {
     skip_to_alignment(total_tile_size, m_uncC->get_tile_align_size());
   }

-  assert(m_tile_width > 0);
-  uint32_t tileIdx = tile_x + tile_y * (m_width / m_tile_width);
-  uint64_t tile_start_offset = total_tile_size * tileIdx;
-
-  return get_compressed_image_data_uncompressed(dataExtent, properties, &tile_data, tile_start_offset, total_tile_size, tileIdx, nullptr);
+  return {total_tile_size};
 }


diff --git a/libheif/codecs/uncompressed/unc_decoder_row_interleave.h b/libheif/codecs/uncompressed/unc_decoder_row_interleave.h
index 0d8d9304..44fcaff9 100644
--- a/libheif/codecs/uncompressed/unc_decoder_row_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_row_interleave.h
@@ -34,10 +34,7 @@ public:
       unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}


-  Error fetch_tile_data(const DataExtent& dataExtent,
-                        const UncompressedImageCodec::unci_properties& properties,
-                        uint32_t tile_x, uint32_t tile_y,
-                        std::vector<uint8_t>& tile_data) override;
+  std::vector<uint64_t> get_tile_data_sizes() const override;

   Error decode_tile(const std::vector<uint8_t>& tile_data,
                     std::shared_ptr<HeifPixelImage>& img,
diff --git a/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.cc
deleted file mode 100644
index 6d675bbc..00000000
--- a/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * HEIF codec.
- * Copyright (c) 2023 Dirk Farin <dirk.farin@gmail.com>
- *
- * This file is part of libheif.
- *
- * libheif is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * libheif is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libheif.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "unc_decoder_tile_component_interleave.h"
-#include "context.h"
-#include "error.h"
-
-#include <map>
-#include <cassert>
-#include <vector>
-
-
-Error unc_decoder_tile_component_interleave::decode_tile(const DataExtent& dataExtent,
-                                                          const UncompressedImageCodec::unci_properties& properties,
-                                                          std::shared_ptr<HeifPixelImage>& img,
-                                                          uint32_t out_x0, uint32_t out_y0,
-                                                          uint32_t tile_column, uint32_t tile_row)
-{
-  ensureChannelList(img);
-
-  if (m_tile_width == 0) {
-    return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_tile_component_interleave tile_width=0"};
-  }
-  if (m_tile_height == 0) {
-    return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_tile_component_interleave tile_height=0"};
-  }
-
-  // --- compute which file range we need to read for the tile
-
-  std::map<heif_channel, uint64_t> channel_tile_size;
-
-  for (ChannelListEntry& entry : channelList) {
-    uint32_t bits_per_pixel = entry.bits_per_component_sample;
-    if (entry.component_alignment > 0) {
-      uint32_t bytes_per_component = (bits_per_pixel + 7) / 8;
-      skip_to_alignment(bytes_per_component, entry.component_alignment);
-      bits_per_pixel = bytes_per_component * 8;
-    }
-
-    uint32_t bytes_per_row;
-    if (m_uncC->get_pixel_size() != 0) { // TODO: does pixel_size apply here?
-      uint32_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
-      skip_to_alignment(bytes_per_pixel, m_uncC->get_pixel_size());
-      bytes_per_row = bytes_per_pixel * m_tile_width;
-    }
-    else {
-      bytes_per_row = (bits_per_pixel * m_tile_width + 7) / 8;
-    }
-
-    skip_to_alignment(bytes_per_row, m_uncC->get_row_align_size());
-
-    uint64_t component_tile_size = bytes_per_row * static_cast<uint64_t>(m_tile_height);
-
-    if (m_uncC->get_tile_align_size() != 0) {
-      skip_to_alignment(component_tile_size, m_uncC->get_tile_align_size());
-    }
-
-    channel_tile_size[entry.channel] = component_tile_size;
-  }
-
-  uint64_t component_start_offset = 0;
-
-  assert(m_tile_width > 0);
-  assert(m_tile_height > 0);
-
-  for (ChannelListEntry& entry : channelList) {
-    if (!entry.use_channel) {
-      component_start_offset += channel_tile_size[entry.channel] * (m_width / m_tile_width) * (m_height / m_tile_height);
-      continue;
-    }
-
-    // --- read required file range
-
-    uint32_t tileIdx = tile_column + tile_row * (m_width / m_tile_width);
-    uint64_t tile_start_offset = component_start_offset + channel_tile_size[entry.channel] * tileIdx;
-
-    std::vector<uint8_t> src_data;
-    Error err = get_compressed_image_data_uncompressed(dataExtent, properties, &src_data, tile_start_offset, channel_tile_size[entry.channel], tileIdx, nullptr);
-    if (err) {
-      return err;
-    }
-
-    UncompressedBitReader srcBits(src_data);
-
-    srcBits.markTileStart();
-    for (uint32_t tile_y = 0; tile_y < entry.tile_height; tile_y++) {
-      srcBits.markRowStart();
-      uint64_t dst_row_offset = entry.getDestinationRowOffset(0, tile_y + out_y0);
-      processComponentRow(entry, srcBits, dst_row_offset + out_x0 * entry.bytes_per_component_sample, 0);
-      srcBits.handleRowAlignment(m_uncC->get_row_align_size());
-    }
-    srcBits.handleTileAlignment(m_uncC->get_tile_align_size());
-
-
-    component_start_offset += channel_tile_size[entry.channel] * (m_width / m_tile_width) * (m_height / m_tile_height);
-  }
-
-  return Error::Ok;
-}
-
-
-bool unc_decoder_factory_tile_component_interleave::can_decode(const std::shared_ptr<const Box_uncC>& uncC) const
-{
-  return uncC->get_interleave_type() == interleave_mode_tile_component;
-}
-
-std::unique_ptr<unc_decoder> unc_decoder_factory_tile_component_interleave::create(
-    uint32_t width, uint32_t height,
-    const std::shared_ptr<const Box_cmpd>& cmpd,
-    const std::shared_ptr<const Box_uncC>& uncC) const
-{
-  return std::make_unique<unc_decoder_tile_component_interleave>(width, height, cmpd, uncC);
-}
diff --git a/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.h b/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.h
deleted file mode 100644
index d940d2a8..00000000
--- a/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * HEIF codec.
- * Copyright (c) 2023 Dirk Farin <dirk.farin@gmail.com>
- *
- * This file is part of libheif.
- *
- * libheif is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * libheif is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libheif.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIBHEIF_UNC_DECODER_TILE_COMPONENT_INTERLEAVE_H
-#define LIBHEIF_UNC_DECODER_TILE_COMPONENT_INTERLEAVE_H
-
-#include "unc_decoder_legacybase.h"
-#include <memory>
-#include <utility>
-
-
-class unc_decoder_tile_component_interleave : public unc_decoder_legacybase
-{
-public:
-  unc_decoder_tile_component_interleave(uint32_t width, uint32_t height,
-                                         std::shared_ptr<const Box_cmpd> cmpd, std::shared_ptr<const Box_uncC> uncC) :
-      unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}
-
-  Error decode_tile(const DataExtent& dataExtent,
-                    const UncompressedImageCodec::unci_properties& properties,
-                    std::shared_ptr<HeifPixelImage>& img,
-                    uint32_t out_x0, uint32_t out_y0,
-                    uint32_t tile_column, uint32_t tile_row) override;
-};
-
-
-class unc_decoder_factory_tile_component_interleave : public unc_decoder_factory
-{
-private:
-  bool can_decode(const std::shared_ptr<const Box_uncC>& uncC) const override;
-
-  std::unique_ptr<unc_decoder> create(
-      uint32_t width, uint32_t height,
-      const std::shared_ptr<const Box_cmpd>& cmpd,
-      const std::shared_ptr<const Box_uncC>& uncC) const override;
-};
-
-#endif // LIBHEIF_UNC_DECODER_TILE_COMPONENT_INTERLEAVE_H