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

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

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
29 */
30
31 #include "config.h"
32
33 #include "core/platform/image-decoders/webp/WEBPImageDecoder.h"
34
35 #include "RuntimeEnabledFeatures.h"
36 #include "platform/SharedBuffer.h"
37 #include "public/platform/Platform.h"
38 #include "public/platform/WebData.h"
39 #include "public/platform/WebSize.h"
40 #include "public/platform/WebUnitTestSupport.h"
41 #include "wtf/OwnPtr.h"
42 #include "wtf/PassOwnPtr.h"
43 #include "wtf/StringHasher.h"
44 #include "wtf/Vector.h"
45 #include "wtf/dtoa/utils.h"
46 #include <gtest/gtest.h>
47
48 using namespace WebCore;
49 using namespace blink;
50
51 namespace {
52
53 PassRefPtr<SharedBuffer> readFile(const char* fileName)
54 {
55 String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
56 filePath.append(fileName);
57
58 return Platform::current()->unitTestSupport()->readFromFile(filePath);
59 }
60
61 PassOwnPtr<WEBPImageDecoder> createDecoder()
62 {
63 return adoptPtr(new WEBPImageDecoder(ImageSource::AlphaNotPremultiplied, Ima geSource::GammaAndColorProfileApplied, ImageDecoder::noDecodedImageByteLimit));
64 }
65
66 unsigned hashSkBitmap(const SkBitmap& bitmap)
67 {
68 return StringHasher::hashMemory(bitmap.getPixels(), bitmap.getSize());
69 }
70
71 void createDecodingBaseline(SharedBuffer* data, Vector<unsigned>* baselineHashes )
72 {
73 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
74 decoder->setData(data, true);
75 size_t frameCount = decoder->frameCount();
76 for (size_t i = 0; i < frameCount; ++i) {
77 ImageFrame* frame = decoder->frameBufferAtIndex(i);
78 baselineHashes->append(hashSkBitmap(frame->getSkBitmap()));
79 }
80 }
81
82 void testRandomFrameDecode(const char* webpFile)
83 {
84 SCOPED_TRACE(webpFile);
85
86 RefPtr<SharedBuffer> fullData = readFile(webpFile);
87 ASSERT_TRUE(fullData.get());
88 Vector<unsigned> baselineHashes;
89 createDecodingBaseline(fullData.get(), &baselineHashes);
90 size_t frameCount = baselineHashes.size();
91
92 // Random decoding should get the same results as sequential decoding.
93 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
94 decoder->setData(fullData.get(), true);
95 const size_t skippingStep = 5;
96 for (size_t i = 0; i < skippingStep; ++i) {
97 for (size_t j = i; j < frameCount; j += skippingStep) {
98 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
99 ImageFrame* frame = decoder->frameBufferAtIndex(j);
100 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap()));
101 }
102 }
103
104 // Decoding in reverse order.
105 decoder = createDecoder();
106 decoder->setData(fullData.get(), true);
107 for (size_t i = frameCount; i; --i) {
108 SCOPED_TRACE(testing::Message() << "Reverse i:" << i);
109 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1);
110 EXPECT_EQ(baselineHashes[i - 1], hashSkBitmap(frame->getSkBitmap()));
111 }
112 }
113
114 void testRandomDecodeAfterClearFrameBufferCache(const char* webpFile)
115 {
116 SCOPED_TRACE(webpFile);
117
118 RefPtr<SharedBuffer> data = readFile(webpFile);
119 ASSERT_TRUE(data.get());
120 Vector<unsigned> baselineHashes;
121 createDecodingBaseline(data.get(), &baselineHashes);
122 size_t frameCount = baselineHashes.size();
123
124 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
125 decoder->setData(data.get(), true);
126 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce ptFrame) {
127 decoder->clearCacheExceptFrame(clearExceptFrame);
128 const size_t skippingStep = 5;
129 for (size_t i = 0; i < skippingStep; ++i) {
130 for (size_t j = 0; j < frameCount; j += skippingStep) {
131 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
132 ImageFrame* frame = decoder->frameBufferAtIndex(j);
133 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap())) ;
134 }
135 }
136 }
137 }
138
139 void testDecodeAfterReallocatingData(const char* webpFile)
140 {
141 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
142 RefPtr<SharedBuffer> data = readFile(webpFile);
143 ASSERT_TRUE(data.get());
144
145 // Parse from 'data'.
146 decoder->setData(data.get(), true);
147 size_t frameCount = decoder->frameCount();
148
149 // ... and then decode frames from 'reallocatedData'.
150 RefPtr<SharedBuffer> reallocatedData = data.get()->copy();
151 ASSERT_TRUE(reallocatedData.get());
152 data.clear();
153 decoder->setData(reallocatedData.get(), true);
154
155 for (size_t i = 0; i < frameCount; ++i) {
156 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
157 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
158 }
159 }
160
161 void testInvalidImage(const char* webpFile)
162 {
163 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
164
165 RefPtr<SharedBuffer> data = readFile(webpFile);
166 ASSERT_TRUE(data.get());
167 decoder->setData(data.get(), true);
168
169 EXPECT_EQ(0u, decoder->frameCount());
170 ImageFrame* frame = decoder->frameBufferAtIndex(0);
171 EXPECT_FALSE(frame);
172 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
173 }
174
175 } // namespace
176
177 class AnimatedWebPTests : public ::testing::Test {
178 protected:
179 virtual void SetUp()
180 {
181 // Enable animated WebP for all the tests.
182 WebCore::RuntimeEnabledFeatures::setAnimatedWebPEnabled(true);
183 }
184 };
185
186 TEST_F(AnimatedWebPTests, uniqueGenerationIDs)
187 {
188 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
189
190 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
191 ASSERT_TRUE(data.get());
192 decoder->setData(data.get(), true);
193
194 ImageFrame* frame = decoder->frameBufferAtIndex(0);
195 uint32_t generationID0 = frame->getSkBitmap().getGenerationID();
196 frame = decoder->frameBufferAtIndex(1);
197 uint32_t generationID1 = frame->getSkBitmap().getGenerationID();
198
199 EXPECT_TRUE(generationID0 != generationID1);
200 }
201
202 TEST_F(AnimatedWebPTests, verifyAnimationParametersTransparentImage)
203 {
204 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
205 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
206
207 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
208 ASSERT_TRUE(data.get());
209 decoder->setData(data.get(), true);
210
211 const int canvasWidth = 11;
212 const int canvasHeight = 29;
213 const struct AnimParam {
214 int xOffset, yOffset, width, height;
215 ImageFrame::DisposalMethod disposalMethod;
216 ImageFrame::AlphaBlendSource alphaBlendSource;
217 unsigned duration;
218 bool hasAlpha;
219 } frameParameters[] = {
220 { 0, 0, 11, 29, ImageFrame::DisposeKeep, ImageFrame::BlendAtopPreviousFr ame, 1000u, true },
221 { 2, 10, 7, 17, ImageFrame::DisposeKeep, ImageFrame::BlendAtopPreviousFr ame, 500u, true },
222 { 2, 2, 7, 16, ImageFrame::DisposeKeep, ImageFrame::BlendAtopPreviousFra me, 1000u, true },
223 };
224
225 for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) {
226 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
227 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
228 EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
229 EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
230 EXPECT_EQ(frameParameters[i].xOffset, frame->originalFrameRect().x());
231 EXPECT_EQ(frameParameters[i].yOffset, frame->originalFrameRect().y());
232 EXPECT_EQ(frameParameters[i].width, frame->originalFrameRect().width());
233 EXPECT_EQ(frameParameters[i].height, frame->originalFrameRect().height() );
234 EXPECT_EQ(frameParameters[i].disposalMethod, frame->disposalMethod());
235 EXPECT_EQ(frameParameters[i].alphaBlendSource, frame->alphaBlendSource() );
236 EXPECT_EQ(frameParameters[i].duration, frame->duration());
237 EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha());
238 }
239
240 EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount());
241 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
242 }
243
244 TEST_F(AnimatedWebPTests, verifyAnimationParametersOpaqueFramesTransparentBackgr ound)
245 {
246 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
247 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
248
249 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated-opaque.webp");
250 ASSERT_TRUE(data.get());
251 decoder->setData(data.get(), true);
252
253 const int canvasWidth = 94;
254 const int canvasHeight = 87;
255 const struct AnimParam {
256 int xOffset, yOffset, width, height;
257 ImageFrame::DisposalMethod disposalMethod;
258 ImageFrame::AlphaBlendSource alphaBlendSource;
259 unsigned duration;
260 bool hasAlpha;
261 } frameParameters[] = {
262 { 4, 10, 33, 32, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::BlendA topPreviousFrame, 1000u, true },
263 { 34, 30, 33, 32, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::Blend AtopPreviousFrame, 1000u, true },
264 { 62, 50, 32, 32, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::Blend AtopPreviousFrame, 1000u, true },
265 { 10, 54, 32, 33, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::Blend AtopPreviousFrame, 1000u, true },
266 };
267
268 for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) {
269 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
270 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
271 EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
272 EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
273 EXPECT_EQ(frameParameters[i].xOffset, frame->originalFrameRect().x());
274 EXPECT_EQ(frameParameters[i].yOffset, frame->originalFrameRect().y());
275 EXPECT_EQ(frameParameters[i].width, frame->originalFrameRect().width());
276 EXPECT_EQ(frameParameters[i].height, frame->originalFrameRect().height() );
277 EXPECT_EQ(frameParameters[i].disposalMethod, frame->disposalMethod());
278 EXPECT_EQ(frameParameters[i].alphaBlendSource, frame->alphaBlendSource() );
279 EXPECT_EQ(frameParameters[i].duration, frame->duration());
280 EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha());
281 }
282
283 EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount());
284 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
285 }
286
287 TEST_F(AnimatedWebPTests, verifyAnimationParametersBlendOverwrite)
288 {
289 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
290 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
291
292 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated-no-blend.webp");
293 ASSERT_TRUE(data.get());
294 decoder->setData(data.get(), true);
295
296 const int canvasWidth = 94;
297 const int canvasHeight = 87;
298 const struct AnimParam {
299 int xOffset, yOffset, width, height;
300 ImageFrame::DisposalMethod disposalMethod;
301 ImageFrame::AlphaBlendSource alphaBlendSource;
302 unsigned duration;
303 bool hasAlpha;
304 } frameParameters[] = {
305 { 4, 10, 33, 32, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::BlendA topBgcolor, 1000u, true },
306 { 34, 30, 33, 32, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::Blend AtopBgcolor, 1000u, true },
307 { 62, 50, 32, 32, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::Blend AtopBgcolor, 1000u, true },
308 { 10, 54, 32, 33, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::Blend AtopBgcolor, 1000u, true },
309 };
310
311 for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) {
312 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
313 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
314 EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
315 EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
316 EXPECT_EQ(frameParameters[i].xOffset, frame->originalFrameRect().x());
317 EXPECT_EQ(frameParameters[i].yOffset, frame->originalFrameRect().y());
318 EXPECT_EQ(frameParameters[i].width, frame->originalFrameRect().width());
319 EXPECT_EQ(frameParameters[i].height, frame->originalFrameRect().height() );
320 EXPECT_EQ(frameParameters[i].disposalMethod, frame->disposalMethod());
321 EXPECT_EQ(frameParameters[i].alphaBlendSource, frame->alphaBlendSource() );
322 EXPECT_EQ(frameParameters[i].duration, frame->duration());
323 EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha());
324 }
325
326 EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount());
327 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
328 }
329
330 TEST_F(AnimatedWebPTests, parseAndDecodeByteByByte)
331 {
332 const struct TestImage {
333 const char* filename;
334 unsigned frameCount;
335 int repetitionCount;
336 } testImages[] = {
337 { "/LayoutTests/fast/images/resources/webp-animated.webp", 3u, cAnimatio nLoopInfinite },
338 { "/LayoutTests/fast/images/resources/webp-animated-icc-xmp.webp", 13u, 32000 },
339 };
340
341 for (size_t i = 0; i < ARRAY_SIZE(testImages); ++i) {
342 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
343 RefPtr<SharedBuffer> data = readFile(testImages[i].filename);
344 ASSERT_TRUE(data.get());
345
346 size_t frameCount = 0;
347 size_t framesDecoded = 0;
348
349 // Pass data to decoder byte by byte.
350 for (size_t length = 1; length <= data->size(); ++length) {
351 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), l ength);
352 decoder->setData(tempData.get(), length == data->size());
353
354 EXPECT_LE(frameCount, decoder->frameCount());
355 frameCount = decoder->frameCount();
356
357 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
358 if (frame && frame->status() == ImageFrame::FrameComplete && framesD ecoded < frameCount)
359 ++framesDecoded;
360 }
361
362 EXPECT_EQ(testImages[i].frameCount, decoder->frameCount());
363 EXPECT_EQ(testImages[i].frameCount, framesDecoded);
364 EXPECT_EQ(testImages[i].repetitionCount, decoder->repetitionCount());
365 }
366 }
367
368 TEST_F(AnimatedWebPTests, invalidImages)
369 {
370 // ANMF chunk size is smaller than ANMF header size.
371 testInvalidImage("/LayoutTests/fast/images/resources/invalid-animated-webp.w ebp");
372 // One of the frame rectangles extends outside the image boundary.
373 testInvalidImage("/LayoutTests/fast/images/resources/invalid-animated-webp3. webp");
374 }
375
376 TEST_F(AnimatedWebPTests, truncatedLastFrame)
377 {
378 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
379
380 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/inv alid-animated-webp2.webp");
381 ASSERT_TRUE(data.get());
382 decoder->setData(data.get(), true);
383
384 unsigned frameCount = 8;
385 EXPECT_EQ(frameCount, decoder->frameCount());
386 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
387 EXPECT_FALSE(frame);
388 frame = decoder->frameBufferAtIndex(0);
389 EXPECT_FALSE(frame);
390 }
391
392 TEST_F(AnimatedWebPTests, truncatedInBetweenFrame)
393 {
394 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
395
396 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /invalid-animated-webp4.webp");
397 ASSERT_TRUE(fullData.get());
398 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), fullData- >size() - 1);
399 decoder->setData(data.get(), false);
400
401 ImageFrame* frame = decoder->frameBufferAtIndex(2);
402 EXPECT_FALSE(frame);
403 }
404
405 // Reproduce a crash that used to happen for a specific file with specific seque nce of method calls.
406 TEST_F(AnimatedWebPTests, reproCrash)
407 {
408 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
409
410 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /invalid_vp8_vp8x.webp");
411 ASSERT_TRUE(fullData.get());
412
413 // Parse partial data up to which error in bitstream is not detected.
414 const size_t partialSize = 32768;
415 ASSERT_GT(fullData->size(), partialSize);
416 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), partialSi ze);
417 decoder->setData(data.get(), false);
418 EXPECT_EQ(1u, decoder->frameCount());
419
420 // Parse full data now. The error in bitstream should now be detected.
421 decoder->setData(fullData.get(), true);
422 EXPECT_EQ(0u, decoder->frameCount());
423 ImageFrame* frame = decoder->frameBufferAtIndex(0);
424 EXPECT_FALSE(frame);
425 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
426 }
427
428 TEST_F(AnimatedWebPTests, progressiveDecode)
429 {
430 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated.webp");
431 ASSERT_TRUE(fullData.get());
432 const size_t fullLength = fullData->size();
433
434 OwnPtr<WEBPImageDecoder> decoder;
435 ImageFrame* frame;
436
437 Vector<unsigned> truncatedHashes;
438 Vector<unsigned> progressiveHashes;
439
440 // Compute hashes when the file is truncated.
441 const size_t increment = 1;
442 for (size_t i = 1; i <= fullLength; i += increment) {
443 decoder = createDecoder();
444 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
445 decoder->setData(data.get(), i == fullLength);
446 frame = decoder->frameBufferAtIndex(0);
447 if (!frame) {
448 truncatedHashes.append(0);
449 continue;
450 }
451 truncatedHashes.append(hashSkBitmap(frame->getSkBitmap()));
452 }
453
454 // Compute hashes when the file is progressively decoded.
455 decoder = createDecoder();
456 for (size_t i = 1; i <= fullLength; i += increment) {
457 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
458 decoder->setData(data.get(), i == fullLength);
459 frame = decoder->frameBufferAtIndex(0);
460 if (!frame) {
461 progressiveHashes.append(0);
462 continue;
463 }
464 progressiveHashes.append(hashSkBitmap(frame->getSkBitmap()));
465 }
466
467 bool match = true;
468 for (size_t i = 0; i < truncatedHashes.size(); ++i) {
469 if (truncatedHashes[i] != progressiveHashes[i]) {
470 match = false;
471 break;
472 }
473 }
474 EXPECT_TRUE(match);
475 }
476
477 TEST_F(AnimatedWebPTests, frameIsCompleteAndDuration)
478 {
479 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
480
481 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
482 ASSERT_TRUE(data.get());
483
484 ASSERT_GE(data->size(), 10u);
485 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz e() - 10);
486 decoder->setData(tempData.get(), false);
487
488 EXPECT_EQ(2u, decoder->frameCount());
489 EXPECT_FALSE(decoder->failed());
490 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
491 EXPECT_EQ(1000, decoder->frameDurationAtIndex(0));
492 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
493 EXPECT_EQ(500, decoder->frameDurationAtIndex(1));
494
495 decoder->setData(data.get(), true);
496 EXPECT_EQ(3u, decoder->frameCount());
497 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
498 EXPECT_EQ(1000, decoder->frameDurationAtIndex(0));
499 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
500 EXPECT_EQ(500, decoder->frameDurationAtIndex(1));
501 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(2));
502 EXPECT_EQ(1000.0, decoder->frameDurationAtIndex(2));
503 }
504
505 TEST_F(AnimatedWebPTests, updateRequiredPreviousFrameAfterFirstDecode)
506 {
507 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
508
509 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated.webp");
510 ASSERT_TRUE(fullData.get());
511
512 // Give it data that is enough to parse but not decode in order to check the status
513 // of requiredPreviousFrameIndex before decoding.
514 size_t partialSize = 1;
515 do {
516 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize);
517 decoder->setData(data.get(), false);
518 ++partialSize;
519 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty);
520
521 EXPECT_EQ(kNotFound, decoder->frameBufferAtIndex(0)->requiredPreviousFrameIn dex());
522 unsigned frameCount = decoder->frameCount();
523 for (size_t i = 1; i < frameCount; ++i)
524 EXPECT_EQ(i - 1, decoder->frameBufferAtIndex(i)->requiredPreviousFrameIn dex());
525
526 decoder->setData(fullData.get(), true);
527 for (size_t i = 0; i < frameCount; ++i)
528 EXPECT_EQ(kNotFound, decoder->frameBufferAtIndex(i)->requiredPreviousFra meIndex());
529 }
530
531 TEST_F(AnimatedWebPTests, randomFrameDecode)
532 {
533 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated.webp ");
534 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-opaq ue.webp");
535 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-larg e.webp");
536 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-icc- xmp.webp");
537 }
538
539 TEST_F(AnimatedWebPTests, randomDecodeAfterClearFrameBufferCache)
540 {
541 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated.webp");
542 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated-opaque.webp");
543 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated-large.webp");
544 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated-icc-xmp.webp");
545 }
546
547 TEST_F(AnimatedWebPTests, resumePartialDecodeAfterClearFrameBufferCache)
548 {
549 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated-large.webp");
550 ASSERT_TRUE(fullData.get());
551 Vector<unsigned> baselineHashes;
552 createDecodingBaseline(fullData.get(), &baselineHashes);
553 size_t frameCount = baselineHashes.size();
554
555 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
556
557 // Let frame 0 be partially decoded.
558 size_t partialSize = 1;
559 do {
560 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize);
561 decoder->setData(data.get(), false);
562 ++partialSize;
563 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty);
564
565 // Skip to the last frame and clear.
566 decoder->setData(fullData.get(), true);
567 EXPECT_EQ(frameCount, decoder->frameCount());
568 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1);
569 EXPECT_EQ(baselineHashes[frameCount - 1], hashSkBitmap(lastFrame->getSkBitma p()));
570 decoder->clearCacheExceptFrame(kNotFound);
571
572 // Resume decoding of the first frame.
573 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0);
574 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->status());
575 EXPECT_EQ(baselineHashes[0], hashSkBitmap(firstFrame->getSkBitmap()));
576 }
577
578 TEST_F(AnimatedWebPTests, decodeAfterReallocatingData)
579 {
580 testDecodeAfterReallocatingData("/LayoutTests/fast/images/resources/webp-ani mated.webp");
581 testDecodeAfterReallocatingData("/LayoutTests/fast/images/resources/webp-ani mated-icc-xmp.webp");
582 }
583
584 TEST(StaticWebPTests, truncatedImage)
585 {
586 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
587
588 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/tru ncated.webp");
589 ASSERT_TRUE(data.get());
590 decoder->setData(data.get(), true);
591
592 ImageFrame* frame = decoder->frameBufferAtIndex(0);
593 EXPECT_FALSE(frame);
594 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698