Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 71 } else { | 71 } else { |
| 72 EXPECT_GT(decoder->frameCount(), 0u); | 72 EXPECT_GT(decoder->frameCount(), 0u); |
| 73 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 73 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
| 74 ASSERT_TRUE(frame); | 74 ASSERT_TRUE(frame); |
| 75 EXPECT_EQ(ImageFrame::FramePartial, frame->getStatus()); | 75 EXPECT_EQ(ImageFrame::FramePartial, frame->getStatus()); |
| 76 } | 76 } |
| 77 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); | 77 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); |
| 78 EXPECT_TRUE(decoder->failed()); | 78 EXPECT_TRUE(decoder->failed()); |
| 79 } | 79 } |
| 80 | 80 |
| 81 uint32_t premultiplyColor(uint32_t c) { | |
| 82 return SkPremultiplyARGBInline(SkGetPackedA32(c), SkGetPackedR32(c), | |
| 83 SkGetPackedG32(c), SkGetPackedB32(c)); | |
| 84 } | |
| 85 | |
| 86 void verifyFramesMatch(const char* webpFile, | |
| 87 const ImageFrame* const a, | |
| 88 ImageFrame* const b) { | |
| 89 const SkBitmap& bitmapA = a->bitmap(); | |
| 90 const SkBitmap& bitmapB = b->bitmap(); | |
| 91 ASSERT_EQ(bitmapA.width(), bitmapB.width()); | |
| 92 ASSERT_EQ(bitmapA.height(), bitmapB.height()); | |
| 93 | |
| 94 int maxDifference = 0; | |
| 95 for (int y = 0; y < bitmapA.height(); ++y) { | |
| 96 for (int x = 0; x < bitmapA.width(); ++x) { | |
| 97 uint32_t colorA = *bitmapA.getAddr32(x, y); | |
| 98 if (!a->premultiplyAlpha()) | |
| 99 colorA = premultiplyColor(colorA); | |
| 100 uint32_t colorB = *bitmapB.getAddr32(x, y); | |
| 101 if (!b->premultiplyAlpha()) | |
| 102 colorB = premultiplyColor(colorB); | |
| 103 uint8_t* pixelA = reinterpret_cast<uint8_t*>(&colorA); | |
| 104 uint8_t* pixelB = reinterpret_cast<uint8_t*>(&colorB); | |
| 105 for (int channel = 0; channel < 4; ++channel) { | |
| 106 const int difference = abs(pixelA[channel] - pixelB[channel]); | |
| 107 if (difference > maxDifference) | |
| 108 maxDifference = difference; | |
| 109 } | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 // Pre-multiplication could round the RGBA channel values. So, we declare | |
| 114 // that the frames match if the RGBA channel values differ by at most 2. | |
| 115 EXPECT_GE(2, maxDifference) << webpFile; | |
| 116 } | |
| 117 | |
| 118 // Verifies that result of alpha blending is similar for AlphaPremultiplied and | |
| 119 // AlphaNotPremultiplied cases. | |
| 120 void testAlphaBlending(const char* webpFile) { | |
| 121 RefPtr<SharedBuffer> data = readFile(webpFile); | |
| 122 ASSERT_TRUE(data.get()); | |
| 123 | |
| 124 std::unique_ptr<ImageDecoder> decoderA = | |
| 125 createDecoder(ImageDecoder::AlphaPremultiplied); | |
| 126 decoderA->setData(data.get(), true); | |
| 127 | |
| 128 std::unique_ptr<ImageDecoder> decoderB = | |
| 129 createDecoder(ImageDecoder::AlphaNotPremultiplied); | |
| 130 decoderB->setData(data.get(), true); | |
| 131 | |
| 132 size_t frameCount = decoderA->frameCount(); | |
| 133 ASSERT_EQ(frameCount, decoderB->frameCount()); | |
| 134 | |
| 135 for (size_t i = 0; i < frameCount; ++i) | |
| 136 verifyFramesMatch(webpFile, decoderA->frameBufferAtIndex(i), | |
| 137 decoderB->frameBufferAtIndex(i)); | |
| 138 } | |
| 139 | |
| 140 } // anonymous namespace | 81 } // anonymous namespace |
| 141 | 82 |
| 142 TEST(AnimatedWebPTests, uniqueGenerationIDs) { | 83 TEST(AnimatedWebPTests, uniqueGenerationIDs) { |
| 143 std::unique_ptr<ImageDecoder> decoder = createDecoder(); | 84 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
| 144 | 85 |
| 145 RefPtr<SharedBuffer> data = | 86 RefPtr<SharedBuffer> data = |
| 146 readFile("/LayoutTests/images/resources/webp-animated.webp"); | 87 readFile("/LayoutTests/images/resources/webp-animated.webp"); |
| 147 ASSERT_TRUE(data.get()); | 88 ASSERT_TRUE(data.get()); |
| 148 decoder->setData(data.get(), true); | 89 decoder->setData(data.get(), true); |
| 149 | 90 |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 EXPECT_EQ(3u, decoder->frameCount()); | 358 EXPECT_EQ(3u, decoder->frameCount()); |
| 418 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); | 359 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); |
| 419 EXPECT_EQ(1000, decoder->frameDurationAtIndex(0)); | 360 EXPECT_EQ(1000, decoder->frameDurationAtIndex(0)); |
| 420 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1)); | 361 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1)); |
| 421 EXPECT_EQ(500, decoder->frameDurationAtIndex(1)); | 362 EXPECT_EQ(500, decoder->frameDurationAtIndex(1)); |
| 422 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(2)); | 363 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(2)); |
| 423 EXPECT_EQ(1000.0, decoder->frameDurationAtIndex(2)); | 364 EXPECT_EQ(1000.0, decoder->frameDurationAtIndex(2)); |
| 424 } | 365 } |
| 425 | 366 |
| 426 TEST(AnimatedWebPTests, updateRequiredPreviousFrameAfterFirstDecode) { | 367 TEST(AnimatedWebPTests, updateRequiredPreviousFrameAfterFirstDecode) { |
| 427 std::unique_ptr<ImageDecoder> decoder = createDecoder(); | 368 testUpdateRequiredPreviousFrameAfterFirstDecode( |
| 428 | 369 &createDecoder, "/LayoutTests/images/resources/webp-animated.webp"); |
| 429 RefPtr<SharedBuffer> fullData = | |
| 430 readFile("/LayoutTests/images/resources/webp-animated.webp"); | |
| 431 ASSERT_TRUE(fullData.get()); | |
| 432 | |
| 433 // Check the status of requiredPreviousFrameIndex before decoding, by | |
| 434 // supplying data sufficient to parse but not decode. | |
| 435 size_t partialSize = 1; | |
| 436 do { | |
| 437 RefPtr<SharedBuffer> data = | |
| 438 SharedBuffer::create(fullData->data(), partialSize); | |
| 439 decoder->setData(data.get(), false); | |
| 440 ++partialSize; | |
| 441 } while (!decoder->frameCount() || | |
| 442 decoder->frameBufferAtIndex(0)->getStatus() == | |
| 443 ImageFrame::FrameEmpty); | |
| 444 | |
| 445 EXPECT_EQ(kNotFound, | |
| 446 decoder->frameBufferAtIndex(0)->requiredPreviousFrameIndex()); | |
| 447 size_t frameCount = decoder->frameCount(); | |
| 448 for (size_t i = 1; i < frameCount; ++i) | |
| 449 EXPECT_EQ(i - 1, | |
| 450 decoder->frameBufferAtIndex(i)->requiredPreviousFrameIndex()); | |
| 451 | |
| 452 decoder->setData(fullData.get(), true); | |
| 453 for (size_t i = 0; i < frameCount; ++i) | |
| 454 EXPECT_EQ(kNotFound, | |
| 455 decoder->frameBufferAtIndex(i)->requiredPreviousFrameIndex()); | |
| 456 } | 370 } |
| 457 | 371 |
| 458 TEST(AnimatedWebPTests, randomFrameDecode) { | 372 TEST(AnimatedWebPTests, randomFrameDecode) { |
| 459 testRandomFrameDecode(&createDecoder, | 373 testRandomFrameDecode(&createDecoder, |
| 460 "/LayoutTests/images/resources/webp-animated.webp"); | 374 "/LayoutTests/images/resources/webp-animated.webp"); |
| 461 testRandomFrameDecode( | 375 testRandomFrameDecode( |
| 462 &createDecoder, | 376 &createDecoder, |
| 463 "/LayoutTests/images/resources/webp-animated-opaque.webp"); | 377 "/LayoutTests/images/resources/webp-animated-opaque.webp"); |
| 464 testRandomFrameDecode( | 378 testRandomFrameDecode( |
| 465 &createDecoder, "/LayoutTests/images/resources/webp-animated-large.webp"); | 379 &createDecoder, "/LayoutTests/images/resources/webp-animated-large.webp"); |
| 466 testRandomFrameDecode( | 380 testRandomFrameDecode( |
| 467 &createDecoder, | 381 &createDecoder, |
| 468 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp"); | 382 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp"); |
| 469 } | 383 } |
| 470 | 384 |
| 471 TEST(AnimatedWebPTests, randomDecodeAfterClearFrameBufferCache) { | 385 TEST(AnimatedWebPTests, randomDecodeAfterClearFrameBufferCache) { |
| 472 testRandomDecodeAfterClearFrameBufferCache( | 386 testRandomDecodeAfterClearFrameBufferCache( |
| 473 &createDecoder, "/LayoutTests/images/resources/webp-animated.webp"); | 387 &createDecoder, "/LayoutTests/images/resources/webp-animated.webp"); |
| 474 testRandomDecodeAfterClearFrameBufferCache( | 388 testRandomDecodeAfterClearFrameBufferCache( |
| 475 &createDecoder, | 389 &createDecoder, |
| 476 "/LayoutTests/images/resources/webp-animated-opaque.webp"); | 390 "/LayoutTests/images/resources/webp-animated-opaque.webp"); |
| 477 testRandomDecodeAfterClearFrameBufferCache( | 391 testRandomDecodeAfterClearFrameBufferCache( |
| 478 &createDecoder, "/LayoutTests/images/resources/webp-animated-large.webp"); | 392 &createDecoder, "/LayoutTests/images/resources/webp-animated-large.webp"); |
| 479 testRandomDecodeAfterClearFrameBufferCache( | 393 testRandomDecodeAfterClearFrameBufferCache( |
| 480 &createDecoder, | 394 &createDecoder, |
| 481 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp"); | 395 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp"); |
| 482 } | 396 } |
| 483 | 397 |
| 398 // This test is disabled since it timed out on the Windows bot. See | |
| 399 // crrev.com/962853004 | |
| 484 TEST(AnimatedWebPTests, | 400 TEST(AnimatedWebPTests, |
| 485 DISABLED_resumePartialDecodeAfterClearFrameBufferCache) { | 401 DISABLED_resumePartialDecodeAfterClearFrameBufferCache) { |
|
urvang
2016/11/21 20:16:15
Unrelated to this patch, but can you later check i
| |
| 486 RefPtr<SharedBuffer> fullData = | 402 testResumePartialDecodeAfterClearFrameBufferCache( |
| 487 readFile("/LayoutTests/images/resources/webp-animated-large.webp"); | 403 &createDecoder, "/LayoutTests/images/resources/webp-animated-large.webp"); |
| 488 ASSERT_TRUE(fullData.get()); | |
| 489 Vector<unsigned> baselineHashes; | |
| 490 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes); | |
| 491 size_t frameCount = baselineHashes.size(); | |
| 492 | |
| 493 std::unique_ptr<ImageDecoder> decoder = createDecoder(); | |
| 494 | |
| 495 // Let frame 0 be partially decoded. | |
| 496 size_t partialSize = 1; | |
| 497 do { | |
| 498 RefPtr<SharedBuffer> data = | |
| 499 SharedBuffer::create(fullData->data(), partialSize); | |
| 500 decoder->setData(data.get(), false); | |
| 501 ++partialSize; | |
| 502 } while (!decoder->frameCount() || | |
| 503 decoder->frameBufferAtIndex(0)->getStatus() == | |
| 504 ImageFrame::FrameEmpty); | |
| 505 | |
| 506 // Skip to the last frame and clear. | |
| 507 decoder->setData(fullData.get(), true); | |
| 508 EXPECT_EQ(frameCount, decoder->frameCount()); | |
| 509 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1); | |
| 510 EXPECT_EQ(baselineHashes[frameCount - 1], hashBitmap(lastFrame->bitmap())); | |
| 511 decoder->clearCacheExceptFrame(kNotFound); | |
| 512 | |
| 513 // Resume decoding of the first frame. | |
| 514 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0); | |
| 515 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->getStatus()); | |
| 516 EXPECT_EQ(baselineHashes[0], hashBitmap(firstFrame->bitmap())); | |
| 517 } | 404 } |
| 518 | 405 |
| 519 TEST(AnimatedWebPTests, decodeAfterReallocatingData) { | 406 TEST(AnimatedWebPTests, decodeAfterReallocatingData) { |
| 520 testDecodeAfterReallocatingData( | 407 testDecodeAfterReallocatingData( |
| 521 &createDecoder, "/LayoutTests/images/resources/webp-animated.webp"); | 408 &createDecoder, "/LayoutTests/images/resources/webp-animated.webp"); |
| 522 testDecodeAfterReallocatingData( | 409 testDecodeAfterReallocatingData( |
| 523 &createDecoder, | 410 &createDecoder, |
| 524 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp"); | 411 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp"); |
| 525 } | 412 } |
| 526 | 413 |
| 527 TEST(AnimatedWebPTests, alphaBlending) { | 414 TEST(AnimatedWebPTests, alphaBlending) { |
| 528 testAlphaBlending("/LayoutTests/images/resources/webp-animated.webp"); | 415 testAlphaBlending(&createDecoder, |
| 416 "/LayoutTests/images/resources/webp-animated.webp"); | |
| 529 testAlphaBlending( | 417 testAlphaBlending( |
| 418 &createDecoder, | |
| 530 "/LayoutTests/images/resources/webp-animated-semitransparent1.webp"); | 419 "/LayoutTests/images/resources/webp-animated-semitransparent1.webp"); |
| 531 testAlphaBlending( | 420 testAlphaBlending( |
| 421 &createDecoder, | |
| 532 "/LayoutTests/images/resources/webp-animated-semitransparent2.webp"); | 422 "/LayoutTests/images/resources/webp-animated-semitransparent2.webp"); |
| 533 testAlphaBlending( | 423 testAlphaBlending( |
| 424 &createDecoder, | |
| 534 "/LayoutTests/images/resources/webp-animated-semitransparent3.webp"); | 425 "/LayoutTests/images/resources/webp-animated-semitransparent3.webp"); |
| 535 testAlphaBlending( | 426 testAlphaBlending( |
| 427 &createDecoder, | |
| 536 "/LayoutTests/images/resources/webp-animated-semitransparent4.webp"); | 428 "/LayoutTests/images/resources/webp-animated-semitransparent4.webp"); |
| 537 } | 429 } |
| 538 | 430 |
| 539 TEST(AnimatedWebPTests, isSizeAvailable) { | 431 TEST(AnimatedWebPTests, isSizeAvailable) { |
| 540 testByteByByteSizeAvailable( | 432 testByteByByteSizeAvailable( |
| 541 &createDecoder, "/LayoutTests/images/resources/webp-animated.webp", 142u, | 433 &createDecoder, "/LayoutTests/images/resources/webp-animated.webp", 142u, |
| 542 false, cAnimationLoopInfinite); | 434 false, cAnimationLoopInfinite); |
| 543 // FIXME: Add color profile support for animated webp images. | 435 // FIXME: Add color profile support for animated webp images. |
| 544 testByteByByteSizeAvailable( | 436 testByteByByteSizeAvailable( |
| 545 &createDecoder, | 437 &createDecoder, |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 651 std::unique_ptr<ImageDecoder> decoder = createDecoder(); | 543 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
| 652 RefPtr<SharedBuffer> data = | 544 RefPtr<SharedBuffer> data = |
| 653 readFile("/LayoutTests/images/resources/webp-color-profile-lossy.webp"); | 545 readFile("/LayoutTests/images/resources/webp-color-profile-lossy.webp"); |
| 654 ASSERT_TRUE(data.get()); | 546 ASSERT_TRUE(data.get()); |
| 655 decoder->setData(data.get(), true); | 547 decoder->setData(data.get(), true); |
| 656 EXPECT_EQ(1u, decoder->frameCount()); | 548 EXPECT_EQ(1u, decoder->frameCount()); |
| 657 EXPECT_EQ(cAnimationNone, decoder->repetitionCount()); | 549 EXPECT_EQ(cAnimationNone, decoder->repetitionCount()); |
| 658 } | 550 } |
| 659 | 551 |
| 660 } // namespace blink | 552 } // namespace blink |
| OLD | NEW |