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

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

Issue 2930513004: [WIP] Move ImageDecoders to SkCodec
Patch Set: Adding check for decoder creation Created 3 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
« no previous file with comments | « third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "platform/image-decoders/webp/WEBPImageDecoder.h"
32
33 #include <memory>
34 #include "platform/RuntimeEnabledFeatures.h"
35 #include "platform/SharedBuffer.h"
36 #include "platform/image-decoders/ImageDecoderTestHelpers.h"
37 #include "platform/wtf/PtrUtil.h"
38 #include "platform/wtf/Vector.h"
39 #include "platform/wtf/dtoa/utils.h"
40 #include "public/platform/WebData.h"
41 #include "public/platform/WebSize.h"
42 #include "testing/gtest/include/gtest/gtest.h"
43
44 namespace blink {
45
46 namespace {
47
48 std::unique_ptr<ImageDecoder> CreateDecoder(
49 ImageDecoder::AlphaOption alpha_option) {
50 return WTF::WrapUnique(new WEBPImageDecoder(
51 alpha_option, ColorBehavior::TransformToTargetForTesting(),
52 ImageDecoder::kNoDecodedImageByteLimit));
53 }
54
55 std::unique_ptr<ImageDecoder> CreateDecoder() {
56 return CreateDecoder(ImageDecoder::kAlphaNotPremultiplied);
57 }
58
59 // If 'parse_error_expected' is true, error is expected during parse
60 // (FrameCount() call); else error is expected during decode
61 // (FrameBufferAtIndex() call).
62 void TestInvalidImage(const char* webp_file, bool parse_error_expected) {
63 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
64
65 RefPtr<SharedBuffer> data = ReadFile(webp_file);
66 ASSERT_TRUE(data.Get());
67 decoder->SetData(data.Get(), true);
68
69 if (parse_error_expected) {
70 EXPECT_EQ(0u, decoder->FrameCount());
71 EXPECT_FALSE(decoder->FrameBufferAtIndex(0));
72 } else {
73 EXPECT_GT(decoder->FrameCount(), 0u);
74 ImageFrame* frame = decoder->FrameBufferAtIndex(0);
75 ASSERT_TRUE(frame);
76 EXPECT_EQ(ImageFrame::kFramePartial, frame->GetStatus());
77 }
78 EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
79 EXPECT_TRUE(decoder->Failed());
80 }
81
82 } // anonymous namespace
83
84 TEST(AnimatedWebPTests, uniqueGenerationIDs) {
85 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
86
87 RefPtr<SharedBuffer> data =
88 ReadFile("/LayoutTests/images/resources/webp-animated.webp");
89 ASSERT_TRUE(data.Get());
90 decoder->SetData(data.Get(), true);
91
92 ImageFrame* frame = decoder->FrameBufferAtIndex(0);
93 uint32_t generation_id0 = frame->Bitmap().getGenerationID();
94 frame = decoder->FrameBufferAtIndex(1);
95 uint32_t generation_id1 = frame->Bitmap().getGenerationID();
96
97 EXPECT_TRUE(generation_id0 != generation_id1);
98 }
99
100 TEST(AnimatedWebPTests, verifyAnimationParametersTransparentImage) {
101 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
102 EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
103
104 RefPtr<SharedBuffer> data =
105 ReadFile("/LayoutTests/images/resources/webp-animated.webp");
106 ASSERT_TRUE(data.Get());
107 decoder->SetData(data.Get(), true);
108
109 const int kCanvasWidth = 11;
110 const int kCanvasHeight = 29;
111 const struct AnimParam {
112 int x_offset, y_offset, width, height;
113 ImageFrame::DisposalMethod disposal_method;
114 ImageFrame::AlphaBlendSource alpha_blend_source;
115 unsigned duration;
116 bool has_alpha;
117 } kFrameParameters[] = {
118 {0, 0, 11, 29, ImageFrame::kDisposeKeep,
119 ImageFrame::kBlendAtopPreviousFrame, 1000u, true},
120 {2, 10, 7, 17, ImageFrame::kDisposeKeep,
121 ImageFrame::kBlendAtopPreviousFrame, 500u, true},
122 {2, 2, 7, 16, ImageFrame::kDisposeKeep,
123 ImageFrame::kBlendAtopPreviousFrame, 1000u, true},
124 };
125
126 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kFrameParameters); ++i) {
127 const ImageFrame* const frame = decoder->FrameBufferAtIndex(i);
128 EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
129 EXPECT_EQ(kCanvasWidth, frame->Bitmap().width());
130 EXPECT_EQ(kCanvasHeight, frame->Bitmap().height());
131 EXPECT_EQ(kFrameParameters[i].x_offset, frame->OriginalFrameRect().X());
132 EXPECT_EQ(kFrameParameters[i].y_offset, frame->OriginalFrameRect().Y());
133 EXPECT_EQ(kFrameParameters[i].width, frame->OriginalFrameRect().Width());
134 EXPECT_EQ(kFrameParameters[i].height, frame->OriginalFrameRect().Height());
135 EXPECT_EQ(kFrameParameters[i].disposal_method, frame->GetDisposalMethod());
136 EXPECT_EQ(kFrameParameters[i].alpha_blend_source,
137 frame->GetAlphaBlendSource());
138 EXPECT_EQ(kFrameParameters[i].duration, frame->Duration());
139 EXPECT_EQ(kFrameParameters[i].has_alpha, frame->HasAlpha());
140 }
141
142 EXPECT_EQ(WTF_ARRAY_LENGTH(kFrameParameters), decoder->FrameCount());
143 EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
144 }
145
146 TEST(AnimatedWebPTests,
147 verifyAnimationParametersOpaqueFramesTransparentBackground) {
148 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
149 EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
150
151 RefPtr<SharedBuffer> data =
152 ReadFile("/LayoutTests/images/resources/webp-animated-opaque.webp");
153 ASSERT_TRUE(data.Get());
154 decoder->SetData(data.Get(), true);
155
156 const int kCanvasWidth = 94;
157 const int kCanvasHeight = 87;
158 const struct AnimParam {
159 int x_offset, y_offset, width, height;
160 ImageFrame::DisposalMethod disposal_method;
161 ImageFrame::AlphaBlendSource alpha_blend_source;
162 unsigned duration;
163 bool has_alpha;
164 } kFrameParameters[] = {
165 {4, 10, 33, 32, ImageFrame::kDisposeOverwriteBgcolor,
166 ImageFrame::kBlendAtopPreviousFrame, 1000u, true},
167 {34, 30, 33, 32, ImageFrame::kDisposeOverwriteBgcolor,
168 ImageFrame::kBlendAtopPreviousFrame, 1000u, true},
169 {62, 50, 32, 32, ImageFrame::kDisposeOverwriteBgcolor,
170 ImageFrame::kBlendAtopPreviousFrame, 1000u, true},
171 {10, 54, 32, 33, ImageFrame::kDisposeOverwriteBgcolor,
172 ImageFrame::kBlendAtopPreviousFrame, 1000u, true},
173 };
174
175 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kFrameParameters); ++i) {
176 const ImageFrame* const frame = decoder->FrameBufferAtIndex(i);
177 EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
178 EXPECT_EQ(kCanvasWidth, frame->Bitmap().width());
179 EXPECT_EQ(kCanvasHeight, frame->Bitmap().height());
180 EXPECT_EQ(kFrameParameters[i].x_offset, frame->OriginalFrameRect().X());
181 EXPECT_EQ(kFrameParameters[i].y_offset, frame->OriginalFrameRect().Y());
182 EXPECT_EQ(kFrameParameters[i].width, frame->OriginalFrameRect().Width());
183 EXPECT_EQ(kFrameParameters[i].height, frame->OriginalFrameRect().Height());
184 EXPECT_EQ(kFrameParameters[i].disposal_method, frame->GetDisposalMethod());
185 EXPECT_EQ(kFrameParameters[i].alpha_blend_source,
186 frame->GetAlphaBlendSource());
187 EXPECT_EQ(kFrameParameters[i].duration, frame->Duration());
188 EXPECT_EQ(kFrameParameters[i].has_alpha, frame->HasAlpha());
189 }
190
191 EXPECT_EQ(WTF_ARRAY_LENGTH(kFrameParameters), decoder->FrameCount());
192 EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
193 }
194
195 TEST(AnimatedWebPTests, verifyAnimationParametersBlendOverwrite) {
196 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
197 EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
198
199 RefPtr<SharedBuffer> data =
200 ReadFile("/LayoutTests/images/resources/webp-animated-no-blend.webp");
201 ASSERT_TRUE(data.Get());
202 decoder->SetData(data.Get(), true);
203
204 const int kCanvasWidth = 94;
205 const int kCanvasHeight = 87;
206 const struct AnimParam {
207 int x_offset, y_offset, width, height;
208 ImageFrame::DisposalMethod disposal_method;
209 ImageFrame::AlphaBlendSource alpha_blend_source;
210 unsigned duration;
211 bool has_alpha;
212 } kFrameParameters[] = {
213 {4, 10, 33, 32, ImageFrame::kDisposeOverwriteBgcolor,
214 ImageFrame::kBlendAtopBgcolor, 1000u, true},
215 {34, 30, 33, 32, ImageFrame::kDisposeOverwriteBgcolor,
216 ImageFrame::kBlendAtopBgcolor, 1000u, true},
217 {62, 50, 32, 32, ImageFrame::kDisposeOverwriteBgcolor,
218 ImageFrame::kBlendAtopBgcolor, 1000u, true},
219 {10, 54, 32, 33, ImageFrame::kDisposeOverwriteBgcolor,
220 ImageFrame::kBlendAtopBgcolor, 1000u, true},
221 };
222
223 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kFrameParameters); ++i) {
224 const ImageFrame* const frame = decoder->FrameBufferAtIndex(i);
225 EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
226 EXPECT_EQ(kCanvasWidth, frame->Bitmap().width());
227 EXPECT_EQ(kCanvasHeight, frame->Bitmap().height());
228 EXPECT_EQ(kFrameParameters[i].x_offset, frame->OriginalFrameRect().X());
229 EXPECT_EQ(kFrameParameters[i].y_offset, frame->OriginalFrameRect().Y());
230 EXPECT_EQ(kFrameParameters[i].width, frame->OriginalFrameRect().Width());
231 EXPECT_EQ(kFrameParameters[i].height, frame->OriginalFrameRect().Height());
232 EXPECT_EQ(kFrameParameters[i].disposal_method, frame->GetDisposalMethod());
233 EXPECT_EQ(kFrameParameters[i].alpha_blend_source,
234 frame->GetAlphaBlendSource());
235 EXPECT_EQ(kFrameParameters[i].duration, frame->Duration());
236 EXPECT_EQ(kFrameParameters[i].has_alpha, frame->HasAlpha());
237 }
238
239 EXPECT_EQ(WTF_ARRAY_LENGTH(kFrameParameters), decoder->FrameCount());
240 EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
241 }
242
243 TEST(AnimatedWebPTests, parseAndDecodeByteByByte) {
244 TestByteByByteDecode(&CreateDecoder,
245 "/LayoutTests/images/resources/webp-animated.webp", 3u,
246 kAnimationLoopInfinite);
247 TestByteByByteDecode(
248 &CreateDecoder,
249 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp", 13u, 32000);
250 }
251
252 TEST(AnimatedWebPTests, invalidImages) {
253 // ANMF chunk size is smaller than ANMF header size.
254 TestInvalidImage("/LayoutTests/images/resources/invalid-animated-webp.webp",
255 true);
256 // One of the frame rectangles extends outside the image boundary.
257 TestInvalidImage("/LayoutTests/images/resources/invalid-animated-webp3.webp",
258 true);
259 }
260
261 TEST(AnimatedWebPTests, truncatedLastFrame) {
262 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
263
264 RefPtr<SharedBuffer> data =
265 ReadFile("/LayoutTests/images/resources/invalid-animated-webp2.webp");
266 ASSERT_TRUE(data.Get());
267 decoder->SetData(data.Get(), true);
268
269 size_t frame_count = 8;
270 EXPECT_EQ(frame_count, decoder->FrameCount());
271 ImageFrame* frame = decoder->FrameBufferAtIndex(0);
272 ASSERT_TRUE(frame);
273 EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
274 EXPECT_FALSE(decoder->Failed());
275 frame = decoder->FrameBufferAtIndex(frame_count - 1);
276 ASSERT_TRUE(frame);
277 EXPECT_EQ(ImageFrame::kFramePartial, frame->GetStatus());
278 EXPECT_TRUE(decoder->Failed());
279 frame = decoder->FrameBufferAtIndex(0);
280 ASSERT_TRUE(frame);
281 EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
282 }
283
284 TEST(AnimatedWebPTests, truncatedInBetweenFrame) {
285 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
286
287 RefPtr<SharedBuffer> full_data =
288 ReadFile("/LayoutTests/images/resources/invalid-animated-webp4.webp");
289 ASSERT_TRUE(full_data.Get());
290 RefPtr<SharedBuffer> data =
291 SharedBuffer::Create(full_data->Data(), full_data->size() - 1);
292 decoder->SetData(data.Get(), false);
293
294 ImageFrame* frame = decoder->FrameBufferAtIndex(1);
295 ASSERT_TRUE(frame);
296 EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
297 frame = decoder->FrameBufferAtIndex(2);
298 ASSERT_TRUE(frame);
299 EXPECT_EQ(ImageFrame::kFramePartial, frame->GetStatus());
300 EXPECT_TRUE(decoder->Failed());
301 }
302
303 // Tests for a crash that used to happen for a specific file with specific
304 // sequence of method calls.
305 TEST(AnimatedWebPTests, reproCrash) {
306 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
307
308 RefPtr<SharedBuffer> full_data =
309 ReadFile("/LayoutTests/images/resources/invalid_vp8_vp8x.webp");
310 ASSERT_TRUE(full_data.Get());
311
312 // Parse partial data up to which error in bitstream is not detected.
313 const size_t kPartialSize = 32768;
314 ASSERT_GT(full_data->size(), kPartialSize);
315 RefPtr<SharedBuffer> data =
316 SharedBuffer::Create(full_data->Data(), kPartialSize);
317 decoder->SetData(data.Get(), false);
318 EXPECT_EQ(1u, decoder->FrameCount());
319 ImageFrame* frame = decoder->FrameBufferAtIndex(0);
320 ASSERT_TRUE(frame);
321 EXPECT_EQ(ImageFrame::kFramePartial, frame->GetStatus());
322 EXPECT_FALSE(decoder->Failed());
323
324 // Parse full data now. The error in bitstream should now be detected.
325 decoder->SetData(full_data.Get(), true);
326 EXPECT_EQ(1u, decoder->FrameCount());
327 frame = decoder->FrameBufferAtIndex(0);
328 ASSERT_TRUE(frame);
329 EXPECT_EQ(ImageFrame::kFramePartial, frame->GetStatus());
330 EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
331 EXPECT_TRUE(decoder->Failed());
332 }
333
334 TEST(AnimatedWebPTests, progressiveDecode) {
335 TestProgressiveDecoding(&CreateDecoder,
336 "/LayoutTests/images/resources/webp-animated.webp");
337 }
338
339 TEST(AnimatedWebPTests, frameIsCompleteAndDuration) {
340 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
341
342 RefPtr<SharedBuffer> data =
343 ReadFile("/LayoutTests/images/resources/webp-animated.webp");
344 ASSERT_TRUE(data.Get());
345
346 ASSERT_GE(data->size(), 10u);
347 RefPtr<SharedBuffer> temp_data =
348 SharedBuffer::Create(data->Data(), data->size() - 10);
349 decoder->SetData(temp_data.Get(), false);
350
351 EXPECT_EQ(2u, decoder->FrameCount());
352 EXPECT_FALSE(decoder->Failed());
353 EXPECT_TRUE(decoder->FrameIsCompleteAtIndex(0));
354 EXPECT_EQ(1000, decoder->FrameDurationAtIndex(0));
355 EXPECT_TRUE(decoder->FrameIsCompleteAtIndex(1));
356 EXPECT_EQ(500, decoder->FrameDurationAtIndex(1));
357
358 decoder->SetData(data.Get(), true);
359 EXPECT_EQ(3u, decoder->FrameCount());
360 EXPECT_TRUE(decoder->FrameIsCompleteAtIndex(0));
361 EXPECT_EQ(1000, decoder->FrameDurationAtIndex(0));
362 EXPECT_TRUE(decoder->FrameIsCompleteAtIndex(1));
363 EXPECT_EQ(500, decoder->FrameDurationAtIndex(1));
364 EXPECT_TRUE(decoder->FrameIsCompleteAtIndex(2));
365 EXPECT_EQ(1000.0, decoder->FrameDurationAtIndex(2));
366 }
367
368 TEST(AnimatedWebPTests, updateRequiredPreviousFrameAfterFirstDecode) {
369 TestUpdateRequiredPreviousFrameAfterFirstDecode(
370 &CreateDecoder, "/LayoutTests/images/resources/webp-animated.webp");
371 }
372
373 TEST(AnimatedWebPTests, randomFrameDecode) {
374 TestRandomFrameDecode(&CreateDecoder,
375 "/LayoutTests/images/resources/webp-animated.webp");
376 TestRandomFrameDecode(
377 &CreateDecoder,
378 "/LayoutTests/images/resources/webp-animated-opaque.webp");
379 TestRandomFrameDecode(
380 &CreateDecoder, "/LayoutTests/images/resources/webp-animated-large.webp");
381 TestRandomFrameDecode(
382 &CreateDecoder,
383 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp");
384 }
385
386 TEST(AnimatedWebPTests, randomDecodeAfterClearFrameBufferCache) {
387 TestRandomDecodeAfterClearFrameBufferCache(
388 &CreateDecoder, "/LayoutTests/images/resources/webp-animated.webp");
389 TestRandomDecodeAfterClearFrameBufferCache(
390 &CreateDecoder,
391 "/LayoutTests/images/resources/webp-animated-opaque.webp");
392 TestRandomDecodeAfterClearFrameBufferCache(
393 &CreateDecoder, "/LayoutTests/images/resources/webp-animated-large.webp");
394 TestRandomDecodeAfterClearFrameBufferCache(
395 &CreateDecoder,
396 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp");
397 }
398
399 // This test is disabled since it timed out on the Windows bot. See
400 // crrev.com/962853004
401 TEST(AnimatedWebPTests,
402 DISABLED_resumePartialDecodeAfterClearFrameBufferCache) {
403 TestResumePartialDecodeAfterClearFrameBufferCache(
404 &CreateDecoder, "/LayoutTests/images/resources/webp-animated-large.webp");
405 }
406
407 TEST(AnimatedWebPTests, decodeAfterReallocatingData) {
408 TestDecodeAfterReallocatingData(
409 &CreateDecoder, "/LayoutTests/images/resources/webp-animated.webp");
410 TestDecodeAfterReallocatingData(
411 &CreateDecoder,
412 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp");
413 }
414
415 TEST(AnimatedWebPTests, alphaBlending) {
416 TestAlphaBlending(&CreateDecoder,
417 "/LayoutTests/images/resources/webp-animated.webp");
418 TestAlphaBlending(
419 &CreateDecoder,
420 "/LayoutTests/images/resources/webp-animated-semitransparent1.webp");
421 TestAlphaBlending(
422 &CreateDecoder,
423 "/LayoutTests/images/resources/webp-animated-semitransparent2.webp");
424 TestAlphaBlending(
425 &CreateDecoder,
426 "/LayoutTests/images/resources/webp-animated-semitransparent3.webp");
427 TestAlphaBlending(
428 &CreateDecoder,
429 "/LayoutTests/images/resources/webp-animated-semitransparent4.webp");
430 }
431
432 TEST(AnimatedWebPTests, isSizeAvailable) {
433 TestByteByByteSizeAvailable(
434 &CreateDecoder, "/LayoutTests/images/resources/webp-animated.webp", 142u,
435 false, kAnimationLoopInfinite);
436 // FIXME: Add color profile support for animated webp images.
437 TestByteByByteSizeAvailable(
438 &CreateDecoder,
439 "/LayoutTests/images/resources/webp-animated-icc-xmp.webp", 1404u, false,
440 32000);
441 }
442
443 TEST(AnimatedWEBPTests, clearCacheExceptFrameWithAncestors) {
444 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
445
446 RefPtr<SharedBuffer> full_data =
447 ReadFile("/LayoutTests/images/resources/webp-animated.webp");
448 ASSERT_TRUE(full_data.Get());
449 decoder->SetData(full_data.Get(), true);
450
451 ASSERT_EQ(3u, decoder->FrameCount());
452 // We need to store pointers to the image frames, since calling
453 // FrameBufferAtIndex will decode the frame if it is not FrameComplete,
454 // and we want to read the status of the frame without decoding it again.
455 ImageFrame* buffers[3];
456 size_t buffer_sizes[3];
457 for (size_t i = 0; i < decoder->FrameCount(); i++) {
458 buffers[i] = decoder->FrameBufferAtIndex(i);
459 ASSERT_EQ(ImageFrame::kFrameComplete, buffers[i]->GetStatus());
460 buffer_sizes[i] = decoder->FrameBytesAtIndex(i);
461 }
462
463 // Explicitly set the required previous frame for the frames, since this test
464 // is designed on this chain. Whether the frames actually depend on each
465 // other is not important for this test - ClearCacheExceptFrame just looks at
466 // the frame status and the required previous frame.
467 buffers[1]->SetRequiredPreviousFrameIndex(0);
468 buffers[2]->SetRequiredPreviousFrameIndex(1);
469
470 // Clear the cache except for a single frame. All other frames should be
471 // cleared to FrameEmpty, since this frame is FrameComplete.
472 EXPECT_EQ(buffer_sizes[0] + buffer_sizes[2],
473 decoder->ClearCacheExceptFrame(1));
474 EXPECT_EQ(ImageFrame::kFrameEmpty, buffers[0]->GetStatus());
475 EXPECT_EQ(ImageFrame::kFrameComplete, buffers[1]->GetStatus());
476 EXPECT_EQ(ImageFrame::kFrameEmpty, buffers[2]->GetStatus());
477
478 // Verify that the required previous frame is also preserved if the provided
479 // frame is not FrameComplete. The simulated situation is:
480 //
481 // Frame 0 <--------- Frame 1 <--------- Frame 2
482 // FrameComplete depends on FrameComplete depends on FramePartial
483 //
484 // The expected outcome is that frame 1 and frame 2 are preserved, since
485 // frame 1 is necessary to fully decode frame 2.
486 for (size_t i = 0; i < decoder->FrameCount(); i++) {
487 ASSERT_EQ(ImageFrame::kFrameComplete,
488 decoder->FrameBufferAtIndex(i)->GetStatus());
489 }
490 buffers[2]->SetStatus(ImageFrame::kFramePartial);
491 EXPECT_EQ(buffer_sizes[0], decoder->ClearCacheExceptFrame(2));
492 EXPECT_EQ(ImageFrame::kFrameEmpty, buffers[0]->GetStatus());
493 EXPECT_EQ(ImageFrame::kFrameComplete, buffers[1]->GetStatus());
494 EXPECT_EQ(ImageFrame::kFramePartial, buffers[2]->GetStatus());
495
496 // Verify that the nearest FrameComplete required frame is preserved if
497 // earlier required frames in the ancestor list are not FrameComplete. The
498 // simulated situation is:
499 //
500 // Frame 0 <--------- Frame 1 <--------- Frame 2
501 // FrameComplete depends on FrameEmpty depends on FramePartial
502 //
503 // The expected outcome is that frame 0 and frame 2 are preserved. Frame 2
504 // should be preserved since it is the frame passed to ClearCacheExceptFrame.
505 // Frame 0 should be preserved since it is the nearest FrameComplete ancestor.
506 // Thus, since frame 1 is FrameEmpty, no data is cleared in this case.
507 for (size_t i = 0; i < decoder->FrameCount(); i++) {
508 ASSERT_EQ(ImageFrame::kFrameComplete,
509 decoder->FrameBufferAtIndex(i)->GetStatus());
510 }
511 buffers[1]->SetStatus(ImageFrame::kFrameEmpty);
512 buffers[2]->SetStatus(ImageFrame::kFramePartial);
513 EXPECT_EQ(0u, decoder->ClearCacheExceptFrame(2));
514 EXPECT_EQ(ImageFrame::kFrameComplete, buffers[0]->GetStatus());
515 EXPECT_EQ(ImageFrame::kFrameEmpty, buffers[1]->GetStatus());
516 EXPECT_EQ(ImageFrame::kFramePartial, buffers[2]->GetStatus());
517 }
518
519 TEST(StaticWebPTests, truncatedImage) {
520 // VP8 data is truncated.
521 TestInvalidImage("/LayoutTests/images/resources/truncated.webp", false);
522 // Chunk size in RIFF header doesn't match the file size.
523 TestInvalidImage("/LayoutTests/images/resources/truncated2.webp", true);
524 }
525
526 // Regression test for a bug where some valid images were failing to decode
527 // incrementally.
528 TEST(StaticWebPTests, incrementalDecode) {
529 TestByteByByteDecode(&CreateDecoder,
530 "/LayoutTests/images/resources/crbug.364830.webp", 1u,
531 kAnimationNone);
532 }
533
534 TEST(StaticWebPTests, isSizeAvailable) {
535 TestByteByByteSizeAvailable(
536 &CreateDecoder,
537 "/LayoutTests/images/resources/webp-color-profile-lossy.webp", 520u, true,
538 kAnimationNone);
539 TestByteByByteSizeAvailable(&CreateDecoder,
540 "/LayoutTests/images/resources/test.webp", 30u,
541 false, kAnimationNone);
542 }
543
544 TEST(StaticWebPTests, notAnimated) {
545 std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
546 RefPtr<SharedBuffer> data =
547 ReadFile("/LayoutTests/images/resources/webp-color-profile-lossy.webp");
548 ASSERT_TRUE(data.Get());
549 decoder->SetData(data.Get(), true);
550 EXPECT_EQ(1u, decoder->FrameCount());
551 EXPECT_EQ(kAnimationNone, decoder->RepetitionCount());
552 }
553
554 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698