Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp

Issue 2386453003: WIP: Implement APNG (Closed)
Patch Set: Progressive decoding for animated images Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
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 "platform/image-decoders/png/PNGImageDecoder.h"
6
7 #include "png.h"
8 #include "platform/image-decoders/ImageDecoderTestHelpers.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include <memory>
11
12 namespace blink {
13
14 namespace {
15
16 std::unique_ptr<ImageDecoder> createDecoder(ImageDecoder::AlphaOption alphaOptio n)
17 {
18 return wrapUnique(new PNGImageDecoder(alphaOption,
19 ImageDecoder::GammaAndColorProfileAppl ied,
20 ImageDecoder::noDecodedImageByteLimit) );
21 }
22
23 std::unique_ptr<ImageDecoder> createDecoder()
24 {
25 return createDecoder(ImageDecoder::AlphaNotPremultiplied);
26 }
27
28 std::unique_ptr<ImageDecoder> createDecoderWithPngData(const char* pngFile)
29 {
30 auto decoder = createDecoder();
31 auto data = readFile(pngFile);
32 EXPECT_FALSE(data->isEmpty());
33 decoder->setData(data.get(), true);
34 return decoder;
35 }
36
37 void testSize(const char* pngFile, IntSize expectedSize)
38 {
39 auto decoder = createDecoderWithPngData(pngFile);
40 EXPECT_TRUE(decoder->isSizeAvailable());
41 EXPECT_EQ(expectedSize, decoder->size());
42 }
43
44 void writeUint32(uint32_t val, png_byte* data)
45 {
46 data[0] = val >> 24;
47 data[1] = val >> 16;
48 data[2] = val >> 8;
49 data[3] = val;
50 }
51
52 void testRepetitionCount(const char* pngFile, int expectedRepetitionCount)
53 {
54 auto decoder = createDecoderWithPngData(pngFile);
55 // Decode frame count should see the number of repetitions as well.
56 decoder->frameCount();
57 EXPECT_FALSE(decoder->failed());
58 EXPECT_EQ(expectedRepetitionCount, decoder->repetitionCount());
59 }
60
61 // Test whether querying for the size of the image works if we present the
62 // data byte by byte.
63 void testSizeByteByByte(const char *pngFile, size_t bytesNeededToDecodeSize,
64 IntSize expectedSize)
65 {
66 auto decoder = createDecoder();
67 auto data = readFile(pngFile);
68 ASSERT_FALSE(data->isEmpty());
69 ASSERT_LT(bytesNeededToDecodeSize, data->size());
70
71 for (size_t length = 1; length <= bytesNeededToDecodeSize; length++) {
72 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(),
73 length);
74 decoder->setData(tempData.get(), false);
75
76 if (length < bytesNeededToDecodeSize) {
77 EXPECT_FALSE(decoder->isSizeAvailable());
78 EXPECT_TRUE(decoder->size().isEmpty());
79 EXPECT_FALSE(decoder->failed());
80 } else {
81 EXPECT_TRUE(decoder->isSizeAvailable());
82 EXPECT_EQ(expectedSize, decoder->size());
83 }
84 }
85 EXPECT_FALSE(decoder->failed());
86 }
87
88 struct PublicFrameInfo {
89 size_t duration;
90 IntRect frameRect;
91 ImageFrame::AlphaBlendSource alphaBlend;
92 ImageFrame::DisposalMethod disposalMethod;
93 };
94
95 // This is the frame data for the following PNG image:
96 // /LayoutTests/fast/images/resources/png-animated-idat-part-of-animation.png
97 static PublicFrameInfo pngAnimatedFrameInfo[] = {
98 {500, {IntPoint(0, 0), IntSize(5, 5)}, ImageFrame::BlendAtopBgcolor,
99 ImageFrame::DisposeKeep},
100 {900, {IntPoint(1, 1), IntSize(3, 1)}, ImageFrame::BlendAtopBgcolor,
101 ImageFrame::DisposeOverwriteBgcolor},
102 {2000, {IntPoint(1, 2), IntSize(3, 2)}, ImageFrame::BlendAtopPreviousFrame,
103 ImageFrame::DisposeKeep},
104 {1500, {IntPoint(1, 2), IntSize(3, 1)}, ImageFrame::BlendAtopBgcolor,
105 ImageFrame::DisposeKeep},
106 };
107
108 void compareFrameWithExpectation(const PublicFrameInfo& expected,
109 const ImageFrame* frame)
110 {
111 EXPECT_EQ(expected.duration, frame->duration());
112 EXPECT_EQ(expected.frameRect, frame->originalFrameRect());
113 EXPECT_EQ(expected.disposalMethod, frame->getDisposalMethod());
114 EXPECT_EQ(expected.alphaBlend, frame->getAlphaBlendSource());
115 }
116
117 // This function removes |length| bytes at |offset|, and then calls frameCount.
118 // It assumes the missing bytes should result in a failed decode.
119 void testMissingDataBreaksDecoding(const char* pngFile, size_t offset,
120 size_t length)
121 {
122 auto decoder = createDecoder();
123 auto data = readFile(pngFile);
124 ASSERT_FALSE(data->isEmpty());
125
126 RefPtr<SharedBuffer> invalidData = SharedBuffer::create(data->data(),
127 offset);
128 invalidData->append(SharedBuffer::create(data->data() + offset + length,
129 data->size() - offset - length));
130 ASSERT_EQ(data->size() - length, invalidData->size());
131
132 decoder->setData(invalidData, true);
133 decoder->frameCount();
134 EXPECT_TRUE(decoder->failed());
135 }
136
137 // Decoding up to the indicated fcTL offset and then provide an fcTL with
138 // the wrong chunk size (20 instead of 26). It should break the decoder.
139 void testInvalidFctlSize(const char* pngFile, size_t offsetFctl,
140 size_t expectedFrameCountBeforeFail)
141 {
142 auto data = readFile(pngFile);
143 ASSERT_FALSE(data->isEmpty());
144
145 auto decoder = createDecoder();
146 RefPtr<SharedBuffer> invalidData = SharedBuffer::create(data->data(),
147 offsetFctl);
148
149 // Test if this gives the correct frame count, before the fcTL is parsed.
150 decoder->setData(invalidData, false);
151 EXPECT_EQ(expectedFrameCountBeforeFail, decoder->frameCount());
152 ASSERT_FALSE(decoder->failed());
153
154 // Append the wrong size to the data stream
155 png_byte sizeChunk[4];
156 writeUint32(20, sizeChunk);
157 invalidData->append(reinterpret_cast<char*>(sizeChunk), 4u);
158
159 // Skip the size in the original data, but provide the rest of the fcTL,
160 // which is 4B of tag, 26B of data and 4B of CRC, totalling 34B.
161 invalidData->append(data->data() + offsetFctl + 4, 34u);
162
163 decoder->setData(invalidData, false);
164 decoder->frameCount();
165 EXPECT_TRUE(decoder->failed());
166 }
167
168 void testDifferentActlFrameCountIsIgnored(const char* pngFile,
169 size_t offsetActl,
170 size_t injectedFrameCount,
171 size_t expectedFrameCount)
172 {
173 // First make sure that this tests makes sense.
174 ASSERT_NE(injectedFrameCount, expectedFrameCount);
175
176 auto data = readFile(pngFile);
177 auto decoder = createDecoder();
178 ASSERT_FALSE(data->isEmpty());
179
180 RefPtr<SharedBuffer> diffActlData = SharedBuffer::create(data->data(),
181 offsetActl + 8);
182 // Write the injectedFrameCount to the stream
183 png_byte sizeChunk[4];
184 writeUint32(injectedFrameCount, sizeChunk);
185 diffActlData->append(reinterpret_cast<char*>(sizeChunk), 4u);
186 // Append the rest of the data. The first |offsetActl + 12| bytes that are
187 // already in diffActlData should not be appended again.
188 diffActlData->append(data->data() + offsetActl + 12,
189 data->size() - offsetActl - 12);
190
191 decoder->setData(diffActlData, true);
192 EXPECT_EQ(expectedFrameCount, decoder->frameCount());
193 }
194
195 // Test if the frame bitmap hashes of truncated decoding are equal to the
196 // hashes found by incremental decoding.
197 void testProgressiveDecoding(const char *pngFile)
198 {
199 RefPtr<SharedBuffer> fullData = readFile(pngFile);
200 ASSERT_TRUE(fullData.get());
201 const size_t fullLength = fullData->size();
202
203 std::unique_ptr<ImageDecoder> decoder;
204 ImageFrame* frame;
205
206 Vector<unsigned> truncatedHashes;
207 Vector<unsigned> progressiveHashes;
208
209 // Compute hashes when the file is truncated.
210 const size_t increment = 13;
211 for (size_t i = 1; i <= fullLength; i += increment) {
212 decoder = createDecoder();
213 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
214 decoder->setData(data.get(), i == fullLength);
215 size_t frameCount = decoder->frameCount();
216 ASSERT_FALSE(decoder->failed());
217 if (frameCount == 0) {
218 truncatedHashes.append(0);
219 continue;
220 }
221 frame = decoder->frameBufferAtIndex(frameCount - 1);
222 if (!frame) {
223 truncatedHashes.append(0);
224 continue;
225 }
226 truncatedHashes.append(hashBitmap(frame->bitmap()));
227 }
228
229 // Compute hashes when the file is progressively decoded.
230 decoder = createDecoder();
231 for (size_t i = 1; i <= fullLength; i += increment) {
232 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
233 decoder->setData(data.get(), i == fullLength);
234 ASSERT_FALSE(decoder->failed());
235 size_t frameCount = decoder->frameCount();
236 if (frameCount == 0) {
237 progressiveHashes.append(0);
238 continue;
239 }
240 frame = decoder->frameBufferAtIndex(frameCount - 1);
241 if (!frame) {
242 progressiveHashes.append(0);
243 continue;
244 }
245 progressiveHashes.append(hashBitmap(frame->bitmap()));
246 }
247
248 for (size_t i = 0; i < truncatedHashes.size(); ++i)
249 ASSERT_EQ(truncatedHashes[i], progressiveHashes[i]);
250 }
251
252 // This test checks whether providing the full data, after the first frame has
scroggo_chromium 2016/10/28 14:20:33 I find this sentence confusing. Instead of saying
joostouwerling 2016/10/28 18:41:25 Done.
253 // been partially decoded, does not result in a failed decoder. It tests whether
254 // the decoder remembers where it stopped progressively decoding the image
255 // and properly continues from there, even though all data is available.
256 void testProgressiveDecodingContinuesAfterFullData(const char* pngFile,
257 size_t offsetMidFirstFrame)
258 {
259 auto fullData = readFile(pngFile);
260 auto decoder = createDecoder();
261 ASSERT_FALSE(fullData->isEmpty());
262
263 RefPtr<SharedBuffer> partialData =
264 SharedBuffer::create(fullData->data(), offsetMidFirstFrame);
265 decoder->setData(partialData, false);
266
267 EXPECT_EQ(1u, decoder->frameCount());
268 ImageFrame* frame = decoder->frameBufferAtIndex(0);
269 EXPECT_EQ(frame->getStatus(), ImageFrame::FramePartial);
270 unsigned hashPartial = hashBitmap(frame->bitmap());
271
272 decoder->setData(fullData, true);
273 frame = decoder->frameBufferAtIndex(0);
274 EXPECT_EQ(frame->getStatus(), ImageFrame::FrameComplete);
275 unsigned hashFull = hashBitmap(frame->bitmap());
276
277 EXPECT_FALSE(decoder->failed());
278 EXPECT_NE(hashFull, hashPartial);
279 }
280
281 // This tests if the frame buffer contents change when progressively decoding
scroggo_chromium 2016/10/28 14:20:32 This test verifies that the frame buffer contents
joostouwerling 2016/10/28 18:41:25 Done.
282 // the first frame. It should change more than 1 time: once for the first data,
283 // and at least once more thereafter. if |offsetFirstFrameEnd| == 0, the test
284 // uses the full data size of the image for it's value.
scroggo_chromium 2016/10/28 14:20:32 its*
joostouwerling 2016/10/28 18:41:25 Done.
285 void testProgressiveDecodingChangesFrameBuffer(const char* pngFile,
286 size_t offsetFirstFrameEnd,
287 size_t step = 1u)
288 {
289 auto fullData = readFile(pngFile);
290 auto decoder = createDecoder();
291 ASSERT_FALSE(fullData->isEmpty());
292
293 if (offsetFirstFrameEnd == 0)
294 offsetFirstFrameEnd = fullData->size();
295
296 size_t numTimesBufferChanged = 0;
297 unsigned lastHash;
298
299 for (size_t length = 1; length <= offsetFirstFrameEnd; length += step) {
300 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(),
301 length);
302 decoder->setData(data, false);
303 ImageFrame* frame = decoder->frameBufferAtIndex(0);
304 if (!frame)
305 continue;
306 unsigned newHash = hashBitmap(frame->bitmap());
307 if (newHash != lastHash) {
308 lastHash = newHash;
309 numTimesBufferChanged++;
310 }
311 }
312 EXPECT_GT(numTimesBufferChanged, 1u);
313 }
314
315 } // Anonymous namespace
316
317 // Animated PNG Tests
318
319 TEST(AnimatedPNGTests, sizeTest)
320 {
321 testSize("/LayoutTests/fast/images/resources/png-animated-idat-part-of-anima tion.png", IntSize(5, 5));
322 testSize("/LayoutTests/fast/images/resources/png-animated-idat-not-part-of-a nimation.png", IntSize(227, 35));
323 }
324
325 TEST(AnimatedPNGTests, repetitionCountTest)
326 {
327 testRepetitionCount("/LayoutTests/fast/images/resources/png-animated-idat-pa rt-of-animation.png", 7u);
328 // This is an "animated" image with only one frame, that is, the IDAT is
329 // ignored and there is one fdAT frame. so it should be considered
330 // non-animated.
331 testRepetitionCount("/LayoutTests/fast/images/resources/png-animated-idat-no t-part-of-animation.png", cAnimationNone);
332 }
333
334 // Test if the decoded metdata corresponds to the defined expectations
335 TEST(AnimatedPNGTests, MetaDataTest)
336 {
337 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
338 constexpr size_t expectedFrameCount = 4;
339
340 auto decoder = createDecoderWithPngData(pngFile);
341 ASSERT_EQ(expectedFrameCount, decoder->frameCount());
342 for (size_t i = 0; i < expectedFrameCount; i++)
343 compareFrameWithExpectation(pngAnimatedFrameInfo[i],
344 decoder->frameBufferAtIndex(i));
345 }
346
347 TEST(AnimatedPNGTests, ByteByByteSizeAvailable)
348 {
349 testSizeByteByByte("/LayoutTests/fast/images/resources/png-animated-idat-par t-of-animation.png",
350 141u, IntSize(5, 5));
351 testSizeByteByByte("/LayoutTests/fast/images/resources/png-animated-idat-not -part-of-animation.png",
352 79u, IntSize(227, 35));
353 }
354
355 // Test whether the frame metadata decoding also works when we provide the data
356 // byte by byte. This should cover the case when the client does not provide
357 // all data at once. At given offsets, we expect frames to become available.
358 // This test checks whether that is the case, and if so, if the frame data is
359 // equal to what we expected.
360 TEST(AnimatedPNGTests, ByteByByteMetaData)
361 {
362 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
363 constexpr size_t expectedFrameCount = 4;
364
365 // These are the byte offsets where each frame should have been parsed.
366 // It boils down to the offset of the first fcTL / IEND after the last
367 // frame data chunk, plus 8 bytes for recognition. The exception on this is
368 // the first frame, which is reported when its first framedata is seen.
369 size_t frameOffsets[expectedFrameCount] = {141, 249, 322, 430};
370
371 auto decoder = createDecoder();
372 auto data = readFile(pngFile);
373 ASSERT_FALSE(data->isEmpty());
374 size_t framesParsed = 0;
375
376 for (size_t length = 1; length <= frameOffsets[expectedFrameCount - 1]; leng th++) {
377 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(),
378 length);
379 decoder->setData(tempData.get(), false);
380 EXPECT_FALSE(decoder->failed());
381 if (length < frameOffsets[framesParsed]) {
382 EXPECT_EQ(framesParsed, decoder->frameCount());
383 } else {
384 ASSERT_EQ(framesParsed + 1, decoder->frameCount());
385 compareFrameWithExpectation(pngAnimatedFrameInfo[framesParsed],
386 decoder->frameBufferAtIndex(framesParsed ));
387 framesParsed++;
388 }
389 }
390 EXPECT_EQ(expectedFrameCount, decoder->frameCount());
391 EXPECT_FALSE(decoder->failed());
392 }
393
394 // This tests if the frame count gets set correctly when parsing frameCount
395 // fails in one of the parsing queries.
396 //
397 // First, enough data is provided such that two frames should be registered.
398 // The decoder should at this point not be in the failed status.
399 //
400 // Then, we provide the rest of the data except for the last IEND chunk, but
401 // tell the decoder that this is all the data we have. Now, the decoder should
402 // be in the failed state since all data is provided but no IEND chunk has been
403 // seen. The frame count should be three, since one extra frame should be
404 // discovered. The fourth frame should *not* be registered since the reader
405 // should not be able to determine where the frame ends.
406 TEST(AnimatedPNGTests, FrameCountWithTruncatedData)
407 {
408 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
409 auto decoder = createDecoder();
410 auto data = readFile(pngFile);
411 ASSERT_FALSE(data->isEmpty());
412
413 // Parse up to and including the first two frames
414 const size_t offsetTwoFrames = 249;
415 const size_t expectedFramesAfter249Bytes = 2;
416 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(),
417 offsetTwoFrames);
418 decoder->setData(tempData.get(), false);
419 EXPECT_EQ(expectedFramesAfter249Bytes, decoder->frameCount());
420 EXPECT_FALSE(decoder->failed());
421
422 // Provide the rest of the data except for the last IEND chunk.
423 const size_t expectedFramesAfterAllExpect12Bytes = 3;
424 tempData = SharedBuffer::create(data->data(), data->size() - 12);
425 decoder->setData(tempData.get(), true);
426 EXPECT_EQ(expectedFramesAfterAllExpect12Bytes, decoder->frameCount());
427 EXPECT_TRUE(decoder->failed());
428 }
429
430 TEST(AnimatedPNGTests, TestRandomFrameDecode)
431 {
432 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /png-animated-idat-part-of-animation.png");
433 ASSERT_TRUE(fullData.get());
434 Vector<unsigned> baselineHashes;
435 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes);
436 size_t frameCount = baselineHashes.size();
437
438 // Random decoding should get the same results as sequential decoding.
439 std::unique_ptr<ImageDecoder> decoder = createDecoder();
440 decoder->setData(fullData.get(), true);
441 const size_t skippingStep = 2;
442 for (size_t i = 0; i < skippingStep; ++i) {
443 for (size_t j = i; j < frameCount; j += skippingStep) {
444 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
445 ImageFrame* frame = decoder->frameBufferAtIndex(j);
446 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->bitmap()));
447 }
448 }
449
450 // Decoding in reverse order.
451 decoder = createDecoder();
452 decoder->setData(fullData.get(), true);
453 for (size_t i = frameCount; i; --i) {
454 SCOPED_TRACE(testing::Message() << "Reverse i:" << i);
455 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1);
456 EXPECT_EQ(baselineHashes[i - 1], hashBitmap(frame->bitmap()));
457 }
458
459 }
460
461 TEST(AnimatedPNGTests, TestDecodeAfterReallocation)
462 {
463 std::unique_ptr<ImageDecoder> decoder = createDecoder();
464 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/png -animated-idat-part-of-animation.png");
465 ASSERT_TRUE(data.get());
466
467 // Parse from |data|.
468 decoder->setData(data.get(), true);
469 size_t frameCount = decoder->frameCount();
470
471 // ... and then decode frames from |reallocatedData|.
472 RefPtr<SharedBuffer> reallocatedData = data.get()->copy();
473 ASSERT_TRUE(reallocatedData.get());
474 data.clear();
475 decoder->setData(reallocatedData.get(), true);
476
477 for (size_t i = 0; i < frameCount; ++i) {
478 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
479 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus());
480 }
481 }
482
483 TEST(AnimatedPNGTests, ProgressiveDecode)
484 {
485 testProgressiveDecoding("/LayoutTests/fast/images/resources/png-animated-ida t-part-of-animation.png");
486 }
487
488 TEST(AnimatedPNGTests, ParseAndDecodeByteByByte)
489 {
490 testByteByByteDecode(&createDecoder,
491 "/LayoutTests/fast/images/resources/png-animated-idat-p art-of-animation.png",
492 4u, 7u);
493 }
494
495 TEST(AnimatedPNGTests, FctlWrongSizeBreaksDecoding)
496 {
497 const char* pngFile = "//LayoutTests/fast/images/resources/png-animated-idat -part-of-animation.png";
498 auto data = readFile(pngFile);
499 ASSERT_FALSE(data->isEmpty());
500
501 // Test the first fcTL in the stream. Because no frame data has been set
502 // at this point, the expected frame count is zero.
503 testInvalidFctlSize("//LayoutTests/fast/images/resources/png-animated-idat-p art-of-animation.png",
504 95u, 0u);
505
506 // Test for the third fcTL in the stream. This should be tested as well,
507 // since the first fcTL is parsed in PNGImageReader::parseSize() whereas
508 // later fcTLs are parsed in PNGImageReader::parse() as part of framecount.
509 // The expected frame count before the fcTL chunk is 1u, since the second
510 // frame is registered when the third fcTL (or IEND) is seen.
511 testInvalidFctlSize("//LayoutTests/fast/images/resources/png-animated-idat-p art-of-animation.png",
512 241u, 1u);
513
514 }
515
516 TEST(AnimatedPNGTests, MissingFctlDataBreaksDecoding)
517 {
518 // The fcTL chunk starts at 95u, add 10u to get to the content data, and
519 // remove 5 bytes of data.
520 testMissingDataBreaksDecoding(
521 "//LayoutTests/fast/images/resources/png-animated-idat-part-of-animation .png",
522 105u, 5u);
523 }
524
525 TEST(AnimatedPNGTests, MissingActlResultsInNonAnimated)
526 {
527 const char* pngFile = "//LayoutTests/fast/images/resources/png-animated-idat -part-of-animation.png";
528 auto data = readFile(pngFile);
529 auto decoder = createDecoder();
530 ASSERT_FALSE(data->isEmpty());
531
532 // Remove the acTL chunk from the stream.
533 size_t offsetActl = 33;
534 RefPtr<SharedBuffer> noActlData = SharedBuffer::create(data->data(),
535 offsetActl);
536 noActlData->append(data->data() + offsetActl + 20,
537 data->size() - offsetActl - 20);
538
539 decoder->setData(noActlData, true);
540 EXPECT_EQ(1u, decoder->frameCount());
541 EXPECT_FALSE(decoder->failed());
542 }
543
544 // Test if the indicated frame count by the acTL is ignored if the actual
545 // number of frames is different. Test for higher and lower indicated number.
546 TEST(AnimatedPNGTests, differentActlFrameCountIsIgnored)
547 {
548 const char* pngFile = "//LayoutTests/fast/images/resources/png-animated-idat -part-of-animation.png";
549 testDifferentActlFrameCountIsIgnored(pngFile, 33u, 2u, 4u);
550 testDifferentActlFrameCountIsIgnored(pngFile, 33u, 8u, 4u);
551 }
552
553 // Check if a frame rectangle, that is larger than the image width, gets
554 // clipped correctly.
555 TEST(AnimatedPNGTests, frameRectIsClipped)
556 {
557 const char* pngFile = "//LayoutTests/fast/images/resources/png-animated-idat -part-of-animation.png";
558 auto data = readFile(pngFile);
559 auto decoder = createDecoder();
560 ASSERT_FALSE(data->isEmpty());
561
562 // Change the width and height of the frame so it falls outside the image.
563 size_t offsetThirdFctl = 241 + 12;
564 RefPtr<SharedBuffer> modifiedData = SharedBuffer::create(data->data(),
565 offsetThirdFctl);
566 png_byte sizeChunk[8];
567 writeUint32(10, sizeChunk);
568 writeUint32(15, sizeChunk + 4);
569 modifiedData->append(const_cast<const char*>(
570 reinterpret_cast<char*>(sizeChunk)), 8u);
571 modifiedData->append(data->data() + offsetThirdFctl + 8,
572 data->size() - offsetThirdFctl - 8);
573
574 decoder->setData(modifiedData, true);
575
576 IntSize expectedSize(5, 5);
577 size_t expectedFrameCount = 4;
578 IntRect expectedFrameRect(IntPoint(1, 2), IntSize(4, 3));
579
580 EXPECT_TRUE(decoder->isSizeAvailable());
581 EXPECT_EQ(expectedSize, decoder->size());
582 EXPECT_EQ(expectedFrameCount, decoder->frameCount());
583 ASSERT_FALSE(decoder->failed());
584 EXPECT_EQ(expectedFrameRect,
585 decoder->frameBufferAtIndex(2)->originalFrameRect());
586 }
587
588 // For explanation of this test, see the definition of
scroggo_chromium 2016/10/28 14:20:33 I think this comment is unnecessary.
joostouwerling 2016/10/28 18:41:25 Done.
scroggo_chromium 2016/10/31 13:35:11 It looks like these comments are still here.
joostouwerling 2016/10/31 18:40:19 Error from my side. Is fixed in patch set 11.
589 // testProgressiveDecodingChangesFrameBuffer
590 TEST(AnimatedPNGTests, ProgressiveDecodingChangesFrameBuffer)
591 {
592 testProgressiveDecodingChangesFrameBuffer(
593 "//LayoutTests/fast/images/resources/png-animated-idat-part-of-animation .png", 249u);
scroggo_chromium 2016/10/28 14:20:33 I just noticed this - these new tests start with "
joostouwerling 2016/10/28 18:41:25 Done.
594 }
595
596 // For explanation of this test, see the definition of
scroggo_chromium 2016/10/28 14:20:32 Again, this comment is unnecessary. If I'm curious
joostouwerling 2016/10/28 18:41:25 Done.
597 // testProgressiveDecodingContinuesAfterFullData
598 TEST(AnimatedPNGTests, ProgressiveDecodingContinuesAfterFullData)
599 {
600 testProgressiveDecodingContinuesAfterFullData(
601 "//LayoutTests/fast/images/resources/png-animated-idat-part-of-animation .png", 160u);
602 }
603
604 // Static PNG tests
605
606 TEST(StaticPNGTests, repetitionCountTest)
607 {
608 testRepetitionCount("/LayoutTests/fast/images/resources/png-simple.png",
609 cAnimationNone);
610 }
611
612 TEST(StaticPNGTests, sizeTest)
613 {
614 testSize("/LayoutTests/fast/images/resources/png-simple.png",
615 IntSize(111, 29));
616 }
617
618 TEST(StaticPNGTests, MetaDataTest)
619 {
620 const size_t expectedFrameCount = 1;
621 const size_t expectedDuration = 0;
622 auto decoder = createDecoderWithPngData("/LayoutTests/fast/images/resources/ png-simple.png");
623 EXPECT_EQ(expectedFrameCount, decoder->frameCount());
624 EXPECT_EQ(expectedDuration, decoder->frameDurationAtIndex(0));
625 }
626
627 // This test removes two random bytes from the IHDR chunk. The decoder should
628 // fail on this since all IHDR data is necessary to decode a PNG image.
629 TEST(StaticPNGTests, InvalidIHDRChunk)
630 {
631 testMissingDataBreaksDecoding(
632 "//LayoutTests/fast/images/resources/png-simple.png", 20u, 2u);
633 }
634
635 TEST(StaticPNGTests, ProgressiveDecoding)
636 {
637 testProgressiveDecoding("/LayoutTests/fast/images/resources/png-simple.png") ;
638 }
639
640 // For explanation of this test, see the definition of
641 // testProgressiveDecodingChangesFrameBuffer
642 TEST(StaticPNGTests, ProgressiveDecodingChangesFrameBuffer)
643 {
644 testProgressiveDecodingChangesFrameBuffer(
645 "/LayoutTests/fast/images/resources/png-simple.png", 0u, 5u);
646 }
647
648 // For explanation of this test, see the definition of
649 // testProgressiveDecodingContinuesAfterFullData
650 TEST(StaticPNGTests, ProgressiveDecodingContinuesAfterFullData)
651 {
652 testProgressiveDecodingContinuesAfterFullData(
653 "/LayoutTests/fast/images/resources/png-simple.png", 1000u);
654 }
655
656 }; // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698