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

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

Issue 2386453003: WIP: Implement APNG (Closed)
Patch Set: Implement frame meta data decoding, include tests Created 4 years, 2 months 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 "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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698