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

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: Enclose under runtime flag 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 "GIFImageDecoder.h" 33 #include "WEBPImageDecoder.h"
34 34
35 #include "FileSystem.h" 35 #include "FileSystem.h"
36 #include "SharedBuffer.h" 36 #include "SharedBuffer.h"
37 #include <base/basictypes.h>
37 #include <gtest/gtest.h> 38 #include <gtest/gtest.h>
38 #include <public/Platform.h> 39 #include <public/Platform.h>
39 #include <public/WebData.h> 40 #include <public/WebData.h>
40 #include <public/WebSize.h> 41 #include <public/WebSize.h>
41 #include <public/WebUnitTestSupport.h> 42 #include <public/WebUnitTestSupport.h>
42 #include <wtf/OwnPtr.h> 43 #include <wtf/OwnPtr.h>
43 #include <wtf/PassOwnPtr.h> 44 #include <wtf/PassOwnPtr.h>
44 #include <wtf/StringHasher.h> 45 #include <wtf/StringHasher.h>
45 #include <wtf/Vector.h> 46 #include <wtf/Vector.h>
46 47
(...skipping 14 matching lines...) Expand all
61 return 0; 62 return 0;
62 63
63 PlatformFileHandle handle = openFile(filePath, OpenForRead); 64 PlatformFileHandle handle = openFile(filePath, OpenForRead);
64 int fileLength = static_cast<int>(fileSize); 65 int fileLength = static_cast<int>(fileSize);
65 Vector<char> buffer(fileLength); 66 Vector<char> buffer(fileLength);
66 readFromFile(handle, buffer.data(), fileLength); 67 readFromFile(handle, buffer.data(), fileLength);
67 closeFile(handle); 68 closeFile(handle);
68 return SharedBuffer::adoptVector(buffer); 69 return SharedBuffer::adoptVector(buffer);
69 } 70 }
70 71
71 static PassOwnPtr<GIFImageDecoder> createDecoder() 72 static PassOwnPtr<WEBPImageDecoder> createDecoder()
72 { 73 {
73 return adoptPtr(new GIFImageDecoder(ImageSource::AlphaNotPremultiplied, Imag eSource::GammaAndColorProfileApplied)); 74 return adoptPtr(new WEBPImageDecoder(ImageSource::AlphaNotPremultiplied, Ima geSource::GammaAndColorProfileApplied));
74 } 75 }
75 76
76 static unsigned hashSkBitmap(const SkBitmap& bitmap) 77 static unsigned hashSkBitmap(const SkBitmap& bitmap)
77 { 78 {
78 return StringHasher::hashMemory(bitmap.getPixels(), bitmap.getSize()); 79 return StringHasher::hashMemory(bitmap.getPixels(), bitmap.getSize());
79 } 80 }
80 81
81 TEST(GIFImageDecoderTest, decodeTwoFrames) 82 TEST(WEBPImageDecoderTest, verifyAnimationParameters)
Alpha Left Google 2013/04/25 22:07:12 You can have these as TEST_F such that enabling an
urvang (Google) 2013/04/26 01:46:23 Done.
82 { 83 {
83 OwnPtr<GIFImageDecoder> decoder(createDecoder()); 84 OwnPtr<WEBPImageDecoder> decoder(createDecoder());
85 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
84 86
85 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 87 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/web p-animated.webp");
86 ASSERT_TRUE(data.get()); 88 ASSERT_TRUE(data.get());
87 decoder->setData(data.get(), true); 89 decoder->setData(data.get(), true);
88 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
89 90
90 ImageFrame* frame = decoder->frameBufferAtIndex(0); 91 const int canvasWidth = 11;
91 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 92 const int canvasHeight = 29;
92 EXPECT_EQ(16, frame->getSkBitmap().width()); 93 const int hasAlpha = true;
93 EXPECT_EQ(16, frame->getSkBitmap().height()); 94 const struct AnimParam {
95 int xOffset, yOffset, width, height;
96 ImageFrame::FrameDisposalMethod dispose;
97 unsigned duration;
98 } animParams[] = {
99 { 0, 0, 11, 29, ImageFrame::DisposeKeep, 1000u },
100 { 2, 10, 7, 17, ImageFrame::DisposeKeep, 500u },
101 { 2, 2, 7, 16, ImageFrame::DisposeKeep, 1000u },
102 };
94 103
95 frame = decoder->frameBufferAtIndex(1); 104 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(animParams); ++i) {
96 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 105 const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
97 EXPECT_EQ(16, frame->getSkBitmap().width()); 106 EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
98 EXPECT_EQ(16, frame->getSkBitmap().height()); 107 EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
108 EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
109 EXPECT_EQ(hasAlpha, frame->hasAlpha());
110 EXPECT_EQ(animParams[i].xOffset, frame->originalFrameRect().x());
111 EXPECT_EQ(animParams[i].yOffset, frame->originalFrameRect().y());
112 EXPECT_EQ(animParams[i].width, frame->originalFrameRect().width());
113 EXPECT_EQ(animParams[i].height, frame->originalFrameRect().height());
114 EXPECT_EQ(animParams[i].dispose, frame->disposalMethod());
115 EXPECT_EQ(animParams[i].duration, frame->duration());
116 }
99 117
100 EXPECT_EQ(2u, decoder->frameCount()); 118 EXPECT_EQ(ARRAYSIZE_UNSAFE(animParams), decoder->frameCount());
101 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); 119 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
102 } 120 }
103 121
104 TEST(GIFImageDecoderTest, parseAndDecode) 122 TEST(WEBPImageDecoderTest, parseAndDecodeByteByByte)
105 { 123 {
106 OwnPtr<GIFImageDecoder> decoder(createDecoder()); 124 const struct TestImage {
125 const char* filename;
126 unsigned frameCount;
127 int repetitionCount;
128 } testImages[] = {
129 { "/LayoutTests/fast/images/resources/webp-animated.webp", 3u, cAnimatio nLoopInfinite },
130 { "/LayoutTests/fast/images/resources/webp-animated-icc-xmp.webp", 13u, 32000 },
131 };
107 132
108 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 133 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(testImages); ++i) {
109 ASSERT_TRUE(data.get()); 134 OwnPtr<WEBPImageDecoder> decoder(createDecoder());
110 decoder->setData(data.get(), true); 135 RefPtr<SharedBuffer> data = readFile(testImages[i].filename);
111 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); 136 ASSERT_TRUE(data.get());
112 137
113 // This call will parse the entire file. 138 size_t frameCount = 0;
114 EXPECT_EQ(2u, decoder->frameCount()); 139 size_t framesDecoded = 0;
115 140
116 ImageFrame* frame = decoder->frameBufferAtIndex(0); 141 // Pass data to decoder byte by byte.
117 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 142 for (unsigned length = 1; length <= data->size(); ++length) {
118 EXPECT_EQ(16, frame->getSkBitmap().width()); 143 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), l ength);
119 EXPECT_EQ(16, frame->getSkBitmap().height()); 144 decoder->setData(tempData.get(), length == data->size());
120 145
121 frame = decoder->frameBufferAtIndex(1); 146 EXPECT_LE(frameCount, decoder->frameCount());
122 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); 147 frameCount = decoder->frameCount();
123 EXPECT_EQ(16, frame->getSkBitmap().width()); 148
124 EXPECT_EQ(16, frame->getSkBitmap().height()); 149 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
125 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); 150 if (frame && frame->status() == ImageFrame::FrameComplete && framesD ecoded < frameCount)
151 ++framesDecoded;
152 }
153
154 EXPECT_EQ(testImages[i].frameCount, decoder->frameCount());
155 EXPECT_EQ(testImages[i].frameCount, framesDecoded);
156 EXPECT_EQ(testImages[i].repetitionCount, decoder->repetitionCount());
157 }
126 } 158 }
127 159
128 TEST(GIFImageDecoderTest, parseByteByByte) 160 TEST(WEBPImageDecoderTest, invalidImage)
129 { 161 {
130 OwnPtr<GIFImageDecoder> decoder(createDecoder()); 162 OwnPtr<WEBPImageDecoder> decoder(createDecoder());
131 163
132 RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/ani mated.gif"); 164 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()); 165 ASSERT_TRUE(data.get());
187 decoder->setData(data.get(), true); 166 decoder->setData(data.get(), true);
188 167
189 EXPECT_EQ(0u, decoder->frameCount()); 168 EXPECT_EQ(0u, decoder->frameCount());
190 ImageFrame* frame = decoder->frameBufferAtIndex(0); 169 ImageFrame* frame = decoder->frameBufferAtIndex(0);
191 EXPECT_FALSE(frame); 170 EXPECT_FALSE(frame);
192 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); 171 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
193 } 172 }
194 173
195 TEST(GIFImageDecoderTest, progressiveDecode) 174 TEST(WEBPImageDecoderTest, progressiveDecode)
196 { 175 {
197 RefPtr<SharedBuffer> fullData = readFile("/Source/WebKit/chromium/tests/data /radient.gif"); 176 RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources /webp-animated.webp");
198 ASSERT_TRUE(fullData.get()); 177 ASSERT_TRUE(fullData.get());
199 const size_t fullLength = fullData->size(); 178 const size_t fullLength = fullData->size();
200 179
201 OwnPtr<GIFImageDecoder> decoder; 180 OwnPtr<WEBPImageDecoder> decoder;
202 ImageFrame* frame; 181 ImageFrame* frame;
203 182
204 Vector<unsigned> truncatedHashes; 183 Vector<unsigned> truncatedHashes;
205 Vector<unsigned> progressiveHashes; 184 Vector<unsigned> progressiveHashes;
206 185
207 // Compute hashes when the file is truncated. 186 // Compute hashes when the file is truncated.
208 const size_t increment = 1; 187 const size_t increment = 1;
209 for (size_t i = 1; i <= fullLength; i += increment) { 188 for (size_t i = 1; i <= fullLength; i += increment) {
210 decoder = createDecoder(); 189 decoder = createDecoder();
211 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i); 190 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
(...skipping 25 matching lines...) Expand all
237 match = false; 216 match = false;
238 break; 217 break;
239 } 218 }
240 } 219 }
241 EXPECT_TRUE(match); 220 EXPECT_TRUE(match);
242 } 221 }
243 222
244 #endif 223 #endif
245 224
246 } // namespace 225 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698