OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "Resources.h" | 8 #include "Resources.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkCodec.h" | 10 #include "SkCodec.h" |
11 #include "SkMD5.h" | 11 #include "SkMD5.h" |
12 #include "SkRandom.h" | 12 #include "SkRandom.h" |
13 #include "SkScaledCodec.h" | 13 #include "SkScaledCodec.h" |
14 #include "SkScanlineDecoder.h" | |
15 #include "Test.h" | 14 #include "Test.h" |
16 | 15 |
17 static SkStreamAsset* resource(const char path[]) { | 16 static SkStreamAsset* resource(const char path[]) { |
18 SkString fullPath = GetResourcePath(path); | 17 SkString fullPath = GetResourcePath(path); |
19 return SkStream::NewFromFile(fullPath.c_str()); | 18 return SkStream::NewFromFile(fullPath.c_str()); |
20 } | 19 } |
21 | 20 |
22 static void md5(const SkBitmap& bm, SkMD5::Digest* digest) { | 21 static void md5(const SkBitmap& bm, SkMD5::Digest* digest) { |
23 SkAutoLockPixels autoLockPixels(bm); | 22 SkAutoLockPixels autoLockPixels(bm); |
24 SkASSERT(bm.getPixels()); | 23 SkASSERT(bm.getPixels()); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
140 } else { | 139 } else { |
141 otherAt = kPremul_SkAlphaType; | 140 otherAt = kPremul_SkAlphaType; |
142 } | 141 } |
143 // The other non-opaque alpha type should always succeed, but not ma tch. | 142 // The other non-opaque alpha type should always succeed, but not ma tch. |
144 test_info(r, codec, info.makeAlphaType(otherAt), SkCodec::kSuccess, nullptr); | 143 test_info(r, codec, info.makeAlphaType(otherAt), SkCodec::kSuccess, nullptr); |
145 } | 144 } |
146 } | 145 } |
147 | 146 |
148 // Scanline decoding follows. | 147 // Scanline decoding follows. |
149 | 148 |
150 stream.reset(resource(path)); | 149 // Need to call start() first. |
151 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder( | 150 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) |
152 SkScanlineDecoder::NewFromStream(stream.detach())); | 151 == SkCodec::kScanlineDecodingNotStarted); |
scroggo
2015/09/25 16:07:50
Again, these can check for 0/false once we change
| |
152 REPORTER_ASSERT(r, codec->skipScanlines(1) | |
153 == SkCodec::kScanlineDecodingNotStarted); | |
154 | |
155 const SkCodec::Result startResult = codec->start(info); | |
153 if (supportsScanlineDecoding) { | 156 if (supportsScanlineDecoding) { |
154 bm.eraseColor(SK_ColorYELLOW); | 157 bm.eraseColor(SK_ColorYELLOW); |
155 REPORTER_ASSERT(r, scanlineDecoder); | |
156 | 158 |
157 REPORTER_ASSERT(r, scanlineDecoder->start(info) == SkCodec::kSuccess); | 159 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); |
158 | 160 |
159 for (int y = 0; y < info.height(); y++) { | 161 for (int y = 0; y < info.height(); y++) { |
160 result = scanlineDecoder->getScanlines(bm.getAddr(0, y), 1, 0); | 162 result = codec->getScanlines(bm.getAddr(0, y), 1, 0); |
161 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | 163 REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
162 } | 164 } |
163 // verify that scanline decoding gives the same result. | 165 // verify that scanline decoding gives the same result. |
164 if (SkScanlineDecoder::kTopDown_SkScanlineOrder == scanlineDecoder->getS canlineOrder()) { | 166 if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) { |
165 compare_to_good_digest(r, digest, bm); | 167 compare_to_good_digest(r, digest, bm); |
166 } | 168 } |
169 | |
170 // Cannot continue to decode scanlines beyond the end | |
msarett
2015/09/28 14:48:50
+1 for new tests
| |
171 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) | |
172 == SkCodec::kInvalidParameters); | |
173 | |
174 // Interrupting a scanline decode with a full decode starts from | |
175 // scratch | |
176 REPORTER_ASSERT(r, codec->start(info) == SkCodec::kSuccess); | |
177 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) | |
178 == SkCodec::kSuccess); | |
179 REPORTER_ASSERT(r, codec->getPixels(bm.info(), bm.getPixels(), bm.rowByt es()) | |
180 == SkCodec::kSuccess); | |
181 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) | |
182 == SkCodec::kScanlineDecodingNotStarted); | |
183 REPORTER_ASSERT(r, codec->skipScanlines(1) | |
184 == SkCodec::kScanlineDecodingNotStarted); | |
167 } else { | 185 } else { |
168 REPORTER_ASSERT(r, !scanlineDecoder); | 186 REPORTER_ASSERT(r, startResult == SkCodec::kUnimplemented); |
169 } | 187 } |
170 | 188 |
171 // The rest of this function tests decoding subsets, and will decode an arbi trary number of | 189 // The rest of this function tests decoding subsets, and will decode an arbi trary number of |
172 // random subsets. | 190 // random subsets. |
173 // Do not attempt to decode subsets of an image of only once pixel, since th ere is no | 191 // Do not attempt to decode subsets of an image of only once pixel, since th ere is no |
174 // meaningful subset. | 192 // meaningful subset. |
175 if (size.width() * size.height() == 1) { | 193 if (size.width() * size.height() == 1) { |
176 return; | 194 return; |
177 } | 195 } |
178 | 196 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 check(r, "baby_tux.png", SkISize::Make(240, 246), true, false); | 258 check(r, "baby_tux.png", SkISize::Make(240, 246), true, false); |
241 check(r, "color_wheel.png", SkISize::Make(128, 128), true, false); | 259 check(r, "color_wheel.png", SkISize::Make(128, 128), true, false); |
242 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, fals e); | 260 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, fals e); |
243 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false); | 261 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false); |
244 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false); | 262 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false); |
245 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false); | 263 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false); |
246 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false); | 264 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false); |
247 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false); | 265 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false); |
248 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false); | 266 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false); |
249 check(r, "plane.png", SkISize::Make(250, 126), true, false); | 267 check(r, "plane.png", SkISize::Make(250, 126), true, false); |
268 check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false); | |
250 check(r, "randPixels.png", SkISize::Make(8, 8), true, false); | 269 check(r, "randPixels.png", SkISize::Make(8, 8), true, false); |
251 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false); | 270 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false); |
252 } | 271 } |
253 | 272 |
273 // Test interlaced PNG in stripes, similar to DM's kStripe_Mode | |
scroggo
2015/09/25 16:07:50
Maybe this test is redundant with kStripe_Mode, bu
msarett
2015/09/28 14:48:50
I like this as a separate test - I think it's good
scroggo
2015/09/28 16:01:53
Thanks for the feedback. FWIW, I don't think anyth
| |
274 DEF_TEST(Codec_stripes, r) { | |
275 const char * path = "plane_interlaced.png"; | |
276 SkAutoTDelete<SkStream> stream(resource(path)); | |
277 if (!stream) { | |
278 SkDebugf("Missing resource '%s'\n", path); | |
279 } | |
280 | |
281 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); | |
282 REPORTER_ASSERT(r, codec); | |
283 | |
284 // Baseline for what the image should look like, using N32. | |
285 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); | |
286 | |
287 SkBitmap bm; | |
288 bm.allocPixels(info); | |
289 SkAutoLockPixels autoLockPixels(bm); | |
290 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( )); | |
291 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
292 | |
293 SkMD5::Digest digest; | |
294 md5(bm, &digest); | |
295 | |
296 // Now decode in stripes | |
297 const int height = info.height(); | |
298 const int numStripes = 4; | |
299 int stripeHeight; | |
300 int remainingLines; | |
301 SkTDivMod(height, numStripes, &stripeHeight, &remainingLines); | |
302 | |
303 bm.eraseColor(SK_ColorYELLOW); | |
304 | |
305 result = codec->start(info); | |
306 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
307 | |
308 // Odd stripes | |
309 for (int i = 1; i < numStripes; i += 2) { | |
310 // Skip the even stripes | |
311 result = codec->skipScanlines(stripeHeight); | |
312 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
313 | |
314 result = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeig ht, | |
315 bm.rowBytes()); | |
316 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
317 } | |
318 | |
319 // Even stripes | |
320 result = codec->start(info); | |
321 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
322 | |
323 for (int i = 0; i < numStripes; i += 2) { | |
324 result = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeig ht, | |
325 bm.rowBytes()); | |
326 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
327 | |
328 // Skip the odd stripes | |
329 if (i + 1 < numStripes) { | |
330 result = codec->skipScanlines(stripeHeight); | |
331 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
332 } | |
333 } | |
334 | |
335 // Remainder at the end | |
336 if (remainingLines > 0) { | |
337 result = codec->start(info); | |
338 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
339 | |
340 result = codec->skipScanlines(height - remainingLines); | |
341 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
342 | |
343 result = codec->getScanlines(bm.getAddr(0, height - remainingLines), | |
344 remainingLines, bm.rowBytes()); | |
345 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | |
346 } | |
347 | |
348 compare_to_good_digest(r, digest, bm); | |
349 } | |
350 | |
254 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) { | 351 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) { |
255 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e)); | 352 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e)); |
256 // We should not have gotten a codec. Bots should catch us if we leaked anyt hing. | 353 // We should not have gotten a codec. Bots should catch us if we leaked anyt hing. |
257 REPORTER_ASSERT(r, !codec); | 354 REPORTER_ASSERT(r, !codec); |
258 } | 355 } |
259 | 356 |
260 // Ensure that SkCodec::NewFromStream handles freeing the passed in SkStream, | 357 // Ensure that SkCodec::NewFromStream handles freeing the passed in SkStream, |
261 // even on failure. Test some bad streams. | 358 // even on failure. Test some bad streams. |
262 DEF_TEST(Codec_leaks, r) { | 359 DEF_TEST(Codec_leaks, r) { |
263 // No codec should claim this as their format, so this tests SkCodec::NewFro mStream. | 360 // No codec should claim this as their format, so this tests SkCodec::NewFro mStream. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 // This image is an ico with an embedded mask-bmp. This is illegal. | 459 // This image is an ico with an embedded mask-bmp. This is illegal. |
363 test_invalid(r, "invalid_images/mask-bmp-ico.ico"); | 460 test_invalid(r, "invalid_images/mask-bmp-ico.ico"); |
364 } | 461 } |
365 | 462 |
366 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { | 463 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { |
367 SkAutoTDelete<SkStream> stream(resource(path)); | 464 SkAutoTDelete<SkStream> stream(resource(path)); |
368 if (!stream) { | 465 if (!stream) { |
369 SkDebugf("Missing resource '%s'\n", path); | 466 SkDebugf("Missing resource '%s'\n", path); |
370 return; | 467 return; |
371 } | 468 } |
372 SkAutoTDelete<SkScanlineDecoder> decoder(SkScanlineDecoder::NewFromStream( | 469 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.detach())); |
373 stream.detach())); | |
374 | 470 |
375 // This should return kSuccess because kIndex8 is supported. | 471 // This should return kSuccess because kIndex8 is supported. |
376 SkPMColor colorStorage[256]; | 472 SkPMColor colorStorage[256]; |
377 int colorCount; | 473 int colorCount; |
378 SkCodec::Result result = decoder->start( | 474 SkCodec::Result result = decoder->start( |
379 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt orage, &colorCount); | 475 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt orage, &colorCount); |
380 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 476 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
381 // The rest of the test is uninteresting if kIndex8 is not supported | 477 // The rest of the test is uninteresting if kIndex8 is not supported |
382 if (SkCodec::kSuccess != result) { | 478 if (SkCodec::kSuccess != result) { |
383 return; | 479 return; |
384 } | 480 } |
385 | 481 |
386 // This should return kInvalidParameters because, in kIndex_8 mode, we must pass in a valid | 482 // This should return kInvalidParameters because, in kIndex_8 mode, we must pass in a valid |
387 // colorPtr and a valid colorCountPtr. | 483 // colorPtr and a valid colorCountPtr. |
388 result = decoder->start( | 484 result = decoder->start( |
389 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, nullptr , nullptr); | 485 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, nullptr , nullptr); |
390 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); | 486 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); |
391 result = decoder->start( | 487 result = decoder->start( |
392 decoder->getInfo().makeColorType(kIndex_8_SkColorType)); | 488 decoder->getInfo().makeColorType(kIndex_8_SkColorType)); |
393 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); | 489 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); |
394 } | 490 } |
395 | 491 |
396 DEF_TEST(Codec_Params, r) { | 492 DEF_TEST(Codec_Params, r) { |
397 test_invalid_parameters(r, "index8.png"); | 493 test_invalid_parameters(r, "index8.png"); |
398 test_invalid_parameters(r, "mandrill.wbmp"); | 494 test_invalid_parameters(r, "mandrill.wbmp"); |
399 } | 495 } |
OLD | NEW |