Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 "platform/image-decoders/ImageDecoderTestHelpers.h" | |
| 8 #include "testing/gtest/include/gtest/gtest.h" | |
| 9 #include <memory> | |
| 10 | |
| 11 namespace blink { | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 std::unique_ptr<ImageDecoder> createDecoder(ImageDecoder::AlphaOption alphaOptio n) | |
| 16 { | |
| 17 return wrapUnique(new PNGImageDecoder(alphaOption, | |
| 18 ImageDecoder::GammaAndColorProfileAppl ied, | |
| 19 ImageDecoder::noDecodedImageByteLimit) ); | |
| 20 } | |
| 21 | |
| 22 std::unique_ptr<ImageDecoder> createDecoder() | |
| 23 { | |
| 24 return createDecoder(ImageDecoder::AlphaNotPremultiplied); | |
| 25 } | |
| 26 | |
| 27 std::unique_ptr<ImageDecoder> createDecoderWithPngData(const char* pngFile) | |
| 28 { | |
| 29 auto decoder = createDecoder(); | |
| 30 auto data = readFile(pngFile); | |
| 31 EXPECT_EQ(false, data->isEmpty()); | |
|
scroggo_chromium
2016/10/11 20:13:10
This can be EXPECT_FALSE(data->isEmpty())
Or mayb
| |
| 32 decoder->setData(data.get(), true); | |
| 33 return decoder; | |
| 34 } | |
| 35 | |
| 36 void testSize(const char* pngFile, IntSize expectedSize) | |
| 37 { | |
| 38 auto decoder = createDecoderWithPngData(pngFile); | |
| 39 EXPECT_EQ(true, decoder->isSizeAvailable()); | |
| 40 EXPECT_EQ(expectedSize, decoder->size()); | |
| 41 } | |
| 42 | |
| 43 void testRepetitionCount(const char* pngFile, int expectedRepetitionCount) | |
| 44 { | |
| 45 auto decoder = createDecoderWithPngData(pngFile); | |
| 46 // Decode frame count should see the number of repetitions as well. | |
| 47 decoder->frameCount(); | |
| 48 EXPECT_EQ(false, decoder->failed()); | |
| 49 EXPECT_EQ(expectedRepetitionCount, decoder->repetitionCount()); | |
| 50 } | |
| 51 | |
| 52 /* | |
| 53 * Test whether the querying for the size of the image works if we present the | |
|
scroggo_chromium
2016/10/11 20:13:10
nit: "Test whether querying..." ("the" is not need
| |
| 54 * data byte by byte. | |
| 55 */ | |
| 56 void testSizeByteByByte(const char *pngFile, size_t frameOffset, IntSize expecte dSize) | |
|
scroggo_chromium
2016/10/11 20:13:09
Why is this variable named "frameOffset"? I think
joostouwerling
2016/10/12 20:49:46
I understand the confusion and will change the nam
| |
| 57 { | |
| 58 auto decoder = createDecoder(); | |
| 59 auto data = readFile(pngFile); | |
| 60 EXPECT_EQ(false, data->isEmpty()); | |
|
scroggo_chromium
2016/10/11 20:13:10
This should probably be ASSERT_FALSE
| |
| 61 EXPECT_LT(frameOffset, data->size()); | |
| 62 | |
| 63 for (size_t length = 1; length <= frameOffset; length++) { | |
| 64 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h); | |
| 65 decoder->setData(tempData.get(), false); | |
| 66 | |
| 67 if (length < frameOffset) { | |
| 68 EXPECT_FALSE(decoder->isSizeAvailable()); | |
| 69 EXPECT_TRUE(decoder->size().isEmpty()); | |
| 70 EXPECT_FALSE(decoder->failed()); | |
| 71 } else { | |
| 72 EXPECT_TRUE(decoder->isSizeAvailable()); | |
| 73 EXPECT_EQ(expectedSize, decoder->size()); | |
| 74 } | |
| 75 } | |
| 76 EXPECT_FALSE(decoder->failed()); | |
| 77 } | |
| 78 | |
| 79 struct FrameInfo { | |
|
scroggo_chromium
2016/10/11 20:13:10
I find this confusing. I guess this is just the pu
joostouwerling
2016/10/12 20:49:46
Yes. I can rephrase it so that becomes clearer. I
| |
| 80 size_t duration; | |
| 81 IntPoint offset; | |
| 82 IntSize size; | |
| 83 ImageFrame::AlphaBlendSource alphaBlend; | |
| 84 ImageFrame::DisposalMethod disposalMethod; | |
| 85 }; | |
| 86 | |
| 87 /* | |
| 88 * This is the frame data for the following PNG image: | |
| 89 * /LayoutTests/fast/images/resources/png-animated-idat-part-of-animation.png | |
| 90 */ | |
| 91 static FrameInfo pngAnimatedFrameInfo[] = { | |
| 92 {75, IntPoint(0, 0), IntSize(100, 100), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 93 {75, IntPoint(31, 36), IntSize(38, 63), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 94 {75, IntPoint(31, 41), IntSize(38, 55), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 95 {75, IntPoint(31, 34), IntSize(38, 65), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 96 {75, IntPoint(31, 23), IntSize(38, 76), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 97 {75, IntPoint(31, 18), IntSize(38, 81), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 98 {75, IntPoint(31, 17), IntSize(38, 82), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 99 {75, IntPoint(31, 14), IntSize(38, 85), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 100 {75, IntPoint(31, 8), IntSize(38, 91), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 101 {75, IntPoint(31, 3), IntSize(38, 96), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 102 {75, IntPoint(31, 3), IntSize(38, 36), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 103 {75, IntPoint(31, 3), IntSize(38, 35), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 104 {75, IntPoint(31, 3), IntSize(38, 36), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep}, | |
| 105 {75, IntPoint(31, 3), IntSize(38, 96), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 106 {75, IntPoint(31, 5), IntSize(38, 94), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 107 {75, IntPoint(31, 8), IntSize(38, 91), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 108 {75, IntPoint(31, 11), IntSize(38, 88), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 109 {75, IntPoint(31, 15), IntSize(38, 84), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 110 {75, IntPoint(31, 20), IntSize(38, 79), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeOverwriteBgcolor}, | |
| 111 {75, IntPoint(31, 25), IntSize(38, 74), ImageFrame::BlendAtopBgcolor, Imag eFrame::DisposeKeep} | |
| 112 }; | |
| 113 | |
| 114 void compareFrameWithExpectation(FrameInfo& expected, ImageFrame* frame) | |
|
scroggo_chromium
2016/10/11 20:13:10
I think both of these parameters can be marked con
| |
| 115 { | |
| 116 EXPECT_EQ(expected.duration, frame->duration()); | |
| 117 EXPECT_EQ(expected.offset, frame->originalFrameRect().location()); | |
|
scroggo_chromium
2016/10/11 20:13:10
If you combine offset and size into an IntRect, I
| |
| 118 EXPECT_EQ(expected.size, frame->originalFrameRect().size()); | |
| 119 EXPECT_EQ(expected.disposalMethod, frame->getDisposalMethod()); | |
| 120 EXPECT_EQ(expected.alphaBlend, frame->getAlphaBlendSource()); | |
| 121 } | |
| 122 | |
| 123 } // Anonymous namespace | |
| 124 | |
| 125 // Animated PNG Tests | |
| 126 | |
| 127 TEST(AnimatedPNGTests, sizeTest) | |
| 128 { | |
| 129 testSize("/LayoutTests/fast/images/resources/png-animated-idat-part-of-anima tion.png", IntSize(100, 100)); | |
| 130 testSize("/LayoutTests/fast/images/resources/png-animated-idat-not-part-of-a nimation.png", IntSize(227, 35)); | |
| 131 } | |
| 132 | |
| 133 // TODO(joostouwerling): make animated PNG's with a non-infinite rep count. | |
| 134 TEST(AnimatedPNGTests, repetitionCountTest) | |
| 135 { | |
| 136 testRepetitionCount("/LayoutTests/fast/images/resources/png-animated-idat-pa rt-of-animation.png", cAnimationLoopInfinite); | |
| 137 testRepetitionCount("/LayoutTests/fast/images/resources/png-animated-idat-no t-part-of-animation.png", cAnimationLoopInfinite); | |
| 138 } | |
| 139 | |
| 140 // Test if the decoded metdata corresponds to the defined expectations | |
| 141 TEST(AnimatedPNGTests, MetaDataTest) | |
| 142 { | |
| 143 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png"; | |
| 144 constexpr size_t expectedFrameCount = 20; | |
| 145 | |
| 146 auto decoder = createDecoderWithPngData(pngFile); | |
| 147 EXPECT_EQ(expectedFrameCount, decoder->frameCount()); | |
|
scroggo_chromium
2016/10/11 20:13:10
This should probably be ASSERT_EQ. If frameCount()
| |
| 148 for (size_t i = 0; i < expectedFrameCount; i++) | |
| 149 compareFrameWithExpectation(pngAnimatedFrameInfo[i], | |
| 150 decoder->frameBufferAtIndex(i)); | |
| 151 } | |
| 152 | |
| 153 TEST(AnimatedPNGTests, ByteByByteSizeAvailable) | |
| 154 { | |
| 155 testSizeByteByByte("/LayoutTests/fast/images/resources/png-animated-idat-par t-of-animation.png", | |
| 156 100u, IntSize(100, 100)); | |
| 157 testSizeByteByByte("/LayoutTests/fast/images/resources/png-animated-idat-not -part-of-animation.png", | |
| 158 80u, IntSize(227, 35)); | |
| 159 } | |
| 160 | |
| 161 /* | |
| 162 * Test whether the frame meta data decoding also works when we provide the data | |
| 163 * byte by byte. This should cover the case when the client does not provide | |
| 164 * all data at once. At given offsets, we expect frames to become available. | |
| 165 * This test checks whether that is the case, and if so, if the frame data is | |
| 166 * equal to what we expected. | |
| 167 */ | |
| 168 TEST(AnimatedPNGTests, ByteByByteMetaData) | |
| 169 { | |
| 170 const char* pngFile = "/LayoutTests/fast/images/resources/png-animated-idat- part-of-animation.png"; | |
| 171 constexpr size_t expectedFrameCount = 20; | |
| 172 | |
| 173 /* | |
| 174 * These are the byte offsets where each frame should have been parsed. | |
| 175 * It boils down to the offset of the first fcTL / IEND after the last | |
| 176 * frame data chunk, plus 8 bytes for recognition. | |
| 177 */ | |
| 178 size_t frameOffsets[expectedFrameCount] = { 4745, 9139, 13231, 17109, | |
| 179 20680, 23898, 26727, 29365, | |
| 180 32135, 34977, 37692, 40323, | |
| 181 43025, 45849, 48743, 51679, | |
| 182 54695, 57942, 61510, 65555}; | |
| 183 auto decoder = createDecoder(); | |
| 184 auto data = readFile(pngFile); | |
| 185 EXPECT_EQ(false, data->isEmpty()); | |
|
scroggo_chromium
2016/10/11 20:13:10
ASSERT_FALSE
| |
| 186 size_t framesParsed = 0; | |
| 187 | |
| 188 for (size_t length = 1; length <= frameOffsets[expectedFrameCount - 1]; leng th++) { | |
| 189 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h); | |
|
scroggo_chromium
2016/10/11 20:13:10
We have some infrastructure to detect if your test
joostouwerling
2016/10/12 20:49:46
Yep, my test runs in 800ms. I'll first work on a s
| |
| 190 decoder->setData(tempData.get(), false); | |
| 191 ASSERT(!decoder->failed()); | |
| 192 | |
| 193 if (length < frameOffsets[framesParsed]) { | |
| 194 EXPECT_EQ(framesParsed, decoder->frameCount()); | |
| 195 } else { | |
| 196 EXPECT_EQ(framesParsed + 1, decoder->frameCount()); | |
|
scroggo_chromium
2016/10/11 20:13:10
Why don't they match exactly?
joostouwerling
2016/10/12 20:49:46
When the code is at an offset where a new frame sh
| |
| 197 compareFrameWithExpectation(pngAnimatedFrameInfo[framesParsed], | |
| 198 decoder->frameBufferAtIndex(framesParsed )); | |
| 199 framesParsed++; | |
| 200 } | |
| 201 } | |
| 202 EXPECT_EQ(expectedFrameCount, decoder->frameCount()); | |
| 203 EXPECT_FALSE(decoder->failed()); | |
| 204 } | |
| 205 | |
| 206 // Static PNG tests | |
| 207 | |
| 208 TEST(StaticPNGTests, repetitionCountTest) | |
| 209 { | |
| 210 testRepetitionCount("/LayoutTests/fast/images/resources/png-simple.png", cAn imationNone); | |
| 211 } | |
| 212 | |
| 213 TEST(StaticPNGTests, sizeTest) | |
| 214 { | |
| 215 testSize("/LayoutTests/fast/images/resources/png-simple.png", IntSize(111, 2 9)); | |
| 216 } | |
| 217 | |
| 218 TEST(StaticPNGTests, MetaDataTest) | |
| 219 { | |
| 220 size_t expectedFrameCount = 1; | |
| 221 size_t expectedDuration = 0; | |
| 222 auto decoder = createDecoderWithPngData("/LayoutTests/fast/images/resources/ png-simple.png"); | |
| 223 EXPECT_EQ(expectedFrameCount, decoder->frameCount()); | |
|
scroggo_chromium
2016/10/11 20:13:10
nit: I would prefer to hardcode these numbers e.g.
joostouwerling
2016/10/12 20:49:46
I prefer, but also not very strongly, this output:
scroggo_chromium
2016/10/13 13:49:32
Wow, haha, I have not paid that much attention to
| |
| 224 EXPECT_EQ(expectedDuration, decoder->frameDurationAtIndex(0)); | |
| 225 } | |
| 226 }; // namespace blink | |
| OLD | NEW |