From 32ea2d74dedb111f643ee65de1f64a972dd3788f Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Thu, 19 Dec 2024 00:25:39 +0100 Subject: [PATCH] explicitly check precondition when scaling chroma sizes --- libheif/common_utils.cc | 30 ++++++++++++++++++++++++------ libheif/common_utils.h | 10 ++++++++-- libheif/pixelimage.cc | 8 ++++---- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/libheif/common_utils.cc b/libheif/common_utils.cc index 1751e2d21f..649738527a 100644 --- a/libheif/common_utils.cc +++ b/libheif/common_utils.cc @@ -65,14 +65,23 @@ uint8_t chroma_v_subsampling(heif_chroma c) uint32_t get_subsampled_size_h(uint32_t width, heif_channel channel, heif_chroma chroma, - bool round_up) + scaling_mode mode) { if (channel == heif_channel_Cb || channel == heif_channel_Cr) { uint8_t chromaSubH = chroma_h_subsampling(chroma); - // NOLINTNEXTLINE(clang-analyzer-core.DivideZero) - return (width + (round_up ? chromaSubH - 1 : 0)) / chromaSubH; + switch (mode) { + case scaling_mode::round_up: + // NOLINTNEXTLINE(clang-analyzer-core.DivideZero) + return (width + chromaSubH - 1) / chromaSubH; + case scaling_mode::round_down: + // NOLINTNEXTLINE(clang-analyzer-core.DivideZero) + return width / chromaSubH; + case scaling_mode::is_divisible: + assert(width % chromaSubH == 0); + return width / chromaSubH; + } } else { return width; } @@ -81,14 +90,23 @@ uint32_t get_subsampled_size_h(uint32_t width, uint32_t get_subsampled_size_v(uint32_t height, heif_channel channel, heif_chroma chroma, - bool round_up) + scaling_mode mode) { if (channel == heif_channel_Cb || channel == heif_channel_Cr) { uint8_t chromaSubV = chroma_v_subsampling(chroma); - // NOLINTNEXTLINE(clang-analyzer-core.DivideZero) - return (height + (round_up ? chromaSubV - 1 : 0)) / chromaSubV; + switch (mode) { + case scaling_mode::round_up: + // NOLINTNEXTLINE(clang-analyzer-core.DivideZero) + return (height + chromaSubV - 1) / chromaSubV; + case scaling_mode::round_down: + // NOLINTNEXTLINE(clang-analyzer-core.DivideZero) + return height / chromaSubV; + case scaling_mode::is_divisible: + assert(height % chromaSubV == 0); + return height / chromaSubV; + } } else { return height; } diff --git a/libheif/common_utils.h b/libheif/common_utils.h index 159646f9bc..928a166821 100644 --- a/libheif/common_utils.h +++ b/libheif/common_utils.h @@ -49,15 +49,21 @@ uint8_t chroma_h_subsampling(heif_chroma c); uint8_t chroma_v_subsampling(heif_chroma c); +enum class scaling_mode : uint8_t { + round_down, + round_up, + is_divisible +}; + uint32_t get_subsampled_size_h(uint32_t width, heif_channel channel, heif_chroma chroma, - bool round_up); + scaling_mode mode); uint32_t get_subsampled_size_v(uint32_t height, heif_channel channel, heif_chroma chroma, - bool round_up); + scaling_mode mode); void get_subsampled_size(uint32_t width, uint32_t height, heif_channel channel, diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc index 461bd5e28a..453b3ae9b4 100644 --- a/libheif/pixelimage.cc +++ b/libheif/pixelimage.cc @@ -1050,10 +1050,10 @@ Result> HeifPixelImage::crop(uint32_t left, uint heif_channel channel = plane_pair.first; const ImagePlane& plane = plane_pair.second; - uint32_t plane_left = get_subsampled_size_h(left, channel, m_chroma, false); // is always divisible - uint32_t plane_right = get_subsampled_size_h(right, channel, m_chroma, true); // keep more chroma - uint32_t plane_top = get_subsampled_size_v(top, channel, m_chroma, false); // is always divisible - uint32_t plane_bottom = get_subsampled_size_v(bottom, channel, m_chroma, true); // keep more chroma + uint32_t plane_left = get_subsampled_size_h(left, channel, m_chroma, scaling_mode::is_divisible); + uint32_t plane_right = get_subsampled_size_h(right, channel, m_chroma, scaling_mode::round_up); // keep more chroma + uint32_t plane_top = get_subsampled_size_v(top, channel, m_chroma, scaling_mode::is_divisible); // is always divisible + uint32_t plane_bottom = get_subsampled_size_v(bottom, channel, m_chroma, scaling_mode::round_up); // keep more chroma auto err = out_img->add_channel(channel, plane_right - plane_left + 1,