Commit 353c0c54 for libheif
commit 353c0c54ed76a3770ec74dee98e5a5704623cf02
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Tue Feb 10 23:59:04 2026 +0100
unci: fix an integer promotion and byte swapping issue
diff --git a/libheif/codecs/uncompressed/unc_decoder.cc b/libheif/codecs/uncompressed/unc_decoder.cc
index bb95132f..1246d708 100644
--- a/libheif/codecs/uncompressed/unc_decoder.cc
+++ b/libheif/codecs/uncompressed/unc_decoder.cc
@@ -321,6 +321,7 @@ bool unc_decoder_factory::check_common_requirements(const std::shared_ptr<const
return false;
}
+#if 0
if (uncC->is_components_little_endian()) {
const auto& comps = uncC->get_components();
bool all_8_bit = std::all_of(comps.begin(), comps.end(),
@@ -329,6 +330,7 @@ bool unc_decoder_factory::check_common_requirements(const std::shared_ptr<const
return false;
}
}
+#endif
return true;
}
diff --git a/libheif/codecs/uncompressed/unc_decoder_legacybase.h b/libheif/codecs/uncompressed/unc_decoder_legacybase.h
index f2a60123..b5ba191b 100644
--- a/libheif/codecs/uncompressed/unc_decoder_legacybase.h
+++ b/libheif/codecs/uncompressed/unc_decoder_legacybase.h
@@ -70,6 +70,9 @@ public:
uint32_t padding = pixel_size - bytes_in_pixel;
skip_bytes(padding);
}
+ if (pixel_size == bytes_in_pixel) {
+ // NOP
+ }
else {
return {
heif_error_Invalid_input,
diff --git a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
index 2b1ed74c..79886e7c 100644
--- a/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_pixel_interleave.cc
@@ -123,6 +123,10 @@ bool unc_decoder_factory_pixel_interleave::can_decode(const std::shared_ptr<cons
return false;
}
+ if (uncC->is_components_little_endian()) {
+ return false;
+ }
+
return true;
}
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
index a97d6d7e..02d24679 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
@@ -106,7 +106,7 @@ std::vector<uint8_t> unc_encoder_rgb_block_pixel_interleave::encode_tile(const s
uint16_t g = src_data[src_stride * y + 3 * x + 1];
uint16_t b = src_data[src_stride * y + 3 * x + 2];
- uint64_t combined_pixel = (r << (2 * bpp)) | (g << bpp) | b;
+ uint64_t combined_pixel = (static_cast<uint64_t>(r) << (2 * bpp)) | (static_cast<uint64_t>(g) << bpp) | b;
*p++ = static_cast<uint8_t>(combined_pixel & 0xFF);
*p++ = static_cast<uint8_t>((combined_pixel >> 8) & 0xFF);
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
index 94255650..a93750c3 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
@@ -80,9 +80,12 @@ unc_encoder_rgb_bytealign_pixel_interleave::unc_encoder_rgb_bytealign_pixel_inte
component_align_size = 0;
}
+ // make sure that we always save as big-endian so that we can read it with out own reader (unc_decoder_pixel_interleave, which only supports big-endian)
+ m_swap_endianess = little_endian;
+
m_uncC->set_interleave_type(interleave_mode_pixel);
m_uncC->set_sampling_type(sampling_mode_no_subsampling);
- m_uncC->set_components_little_endian(little_endian);
+ m_uncC->set_components_little_endian(false); // little_endian);
m_uncC->set_pixel_size(m_bytes_per_pixel);
m_uncC->add_component({0, bpp, component_format_unsigned, component_align_size});
@@ -100,6 +103,20 @@ uint64_t unc_encoder_rgb_bytealign_pixel_interleave::compute_tile_data_size_byte
}
+void *memcpy_swap16(uint8_t *dst, const uint8_t *src, size_t n)
+{
+ assert(n % 2 == 0);
+
+ /* swap pairs */
+ for (size_t i = 0; i + 1 < n; i += 2) {
+ dst[i] = src[i + 1];
+ dst[i + 1] = src[i];
+ }
+
+ return dst;
+}
+
+
std::vector<uint8_t> unc_encoder_rgb_bytealign_pixel_interleave::encode_tile(const std::shared_ptr<const HeifPixelImage>& src_image) const
{
std::vector<uint8_t> data;
@@ -111,7 +128,12 @@ std::vector<uint8_t> unc_encoder_rgb_bytealign_pixel_interleave::encode_tile(con
data.resize(out_size);
for (uint32_t y = 0; y < src_image->get_height(); y++) {
- memcpy(data.data() + y * src_image->get_width() * m_bytes_per_pixel, src_data + src_stride * y, src_image->get_width() * m_bytes_per_pixel);
+ if (m_swap_endianess) {
+ memcpy_swap16(data.data() + y * src_image->get_width() * m_bytes_per_pixel, src_data + src_stride * y, src_image->get_width() * m_bytes_per_pixel);
+ }
+ else {
+ memcpy(data.data() + y * src_image->get_width() * m_bytes_per_pixel, src_data + src_stride * y, src_image->get_width() * m_bytes_per_pixel);
+ }
}
return data;
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.h b/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.h
index 42a69186..7ada28fd 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.h
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.h
@@ -38,6 +38,7 @@ public:
private:
uint8_t m_bytes_per_pixel = 0;
+ bool m_swap_endianess = false;
};