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

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: Make PNG test !incomplete, too 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
« no previous file with comments | « tests/CodecPartialTest.cpp ('k') | tests/ImageTest.cpp » ('j') | 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 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 REPORTER_ASSERT(r, bufferedStream); 433 REPORTER_ASSERT(r, bufferedStream);
373 codec.reset(SkCodec::NewFromStream(bufferedStream)); 434 codec.reset(SkCodec::NewFromStream(bufferedStream));
374 REPORTER_ASSERT(r, codec); 435 REPORTER_ASSERT(r, codec);
375 if (codec) { 436 if (codec) {
376 test_info(r, codec.get(), info, SkCodec::kSuccess, &codecDigest); 437 test_info(r, codec.get(), info, SkCodec::kSuccess, &codecDigest);
377 } 438 }
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,
444 supportsNewScanlineDecoding);
383 } 445 }
384 } 446 }
385 447
386 DEF_TEST(Codec, r) { 448 DEF_TEST(Codec, r) {
387 // WBMP 449 // WBMP
388 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false); 450 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false, true);
389 451
390 // WEBP 452 // WEBP
391 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true); 453 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true, true);
392 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true); 454 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true, true);
393 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true); 455 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true, true);
394 456
395 // BMP 457 // BMP
396 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false); 458 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false, true);
397 check(r, "rle.bmp", SkISize::Make(320, 240), true, false); 459 check(r, "rle.bmp", SkISize::Make(320, 240), true, false, true);
398 460
399 // ICO 461 // ICO
400 // FIXME: We are not ready to test incomplete ICOs 462 // FIXME: We are not ready to test incomplete ICOs
401 // These two tests examine interestingly different behavior: 463 // These two tests examine interestingly different behavior:
402 // Decodes an embedded BMP image 464 // Decodes an embedded BMP image
403 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false); 465 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false);
404 // Decodes an embedded PNG image 466 // Decodes an embedded PNG image
405 check(r, "google_chrome.ico", SkISize::Make(256, 256), true, false, false); 467 check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false, false, true);
406 468
407 // GIF 469 // GIF
408 // FIXME: We are not ready to test incomplete GIFs 470 // FIXME: We are not ready to test incomplete GIFs
409 check(r, "box.gif", SkISize::Make(200, 55), true, false, false); 471 check(r, "box.gif", SkISize::Make(200, 55), true, false, false);
410 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false); 472 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false);
411 // randPixels.gif is too small to test incomplete 473 // randPixels.gif is too small to test incomplete
412 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false); 474 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false);
413 475
414 // JPG 476 // JPG
415 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false); 477 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false, true);
416 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false); 478 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false, true);
417 // grayscale.jpg is too small to test incomplete 479 // grayscale.jpg is too small to test incomplete
418 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false); 480 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false);
419 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false); 481 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false, true );
420 // randPixels.jpg is too small to test incomplete 482 // randPixels.jpg is too small to test incomplete
421 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false); 483 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false);
422 484
423 // PNG 485 // PNG
424 check(r, "arrow.png", SkISize::Make(187, 312), true, false, false); 486 check(r, "arrow.png", SkISize::Make(187, 312), false, false, true, true);
scroggo_chromium 2016/09/15 22:34:54 (Moving your comment to a spot relevant to my poin
msarett 2016/09/16 12:20:16 I think it's a fill() problem. The problem I thou
425 check(r, "baby_tux.png", SkISize::Make(240, 246), true, false, false); 487 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); 488 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); 489 // half-transparent-white-pixel.png is too small to test incomplete
428 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false, false); 490 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); 491 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); 492 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); 493 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); 494 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); 495 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); 496 check(r, "mandrill_64.png", SkISize::Make(64, 64), false, false, true, true) ;
435 // FIXME: We are not ready to test incomplete interlaced pngs 497 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 ); 498 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); 499 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); 500 check(r, "yellow_rose.png", SkISize::Make(400, 301), false, false, true, tru e);
439 501
440 // RAW 502 // RAW
441 // Disable RAW tests for Win32. 503 // Disable RAW tests for Win32.
442 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 504 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32))
443 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false); 505 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); 506 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 ); 507 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false );
446 #endif 508 #endif
447 } 509 }
448 510
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) { 511 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. 512 // 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)); 513 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e));
543 REPORTER_ASSERT(r, !codec); 514 REPORTER_ASSERT(r, !codec);
544 515
545 SkAndroidCodec* androidCodec = 516 SkAndroidCodec* androidCodec =
546 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) ); 517 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) );
547 REPORTER_ASSERT(r, !androidCodec); 518 REPORTER_ASSERT(r, !androidCodec);
548 } 519 }
549 520
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 test_invalid(r, "invalid_images/mask-bmp-ico.ico"); 643 test_invalid(r, "invalid_images/mask-bmp-ico.ico");
673 } 644 }
674 645
675 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { 646 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) {
676 SkAutoTDelete<SkStream> stream(resource(path)); 647 SkAutoTDelete<SkStream> stream(resource(path));
677 if (!stream) { 648 if (!stream) {
678 SkDebugf("Missing resource '%s'\n", path); 649 SkDebugf("Missing resource '%s'\n", path);
679 return; 650 return;
680 } 651 }
681 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release())); 652 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release()));
653 if (!decoder) {
654 SkDebugf("Missing codec for %s\n", path);
655 return;
656 }
657
658 const SkImageInfo info = decoder->getInfo().makeColorType(kIndex_8_SkColorTy pe);
682 659
683 // This should return kSuccess because kIndex8 is supported. 660 // This should return kSuccess because kIndex8 is supported.
684 SkPMColor colorStorage[256]; 661 SkPMColor colorStorage[256];
685 int colorCount; 662 int colorCount;
686 SkCodec::Result result = decoder->startScanlineDecode( 663 SkCodec::Result result = decoder->startScanlineDecode(info, nullptr, colorSt orage,
687 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt orage, &colorCount); 664 &colorCount);
688 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 665 if (SkCodec::kSuccess == result) {
689 // The rest of the test is uninteresting if kIndex8 is not supported 666 // This should return kInvalidParameters because, in kIndex_8 mode, we m ust pass in a valid
690 if (SkCodec::kSuccess != result) { 667 // colorPtr and a valid colorCountPtr.
668 result = decoder->startScanlineDecode(info, nullptr, nullptr, nullptr);
669 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
670 result = decoder->startScanlineDecode(info);
671 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
672 } else if (SkCodec::kUnimplemented == result) {
673 // New method should be supported:
674 SkBitmap bm;
675 sk_sp<SkColorTable> colorTable(new SkColorTable(colorStorage, 256));
676 bm.allocPixels(info, nullptr, colorTable.get());
677 result = decoder->startIncrementalDecode(info, bm.getPixels(), bm.rowByt es(), nullptr,
678 colorStorage, &colorCount);
679 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
680 result = decoder->startIncrementalDecode(info, bm.getPixels(), bm.rowByt es());
681 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
682 } else {
683 // The test is uninteresting if kIndex8 is not supported
684 ERRORF(r, "Should not call test_invalid_parameters for non-Index8 file: %s\n", path);
691 return; 685 return;
692 } 686 }
693 687
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 } 688 }
703 689
704 DEF_TEST(Codec_Params, r) { 690 DEF_TEST(Codec_Params, r) {
705 test_invalid_parameters(r, "index8.png"); 691 test_invalid_parameters(r, "index8.png");
706 test_invalid_parameters(r, "mandrill.wbmp"); 692 test_invalid_parameters(r, "mandrill.wbmp");
707 } 693 }
708 694
709 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 695 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); 696 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
711 if (!sk_stream->write(data, len)) { 697 if (!sk_stream->write(data, len)) {
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 codec.reset(SkCodec::NewFromStream(stream.release())); 1157 codec.reset(SkCodec::NewFromStream(stream.release()));
1172 1158
1173 for (SkAlphaType alphaType : alphaTypes) { 1159 for (SkAlphaType alphaType : alphaTypes) {
1174 SkImageInfo newInfo = codec->getInfo().makeAlphaType(alphaType) 1160 SkImageInfo newInfo = codec->getInfo().makeAlphaType(alphaType)
1175 .makeColorSpace(nullptr); 1161 .makeColorSpace(nullptr);
1176 check_round_trip(r, codec.get(), newInfo); 1162 check_round_trip(r, codec.get(), newInfo);
1177 } 1163 }
1178 } 1164 }
1179 1165
1180 static void test_conversion_possible(skiatest::Reporter* r, const char* path, 1166 static void test_conversion_possible(skiatest::Reporter* r, const char* path,
1181 bool testScanlineDecoder) { 1167 bool supportsScanlineDecoder,
1168 bool supportsIncrementalDecoder) {
1182 SkAutoTDelete<SkStream> stream(resource(path)); 1169 SkAutoTDelete<SkStream> stream(resource(path));
1183 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); 1170 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
1184 SkImageInfo infoF16 = codec->getInfo().makeColorType(kRGBA_F16_SkColorType); 1171 SkImageInfo infoF16 = codec->getInfo().makeColorType(kRGBA_F16_SkColorType);
1185 1172
1186 SkBitmap bm; 1173 SkBitmap bm;
1187 bm.allocPixels(infoF16); 1174 bm.allocPixels(infoF16);
1188 SkCodec::Result result = codec->getPixels(infoF16, bm.getPixels(), bm.rowByt es()); 1175 SkCodec::Result result = codec->getPixels(infoF16, bm.getPixels(), bm.rowByt es());
1189 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); 1176 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result);
1190 if (testScanlineDecoder) { 1177
1191 result = codec->startScanlineDecode(infoF16); 1178 result = codec->startScanlineDecode(infoF16);
1179 if (supportsScanlineDecoder) {
1192 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); 1180 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result);
1181 } else {
1182 REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
1183 }
1184
1185 result = codec->startIncrementalDecode(infoF16, bm.getPixels(), bm.rowBytes( ));
1186 if (supportsIncrementalDecoder) {
1187 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result);
1188 } else {
1189 REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
1193 } 1190 }
1194 1191
1195 infoF16 = infoF16.makeColorSpace(infoF16.colorSpace()->makeLinearGamma()); 1192 infoF16 = infoF16.makeColorSpace(infoF16.colorSpace()->makeLinearGamma());
1196 result = codec->getPixels(infoF16, bm.getPixels(), bm.rowBytes()); 1193 result = codec->getPixels(infoF16, bm.getPixels(), bm.rowBytes());
1197 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1194 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
1198 if (testScanlineDecoder) { 1195 result = codec->startScanlineDecode(infoF16);
1199 result = codec->startScanlineDecode(infoF16); 1196 if (supportsScanlineDecoder) {
1200 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1197 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
1198 } else {
1199 REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
1200 }
1201
1202 result = codec->startIncrementalDecode(infoF16, bm.getPixels(), bm.rowBytes( ));
1203 if (supportsIncrementalDecoder) {
1204 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
1205 } else {
1206 REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
1201 } 1207 }
1202 } 1208 }
1203 1209
1204 DEF_TEST(Codec_F16ConversionPossible, r) { 1210 DEF_TEST(Codec_F16ConversionPossible, r) {
1205 test_conversion_possible(r, "color_wheel.webp", false); 1211 test_conversion_possible(r, "color_wheel.webp", false, false);
1206 test_conversion_possible(r, "mandrill_512_q075.jpg", true); 1212 test_conversion_possible(r, "mandrill_512_q075.jpg", true, false);
1207 test_conversion_possible(r, "yellow_rose.png", true); 1213 test_conversion_possible(r, "yellow_rose.png", false, true);
1208 } 1214 }
1215
1216 // Only rewinds up to a limit.
1217 class LimitedRewindingStream : public SkStream {
1218 public:
1219 static SkStream* Make(const char path[], size_t limit) {
1220 SkStream* stream = resource(path);
1221 if (!stream) {
1222 return nullptr;
1223 }
1224 return new LimitedRewindingStream(stream, limit);
1225 }
1226
1227 size_t read(void* buffer, size_t size) override {
1228 const size_t bytes = fStream->read(buffer, size);
1229 fPosition += bytes;
1230 return bytes;
1231 }
1232
1233 bool isAtEnd() const override {
1234 return fStream->isAtEnd();
1235 }
1236
1237 bool rewind() override {
1238 if (fPosition <= fLimit && fStream->rewind()) {
1239 fPosition = 0;
1240 return true;
1241 }
1242
1243 return false;
1244 }
1245
1246 private:
1247 SkAutoTDelete<SkStream> fStream;
1248 const size_t fLimit;
1249 size_t fPosition;
1250
1251 LimitedRewindingStream(SkStream* stream, size_t limit)
1252 : fStream(stream)
1253 , fLimit(limit)
1254 , fPosition(0)
1255 {
1256 SkASSERT(fStream);
1257 }
1258 };
1259
1260 DEF_TEST(Codec_fallBack, r) {
1261 // SkAndroidCodec needs to be able to fall back to scanline decoding
1262 // if incremental decoding does not work. Make sure this does not
1263 // require a rewind.
1264
1265 // Formats that currently do not support incremental decoding
1266 auto files = {
1267 "box.gif",
1268 "CMYK.jpg",
1269 "color_wheel.ico",
1270 "mandrill.wbmp",
1271 "randPixels.bmp",
1272 };
1273 for (auto file : files) {
1274 SkStream* stream = LimitedRewindingStream::Make(file, 14);
1275 if (!stream) {
1276 SkDebugf("Missing resources (%s). Set --resourcePath.\n", file);
1277 return;
1278 }
1279
1280 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
1281 if (!codec) {
1282 ERRORF(r, "Failed to create codec for %s,", file);
1283 continue;
1284 }
1285
1286 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
1287 SkBitmap bm;
1288 bm.allocPixels(info);
1289
1290 if (SkCodec::kUnimplemented != codec->startIncrementalDecode(info, bm.ge tPixels(),
1291 bm.rowBytes())) {
1292 ERRORF(r, "Is scanline decoding now implemented for %s?", file);
1293 continue;
1294 }
1295
1296 // Scanline decoding should not require a rewind.
1297 SkCodec::Result result = codec->startScanlineDecode(info);
1298 if (SkCodec::kSuccess != result) {
1299 ERRORF(r, "Scanline decoding failed for %s with %i", file, result);
1300 }
1301 }
1302 }
OLDNEW
« no previous file with comments | « tests/CodecPartialTest.cpp ('k') | tests/ImageTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698