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

Side by Side Diff: Source/core/platform/image-decoders/webp/WEBPImageDecoderTest.cpp

Issue 13980003: Add animation support for WebP images (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Adapt to recent animation code changes Created 7 years, 6 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
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 12 matching lines...) Expand all
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 32
33 #include "core/platform/image-decoders/gif/GIFImageDecoder.h" 33 #include "core/platform/image-decoders/webp/WEBPImageDecoder.h"
34 34
35 #include "RuntimeEnabledFeatures.h"
35 #include "core/platform/FileSystem.h" 36 #include "core/platform/FileSystem.h"
36 #include "core/platform/SharedBuffer.h" 37 #include "core/platform/SharedBuffer.h"
37 #include "public/platform/Platform.h" 38 #include "public/platform/Platform.h"
38 #include "public/platform/WebData.h" 39 #include "public/platform/WebData.h"
39 #include "public/platform/WebSize.h" 40 #include "public/platform/WebSize.h"
40 #include "public/platform/WebUnitTestSupport.h" 41 #include "public/platform/WebUnitTestSupport.h"
41 #include "wtf/OwnPtr.h" 42 #include "wtf/OwnPtr.h"
42 #include "wtf/PassOwnPtr.h" 43 #include "wtf/PassOwnPtr.h"
43 #include "wtf/StringHasher.h" 44 #include "wtf/StringHasher.h"
44 #include "wtf/Vector.h" 45 #include "wtf/Vector.h"
46 #include <base/basictypes.h>
45 #include <gtest/gtest.h> 47 #include <gtest/gtest.h>
46 48
47 using namespace WebCore; 49 using namespace WebCore;
48 using namespace WebKit; 50 using namespace WebKit;
49 51
50 namespace { 52 namespace {
51 53
52 #if !OS(ANDROID) 54 #if !OS(ANDROID)
53 55
54 static PassRefPtr<SharedBuffer> readFile(const char* fileName) 56 static PassRefPtr<SharedBuffer> readFile(const char* fileName)
55 { 57 {
56 String filePath = Platform::current()->unitTestSupport()->webKitRootDir(); 58 String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
57 filePath.append(fileName); 59 filePath.append(fileName);
58 60
59 long long fileSize; 61 long long fileSize;
60 if (!getFileSize(filePath, fileSize)) 62 if (!getFileSize(filePath, fileSize))
61 return 0; 63 return 0;
62 64
63 PlatformFileHandle handle = openFile(filePath, OpenForRead); 65 PlatformFileHandle handle = openFile(filePath, OpenForRead);
64 int fileLength = static_cast<int>(fileSize); 66 int fileLength = static_cast<int>(fileSize);
65 Vector<char> buffer(fileLength); 67 Vector<char> buffer(fileLength);
66 readFromFile(handle, buffer.data(), fileLength); 68 readFromFile(handle, buffer.data(), fileLength);
67 closeFile(handle); 69 closeFile(handle);
68 return SharedBuffer::adoptVector(buffer); 70 return SharedBuffer::adoptVector(buffer);
69 } 71 }
70 72
71 static PassOwnPtr<GIFImageDecoder> createDecoder() 73 static PassOwnPtr<WEBPImageDecoder> createDecoder()
72 { 74 {
73 return adoptPtr(new GIFImageDecoder(ImageSource::AlphaNotPremultiplied, Imag eSource::GammaAndColorProfileApplied)); 75 return adoptPtr(new WEBPImageDecoder(ImageSource::AlphaNotPremultiplied, Ima geSource::GammaAndColorProfileApplied));
74 } 76 }
75 77
76 static unsigned hashSkBitmap(const SkBitmap& bitmap) 78 static unsigned hashSkBitmap(const SkBitmap& bitmap)
77 { 79 {
78 return StringHasher::hashMemory(bitmap.getPixels(), bitmap.getSize()); 80 return StringHasher::hashMemory(bitmap.getPixels(), bitmap.getSize());
79 } 81 }
80 82
81 static void createDecodingBaseline(SharedBuffer* data, Vector<unsigned>* baselin eHashes) 83 static void createDecodingBaseline(SharedBuffer* data, Vector<unsigned>* baselin eHashes)
82 { 84 {
83 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 85 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
84 decoder->setData(data, true); 86 decoder->setData(data, true);
85 size_t frameCount = decoder->frameCount(); 87 size_t frameCount = decoder->frameCount();
86 for (size_t i = 0; i < frameCount; ++i) { 88 for (size_t i = 0; i < frameCount; ++i) {
87 ImageFrame* frame = decoder->frameBufferAtIndex(i); 89 ImageFrame* frame = decoder->frameBufferAtIndex(i);
88 baselineHashes->append(hashSkBitmap(frame->getSkBitmap())); 90 baselineHashes->append(hashSkBitmap(frame->getSkBitmap()));
89 } 91 }
90 } 92 }
91 93
92 TEST(GIFImageDecoderTest, decodeTwoFrames) 94 void testRandomFrameDecode(const char* webpFile)
93 { 95 {
94 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 96 SCOPED_TRACE(webpFile);
95 97
96 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 98 RefPtr<SharedBuffer> fullData = readFile(webpFile);
99 ASSERT_TRUE(fullData.get());
100 Vector<unsigned> baselineHashes;
101 createDecodingBaseline(fullData.get(), &baselineHashes);
102 size_t frameCount = baselineHashes.size();
103
104 // Random decoding should get the same results as sequential decoding.
105 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
106 decoder->setData(fullData.get(), true);
107 const size_t skippingStep = 5;
108 for (size_t i = 0; i < skippingStep; ++i) {
109 for (size_t j = i; j < frameCount; j += skippingStep) {
110 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
111 ImageFrame* frame = decoder->frameBufferAtIndex(j);
112 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap()));
113 }
114 }
115
116 // Decoding in reverse order.
117 decoder = createDecoder();
118 decoder->setData(fullData.get(), true);
119 for (size_t i = frameCount; i; --i) {
120 SCOPED_TRACE(testing::Message() << "Reverse i:" << i);
121 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1);
122 EXPECT_EQ(baselineHashes[i - 1], hashSkBitmap(frame->getSkBitmap()));
123 }
124 }
125
126 void testRandomDecodeAfterClearFrameBufferCache(const char* webpFile)
127 {
128 SCOPED_TRACE(webpFile);
129
130 RefPtr<SharedBuffer> data = readFile(webpFile);
131 ASSERT_TRUE(data.get());
132 Vector<unsigned> baselineHashes;
133 createDecodingBaseline(data.get(), &baselineHashes);
134 size_t frameCount = baselineHashes.size();
135
136 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
137 decoder->setData(data.get(), true);
138 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce ptFrame) {
139 decoder->clearCacheExceptFrame(clearExceptFrame);
140 const size_t skippingStep = 5;
141 for (size_t i = 0; i < skippingStep; ++i) {
142 for (size_t j = 0; j < frameCount; j += skippingStep) {
143 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
144 ImageFrame* frame = decoder->frameBufferAtIndex(j);
145 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap())) ;
146 }
147 }
148 }
149 }
150
151 class AnimatedWebPTests : public ::testing::Test {
152 protected:
153 virtual void SetUp()
154 {
155 // Enable animated WebP for all the tests.
156 WebCore::RuntimeEnabledFeatures::setAnimatedWebPEnabled(true);
157 }
158 };
159
160 TEST_F(AnimatedWebPTests, verifyAnimationParameters)
161 {
162 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
163 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
164
165 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
97 ASSERT_TRUE(data.get()); 166 ASSERT_TRUE(data.get());
98 decoder->setData(data.get(), true); 167 decoder->setData(data.get(), true);
99 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
100 168
101 ImageFrame* frame = decoder->frameBufferAtIndex(0); 169 const int canvasWidth = 11;
102 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 170 const int canvasHeight = 29;
103 EXPECT_EQ(16, frame->getSkBitmap().width()); 171 const int hasAlpha = true;
104 EXPECT_EQ(16, frame->getSkBitmap().height()); 172 const struct AnimParam {
173 int xOffset, yOffset, width, height;
174 ImageFrame::FrameDisposalMethod dispose;
175 unsigned duration;
176 } animParams[] = {
177 { 0, 0, 11, 29, ImageFrame::DisposeKeep, 1000u },
178 { 2, 10, 7, 17, ImageFrame::DisposeKeep, 500u },
179 { 2, 2, 7, 16, ImageFrame::DisposeKeep, 1000u },
180 };
105 181
106 frame = decoder->frameBufferAtIndex(1); 182 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(animParams); ++i) {
107 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 183 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
108 EXPECT_EQ(16, frame->getSkBitmap().width()); 184 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
109 EXPECT_EQ(16, frame->getSkBitmap().height()); 185 EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
186 EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
187 EXPECT_EQ(hasAlpha, frame->hasAlpha());
188 EXPECT_EQ(animParams[i].xOffset, frame->originalFrameRect().x());
189 EXPECT_EQ(animParams[i].yOffset, frame->originalFrameRect().y());
190 EXPECT_EQ(animParams[i].width, frame->originalFrameRect().width());
191 EXPECT_EQ(animParams[i].height, frame->originalFrameRect().height());
192 EXPECT_EQ(animParams[i].dispose, frame->disposalMethod());
193 EXPECT_EQ(animParams[i].duration, frame->duration());
194 }
110 195
111 EXPECT_EQ(2u, decoder->frameCount()); 196 EXPECT_EQ(ARRAYSIZE_UNSAFE(animParams), decoder->frameCount());
112 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); 197 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
113 } 198 }
114 199
115 TEST(GIFImageDecoderTest, parseAndDecode) 200 TEST_F(AnimatedWebPTests, parseAndDecodeByteByByte)
116 { 201 {
117 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 202 const struct TestImage {
203 const char* filename;
204 unsigned frameCount;
205 int repetitionCount;
206 } testImages[] = {
207 { "/LayoutTests/fast/images/resources/webp-animated.webp", 3u, cAnimatio nLoopInfinite },
208 { "/LayoutTests/fast/images/resources/webp-animated-icc-xmp.webp", 13u, 32000 },
209 };
118 210
119 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 211 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(testImages); ++i) {
120 ASSERT_TRUE(data.get()); 212 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
121 decoder->setData(data.get(), true); 213 RefPtr<SharedBuffer> data = readFile(testImages[i].filename);
122 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); 214 ASSERT_TRUE(data.get());
123 215
124 // This call will parse the entire file. 216 size_t frameCount = 0;
125 EXPECT_EQ(2u, decoder->frameCount()); 217 size_t framesDecoded = 0;
126 218
127 ImageFrame* frame = decoder->frameBufferAtIndex(0); 219 // Pass data to decoder byte by byte.
128 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 220 for (size_t length = 1; length <= data->size(); ++length) {
129 EXPECT_EQ(16, frame->getSkBitmap().width()); 221 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), l ength);
130 EXPECT_EQ(16, frame->getSkBitmap().height()); 222 decoder->setData(tempData.get(), length == data->size());
131 223
132 frame = decoder->frameBufferAtIndex(1); 224 EXPECT_LE(frameCount, decoder->frameCount());
133 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 225 frameCount = decoder->frameCount();
134 EXPECT_EQ(16, frame->getSkBitmap().width()); 226
135 EXPECT_EQ(16, frame->getSkBitmap().height()); 227 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
136 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); 228 if (frame && frame->status() == ImageFrame::FrameComplete && framesD ecoded < frameCount)
229 ++framesDecoded;
230 }
231
232 EXPECT_EQ(testImages[i].frameCount, decoder->frameCount());
233 EXPECT_EQ(testImages[i].frameCount, framesDecoded);
234 EXPECT_EQ(testImages[i].repetitionCount, decoder->repetitionCount());
235 }
137 } 236 }
138 237
139 TEST(GIFImageDecoderTest, parseByteByByte) 238 TEST_F(AnimatedWebPTests, invalidImage)
140 { 239 {
141 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 240 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
142 241
143 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 242 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/inv alid-animated-webp.webp");
144 ASSERT_TRUE(data.get());
145
146 size_t frameCount = 0;
147
148 // Pass data to decoder byte by byte.
149 for (size_t length = 1; length <= data->size(); ++length) {
150 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h);
151 decoder->setData(tempData.get(), length == data->size());
152
153 EXPECT_LE(frameCount, decoder->frameCount());
154 frameCount = decoder->frameCount();
155 }
156
157 EXPECT_EQ(2u, decoder->frameCount());
158
159 decoder->frameBufferAtIndex(0);
160 decoder->frameBufferAtIndex(1);
161 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
162 }
163
164 TEST(GIFImageDecoderTest, parseAndDecodeByteByByte)
165 {
166 OwnPtr<GIFImageDecoder> decoder = createDecoder();
167
168 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated-gif-with-offsets.gif");
169 ASSERT_TRUE(data.get());
170
171 size_t frameCount = 0;
172 size_t framesDecoded = 0;
173
174 // Pass data to decoder byte by byte.
175 for (size_t length = 1; length <= data->size(); ++length) {
176 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h);
177 decoder->setData(tempData.get(), length == data->size());
178
179 EXPECT_LE(frameCount, decoder->frameCount());
180 frameCount = decoder->frameCount();
181
182 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
183 if (frame && frame->status() == ImageFrame::FrameComplete && framesDecod ed < frameCount)
184 ++framesDecoded;
185 }
186
187 EXPECT_EQ(5u, decoder->frameCount());
188 EXPECT_EQ(5u, framesDecoded);
189 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
190 }
191
192 TEST(GIFImageDecoderTest, brokenSecondFrame)
193 {
194 OwnPtr<GIFImageDecoder> decoder = createDecoder();
195
196 RefPtr<SharedBuffer> data = readFile("/Source/WebKit/chromium/tests/data/bro ken.gif");
197 ASSERT_TRUE(data.get()); 243 ASSERT_TRUE(data.get());
198 decoder->setData(data.get(), true); 244 decoder->setData(data.get(), true);
199 245
200 // One frame is detected but cannot be decoded. 246 EXPECT_EQ(0u, decoder->frameCount());
201 EXPECT_EQ(1u, decoder->frameCount()); 247 ImageFrame* frame = decoder->frameBufferAtIndex(0);
202 ImageFrame* frame = decoder->frameBufferAtIndex(1);
203 EXPECT_FALSE(frame); 248 EXPECT_FALSE(frame);
249 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
204 } 250 }
205 251
206 TEST(GIFImageDecoderTest, progressiveDecode) 252 TEST_F(AnimatedWebPTests, progressiveDecode)
207 { 253 {
208 RefPtr<SharedBuffer> fullData = readFile("/Source/WebKit/chromium/tests/data /radient.gif"); 254 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated.webp");
209 ASSERT_TRUE(fullData.get()); 255 ASSERT_TRUE(fullData.get());
210 const size_t fullLength = fullData->size(); 256 const size_t fullLength = fullData->size();
211 257
212 OwnPtr<GIFImageDecoder> decoder; 258 OwnPtr<WEBPImageDecoder> decoder;
213 ImageFrame* frame; 259 ImageFrame* frame;
214 260
215 Vector<unsigned> truncatedHashes; 261 Vector<unsigned> truncatedHashes;
216 Vector<unsigned> progressiveHashes; 262 Vector<unsigned> progressiveHashes;
217 263
218 // Compute hashes when the file is truncated. 264 // Compute hashes when the file is truncated.
219 const size_t increment = 1; 265 const size_t increment = 1;
220 for (size_t i = 1; i <= fullLength; i += increment) { 266 for (size_t i = 1; i <= fullLength; i += increment) {
221 decoder = createDecoder(); 267 decoder = createDecoder();
222 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i); 268 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
(...skipping 22 matching lines...) Expand all
245 bool match = true; 291 bool match = true;
246 for (size_t i = 0; i < truncatedHashes.size(); ++i) { 292 for (size_t i = 0; i < truncatedHashes.size(); ++i) {
247 if (truncatedHashes[i] != progressiveHashes[i]) { 293 if (truncatedHashes[i] != progressiveHashes[i]) {
248 match = false; 294 match = false;
249 break; 295 break;
250 } 296 }
251 } 297 }
252 EXPECT_TRUE(match); 298 EXPECT_TRUE(match);
253 } 299 }
254 300
255 TEST(GIFImageDecoderTest, allDataReceivedTruncation) 301 TEST_F(AnimatedWebPTests, frameIsCompleteAndDuration)
256 { 302 {
257 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 303 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
258 304
259 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 305 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
260 ASSERT_TRUE(data.get()); 306 ASSERT_TRUE(data.get());
261 307
262 ASSERT_GE(data->size(), 10u); 308 ASSERT_GE(data->size(), 10u);
263 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz e() - 10);
264 decoder->setData(tempData.get(), true);
265
266 EXPECT_EQ(2u, decoder->frameCount());
267 EXPECT_FALSE(decoder->failed());
268
269 decoder->frameBufferAtIndex(0);
270 EXPECT_FALSE(decoder->failed());
271 decoder->frameBufferAtIndex(1);
272 EXPECT_TRUE(decoder->failed());
273 }
274
275 TEST(GIFImageDecoderTest, frameIsComplete)
276 {
277 OwnPtr<GIFImageDecoder> decoder = createDecoder();
278
279 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif");
280 ASSERT_TRUE(data.get());
281 decoder->setData(data.get(), true);
282
283 EXPECT_EQ(2u, decoder->frameCount());
284 EXPECT_FALSE(decoder->failed());
285 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
286 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
287 }
288
289 TEST(GIFImageDecoderTest, frameIsCompleteLoading)
290 {
291 OwnPtr<GIFImageDecoder> decoder = createDecoder();
292
293 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif");
294 ASSERT_TRUE(data.get());
295
296 ASSERT_GE(data->size(), 10u);
297 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz e() - 10); 309 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz e() - 10);
298 decoder->setData(tempData.get(), false); 310 decoder->setData(tempData.get(), false);
299 311
300 EXPECT_EQ(2u, decoder->frameCount()); 312 EXPECT_EQ(2u, decoder->frameCount());
301 EXPECT_FALSE(decoder->failed()); 313 EXPECT_FALSE(decoder->failed());
302 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); 314 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
303 EXPECT_FALSE(decoder->frameIsCompleteAtIndex(1)); 315 EXPECT_EQ(1000, decoder->frameDurationAtIndex(0));
316 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
317 EXPECT_EQ(500, decoder->frameDurationAtIndex(1));
304 318
305 decoder->setData(data.get(), true); 319 decoder->setData(data.get(), true);
306 EXPECT_EQ(2u, decoder->frameCount()); 320 EXPECT_EQ(3u, decoder->frameCount());
307 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); 321 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
322 EXPECT_EQ(1000, decoder->frameDurationAtIndex(0));
308 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1)); 323 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
324 EXPECT_EQ(500, decoder->frameDurationAtIndex(1));
325 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(2));
326 EXPECT_EQ(1000.0, decoder->frameDurationAtIndex(2));
309 } 327 }
310 328
311 TEST(GIFImageDecoderTest, badTerminator) 329 TEST_F(AnimatedWebPTests, updateRequiredPreviousFrameAfterFirstDecode)
312 { 330 {
313 RefPtr<SharedBuffer> referenceData = readFile("/Source/WebKit/chromium/tests /data/radient.gif"); 331 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
314 RefPtr<SharedBuffer> testData = readFile("/Source/WebKit/chromium/tests/data /radient-bad-terminator.gif");
315 ASSERT_TRUE(referenceData.get());
316 ASSERT_TRUE(testData.get());
317 332
318 OwnPtr<GIFImageDecoder> referenceDecoder(createDecoder()); 333 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated.webp");
319 referenceDecoder->setData(referenceData.get(), true);
320 EXPECT_EQ(1u, referenceDecoder->frameCount());
321 ImageFrame* referenceFrame = referenceDecoder->frameBufferAtIndex(0);
322 ASSERT(referenceFrame);
323
324 OwnPtr<GIFImageDecoder> testDecoder(createDecoder());
325 testDecoder->setData(testData.get(), true);
326 EXPECT_EQ(1u, testDecoder->frameCount());
327 ImageFrame* testFrame = testDecoder->frameBufferAtIndex(0);
328 ASSERT(testFrame);
329
330 EXPECT_EQ(hashSkBitmap(referenceFrame->getSkBitmap()), hashSkBitmap(testFram e->getSkBitmap()));
331 }
332
333 TEST(GIFImageDecoderTest, updateRequiredPreviousFrameAfterFirstDecode)
334 {
335 OwnPtr<GIFImageDecoder> decoder = createDecoder();
336
337 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /animated-10color.gif");
338 ASSERT_TRUE(fullData.get()); 334 ASSERT_TRUE(fullData.get());
339 335
340 // Give it data that is enough to parse but not decode in order to check the status 336 // Give it data that is enough to parse but not decode in order to check the status
341 // of requiredPreviousFrameIndex before decoding. 337 // of requiredPreviousFrameIndex before decoding.
342 size_t partialSize = 1; 338 size_t partialSize = 1;
343 do { 339 do {
344 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize); 340 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize);
345 decoder->setData(data.get(), false); 341 decoder->setData(data.get(), false);
346 ++partialSize; 342 ++partialSize;
347 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty); 343 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty);
348 344
349 EXPECT_EQ(notFound, decoder->frameBufferAtIndex(0)->requiredPreviousFrameInd ex()); 345 EXPECT_EQ(notFound, decoder->frameBufferAtIndex(0)->requiredPreviousFrameInd ex());
350 unsigned frameCount = decoder->frameCount(); 346 unsigned frameCount = decoder->frameCount();
351 for (size_t i = 1; i < frameCount; ++i) 347 for (size_t i = 1; i < frameCount; ++i)
352 EXPECT_EQ(i - 1, decoder->frameBufferAtIndex(i)->requiredPreviousFrameIn dex()); 348 EXPECT_EQ(i - 1, decoder->frameBufferAtIndex(i)->requiredPreviousFrameIn dex());
353 349
354 decoder->setData(fullData.get(), true); 350 decoder->setData(fullData.get(), true);
355 for (size_t i = 0; i < frameCount; ++i) 351 for (size_t i = 0; i < frameCount; ++i)
356 EXPECT_EQ(notFound, decoder->frameBufferAtIndex(i)->requiredPreviousFram eIndex()); 352 EXPECT_EQ(notFound, decoder->frameBufferAtIndex(i)->requiredPreviousFram eIndex());
357 } 353 }
358 354
359 void testRandomFrameDecode(const char* gifFile) 355 TEST_F(AnimatedWebPTests, randomFrameDecode)
360 { 356 {
361 SCOPED_TRACE(gifFile); 357 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated.webp ");
358 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-larg e.webp");
359 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-icc- xmp.webp");
360 }
362 361
363 RefPtr<SharedBuffer> fullData = readFile(gifFile); 362 TEST_F(AnimatedWebPTests, randomDecodeAfterClearFrameBufferCache)
363 {
364 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated.webp");
365 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated-large.webp");
366 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated-icc-xmp.webp");
367 }
368
369 TEST_F(AnimatedWebPTests, resumePartialDecodeAfterClearFrameBufferCache)
370 {
371 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated-large.webp");
364 ASSERT_TRUE(fullData.get()); 372 ASSERT_TRUE(fullData.get());
365 Vector<unsigned> baselineHashes; 373 Vector<unsigned> baselineHashes;
366 createDecodingBaseline(fullData.get(), &baselineHashes); 374 createDecodingBaseline(fullData.get(), &baselineHashes);
367 size_t frameCount = baselineHashes.size(); 375 size_t frameCount = baselineHashes.size();
368 376
369 // Random decoding should get the same results as sequential decoding. 377 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
370 OwnPtr<GIFImageDecoder> decoder = createDecoder();
371 decoder->setData(fullData.get(), true);
372 const size_t skippingStep = 5;
373 for (size_t i = 0; i < skippingStep; ++i) {
374 for (size_t j = i; j < frameCount; j += skippingStep) {
375 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
376 ImageFrame* frame = decoder->frameBufferAtIndex(j);
377 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap()));
378 }
379 }
380
381 // Decoding in reverse order.
382 decoder = createDecoder();
383 decoder->setData(fullData.get(), true);
384 for (size_t i = frameCount; i; --i) {
385 SCOPED_TRACE(testing::Message() << "Reverse i:" << i);
386 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1);
387 EXPECT_EQ(baselineHashes[i - 1], hashSkBitmap(frame->getSkBitmap()));
388 }
389 }
390
391 TEST(GIFImageDecoderTest, randomFrameDecode)
392 {
393 // Single frame image.
394 testRandomFrameDecode("/Source/WebKit/chromium/tests/data/radient.gif");
395 // Multiple frame image.
396 testRandomFrameDecode("/LayoutTests/fast/images/resources/animated-gif-with- offsets.gif");
397 testRandomFrameDecode("/LayoutTests/fast/images/resources/animated-10color.g if");
398 }
399
400 void testRandomDecodeAfterClearFrameBufferCache(const char* gifFile)
401 {
402 SCOPED_TRACE(gifFile);
403
404 RefPtr<SharedBuffer> data = readFile(gifFile);
405 ASSERT_TRUE(data.get());
406 Vector<unsigned> baselineHashes;
407 createDecodingBaseline(data.get(), &baselineHashes);
408 size_t frameCount = baselineHashes.size();
409
410 OwnPtr<GIFImageDecoder> decoder = createDecoder();
411 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce ptFrame) {
412 decoder->clearCacheExceptFrame(clearExceptFrame);
413 const size_t skippingStep = 5;
414 for (size_t i = 0; i < skippingStep; ++i) {
415 for (size_t j = 0; j < frameCount; j += skippingStep) {
416 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
417 ImageFrame* frame = decoder->frameBufferAtIndex(j);
418 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap())) ;
419 }
420 }
421 }
422 }
423
424 TEST(GIFImageDecoderTest, randomDecodeAfterClearFrameBufferCache)
425 {
426 // Single frame image.
427 testRandomFrameDecode("/Source/WebKit/chromium/tests/data/radient.gif");
428 // Multiple frame image.
429 testRandomFrameDecode("/LayoutTests/fast/images/resources/animated-gif-with- offsets.gif");
430 testRandomFrameDecode("/LayoutTests/fast/images/resources/animated-10color.g if");
431 }
432
433 TEST(GIFImageDecoderTest, resumePartialDecodeAfterClearFrameBufferCache)
434 {
435 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /animated-10color.gif");
436 ASSERT_TRUE(fullData.get());
437 Vector<unsigned> baselineHashes;
438 createDecodingBaseline(fullData.get(), &baselineHashes);
439 size_t frameCount = baselineHashes.size();
440
441 OwnPtr<GIFImageDecoder> decoder = createDecoder();
442 378
443 // Let frame 0 be partially decoded. 379 // Let frame 0 be partially decoded.
444 size_t partialSize = 1; 380 size_t partialSize = 1;
445 do { 381 do {
446 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize); 382 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize);
447 decoder->setData(data.get(), false); 383 decoder->setData(data.get(), false);
448 ++partialSize; 384 ++partialSize;
449 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty); 385 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty);
450 386
451 // Skip to the last frame and clear. 387 // Skip to the last frame and clear.
452 decoder->setData(fullData.get(), true); 388 decoder->setData(fullData.get(), true);
453 EXPECT_EQ(frameCount, decoder->frameCount()); 389 EXPECT_EQ(frameCount, decoder->frameCount());
454 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1); 390 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1);
455 EXPECT_EQ(baselineHashes[frameCount - 1], hashSkBitmap(lastFrame->getSkBitma p())); 391 EXPECT_EQ(baselineHashes[frameCount - 1], hashSkBitmap(lastFrame->getSkBitma p()));
456 decoder->clearCacheExceptFrame(notFound); 392 decoder->clearCacheExceptFrame(notFound);
457 393
458 // Resume decoding of the first frame. 394 // Resume decoding of the first frame.
459 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0); 395 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0);
460 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->status()); 396 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->status());
461 EXPECT_EQ(baselineHashes[0], hashSkBitmap(firstFrame->getSkBitmap())); 397 EXPECT_EQ(baselineHashes[0], hashSkBitmap(firstFrame->getSkBitmap()));
462 } 398 }
463 399
464 #endif 400 #endif
465 401
466 } // namespace 402 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698