Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 | 46 |
| 47 const char decodersTestingDir[] = "Source/platform/image-decoders/testing"; | 47 const char decodersTestingDir[] = "Source/platform/image-decoders/testing"; |
| 48 const char layoutTestResourcesDir[] = "LayoutTests/fast/images/resources"; | 48 const char layoutTestResourcesDir[] = "LayoutTests/fast/images/resources"; |
| 49 const char webTestsDataDir[] = "Source/web/tests/data"; | 49 const char webTestsDataDir[] = "Source/web/tests/data"; |
| 50 | 50 |
| 51 PassOwnPtr<ImageDecoder> createDecoder() | 51 PassOwnPtr<ImageDecoder> createDecoder() |
| 52 { | 52 { |
| 53 return adoptPtr(new GIFImageDecoder(ImageDecoder::AlphaNotPremultiplied, Ima geDecoder::GammaAndColorProfileApplied, ImageDecoder::noDecodedImageByteLimit)); | 53 return adoptPtr(new GIFImageDecoder(ImageDecoder::AlphaNotPremultiplied, Ima geDecoder::GammaAndColorProfileApplied, ImageDecoder::noDecodedImageByteLimit)); |
| 54 } | 54 } |
| 55 | 55 |
| 56 void testRandomFrameDecode(const char* dir, const char* gifFile) | 56 static bool areFramesColorsEqual(ImageFrame* b1, ImageFrame* b2) |
|
scroggo_chromium
2015/12/03 21:47:22
can these be const references?
aleksandar.stojiljkovic
2015/12/22 15:19:55
Done.
| |
| 57 { | |
| 58 // The same premultiply alpha should be set. | |
| 59 if (b1->premultiplyAlpha() != b2->premultiplyAlpha()) | |
| 60 return false; | |
| 61 if (b1->getSkBitmap().width() != b2->getSkBitmap().width() | |
| 62 || b1->getSkBitmap().height() != b2->getSkBitmap().height()) | |
| 63 return false; | |
| 64 | |
| 65 int width = b1->getSkBitmap().width(); | |
|
scroggo_chromium
2015/12/03 21:47:22
Why not set these variables before the last if sta
aleksandar.stojiljkovic
2015/12/22 15:19:55
Done.
| |
| 66 int height = b1->getSkBitmap().height(); | |
| 67 for (int j = 0; j < height; ++j) { | |
| 68 for (int i = 0; i < width; ++i) { | |
| 69 uint32_t c1 = b1->getSkBitmap().getColor(i, j); | |
| 70 uint32_t c2 = b2->getSkBitmap().getColor(i, j); | |
| 71 if (c1 != c2) { | |
| 72 return false; | |
| 73 } | |
| 74 } | |
| 75 } | |
| 76 return true; | |
| 77 } | |
| 78 | |
| 79 void testRandomFrameDecode(const char* dir, const char* gifFile, ImageFrame::Col orType targetType = ImageFrame::N32) | |
| 57 { | 80 { |
| 58 SCOPED_TRACE(gifFile); | 81 SCOPED_TRACE(gifFile); |
| 59 | 82 |
| 83 RefPtr<SharedBuffer> fullData = readFile(dir, gifFile); | |
| 84 ASSERT_TRUE(fullData.get()); | |
| 85 Vector<unsigned> baselineHashes; | |
| 86 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes, targ etType); | |
| 87 size_t frameCount = baselineHashes.size(); | |
| 88 | |
| 89 // Random decoding should get the same results as sequential decoding. | |
| 90 OwnPtr<ImageDecoder> decoder = createDecoder(); | |
| 91 decoder->setData(fullData.get(), true); | |
| 92 const size_t skippingStep = 5; | |
| 93 for (size_t i = 0; i < skippingStep; ++i) { | |
| 94 for (size_t j = i; j < frameCount; j += skippingStep) { | |
| 95 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); | |
| 96 ImageFrame* frame = decoder->frameBufferAtIndex(j, targetType); | |
| 97 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->getSkBitmap())); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 // Decoding in reverse order. | |
| 102 decoder = createDecoder(); | |
| 103 decoder->setData(fullData.get(), true); | |
| 104 for (size_t i = frameCount; i; --i) { | |
| 105 SCOPED_TRACE(testing::Message() << "Reverse i:" << i); | |
| 106 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1, targetType); | |
| 107 EXPECT_EQ(baselineHashes[i - 1], hashBitmap(frame->getSkBitmap())); | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 void testRandomDecodeAfterClearFrameBufferCache(const char* dir, const char* gif File, ImageFrame::ColorType targetType = ImageFrame::N32) | |
| 112 { | |
| 113 SCOPED_TRACE(gifFile); | |
| 114 | |
| 115 RefPtr<SharedBuffer> data = readFile(dir, gifFile); | |
| 116 ASSERT_TRUE(data.get()); | |
| 117 Vector<unsigned> baselineHashes; | |
| 118 createDecodingBaseline(&createDecoder, data.get(), &baselineHashes, targetTy pe); | |
| 119 size_t frameCount = baselineHashes.size(); | |
| 120 | |
| 121 OwnPtr<ImageDecoder> decoder = createDecoder(); | |
| 122 decoder->setData(data.get(), true); | |
| 123 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce ptFrame) { | |
| 124 decoder->clearCacheExceptFrame(clearExceptFrame); | |
| 125 const size_t skippingStep = 5; | |
| 126 for (size_t i = 0; i < skippingStep; ++i) { | |
| 127 for (size_t j = 0; j < frameCount; j += skippingStep) { | |
| 128 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); | |
| 129 ImageFrame* frame = decoder->frameBufferAtIndex(j, targetType); | |
| 130 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->getSkBitmap())); | |
| 131 } | |
| 132 } | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 void testRandomFrameDecodeCompare(const char* dir, const char* gifFile) | |
| 137 { | |
| 138 SCOPED_TRACE(gifFile); | |
| 139 | |
| 60 RefPtr<SharedBuffer> fullData = readFile(dir, gifFile); | 140 RefPtr<SharedBuffer> fullData = readFile(dir, gifFile); |
| 61 ASSERT_TRUE(fullData.get()); | 141 ASSERT_TRUE(fullData.get()); |
| 62 Vector<unsigned> baselineHashes; | 142 Vector<unsigned> baselineHashes; |
| 63 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes); | 143 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes); |
| 64 size_t frameCount = baselineHashes.size(); | 144 size_t frameCount = baselineHashes.size(); |
| 65 | 145 |
| 66 // Random decoding should get the same results as sequential decoding. | 146 // Random decoding should get the same results as sequential decoding. |
| 67 OwnPtr<ImageDecoder> decoder = createDecoder(); | 147 OwnPtr<ImageDecoder> decoder = createDecoder(); |
| 148 // Test Index8 and RGBA through the same scenario. | |
| 149 OwnPtr<ImageDecoder> decoderI8 = createDecoder(); | |
| 150 | |
| 68 decoder->setData(fullData.get(), true); | 151 decoder->setData(fullData.get(), true); |
| 152 decoderI8->setData(fullData.get(), true); | |
| 69 const size_t skippingStep = 5; | 153 const size_t skippingStep = 5; |
| 70 for (size_t i = 0; i < skippingStep; ++i) { | 154 for (size_t i = 0; i < skippingStep; ++i) { |
| 71 for (size_t j = i; j < frameCount; j += skippingStep) { | 155 for (size_t j = i; j < frameCount; j += skippingStep) { |
| 72 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); | 156 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); |
| 73 ImageFrame* frame = decoder->frameBufferAtIndex(j); | 157 ImageFrame* frame = decoder->frameBufferAtIndex(j); |
| 74 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->getSkBitmap())); | 158 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->getSkBitmap())); |
| 159 ImageFrame* frameI8 = decoderI8->frameBufferAtIndex(j, ImageFrame::I ndex8); | |
| 160 ASSERT_TRUE(areFramesColorsEqual(frame, frameI8)); | |
| 75 } | 161 } |
| 76 } | 162 } |
| 77 | 163 |
| 78 // Decoding in reverse order. | 164 // Decoding in reverse order. |
| 79 decoder = createDecoder(); | 165 decoder = createDecoder(); |
| 166 decoderI8 = createDecoder(); | |
| 80 decoder->setData(fullData.get(), true); | 167 decoder->setData(fullData.get(), true); |
| 168 decoderI8->setData(fullData.get(), true); | |
| 81 for (size_t i = frameCount; i; --i) { | 169 for (size_t i = frameCount; i; --i) { |
| 82 SCOPED_TRACE(testing::Message() << "Reverse i:" << i); | 170 SCOPED_TRACE(testing::Message() << "Reverse i:" << i); |
| 83 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1); | 171 ImageFrame* frame = decoder->frameBufferAtIndex(i - 1); |
| 84 EXPECT_EQ(baselineHashes[i - 1], hashBitmap(frame->getSkBitmap())); | 172 EXPECT_EQ(baselineHashes[i - 1], hashBitmap(frame->getSkBitmap())); |
| 173 ImageFrame* frameI8 = decoderI8->frameBufferAtIndex(i - 1, ImageFrame::I ndex8); | |
| 174 ASSERT_TRUE(areFramesColorsEqual(frame, frameI8)); | |
| 85 } | 175 } |
| 86 } | 176 } |
| 87 | 177 |
| 88 void testRandomDecodeAfterClearFrameBufferCache(const char* dir, const char* gif File) | 178 void testRandomDecodeAfterClearFrameBufferCacheCompare(const char* dir, const ch ar* gifFile) |
| 89 { | 179 { |
| 90 SCOPED_TRACE(gifFile); | 180 SCOPED_TRACE(gifFile); |
| 91 | 181 |
| 92 RefPtr<SharedBuffer> data = readFile(dir, gifFile); | 182 RefPtr<SharedBuffer> data = readFile(dir, gifFile); |
| 93 ASSERT_TRUE(data.get()); | 183 ASSERT_TRUE(data.get()); |
| 94 Vector<unsigned> baselineHashes; | 184 Vector<unsigned> baselineHashes; |
| 95 createDecodingBaseline(&createDecoder, data.get(), &baselineHashes); | 185 createDecodingBaseline(&createDecoder, data.get(), &baselineHashes); |
| 96 size_t frameCount = baselineHashes.size(); | 186 size_t frameCount = baselineHashes.size(); |
| 97 | 187 |
| 98 OwnPtr<ImageDecoder> decoder = createDecoder(); | 188 OwnPtr<ImageDecoder> decoder = createDecoder(); |
| 189 // Test Index8 and RGBA through the same scenario. | |
| 190 OwnPtr<ImageDecoder> decoderI8 = createDecoder(); | |
| 99 decoder->setData(data.get(), true); | 191 decoder->setData(data.get(), true); |
| 192 decoderI8->setData(data.get(), true); | |
| 100 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce ptFrame) { | 193 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce ptFrame) { |
| 101 decoder->clearCacheExceptFrame(clearExceptFrame); | 194 decoder->clearCacheExceptFrame(clearExceptFrame); |
| 195 decoderI8->clearCacheExceptFrame(clearExceptFrame); | |
| 102 const size_t skippingStep = 5; | 196 const size_t skippingStep = 5; |
| 103 for (size_t i = 0; i < skippingStep; ++i) { | 197 for (size_t i = 0; i < skippingStep; ++i) { |
| 104 for (size_t j = 0; j < frameCount; j += skippingStep) { | 198 for (size_t j = 0; j < frameCount; j += (i + 2)) { |
| 105 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); | 199 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); |
| 106 ImageFrame* frame = decoder->frameBufferAtIndex(j); | 200 ImageFrame* frame = decoder->frameBufferAtIndex(j); |
| 107 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->getSkBitmap())); | 201 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->getSkBitmap())); |
| 202 ImageFrame* frameI8 = decoderI8->frameBufferAtIndex(j, ImageFram e::Index8); | |
| 203 ASSERT_TRUE(areFramesColorsEqual(frame, frameI8)); | |
| 108 } | 204 } |
| 109 } | 205 } |
| 110 } | 206 } |
| 111 } | 207 } |
| 112 | 208 |
| 113 } // anonymous namespace | 209 } // anonymous namespace |
| 114 | 210 |
| 115 TEST(GIFImageDecoderTest, decodeTwoFrames) | 211 TEST(GIFImageDecoderTest, decodeTwoFrames) |
| 116 { | 212 { |
| 117 OwnPtr<ImageDecoder> decoder = createDecoder(); | 213 OwnPtr<ImageDecoder> decoder = createDecoder(); |
| 214 OwnPtr<ImageDecoder> decoderI8 = createDecoder(); | |
| 118 | 215 |
| 119 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif") ; | 216 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif") ; |
| 120 ASSERT_TRUE(data.get()); | 217 ASSERT_TRUE(data.get()); |
| 121 decoder->setData(data.get(), true); | 218 decoder->setData(data.get(), true); |
| 219 decoderI8->setData(data.get(), true); | |
| 122 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); | 220 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); |
| 123 | 221 |
| 124 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 222 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
| 125 uint32_t generationID0 = frame->getSkBitmap().getGenerationID(); | 223 uint32_t generationID0 = frame->getSkBitmap().getGenerationID(); |
| 126 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); | 224 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); |
| 127 EXPECT_EQ(16, frame->getSkBitmap().width()); | 225 EXPECT_EQ(16, frame->getSkBitmap().width()); |
| 128 EXPECT_EQ(16, frame->getSkBitmap().height()); | 226 EXPECT_EQ(16, frame->getSkBitmap().height()); |
| 129 | 227 |
| 228 ImageFrame* frameI8 = decoderI8->frameBufferAtIndex(0, ImageFrame::Index8); | |
| 229 generationID0 = frameI8->getSkBitmap().getGenerationID(); | |
| 230 EXPECT_EQ(ImageFrame::FrameComplete, frameI8->status()); | |
| 231 EXPECT_EQ(16, frameI8->getSkBitmap().width()); | |
| 232 EXPECT_EQ(16, frameI8->getSkBitmap().height()); | |
| 233 | |
| 234 ASSERT_TRUE(areFramesColorsEqual(frame, frameI8)); | |
| 235 | |
| 130 frame = decoder->frameBufferAtIndex(1); | 236 frame = decoder->frameBufferAtIndex(1); |
| 131 uint32_t generationID1 = frame->getSkBitmap().getGenerationID(); | 237 uint32_t generationID1 = frame->getSkBitmap().getGenerationID(); |
| 132 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); | 238 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); |
| 133 EXPECT_EQ(16, frame->getSkBitmap().width()); | 239 EXPECT_EQ(16, frame->getSkBitmap().width()); |
| 134 EXPECT_EQ(16, frame->getSkBitmap().height()); | 240 EXPECT_EQ(16, frame->getSkBitmap().height()); |
| 135 EXPECT_TRUE(generationID0 != generationID1); | 241 EXPECT_TRUE(generationID0 != generationID1); |
| 136 | 242 |
| 137 EXPECT_EQ(2u, decoder->frameCount()); | 243 EXPECT_EQ(2u, decoder->frameCount()); |
| 138 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 244 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
| 245 | |
| 246 frameI8 = decoderI8->frameBufferAtIndex(1, ImageFrame::Index8); | |
| 247 ASSERT_TRUE(areFramesColorsEqual(frame, frameI8)); | |
| 248 EXPECT_EQ(2u, decoderI8->frameCount()); | |
| 249 EXPECT_EQ(cAnimationLoopInfinite, decoderI8->repetitionCount()); | |
| 139 } | 250 } |
| 140 | 251 |
| 141 TEST(GIFImageDecoderTest, parseAndDecode) | 252 TEST(GIFImageDecoderTest, parseAndDecode) |
| 142 { | 253 { |
| 143 OwnPtr<ImageDecoder> decoder = createDecoder(); | 254 OwnPtr<ImageDecoder> decoder = createDecoder(); |
| 144 | 255 |
| 145 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif") ; | 256 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif") ; |
| 146 ASSERT_TRUE(data.get()); | 257 ASSERT_TRUE(data.get()); |
| 147 decoder->setData(data.get(), true); | 258 decoder->setData(data.get(), true); |
| 148 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); | 259 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); |
| 149 | 260 |
| 150 // This call will parse the entire file. | 261 // This call will parse the entire file. |
| 151 EXPECT_EQ(2u, decoder->frameCount()); | 262 EXPECT_EQ(2u, decoder->frameCount()); |
| 152 | 263 |
| 153 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 264 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
| 154 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); | 265 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); |
| 155 EXPECT_EQ(16, frame->getSkBitmap().width()); | 266 EXPECT_EQ(16, frame->getSkBitmap().width()); |
| 156 EXPECT_EQ(16, frame->getSkBitmap().height()); | 267 EXPECT_EQ(16, frame->getSkBitmap().height()); |
| 157 | 268 |
| 158 frame = decoder->frameBufferAtIndex(1); | 269 frame = decoder->frameBufferAtIndex(1); |
| 159 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); | 270 EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); |
| 160 EXPECT_EQ(16, frame->getSkBitmap().width()); | 271 EXPECT_EQ(16, frame->getSkBitmap().width()); |
| 161 EXPECT_EQ(16, frame->getSkBitmap().height()); | 272 EXPECT_EQ(16, frame->getSkBitmap().height()); |
| 162 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 273 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
| 163 } | 274 } |
| 164 | 275 |
| 165 TEST(GIFImageDecoderTest, parseByteByByte) | 276 TEST(GIFImageDecoderTest, parseByteByByte) |
| 166 { | 277 { |
| 167 OwnPtr<ImageDecoder> decoder = createDecoder(); | 278 OwnPtr<ImageDecoder> decoder = createDecoder(); |
| 279 OwnPtr<ImageDecoder> decoderI8 = createDecoder(); | |
| 168 | 280 |
| 169 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif") ; | 281 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif") ; |
| 170 ASSERT_TRUE(data.get()); | 282 ASSERT_TRUE(data.get()); |
| 171 | 283 |
| 172 size_t frameCount = 0; | 284 size_t frameCount = 0; |
| 173 | 285 |
| 174 // Pass data to decoder byte by byte. | 286 // Pass data to decoder byte by byte. |
| 175 for (size_t length = 1; length <= data->size(); ++length) { | 287 for (size_t length = 1; length <= data->size(); ++length) { |
| 176 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h); | 288 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h); |
| 177 decoder->setData(tempData.get(), length == data->size()); | 289 decoder->setData(tempData.get(), length == data->size()); |
| 290 decoderI8->setData(tempData.get(), length == data->size()); | |
| 178 | 291 |
| 179 EXPECT_LE(frameCount, decoder->frameCount()); | 292 EXPECT_LE(frameCount, decoder->frameCount()); |
| 293 EXPECT_LE(frameCount, decoderI8->frameCount()); | |
| 294 EXPECT_EQ(decoder->frameCount(), decoderI8->frameCount()); | |
| 180 frameCount = decoder->frameCount(); | 295 frameCount = decoder->frameCount(); |
| 181 } | 296 } |
| 182 | 297 |
| 183 EXPECT_EQ(2u, decoder->frameCount()); | 298 EXPECT_EQ(2u, decoder->frameCount()); |
| 184 | 299 |
| 185 decoder->frameBufferAtIndex(0); | 300 decoder->frameBufferAtIndex(0); |
| 186 decoder->frameBufferAtIndex(1); | 301 decoder->frameBufferAtIndex(1); |
| 187 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 302 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
| 188 } | 303 } |
| 189 | 304 |
| 190 TEST(GIFImageDecoderTest, parseAndDecodeByteByByte) | 305 TEST(GIFImageDecoderTest, parseAndDecodeByteByByte) |
| 191 { | 306 { |
| 192 OwnPtr<ImageDecoder> decoder = createDecoder(); | 307 OwnPtr<ImageDecoder> decoder = createDecoder(); |
| 308 OwnPtr<ImageDecoder> decoderI8 = createDecoder(); | |
| 193 | 309 |
| 194 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated-gif-w ith-offsets.gif"); | 310 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated-gif-w ith-offsets.gif"); |
| 195 ASSERT_TRUE(data.get()); | 311 ASSERT_TRUE(data.get()); |
| 196 | 312 |
| 197 size_t frameCount = 0; | 313 size_t frameCount = 0; |
| 198 size_t framesDecoded = 0; | 314 size_t framesDecoded = 0; |
| 199 | 315 |
| 200 // Pass data to decoder byte by byte. | 316 // Pass data to decoder byte by byte. |
| 201 for (size_t length = 1; length <= data->size(); ++length) { | 317 for (size_t length = 1; length <= data->size(); ++length) { |
| 202 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h); | 318 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt h); |
| 203 decoder->setData(tempData.get(), length == data->size()); | 319 decoder->setData(tempData.get(), length == data->size()); |
| 320 decoderI8->setData(tempData.get(), length == data->size()); | |
| 204 | 321 |
| 205 EXPECT_LE(frameCount, decoder->frameCount()); | 322 EXPECT_LE(frameCount, decoder->frameCount()); |
| 206 frameCount = decoder->frameCount(); | 323 frameCount = decoder->frameCount(); |
| 324 EXPECT_EQ(frameCount, decoderI8->frameCount()); | |
| 207 | 325 |
| 208 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1); | 326 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1); |
| 209 if (frame && frame->status() == ImageFrame::FrameComplete && framesDecod ed < frameCount) | 327 if (frame && frame->status() == ImageFrame::FrameComplete && framesDecod ed < frameCount) |
| 210 ++framesDecoded; | 328 ++framesDecoded; |
| 329 | |
| 330 ImageFrame* frameI8 = decoderI8->frameBufferAtIndex(frameCount - 1, Imag eFrame::Index8); | |
| 331 ASSERT_TRUE(!(frame || frameI8) || areFramesColorsEqual(frame, frameI8)) ; | |
| 211 } | 332 } |
| 212 | 333 |
| 213 EXPECT_EQ(5u, decoder->frameCount()); | 334 EXPECT_EQ(5u, decoder->frameCount()); |
| 214 EXPECT_EQ(5u, framesDecoded); | 335 EXPECT_EQ(5u, framesDecoded); |
| 215 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 336 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
| 216 } | 337 } |
| 217 | 338 |
| 218 TEST(GIFImageDecoderTest, brokenSecondFrame) | 339 TEST(GIFImageDecoderTest, brokenSecondFrame) |
| 219 { | 340 { |
| 220 OwnPtr<ImageDecoder> decoder = createDecoder(); | 341 OwnPtr<ImageDecoder> decoder = createDecoder(); |
| 221 | 342 |
| 222 RefPtr<SharedBuffer> data = readFile(webTestsDataDir, "broken.gif"); | 343 RefPtr<SharedBuffer> data = readFile(webTestsDataDir, "broken.gif"); |
| 223 ASSERT_TRUE(data.get()); | 344 ASSERT_TRUE(data.get()); |
| 224 decoder->setData(data.get(), true); | 345 decoder->setData(data.get(), true); |
| 225 | 346 |
| 226 // One frame is detected but cannot be decoded. | 347 // One frame is detected but cannot be decoded. |
| 227 EXPECT_EQ(1u, decoder->frameCount()); | 348 EXPECT_EQ(1u, decoder->frameCount()); |
| 228 ImageFrame* frame = decoder->frameBufferAtIndex(1); | 349 ImageFrame* frame = decoder->frameBufferAtIndex(1); |
| 229 EXPECT_FALSE(frame); | 350 EXPECT_FALSE(frame); |
| 351 frame = decoder->frameBufferAtIndex(1, ImageFrame::Index8); | |
| 352 EXPECT_FALSE(frame); | |
| 230 } | 353 } |
| 231 | 354 |
| 232 TEST(GIFImageDecoderTest, progressiveDecode) | 355 TEST(GIFImageDecoderTest, progressiveDecode) |
| 233 { | 356 { |
| 234 RefPtr<SharedBuffer> fullData = readFile(webTestsDataDir, "radient.gif"); | 357 RefPtr<SharedBuffer> fullData = readFile(webTestsDataDir, "radient.gif"); |
| 235 ASSERT_TRUE(fullData.get()); | 358 ASSERT_TRUE(fullData.get()); |
| 236 const size_t fullLength = fullData->size(); | 359 const size_t fullLength = fullData->size(); |
| 237 | 360 |
| 238 OwnPtr<ImageDecoder> decoder; | 361 OwnPtr<ImageDecoder> decoder; |
| 239 ImageFrame* frame; | 362 ImageFrame* frame; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 testDecoder->setData(testData.get(), true); | 477 testDecoder->setData(testData.get(), true); |
| 355 EXPECT_EQ(1u, testDecoder->frameCount()); | 478 EXPECT_EQ(1u, testDecoder->frameCount()); |
| 356 ImageFrame* testFrame = testDecoder->frameBufferAtIndex(0); | 479 ImageFrame* testFrame = testDecoder->frameBufferAtIndex(0); |
| 357 ASSERT(testFrame); | 480 ASSERT(testFrame); |
| 358 | 481 |
| 359 EXPECT_EQ(hashBitmap(referenceFrame->getSkBitmap()), hashBitmap(testFrame->g etSkBitmap())); | 482 EXPECT_EQ(hashBitmap(referenceFrame->getSkBitmap()), hashBitmap(testFrame->g etSkBitmap())); |
| 360 } | 483 } |
| 361 | 484 |
| 362 TEST(GIFImageDecoderTest, updateRequiredPreviousFrameAfterFirstDecode) | 485 TEST(GIFImageDecoderTest, updateRequiredPreviousFrameAfterFirstDecode) |
| 363 { | 486 { |
| 364 OwnPtr<ImageDecoder> decoder = createDecoder(); | 487 const ImageFrame::ColorType targetTypes[] = { ImageFrame::N32, ImageFrame::I ndex8 }; |
| 488 for (ImageFrame::ColorType targetType : targetTypes) { | |
| 489 OwnPtr<ImageDecoder> decoder = createDecoder(); | |
| 365 | 490 |
| 366 RefPtr<SharedBuffer> fullData = readFile(layoutTestResourcesDir, "animated-1 0color.gif"); | 491 RefPtr<SharedBuffer> fullData = readFile(layoutTestResourcesDir, "animat ed-10color.gif"); |
| 367 ASSERT_TRUE(fullData.get()); | 492 ASSERT_TRUE(fullData.get()); |
| 368 | 493 |
| 369 // Give it data that is enough to parse but not decode in order to check the status | 494 // Give it data that is enough to parse but not decode in order to check the status |
| 370 // of requiredPreviousFrameIndex before decoding. | 495 // of requiredPreviousFrameIndex before decoding. |
| 371 size_t partialSize = 1; | 496 size_t partialSize = 1; |
| 372 do { | 497 do { |
| 373 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize); | 498 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), p artialSize); |
| 374 decoder->setData(data.get(), false); | 499 decoder->setData(data.get(), false); |
| 375 ++partialSize; | 500 ++partialSize; |
| 376 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty); | 501 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0, target Type)->status() == ImageFrame::FrameEmpty); |
| 377 | 502 |
| 378 EXPECT_EQ(kNotFound, decoder->frameBufferAtIndex(0)->requiredPreviousFrameIn dex()); | 503 EXPECT_EQ(kNotFound, decoder->frameBufferAtIndex(0, targetType)->require dPreviousFrameIndex()); |
| 379 unsigned frameCount = decoder->frameCount(); | 504 unsigned frameCount = decoder->frameCount(); |
| 380 for (size_t i = 1; i < frameCount; ++i) | 505 for (size_t i = 1; i < frameCount; ++i) |
| 381 EXPECT_EQ(i - 1, decoder->frameBufferAtIndex(i)->requiredPreviousFrameIn dex()); | 506 EXPECT_EQ(i - 1, decoder->frameBufferAtIndex(i, targetType)->require dPreviousFrameIndex()); |
| 382 | 507 |
| 383 decoder->setData(fullData.get(), true); | 508 decoder->setData(fullData.get(), true); |
| 384 for (size_t i = 0; i < frameCount; ++i) | 509 for (size_t i = 0; i < frameCount; ++i) |
| 385 EXPECT_EQ(kNotFound, decoder->frameBufferAtIndex(i)->requiredPreviousFra meIndex()); | 510 EXPECT_EQ(kNotFound, decoder->frameBufferAtIndex(i, targetType)->req uiredPreviousFrameIndex()); |
| 511 } | |
| 386 } | 512 } |
| 387 | 513 |
| 388 TEST(GIFImageDecoderTest, randomFrameDecode) | 514 TEST(GIFImageDecoderTest, randomFrameDecode) |
| 389 { | 515 { |
| 390 // Single frame image. | 516 // Single frame image. |
| 391 testRandomFrameDecode(webTestsDataDir, "radient.gif"); | 517 testRandomFrameDecode(webTestsDataDir, "radient.gif"); |
| 392 // Multiple frame images. | 518 // Multiple frame images. |
| 393 testRandomFrameDecode(layoutTestResourcesDir, "animated-gif-with-offsets.gif "); | 519 testRandomFrameDecode(layoutTestResourcesDir, "animated-gif-with-offsets.gif "); |
| 394 testRandomFrameDecode(layoutTestResourcesDir, "animated-10color.gif"); | 520 testRandomFrameDecode(layoutTestResourcesDir, "animated-10color.gif"); |
| 395 } | 521 } |
| 396 | 522 |
| 523 TEST(GIFImageDecoderTest, randomFrameDecodeCompare) | |
| 524 { | |
| 525 // Single frame image. | |
| 526 testRandomFrameDecodeCompare(webTestsDataDir, "radient.gif"); | |
| 527 // Multiple frame images. | |
| 528 testRandomFrameDecodeCompare(layoutTestResourcesDir, "animated-gif-with-offs ets.gif"); | |
| 529 testRandomFrameDecodeCompare(layoutTestResourcesDir, "animated-10color.gif") ; | |
| 530 } | |
| 531 | |
| 397 TEST(GIFImageDecoderTest, randomDecodeAfterClearFrameBufferCache) | 532 TEST(GIFImageDecoderTest, randomDecodeAfterClearFrameBufferCache) |
| 398 { | 533 { |
| 399 // Single frame image. | 534 // Single frame image. |
| 400 testRandomDecodeAfterClearFrameBufferCache(webTestsDataDir, "radient.gif"); | 535 testRandomDecodeAfterClearFrameBufferCache(webTestsDataDir, "radient.gif"); |
| 401 // Multiple frame images. | 536 // Multiple frame images. |
| 402 testRandomDecodeAfterClearFrameBufferCache(layoutTestResourcesDir, "animated -gif-with-offsets.gif"); | 537 testRandomDecodeAfterClearFrameBufferCache(layoutTestResourcesDir, "animated -gif-with-offsets.gif"); |
| 403 testRandomDecodeAfterClearFrameBufferCache(layoutTestResourcesDir, "animated -10color.gif"); | 538 testRandomDecodeAfterClearFrameBufferCache(layoutTestResourcesDir, "animated -10color.gif"); |
| 404 } | 539 } |
| 405 | 540 |
| 541 TEST(GIFImageDecoderTest, randomDecodeAfterClearFrameBufferCacheCompare) | |
| 542 { | |
| 543 // Single frame image. | |
| 544 testRandomDecodeAfterClearFrameBufferCacheCompare(webTestsDataDir, "radient. gif"); | |
| 545 // Multiple frame images with offset. All frames depend to frame 0. | |
| 546 testRandomDecodeAfterClearFrameBufferCacheCompare(layoutTestResourcesDir, "a nimated-gif-with-offsets.gif"); | |
| 547 testRandomDecodeAfterClearFrameBufferCacheCompare(layoutTestResourcesDir, "a nimated-10color.gif"); | |
| 548 } | |
| 549 | |
| 406 TEST(GIFImageDecoderTest, resumePartialDecodeAfterClearFrameBufferCache) | 550 TEST(GIFImageDecoderTest, resumePartialDecodeAfterClearFrameBufferCache) |
| 407 { | 551 { |
| 408 RefPtr<SharedBuffer> fullData = readFile(layoutTestResourcesDir, "animated-1 0color.gif"); | 552 const ImageFrame::ColorType targetTypes[] = { ImageFrame::N32, ImageFrame::I ndex8 }; |
| 409 ASSERT_TRUE(fullData.get()); | 553 for (ImageFrame::ColorType targetType : targetTypes) { |
| 410 Vector<unsigned> baselineHashes; | 554 RefPtr<SharedBuffer> fullData = readFile(layoutTestResourcesDir, "animat ed-10color.gif"); |
| 411 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes); | 555 ASSERT_TRUE(fullData.get()); |
| 412 size_t frameCount = baselineHashes.size(); | 556 Vector<unsigned> baselineHashes; |
| 557 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes, targetType); | |
| 558 size_t frameCount = baselineHashes.size(); | |
| 413 | 559 |
| 414 OwnPtr<ImageDecoder> decoder = createDecoder(); | 560 OwnPtr<ImageDecoder> decoder = createDecoder(); |
| 415 | 561 |
| 416 // Let frame 0 be partially decoded. | 562 // Let frame 0 be partially decoded. |
| 417 size_t partialSize = 1; | 563 size_t partialSize = 1; |
| 418 do { | 564 do { |
| 419 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti alSize); | 565 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), p artialSize); |
| 420 decoder->setData(data.get(), false); | 566 decoder->setData(data.get(), false); |
| 421 ++partialSize; | 567 ++partialSize; |
| 422 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty); | 568 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0, target Type)->status() == ImageFrame::FrameEmpty); |
| 423 | 569 |
| 424 // Skip to the last frame and clear. | 570 // Skip to the last frame and clear. |
| 425 decoder->setData(fullData.get(), true); | 571 decoder->setData(fullData.get(), true); |
| 426 EXPECT_EQ(frameCount, decoder->frameCount()); | 572 EXPECT_EQ(frameCount, decoder->frameCount()); |
| 427 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1); | 573 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1, targ etType); |
| 428 EXPECT_EQ(baselineHashes[frameCount - 1], hashBitmap(lastFrame->getSkBitmap( ))); | 574 EXPECT_EQ(baselineHashes[frameCount - 1], hashBitmap(lastFrame->getSkBit map())); |
| 429 decoder->clearCacheExceptFrame(kNotFound); | 575 decoder->clearCacheExceptFrame(kNotFound); |
| 430 | 576 |
| 431 // Resume decoding of the first frame. | 577 // Resume decoding of the first frame. |
| 432 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0); | 578 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0, targetType); |
| 433 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->status()); | 579 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->status()); |
| 434 EXPECT_EQ(baselineHashes[0], hashBitmap(firstFrame->getSkBitmap())); | 580 EXPECT_EQ(baselineHashes[0], hashBitmap(firstFrame->getSkBitmap())); |
| 581 } | |
| 435 } | 582 } |
| 436 | 583 |
| 437 // The first LZW codes in the image are invalid values that try to create a loop | 584 // The first LZW codes in the image are invalid values that try to create a loop |
| 438 // in the dictionary. Decoding should fail, but not infinitely loop or corrupt m emory. | 585 // in the dictionary. Decoding should fail, but not infinitely loop or corrupt m emory. |
| 439 TEST(GIFImageDecoderTest, badInitialCode) | 586 TEST(GIFImageDecoderTest, badInitialCode) |
| 440 { | 587 { |
| 441 RefPtr<SharedBuffer> testData = readFile(decodersTestingDir, "bad-initial-co de.gif"); | 588 RefPtr<SharedBuffer> testData = readFile(decodersTestingDir, "bad-initial-co de.gif"); |
| 442 ASSERT_TRUE(testData.get()); | 589 ASSERT_TRUE(testData.get()); |
| 443 | 590 |
| 444 OwnPtr<ImageDecoder> testDecoder = createDecoder(); | 591 OwnPtr<ImageDecoder> testDecoder = createDecoder(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 494 if (decoder->isSizeAvailable() && !frameSize.width() && !frameSize.heigh t()) { | 641 if (decoder->isSizeAvailable() && !frameSize.width() && !frameSize.heigh t()) { |
| 495 frameSize = decoder->decodedSize(); | 642 frameSize = decoder->decodedSize(); |
| 496 continue; | 643 continue; |
| 497 } | 644 } |
| 498 | 645 |
| 499 ASSERT_EQ(frameSize.width(), decoder->decodedSize().width()); | 646 ASSERT_EQ(frameSize.width(), decoder->decodedSize().width()); |
| 500 ASSERT_EQ(frameSize.height(), decoder->decodedSize().height()); | 647 ASSERT_EQ(frameSize.height(), decoder->decodedSize().height()); |
| 501 } | 648 } |
| 502 } | 649 } |
| 503 | 650 |
| 651 #define BENCHMARK_DECODE(dir, file, title, count)\ | |
| 652 TEST(GIFImageDecoderTest, tempBench_decodeIndex8##title##warmuprun)\ | |
| 653 {\ | |
| 654 testRandomDecodeAfterClearFrameBufferCache(dir, file);\ | |
| 655 }\ | |
| 656 TEST(GIFImageDecoderTest, tempBench_decodeN32##title##_x##count) \ | |
| 657 {\ | |
| 658 for (int i = 0; i < count; ++i)\ | |
| 659 testRandomDecodeAfterClearFrameBufferCache(dir, file);\ | |
| 660 }\ | |
| 661 \ | |
| 662 TEST(GIFImageDecoderTest, tempBench_decodeIndex8##title##_x##count)\ | |
| 663 {\ | |
| 664 for (int i = 0; i < count; ++i)\ | |
| 665 testRandomDecodeAfterClearFrameBufferCache(dir, file, ImageFrame::Index8 );\ | |
| 666 }\ | |
| 667 | |
| 668 BENCHMARK_DECODE(layoutTestResourcesDir, "animated-10color.gif", animated_10colo r_gif, 5) | |
| 669 BENCHMARK_DECODE(webTestsDataDir, "radient.gif", radient_gif, 10) | |
| 670 BENCHMARK_DECODE(layoutTestResourcesDir, "animated-gif-with-offsets.gif", animat ed_gif_with_offsets_gif, 5) | |
| 671 BENCHMARK_DECODE(layoutTestResourcesDir, "animated.gif", animated_gif, 10) | |
| 672 BENCHMARK_DECODE(layoutTestResourcesDir, "quicksort.gif", quicksort_gif, 5) | |
| 673 BENCHMARK_DECODE(layoutTestResourcesDir, "large-gif-checkerboard.gif", large_gif _checkerboard_gif, 5) | |
| 674 BENCHMARK_DECODE(layoutTestResourcesDir, "3dolph.gif", 3dolph_gif, 5) | |
| 675 // BENCHMARK_DECODE(layoutTestResourcesDir, "disneypixar-disney-pixar-jTXvL4Ljak YI8.gif", disneypixar_disney_pixar_jTXvL4LjakYI8_gif, 1) | |
| 676 // BENCHMARK_DECODE(webTestsDataDir, "issue_476531_AqLvXJh.gif", issue_476531_Aq LvXJh_gif, 1) | |
| 677 | |
| 504 } // namespace blink | 678 } // namespace blink |
| OLD | NEW |