Skip to content

Commit 4b40100

Browse files
committed
Don't require crop width,height be even for 4:2:0
These requirements were removed in ISO/IEC 23000-22:2019/Amd. 2:2021 from Section 7.3.6.7. This is one reason most of the clap properties seen by Chrome were considered invalid. Bug: b/308458941 (cherry picked from commit 9342e58)
1 parent d1c26fa commit 4b40100

File tree

3 files changed

+34
-12
lines changed

3 files changed

+34
-12
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Changed
10+
* Update avifCropRectConvertCleanApertureBox() to the revised requirements in
11+
ISO/IEC 23000-22:2019/Amd. 2:2021 Section 7.3.6.7.
12+
913
## [1.0.1] - 2023-08-29
1014

1115
### Changed

src/avif.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -624,16 +624,15 @@ static avifBool overflowsInt32(int64_t x)
624624
static avifBool avifCropRectIsValid(const avifCropRect * cropRect, uint32_t imageW, uint32_t imageH, avifPixelFormat yuvFormat, avifDiagnostics * diag)
625625

626626
{
627-
// ISO/IEC 23000-22:2019/DAM 2:2021, Section 7.3.6.7:
627+
// ISO/IEC 23000-22:2019/Amd. 2:2021, Section 7.3.6.7:
628628
// The clean aperture property is restricted according to the chroma
629629
// sampling format of the input image (4:4:4, 4:2:2:, 4:2:0, or 4:0:0) as
630630
// follows:
631-
// - when the image is 4:0:0 (monochrome) or 4:4:4, the horizontal and
632-
// vertical cropped offsets and widths shall be integers;
633-
// - when the image is 4:2:2 the horizontal cropped offset and width
634-
// shall be even numbers and the vertical values shall be integers;
635-
// - when the image is 4:2:0 both the horizontal and vertical cropped
636-
// offsets and widths shall be even numbers.
631+
// ...
632+
// - If chroma is subsampled horizontally (i.e., 4:2:2 and 4:2:0), the
633+
// leftmost pixel of the clean aperture shall be even numbers;
634+
// - If chroma is subsampled vertically (i.e., 4:2:0), the topmost line
635+
// of the clean aperture shall be even numbers.
637636

638637
if ((cropRect->width == 0) || (cropRect->height == 0)) {
639638
avifDiagnosticsPrintf(diag, "[Strict] crop rect width and height must be nonzero");
@@ -646,14 +645,14 @@ static avifBool avifCropRectIsValid(const avifCropRect * cropRect, uint32_t imag
646645
}
647646

648647
if ((yuvFormat == AVIF_PIXEL_FORMAT_YUV420) || (yuvFormat == AVIF_PIXEL_FORMAT_YUV422)) {
649-
if (((cropRect->x % 2) != 0) || ((cropRect->width % 2) != 0)) {
650-
avifDiagnosticsPrintf(diag, "[Strict] crop rect X offset and width must both be even due to this image's YUV subsampling");
648+
if ((cropRect->x % 2) != 0) {
649+
avifDiagnosticsPrintf(diag, "[Strict] crop rect X offset must be even due to this image's YUV subsampling");
651650
return AVIF_FALSE;
652651
}
653652
}
654653
if (yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
655-
if (((cropRect->y % 2) != 0) || ((cropRect->height % 2) != 0)) {
656-
avifDiagnosticsPrintf(diag, "[Strict] crop rect Y offset and height must both be even due to this image's YUV subsampling");
654+
if ((cropRect->y % 2) != 0) {
655+
avifDiagnosticsPrintf(diag, "[Strict] crop rect Y offset must be even due to this image's YUV subsampling");
657656
return AVIF_FALSE;
658657
}
659658
}

tests/gtest/avifclaptest.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@ constexpr InvalidClapPropertyParam kInvalidClapPropertyTestParams[] = {
6565
722,
6666
AVIF_PIXEL_FORMAT_YUV420,
6767
{330, 1, 385, 1, static_cast<uint32_t>(-308), 1, 103, 1}},
68+
// pcX = -1/2 + (99 - 1)/2 = 48.5
69+
// pcY = -1/2 + (99 - 1)/2 = 48.5
70+
// leftmost = 48.5 - (99 - 1)/2 = -0.5 (not an integer)
71+
// topmost = 48.5 - (99 - 1)/2 = -0.5 (not an integer)
72+
{99,
73+
99,
74+
AVIF_PIXEL_FORMAT_YUV420,
75+
{99, 1, 99, 1, static_cast<uint32_t>(-1), 2, static_cast<uint32_t>(-1),
76+
2}},
6877
};
6978

7079
using InvalidClapPropertyTest =
@@ -112,6 +121,15 @@ constexpr ValidClapPropertyParam kValidClapPropertyTestParams[] = {
112121
{60, 1, 80, 1, static_cast<uint32_t>(-30), 1, static_cast<uint32_t>(-40),
113122
1},
114123
{0, 0, 60, 80}},
124+
// pcX = -1/2 + (100 - 1)/2 = 49
125+
// pcY = -1/2 + (100 - 1)/2 = 49
126+
// leftmost = 49 - (99 - 1)/2 = 0
127+
// topmost = 49 - (99 - 1)/2 = 0
128+
{100,
129+
100,
130+
AVIF_PIXEL_FORMAT_YUV420,
131+
{99, 1, 99, 1, static_cast<uint32_t>(-1), 2, static_cast<uint32_t>(-1), 2},
132+
{0, 0, 99, 99}},
115133
};
116134

117135
using ValidClapPropertyTest = ::testing::TestWithParam<ValidClapPropertyParam>;
@@ -126,7 +144,8 @@ TEST_P(ValidClapPropertyTest, ValidateClapProperty) {
126144
avifDiagnostics diag;
127145
EXPECT_TRUE(avifCropRectConvertCleanApertureBox(&crop_rect, &param.clap,
128146
param.width, param.height,
129-
param.yuv_format, &diag));
147+
param.yuv_format, &diag))
148+
<< diag.error;
130149
EXPECT_EQ(crop_rect.x, param.expected_crop_rect.x);
131150
EXPECT_EQ(crop_rect.y, param.expected_crop_rect.y);
132151
EXPECT_EQ(crop_rect.width, param.expected_crop_rect.width);

0 commit comments

Comments
 (0)