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

Side by Side Diff: Source/WebKit/chromium/tests/WEBPImageDecoderTest.cpp

Issue 13980003: Add animation support for WebP images (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 7 years, 8 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 <gtest/gtest.h> 35 #include "core/page/RuntimeEnabledFeatures.h"
36 #include "core/platform/FileSystem.h" 36 #include "core/platform/FileSystem.h"
37 #include "core/platform/SharedBuffer.h" 37 #include "core/platform/SharedBuffer.h"
38 #include <base/basictypes.h>
39 #include <gtest/gtest.h>
38 #include <public/Platform.h> 40 #include <public/Platform.h>
39 #include <public/WebData.h> 41 #include <public/WebData.h>
40 #include <public/WebSize.h> 42 #include <public/WebSize.h>
41 #include <public/WebUnitTestSupport.h> 43 #include <public/WebUnitTestSupport.h>
42 #include <wtf/OwnPtr.h> 44 #include <wtf/OwnPtr.h>
43 #include <wtf/PassOwnPtr.h> 45 #include <wtf/PassOwnPtr.h>
44 #include <wtf/StringHasher.h> 46 #include <wtf/StringHasher.h>
45 #include <wtf/Vector.h> 47 #include <wtf/Vector.h>
46 48
47 using namespace WebCore; 49 using namespace WebCore;
(...skipping 13 matching lines...) Expand all
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 TEST(GIFImageDecoderTest, decodeTwoFrames) 83 class WEBPImageDecoderTest : public ::testing::Test {
84 protected:
85 virtual void SetUp()
86 {
87 // Enable animated WebP for all the tests.
88 WebCore::RuntimeEnabledFeatures::setAnimatedWebPEnabled(true);
89 }
90 };
91
92 TEST_F(WEBPImageDecoderTest, verifyAnimationParameters)
Noel Gordon 2013/04/29 18:41:57 I like that you added "Animation" to the test name
urvang (Google) 2013/04/30 13:14:15 Changed the name of the fixture class itself to in
82 { 93 {
83 OwnPtr<GIFImageDecoder> decoder(createDecoder()); 94 OwnPtr<WEBPImageDecoder> decoder(createDecoder());
95 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
84 96
85 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 97 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
86 ASSERT_TRUE(data.get()); 98 ASSERT_TRUE(data.get());
87 decoder->setData(data.get(), true); 99 decoder->setData(data.get(), true);
88 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
89 100
90 ImageFrame* frame = decoder->frameBufferAtIndex(0); 101 const int canvasWidth = 11;
91 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 102 const int canvasHeight = 29;
92 EXPECT_EQ(16, frame->getSkBitmap().width()); 103 const int hasAlpha = true;
93 EXPECT_EQ(16, frame->getSkBitmap().height()); 104 const struct AnimParam {
105 int xOffset, yOffset, width, height;
106 ImageFrame::FrameDisposalMethod dispose;
107 unsigned duration;
108 } animParams[] = {
109 { 0, 0, 11, 29, ImageFrame::DisposeKeep, 1000u },
110 { 2, 10, 7, 17, ImageFrame::DisposeKeep, 500u },
111 { 2, 2, 7, 16, ImageFrame::DisposeKeep, 1000u },
112 };
94 113
95 frame = decoder->frameBufferAtIndex(1); 114 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(animParams); ++i) {
96 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 115 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
97 EXPECT_EQ(16, frame->getSkBitmap().width()); 116 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
98 EXPECT_EQ(16, frame->getSkBitmap().height()); 117 EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
118 EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
119 EXPECT_EQ(hasAlpha, frame->hasAlpha());
120 EXPECT_EQ(animParams[i].xOffset, frame->originalFrameRect().x());
121 EXPECT_EQ(animParams[i].yOffset, frame->originalFrameRect().y());
122 EXPECT_EQ(animParams[i].width, frame->originalFrameRect().width());
123 EXPECT_EQ(animParams[i].height, frame->originalFrameRect().height());
124 EXPECT_EQ(animParams[i].dispose, frame->disposalMethod());
125 EXPECT_EQ(animParams[i].duration, frame->duration());
126 }
99 127
100 EXPECT_EQ(2u, decoder->frameCount()); 128 EXPECT_EQ(ARRAYSIZE_UNSAFE(animParams), decoder->frameCount());
101 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); 129 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
102 } 130 }
103 131
104 TEST(GIFImageDecoderTest, parseAndDecode) 132 TEST_F(WEBPImageDecoderTest, parseAndDecodeByteByByte)
105 { 133 {
106 OwnPtr<GIFImageDecoder> decoder(createDecoder()); 134 const struct TestImage {
135 const char* filename;
136 unsigned frameCount;
137 int repetitionCount;
138 } testImages[] = {
139 { "/LayoutTests/fast/images/resources/webp-animated.webp", 3u, cAnimatio nLoopInfinite },
140 { "/LayoutTests/fast/images/resources/webp-animated-icc-xmp.webp", 13u, 32000 },
141 };
107 142
108 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 143 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(testImages); ++i) {
109 ASSERT_TRUE(data.get()); 144 OwnPtr<WEBPImageDecoder> decoder(createDecoder());
110 decoder->setData(data.get(), true); 145 RefPtr<SharedBuffer> data = readFile(testImages[i].filename);
111 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); 146 ASSERT_TRUE(data.get());
112 147
113 // This call will parse the entire file. 148 size_t frameCount = 0;
114 EXPECT_EQ(2u, decoder->frameCount()); 149 size_t framesDecoded = 0;
115 150
116 ImageFrame* frame = decoder->frameBufferAtIndex(0); 151 // Pass data to decoder byte by byte.
117 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 152 for (unsigned length = 1; length <= data->size(); ++length) {
118 EXPECT_EQ(16, frame->getSkBitmap().width()); 153 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), l ength);
119 EXPECT_EQ(16, frame->getSkBitmap().height()); 154 decoder->setData(tempData.get(), length == data->size());
120 155
121 frame = decoder->frameBufferAtIndex(1); 156 EXPECT_LE(frameCount, decoder->frameCount());
122 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 157 frameCount = decoder->frameCount();
123 EXPECT_EQ(16, frame->getSkBitmap().width()); 158
124 EXPECT_EQ(16, frame->getSkBitmap().height()); 159 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
125 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); 160 if (frame && frame->status() == ImageFrame::FrameComplete && framesD ecoded < frameCount)
161 ++framesDecoded;
162 }
163
164 EXPECT_EQ(testImages[i].frameCount, decoder->frameCount());
165 EXPECT_EQ(testImages[i].frameCount, framesDecoded);
166 EXPECT_EQ(testImages[i].repetitionCount, decoder->repetitionCount());
167 }
126 } 168 }
127 169
128 TEST(GIFImageDecoderTest, parseByteByByte) 170 TEST_F(WEBPImageDecoderTest, invalidImage)
129 { 171 {
130 OwnPtr<GIFImageDecoder> decoder(createDecoder()); 172 OwnPtr<WEBPImageDecoder> decoder(createDecoder());
131 173
132 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 174 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/inv alid-animated-webp.webp");
133 ASSERT_TRUE(data.get());
134
135 size_t frameCount = 0;
136
137 // Pass data to decoder byte by byte.
138 for (unsigned length = 1; length <= data->size(); ++length) {
139 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h);
140 decoder->setData(tempData.get(), length == data->size());
141
142 EXPECT_LE(frameCount, decoder->frameCount());
143 frameCount = decoder->frameCount();
144 }
145
146 EXPECT_EQ(2u, decoder->frameCount());
147
148 decoder->frameBufferAtIndex(0);
149 decoder->frameBufferAtIndex(1);
150 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
151 }
152
153 TEST(GIFImageDecoderTest, parseAndDecodeByteByByte)
154 {
155 OwnPtr<GIFImageDecoder> decoder(createDecoder());
156
157 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated-gif-with-offsets.gif");
158 ASSERT_TRUE(data.get());
159
160 size_t frameCount = 0;
161 size_t framesDecoded = 0;
162
163 // Pass data to decoder byte by byte.
164 for (unsigned length = 1; length <= data->size(); ++length) {
165 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h);
166 decoder->setData(tempData.get(), length == data->size());
167
168 EXPECT_LE(frameCount, decoder->frameCount());
169 frameCount = decoder->frameCount();
170
171 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
172 if (frame && frame->status() == ImageFrame::FrameComplete && framesDecod ed < frameCount)
173 ++framesDecoded;
174 }
175
176 EXPECT_EQ(5u, decoder->frameCount());
177 EXPECT_EQ(5u, framesDecoded);
178 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
179 }
180
181 TEST(GIFImageDecoderTest, brokenSecondFrame)
182 {
183 OwnPtr<GIFImageDecoder> decoder(createDecoder());
184
185 RefPtr<SharedBuffer> data = readFile("/Source/WebKit/chromium/tests/data/bro ken.gif");
186 ASSERT_TRUE(data.get()); 175 ASSERT_TRUE(data.get());
187 decoder->setData(data.get(), true); 176 decoder->setData(data.get(), true);
188 177
189 EXPECT_EQ(0u, decoder->frameCount()); 178 EXPECT_EQ(0u, decoder->frameCount());
190 ImageFrame* frame = decoder->frameBufferAtIndex(0); 179 ImageFrame* frame = decoder->frameBufferAtIndex(0);
191 EXPECT_FALSE(frame); 180 EXPECT_FALSE(frame);
192 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); 181 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
193 } 182 }
194 183
195 TEST(GIFImageDecoderTest, progressiveDecode) 184 TEST_F(WEBPImageDecoderTest, progressiveDecode)
196 { 185 {
197 RefPtr<SharedBuffer> fullData = readFile("/Source/WebKit/chromium/tests/data /radient.gif"); 186 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated.webp");
198 ASSERT_TRUE(fullData.get()); 187 ASSERT_TRUE(fullData.get());
199 const size_t fullLength = fullData->size(); 188 const size_t fullLength = fullData->size();
200 189
201 OwnPtr<GIFImageDecoder> decoder; 190 OwnPtr<WEBPImageDecoder> decoder;
202 ImageFrame* frame; 191 ImageFrame* frame;
203 192
204 Vector<unsigned> truncatedHashes; 193 Vector<unsigned> truncatedHashes;
205 Vector<unsigned> progressiveHashes; 194 Vector<unsigned> progressiveHashes;
206 195
207 // Compute hashes when the file is truncated. 196 // Compute hashes when the file is truncated.
208 const size_t increment = 1; 197 const size_t increment = 1;
209 for (size_t i = 1; i <= fullLength; i += increment) { 198 for (size_t i = 1; i <= fullLength; i += increment) {
210 decoder = createDecoder(); 199 decoder = createDecoder();
211 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i); 200 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
(...skipping 25 matching lines...) Expand all
237 match = false; 226 match = false;
238 break; 227 break;
239 } 228 }
240 } 229 }
241 EXPECT_TRUE(match); 230 EXPECT_TRUE(match);
242 } 231 }
243 232
244 #endif 233 #endif
245 234
246 } // namespace 235 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698