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

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: Simplify applyXformRow Created 4 years, 3 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 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 do { 77 do {
78 rect.fLeft = rand->nextRangeU(0, w); 78 rect.fLeft = rand->nextRangeU(0, w);
79 rect.fTop = rand->nextRangeU(0, h); 79 rect.fTop = rand->nextRangeU(0, h);
80 rect.fRight = rand->nextRangeU(0, w); 80 rect.fRight = rand->nextRangeU(0, w);
81 rect.fBottom = rand->nextRangeU(0, h); 81 rect.fBottom = rand->nextRangeU(0, h);
82 rect.sort(); 82 rect.sort();
83 } while (rect.isEmpty()); 83 } while (rect.isEmpty());
84 return rect; 84 return rect;
85 } 85 }
86 86
87 static void test_incremental_decode(skiatest::Reporter* r, SkCodec* codec, const SkImageInfo& info,
88 const SkMD5::Digest& goodDigest) {
89 SkBitmap bm;
90 bm.allocPixels(info);
91 SkAutoLockPixels autoLockPixels(bm);
92
93 REPORTER_ASSERT(r, SkCodec::kSuccess == codec->startIncrementalDecode(info, bm.getPixels(),
94 bm.row Bytes()));
95
96 REPORTER_ASSERT(r, SkCodec::kSuccess == codec->incrementalDecode());
97
98 compare_to_good_digest(r, goodDigest, bm);
99 }
100
101 // Test in stripes, similar to DM's kStripe_Mode
102 static void test_in_stripes(skiatest::Reporter* r, SkCodec* codec, const SkImage Info& info,
103 const SkMD5::Digest& goodDigest) {
104 SkBitmap bm;
105 bm.allocPixels(info);
106 bm.eraseColor(SK_ColorYELLOW);
107
108 const int height = info.height();
109 // Note that if numStripes does not evenly divide height there will be an ex tra
110 // stripe.
111 const int numStripes = 4;
112
113 if (numStripes > height) {
114 // Image is too small.
115 return;
116 }
117
118 const int stripeHeight = height / numStripes;
119
120 // Iterate through the image twice. Once to decode odd stripes, and once for even.
121 for (int oddEven = 1; oddEven >= 0; oddEven--) {
122 for (int y = oddEven * stripeHeight; y < height; y += 2 * stripeHeight) {
123 SkIRect subset = SkIRect::MakeLTRB(0, y, info.width(),
124 SkTMin(y + stripeHeight, height)) ;
125 SkCodec::Options options;
126 options.fSubset = &subset;
127 if (SkCodec::kSuccess != codec->startIncrementalDecode(info, bm.getA ddr(0, y),
128 bm.rowBytes(), &options)) {
129 ERRORF(r, "failed to start incremental decode!\ttop: %i\tbottom% i\n",
130 subset.top(), subset.bottom());
131 return;
132 }
133 if (SkCodec::kSuccess != codec->incrementalDecode()) {
134 ERRORF(r, "failed incremental decode starting from line %i\n", y );
135 return;
136 }
137 }
138 }
139
140 compare_to_good_digest(r, goodDigest, bm);
141 }
142
87 template<typename Codec> 143 template<typename Codec>
88 static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info, 144 static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info,
89 const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* dige st, 145 const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* dige st,
90 const SkMD5::Digest* goodDigest) { 146 const SkMD5::Digest* goodDigest) {
91 147
92 REPORTER_ASSERT(r, info.dimensions() == size); 148 REPORTER_ASSERT(r, info.dimensions() == size);
93 bm.allocPixels(info); 149 bm.allocPixels(info);
94 SkAutoLockPixels autoLockPixels(bm); 150 SkAutoLockPixels autoLockPixels(bm);
95 151
96 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( )); 152 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( ));
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 }; 241 };
186 242
187 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) { 243 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
188 if (SkStrEndsWith(path, exts[i])) { 244 if (SkStrEndsWith(path, exts[i])) {
189 return true; 245 return true;
190 } 246 }
191 } 247 }
192 return false; 248 return false;
193 } 249 }
194 250
251 // FIXME: Break up this giant function
195 static void check(skiatest::Reporter* r, 252 static void check(skiatest::Reporter* r,
196 const char path[], 253 const char path[],
197 SkISize size, 254 SkISize size,
198 bool supportsScanlineDecoding, 255 bool supportsScanlineDecoding,
199 bool supportsSubsetDecoding, 256 bool supportsSubsetDecoding,
200 bool supportsIncomplete = true) { 257 bool supportsIncomplete,
258 bool supportsNewScanlineDecoding = false) {
201 259
202 SkAutoTDelete<SkStream> stream(resource(path)); 260 SkAutoTDelete<SkStream> stream(resource(path));
203 if (!stream) { 261 if (!stream) {
204 SkDebugf("Missing resource '%s'\n", path); 262 SkDebugf("Missing resource '%s'\n", path);
205 return; 263 return;
206 } 264 }
207 265
208 SkAutoTDelete<SkCodec> codec(nullptr); 266 SkAutoTDelete<SkCodec> codec(nullptr);
209 bool isIncomplete = supportsIncomplete; 267 bool isIncomplete = supportsIncomplete;
210 if (isIncomplete) { 268 if (isIncomplete) {
211 size_t size = stream->getLength(); 269 size_t size = stream->getLength();
212 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); 270 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3)));
213 codec.reset(SkCodec::NewFromData(data)); 271 codec.reset(SkCodec::NewFromData(data));
214 } else { 272 } else {
215 codec.reset(SkCodec::NewFromStream(stream.release())); 273 codec.reset(SkCodec::NewFromStream(stream.release()));
216 } 274 }
217 if (!codec) { 275 if (!codec) {
218 ERRORF(r, "Unable to decode '%s'", path); 276 ERRORF(r, "Unable to decode '%s'", path);
219 return; 277 return;
220 } 278 }
221 279
222 // Test full image decodes with SkCodec 280 // Test full image decodes with SkCodec
223 SkMD5::Digest codecDigest; 281 SkMD5::Digest codecDigest;
224 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); 282 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
225 SkBitmap bm; 283 SkBitmap bm;
226 SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess; 284 SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess;
227 test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nul lptr); 285 test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nul lptr);
228 286
229 // Scanline decoding follows. 287 // Scanline decoding follows.
288
289 if (supportsNewScanlineDecoding && !isIncomplete) {
290 test_incremental_decode(r, codec, info, codecDigest);
291 test_in_stripes(r, codec, info, codecDigest);
292 }
293
230 // Need to call startScanlineDecode() first. 294 // Need to call startScanlineDecode() first.
231 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 295 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0);
232 == 0); 296 REPORTER_ASSERT(r, !codec->skipScanlines(1));
233 REPORTER_ASSERT(r, codec->skipScanlines(1)
234 == 0);
235
236 const SkCodec::Result startResult = codec->startScanlineDecode(info); 297 const SkCodec::Result startResult = codec->startScanlineDecode(info);
237 if (supportsScanlineDecoding) { 298 if (supportsScanlineDecoding) {
238 bm.eraseColor(SK_ColorYELLOW); 299 bm.eraseColor(SK_ColorYELLOW);
239 300
240 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); 301 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess);
241 302
242 for (int y = 0; y < info.height(); y++) { 303 for (int y = 0; y < info.height(); y++) {
243 const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); 304 const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0);
244 if (!isIncomplete) { 305 if (!isIncomplete) {
245 REPORTER_ASSERT(r, 1 == lines); 306 REPORTER_ASSERT(r, 1 == lines);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 // Webp is the only codec that supports subsets, and it will have mo dified the subset 381 // Webp is the only codec that supports subsets, and it will have mo dified the subset
321 // to have even left/top. 382 // to have even left/top.
322 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo p)); 383 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo p));
323 } else { 384 } else {
324 // No subsets will work. 385 // No subsets will work.
325 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); 386 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented);
326 } 387 }
327 } 388 }
328 389
329 // SkAndroidCodec tests 390 // SkAndroidCodec tests
330 if (supportsScanlineDecoding || supportsSubsetDecoding) { 391 if (supportsScanlineDecoding || supportsSubsetDecoding || supportsNewScanlin eDecoding) {
331 392
332 SkAutoTDelete<SkStream> stream(resource(path)); 393 SkAutoTDelete<SkStream> stream(resource(path));
333 if (!stream) { 394 if (!stream) {
334 SkDebugf("Missing resource '%s'\n", path); 395 SkDebugf("Missing resource '%s'\n", path);
335 return; 396 return;
336 } 397 }
337 398
338 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); 399 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr);
339 if (isIncomplete) { 400 if (isIncomplete) {
340 size_t size = stream->getLength(); 401 size_t size = stream->getLength();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 } 439 }
379 440
380 // If we've just tested incomplete decodes, let's run the same test again on full decodes. 441 // If we've just tested incomplete decodes, let's run the same test again on full decodes.
381 if (isIncomplete) { 442 if (isIncomplete) {
382 check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, f alse); 443 check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, f alse);
383 } 444 }
384 } 445 }
385 446
386 DEF_TEST(Codec, r) { 447 DEF_TEST(Codec, r) {
387 // WBMP 448 // WBMP
388 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false); 449 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false, true);
389 450
390 // WEBP 451 // WEBP
391 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true); 452 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true, true);
392 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true); 453 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true, true);
393 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true); 454 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true, true);
394 455
395 // BMP 456 // BMP
396 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false); 457 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false, true);
397 check(r, "rle.bmp", SkISize::Make(320, 240), true, false); 458 check(r, "rle.bmp", SkISize::Make(320, 240), true, false, true);
398 459
399 // ICO 460 // ICO
400 // FIXME: We are not ready to test incomplete ICOs 461 // FIXME: We are not ready to test incomplete ICOs
401 // These two tests examine interestingly different behavior: 462 // These two tests examine interestingly different behavior:
402 // Decodes an embedded BMP image 463 // Decodes an embedded BMP image
403 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false); 464 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false);
404 // Decodes an embedded PNG image 465 // Decodes an embedded PNG image
405 check(r, "google_chrome.ico", SkISize::Make(256, 256), true, false, false); 466 check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false, false, true);
406 467
407 // GIF 468 // GIF
408 // FIXME: We are not ready to test incomplete GIFs 469 // FIXME: We are not ready to test incomplete GIFs
409 check(r, "box.gif", SkISize::Make(200, 55), true, false, false); 470 check(r, "box.gif", SkISize::Make(200, 55), true, false, false);
410 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false); 471 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false);
411 // randPixels.gif is too small to test incomplete 472 // randPixels.gif is too small to test incomplete
412 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false); 473 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false);
413 474
414 // JPG 475 // JPG
415 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false); 476 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false, true);
416 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false); 477 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false, true);
417 // grayscale.jpg is too small to test incomplete 478 // grayscale.jpg is too small to test incomplete
418 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false); 479 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false);
419 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false); 480 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false, true );
420 // randPixels.jpg is too small to test incomplete 481 // randPixels.jpg is too small to test incomplete
421 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false); 482 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false);
422 483
423 // PNG 484 // PNG
424 check(r, "arrow.png", SkISize::Make(187, 312), true, false, false); 485 check(r, "arrow.png", SkISize::Make(187, 312), false, false, true, true);
425 check(r, "baby_tux.png", SkISize::Make(240, 246), true, false, false); 486 check(r, "baby_tux.png", SkISize::Make(240, 246), false, false, true, true);
426 check(r, "color_wheel.png", SkISize::Make(128, 128), true, false, false); 487 check(r, "color_wheel.png", SkISize::Make(128, 128), false, false, true, tru e);
427 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, fals e, false); 488 // half-transparent-white-pixel.png is too small to test incomplete
428 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false, false); 489 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), false, fal se, false, true);
429 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false, false); 490 check(r, "mandrill_128.png", SkISize::Make(128, 128), false, false, true, tr ue);
430 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false, false); 491 check(r, "mandrill_16.png", SkISize::Make(16, 16), false, false, true, true) ;
431 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false, false); 492 check(r, "mandrill_256.png", SkISize::Make(256, 256), false, false, true, tr ue);
432 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false, false); 493 check(r, "mandrill_32.png", SkISize::Make(32, 32), false, false, true, true) ;
433 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false, false); 494 check(r, "mandrill_512.png", SkISize::Make(512, 512), false, false, true, tr ue);
434 check(r, "plane.png", SkISize::Make(250, 126), true, false, false); 495 check(r, "mandrill_64.png", SkISize::Make(64, 64), false, false, true, true) ;
435 // FIXME: We are not ready to test incomplete interlaced pngs 496 check(r, "plane.png", SkISize::Make(250, 126), false, false, true, true);
436 check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false, false ); 497 check(r, "plane_interlaced.png", SkISize::Make(250, 126), false, false, true , true);
437 check(r, "randPixels.png", SkISize::Make(8, 8), true, false, false); 498 check(r, "randPixels.png", SkISize::Make(8, 8), false, false, true, true);
438 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false, false); 499 check(r, "yellow_rose.png", SkISize::Make(400, 301), false, false, true, tru e);
439 500
440 // RAW 501 // RAW
441 // Disable RAW tests for Win32. 502 // Disable RAW tests for Win32.
442 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 503 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32))
443 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false); 504 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false);
444 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa lse); 505 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa lse);
445 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false ); 506 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false );
446 #endif 507 #endif
447 } 508 }
448 509
449 // Test interlaced PNG in stripes, similar to DM's kStripe_Mode
450 DEF_TEST(Codec_stripes, r) {
451 const char * path = "plane_interlaced.png";
452 SkAutoTDelete<SkStream> stream(resource(path));
453 if (!stream) {
454 SkDebugf("Missing resource '%s'\n", path);
455 }
456
457 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
458 REPORTER_ASSERT(r, codec);
459
460 if (!codec) {
461 return;
462 }
463
464 switch (codec->getScanlineOrder()) {
465 case SkCodec::kBottomUp_SkScanlineOrder:
466 case SkCodec::kOutOfOrder_SkScanlineOrder:
467 ERRORF(r, "This scanline order will not match the original.");
468 return;
469 default:
470 break;
471 }
472
473 // Baseline for what the image should look like, using N32.
474 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
475
476 SkBitmap bm;
477 bm.allocPixels(info);
478 SkAutoLockPixels autoLockPixels(bm);
479 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( ));
480 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
481
482 SkMD5::Digest digest;
483 md5(bm, &digest);
484
485 // Now decode in stripes
486 const int height = info.height();
487 const int numStripes = 4;
488 int stripeHeight;
489 int remainingLines;
490 SkTDivMod(height, numStripes, &stripeHeight, &remainingLines);
491
492 bm.eraseColor(SK_ColorYELLOW);
493
494 result = codec->startScanlineDecode(info);
495 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
496
497 // Odd stripes
498 for (int i = 1; i < numStripes; i += 2) {
499 // Skip the even stripes
500 bool skipResult = codec->skipScanlines(stripeHeight);
501 REPORTER_ASSERT(r, skipResult);
502
503 int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
504 bm.rowBytes());
505 REPORTER_ASSERT(r, linesDecoded == stripeHeight);
506 }
507
508 // Even stripes
509 result = codec->startScanlineDecode(info);
510 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
511
512 for (int i = 0; i < numStripes; i += 2) {
513 int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
514 bm.rowBytes());
515 REPORTER_ASSERT(r, linesDecoded == stripeHeight);
516
517 // Skip the odd stripes
518 if (i + 1 < numStripes) {
519 bool skipResult = codec->skipScanlines(stripeHeight);
520 REPORTER_ASSERT(r, skipResult);
521 }
522 }
523
524 // Remainder at the end
525 if (remainingLines > 0) {
526 result = codec->startScanlineDecode(info);
527 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
528
529 bool skipResult = codec->skipScanlines(height - remainingLines);
530 REPORTER_ASSERT(r, skipResult);
531
532 int linesDecoded = codec->getScanlines(bm.getAddr(0, height - remainingL ines),
533 remainingLines, bm.rowBytes());
534 REPORTER_ASSERT(r, linesDecoded == remainingLines);
535 }
536
537 compare_to_good_digest(r, digest, bm);
538 }
539
540 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) { 510 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) {
541 // Neither of these calls should return a codec. Bots should catch us if we leaked anything. 511 // Neither of these calls should return a codec. Bots should catch us if we leaked anything.
542 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e)); 512 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e));
543 REPORTER_ASSERT(r, !codec); 513 REPORTER_ASSERT(r, !codec);
544 514
545 SkAndroidCodec* androidCodec = 515 SkAndroidCodec* androidCodec =
546 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) ); 516 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) );
547 REPORTER_ASSERT(r, !androidCodec); 517 REPORTER_ASSERT(r, !androidCodec);
548 } 518 }
549 519
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 test_invalid(r, "invalid_images/mask-bmp-ico.ico"); 642 test_invalid(r, "invalid_images/mask-bmp-ico.ico");
673 } 643 }
674 644
675 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { 645 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) {
676 SkAutoTDelete<SkStream> stream(resource(path)); 646 SkAutoTDelete<SkStream> stream(resource(path));
677 if (!stream) { 647 if (!stream) {
678 SkDebugf("Missing resource '%s'\n", path); 648 SkDebugf("Missing resource '%s'\n", path);
679 return; 649 return;
680 } 650 }
681 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release())); 651 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release()));
652 if (!decoder) {
653 SkDebugf("Missing codec for %s\n", path);
654 return;
655 }
656
657 const SkImageInfo info = decoder->getInfo().makeColorType(kIndex_8_SkColorTy pe);
682 658
683 // This should return kSuccess because kIndex8 is supported. 659 // This should return kSuccess because kIndex8 is supported.
684 SkPMColor colorStorage[256]; 660 SkPMColor colorStorage[256];
685 int colorCount; 661 int colorCount;
686 SkCodec::Result result = decoder->startScanlineDecode( 662 SkCodec::Result result = decoder->startScanlineDecode(info, nullptr, colorSt orage,
687 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt orage, &colorCount); 663 &colorCount);
688 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 664 if (SkCodec::kSuccess == result) {
689 // The rest of the test is uninteresting if kIndex8 is not supported 665 // This should return kInvalidParameters because, in kIndex_8 mode, we m ust pass in a valid
690 if (SkCodec::kSuccess != result) { 666 // colorPtr and a valid colorCountPtr.
667 result = decoder->startScanlineDecode(info, nullptr, nullptr, nullptr);
668 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
669 result = decoder->startScanlineDecode(info);
670 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
671 } else if (SkCodec::kUnimplemented == result) {
672 // New method should be supported:
673 SkBitmap bm;
674 sk_sp<SkColorTable> colorTable(new SkColorTable(colorStorage, 256));
675 bm.allocPixels(info, nullptr, colorTable.get());
676 result = decoder->startIncrementalDecode(info, bm.getPixels(), bm.rowByt es(), nullptr,
677 colorStorage, &colorCount);
678 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
679 result = decoder->startIncrementalDecode(info, bm.getPixels(), bm.rowByt es());
680 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
681 } else {
682 // The test is uninteresting if kIndex8 is not supported
683 ERRORF(r, "Should not call test_invalid_parameters for non-Index8 file: %s\n", path);
691 return; 684 return;
692 } 685 }
693 686
694 // This should return kInvalidParameters because, in kIndex_8 mode, we must pass in a valid
695 // colorPtr and a valid colorCountPtr.
696 result = decoder->startScanlineDecode(
697 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, nullptr , nullptr);
698 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
699 result = decoder->startScanlineDecode(
700 decoder->getInfo().makeColorType(kIndex_8_SkColorType));
701 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
702 } 687 }
703 688
704 DEF_TEST(Codec_Params, r) { 689 DEF_TEST(Codec_Params, r) {
705 test_invalid_parameters(r, "index8.png"); 690 test_invalid_parameters(r, "index8.png");
706 test_invalid_parameters(r, "mandrill.wbmp"); 691 test_invalid_parameters(r, "mandrill.wbmp");
707 } 692 }
708 693
709 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 694 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
710 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); 695 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
711 if (!sk_stream->write(data, len)) { 696 if (!sk_stream->write(data, len)) {
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 stream.reset(resource(path)); 1099 stream.reset(resource(path));
1115 codec.reset(SkCodec::NewFromStream(stream.release())); 1100 codec.reset(SkCodec::NewFromStream(stream.release()));
1116 SkBitmap bm2; 1101 SkBitmap bm2;
1117 bm2.allocPixels(codec->getInfo()); 1102 bm2.allocPixels(codec->getInfo());
1118 result = codec->getPixels(codec->getInfo(), bm2.getPixels(), bm2.rowBytes()) ; 1103 result = codec->getPixels(codec->getInfo(), bm2.getPixels(), bm2.rowBytes()) ;
1119 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1104 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
1120 check_round_trip(r, bm2); 1105 check_round_trip(r, bm2);
1121 } 1106 }
1122 1107
1123 static void test_conversion_possible(skiatest::Reporter* r, const char* path, 1108 static void test_conversion_possible(skiatest::Reporter* r, const char* path,
1124 bool testScanlineDecoder) { 1109 bool supportsScanlineDecoder,
1110 bool supportsIncrementalDecoder) {
1125 SkAutoTDelete<SkStream> stream(resource(path)); 1111 SkAutoTDelete<SkStream> stream(resource(path));
1126 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); 1112 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
1127 SkImageInfo infoF16 = codec->getInfo().makeColorType(kRGBA_F16_SkColorType); 1113 SkImageInfo infoF16 = codec->getInfo().makeColorType(kRGBA_F16_SkColorType);
1128 1114
1129 SkBitmap bm; 1115 SkBitmap bm;
1130 bm.allocPixels(infoF16); 1116 bm.allocPixels(infoF16);
1131 SkCodec::Result result = codec->getPixels(infoF16, bm.getPixels(), bm.rowByt es()); 1117 SkCodec::Result result = codec->getPixels(infoF16, bm.getPixels(), bm.rowByt es());
1132 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); 1118 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result);
1133 if (testScanlineDecoder) { 1119
1134 result = codec->startScanlineDecode(infoF16); 1120 result = codec->startScanlineDecode(infoF16);
1121 if (supportsScanlineDecoder) {
1135 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); 1122 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result);
1123 } else {
1124 REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
1125 }
1126
1127 result = codec->startIncrementalDecode(infoF16, bm.getPixels(), bm.rowBytes( ));
1128 if (supportsIncrementalDecoder) {
1129 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result);
1130 } else {
1131 REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
1136 } 1132 }
1137 1133
1138 infoF16 = infoF16.makeColorSpace(infoF16.colorSpace()->makeLinearGamma()); 1134 infoF16 = infoF16.makeColorSpace(infoF16.colorSpace()->makeLinearGamma());
1139 result = codec->getPixels(infoF16, bm.getPixels(), bm.rowBytes()); 1135 result = codec->getPixels(infoF16, bm.getPixels(), bm.rowBytes());
1140 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1136 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
1141 if (testScanlineDecoder) { 1137 result = codec->startScanlineDecode(infoF16);
1142 result = codec->startScanlineDecode(infoF16); 1138 if (supportsScanlineDecoder) {
1143 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1139 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
1140 } else {
1141 REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
1142 }
1143
1144 result = codec->startIncrementalDecode(infoF16, bm.getPixels(), bm.rowBytes( ));
1145 if (supportsIncrementalDecoder) {
1146 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
1147 } else {
1148 REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
1144 } 1149 }
1145 } 1150 }
1146 1151
1147 DEF_TEST(Codec_F16ConversionPossible, r) { 1152 DEF_TEST(Codec_F16ConversionPossible, r) {
1148 test_conversion_possible(r, "color_wheel.webp", false); 1153 test_conversion_possible(r, "color_wheel.webp", false, false);
1149 test_conversion_possible(r, "mandrill_512_q075.jpg", true); 1154 test_conversion_possible(r, "mandrill_512_q075.jpg", true, false);
1150 test_conversion_possible(r, "yellow_rose.png", true); 1155 test_conversion_possible(r, "yellow_rose.png", false, true);
1151 } 1156 }
1157
1158 // Only rewinds up to a limit.
1159 class LimitedRewindingStream : public SkStream {
1160 public:
1161 static SkStream* Make(const char path[], size_t limit) {
1162 SkStream* stream = resource(path);
1163 if (!stream) {
1164 return nullptr;
1165 }
1166 return new LimitedRewindingStream(stream, limit);
1167 }
1168
1169 size_t read(void* buffer, size_t size) override {
1170 const size_t bytes = fStream->read(buffer, size);
1171 fPosition += bytes;
1172 return bytes;
1173 }
1174
1175 bool isAtEnd() const override {
1176 return fStream->isAtEnd();
1177 }
1178
1179 bool rewind() override {
1180 if (fPosition <= fLimit && fStream->rewind()) {
1181 fPosition = 0;
1182 return true;
1183 }
1184
1185 return false;
1186 }
1187
1188 private:
1189 SkAutoTDelete<SkStream> fStream;
1190 const size_t fLimit;
1191 size_t fPosition;
1192
1193 LimitedRewindingStream(SkStream* stream, size_t limit)
1194 : fStream(stream)
1195 , fLimit(limit)
1196 , fPosition(0)
1197 {
1198 SkASSERT(fStream);
1199 }
1200 };
1201
1202 DEF_TEST(Codec_fallBack, r) {
1203 // SkAndroidCodec needs to be able to fall back to scanline decoding
1204 // if incremental decoding does not work. Make sure this does not
1205 // require a rewind.
1206
1207 // Formats that currently do not support incremental decoding
1208 auto files = {
1209 "box.gif",
1210 "CMYK.jpg",
1211 "color_wheel.ico",
1212 "mandrill.wbmp",
1213 "randPixels.bmp",
1214 };
1215 for (auto file : files) {
1216 SkStream* stream = LimitedRewindingStream::Make(file, 14);
1217 if (!stream) {
1218 SkDebugf("Missing resources (%s). Set --resourcePath.\n", file);
1219 return;
1220 }
1221
1222 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
1223 if (!codec) {
1224 ERRORF(r, "Failed to create codec for %s,", file);
1225 continue;
1226 }
1227
1228 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
1229 SkBitmap bm;
1230 bm.allocPixels(info);
1231
1232 if (SkCodec::kUnimplemented != codec->startIncrementalDecode(info, bm.ge tPixels(),
1233 bm.rowBytes())) {
1234 ERRORF(r, "Is scanline decoding now implemented for %s?", file);
1235 continue;
1236 }
1237
1238 // Scanline decoding should not require a rewind.
1239 SkCodec::Result result = codec->startScanlineDecode(info);
1240 if (SkCodec::kSuccess != result) {
1241 ERRORF(r, "Scanline decoding failed for %s with %i", file, result);
1242 }
1243 }
1244 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698