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

Side by Side Diff: tests/CodecTest.cpp

Issue 2044573002: Revert of Make SkPngCodec decode progressively. (Closed) Base URL: https://skia.googlesource.com/skia.git@foil
Patch Set: Rebase 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
« no previous file with comments | « tests/CodecPartial.cpp ('k') | tests/ColorSpaceTest.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 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
142 template<typename Codec> 86 template<typename Codec>
143 static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info, 87 static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info,
144 const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* dige st, 88 const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* dige st,
145 const SkMD5::Digest* goodDigest) { 89 const SkMD5::Digest* goodDigest) {
146 90
147 REPORTER_ASSERT(r, info.dimensions() == size); 91 REPORTER_ASSERT(r, info.dimensions() == size);
148 bm.allocPixels(info); 92 bm.allocPixels(info);
149 SkAutoLockPixels autoLockPixels(bm); 93 SkAutoLockPixels autoLockPixels(bm);
150 94
151 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( )); 95 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( ));
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 }; 184 };
241 185
242 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) { 186 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
243 if (SkStrEndsWith(path, exts[i])) { 187 if (SkStrEndsWith(path, exts[i])) {
244 return true; 188 return true;
245 } 189 }
246 } 190 }
247 return false; 191 return false;
248 } 192 }
249 193
250 // FIXME: Break up this giant function
251 static void check(skiatest::Reporter* r, 194 static void check(skiatest::Reporter* r,
252 const char path[], 195 const char path[],
253 SkISize size, 196 SkISize size,
254 bool supportsScanlineDecoding, 197 bool supportsScanlineDecoding,
255 bool supportsSubsetDecoding, 198 bool supportsSubsetDecoding,
256 bool supportsIncomplete, 199 bool supportsIncomplete = true) {
257 bool supportsNewScanlineDecoding = false) {
258 200
259 SkAutoTDelete<SkStream> stream(resource(path)); 201 SkAutoTDelete<SkStream> stream(resource(path));
260 if (!stream) { 202 if (!stream) {
261 SkDebugf("Missing resource '%s'\n", path); 203 SkDebugf("Missing resource '%s'\n", path);
262 return; 204 return;
263 } 205 }
264 206
265 SkAutoTDelete<SkCodec> codec(nullptr); 207 SkAutoTDelete<SkCodec> codec(nullptr);
266 bool isIncomplete = supportsIncomplete; 208 bool isIncomplete = supportsIncomplete;
267 if (isIncomplete) { 209 if (isIncomplete) {
268 size_t size = stream->getLength(); 210 size_t size = stream->getLength();
269 SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))) ; 211 SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))) ;
270 codec.reset(SkCodec::NewFromData(data)); 212 codec.reset(SkCodec::NewFromData(data));
271 } else { 213 } else {
272 codec.reset(SkCodec::NewFromStream(stream.release())); 214 codec.reset(SkCodec::NewFromStream(stream.release()));
273 } 215 }
274 if (!codec) { 216 if (!codec) {
275 ERRORF(r, "Unable to decode '%s'", path); 217 ERRORF(r, "Unable to decode '%s'", path);
276 return; 218 return;
277 } 219 }
278 220
279 // Test full image decodes with SkCodec 221 // Test full image decodes with SkCodec
280 SkMD5::Digest codecDigest; 222 SkMD5::Digest codecDigest;
281 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); 223 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
282 SkBitmap bm; 224 SkBitmap bm;
283 SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess; 225 SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess;
284 test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nul lptr); 226 test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nul lptr);
285 227
286 // Scanline decoding follows. 228 // Scanline decoding follows.
229 // Need to call startScanlineDecode() first.
230 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0)
231 == 0);
232 REPORTER_ASSERT(r, codec->skipScanlines(1)
233 == 0);
287 234
288 if (supportsNewScanlineDecoding && !isIncomplete) {
289 test_incremental_decode(r, codec, info, codecDigest);
290 test_in_stripes(r, codec, info, codecDigest);
291 }
292
293 // Need to call startScanlineDecode() first.
294 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0);
295 REPORTER_ASSERT(r, !codec->skipScanlines(1));
296 const SkCodec::Result startResult = codec->startScanlineDecode(info); 235 const SkCodec::Result startResult = codec->startScanlineDecode(info);
297 if (supportsScanlineDecoding) { 236 if (supportsScanlineDecoding) {
298 bm.eraseColor(SK_ColorYELLOW); 237 bm.eraseColor(SK_ColorYELLOW);
299 238
300 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); 239 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess);
301 240
302 for (int y = 0; y < info.height(); y++) { 241 for (int y = 0; y < info.height(); y++) {
303 const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); 242 const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0);
304 if (!isIncomplete) { 243 if (!isIncomplete) {
305 REPORTER_ASSERT(r, 1 == lines); 244 REPORTER_ASSERT(r, 1 == lines);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 // Webp is the only codec that supports subsets, and it will have mo dified the subset 319 // Webp is the only codec that supports subsets, and it will have mo dified the subset
381 // to have even left/top. 320 // to have even left/top.
382 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo p)); 321 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo p));
383 } else { 322 } else {
384 // No subsets will work. 323 // No subsets will work.
385 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); 324 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented);
386 } 325 }
387 } 326 }
388 327
389 // SkAndroidCodec tests 328 // SkAndroidCodec tests
390 if (supportsScanlineDecoding || supportsSubsetDecoding || supportsNewScanlin eDecoding) { 329 if (supportsScanlineDecoding || supportsSubsetDecoding) {
391 330
392 SkAutoTDelete<SkStream> stream(resource(path)); 331 SkAutoTDelete<SkStream> stream(resource(path));
393 if (!stream) { 332 if (!stream) {
394 SkDebugf("Missing resource '%s'\n", path); 333 SkDebugf("Missing resource '%s'\n", path);
395 return; 334 return;
396 } 335 }
397 336
398 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); 337 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr);
399 if (isIncomplete) { 338 if (isIncomplete) {
400 size_t size = stream->getLength(); 339 size_t size = stream->getLength();
(...skipping 17 matching lines...) Expand all
418 // Test SkCodecImageGenerator 357 // Test SkCodecImageGenerator
419 SkAutoTDelete<SkStream> stream(resource(path)); 358 SkAutoTDelete<SkStream> stream(resource(path));
420 SkAutoTUnref<SkData> fullData(SkData::NewFromStream(stream, stream->getL ength())); 359 SkAutoTUnref<SkData> fullData(SkData::NewFromStream(stream, stream->getL ength()));
421 SkAutoTDelete<SkImageGenerator> gen(SkCodecImageGenerator::NewFromEncode dCodec(fullData)); 360 SkAutoTDelete<SkImageGenerator> gen(SkCodecImageGenerator::NewFromEncode dCodec(fullData));
422 SkBitmap bm; 361 SkBitmap bm;
423 bm.allocPixels(info); 362 bm.allocPixels(info);
424 SkAutoLockPixels autoLockPixels(bm); 363 SkAutoLockPixels autoLockPixels(bm);
425 REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes())); 364 REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes()));
426 compare_to_good_digest(r, codecDigest, bm); 365 compare_to_good_digest(r, codecDigest, bm);
427 366
428 #if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 5 367 // Test using SkFrontBufferedStream, as Android does
429 // FIXME: With older versions of libpng, SkPngCodec requires being able to call 368 SkStream* bufferedStream = SkFrontBufferedStream::Create(new SkMemoryStr eam(fullData),
430 // SkStream::move(), which is not supported by SkFrontBufferedStream. (A ndroid 369 SkCodec::MinBufferedBytesNeeded());
431 // has a more recent version of libpng which uses png_process_data_pause to 370 REPORTER_ASSERT(r, bufferedStream);
432 // avoid calling move().) 371 codec.reset(SkCodec::NewFromStream(bufferedStream));
433 if (!SkStrEndsWith(path, ".png")) 372 REPORTER_ASSERT(r, codec);
434 #endif 373 if (codec) {
435 { 374 test_info(r, codec.get(), info, SkCodec::kSuccess, &codecDigest);
436 // Test using SkFrontBufferedStream, as Android does
437 SkStream* bufferedStream = SkFrontBufferedStream::Create(new SkMemor yStream(fullData),
438 SkCodec::MinBufferedBytesNeeded());
439 REPORTER_ASSERT(r, bufferedStream);
440 codec.reset(SkCodec::NewFromStream(bufferedStream));
441 REPORTER_ASSERT(r, codec);
442 if (codec) {
443 test_info(r, codec.get(), info, SkCodec::kSuccess, &codecDigest) ;
444 }
445 } 375 }
446 } 376 }
447 377
448 // If we've just tested incomplete decodes, let's run the same test again on full decodes. 378 // If we've just tested incomplete decodes, let's run the same test again on full decodes.
449 if (isIncomplete) { 379 if (isIncomplete) {
450 check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, f alse); 380 check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, f alse);
451 } 381 }
452 } 382 }
453 383
454 DEF_TEST(Codec, r) { 384 DEF_TEST(Codec, r) {
455 // WBMP 385 // WBMP
456 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false, true); 386 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false);
457 387
458 // WEBP 388 // WEBP
459 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true, true); 389 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true);
460 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true, true); 390 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true);
461 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true, true); 391 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true);
462 392
463 // BMP 393 // BMP
464 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false, true); 394 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false);
465 check(r, "rle.bmp", SkISize::Make(320, 240), true, false, true); 395 check(r, "rle.bmp", SkISize::Make(320, 240), true, false);
466 396
467 // ICO 397 // ICO
468 // FIXME: We are not ready to test incomplete ICOs 398 // FIXME: We are not ready to test incomplete ICOs
469 // These two tests examine interestingly different behavior: 399 // These two tests examine interestingly different behavior:
470 // Decodes an embedded BMP image 400 // Decodes an embedded BMP image
471 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false); 401 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false);
472 // Decodes an embedded PNG image 402 // Decodes an embedded PNG image
473 check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false, false, true); 403 check(r, "google_chrome.ico", SkISize::Make(256, 256), true, false, false);
474 404
475 // GIF 405 // GIF
476 // FIXME: We are not ready to test incomplete GIFs 406 // FIXME: We are not ready to test incomplete GIFs
477 check(r, "box.gif", SkISize::Make(200, 55), true, false, false); 407 check(r, "box.gif", SkISize::Make(200, 55), true, false, false);
478 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false); 408 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false);
479 // randPixels.gif is too small to test incomplete 409 // randPixels.gif is too small to test incomplete
480 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false); 410 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false);
481 411
482 // JPG 412 // JPG
483 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false, true); 413 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false);
484 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false, true); 414 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false);
485 // grayscale.jpg is too small to test incomplete 415 // grayscale.jpg is too small to test incomplete
486 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false); 416 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false);
487 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false, true ); 417 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false);
488 // randPixels.jpg is too small to test incomplete 418 // randPixels.jpg is too small to test incomplete
489 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false); 419 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false);
490 420
491 // PNG 421 // PNG
492 check(r, "arrow.png", SkISize::Make(187, 312), false, false, true, true); 422 check(r, "arrow.png", SkISize::Make(187, 312), true, false, false);
493 check(r, "baby_tux.png", SkISize::Make(240, 246), false, false, true, true); 423 check(r, "baby_tux.png", SkISize::Make(240, 246), true, false, false);
494 check(r, "color_wheel.png", SkISize::Make(128, 128), false, false, true, tru e); 424 check(r, "color_wheel.png", SkISize::Make(128, 128), true, false, false);
495 // half-transparent-white-pixel.png is too small to test incomplete 425 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, fals e, false);
496 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), false, fal se, false, true); 426 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false, false);
497 check(r, "mandrill_128.png", SkISize::Make(128, 128), false, false, true, tr ue); 427 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false, false);
498 check(r, "mandrill_16.png", SkISize::Make(16, 16), false, false, true, true) ; 428 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false, false);
499 check(r, "mandrill_256.png", SkISize::Make(256, 256), false, false, true, tr ue); 429 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false, false);
500 check(r, "mandrill_32.png", SkISize::Make(32, 32), false, false, true, true) ; 430 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false, false);
501 check(r, "mandrill_512.png", SkISize::Make(512, 512), false, false, true, tr ue); 431 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false, false);
502 check(r, "mandrill_64.png", SkISize::Make(64, 64), false, false, true, true) ; 432 check(r, "plane.png", SkISize::Make(250, 126), true, false, false);
503 check(r, "plane.png", SkISize::Make(250, 126), false, false, true, true); 433 // FIXME: We are not ready to test incomplete interlaced pngs
504 check(r, "plane_interlaced.png", SkISize::Make(250, 126), false, false, true , true); 434 check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false, false );
505 check(r, "randPixels.png", SkISize::Make(8, 8), false, false, true, true); 435 check(r, "randPixels.png", SkISize::Make(8, 8), true, false, false);
506 check(r, "yellow_rose.png", SkISize::Make(400, 301), false, false, true, tru e); 436 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false, false);
507 437
508 // RAW 438 // RAW
509 // Disable RAW tests for Win32. 439 // Disable RAW tests for Win32.
510 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 440 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32))
511 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false); 441 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false);
512 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa lse); 442 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa lse);
513 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false ); 443 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false );
514 #endif 444 #endif
515 } 445 }
516 446
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
517 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) { 538 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) {
518 // Neither of these calls should return a codec. Bots should catch us if we leaked anything. 539 // Neither of these calls should return a codec. Bots should catch us if we leaked anything.
519 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e)); 540 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e));
520 REPORTER_ASSERT(r, !codec); 541 REPORTER_ASSERT(r, !codec);
521 542
522 SkAndroidCodec* androidCodec = 543 SkAndroidCodec* androidCodec =
523 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) ); 544 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) );
524 REPORTER_ASSERT(r, !androidCodec); 545 REPORTER_ASSERT(r, !androidCodec);
525 } 546 }
526 547
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 test_invalid(r, "invalid_images/mask-bmp-ico.ico"); 670 test_invalid(r, "invalid_images/mask-bmp-ico.ico");
650 } 671 }
651 672
652 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { 673 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) {
653 SkAutoTDelete<SkStream> stream(resource(path)); 674 SkAutoTDelete<SkStream> stream(resource(path));
654 if (!stream) { 675 if (!stream) {
655 SkDebugf("Missing resource '%s'\n", path); 676 SkDebugf("Missing resource '%s'\n", path);
656 return; 677 return;
657 } 678 }
658 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release())); 679 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release()));
659 if (!decoder) {
660 SkDebugf("Missing codec for %s\n", path);
661 return;
662 }
663
664 const SkImageInfo info = decoder->getInfo().makeColorType(kIndex_8_SkColorTy pe);
665 680
666 // This should return kSuccess because kIndex8 is supported. 681 // This should return kSuccess because kIndex8 is supported.
667 SkPMColor colorStorage[256]; 682 SkPMColor colorStorage[256];
668 int colorCount; 683 int colorCount;
669 SkCodec::Result result = decoder->startScanlineDecode(info, nullptr, colorSt orage, 684 SkCodec::Result result = decoder->startScanlineDecode(
670 &colorCount); 685 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt orage, &colorCount);
671 if (SkCodec::kSuccess == result) { 686 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
672 // This should return kInvalidParameters because, in kIndex_8 mode, we m ust pass in a valid 687 // The rest of the test is uninteresting if kIndex8 is not supported
673 // colorPtr and a valid colorCountPtr. 688 if (SkCodec::kSuccess != result) {
674 result = decoder->startScanlineDecode(info, nullptr, nullptr, nullptr);
675 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
676 result = decoder->startScanlineDecode(info);
677 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
678 } else if (SkCodec::kUnimplemented == result) {
679 // New method should be supported:
680 SkBitmap bm;
681 sk_sp<SkColorTable> colorTable(new SkColorTable(colorStorage, 256));
682 bm.allocPixels(info, nullptr, colorTable.get());
683 result = decoder->startIncrementalDecode(info, bm.getPixels(), bm.rowByt es(), nullptr,
684 colorStorage, &colorCount);
685 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
686 result = decoder->startIncrementalDecode(info, bm.getPixels(), bm.rowByt es());
687 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
688 } else {
689 // The test is uninteresting if kIndex8 is not supported
690 ERRORF(r, "Should not call test_invalid_parameters for non-Index8 file: %s\n", path);
691 return; 689 return;
692 } 690 }
693 691
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);
694 } 700 }
695 701
696 DEF_TEST(Codec_Params, r) { 702 DEF_TEST(Codec_Params, r) {
697 test_invalid_parameters(r, "index8.png"); 703 test_invalid_parameters(r, "index8.png");
698 test_invalid_parameters(r, "mandrill.wbmp"); 704 test_invalid_parameters(r, "mandrill.wbmp");
699 } 705 }
700 706
701 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 707 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
702 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); 708 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
703 if (!sk_stream->write(data, len)) { 709 if (!sk_stream->write(data, len)) {
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 // Now test an image which is too big. Any image with a larger header (i.e. 1005 // Now test an image which is too big. Any image with a larger header (i.e.
1000 // has bigger width/height) is also too big. 1006 // has bigger width/height) is also too big.
1001 const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header 1007 const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header
1002 0x84, 0x80, 0x00, // W: 65536 1008 0x84, 0x80, 0x00, // W: 65536
1003 0x84, 0x80, 0x00 }; // H: 65536 1009 0x84, 0x80, 0x00 }; // H: 65536
1004 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false)); 1010 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false));
1005 codec.reset(SkCodec::NewFromStream(stream.release())); 1011 codec.reset(SkCodec::NewFromStream(stream.release()));
1006 1012
1007 REPORTER_ASSERT(r, !codec); 1013 REPORTER_ASSERT(r, !codec);
1008 } 1014 }
1009
1010 // Only rewinds up to a limit.
1011 class LimitedRewindingStream : public SkStream {
1012 public:
1013 static SkStream* Make(const char path[], size_t limit) {
1014 SkStream* stream = resource(path);
1015 if (!stream) {
1016 return nullptr;
1017 }
1018 return new LimitedRewindingStream(stream, limit);
1019 }
1020
1021 size_t read(void* buffer, size_t size) override {
1022 const size_t bytes = fStream->read(buffer, size);
1023 fPosition += bytes;
1024 return bytes;
1025 }
1026
1027 bool isAtEnd() const override {
1028 return fStream->isAtEnd();
1029 }
1030
1031 bool rewind() override {
1032 if (fPosition <= fLimit && fStream->rewind()) {
1033 fPosition = 0;
1034 return true;
1035 }
1036
1037 return false;
1038 }
1039
1040 private:
1041 SkAutoTDelete<SkStream> fStream;
1042 const size_t fLimit;
1043 size_t fPosition;
1044
1045 LimitedRewindingStream(SkStream* stream, size_t limit)
1046 : fStream(stream)
1047 , fLimit(limit)
1048 , fPosition(0)
1049 {
1050 SkASSERT(fStream);
1051 }
1052 };
1053
1054 DEF_TEST(Codec_fallBack, r) {
1055 // SkAndroidCodec needs to be able to fall back to scanline decoding
1056 // if incremental decoding does not work. Make sure this does not
1057 // require a rewind.
1058
1059 // Formats that currently do not support incremental decoding
1060 auto files = {
1061 "box.gif",
1062 "CMYK.jpg",
1063 "color_wheel.ico",
1064 "mandrill.wbmp",
1065 "randPixels.bmp",
1066 };
1067 for (auto file : files) {
1068 SkStream* stream = LimitedRewindingStream::Make(file, 14);
1069 if (!stream) {
1070 SkDebugf("Missing resources (%s). Set --resourcePath.\n", file);
1071 return;
1072 }
1073
1074 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
1075 if (!codec) {
1076 ERRORF(r, "Failed to create codec for %s,", file);
1077 continue;
1078 }
1079
1080 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
1081 SkBitmap bm;
1082 bm.allocPixels(info);
1083
1084 if (SkCodec::kUnimplemented != codec->startIncrementalDecode(info, bm.ge tPixels(),
1085 bm.rowBytes())) {
1086 ERRORF(r, "Is scanline decoding now implemented for %s?", file);
1087 continue;
1088 }
1089
1090 // Scanline decoding should not require a rewind.
1091 SkCodec::Result result = codec->startScanlineDecode(info);
1092 if (SkCodec::kSuccess != result) {
1093 ERRORF(r, "Scanline decoding failed for %s with %i", file, result);
1094 }
1095 }
1096 }
OLDNEW
« no previous file with comments | « tests/CodecPartial.cpp ('k') | tests/ColorSpaceTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698