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

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

Issue 2386453003: WIP: Implement APNG (Closed)
Patch Set: Fixed feedback on patch 8 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 // Check that providing the full data after the first frame was partially
253 // decoded properly continues where it left off.
254 void testProgressiveDecodingContinuesAfterFullData(const char* pngFile,
255 size_t offsetMidFirstFrame)
256 {
257 auto fullData = readFile(pngFile);
258 auto decoder = createDecoder();
259 ASSERT_FALSE(fullData->isEmpty());
260
261 RefPtr<SharedBuffer> partialData =
262 SharedBuffer::create(fullData->data(), offsetMidFirstFrame);
263 decoder->setData(partialData, false);
264
265 EXPECT_EQ(1u, decoder->frameCount());
266 ImageFrame* frame = decoder->frameBufferAtIndex(0);
267 EXPECT_EQ(frame->getStatus(), ImageFrame::FramePartial);
268 unsigned hashPartial = hashBitmap(frame->bitmap());
269
270 decoder->setData(fullData, true);
271 frame = decoder->frameBufferAtIndex(0);
272 EXPECT_EQ(frame->getStatus(), ImageFrame::FrameComplete);
273 unsigned hashFull = hashBitmap(frame->bitmap());
274
275 EXPECT_FALSE(decoder->failed());
276 EXPECT_NE(hashFull, hashPartial);
277 }
278
279 // This test verifies that the frame buffer contents change when progressively
280 // decoding the first frame. It should change more than 1 time: once for the
281 // first data, and at least once more thereafter. If |offsetFirstFrameEnd| == 0,
282 // the test uses the full data size of the image for its value.
283 void testProgressiveDecodingChangesFrameBuffer(const char* pngFile,
284 size_t offsetFirstFrameEnd,
285 size_t step = 1u)
286 {
287 auto fullData = readFile(pngFile);
288 auto decoder = createDecoder();
289 ASSERT_FALSE(fullData->isEmpty());
290
291 if (offsetFirstFrameEnd == 0)
292 offsetFirstFrameEnd = fullData->size();
293
294 size_t numTimesBufferChanged = 0;
295 unsigned lastHash;
296
297 for (size_t length = 1; length <= offsetFirstFrameEnd; length += step) {
298 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(),
299 length);
300 decoder->setData(data, false);
301 ImageFrame* frame = decoder->frameBufferAtIndex(0);
302 if (!frame)
303 continue;
304 unsigned newHash = hashBitmap(frame->bitmap());
305 if (newHash != lastHash) {
306 lastHash = newHash;
307 numTimesBufferChanged++;
308 }
309 }
310 EXPECT_GT(numTimesBufferChanged, 1u);
311 }
312
313 } // Anonymous namespace
314
315 // Animated PNG Tests
316
317 TEST(AnimatedPNGTests, sizeTest)
318 {
319 testSize("/LayoutTests/fast/images/resources/png-animated-idat-part-of-anima tion.png", IntSize(5, 5));
320 testSize("/LayoutTests/fast/images/resources/png-animated-idat-not-part-of-a nimation.png", IntSize(227, 35));
321 }
322
323 TEST(AnimatedPNGTests, repetitionCountTest)
324 {
325 testRepetitionCount("/LayoutTests/fast/images/resources/png-animated-idat-pa rt-of-animation.png", 7u);
326 // This is an "animated" image with only one frame, that is, the IDAT is
327 // ignored and there is one fdAT frame. so it should be considered
328 // non-animated.
329 testRepetitionCount("/LayoutTests/fast/images/resources/png-animated-idat-no t-part-of-animation.png", cAnimationNone);
330 }
331
332 // Test if the decoded metdata corresponds to the defined expectations
333 TEST(AnimatedPNGTests, MetaDataTest)
334 {
335 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
336 constexpr size_t expectedFrameCount = 4;
337
338 auto decoder = createDecoderWithPngData(pngFile);
339 ASSERT_EQ(expectedFrameCount, decoder->frameCount());
340 for (size_t i = 0; i < expectedFrameCount; i++)
341 compareFrameWithExpectation(pngAnimatedFrameInfo[i],
342 decoder->frameBufferAtIndex(i));
343 }
344
345 TEST(AnimatedPNGTests, ByteByByteSizeAvailable)
346 {
347 testSizeByteByByte("/LayoutTests/fast/images/resources/png-animated-idat-par t-of-animation.png",
348 141u, IntSize(5, 5));
349 testSizeByteByByte("/LayoutTests/fast/images/resources/png-animated-idat-not -part-of-animation.png",
350 79u, IntSize(227, 35));
351 }
352
353 // Test whether the frame metadata decoding also works when we provide the data
354 // byte by byte. This should cover the case when the client does not provide
355 // all data at once. At given offsets, we expect frames to become available.
356 // This test checks whether that is the case, and if so, if the frame data is
357 // equal to what we expected.
358 TEST(AnimatedPNGTests, ByteByByteMetaData)
359 {
360 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
361 constexpr size_t expectedFrameCount = 4;
362
363 // These are the byte offsets where each frame should have been parsed.
364 // It boils down to the offset of the first fcTL / IEND after the last
365 // frame data chunk, plus 8 bytes for recognition. The exception on this is
366 // the first frame, which is reported when its first framedata is seen.
367 size_t frameOffsets[expectedFrameCount] = {141, 249, 322, 430};
368
369 auto decoder = createDecoder();
370 auto data = readFile(pngFile);
371 ASSERT_FALSE(data->isEmpty());
372 size_t framesParsed = 0;
373
374 for (size_t length = 1; length <= frameOffsets[expectedFrameCount - 1]; leng th++) {
375 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(),
376 length);
377 decoder->setData(tempData.get(), false);
378 EXPECT_FALSE(decoder->failed());
379 if (length < frameOffsets[framesParsed]) {
380 EXPECT_EQ(framesParsed, decoder->frameCount());
381 } else {
382 ASSERT_EQ(framesParsed + 1, decoder->frameCount());
383 compareFrameWithExpectation(pngAnimatedFrameInfo[framesParsed],
384 decoder->frameBufferAtIndex(framesParsed ));
385 framesParsed++;
386 }
387 }
388 EXPECT_EQ(expectedFrameCount, decoder->frameCount());
389 EXPECT_FALSE(decoder->failed());
390 }
391
392 // This tests if the frame count gets set correctly when parsing frameCount
393 // fails in one of the parsing queries.
394 //
395 // First, enough data is provided such that two frames should be registered.
396 // The decoder should at this point not be in the failed status.
397 //
398 // Then, we provide the rest of the data except for the last IEND chunk, but
399 // tell the decoder that this is all the data we have. Now, the decoder should
400 // be in the failed state since all data is provided but no IEND chunk has been
401 // seen. The frame count should be three, since one extra frame should be
402 // discovered. The fourth frame should *not* be registered since the reader
403 // should not be able to determine where the frame ends.
404 TEST(AnimatedPNGTests, FrameCountWithTruncatedData)
405 {
406 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
407 auto decoder = createDecoder();
408 auto data = readFile(pngFile);
409 ASSERT_FALSE(data->isEmpty());
410
411 // Parse up to and including the first two frames
412 const size_t offsetTwoFrames = 249;
413 const size_t expectedFramesAfter249Bytes = 2;
414 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(),
415 offsetTwoFrames);
416 decoder->setData(tempData.get(), false);
417 EXPECT_EQ(expectedFramesAfter249Bytes, decoder->frameCount());
418 EXPECT_FALSE(decoder->failed());
419
420 // Provide the rest of the data except for the last IEND chunk.
421 const size_t expectedFramesAfterAllExpect12Bytes = 3;
422 tempData = SharedBuffer::create(data->data(), data->size() - 12);
423 decoder->setData(tempData.get(), true);
424 EXPECT_EQ(expectedFramesAfterAllExpect12Bytes, decoder->frameCount());
425 EXPECT_TRUE(decoder->failed());
426 }
427
428 TEST(AnimatedPNGTests, TestRandomFrameDecode)
429 {
430 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /png-animated-idat-part-of-animation.png");
431 ASSERT_TRUE(fullData.get());
432 Vector<unsigned> baselineHashes;
433 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes);
434 size_t frameCount = baselineHashes.size();
435
436 // Random decoding should get the same results as sequential decoding.
437 std::unique_ptr<ImageDecoder> decoder = createDecoder();
438 decoder->setData(fullData.get(), true);
439 const size_t skippingStep = 2;
440 for (size_t i = 0; i < skippingStep; ++i) {
441 for (size_t j = i; j < frameCount; j += skippingStep) {
442 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
443 ImageFrame* frame = decoder->frameBufferAtIndex(j);
444 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->bitmap()));
445 }
446 }
447
448 // Decoding in reverse order.
449 decoder = createDecoder();
450 decoder->setData(fullData.get(), true);
451 for (size_t i = frameCount; i; --i) {
452 SCOPED_TRACE(testing::Message() << "Reverse i:" << i);
453 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1);
454 EXPECT_EQ(baselineHashes[i - 1], hashBitmap(frame->bitmap()));
455 }
456
457 }
458
459 TEST(AnimatedPNGTests, TestDecodeAfterReallocation)
460 {
461 std::unique_ptr<ImageDecoder> decoder = createDecoder();
462 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/png -animated-idat-part-of-animation.png");
463 ASSERT_TRUE(data.get());
464
465 // Parse from |data|.
466 decoder->setData(data.get(), true);
467 size_t frameCount = decoder->frameCount();
468
469 // ... and then decode frames from |reallocatedData|.
470 RefPtr<SharedBuffer> reallocatedData = data.get()->copy();
471 ASSERT_TRUE(reallocatedData.get());
472 data.clear();
473 decoder->setData(reallocatedData.get(), true);
474
475 for (size_t i = 0; i < frameCount; ++i) {
476 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
477 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus());
478 }
479 }
480
481 TEST(AnimatedPNGTests, ProgressiveDecode)
482 {
483 testProgressiveDecoding("/LayoutTests/fast/images/resources/png-animated-ida t-part-of-animation.png");
484 }
485
486 TEST(AnimatedPNGTests, ParseAndDecodeByteByByte)
487 {
488 testByteByByteDecode(&createDecoder,
489 "/LayoutTests/fast/images/resources/png-animated-idat-p art-of-animation.png",
490 4u, 7u);
491 }
492
493 TEST(AnimatedPNGTests, FctlWrongSizeBreaksDecoding)
494 {
495 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
496 auto data = readFile(pngFile);
497 ASSERT_FALSE(data->isEmpty());
498
499 // Test the first fcTL in the stream. Because no frame data has been set
500 // at this point, the expected frame count is zero.
501 testInvalidFctlSize("/LayoutTests/fast/images/resources/png-animated-idat-pa rt-of-animation.png",
502 95u, 0u);
503
504 // Test for the third fcTL in the stream. This should be tested as well,
505 // since the first fcTL is parsed in PNGImageReader::parseSize() whereas
506 // later fcTLs are parsed in PNGImageReader::parse() as part of framecount.
507 // The expected frame count before the fcTL chunk is 1u, since the second
508 // frame is registered when the third fcTL (or IEND) is seen.
509 testInvalidFctlSize("/LayoutTests/fast/images/resources/png-animated-idat-pa rt-of-animation.png",
510 241u, 1u);
511
512 }
513
514 TEST(AnimatedPNGTests, MissingFctlDataBreaksDecoding)
515 {
516 // The fcTL chunk starts at 95u, add 10u to get to the content data, and
517 // remove 5 bytes of data.
518 testMissingDataBreaksDecoding(
519 "/LayoutTests/fast/images/resources/png-animated-idat-part-of-animation. png",
520 105u, 5u);
521 }
522
523 TEST(AnimatedPNGTests, MissingActlResultsInNonAnimated)
524 {
525 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
526 auto data = readFile(pngFile);
527 auto decoder = createDecoder();
528 ASSERT_FALSE(data->isEmpty());
529
530 // Remove the acTL chunk from the stream.
531 size_t offsetActl = 33;
532 RefPtr<SharedBuffer> noActlData = SharedBuffer::create(data->data(),
533 offsetActl);
534 noActlData->append(data->data() + offsetActl + 20,
535 data->size() - offsetActl - 20);
536
537 decoder->setData(noActlData, true);
538 EXPECT_EQ(1u, decoder->frameCount());
539 EXPECT_FALSE(decoder->failed());
540 }
541
542 // Test if the indicated frame count by the acTL is ignored if the actual
543 // number of frames is different. Test for higher and lower indicated number.
544 TEST(AnimatedPNGTests, differentActlFrameCountIsIgnored)
545 {
546 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png";
547 testDifferentActlFrameCountIsIgnored(pngFile, 33u, 2u, 4u);
548 testDifferentActlFrameCountIsIgnored(pngFile, 33u, 8u, 4u);
549 }
550
551 // Check if a frame rectangle, that is larger than the image width, gets
552 // clipped correctly.
553 // @TODO(joostouwerling) use an image that also has data that needs to be
554 // clippedi, not just report larger dimensions.
scroggo_chromium 2016/10/31 13:35:12 clipped*
joostouwerling 2016/10/31 18:40:19 Done.
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
589 // testProgressiveDecodingChangesFrameBuffer
590 TEST(AnimatedPNGTests, ProgressiveDecodingChangesFrameBuffer)
591 {
592 testProgressiveDecodingChangesFrameBuffer(
593 "/LayoutTests/fast/images/resources/png-animated-idat-part-of-animation. png", 249u);
594 }
595
596 // For explanation of this test, see the definition of
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 TEST(StaticPNGTests, InvalidIHDRChunk)
628 {
629 testMissingDataBreaksDecoding(
630 "/LayoutTests/fast/images/resources/png-simple.png", 20u, 2u);
631 }
632
633 TEST(StaticPNGTests, ProgressiveDecoding)
634 {
635 testProgressiveDecoding("/LayoutTests/fast/images/resources/png-simple.png") ;
636 }
637
638 TEST(StaticPNGTests, ProgressiveDecodingChangesFrameBuffer)
639 {
640 testProgressiveDecodingChangesFrameBuffer(
641 "/LayoutTests/fast/images/resources/png-simple.png", 0u, 5u);
642 }
643
644 TEST(StaticPNGTests, ProgressiveDecodingContinuesAfterFullData)
645 {
646 testProgressiveDecodingContinuesAfterFullData(
647 "/LayoutTests/fast/images/resources/png-simple.png", 1000u);
648 }
649
650 }; // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698