Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
JBig2_Image_unittest.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// TODO(tsepez) this requires a lot more testing.
6
7#include "core/fxcodec/jbig2/JBig2_Image.h"
8
9#include <stdint.h>
10
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace {
14
15const int32_t kWidthPixels = 80;
16const int32_t kWidthBytes = 10;
17const int32_t kStrideBytes = kWidthBytes + 2; // For testing stride != width.
18const int32_t kHeightLines = 20;
19const int32_t kLargerHeightLines = 100;
20const int32_t kTooLargeHeightLines = 40000000;
21
22void CheckImageEq(CJBig2_Image* img1, CJBig2_Image* img2, int line) {
23 EXPECT_EQ(img1->width(), img2->width());
24 EXPECT_EQ(img1->height(), img2->height());
25 for (int32_t y = 0; y < img1->height(); ++y) {
26 for (int32_t x = 0; x < img1->width(); ++x) {
27 EXPECT_EQ(img1->GetPixel(x, y), img2->GetPixel(x, y))
28 << " at " << x << " " << y << " actual line " << line;
29 }
30 }
31}
32
33} // namespace
34
36 CJBig2_Image empty(0, 0);
37 EXPECT_EQ(empty.width(), 0);
38 EXPECT_EQ(empty.height(), 0);
39
40 // Out-of-bounds SetPixel() is silent no-op.
41 empty.SetPixel(0, 0, true);
42 empty.SetPixel(1, 1, true);
43
44 // Out-of-bounds GetPixel returns 0.
45 EXPECT_EQ(empty.GetPixel(0, 0), 0);
46 EXPECT_EQ(empty.GetPixel(1, 1), 0);
47
48 // Out-of-bounds GetLine() returns null.
49 EXPECT_EQ(empty.GetLine(0), nullptr);
50 EXPECT_EQ(empty.GetLine(1), nullptr);
51}
52
54 CJBig2_Image img(kWidthPixels, kHeightLines);
55 EXPECT_EQ(kWidthPixels, img.width());
56 EXPECT_EQ(kHeightLines, img.height());
57 EXPECT_EQ(0, img.GetPixel(0, 0));
58 EXPECT_EQ(0, img.GetLine(0)[0]);
59 EXPECT_EQ(0, img.GetPixel(kWidthPixels - 1, kHeightLines - 1));
60 EXPECT_EQ(0, img.GetLine(kHeightLines - 1)[kWidthBytes - 1]);
61
62 img.SetPixel(0, 0, true);
63 img.SetPixel(kWidthPixels - 1, kHeightLines - 1, true);
64 EXPECT_EQ(1, img.GetPixel(0, 0));
65 EXPECT_EQ(1, img.GetPixel(kWidthPixels - 1, kHeightLines - 1));
66 EXPECT_EQ(0x80, img.GetLine(0)[0]);
67 EXPECT_EQ(0x01, img.GetLine(kHeightLines - 1)[kWidthBytes - 1]);
68
69 // Out-of-bounds SetPixel() is silent no-op.
70 img.SetPixel(-1, 1, true);
71 img.SetPixel(kWidthPixels, kHeightLines, true);
72
73 // Out-of-bounds GetPixel returns 0.
74 EXPECT_EQ(0, img.GetPixel(-1, -1));
75 EXPECT_EQ(0, img.GetPixel(kWidthPixels, kHeightLines));
76
77 // Out-of-bounds GetLine() returns null.
78 EXPECT_FALSE(img.GetLine(-1));
79 EXPECT_FALSE(img.GetLine(kHeightLines));
80}
81
83 CJBig2_Image img(kWidthPixels, kTooLargeHeightLines);
84 EXPECT_EQ(0, img.width());
85 EXPECT_EQ(0, img.height());
86 EXPECT_FALSE(img.data());
87}
88
90 uint8_t buf[kHeightLines * kStrideBytes];
91 CJBig2_Image img(kWidthPixels, kHeightLines, kStrideBytes, buf);
92 img.SetPixel(0, 0, true);
93 img.SetPixel(kWidthPixels - 1, kHeightLines - 1, false);
94 EXPECT_EQ(kWidthPixels, img.width());
95 EXPECT_EQ(kHeightLines, img.height());
96 EXPECT_TRUE(img.GetPixel(0, 0));
97 EXPECT_FALSE(img.GetPixel(kWidthPixels - 1, kHeightLines - 1));
98}
99
101 uint8_t buf[kHeightLines * kStrideBytes];
102 CJBig2_Image img(kWidthPixels, kTooLargeHeightLines, kStrideBytes, buf);
103 EXPECT_EQ(0, img.width());
104 EXPECT_EQ(0, img.height());
105 EXPECT_FALSE(img.data());
106}
107
109 uint8_t buf[kHeightLines * kStrideBytes];
110 CJBig2_Image img(kWidthPixels, kTooLargeHeightLines, kStrideBytes - 1, buf);
111 EXPECT_EQ(0, img.width());
112 EXPECT_EQ(0, img.height());
113 EXPECT_FALSE(img.data());
114}
115
117 CJBig2_Image img(kWidthPixels, kHeightLines);
118 img.SetPixel(0, 0, true);
119 img.SetPixel(kWidthPixels - 1, kHeightLines - 1, false);
120 img.Expand(kLargerHeightLines, true);
121 EXPECT_EQ(kWidthPixels, img.width());
122 EXPECT_EQ(kLargerHeightLines, img.height());
123 EXPECT_TRUE(img.GetPixel(0, 0));
124 EXPECT_FALSE(img.GetPixel(kWidthPixels - 1, kHeightLines - 1));
125 EXPECT_TRUE(img.GetPixel(kWidthPixels - 1, kLargerHeightLines - 1));
126}
127
129 CJBig2_Image img(kWidthPixels, kHeightLines);
130 img.SetPixel(0, 0, true);
131 img.SetPixel(kWidthPixels - 1, kHeightLines - 1, false);
132 img.Expand(kTooLargeHeightLines, true);
133 EXPECT_EQ(kWidthPixels, img.width());
134 EXPECT_EQ(kHeightLines, img.height());
135 EXPECT_TRUE(img.GetPixel(0, 0));
136 EXPECT_FALSE(img.GetPixel(kWidthPixels - 1, kHeightLines - 1));
137}
138
140 uint8_t buf[kHeightLines * kStrideBytes];
141 CJBig2_Image img(kWidthPixels, kHeightLines, kStrideBytes, buf);
142 img.SetPixel(0, 0, true);
143 img.SetPixel(kWidthPixels - 1, kHeightLines - 1, false);
144 img.Expand(kLargerHeightLines, true);
145 EXPECT_EQ(kWidthPixels, img.width());
146 EXPECT_EQ(kLargerHeightLines, img.height());
147 EXPECT_TRUE(img.GetPixel(0, 0));
148 EXPECT_FALSE(img.GetPixel(kWidthPixels - 1, kHeightLines - 1));
149 EXPECT_TRUE(img.GetPixel(kWidthPixels - 1, kLargerHeightLines - 1));
150}
151
153 uint8_t buf[kHeightLines * kStrideBytes];
154 CJBig2_Image img(kWidthPixels, kHeightLines, kStrideBytes, buf);
155 img.SetPixel(0, 0, true);
156 img.SetPixel(kWidthPixels - 1, kHeightLines - 1, false);
157 img.Expand(kTooLargeHeightLines, true);
158 EXPECT_EQ(kWidthPixels, img.width());
159 EXPECT_EQ(kHeightLines, img.height());
160 EXPECT_TRUE(img.GetPixel(0, 0));
161 EXPECT_FALSE(img.GetPixel(kWidthPixels - 1, kHeightLines - 1));
162}
163
165 auto empty = std::make_unique<CJBig2_Image>(0, 0);
166
167 // Empty subimage.
168 auto sub1 = empty->SubImage(0, 0, 0, 0);
169 EXPECT_EQ(sub1->width(), 0);
170 EXPECT_EQ(sub1->height(), 0);
171
172 // Larger dimensions are zero-padded.
173 auto sub2 = empty->SubImage(0, 0, 1, 1);
174 EXPECT_EQ(1, sub2->width());
175 EXPECT_EQ(1, sub2->height());
176 EXPECT_EQ(0, sub2->GetPixel(0, 0));
177
178 // Bad dimensions give an empty image.
179 sub2 = empty->SubImage(0, 0, -1, -1);
180 EXPECT_EQ(sub2->width(), 0);
181 EXPECT_EQ(sub2->height(), 0);
182
183 // Bad offsets zero pad the image.
184 auto sub3 = empty->SubImage(-1, -1, 2, 2);
185 EXPECT_EQ(sub3->width(), 2);
186 EXPECT_EQ(sub3->height(), 2);
187
188 // Bad dimensions and bad offsets give an empty image.
189 sub3 = empty->SubImage(-1, -1, -100, -100);
190 EXPECT_EQ(sub3->width(), 0);
191 EXPECT_EQ(sub3->height(), 0);
192}
193
195 // clang-format off
196 // 1-px wide rectangle in image.
197 uint8_t pattern[40] = {
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 };
204
205 // 1-px wide rectangle in image, offset 2 in x.
206 uint8_t pattern20[40] = {
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 };
213
214 // 1-px wide rectangle in image, offset 2 in x and y, padded.
215 uint8_t pattern22[40] = {
216 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 };
222
223 // 1-px wide rectangle in image, offset 16 in x, 1 in y, padded.
224 uint8_t pattern161[40] = {
225 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 };
231 // clang-format on
232
233 // Image size a nice clean power of two.
234 auto img32 = std::make_unique<CJBig2_Image>(32, 5, 8, pattern);
235
236 // Image size not a nice clean value.
237 auto img37 = std::make_unique<CJBig2_Image>(37, 5, 8, pattern);
238
239 // Expected results to check against.
240 auto expected20 = std::make_unique<CJBig2_Image>(30, 5, 8, pattern20);
241 auto expected22 = std::make_unique<CJBig2_Image>(30, 5, 8, pattern22);
242 auto expected161 = std::make_unique<CJBig2_Image>(25, 5, 8, pattern161);
243 auto expected_zeros = std::make_unique<CJBig2_Image>(32, 5);
244
245 // Empty subimage.
246 auto sub = img32->SubImage(0, 0, 0, 0);
247 EXPECT_EQ(sub->width(), 0);
248 EXPECT_EQ(sub->height(), 0);
249
250 // Full sub-image.
251 sub = img32->SubImage(0, 0, 32, 5);
252 EXPECT_EQ(sub->width(), 32);
253 EXPECT_EQ(sub->height(), 5);
254 CheckImageEq(img32.get(), sub.get(), __LINE__);
255
256 sub = img37->SubImage(0, 0, 32, 5);
257 EXPECT_EQ(sub->width(), 32);
258 EXPECT_EQ(sub->height(), 5);
259 CheckImageEq(img32.get(), sub.get(), __LINE__);
260
261 // Actual bit manipulations.
262 sub = img32->SubImage(2, 0, 30, 5);
263 CheckImageEq(expected20.get(), sub.get(), __LINE__);
264
265 sub = img37->SubImage(2, 2, 30, 5);
266 CheckImageEq(expected22.get(), sub.get(), __LINE__);
267
268 // Fast path.
269 sub = img37->SubImage(16, 1, 25, 5);
270 CheckImageEq(expected161.get(), sub.get(), __LINE__);
271
272 // Aligned Sub-image including cruft in stride beyond width.
273 sub = img37->SubImage(32, 0, 32, 5);
274 CheckImageEq(expected_zeros.get(), sub.get(), __LINE__);
275
276 // Sub-image waaaaay beyond width.
277 sub = img37->SubImage(2000, 0, 32, 5);
278 CheckImageEq(expected_zeros.get(), sub.get(), __LINE__);
279
280 // Sub-image waaaaay beyond height.
281 sub = img37->SubImage(0, 2000, 32, 5);
282 CheckImageEq(expected_zeros.get(), sub.get(), __LINE__);
283
284 // Sub-image with negative x offset.
285 sub = img37->SubImage(-1, 0, 32, 5);
286 CheckImageEq(expected_zeros.get(), sub.get(), __LINE__);
287
288 // Sub-image with negative y offset.
289 sub = img37->SubImage(0, -1, 32, 5);
290 CheckImageEq(expected_zeros.get(), sub.get(), __LINE__);
291
292 // Sub-image with negative width.
293 sub = img37->SubImage(-1, 0, 32, 5);
294 CheckImageEq(expected_zeros.get(), sub.get(), __LINE__);
295
296 // Sub-image with negative height.
297 sub = img37->SubImage(0, -1, 32, 5);
298 CheckImageEq(expected_zeros.get(), sub.get(), __LINE__);
299
300 // Sub-image wider than original.
301 sub = img37->SubImage(0, 0, 128, 5);
302 EXPECT_EQ(128, sub->width());
303 EXPECT_EQ(5, sub->height());
304
305 // Sub-image higher than original.
306 sub = img37->SubImage(0, 0, 32, 40);
307 EXPECT_EQ(32, sub->width());
308 EXPECT_EQ(40, sub->height());
309}
310
312 // clang-format off
313 // Horizontal line in image.
314 uint8_t pattern[24] = {
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 };
319
320 uint8_t expected_pattern[24] = {
321 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 };
325 // clang-format on
326
327 auto img = std::make_unique<CJBig2_Image>(37, 3, 8, pattern);
328 auto expected = std::make_unique<CJBig2_Image>(37, 3, 8, expected_pattern);
329
330 // Shuffle.
331 img->CopyLine(2, 1);
332 img->CopyLine(1, 0);
333 img->CopyLine(0, 2);
334
335 // Clear top line via invalid |from| offset.
336 img->CopyLine(2, 3);
337
338 // Copies with invalid |to|s don't mess with things.
339 img->CopyLine(-1, 0);
340 img->CopyLine(4, 0);
341 img->CopyLine(-1, -1);
342 img->CopyLine(4, 4);
343
344 CheckImageEq(expected.get(), img.get(), __LINE__);
345}
void SetPixel(int32_t x, int32_t y, int v)
int32_t height() const
Definition JBig2_Image.h:40
CJBig2_Image(int32_t w, int32_t h)
uint8_t * GetLine(int32_t y) const
Definition JBig2_Image.h:49
uint8_t * data() const
Definition JBig2_Image.h:43
int GetPixel(int32_t x, int32_t y) const
int32_t width() const
Definition JBig2_Image.h:39
void Expand(int32_t h, bool v)
TEST(FXCRYPT, MD5GenerateEmtpyData)