Skip to content

Commit

Permalink
explicitly check precondition when scaling chroma sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Dec 18, 2024
1 parent 97e517d commit 32ea2d7
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 12 deletions.
30 changes: 24 additions & 6 deletions libheif/common_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
10 changes: 8 additions & 2 deletions libheif/common_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions libheif/pixelimage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1050,10 +1050,10 @@ Result<std::shared_ptr<HeifPixelImage>> 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,
Expand Down

0 comments on commit 32ea2d7

Please sign in to comment.