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

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: Create and use zeroFillPixelData() Created 7 years, 5 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 | « Source/core/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
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 "wtf/dtoa/utils.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 #if !OS(ANDROID) 52 #if !OS(ANDROID)
51 53
52 namespace { 54 namespace {
53 55
54 PassRefPtr<SharedBuffer> readFile(const char* fileName) 56 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 PassOwnPtr<GIFImageDecoder> createDecoder() 73 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 unsigned hashSkBitmap(const SkBitmap& bitmap) 78 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 void createDecodingBaseline(SharedBuffer* data, Vector<unsigned>* baselineHashes ) 83 void createDecodingBaseline(SharedBuffer* data, Vector<unsigned>* baselineHashes )
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 void testRandomFrameDecode(const char* gifFile) 94 void testRandomFrameDecode(const char* webpFile)
93 { 95 {
94 SCOPED_TRACE(gifFile); 96 SCOPED_TRACE(webpFile);
95 97
96 RefPtr<SharedBuffer> fullData = readFile(gifFile); 98 RefPtr<SharedBuffer> fullData = readFile(webpFile);
97 ASSERT_TRUE(fullData.get()); 99 ASSERT_TRUE(fullData.get());
98 Vector<unsigned> baselineHashes; 100 Vector<unsigned> baselineHashes;
99 createDecodingBaseline(fullData.get(), &baselineHashes); 101 createDecodingBaseline(fullData.get(), &baselineHashes);
100 size_t frameCount = baselineHashes.size(); 102 size_t frameCount = baselineHashes.size();
101 103
102 // Random decoding should get the same results as sequential decoding. 104 // Random decoding should get the same results as sequential decoding.
103 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 105 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
104 decoder->setData(fullData.get(), true); 106 decoder->setData(fullData.get(), true);
105 const size_t skippingStep = 5; 107 const size_t skippingStep = 5;
106 for (size_t i = 0; i < skippingStep; ++i) { 108 for (size_t i = 0; i < skippingStep; ++i) {
107 for (size_t j = i; j < frameCount; j += skippingStep) { 109 for (size_t j = i; j < frameCount; j += skippingStep) {
108 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); 110 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
109 ImageFrame* frame = decoder->frameBufferAtIndex(j); 111 ImageFrame* frame = decoder->frameBufferAtIndex(j);
110 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap())); 112 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap()));
111 } 113 }
112 } 114 }
113 115
114 // Decoding in reverse order. 116 // Decoding in reverse order.
115 decoder = createDecoder(); 117 decoder = createDecoder();
116 decoder->setData(fullData.get(), true); 118 decoder->setData(fullData.get(), true);
117 for (size_t i = frameCount; i; --i) { 119 for (size_t i = frameCount; i; --i) {
118 SCOPED_TRACE(testing::Message() << "Reverse i:" << i); 120 SCOPED_TRACE(testing::Message() << "Reverse i:" << i);
119 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1); 121 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1);
120 EXPECT_EQ(baselineHashes[i - 1], hashSkBitmap(frame->getSkBitmap())); 122 EXPECT_EQ(baselineHashes[i - 1], hashSkBitmap(frame->getSkBitmap()));
121 } 123 }
122 } 124 }
123 125
124 void testRandomDecodeAfterClearFrameBufferCache(const char* gifFile) 126 void testRandomDecodeAfterClearFrameBufferCache(const char* webpFile)
125 { 127 {
126 SCOPED_TRACE(gifFile); 128 SCOPED_TRACE(webpFile);
127 129
128 RefPtr<SharedBuffer> data = readFile(gifFile); 130 RefPtr<SharedBuffer> data = readFile(webpFile);
129 ASSERT_TRUE(data.get()); 131 ASSERT_TRUE(data.get());
130 Vector<unsigned> baselineHashes; 132 Vector<unsigned> baselineHashes;
131 createDecodingBaseline(data.get(), &baselineHashes); 133 createDecodingBaseline(data.get(), &baselineHashes);
132 size_t frameCount = baselineHashes.size(); 134 size_t frameCount = baselineHashes.size();
133 135
134 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 136 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
135 decoder->setData(data.get(), true); 137 decoder->setData(data.get(), true);
136 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce ptFrame) { 138 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce ptFrame) {
137 decoder->clearCacheExceptFrame(clearExceptFrame); 139 decoder->clearCacheExceptFrame(clearExceptFrame);
138 const size_t skippingStep = 5; 140 const size_t skippingStep = 5;
139 for (size_t i = 0; i < skippingStep; ++i) { 141 for (size_t i = 0; i < skippingStep; ++i) {
140 for (size_t j = 0; j < frameCount; j += skippingStep) { 142 for (size_t j = 0; j < frameCount; j += skippingStep) {
141 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); 143 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
142 ImageFrame* frame = decoder->frameBufferAtIndex(j); 144 ImageFrame* frame = decoder->frameBufferAtIndex(j);
143 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap())) ; 145 EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap())) ;
144 } 146 }
145 } 147 }
146 } 148 }
147 } 149 }
148 150
149 } // namespace 151 } // namespace
150 152
151 TEST(GIFImageDecoderTest, decodeTwoFrames) 153 class AnimatedWebPTests : public ::testing::Test {
154 protected:
155 virtual void SetUp()
156 {
157 // Enable animated WebP for all the tests.
158 WebCore::RuntimeEnabledFeatures::setAnimatedWebPEnabled(true);
159 }
160 };
161
162 TEST_F(AnimatedWebPTests, verifyAnimationParametersTransparentImage)
152 { 163 {
153 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 164 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
165 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
154 166
155 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 167 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
156 ASSERT_TRUE(data.get()); 168 ASSERT_TRUE(data.get());
157 decoder->setData(data.get(), true); 169 decoder->setData(data.get(), true);
158 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
159 170
160 ImageFrame* frame = decoder->frameBufferAtIndex(0); 171 const int canvasWidth = 11;
161 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 172 const int canvasHeight = 29;
162 EXPECT_EQ(16, frame->getSkBitmap().width()); 173 const struct AnimParam {
163 EXPECT_EQ(16, frame->getSkBitmap().height()); 174 int xOffset, yOffset, width, height;
175 ImageFrame::FrameDisposalMethod dispose;
176 unsigned duration;
177 bool hasAlpha;
178 } frameParameters[] = {
179 { 0, 0, 11, 29, ImageFrame::DisposeKeep, 1000u, true },
180 { 2, 10, 7, 17, ImageFrame::DisposeKeep, 500u, true },
181 { 2, 2, 7, 16, ImageFrame::DisposeKeep, 1000u, true },
182 };
164 183
165 frame = decoder->frameBufferAtIndex(1); 184 for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) {
166 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 185 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
167 EXPECT_EQ(16, frame->getSkBitmap().width()); 186 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
168 EXPECT_EQ(16, frame->getSkBitmap().height()); 187 EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
188 EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
189 EXPECT_EQ(frameParameters[i].xOffset, frame->originalFrameRect().x());
190 EXPECT_EQ(frameParameters[i].yOffset, frame->originalFrameRect().y());
191 EXPECT_EQ(frameParameters[i].width, frame->originalFrameRect().width());
192 EXPECT_EQ(frameParameters[i].height, frame->originalFrameRect().height() );
193 EXPECT_EQ(frameParameters[i].dispose, frame->disposalMethod());
194 EXPECT_EQ(frameParameters[i].duration, frame->duration());
195 EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha());
196 }
169 197
170 EXPECT_EQ(2u, decoder->frameCount()); 198 EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount());
171 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); 199 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
172 } 200 }
173 201
174 TEST(GIFImageDecoderTest, parseAndDecode) 202 TEST_F(AnimatedWebPTests, verifyAnimationParametersOpaqueFramesTransparentBackgr ound)
175 { 203 {
176 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 204 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
205 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
177 206
178 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 207 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated-opaque.webp");
179 ASSERT_TRUE(data.get()); 208 ASSERT_TRUE(data.get());
180 decoder->setData(data.get(), true); 209 decoder->setData(data.get(), true);
181 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
182 210
183 // This call will parse the entire file. 211 const int canvasWidth = 94;
184 EXPECT_EQ(2u, decoder->frameCount()); 212 const int canvasHeight = 87;
213 const struct AnimParam {
214 int xOffset, yOffset, width, height;
215 ImageFrame::FrameDisposalMethod dispose;
216 unsigned duration;
217 bool hasAlpha;
218 } frameParameters[] = {
219 { 4, 10, 33, 32, ImageFrame::DisposeOverwriteBgcolor, 1000u, true },
220 { 34, 30, 33, 32, ImageFrame::DisposeOverwriteBgcolor, 1000u, true },
221 { 62, 50, 32, 32, ImageFrame::DisposeOverwriteBgcolor, 1000u, true },
222 { 10, 54, 32, 33, ImageFrame::DisposeOverwriteBgcolor, 1000u, true },
223 };
185 224
186 ImageFrame* frame = decoder->frameBufferAtIndex(0); 225 for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) {
187 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 226 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
188 EXPECT_EQ(16, frame->getSkBitmap().width()); 227 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
189 EXPECT_EQ(16, frame->getSkBitmap().height()); 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].dispose, frame->disposalMethod());
235 EXPECT_EQ(frameParameters[i].duration, frame->duration());
236 EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha());
237 }
190 238
191 frame = decoder->frameBufferAtIndex(1); 239 EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount());
192 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
193 EXPECT_EQ(16, frame->getSkBitmap().width());
194 EXPECT_EQ(16, frame->getSkBitmap().height());
195 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); 240 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
196 } 241 }
197 242
198 TEST(GIFImageDecoderTest, parseByteByByte) 243 TEST_F(AnimatedWebPTests, parseAndDecodeByteByByte)
199 { 244 {
200 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 245 const struct TestImage {
246 const char* filename;
247 unsigned frameCount;
248 int repetitionCount;
249 } testImages[] = {
250 { "/LayoutTests/fast/images/resources/webp-animated.webp", 3u, cAnimatio nLoopInfinite },
251 { "/LayoutTests/fast/images/resources/webp-animated-icc-xmp.webp", 13u, 32000 },
252 };
201 253
202 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 254 for (size_t i = 0; i < ARRAY_SIZE(testImages); ++i) {
203 ASSERT_TRUE(data.get()); 255 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
256 RefPtr<SharedBuffer> data = readFile(testImages[i].filename);
257 ASSERT_TRUE(data.get());
204 258
205 size_t frameCount = 0; 259 size_t frameCount = 0;
260 size_t framesDecoded = 0;
206 261
207 // Pass data to decoder byte by byte. 262 // Pass data to decoder byte by byte.
208 for (size_t length = 1; length <= data->size(); ++length) { 263 for (size_t length = 1; length <= data->size(); ++length) {
209 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h); 264 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), l ength);
210 decoder->setData(tempData.get(), length == data->size()); 265 decoder->setData(tempData.get(), length == data->size());
211 266
212 EXPECT_LE(frameCount, decoder->frameCount()); 267 EXPECT_LE(frameCount, decoder->frameCount());
213 frameCount = decoder->frameCount(); 268 frameCount = decoder->frameCount();
269
270 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
271 if (frame && frame->status() == ImageFrame::FrameComplete && framesD ecoded < frameCount)
272 ++framesDecoded;
273 }
274
275 EXPECT_EQ(testImages[i].frameCount, decoder->frameCount());
276 EXPECT_EQ(testImages[i].frameCount, framesDecoded);
277 EXPECT_EQ(testImages[i].repetitionCount, decoder->repetitionCount());
214 } 278 }
215
216 EXPECT_EQ(2u, decoder->frameCount());
217
218 decoder->frameBufferAtIndex(0);
219 decoder->frameBufferAtIndex(1);
220 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
221 } 279 }
222 280
223 TEST(GIFImageDecoderTest, parseAndDecodeByteByByte) 281 TEST_F(AnimatedWebPTests, invalidImage)
224 { 282 {
225 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 283 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
226 284
227 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated-gif-with-offsets.gif"); 285 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/inv alid-animated-webp.webp");
228 ASSERT_TRUE(data.get());
229
230 size_t frameCount = 0;
231 size_t framesDecoded = 0;
232
233 // Pass data to decoder byte by byte.
234 for (size_t length = 1; length <= data->size(); ++length) {
235 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h);
236 decoder->setData(tempData.get(), length == data->size());
237
238 EXPECT_LE(frameCount, decoder->frameCount());
239 frameCount = decoder->frameCount();
240
241 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
242 if (frame && frame->status() == ImageFrame::FrameComplete && framesDecod ed < frameCount)
243 ++framesDecoded;
244 }
245
246 EXPECT_EQ(5u, decoder->frameCount());
247 EXPECT_EQ(5u, framesDecoded);
248 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
249 }
250
251 TEST(GIFImageDecoderTest, brokenSecondFrame)
252 {
253 OwnPtr<GIFImageDecoder> decoder = createDecoder();
254
255 RefPtr<SharedBuffer> data = readFile("/Source/WebKit/chromium/tests/data/bro ken.gif");
256 ASSERT_TRUE(data.get()); 286 ASSERT_TRUE(data.get());
257 decoder->setData(data.get(), true); 287 decoder->setData(data.get(), true);
258 288
259 // One frame is detected but cannot be decoded. 289 EXPECT_EQ(0u, decoder->frameCount());
260 EXPECT_EQ(1u, decoder->frameCount()); 290 ImageFrame* frame = decoder->frameBufferAtIndex(0);
261 ImageFrame* frame = decoder->frameBufferAtIndex(1);
262 EXPECT_FALSE(frame); 291 EXPECT_FALSE(frame);
292 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
263 } 293 }
264 294
265 TEST(GIFImageDecoderTest, progressiveDecode) 295 TEST_F(AnimatedWebPTests, progressiveDecode)
266 { 296 {
267 RefPtr<SharedBuffer> fullData = readFile("/Source/WebKit/chromium/tests/data /radient.gif"); 297 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated.webp");
268 ASSERT_TRUE(fullData.get()); 298 ASSERT_TRUE(fullData.get());
269 const size_t fullLength = fullData->size(); 299 const size_t fullLength = fullData->size();
270 300
271 OwnPtr<GIFImageDecoder> decoder; 301 OwnPtr<WEBPImageDecoder> decoder;
272 ImageFrame* frame; 302 ImageFrame* frame;
273 303
274 Vector<unsigned> truncatedHashes; 304 Vector<unsigned> truncatedHashes;
275 Vector<unsigned> progressiveHashes; 305 Vector<unsigned> progressiveHashes;
276 306
277 // Compute hashes when the file is truncated. 307 // Compute hashes when the file is truncated.
278 const size_t increment = 1; 308 const size_t increment = 1;
279 for (size_t i = 1; i <= fullLength; i += increment) { 309 for (size_t i = 1; i <= fullLength; i += increment) {
280 decoder = createDecoder(); 310 decoder = createDecoder();
281 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i); 311 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
(...skipping 22 matching lines...) Expand all
304 bool match = true; 334 bool match = true;
305 for (size_t i = 0; i < truncatedHashes.size(); ++i) { 335 for (size_t i = 0; i < truncatedHashes.size(); ++i) {
306 if (truncatedHashes[i] != progressiveHashes[i]) { 336 if (truncatedHashes[i] != progressiveHashes[i]) {
307 match = false; 337 match = false;
308 break; 338 break;
309 } 339 }
310 } 340 }
311 EXPECT_TRUE(match); 341 EXPECT_TRUE(match);
312 } 342 }
313 343
314 TEST(GIFImageDecoderTest, allDataReceivedTruncation) 344 TEST_F(AnimatedWebPTests, frameIsCompleteAndDuration)
315 { 345 {
316 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 346 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
317 347
318 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 348 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
319 ASSERT_TRUE(data.get()); 349 ASSERT_TRUE(data.get());
320 350
321 ASSERT_GE(data->size(), 10u); 351 ASSERT_GE(data->size(), 10u);
322 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz e() - 10);
323 decoder->setData(tempData.get(), true);
324
325 EXPECT_EQ(2u, decoder->frameCount());
326 EXPECT_FALSE(decoder->failed());
327
328 decoder->frameBufferAtIndex(0);
329 EXPECT_FALSE(decoder->failed());
330 decoder->frameBufferAtIndex(1);
331 EXPECT_TRUE(decoder->failed());
332 }
333
334 TEST(GIFImageDecoderTest, frameIsComplete)
335 {
336 OwnPtr<GIFImageDecoder> decoder = createDecoder();
337
338 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif");
339 ASSERT_TRUE(data.get());
340 decoder->setData(data.get(), true);
341
342 EXPECT_EQ(2u, decoder->frameCount());
343 EXPECT_FALSE(decoder->failed());
344 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
345 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
346 }
347
348 TEST(GIFImageDecoderTest, frameIsCompleteLoading)
349 {
350 OwnPtr<GIFImageDecoder> decoder = createDecoder();
351
352 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif");
353 ASSERT_TRUE(data.get());
354
355 ASSERT_GE(data->size(), 10u);
356 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz e() - 10); 352 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz e() - 10);
357 decoder->setData(tempData.get(), false); 353 decoder->setData(tempData.get(), false);
358 354
359 EXPECT_EQ(2u, decoder->frameCount()); 355 EXPECT_EQ(2u, decoder->frameCount());
360 EXPECT_FALSE(decoder->failed()); 356 EXPECT_FALSE(decoder->failed());
361 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); 357 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
362 EXPECT_FALSE(decoder->frameIsCompleteAtIndex(1)); 358 EXPECT_EQ(1000, decoder->frameDurationAtIndex(0));
359 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
360 EXPECT_EQ(500, decoder->frameDurationAtIndex(1));
363 361
364 decoder->setData(data.get(), true); 362 decoder->setData(data.get(), true);
365 EXPECT_EQ(2u, decoder->frameCount()); 363 EXPECT_EQ(3u, decoder->frameCount());
366 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); 364 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
365 EXPECT_EQ(1000, decoder->frameDurationAtIndex(0));
367 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1)); 366 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
367 EXPECT_EQ(500, decoder->frameDurationAtIndex(1));
368 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(2));
369 EXPECT_EQ(1000.0, decoder->frameDurationAtIndex(2));
368 } 370 }
369 371
370 TEST(GIFImageDecoderTest, badTerminator) 372 TEST_F(AnimatedWebPTests, updateRequiredPreviousFrameAfterFirstDecode)
371 { 373 {
372 RefPtr<SharedBuffer> referenceData = readFile("/Source/WebKit/chromium/tests /data/radient.gif"); 374 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
373 RefPtr<SharedBuffer> testData = readFile("/Source/WebKit/chromium/tests/data /radient-bad-terminator.gif");
374 ASSERT_TRUE(referenceData.get());
375 ASSERT_TRUE(testData.get());
376 375
377 OwnPtr<GIFImageDecoder> referenceDecoder(createDecoder()); 376 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated.webp");
378 referenceDecoder->setData(referenceData.get(), true);
379 EXPECT_EQ(1u, referenceDecoder->frameCount());
380 ImageFrame* referenceFrame = referenceDecoder->frameBufferAtIndex(0);
381 ASSERT(referenceFrame);
382
383 OwnPtr<GIFImageDecoder> testDecoder(createDecoder());
384 testDecoder->setData(testData.get(), true);
385 EXPECT_EQ(1u, testDecoder->frameCount());
386 ImageFrame* testFrame = testDecoder->frameBufferAtIndex(0);
387 ASSERT(testFrame);
388
389 EXPECT_EQ(hashSkBitmap(referenceFrame->getSkBitmap()), hashSkBitmap(testFram e->getSkBitmap()));
390 }
391
392 TEST(GIFImageDecoderTest, updateRequiredPreviousFrameAfterFirstDecode)
393 {
394 OwnPtr<GIFImageDecoder> decoder = createDecoder();
395
396 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /animated-10color.gif");
397 ASSERT_TRUE(fullData.get()); 377 ASSERT_TRUE(fullData.get());
398 378
399 // Give it data that is enough to parse but not decode in order to check the status 379 // Give it data that is enough to parse but not decode in order to check the status
400 // of requiredPreviousFrameIndex before decoding. 380 // of requiredPreviousFrameIndex before decoding.
401 size_t partialSize = 1; 381 size_t partialSize = 1;
402 do { 382 do {
403 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize); 383 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize);
404 decoder->setData(data.get(), false); 384 decoder->setData(data.get(), false);
405 ++partialSize; 385 ++partialSize;
406 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty); 386 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty);
407 387
408 EXPECT_EQ(notFound, decoder->frameBufferAtIndex(0)->requiredPreviousFrameInd ex()); 388 EXPECT_EQ(notFound, decoder->frameBufferAtIndex(0)->requiredPreviousFrameInd ex());
409 unsigned frameCount = decoder->frameCount(); 389 unsigned frameCount = decoder->frameCount();
410 for (size_t i = 1; i < frameCount; ++i) 390 for (size_t i = 1; i < frameCount; ++i)
411 EXPECT_EQ(i - 1, decoder->frameBufferAtIndex(i)->requiredPreviousFrameIn dex()); 391 EXPECT_EQ(i - 1, decoder->frameBufferAtIndex(i)->requiredPreviousFrameIn dex());
412 392
413 decoder->setData(fullData.get(), true); 393 decoder->setData(fullData.get(), true);
414 for (size_t i = 0; i < frameCount; ++i) 394 for (size_t i = 0; i < frameCount; ++i)
415 EXPECT_EQ(notFound, decoder->frameBufferAtIndex(i)->requiredPreviousFram eIndex()); 395 EXPECT_EQ(notFound, decoder->frameBufferAtIndex(i)->requiredPreviousFram eIndex());
416 } 396 }
417 397
418 TEST(GIFImageDecoderTest, randomFrameDecode) 398 TEST_F(AnimatedWebPTests, randomFrameDecode)
419 { 399 {
420 // Single frame image. 400 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated.webp ");
421 testRandomFrameDecode("/Source/WebKit/chromium/tests/data/radient.gif"); 401 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-opaq ue.webp");
422 // Multiple frame images. 402 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-larg e.webp");
423 testRandomFrameDecode("/LayoutTests/fast/images/resources/animated-gif-with- offsets.gif"); 403 testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-icc- xmp.webp");
424 testRandomFrameDecode("/LayoutTests/fast/images/resources/animated-10color.g if");
425 } 404 }
426 405
427 TEST(GIFImageDecoderTest, randomDecodeAfterClearFrameBufferCache) 406 TEST_F(AnimatedWebPTests, randomDecodeAfterClearFrameBufferCache)
428 { 407 {
429 // Single frame image. 408 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated.webp");
430 testRandomDecodeAfterClearFrameBufferCache("/Source/WebKit/chromium/tests/da ta/radient.gif"); 409 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated-opaque.webp");
431 // Multiple frame images. 410 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated-large.webp");
432 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/animated-gif-with-offsets.gif"); 411 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/webp-animated-icc-xmp.webp");
433 testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resourc es/animated-10color.gif");
434 } 412 }
435 413
436 TEST(GIFImageDecoderTest, resumePartialDecodeAfterClearFrameBufferCache) 414 TEST_F(AnimatedWebPTests, resumePartialDecodeAfterClearFrameBufferCache)
437 { 415 {
438 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /animated-10color.gif"); 416 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated-large.webp");
439 ASSERT_TRUE(fullData.get()); 417 ASSERT_TRUE(fullData.get());
440 Vector<unsigned> baselineHashes; 418 Vector<unsigned> baselineHashes;
441 createDecodingBaseline(fullData.get(), &baselineHashes); 419 createDecodingBaseline(fullData.get(), &baselineHashes);
442 size_t frameCount = baselineHashes.size(); 420 size_t frameCount = baselineHashes.size();
443 421
444 OwnPtr<GIFImageDecoder> decoder = createDecoder(); 422 OwnPtr<WEBPImageDecoder> decoder = createDecoder();
445 423
446 // Let frame 0 be partially decoded. 424 // Let frame 0 be partially decoded.
447 size_t partialSize = 1; 425 size_t partialSize = 1;
448 do { 426 do {
449 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize); 427 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize);
450 decoder->setData(data.get(), false); 428 decoder->setData(data.get(), false);
451 ++partialSize; 429 ++partialSize;
452 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty); 430 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty);
453 431
454 // Skip to the last frame and clear. 432 // Skip to the last frame and clear.
455 decoder->setData(fullData.get(), true); 433 decoder->setData(fullData.get(), true);
456 EXPECT_EQ(frameCount, decoder->frameCount()); 434 EXPECT_EQ(frameCount, decoder->frameCount());
457 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1); 435 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1);
458 EXPECT_EQ(baselineHashes[frameCount - 1], hashSkBitmap(lastFrame->getSkBitma p())); 436 EXPECT_EQ(baselineHashes[frameCount - 1], hashSkBitmap(lastFrame->getSkBitma p()));
459 decoder->clearCacheExceptFrame(notFound); 437 decoder->clearCacheExceptFrame(notFound);
460 438
461 // Resume decoding of the first frame. 439 // Resume decoding of the first frame.
462 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0); 440 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0);
463 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->status()); 441 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->status());
464 EXPECT_EQ(baselineHashes[0], hashSkBitmap(firstFrame->getSkBitmap())); 442 EXPECT_EQ(baselineHashes[0], hashSkBitmap(firstFrame->getSkBitmap()));
465 } 443 }
466 444
467 #endif 445 #endif
446
OLDNEW
« no previous file with comments | « Source/core/platform/image-decoders/webp/WEBPImageDecoder.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698