Commit f6436f22 for libheif
commit f6436f228379d2ab8528f78a1f229cb6d9d083e5
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sun Feb 8 20:46:58 2026 +0100
unci: refactor unc_decoder into a clean base class and move everything else into unc_decoder_legacybase
diff --git a/libheif/CMakeLists.txt b/libheif/CMakeLists.txt
index 6e789e0b..93843028 100644
--- a/libheif/CMakeLists.txt
+++ b/libheif/CMakeLists.txt
@@ -295,6 +295,8 @@ if (WITH_UNCOMPRESSED_CODEC)
codecs/uncompressed/unc_enc.cc
codecs/uncompressed/unc_decoder.h
codecs/uncompressed/unc_decoder.cc
+ codecs/uncompressed/unc_decoder_legacybase.h
+ codecs/uncompressed/unc_decoder_legacybase.cc
codecs/uncompressed/unc_decoder_component_interleave.h
codecs/uncompressed/unc_decoder_component_interleave.cc
codecs/uncompressed/unc_decoder_pixel_interleave.h
diff --git a/libheif/codecs/uncompressed/unc_codec.cc b/libheif/codecs/uncompressed/unc_codec.cc
index cde86830..fcfb03cc 100644
--- a/libheif/codecs/uncompressed/unc_codec.cc
+++ b/libheif/codecs/uncompressed/unc_codec.cc
@@ -527,8 +527,6 @@ Error UncompressedImageCodec::decode_uncompressed_image_tile(const HeifContext*
auto& decoder = *decoderResult;
- decoder->buildChannelList(img);
-
DataExtent dataExtent;
dataExtent.set_from_image_item(file, ID);
diff --git a/libheif/codecs/uncompressed/unc_decoder.cc b/libheif/codecs/uncompressed/unc_decoder.cc
index bffd52f3..2dfa9b10 100644
--- a/libheif/codecs/uncompressed/unc_decoder.cc
+++ b/libheif/codecs/uncompressed/unc_decoder.cc
@@ -18,42 +18,30 @@
* along with libheif. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <cstring>
-#include <algorithm>
-#include <iostream>
#include <cassert>
-#include <utility>
+#include <sstream>
-#if ((defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__PGI)) && __GNUC__ < 9) || (defined(__clang__) && __clang_major__ < 10)
-#include <type_traits>
-#else
-#include <bit>
-#endif
-
-#include "common_utils.h"
-#include "context.h"
-#include "compression.h"
-#include "error.h"
-#include "libheif/heif.h"
-#include "unc_types.h"
-#include "unc_boxes.h"
-#include "unc_codec.h"
#include "unc_decoder.h"
#include "unc_decoder_component_interleave.h"
#include "unc_decoder_pixel_interleave.h"
#include "unc_decoder_mixed_interleave.h"
#include "unc_decoder_row_interleave.h"
#include "unc_decoder_tile_component_interleave.h"
+#include "unc_codec.h"
+#include "unc_boxes.h"
#include "codecs/decoder.h"
-#include "codecs/uncompressed/unc_codec.h"
#include "security_limits.h"
-unc_decoder::unc_decoder(uint32_t width, uint32_t height, const std::shared_ptr<const Box_cmpd> cmpd, const std::shared_ptr<const Box_uncC> uncC) :
- m_width(width),
- m_height(height),
- m_cmpd(std::move(cmpd)),
- m_uncC(std::move(uncC))
+// --- unc_decoder ---
+
+unc_decoder::unc_decoder(uint32_t width, uint32_t height,
+ const std::shared_ptr<const Box_cmpd>& cmpd,
+ const std::shared_ptr<const Box_uncC>& uncC)
+ : m_width(width),
+ m_height(height),
+ m_cmpd(cmpd),
+ m_uncC(uncC)
{
m_tile_height = m_height / m_uncC->get_number_of_tile_rows();
m_tile_width = m_width / m_uncC->get_number_of_tile_columns();
@@ -62,285 +50,28 @@ unc_decoder::unc_decoder(uint32_t width, uint32_t height, const std::shared_ptr<
assert(m_tile_height > 0);
}
-void unc_decoder::buildChannelList(std::shared_ptr<HeifPixelImage>& img)
-{
- for (Box_uncC::Component component : m_uncC->get_components()) {
- ChannelListEntry entry = buildChannelListEntry(component, img);
- channelList.push_back(entry);
- }
-}
-
-void unc_decoder::memcpy_to_native_endian(uint8_t* dst, uint32_t value, uint32_t bytes_per_sample)
-{
- // TODO: this assumes that the file endianness is always big-endian. The endianness flags in the uncC header are not taken into account yet.
- if (bytes_per_sample==1) {
- *dst = static_cast<uint8_t>(value);
- return;
- }
- else if (std::endian::native == std::endian::big) {
- for (uint32_t i = 0; i < bytes_per_sample; i++) {
- dst[bytes_per_sample - 1 - i] = static_cast<uint8_t>((value >> (i * 8)) & 0xFF);
- }
- }
- else {
- for (uint32_t i = 0; i < bytes_per_sample; i++) {
- dst[i] = static_cast<uint8_t>((value >> (i * 8)) & 0xFF);
- }
- }
-}
-
-void unc_decoder::processComponentSample(UncompressedBitReader& srcBits, const ChannelListEntry& entry, uint64_t dst_row_offset, uint32_t tile_column, uint32_t tile_x)
-{
- uint64_t dst_col_number = static_cast<uint64_t>(tile_column) * entry.tile_width + tile_x;
- uint64_t dst_column_offset = dst_col_number * entry.bytes_per_component_sample;
- int val = srcBits.get_bits(entry.bits_per_component_sample); // get_bits() reads input in big-endian order
- memcpy_to_native_endian(entry.dst_plane + dst_row_offset + dst_column_offset, val, entry.bytes_per_component_sample);
-}
-
-// Handles the case where a row consists of a single component type
-// Not valid for Pixel interleave
-// Not valid for the Cb/Cr channels in Mixed Interleave
-// Not valid for multi-Y pixel interleave
-void unc_decoder::processComponentRow(ChannelListEntry& entry, UncompressedBitReader& srcBits, uint64_t dst_row_offset, uint32_t tile_column)
-{
- for (uint32_t tile_x = 0; tile_x < entry.tile_width; tile_x++) {
- if (entry.component_alignment != 0) {
- srcBits.skip_to_byte_boundary();
- int numPadBits = (entry.component_alignment * 8) - entry.bits_per_component_sample;
- srcBits.skip_bits(numPadBits);
- }
- processComponentSample(srcBits, entry, dst_row_offset, tile_column, tile_x);
- }
- srcBits.skip_to_byte_boundary();
-}
-
-void unc_decoder::processComponentTileSample(UncompressedBitReader& srcBits, const ChannelListEntry& entry, uint64_t dst_offset, uint32_t tile_x)
-{
- uint64_t dst_sample_offset = uint64_t{tile_x} * entry.bytes_per_component_sample;
- int val = srcBits.get_bits(entry.bits_per_component_sample);
- memcpy_to_native_endian(entry.dst_plane + dst_offset + dst_sample_offset, val, entry.bytes_per_component_sample);
-}
-
-// Handles the case where a row consists of a single component type
-// Not valid for Pixel interleave
-// Not valid for the Cb/Cr channels in Mixed Interleave
-// Not valid for multi-Y pixel interleave
-void unc_decoder::processComponentTileRow(ChannelListEntry& entry, UncompressedBitReader& srcBits, uint64_t dst_offset)
-{
- for (uint32_t tile_x = 0; tile_x < entry.tile_width; tile_x++) {
- if (entry.component_alignment != 0) {
- srcBits.skip_to_byte_boundary();
- int numPadBits = (entry.component_alignment * 8) - entry.bits_per_component_sample;
- srcBits.skip_bits(numPadBits);
- }
- processComponentTileSample(srcBits, entry, dst_offset, tile_x);
- }
- srcBits.skip_to_byte_boundary();
-}
-
-
-unc_decoder::ChannelListEntry unc_decoder::buildChannelListEntry(Box_uncC::Component component,
- std::shared_ptr<HeifPixelImage>& img)
-{
- ChannelListEntry entry;
- entry.use_channel = map_uncompressed_component_to_channel(m_cmpd, m_uncC, component, &(entry.channel));
- entry.dst_plane = img->get_plane(entry.channel, &(entry.dst_plane_stride));
- entry.tile_width = m_tile_width;
- entry.tile_height = m_tile_height;
- entry.other_chroma_dst_plane_stride = 0; // will be overwritten below if used
- if ((entry.channel == heif_channel_Cb) || (entry.channel == heif_channel_Cr)) {
- if (m_uncC->get_sampling_type() == sampling_mode_422) {
- entry.tile_width /= 2;
- }
- else if (m_uncC->get_sampling_type() == sampling_mode_420) {
- entry.tile_width /= 2;
- entry.tile_height /= 2;
- }
- if (entry.channel == heif_channel_Cb) {
- entry.other_chroma_dst_plane = img->get_plane(heif_channel_Cr, &(entry.other_chroma_dst_plane_stride));
- }
- else if (entry.channel == heif_channel_Cr) {
- entry.other_chroma_dst_plane = img->get_plane(heif_channel_Cb, &(entry.other_chroma_dst_plane_stride));
- }
- }
- entry.bits_per_component_sample = component.component_bit_depth;
- entry.component_alignment = component.component_align_size;
- entry.bytes_per_component_sample = (component.component_bit_depth + 7) / 8;
- entry.bytes_per_tile_row_src = entry.tile_width * entry.bytes_per_component_sample;
- return entry;
-}
-
-
-const Error unc_decoder::get_compressed_image_data_uncompressed(const DataExtent& dataExtent,
- const UncompressedImageCodec::unci_properties& properties,
- std::vector<uint8_t>* data,
- uint64_t range_start_offset, uint64_t range_size,
- uint32_t tile_idx,
- const Box_iloc::Item* item) const
+Error unc_decoder::decode_image(const DataExtent& extent,
+ const UncompressedImageCodec::unci_properties& properties,
+ std::shared_ptr<HeifPixelImage>& img)
{
- // --- get codec configuration
-
- std::shared_ptr<const Box_cmpC> cmpC_box = properties.cmpC;
- std::shared_ptr<const Box_icef> icef_box = properties.icef;
-
- if (!cmpC_box) {
- // assume no generic compression
- auto readResult = dataExtent.read_data(range_start_offset, range_size);
- if (!readResult) {
- return readResult.error();
- }
-
- data->insert(data->end(), readResult->begin(), readResult->end());
-
- return Error::Ok;
- }
-
- if (icef_box && cmpC_box->get_compressed_unit_type() == heif_cmpC_compressed_unit_type_image_tile) {
- const auto& units = icef_box->get_units();
- if (tile_idx >= units.size()) {
- return {heif_error_Invalid_input,
- heif_suberror_Unspecified,
- "no icef-box entry for tile index"};
- }
-
- const auto unit = units[tile_idx];
-
- // get data needed for one tile
- Result<std::vector<uint8_t>> readingResult = dataExtent.read_data(unit.unit_offset, unit.unit_size);
- if (!readingResult) {
- return readingResult.error();
- }
-
- const std::vector<uint8_t>& compressed_bytes = *readingResult;
-
- // decompress only the unit
- auto dataResult = do_decompress_data(cmpC_box, compressed_bytes);
- if (!dataResult) {
- return dataResult.error();
- }
-
- *data = std::move(*dataResult);
- }
- else if (icef_box) {
- // get all data and decode all
- Result<std::vector<uint8_t>*> readResult = dataExtent.read_data();
- if (!readResult) {
- return readResult.error();
- }
-
- const std::vector<uint8_t> compressed_bytes = std::move(**readResult);
-
- for (Box_icef::CompressedUnitInfo unit_info : icef_box->get_units()) {
- if (unit_info.unit_offset + unit_info.unit_size > compressed_bytes.size()) {
- return Error{
- heif_error_Invalid_input,
- heif_suberror_Unspecified,
- "incomplete data in unci image"
- };
- }
-
- auto unit_start = compressed_bytes.begin() + unit_info.unit_offset;
- auto unit_end = unit_start + unit_info.unit_size;
- std::vector<uint8_t> compressed_unit_data = std::vector<uint8_t>(unit_start, unit_end);
+ uint32_t tile_width = m_width / m_uncC->get_number_of_tile_columns();
+ uint32_t tile_height = m_height / m_uncC->get_number_of_tile_rows();
- auto dataResult = do_decompress_data(cmpC_box, std::move(compressed_unit_data));
- if (!dataResult) {
- return dataResult.error();
+ for (uint32_t tile_y0 = 0; tile_y0 < m_height; tile_y0 += tile_height)
+ for (uint32_t tile_x0 = 0; tile_x0 < m_width; tile_x0 += tile_width) {
+ Error error = decode_tile(extent, properties, img, tile_x0, tile_y0,
+ m_width, m_height,
+ tile_x0 / tile_width, tile_y0 / tile_height);
+ if (error) {
+ return error;
}
-
- const std::vector<uint8_t> uncompressed_unit_data = std::move(*dataResult);
- data->insert(data->end(), uncompressed_unit_data.data(), uncompressed_unit_data.data() + uncompressed_unit_data.size());
- }
-
- if (range_start_offset + range_size > data->size()) {
- return {heif_error_Invalid_input,
- heif_suberror_Unspecified,
- "Data range out of existing range"};
}
- // cut out the range that we actually need
- memcpy(data->data(), data->data() + range_start_offset, range_size);
- data->resize(range_size);
- }
- else {
- // get all data and decode all
- Result<std::vector<uint8_t>*> readResult = dataExtent.read_data();
- if (!readResult) {
- return readResult.error();
- }
-
- std::vector<uint8_t> compressed_bytes = std::move(**readResult);
-
- // Decode as a single blob
- auto dataResult = do_decompress_data(cmpC_box, compressed_bytes);
- if (!dataResult) {
- return dataResult.error();
- }
-
- *data = std::move(*dataResult);
-
- if (range_start_offset + range_size > data->size()) {
- return {heif_error_Invalid_input,
- heif_suberror_Unspecified,
- "Data range out of existing range"};
- }
-
- // cut out the range that we actually need
- memcpy(data->data(), data->data() + range_start_offset, range_size);
- data->resize(range_size);
- }
-
return Error::Ok;
}
-Result<std::vector<uint8_t>> unc_decoder::do_decompress_data(std::shared_ptr<const Box_cmpC>& cmpC_box,
- std::vector<uint8_t> compressed_data) const
-{
- if (cmpC_box->get_compression_type() == fourcc("brot")) {
-#if HAVE_BROTLI
- return decompress_brotli(compressed_data);
-#else
- std::stringstream sstr;
- sstr << "cannot decode unci item with brotli compression - not enabled" << std::endl;
- return Error(heif_error_Unsupported_feature,
- heif_suberror_Unsupported_generic_compression_method,
- sstr.str());
-#endif
- }
- else if (cmpC_box->get_compression_type() == fourcc("zlib")) {
-#if HAVE_ZLIB
- return decompress_zlib(compressed_data);
-#else
- std::stringstream sstr;
- sstr << "cannot decode unci item with zlib compression - not enabled" << std::endl;
- return Error(heif_error_Unsupported_feature,
- heif_suberror_Unsupported_generic_compression_method,
- sstr.str());
-#endif
- }
- else if (cmpC_box->get_compression_type() == fourcc("defl")) {
-#if HAVE_ZLIB
- return decompress_deflate(compressed_data);
-#else
- std::stringstream sstr;
- sstr << "cannot decode unci item with deflate compression - not enabled" << std::endl;
- return Error(heif_error_Unsupported_feature,
- heif_suberror_Unsupported_generic_compression_method,
- sstr.str());
-#endif
- }
- else {
- std::stringstream sstr;
- sstr << "cannot decode unci item with unsupported compression type: " << cmpC_box->get_compression_type() << std::endl;
- return Error(heif_error_Unsupported_feature,
- heif_suberror_Unsupported_generic_compression_method,
- sstr.str());
- }
-}
-
-
// --- unc_decoder_factory ---
Result<std::unique_ptr<unc_decoder>> unc_decoder_factory::get_unc_decoder(
@@ -399,8 +130,6 @@ Result<std::shared_ptr<HeifPixelImage>> unc_decoder::decode_full_image(
auto& decoder = *decoderResult;
- decoder->buildChannelList(img);
-
Error error = decoder->decode_image(extent, properties, img);
if (error) {
return error;
@@ -408,24 +137,3 @@ Result<std::shared_ptr<HeifPixelImage>> unc_decoder::decode_full_image(
return img;
}
-
-
-Error unc_decoder::decode_image(const DataExtent& extent,
- const UncompressedImageCodec::unci_properties& properties,
- std::shared_ptr<HeifPixelImage>& img)
-{
- uint32_t tile_width = m_width / m_uncC->get_number_of_tile_columns();
- uint32_t tile_height = m_height / m_uncC->get_number_of_tile_rows();
-
- for (uint32_t tile_y0 = 0; tile_y0 < m_height; tile_y0 += tile_height)
- for (uint32_t tile_x0 = 0; tile_x0 < m_width; tile_x0 += tile_width) {
- Error error = decode_tile(extent, properties, img, tile_x0, tile_y0,
- m_width, m_height,
- tile_x0 / tile_width, tile_y0 / tile_height);
- if (error) {
- return error;
- }
- }
-
- return Error::Ok;
-}
diff --git a/libheif/codecs/uncompressed/unc_decoder.h b/libheif/codecs/uncompressed/unc_decoder.h
index 2796136a..48ee8a03 100644
--- a/libheif/codecs/uncompressed/unc_decoder.h
+++ b/libheif/codecs/uncompressed/unc_decoder.h
@@ -22,110 +22,15 @@
#define LIBHEIF_UNC_DECODER_H
#include <cstdint>
-#include <cstring>
-#include <algorithm>
-#include <map>
-#include <iostream>
-#include <cassert>
-#include <utility>
-#include <vector>
#include <memory>
-#include "common_utils.h"
-#include "context.h"
-#include "compression.h"
#include "error.h"
-#include "libheif/heif.h"
-#include "unc_types.h"
-#include "unc_boxes.h"
#include "unc_codec.h"
+#include "unc_boxes.h"
-
-class UncompressedBitReader : public BitReader
-{
-public:
- UncompressedBitReader(const std::vector<uint8_t>& data) : BitReader(data.data(), (int) data.size()) {}
-
- void markPixelStart()
- {
- m_pixelStartOffset = get_current_byte_index();
- }
-
- void markRowStart()
- {
- m_rowStartOffset = get_current_byte_index();
- }
-
- void markTileStart()
- {
- m_tileStartOffset = get_current_byte_index();
- }
-
- inline Error handlePixelAlignment(uint32_t pixel_size)
- {
- if (pixel_size != 0) {
- uint32_t bytes_in_pixel = get_current_byte_index() - m_pixelStartOffset;
- if (pixel_size > bytes_in_pixel) {
- uint32_t padding = pixel_size - bytes_in_pixel;
- skip_bytes(padding);
- }
- else {
- return {
- heif_error_Invalid_input,
- heif_suberror_Unspecified,
- "Uncompressed image: invalid 'pixel_size'"
- };
- }
- }
-
- return {};
- }
-
- void handleRowAlignment(uint32_t alignment)
- {
- skip_to_byte_boundary();
- if (alignment != 0) {
- uint32_t bytes_in_row = get_current_byte_index() - m_rowStartOffset;
- uint32_t residual = bytes_in_row % alignment;
- if (residual != 0) {
- uint32_t padding = alignment - residual;
- skip_bytes(padding);
- }
- }
- }
-
- void handleTileAlignment(uint32_t alignment)
- {
- if (alignment != 0) {
- uint32_t bytes_in_tile = get_current_byte_index() - m_tileStartOffset;
- uint32_t residual = bytes_in_tile % alignment;
- if (residual != 0) {
- uint32_t tile_padding = alignment - residual;
- skip_bytes(tile_padding);
- }
- }
- }
-
-private:
- int m_pixelStartOffset = 0;
- int m_rowStartOffset = 0;
- int m_tileStartOffset = 0;
-};
-
-
-template<typename T> void skip_to_alignment(T& position, uint32_t alignment)
-{
- if (alignment == 0) {
- return;
- }
-
- T residual = position % alignment;
- if (residual == 0) {
- return;
- }
-
- position += alignment - residual;
-}
+class HeifPixelImage;
+struct DataExtent;
+struct heif_security_limits;
class unc_decoder
@@ -140,92 +45,26 @@ public:
uint32_t image_width, uint32_t image_height,
uint32_t tile_x, uint32_t tile_y) = 0;
- void buildChannelList(std::shared_ptr<HeifPixelImage>& img);
+ Error decode_image(const DataExtent& extent,
+ const UncompressedImageCodec::unci_properties& properties,
+ std::shared_ptr<HeifPixelImage>& img);
static Result<std::shared_ptr<HeifPixelImage>> decode_full_image(
const UncompressedImageCodec::unci_properties& properties,
const DataExtent& extent,
const heif_security_limits* limits);
- Error decode_image(const DataExtent& extent,
- const UncompressedImageCodec::unci_properties& properties,
- std::shared_ptr<HeifPixelImage>& img);
-
protected:
unc_decoder(uint32_t width, uint32_t height,
- const std::shared_ptr<const Box_cmpd> cmpd,
- const std::shared_ptr<const Box_uncC> uncC);
+ const std::shared_ptr<const Box_cmpd>& cmpd,
+ const std::shared_ptr<const Box_uncC>& uncC);
const uint32_t m_width;
const uint32_t m_height;
const std::shared_ptr<const Box_cmpd> m_cmpd;
const std::shared_ptr<const Box_uncC> m_uncC;
- // TODO: see if we can make this const
uint32_t m_tile_height;
uint32_t m_tile_width;
-
- class ChannelListEntry
- {
- public:
- uint32_t get_bytes_per_tile() const
- {
- return bytes_per_tile_row_src * tile_height;
- }
-
- inline uint64_t getDestinationRowOffset(uint32_t tile_row, uint32_t tile_y) const
- {
- uint64_t dst_row_number = uint64_t{tile_row} * tile_height + tile_y;
- return dst_row_number * dst_plane_stride;
- }
-
- heif_channel channel = heif_channel_Y;
- uint8_t* dst_plane = nullptr;
- uint8_t* other_chroma_dst_plane = nullptr;
- size_t dst_plane_stride;
- size_t other_chroma_dst_plane_stride;
- uint32_t tile_width;
- uint32_t tile_height;
- uint32_t bytes_per_component_sample;
- uint16_t bits_per_component_sample;
- uint8_t component_alignment;
- uint32_t bytes_per_tile_row_src;
- bool use_channel;
- };
-
- std::vector<ChannelListEntry> channelList;
-
- void processComponentSample(UncompressedBitReader& srcBits, const ChannelListEntry& entry, uint64_t dst_row_offset, uint32_t tile_column, uint32_t tile_x);
-
- // Handles the case where a row consists of a single component type
- // Not valid for Pixel interleave
- // Not valid for the Cb/Cr channels in Mixed Interleave
- // Not valid for multi-Y pixel interleave
- void processComponentRow(ChannelListEntry& entry, UncompressedBitReader& srcBits, uint64_t dst_row_offset, uint32_t tile_column);
-
- void processComponentTileSample(UncompressedBitReader& srcBits, const ChannelListEntry& entry, uint64_t dst_offset, uint32_t tile_x);
-
- // Handles the case where a row consists of a single component type
- // Not valid for Pixel interleave
- // Not valid for the Cb/Cr channels in Mixed Interleave
- // Not valid for multi-Y pixel interleave
- void processComponentTileRow(ChannelListEntry& entry, UncompressedBitReader& srcBits, uint64_t dst_offset);
-
- // generic compression and uncompressed, per 23001-17
- const Error get_compressed_image_data_uncompressed(const DataExtent& dataExtent,
- const UncompressedImageCodec::unci_properties& properties,
- std::vector<uint8_t>* data,
- uint64_t range_start_offset, uint64_t range_size,
- uint32_t tile_idx,
- const Box_iloc::Item* item) const;
-
- Result<std::vector<uint8_t>> do_decompress_data(std::shared_ptr<const Box_cmpC>& cmpC_box,
- std::vector<uint8_t> compressed_data) const;
-
-protected:
- void memcpy_to_native_endian(uint8_t* dst, uint32_t value, uint32_t bytes_per_sample);
-
-private:
- ChannelListEntry buildChannelListEntry(Box_uncC::Component component, std::shared_ptr<HeifPixelImage>& img);
};
diff --git a/libheif/codecs/uncompressed/unc_decoder_component_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_component_interleave.cc
index b6ae03cd..f5b8ad63 100644
--- a/libheif/codecs/uncompressed/unc_decoder_component_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_component_interleave.cc
@@ -33,6 +33,8 @@ Error unc_decoder_component_interleave::decode_tile(const DataExtent& dataExtent
uint32_t image_width, uint32_t image_height,
uint32_t tile_x, uint32_t tile_y)
{
+ ensureChannelList(img);
+
if (m_tile_width == 0) {
return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_component_interleave tile_width=0"};
}
diff --git a/libheif/codecs/uncompressed/unc_decoder_component_interleave.h b/libheif/codecs/uncompressed/unc_decoder_component_interleave.h
index 81f70121..2cd5d019 100644
--- a/libheif/codecs/uncompressed/unc_decoder_component_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_component_interleave.h
@@ -21,18 +21,18 @@
#ifndef LIBHEIF_UNC_DECODER_COMPONENT_INTERLEAVE_H
#define LIBHEIF_UNC_DECODER_COMPONENT_INTERLEAVE_H
-#include "unc_decoder.h"
+#include "unc_decoder_legacybase.h"
#include <memory>
#include <utility>
-class unc_decoder_component_interleave : public unc_decoder
+class unc_decoder_component_interleave : public unc_decoder_legacybase
{
public:
unc_decoder_component_interleave(uint32_t width, uint32_t height,
std::shared_ptr<const Box_cmpd> cmpd,
std::shared_ptr<const Box_uncC> uncC) :
- unc_decoder(width, height, std::move(cmpd), std::move(uncC)) {}
+ unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}
Error decode_tile(const DataExtent& dataExtent,
const UncompressedImageCodec::unci_properties& properties,
diff --git a/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.cc
index be117de4..dc0dec81 100644
--- a/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.cc
@@ -34,6 +34,8 @@ Error unc_decoder_mixed_interleave::decode_tile(const DataExtent& dataExtent,
uint32_t image_width, uint32_t image_height,
uint32_t tile_x, uint32_t tile_y)
{
+ ensureChannelList(img);
+
if (m_tile_width == 0) {
return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_mixed_interleave tile_width=0"};
}
diff --git a/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.h b/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.h
index e9f4969d..e8a2dd4f 100644
--- a/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_mixed_interleave.h
@@ -21,16 +21,16 @@
#ifndef LIBHEIF_UNC_DECODER_MIXED_INTERLEAVE_H
#define LIBHEIF_UNC_DECODER_MIXED_INTERLEAVE_H
-#include "unc_decoder.h"
+#include "unc_decoder_legacybase.h"
#include <memory>
#include <utility>
-class unc_decoder_mixed_interleave : public unc_decoder
+class unc_decoder_mixed_interleave : public unc_decoder_legacybase
{
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(width, height, std::move(cmpd), std::move(uncC)) {}
+ unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}
Error decode_tile(const DataExtent& dataExtent,
const UncompressedImageCodec::unci_properties& properties,
diff --git a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
index 2b1944c0..15e69e81 100644
--- a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
@@ -33,6 +33,8 @@ Error unc_decoder_pixel_interleave::decode_tile(const DataExtent& dataExtent,
uint32_t image_width, uint32_t image_height,
uint32_t tile_x, uint32_t tile_y)
{
+ ensureChannelList(img);
+
if (m_tile_width == 0) {
return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_pixel_interleave tile_width=0"};
}
diff --git a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.h b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.h
index 0174b4ec..152e4d49 100644
--- a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.h
@@ -21,16 +21,16 @@
#ifndef LIBHEIF_UNC_DECODER_PIXEL_INTERLEAVE_H
#define LIBHEIF_UNC_DECODER_PIXEL_INTERLEAVE_H
-#include "unc_decoder.h"
+#include "unc_decoder_legacybase.h"
#include <memory>
#include <utility>
-class unc_decoder_pixel_interleave : public unc_decoder
+class unc_decoder_pixel_interleave : public unc_decoder_legacybase
{
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(width, height, std::move(cmpd), std::move(uncC)) {}
+ unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}
Error decode_tile(const DataExtent& dataExtent,
const UncompressedImageCodec::unci_properties& properties,
diff --git a/libheif/codecs/uncompressed/unc_decoder_row_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_row_interleave.cc
index 8851e207..5616be29 100644
--- a/libheif/codecs/uncompressed/unc_decoder_row_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_row_interleave.cc
@@ -33,6 +33,8 @@ Error unc_decoder_row_interleave::decode_tile(const DataExtent& dataExtent,
uint32_t image_width, uint32_t image_height,
uint32_t tile_x, uint32_t tile_y)
{
+ ensureChannelList(img);
+
if (m_tile_width == 0) {
return {heif_error_Decoder_plugin_error, heif_suberror_Unspecified, "Internal error: unc_decoder_row_interleave tile_width=0"};
}
diff --git a/libheif/codecs/uncompressed/unc_decoder_row_interleave.h b/libheif/codecs/uncompressed/unc_decoder_row_interleave.h
index 05bad259..898c3801 100644
--- a/libheif/codecs/uncompressed/unc_decoder_row_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_row_interleave.h
@@ -21,17 +21,17 @@
#ifndef LIBHEIF_UNC_DECODER_ROW_INTERLEAVE_H
#define LIBHEIF_UNC_DECODER_ROW_INTERLEAVE_H
-#include "unc_decoder.h"
+#include "unc_decoder_legacybase.h"
#include <memory>
#include <utility>
-class unc_decoder_row_interleave : public unc_decoder
+class unc_decoder_row_interleave : public unc_decoder_legacybase
{
public:
unc_decoder_row_interleave(uint32_t width, uint32_t height,
std::shared_ptr<const Box_cmpd> cmpd, std::shared_ptr<const Box_uncC> uncC) :
- unc_decoder(width, height, std::move(cmpd), std::move(uncC)) {}
+ unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}
Error decode_tile(const DataExtent& dataExtent,
diff --git a/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.cc
index c7e26edc..92db8348 100644
--- a/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.cc
@@ -35,6 +35,8 @@ Error unc_decoder_tile_component_interleave::decode_tile(const DataExtent& dataE
uint32_t image_width, uint32_t image_height,
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"};
}
diff --git a/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.h b/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.h
index ed083f9e..64d4a1b4 100644
--- a/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.h
+++ b/libheif/codecs/uncompressed/unc_decoder_tile_component_interleave.h
@@ -21,17 +21,17 @@
#ifndef LIBHEIF_UNC_DECODER_TILE_COMPONENT_INTERLEAVE_H
#define LIBHEIF_UNC_DECODER_TILE_COMPONENT_INTERLEAVE_H
-#include "unc_decoder.h"
+#include "unc_decoder_legacybase.h"
#include <memory>
#include <utility>
-class unc_decoder_tile_component_interleave : public unc_decoder
+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(width, height, std::move(cmpd), std::move(uncC)) {}
+ unc_decoder_legacybase(width, height, std::move(cmpd), std::move(uncC)) {}
Error decode_tile(const DataExtent& dataExtent,
const UncompressedImageCodec::unci_properties& properties,