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

Side by Side Diff: tests/CodecTest.cpp

Issue 1997703003: Make SkPngCodec decode progressively. (Closed) Base URL: https://skia.googlesource.com/skia.git@foil
Patch Set: Use the correct Options object Created 4 years, 6 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
« src/codec/SkPngCodec.cpp ('K') | « tests/CodecPartial.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 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 "SkAndroidCodec.h" 9 #include "SkAndroidCodec.h"
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 do { 76 do {
77 rect.fLeft = rand->nextRangeU(0, w); 77 rect.fLeft = rand->nextRangeU(0, w);
78 rect.fTop = rand->nextRangeU(0, h); 78 rect.fTop = rand->nextRangeU(0, h);
79 rect.fRight = rand->nextRangeU(0, w); 79 rect.fRight = rand->nextRangeU(0, w);
80 rect.fBottom = rand->nextRangeU(0, h); 80 rect.fBottom = rand->nextRangeU(0, h);
81 rect.sort(); 81 rect.sort();
82 } while (rect.isEmpty()); 82 } while (rect.isEmpty());
83 return rect; 83 return rect;
84 } 84 }
85 85
86 static void test_incremental_decode(skiatest::Reporter* r, SkCodec* codec, const SkImageInfo& info,
87 const SkMD5::Digest& goodDigest) {
88 SkBitmap bm;
89 bm.allocPixels(info);
90 SkAutoLockPixels autoLockPixels(bm);
91
92 REPORTER_ASSERT(r, SkCodec::kSuccess == codec->startIncrementalDecode(info, bm.getPixels(),
93 bm.row Bytes()));
94
95 REPORTER_ASSERT(r, SkCodec::kSuccess == codec->incrementalDecode());
96
97 compare_to_good_digest(r, goodDigest, bm);
98 }
99
100 // Test in stripes, similar to DM's kStripe_Mode
101 static void test_in_stripes(skiatest::Reporter* r, SkCodec* codec, const SkImage Info& info,
102 const SkMD5::Digest& goodDigest) {
103 SkBitmap bm;
104 bm.allocPixels(info);
105 bm.eraseColor(SK_ColorYELLOW);
106
107 const int height = info.height();
108 // Note that if numStripes does not evenly divide height there will be an ex tra
109 // stripe.
110 const int numStripes = 4;
111
112 if (numStripes > height) {
113 // Image is too small.
114 return;
115 }
116
117 const int stripeHeight = height / numStripes;
118
119 // Iterate through the image twice. Once to decode odd stripes, and once for even.
120 for (int oddEven = 1; oddEven >= 0; oddEven--) {
121 for (int y = oddEven * stripeHeight; y < height; y += 2 * stripeHeight) {
122 SkIRect subset = SkIRect::MakeLTRB(0, y, info.width(),
123 SkTMin(y + stripeHeight, height)) ;
124 SkCodec::Options options;
125 options.fSubset = &subset;
126 if (SkCodec::kSuccess != codec->startIncrementalDecode(info, bm.getA ddr(0, y),
127 bm.rowBytes(), &options)) {
128 ERRORF(r, "failed to start incremental decode!\ttop: %i\tbottom% i\n",
129 subset.top(), subset.bottom());
130 return;
131 }
132 if (SkCodec::kSuccess != codec->incrementalDecode()) {
133 ERRORF(r, "failed incremental decode starting from line %i\n", y );
134 return;
135 }
136 }
137 }
138
139 compare_to_good_digest(r, goodDigest, bm);
140 }
141
86 template<typename Codec> 142 template<typename Codec>
87 static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info, 143 static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info,
88 const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* dige st, 144 const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* dige st,
89 const SkMD5::Digest* goodDigest) { 145 const SkMD5::Digest* goodDigest) {
90 146
91 REPORTER_ASSERT(r, info.dimensions() == size); 147 REPORTER_ASSERT(r, info.dimensions() == size);
92 bm.allocPixels(info); 148 bm.allocPixels(info);
93 SkAutoLockPixels autoLockPixels(bm); 149 SkAutoLockPixels autoLockPixels(bm);
94 150
95 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( )); 151 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( ));
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 }; 240 };
185 241
186 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) { 242 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
187 if (SkStrEndsWith(path, exts[i])) { 243 if (SkStrEndsWith(path, exts[i])) {
188 return true; 244 return true;
189 } 245 }
190 } 246 }
191 return false; 247 return false;
192 } 248 }
193 249
250 // FIXME: Break up this giant function
194 static void check(skiatest::Reporter* r, 251 static void check(skiatest::Reporter* r,
195 const char path[], 252 const char path[],
196 SkISize size, 253 SkISize size,
197 bool supportsScanlineDecoding, 254 bool supportsScanlineDecoding,
198 bool supportsSubsetDecoding, 255 bool supportsSubsetDecoding,
199 bool supportsIncomplete = true) { 256 bool supportsIncomplete,
257 bool supportsNewScanlineDecoding = false) {
200 258
201 SkAutoTDelete<SkStream> stream(resource(path)); 259 SkAutoTDelete<SkStream> stream(resource(path));
202 if (!stream) { 260 if (!stream) {
203 SkDebugf("Missing resource '%s'\n", path); 261 SkDebugf("Missing resource '%s'\n", path);
204 return; 262 return;
205 } 263 }
206 264
207 SkAutoTDelete<SkCodec> codec(nullptr); 265 SkAutoTDelete<SkCodec> codec(nullptr);
208 bool isIncomplete = supportsIncomplete; 266 bool isIncomplete = supportsIncomplete;
209 if (isIncomplete) { 267 if (isIncomplete) {
210 size_t size = stream->getLength(); 268 size_t size = stream->getLength();
211 SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))) ; 269 SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))) ;
212 codec.reset(SkCodec::NewFromData(data)); 270 codec.reset(SkCodec::NewFromData(data));
213 } else { 271 } else {
214 codec.reset(SkCodec::NewFromStream(stream.release())); 272 codec.reset(SkCodec::NewFromStream(stream.release()));
215 } 273 }
216 if (!codec) { 274 if (!codec) {
217 ERRORF(r, "Unable to decode '%s'", path); 275 ERRORF(r, "Unable to decode '%s'", path);
218 return; 276 return;
219 } 277 }
220 278
221 // Test full image decodes with SkCodec 279 // Test full image decodes with SkCodec
222 SkMD5::Digest codecDigest; 280 SkMD5::Digest codecDigest;
223 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); 281 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
224 SkBitmap bm; 282 SkBitmap bm;
225 SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess; 283 SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess;
226 test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nul lptr); 284 test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nul lptr);
227 285
228 // Scanline decoding follows. 286 // Scanline decoding follows.
287
288 if (supportsNewScanlineDecoding && !isIncomplete) {
289 test_incremental_decode(r, codec, info, codecDigest);
290 test_in_stripes(r, codec, info, codecDigest);
291 }
292
229 // Need to call startScanlineDecode() first. 293 // Need to call startScanlineDecode() first.
230 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 294 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0);
231 == 0); 295 REPORTER_ASSERT(r, !codec->skipScanlines(1));
232 REPORTER_ASSERT(r, codec->skipScanlines(1)
233 == 0);
234
235 const SkCodec::Result startResult = codec->startScanlineDecode(info); 296 const SkCodec::Result startResult = codec->startScanlineDecode(info);
236 if (supportsScanlineDecoding) { 297 if (supportsScanlineDecoding) {
237 bm.eraseColor(SK_ColorYELLOW); 298 bm.eraseColor(SK_ColorYELLOW);
238 299
239 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); 300 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess);
240 301
241 for (int y = 0; y < info.height(); y++) { 302 for (int y = 0; y < info.height(); y++) {
242 const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); 303 const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0);
243 if (!isIncomplete) { 304 if (!isIncomplete) {
244 REPORTER_ASSERT(r, 1 == lines); 305 REPORTER_ASSERT(r, 1 == lines);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 // Webp is the only codec that supports subsets, and it will have mo dified the subset 380 // Webp is the only codec that supports subsets, and it will have mo dified the subset
320 // to have even left/top. 381 // to have even left/top.
321 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo p)); 382 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo p));
322 } else { 383 } else {
323 // No subsets will work. 384 // No subsets will work.
324 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); 385 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented);
325 } 386 }
326 } 387 }
327 388
328 // SkAndroidCodec tests 389 // SkAndroidCodec tests
329 if (supportsScanlineDecoding || supportsSubsetDecoding) { 390 if (supportsScanlineDecoding || supportsSubsetDecoding || supportsNewScanlin eDecoding) {
330 391
331 SkAutoTDelete<SkStream> stream(resource(path)); 392 SkAutoTDelete<SkStream> stream(resource(path));
332 if (!stream) { 393 if (!stream) {
333 SkDebugf("Missing resource '%s'\n", path); 394 SkDebugf("Missing resource '%s'\n", path);
334 return; 395 return;
335 } 396 }
336 397
337 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); 398 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr);
338 if (isIncomplete) { 399 if (isIncomplete) {
339 size_t size = stream->getLength(); 400 size_t size = stream->getLength();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 } 437 }
377 438
378 // If we've just tested incomplete decodes, let's run the same test again on full decodes. 439 // If we've just tested incomplete decodes, let's run the same test again on full decodes.
379 if (isIncomplete) { 440 if (isIncomplete) {
380 check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, f alse); 441 check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, f alse);
381 } 442 }
382 } 443 }
383 444
384 DEF_TEST(Codec, r) { 445 DEF_TEST(Codec, r) {
385 // WBMP 446 // WBMP
386 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false); 447 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false, true);
387 448
388 // WEBP 449 // WEBP
389 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true); 450 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true, true);
390 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true); 451 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true, true);
391 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true); 452 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true, true);
392 453
393 // BMP 454 // BMP
394 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false); 455 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false, true);
395 check(r, "rle.bmp", SkISize::Make(320, 240), true, false); 456 check(r, "rle.bmp", SkISize::Make(320, 240), true, false, true);
396 457
397 // ICO 458 // ICO
398 // FIXME: We are not ready to test incomplete ICOs 459 // FIXME: We are not ready to test incomplete ICOs
399 // These two tests examine interestingly different behavior: 460 // These two tests examine interestingly different behavior:
400 // Decodes an embedded BMP image 461 // Decodes an embedded BMP image
401 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false); 462 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false);
402 // Decodes an embedded PNG image 463 // Decodes an embedded PNG image
403 check(r, "google_chrome.ico", SkISize::Make(256, 256), true, false, false); 464 check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false, false, true);
404 465
405 // GIF 466 // GIF
406 // FIXME: We are not ready to test incomplete GIFs 467 // FIXME: We are not ready to test incomplete GIFs
407 check(r, "box.gif", SkISize::Make(200, 55), true, false, false); 468 check(r, "box.gif", SkISize::Make(200, 55), true, false, false);
408 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false); 469 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false);
409 // randPixels.gif is too small to test incomplete 470 // randPixels.gif is too small to test incomplete
410 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false); 471 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false);
411 472
412 // JPG 473 // JPG
413 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false); 474 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false, true);
414 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false); 475 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false, true);
415 // grayscale.jpg is too small to test incomplete 476 // grayscale.jpg is too small to test incomplete
416 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false); 477 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false);
417 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false); 478 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false, true );
418 // randPixels.jpg is too small to test incomplete 479 // randPixels.jpg is too small to test incomplete
419 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false); 480 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false);
420 481
421 // PNG 482 // PNG
422 check(r, "arrow.png", SkISize::Make(187, 312), true, false, false); 483 check(r, "arrow.png", SkISize::Make(187, 312), false, false, true, true);
423 check(r, "baby_tux.png", SkISize::Make(240, 246), true, false, false); 484 check(r, "baby_tux.png", SkISize::Make(240, 246), false, false, true, true);
424 check(r, "color_wheel.png", SkISize::Make(128, 128), true, false, false); 485 check(r, "color_wheel.png", SkISize::Make(128, 128), false, false, true, tru e);
425 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, fals e, false); 486 // half-transparent-white-pixel.png is too small to test incomplete
426 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false, false); 487 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), false, fal se, false, true);
427 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false, false); 488 check(r, "mandrill_128.png", SkISize::Make(128, 128), false, false, true, tr ue);
428 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false, false); 489 check(r, "mandrill_16.png", SkISize::Make(16, 16), false, false, true, true) ;
429 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false, false); 490 check(r, "mandrill_256.png", SkISize::Make(256, 256), false, false, true, tr ue);
430 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false, false); 491 check(r, "mandrill_32.png", SkISize::Make(32, 32), false, false, true, true) ;
431 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false, false); 492 check(r, "mandrill_512.png", SkISize::Make(512, 512), false, false, true, tr ue);
432 check(r, "plane.png", SkISize::Make(250, 126), true, false, false); 493 check(r, "mandrill_64.png", SkISize::Make(64, 64), false, false, true, true) ;
433 // FIXME: We are not ready to test incomplete interlaced pngs 494 check(r, "plane.png", SkISize::Make(250, 126), false, false, true, true);
434 check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false, false ); 495 check(r, "plane_interlaced.png", SkISize::Make(250, 126), false, false, true , true);
435 check(r, "randPixels.png", SkISize::Make(8, 8), true, false, false); 496 check(r, "randPixels.png", SkISize::Make(8, 8), false, false, true, true);
436 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false, false); 497 check(r, "yellow_rose.png", SkISize::Make(400, 301), false, false, true, tru e);
437 498
438 // RAW 499 // RAW
439 // Disable RAW tests for Win32. 500 // Disable RAW tests for Win32.
440 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 501 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32))
441 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false); 502 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false);
442 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa lse); 503 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa lse);
443 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false ); 504 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false );
444 #endif 505 #endif
445 } 506 }
446 507
447 // Test interlaced PNG in stripes, similar to DM's kStripe_Mode
448 DEF_TEST(Codec_stripes, r) {
449 const char * path = "plane_interlaced.png";
450 SkAutoTDelete<SkStream> stream(resource(path));
451 if (!stream) {
452 SkDebugf("Missing resource '%s'\n", path);
453 }
454
455 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
456 REPORTER_ASSERT(r, codec);
457
458 if (!codec) {
459 return;
460 }
461
462 switch (codec->getScanlineOrder()) {
463 case SkCodec::kBottomUp_SkScanlineOrder:
464 case SkCodec::kOutOfOrder_SkScanlineOrder:
465 ERRORF(r, "This scanline order will not match the original.");
466 return;
467 default:
468 break;
469 }
470
471 // Baseline for what the image should look like, using N32.
472 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
473
474 SkBitmap bm;
475 bm.allocPixels(info);
476 SkAutoLockPixels autoLockPixels(bm);
477 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( ));
478 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
479
480 SkMD5::Digest digest;
481 md5(bm, &digest);
482
483 // Now decode in stripes
484 const int height = info.height();
485 const int numStripes = 4;
486 int stripeHeight;
487 int remainingLines;
488 SkTDivMod(height, numStripes, &stripeHeight, &remainingLines);
489
490 bm.eraseColor(SK_ColorYELLOW);
491
492 result = codec->startScanlineDecode(info);
493 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
494
495 // Odd stripes
496 for (int i = 1; i < numStripes; i += 2) {
497 // Skip the even stripes
498 bool skipResult = codec->skipScanlines(stripeHeight);
499 REPORTER_ASSERT(r, skipResult);
500
501 int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
502 bm.rowBytes());
503 REPORTER_ASSERT(r, linesDecoded == stripeHeight);
504 }
505
506 // Even stripes
507 result = codec->startScanlineDecode(info);
508 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
509
510 for (int i = 0; i < numStripes; i += 2) {
511 int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
512 bm.rowBytes());
513 REPORTER_ASSERT(r, linesDecoded == stripeHeight);
514
515 // Skip the odd stripes
516 if (i + 1 < numStripes) {
517 bool skipResult = codec->skipScanlines(stripeHeight);
518 REPORTER_ASSERT(r, skipResult);
519 }
520 }
521
522 // Remainder at the end
523 if (remainingLines > 0) {
524 result = codec->startScanlineDecode(info);
525 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
526
527 bool skipResult = codec->skipScanlines(height - remainingLines);
528 REPORTER_ASSERT(r, skipResult);
529
530 int linesDecoded = codec->getScanlines(bm.getAddr(0, height - remainingL ines),
531 remainingLines, bm.rowBytes());
532 REPORTER_ASSERT(r, linesDecoded == remainingLines);
533 }
534
535 compare_to_good_digest(r, digest, bm);
536 }
537
538 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) { 508 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) {
539 // Neither of these calls should return a codec. Bots should catch us if we leaked anything. 509 // Neither of these calls should return a codec. Bots should catch us if we leaked anything.
540 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e)); 510 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e));
541 REPORTER_ASSERT(r, !codec); 511 REPORTER_ASSERT(r, !codec);
542 512
543 SkAndroidCodec* androidCodec = 513 SkAndroidCodec* androidCodec =
544 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) ); 514 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) );
545 REPORTER_ASSERT(r, !androidCodec); 515 REPORTER_ASSERT(r, !androidCodec);
546 } 516 }
547 517
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 } 641 }
672 642
673 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { 643 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) {
674 SkAutoTDelete<SkStream> stream(resource(path)); 644 SkAutoTDelete<SkStream> stream(resource(path));
675 if (!stream) { 645 if (!stream) {
676 SkDebugf("Missing resource '%s'\n", path); 646 SkDebugf("Missing resource '%s'\n", path);
677 return; 647 return;
678 } 648 }
679 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release())); 649 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release()));
680 650
651 const SkImageInfo info = decoder->getInfo().makeColorType(kIndex_8_SkColorTy pe);
652
681 // This should return kSuccess because kIndex8 is supported. 653 // This should return kSuccess because kIndex8 is supported.
682 SkPMColor colorStorage[256]; 654 SkPMColor colorStorage[256];
683 int colorCount; 655 int colorCount;
684 SkCodec::Result result = decoder->startScanlineDecode( 656 SkCodec::Result result = decoder->startScanlineDecode(info, nullptr, colorSt orage,
685 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt orage, &colorCount); 657 &colorCount);
686 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 658 if (SkCodec::kSuccess == result) {
687 // The rest of the test is uninteresting if kIndex8 is not supported 659 // This should return kInvalidParameters because, in kIndex_8 mode, we m ust pass in a valid
688 if (SkCodec::kSuccess != result) { 660 // colorPtr and a valid colorCountPtr.
661 result = decoder->startScanlineDecode(info, nullptr, nullptr, nullptr);
662 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
663 result = decoder->startScanlineDecode(info);
664 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
665 } else if (SkCodec::kUnimplemented == result) {
666 // New method should be supported:
667 SkBitmap bm;
668 sk_sp<SkColorTable> colorTable(new SkColorTable(colorStorage, 256));
669 bm.allocPixels(info, nullptr, colorTable.get());
670 result = decoder->startIncrementalDecode(info, bm.getPixels(), bm.rowByt es(), nullptr,
671 colorStorage, &colorCount);
672 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
673 result = decoder->startIncrementalDecode(info, bm.getPixels(), bm.rowByt es());
674 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
675 } else {
676 // The test is uninteresting if kIndex8 is not supported
677 ERRORF(r, "Should not call test_invalid_parameters for non-Index8 file: %s\n", path);
689 return; 678 return;
690 } 679 }
691 680
692 // This should return kInvalidParameters because, in kIndex_8 mode, we must pass in a valid
693 // colorPtr and a valid colorCountPtr.
694 result = decoder->startScanlineDecode(
695 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, nullptr , nullptr);
696 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
697 result = decoder->startScanlineDecode(
698 decoder->getInfo().makeColorType(kIndex_8_SkColorType));
699 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
700 } 681 }
701 682
702 DEF_TEST(Codec_Params, r) { 683 DEF_TEST(Codec_Params, r) {
703 test_invalid_parameters(r, "index8.png"); 684 test_invalid_parameters(r, "index8.png");
704 test_invalid_parameters(r, "mandrill.wbmp"); 685 test_invalid_parameters(r, "mandrill.wbmp");
705 } 686 }
706 687
707 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 688 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
708 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); 689 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
709 if (!sk_stream->write(data, len)) { 690 if (!sk_stream->write(data, len)) {
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 // Now test an image which is too big. Any image with a larger header (i.e. 986 // Now test an image which is too big. Any image with a larger header (i.e.
1006 // has bigger width/height) is also too big. 987 // has bigger width/height) is also too big.
1007 const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header 988 const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header
1008 0x84, 0x80, 0x00, // W: 65536 989 0x84, 0x80, 0x00, // W: 65536
1009 0x84, 0x80, 0x00 }; // H: 65536 990 0x84, 0x80, 0x00 }; // H: 65536
1010 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false)); 991 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false));
1011 codec.reset(SkCodec::NewFromStream(stream.release())); 992 codec.reset(SkCodec::NewFromStream(stream.release()));
1012 993
1013 REPORTER_ASSERT(r, !codec); 994 REPORTER_ASSERT(r, !codec);
1014 } 995 }
996
997 // Only rewinds up to a limit.
998 class LimitedRewindingStream : public SkStream {
999 public:
1000 static SkStream* Make(const char path[], size_t limit) {
1001 SkStream* stream = resource(path);
1002 if (!stream) {
1003 return nullptr;
1004 }
1005 return new LimitedRewindingStream(stream, limit);
1006 }
1007
1008 size_t read(void* buffer, size_t size) override {
1009 const size_t bytes = fStream->read(buffer, size);
1010 fPosition += bytes;
1011 return bytes;
1012 }
1013
1014 bool isAtEnd() const override {
1015 return fStream->isAtEnd();
1016 }
1017
1018 bool rewind() override {
1019 if (fPosition <= fLimit && fStream->rewind()) {
1020 fPosition = 0;
1021 return true;
1022 }
1023
1024 return false;
1025 }
1026
1027 private:
1028 SkAutoTDelete<SkStream> fStream;
1029 const size_t fLimit;
1030 size_t fPosition;
1031
1032 LimitedRewindingStream(SkStream* stream, size_t limit)
1033 : fStream(stream)
1034 , fLimit(limit)
1035 , fPosition(0)
1036 {
1037 SkASSERT(fStream);
1038 }
1039 };
1040
1041 DEF_TEST(Codec_fallBack, r) {
1042 // SkAndroidCodec needs to be able to fall back to scanline decoding
1043 // if incremental decoding does not work. Make sure this does not
1044 // require a rewind.
1045
1046 // Formats that currently do not support incremental decoding
1047 auto files = {
1048 "box.gif",
1049 "CMYK.jpg",
1050 "color_wheel.ico",
1051 "mandrill.wbmp",
1052 "randPixels.bmp",
1053 };
1054 for (auto file : files) {
1055 SkStream* stream = LimitedRewindingStream::Make(file, 14);
1056 if (!stream) {
1057 SkDebugf("Missing resources (%s). Set --resourcePath.\n", file);
1058 return;
1059 }
1060
1061 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
1062 if (!codec) {
1063 ERRORF(r, "Failed to create codec for %s,", file);
1064 continue;
1065 }
1066
1067 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
1068 SkBitmap bm;
1069 bm.allocPixels(info);
1070
1071 if (SkCodec::kUnimplemented != codec->startIncrementalDecode(info, bm.ge tPixels(),
1072 bm.rowBytes())) {
1073 ERRORF(r, "Is scanline decoding now implemented for %s?", file);
1074 continue;
1075 }
1076
1077 // Scanline decoding should not require a rewind.
1078 SkCodec::Result result = codec->startScanlineDecode(info);
1079 if (SkCodec::kSuccess != result) {
1080 ERRORF(r, "Scanline decoding failed for %s with %i", file, result);
1081 }
1082 }
1083 }
OLDNEW
« src/codec/SkPngCodec.cpp ('K') | « tests/CodecPartial.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698