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 |