1 // Copyright 2023 Google LLC
2 // SPDX-License-Identifier: BSD-2-Clause
3 
4 #include "avif/avif.h"
5 #include "aviftest_helpers.h"
6 #include "gtest/gtest.h"
7 
8 namespace {
9 
10 struct InvalidClapPropertyParam {
11   uint32_t width;
12   uint32_t height;
13   avifPixelFormat yuv_format;
14   avifCleanApertureBox clap;
15 };
16 
17 constexpr InvalidClapPropertyParam kInvalidClapPropertyTestParams[] = {
18     // Zero or negative denominators.
19     {120, 160, AVIF_PIXEL_FORMAT_YUV420, {96, 0, 132, 1, 0, 1, 0, 1}},
20     {120,
21      160,
22      AVIF_PIXEL_FORMAT_YUV420,
23      {96, static_cast<uint32_t>(-1), 132, 1, 0, 1, 0, 1}},
24     {120, 160, AVIF_PIXEL_FORMAT_YUV420, {96, 1, 132, 0, 0, 1, 0, 1}},
25     {120,
26      160,
27      AVIF_PIXEL_FORMAT_YUV420,
28      {96, 1, 132, static_cast<uint32_t>(-1), 0, 1, 0, 1}},
29     {120, 160, AVIF_PIXEL_FORMAT_YUV420, {96, 1, 132, 1, 0, 0, 0, 1}},
30     {120,
31      160,
32      AVIF_PIXEL_FORMAT_YUV420,
33      {96, 1, 132, 1, 0, static_cast<uint32_t>(-1), 0, 1}},
34     {120, 160, AVIF_PIXEL_FORMAT_YUV420, {96, 1, 132, 1, 0, 1, 0, 0}},
35     {120,
36      160,
37      AVIF_PIXEL_FORMAT_YUV420,
38      {96, 1, 132, 1, 0, 1, 0, static_cast<uint32_t>(-1)}},
39     // Zero or negative clean aperture width or height.
40     {120,
41      160,
42      AVIF_PIXEL_FORMAT_YUV420,
43      {static_cast<uint32_t>(-96), 1, 132, 1, 0, 1, 0, 1}},
44     {120, 160, AVIF_PIXEL_FORMAT_YUV420, {0, 1, 132, 1, 0, 1, 0, 1}},
45     {120,
46      160,
47      AVIF_PIXEL_FORMAT_YUV420,
48      {96, 1, static_cast<uint32_t>(-132), 1, 0, 1, 0, 1}},
49     {120, 160, AVIF_PIXEL_FORMAT_YUV420, {96, 1, 0, 1, 0, 1, 0, 1}},
50     // Clean aperture width or height is not an integer.
51     {120, 160, AVIF_PIXEL_FORMAT_YUV420, {96, 5, 132, 1, 0, 1, 0, 1}},
52     {120, 160, AVIF_PIXEL_FORMAT_YUV420, {96, 1, 132, 5, 0, 1, 0, 1}},
53     // pcX = 103 + (722 - 1)/2 = 463.5
54     // pcY = -308 + (1024 - 1)/2 = 203.5
55     // leftmost = 463.5 - (385 - 1)/2 = 271.5 (not an integer)
56     // topmost = 203.5 - (330 - 1)/2 = 39
57     {722,
58      1024,
59      AVIF_PIXEL_FORMAT_YUV420,
60      {385, 1, 330, 1, 103, 1, static_cast<uint32_t>(-308), 1}},
61     // pcX = -308 + (1024 - 1)/2 = 203.5
62     // pcY = 103 + (722 - 1)/2 = 463.5
63     // leftmost = 203.5 - (330 - 1)/2 = 39
64     // topmost = 463.5 - (385 - 1)/2 = 271.5 (not an integer)
65     {1024,
66      722,
67      AVIF_PIXEL_FORMAT_YUV420,
68      {330, 1, 385, 1, static_cast<uint32_t>(-308), 1, 103, 1}},
69     // pcX = -1/2 + (99 - 1)/2 = 48.5
70     // pcY = -1/2 + (99 - 1)/2 = 48.5
71     // leftmost = 48.5 - (99 - 1)/2 = -0.5 (not an integer)
72     // topmost = 48.5 - (99 - 1)/2 = -0.5 (not an integer)
73     {99,
74      99,
75      AVIF_PIXEL_FORMAT_YUV420,
76      {99, 1, 99, 1, static_cast<uint32_t>(-1), 2, static_cast<uint32_t>(-1),
77       2}},
78 };
79 
80 using InvalidClapPropertyTest =
81     ::testing::TestWithParam<InvalidClapPropertyParam>;
82 
83 INSTANTIATE_TEST_SUITE_P(Parameterized, InvalidClapPropertyTest,
84                          ::testing::ValuesIn(kInvalidClapPropertyTestParams));
85 
86 // Negative tests for the avifCropRectConvertCleanApertureBox() function.
TEST_P(InvalidClapPropertyTest,ValidateClapProperty)87 TEST_P(InvalidClapPropertyTest, ValidateClapProperty) {
88   const InvalidClapPropertyParam& param = GetParam();
89   avifCropRect crop_rect;
90   avifDiagnostics diag;
91   EXPECT_FALSE(avifCropRectConvertCleanApertureBox(&crop_rect, &param.clap,
92                                                    param.width, param.height,
93                                                    param.yuv_format, &diag));
94 }
95 
96 struct ValidClapPropertyParam {
97   uint32_t width;
98   uint32_t height;
99   avifPixelFormat yuv_format;
100   avifCleanApertureBox clap;
101 
102   avifCropRect expected_crop_rect;
103 };
104 
105 constexpr ValidClapPropertyParam kValidClapPropertyTestParams[] = {
106     // pcX = 0 + (120 - 1)/2 = 59.5
107     // pcY = 0 + (160 - 1)/2 = 79.5
108     // leftmost = 59.5 - (96 - 1)/2 = 12
109     // topmost = 79.5 - (132 - 1)/2 = 14
110     {120,
111      160,
112      AVIF_PIXEL_FORMAT_YUV420,
113      {96, 1, 132, 1, 0, 1, 0, 1},
114      {12, 14, 96, 132}},
115     // pcX = -30 + (120 - 1)/2 = 29.5
116     // pcY = -40 + (160 - 1)/2 = 39.5
117     // leftmost = 29.5 - (60 - 1)/2 = 0
118     // topmost = 39.5 - (80 - 1)/2 = 0
119     {120,
120      160,
121      AVIF_PIXEL_FORMAT_YUV420,
122      {60, 1, 80, 1, static_cast<uint32_t>(-30), 1, static_cast<uint32_t>(-40),
123       1},
124      {0, 0, 60, 80}},
125     // pcX = -1/2 + (100 - 1)/2 = 49
126     // pcY = -1/2 + (100 - 1)/2 = 49
127     // leftmost = 49 - (99 - 1)/2 = 0
128     // topmost = 49 - (99 - 1)/2 = 0
129     {100,
130      100,
131      AVIF_PIXEL_FORMAT_YUV420,
132      {99, 1, 99, 1, static_cast<uint32_t>(-1), 2, static_cast<uint32_t>(-1), 2},
133      {0, 0, 99, 99}},
134 };
135 
136 using ValidClapPropertyTest = ::testing::TestWithParam<ValidClapPropertyParam>;
137 
138 INSTANTIATE_TEST_SUITE_P(Parameterized, ValidClapPropertyTest,
139                          ::testing::ValuesIn(kValidClapPropertyTestParams));
140 
141 // Positive tests for the avifCropRectConvertCleanApertureBox() function.
TEST_P(ValidClapPropertyTest,ValidateClapProperty)142 TEST_P(ValidClapPropertyTest, ValidateClapProperty) {
143   const ValidClapPropertyParam& param = GetParam();
144   avifCropRect crop_rect;
145   avifDiagnostics diag;
146   EXPECT_TRUE(avifCropRectConvertCleanApertureBox(&crop_rect, &param.clap,
147                                                   param.width, param.height,
148                                                   param.yuv_format, &diag))
149       << diag.error;
150   EXPECT_EQ(crop_rect.x, param.expected_crop_rect.x);
151   EXPECT_EQ(crop_rect.y, param.expected_crop_rect.y);
152   EXPECT_EQ(crop_rect.width, param.expected_crop_rect.width);
153   EXPECT_EQ(crop_rect.height, param.expected_crop_rect.height);
154 }
155 
156 }  // namespace
157