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
progressive_decoder_unittest.cpp
Go to the documentation of this file.
1// Copyright 2019 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#include "core/fxcodec/progressive_decoder.h"
6
7#include <stddef.h>
8#include <stdint.h>
9
10#include <array>
11#include <numeric>
12#include <tuple>
13#include <utility>
14
15#include "core/fxcodec/fx_codec.h"
16#include "core/fxcodec/fx_codec_def.h"
17#include "core/fxcodec/jpeg/jpeg_progressive_decoder.h"
18#include "core/fxcrt/cfx_read_only_span_stream.h"
19#include "core/fxcrt/cfx_read_only_vector_stream.h"
20#include "core/fxcrt/data_vector.h"
21#include "core/fxcrt/retain_ptr.h"
22#include "core/fxge/dib/cfx_dibitmap.h"
23#include "core/fxge/dib/fx_dib.h"
24#include "testing/gmock/include/gmock/gmock.h"
25#include "testing/gtest/include/gtest/gtest.h"
26#include "third_party/base/containers/span.h"
27
28#ifdef PDF_ENABLE_XFA_BMP
29#include "core/fxcodec/bmp/bmp_decoder.h"
30#include "core/fxcodec/bmp/bmp_progressive_decoder.h"
31#endif // PDF_ENABLE_XFA_BMP
32
33#ifdef PDF_ENABLE_XFA_GIF
34#include "core/fxcodec/gif/gif_decoder.h"
35#include "core/fxcodec/gif/gif_progressive_decoder.h"
36#endif // PDF_ENABLE_XFA_GIF
37
38namespace fxcodec {
39
40namespace {
41
42using ::testing::ElementsAre;
43using ::testing::ElementsAreArray;
44
45template <size_t Size>
46constexpr std::array<uint8_t, Size> IotaArray(uint8_t start) {
47 std::array<uint8_t, Size> result;
48 std::iota(result.begin(), result.end(), start);
49 return result;
50}
51
52FXCODEC_STATUS DecodeToBitmap(ProgressiveDecoder& decoder,
53 const fxcrt::RetainPtr<CFX_DIBitmap>& bitmap) {
54 FXCODEC_STATUS status = decoder.StartDecode(bitmap, 0, 0, bitmap->GetWidth(),
55 bitmap->GetHeight());
57 status = decoder.ContinueDecode();
58 return status;
59}
60
61class ProgressiveDecoderTest : public testing::Test {
62 void SetUp() override {
63#ifdef PDF_ENABLE_XFA_BMP
64 BmpProgressiveDecoder::InitializeGlobals();
65#endif
66#ifdef PDF_ENABLE_XFA_GIF
67 GifProgressiveDecoder::InitializeGlobals();
68#endif
69 JpegProgressiveDecoder::InitializeGlobals();
70 }
71 void TearDown() override {
72 JpegProgressiveDecoder::DestroyGlobals();
73#ifdef PDF_ENABLE_XFA_GIF
74 GifProgressiveDecoder::DestroyGlobals();
75#endif
76#ifdef PDF_ENABLE_XFA_BMP
77 BmpProgressiveDecoder::DestroyGlobals();
78#endif
79 }
80};
81
82} // namespace
83
84#ifdef PDF_ENABLE_XFA_BMP
86 static constexpr uint8_t kInput[] = {
87 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
88 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
89 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b,
91 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc0,
92 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};
93
95
101
104
107
111 ASSERT_EQ(1u, frames);
112
115 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
116}
117
119 static constexpr uint8_t kInput[] = {
120 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
121 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
122 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b,
124 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc0,
125 0x80, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00};
126
128
134
137
140
144 ASSERT_EQ(1u, frames);
145
148}
149
151 static constexpr uint8_t kInput[] = {
152 0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
153 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
154 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
155 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0x00};
157
159
165
168
171
175 ASSERT_EQ(1u, frames);
176
179 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
180}
181
183 static constexpr uint8_t kInput[] = {
184 0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
185 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
186 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
187 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0xff};
189
191
197
200
203
207 ASSERT_EQ(1u, frames);
208
211 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
212}
213
215 static constexpr uint8_t kInput[] = {
216 0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00,
217 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
218 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
219 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0x00};
221
223
229
232
235
239 ASSERT_EQ(1u, frames);
240
243 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
244}
245
247 static constexpr uint8_t kInput[] = {
248 0x42, 0x4d, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00,
249 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
250 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
251 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0x00};
253
255
261
264
267
271 ASSERT_EQ(1u, frames);
272
275 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
276}
277
279 // Construct a 24-bit BMP larger than `kBlockSize` (4096 bytes).
280 static constexpr uint8_t kWidth = 37;
281 static constexpr uint8_t kHeight = 38;
282 static constexpr size_t kScanlineSize = kWidth * 3 + 1;
284 0x42, 0x4d, 0xd6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36,
285 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, kWidth, 0x00, 0x00, 0x00,
286 kHeight, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0xa0, 0x10, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b,
288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
290 std::iota(input.begin() + 54, input.end(), 0);
291 ASSERT_EQ(4310u, input.size());
292
294
300
303
306
310 ASSERT_EQ(1u, frames);
311
314
315 for (size_t row = 0; row < kHeight; ++row) {
316 // BMP encodes rows from bottom to top by default.
317 pdfium::span<const uint8_t> scanline =
319
323
324 // Last byte is padding to a 32-bit boundary.
326 }
327}
328#endif // PDF_ENABLE_XFA_BMP
329
330#ifdef PDF_ENABLE_XFA_GIF
332 static constexpr uint8_t kInput[] = {
333 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x01,
334 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x2c, 0x00, 0x00, 0x00, 0x00,
335 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b};
336
338
344
347
350
354 ASSERT_EQ(1u, frames);
355
358 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0xff));
359}
360
362 static constexpr uint8_t kInput[] = {
363 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80,
364 0x01, 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x21, 0xf9, 0x04,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01,
366 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b};
367
369
375
378
381
385 ASSERT_EQ(1u, frames);
386
389 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0xff));
390}
391
393 // This GIF causes `LZWDecompressor::Create()` to fail because the minimum
394 // code size is too small for the palette.
395 static constexpr uint8_t kInput[] = {
396 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00, 0x01, 0x00, 0x82,
397 0x01, 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81,
398 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
399 0x85, 0x86, 0x86, 0x86, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
400 0x01, 0x00, 0x00, 0x02, 0x2, 0x44, 0x01, 0x00, 0x3b};
401
403
409
412
415
419 ASSERT_EQ(1u, frames);
420
423}
424
426 // This GIF contains an LZW code unit split across 2 scanlines. The decoder
427 // must continue decoding the second scanline using the residual data.
428 static constexpr uint8_t kInput[] = {
429 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x02, 0x00, 0x80, 0x01,
430 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x2c, 0x00, 0x00, 0x00, 0x00,
431 0x04, 0x00, 0x02, 0x00, 0x00, 0x02, 0x03, 0x84, 0x6f, 0x05, 0x00, 0x3b};
432
434
440
443
446
450 ASSERT_EQ(1u, frames);
451
455 ElementsAre(0xc0, 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff, 0xc0,
456 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
458 ElementsAre(0xc0, 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff, 0xc0,
459 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
460}
461
463 // This GIF contains a scanline split across 2 data sub-blocks. The decoder
464 // must continue decoding in the second sub-block.
465 static constexpr uint8_t kInput[] = {
466 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x02, 0x00,
467 0x80, 0x01, 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x2c,
468 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x02,
469 0x02, 0x84, 0x6f, 0x01, 0x05, 0x00, 0x3b};
470
472
478
481
484
488 ASSERT_EQ(1u, frames);
489
493 ElementsAre(0xc0, 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff, 0xc0,
494 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
496 ElementsAre(0xc0, 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff, 0xc0,
497 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
498}
499#endif // PDF_ENABLE_XFA_GIF
500
501} // namespace fxcodec
FXCODEC_STATUS