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/fxcrt/span.h"
23#include "core/fxge/dib/cfx_dibitmap.h"
24#include "core/fxge/dib/fx_dib.h"
25#include "testing/gmock/include/gmock/gmock.h"
26#include "testing/gtest/include/gtest/gtest.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 RetainPtr<CFX_DIBitmap> bitmap) {
54 FXCODEC_STATUS status = decoder.StartDecode(std::move(bitmap));
55 while (status == FXCODEC_STATUS::kDecodeToBeContinued) {
56 status = decoder.ContinueDecode();
57 }
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
105
109
113 ASSERT_EQ(1u, frames);
114
117 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
118}
119
121 static constexpr uint8_t kInput[] = {
122 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
123 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
124 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b,
126 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc0,
127 0x80, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00};
128
130
136
140
144
148 ASSERT_EQ(1u, frames);
149
152}
153
155 static constexpr uint8_t kInput[] = {
156 0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
157 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
158 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
159 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0x00};
161
163
169
173
177
181 ASSERT_EQ(1u, frames);
182
185 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
186}
187
189 static constexpr uint8_t kInput[] = {
190 0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
191 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
192 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
193 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0xff};
195
197
203
207
211
215 ASSERT_EQ(1u, frames);
216
219 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
220}
221
223 static constexpr uint8_t kInput[] = {
224 0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00,
225 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
226 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
227 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0x00};
229
231
237
241
245
249 ASSERT_EQ(1u, frames);
250
253 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
254}
255
257 static constexpr uint8_t kInput[] = {
258 0x42, 0x4d, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00,
259 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
260 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
261 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0x00};
263
265
271
275
279
283 ASSERT_EQ(1u, frames);
284
287 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
288}
289
291 // Construct a 24-bit BMP larger than `kBlockSize` (4096 bytes).
292 static constexpr uint8_t kWidth = 37;
293 static constexpr uint8_t kHeight = 38;
294 static constexpr size_t kScanlineSize = kWidth * 3 + 1;
296 0x42, 0x4d, 0xd6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36,
297 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, kWidth, 0x00, 0x00, 0x00,
298 kHeight, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0xa0, 0x10, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b,
300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
302 std::iota(input.begin() + 54, input.end(), 0);
303 ASSERT_EQ(4310u, input.size());
304
306
312
316
320
324 ASSERT_EQ(1u, frames);
325
328
329 for (size_t row = 0; row < kHeight; ++row) {
330 // BMP encodes rows from bottom to top by default.
331 pdfium::span<const uint8_t> scanline =
333
337
338 // Last byte is padding to a 32-bit boundary.
340 }
341}
342#endif // PDF_ENABLE_XFA_BMP
343
344#ifdef PDF_ENABLE_XFA_GIF
346 static constexpr uint8_t kInput[] = {
347 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x01,
348 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x2c, 0x00, 0x00, 0x00, 0x00,
349 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b};
350
352
358
362
366
370 ASSERT_EQ(1u, frames);
371
374 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0xff));
375}
376
378 static constexpr uint8_t kInput[] = {
379 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80,
380 0x01, 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x21, 0xf9, 0x04,
381 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01,
382 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b};
383
385
391
395
399
403 ASSERT_EQ(1u, frames);
404
407 EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0xff));
408}
409
411 // This GIF causes `LZWDecompressor::Create()` to fail because the minimum
412 // code size is too small for the palette.
413 static constexpr uint8_t kInput[] = {
414 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00, 0x01, 0x00, 0x82,
415 0x01, 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81,
416 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
417 0x85, 0x86, 0x86, 0x86, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
418 0x01, 0x00, 0x00, 0x02, 0x2, 0x44, 0x01, 0x00, 0x3b};
419
421
427
431
435
439 ASSERT_EQ(1u, frames);
440
443}
444
446 // This GIF contains an LZW code unit split across 2 scanlines. The decoder
447 // must continue decoding the second scanline using the residual data.
448 static constexpr uint8_t kInput[] = {
449 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x02, 0x00, 0x80, 0x01,
450 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x2c, 0x00, 0x00, 0x00, 0x00,
451 0x04, 0x00, 0x02, 0x00, 0x00, 0x02, 0x03, 0x84, 0x6f, 0x05, 0x00, 0x3b};
452
454
460
464
468
472 ASSERT_EQ(1u, frames);
473
477 ElementsAre(0xc0, 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff, 0xc0,
478 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
480 ElementsAre(0xc0, 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff, 0xc0,
481 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
482}
483
485 // This GIF contains a scanline split across 2 data sub-blocks. The decoder
486 // must continue decoding in the second sub-block.
487 static constexpr uint8_t kInput[] = {
488 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x02, 0x00,
489 0x80, 0x01, 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x2c,
490 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x02,
491 0x02, 0x84, 0x6f, 0x01, 0x05, 0x00, 0x3b};
492
494
500
504
508
512 ASSERT_EQ(1u, frames);
513
517 ElementsAre(0xc0, 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff, 0xc0,
518 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
520 ElementsAre(0xc0, 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff, 0xc0,
521 0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
522}
523#endif // PDF_ENABLE_XFA_GIF
524
525} // namespace fxcodec
FXCODEC_STATUS StartDecode(RetainPtr< CFX_DIBitmap > bitmap)
FXCODEC_STATUS