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

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: Add explanatory comment 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
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "Resources.h" 8 #include "Resources.h"
9 #include "SkAndroidCodec.h" 9 #include "SkAndroidCodec.h"
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 do { 76 do {
77 rect.fLeft = rand->nextRangeU(0, w); 77 rect.fLeft = rand->nextRangeU(0, w);
78 rect.fTop = rand->nextRangeU(0, h); 78 rect.fTop = rand->nextRangeU(0, h);
79 rect.fRight = rand->nextRangeU(0, w); 79 rect.fRight = rand->nextRangeU(0, w);
80 rect.fBottom = rand->nextRangeU(0, h); 80 rect.fBottom = rand->nextRangeU(0, h);
81 rect.sort(); 81 rect.sort();
82 } while (rect.isEmpty()); 82 } while (rect.isEmpty());
83 return rect; 83 return rect;
84 } 84 }
85 85
86 static void test_incremental_decode(skiatest::Reporter* r, SkCodec* codec, const SkImageInfo& info,
87 const SkMD5::Digest& goodDigest) {
88 SkBitmap bm;
89 bm.allocPixels(info);
90 SkAutoLockPixels autoLockPixels(bm);
91
92 REPORTER_ASSERT(r, SkCodec::kSuccess == codec->startIncrementalDecode(info, bm.getPixels(),
93 bm.row Bytes()));
94
95 REPORTER_ASSERT(r, SkCodec::kSuccess == codec->incrementalDecode());
96
97 compare_to_good_digest(r, goodDigest, bm);
98 }
99
100 // Test in stripes, similar to DM's kStripe_Mode
101 static void test_in_stripes(skiatest::Reporter* r, SkCodec* codec, const SkImage Info& info,
102 const SkMD5::Digest& goodDigest) {
103 SkBitmap bm;
104 bm.allocPixels(info);
105 bm.eraseColor(SK_ColorYELLOW);
106
107 const int height = info.height();
108 // Note that if numStripes does not evenly divide height there will be an ex tra
109 // stripe.
110 const int numStripes = 4;
111
112 if (numStripes > height) {
113 // Image is too small.
114 return;
115 }
116
117 const int stripeHeight = height / numStripes;
118
119 // Iterate through the image twice. Once to decode odd stripes, and once for even.
120 for (int oddEven = 1; oddEven >= 0; oddEven--) {
121 for (int y = oddEven * stripeHeight; y < height; y += 2 * stripeHeight) {
122 SkIRect subset = SkIRect::MakeLTRB(0, y, info.width(),
123 SkTMin(y + stripeHeight, height)) ;
124 SkCodec::Options options;
125 options.fSubset = &subset;
126 if (SkCodec::kSuccess != codec->startIncrementalDecode(info, bm.getA ddr(0, y),
127 bm.rowBytes(), &options)) {
128 ERRORF(r, "failed to start incremental decode!\ttop: %i\tbottom% i\n",
129 subset.top(), subset.bottom());
130 return;
131 }
132 if (SkCodec::kSuccess != codec->incrementalDecode()) {
133 ERRORF(r, "failed incremental decode starting from line %i\n", y );
134 return;
135 }
136 }
137 }
138
139 compare_to_good_digest(r, goodDigest, bm);
140 }
141
86 template<typename Codec> 142 template<typename Codec>
87 static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info, 143 static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info,
88 const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* dige st, 144 const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* dige st,
89 const SkMD5::Digest* goodDigest) { 145 const SkMD5::Digest* goodDigest) {
90 146
91 REPORTER_ASSERT(r, info.dimensions() == size); 147 REPORTER_ASSERT(r, info.dimensions() == size);
92 bm.allocPixels(info); 148 bm.allocPixels(info);
93 SkAutoLockPixels autoLockPixels(bm); 149 SkAutoLockPixels autoLockPixels(bm);
94 150
95 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( )); 151 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( ));
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 }; 240 };
185 241
186 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) { 242 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
187 if (SkStrEndsWith(path, exts[i])) { 243 if (SkStrEndsWith(path, exts[i])) {
188 return true; 244 return true;
189 } 245 }
190 } 246 }
191 return false; 247 return false;
192 } 248 }
193 249
250 // FIXME: Break up this giant function
194 static void check(skiatest::Reporter* r, 251 static void check(skiatest::Reporter* r,
195 const char path[], 252 const char path[],
196 SkISize size, 253 SkISize size,
197 bool supportsScanlineDecoding, 254 bool supportsScanlineDecoding,
198 bool supportsSubsetDecoding, 255 bool supportsSubsetDecoding,
199 bool supportsIncomplete = true) { 256 bool supportsIncomplete,
257 bool supportsNewScanlineDecoding = false) {
200 258
201 SkAutoTDelete<SkStream> stream(resource(path)); 259 SkAutoTDelete<SkStream> stream(resource(path));
202 if (!stream) { 260 if (!stream) {
203 SkDebugf("Missing resource '%s'\n", path); 261 SkDebugf("Missing resource '%s'\n", path);
204 return; 262 return;
205 } 263 }
206 264
207 SkAutoTDelete<SkCodec> codec(nullptr); 265 SkAutoTDelete<SkCodec> codec(nullptr);
208 bool isIncomplete = supportsIncomplete; 266 bool isIncomplete = supportsIncomplete;
209 if (isIncomplete) { 267 if (isIncomplete) {
210 size_t size = stream->getLength(); 268 size_t size = stream->getLength();
211 SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))) ; 269 SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))) ;
212 codec.reset(SkCodec::NewFromData(data)); 270 codec.reset(SkCodec::NewFromData(data));
213 } else { 271 } else {
214 codec.reset(SkCodec::NewFromStream(stream.release())); 272 codec.reset(SkCodec::NewFromStream(stream.release()));
215 } 273 }
216 if (!codec) { 274 if (!codec) {
217 ERRORF(r, "Unable to decode '%s'", path); 275 ERRORF(r, "Unable to decode '%s'", path);
218 return; 276 return;
219 } 277 }
220 278
221 // Test full image decodes with SkCodec 279 // Test full image decodes with SkCodec
222 SkMD5::Digest codecDigest; 280 SkMD5::Digest codecDigest;
223 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); 281 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
224 SkBitmap bm; 282 SkBitmap bm;
225 SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess; 283 SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess;
226 test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nul lptr); 284 test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nul lptr);
227 285
228 // Scanline decoding follows. 286 // Scanline decoding follows.
287
288 if (supportsNewScanlineDecoding && !isIncomplete) {
289 test_incremental_decode(r, codec, info, codecDigest);
290 test_in_stripes(r, codec, info, codecDigest);
291 }
292
229 // Need to call startScanlineDecode() first. 293 // Need to call startScanlineDecode() first.
230 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 294 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0);
231 == 0); 295 REPORTER_ASSERT(r, !codec->skipScanlines(1));
232 REPORTER_ASSERT(r, codec->skipScanlines(1)
233 == 0);
234
235 const SkCodec::Result startResult = codec->startScanlineDecode(info); 296 const SkCodec::Result startResult = codec->startScanlineDecode(info);
236 if (supportsScanlineDecoding) { 297 if (supportsScanlineDecoding) {
237 bm.eraseColor(SK_ColorYELLOW); 298 bm.eraseColor(SK_ColorYELLOW);
238 299
239 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); 300 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess);
240 301
241 for (int y = 0; y < info.height(); y++) { 302 for (int y = 0; y < info.height(); y++) {
242 const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); 303 const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0);
243 if (!isIncomplete) { 304 if (!isIncomplete) {
244 REPORTER_ASSERT(r, 1 == lines); 305 REPORTER_ASSERT(r, 1 == lines);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 // Webp is the only codec that supports subsets, and it will have mo dified the subset 380 // Webp is the only codec that supports subsets, and it will have mo dified the subset
320 // to have even left/top. 381 // to have even left/top.
321 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo p)); 382 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo p));
322 } else { 383 } else {
323 // No subsets will work. 384 // No subsets will work.
324 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); 385 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented);
325 } 386 }
326 } 387 }
327 388
328 // SkAndroidCodec tests 389 // SkAndroidCodec tests
329 if (supportsScanlineDecoding || supportsSubsetDecoding) { 390 if (supportsScanlineDecoding || supportsSubsetDecoding || supportsNewScanlin eDecoding) {
330 391
331 SkAutoTDelete<SkStream> stream(resource(path)); 392 SkAutoTDelete<SkStream> stream(resource(path));
332 if (!stream) { 393 if (!stream) {
333 SkDebugf("Missing resource '%s'\n", path); 394 SkDebugf("Missing resource '%s'\n", path);
334 return; 395 return;
335 } 396 }
336 397
337 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); 398 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr);
338 if (isIncomplete) { 399 if (isIncomplete) {
339 size_t size = stream->getLength(); 400 size_t size = stream->getLength();
(...skipping 17 matching lines...) Expand all
357 // Test SkCodecImageGenerator 418 // Test SkCodecImageGenerator
358 SkAutoTDelete<SkStream> stream(resource(path)); 419 SkAutoTDelete<SkStream> stream(resource(path));
359 SkAutoTUnref<SkData> fullData(SkData::NewFromStream(stream, stream->getL ength())); 420 SkAutoTUnref<SkData> fullData(SkData::NewFromStream(stream, stream->getL ength()));
360 SkAutoTDelete<SkImageGenerator> gen(SkCodecImageGenerator::NewFromEncode dCodec(fullData)); 421 SkAutoTDelete<SkImageGenerator> gen(SkCodecImageGenerator::NewFromEncode dCodec(fullData));
361 SkBitmap bm; 422 SkBitmap bm;
362 bm.allocPixels(info); 423 bm.allocPixels(info);
363 SkAutoLockPixels autoLockPixels(bm); 424 SkAutoLockPixels autoLockPixels(bm);
364 REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes())); 425 REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes()));
365 compare_to_good_digest(r, codecDigest, bm); 426 compare_to_good_digest(r, codecDigest, bm);
366 427
367 // Test using SkFrontBufferedStream, as Android does 428 #if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 5
368 SkStream* bufferedStream = SkFrontBufferedStream::Create(new SkMemoryStr eam(fullData), 429 // FIXME: With older versions of libpng, SkPngCodec requires being able to call
369 SkCodec::MinBufferedBytesNeeded()); 430 // SkStream::move(), which is not supported by SkFrontBufferedStream. (A ndroid
370 REPORTER_ASSERT(r, bufferedStream); 431 // has a more recent version of libpng which uses png_process_data_pause to
371 codec.reset(SkCodec::NewFromStream(bufferedStream)); 432 // avoid calling move().)
372 REPORTER_ASSERT(r, codec); 433 if (!SkStrEndsWith(path, ".png"))
373 if (codec) { 434 #endif
374 test_info(r, codec.get(), info, SkCodec::kSuccess, &codecDigest); 435 {
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 }
375 } 445 }
376 } 446 }
377 447
378 // If we've just tested incomplete decodes, let's run the same test again on full decodes. 448 // If we've just tested incomplete decodes, let's run the same test again on full decodes.
379 if (isIncomplete) { 449 if (isIncomplete) {
380 check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, f alse); 450 check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, f alse);
381 } 451 }
382 } 452 }
383 453
384 DEF_TEST(Codec, r) { 454 DEF_TEST(Codec, r) {
385 // WBMP 455 // WBMP
386 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false); 456 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false, true);
387 457
388 // WEBP 458 // WEBP
389 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true); 459 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true, true);
390 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true); 460 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true, true);
391 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true); 461 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true, true);
392 462
393 // BMP 463 // BMP
394 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false); 464 check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false, true);
395 check(r, "rle.bmp", SkISize::Make(320, 240), true, false); 465 check(r, "rle.bmp", SkISize::Make(320, 240), true, false, true);
396 466
397 // ICO 467 // ICO
398 // FIXME: We are not ready to test incomplete ICOs 468 // FIXME: We are not ready to test incomplete ICOs
399 // These two tests examine interestingly different behavior: 469 // These two tests examine interestingly different behavior:
400 // Decodes an embedded BMP image 470 // Decodes an embedded BMP image
401 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false); 471 check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false);
402 // Decodes an embedded PNG image 472 // Decodes an embedded PNG image
403 check(r, "google_chrome.ico", SkISize::Make(256, 256), true, false, false); 473 check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false, false, true);
404 474
405 // GIF 475 // GIF
406 // FIXME: We are not ready to test incomplete GIFs 476 // FIXME: We are not ready to test incomplete GIFs
407 check(r, "box.gif", SkISize::Make(200, 55), true, false, false); 477 check(r, "box.gif", SkISize::Make(200, 55), true, false, false);
408 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false); 478 check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, false);
409 // randPixels.gif is too small to test incomplete 479 // randPixels.gif is too small to test incomplete
410 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false); 480 check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false);
411 481
412 // JPG 482 // JPG
413 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false); 483 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false, true);
414 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false); 484 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false, true);
415 // grayscale.jpg is too small to test incomplete 485 // grayscale.jpg is too small to test incomplete
416 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false); 486 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false);
417 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false); 487 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false, true );
418 // randPixels.jpg is too small to test incomplete 488 // randPixels.jpg is too small to test incomplete
419 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false); 489 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false);
420 490
421 // PNG 491 // PNG
422 check(r, "arrow.png", SkISize::Make(187, 312), true, false, false); 492 check(r, "arrow.png", SkISize::Make(187, 312), false, false, true, true);
423 check(r, "baby_tux.png", SkISize::Make(240, 246), true, false, false); 493 check(r, "baby_tux.png", SkISize::Make(240, 246), false, false, true, true);
424 check(r, "color_wheel.png", SkISize::Make(128, 128), true, false, false); 494 check(r, "color_wheel.png", SkISize::Make(128, 128), false, false, true, tru e);
425 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, fals e, false); 495 // half-transparent-white-pixel.png is too small to test incomplete
426 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false, false); 496 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), false, fal se, false, true);
427 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false, false); 497 check(r, "mandrill_128.png", SkISize::Make(128, 128), false, false, true, tr ue);
428 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false, false); 498 check(r, "mandrill_16.png", SkISize::Make(16, 16), false, false, true, true) ;
429 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false, false); 499 check(r, "mandrill_256.png", SkISize::Make(256, 256), false, false, true, tr ue);
430 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false, false); 500 check(r, "mandrill_32.png", SkISize::Make(32, 32), false, false, true, true) ;
431 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false, false); 501 check(r, "mandrill_512.png", SkISize::Make(512, 512), false, false, true, tr ue);
432 check(r, "plane.png", SkISize::Make(250, 126), true, false, false); 502 check(r, "mandrill_64.png", SkISize::Make(64, 64), false, false, true, true) ;
433 // FIXME: We are not ready to test incomplete interlaced pngs 503 check(r, "plane.png", SkISize::Make(250, 126), false, false, true, true);
434 check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false, false ); 504 check(r, "plane_interlaced.png", SkISize::Make(250, 126), false, false, true , true);
435 check(r, "randPixels.png", SkISize::Make(8, 8), true, false, false); 505 check(r, "randPixels.png", SkISize::Make(8, 8), false, false, true, true);
436 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false, false); 506 check(r, "yellow_rose.png", SkISize::Make(400, 301), false, false, true, tru e);
437 507
438 // RAW 508 // RAW
439 // Disable RAW tests for Win32. 509 // Disable RAW tests for Win32.
440 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 510 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32))
441 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false); 511 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false);
442 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa lse); 512 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa lse);
443 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false ); 513 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false );
444 #endif 514 #endif
445 } 515 }
446 516
447 // Test interlaced PNG in stripes, similar to DM's kStripe_Mode
448 DEF_TEST(Codec_stripes, r) {
449 const char * path = "plane_interlaced.png";
450 SkAutoTDelete<SkStream> stream(resource(path));
451 if (!stream) {
452 SkDebugf("Missing resource '%s'\n", path);
453 }
454
455 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
456 REPORTER_ASSERT(r, codec);
457
458 if (!codec) {
459 return;
460 }
461
462 switch (codec->getScanlineOrder()) {
463 case SkCodec::kBottomUp_SkScanlineOrder:
464 case SkCodec::kOutOfOrder_SkScanlineOrder:
465 ERRORF(r, "This scanline order will not match the original.");
466 return;
467 default:
468 break;
469 }
470
471 // Baseline for what the image should look like, using N32.
472 const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
473
474 SkBitmap bm;
475 bm.allocPixels(info);
476 SkAutoLockPixels autoLockPixels(bm);
477 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes( ));
478 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
479
480 SkMD5::Digest digest;
481 md5(bm, &digest);
482
483 // Now decode in stripes
484 const int height = info.height();
485 const int numStripes = 4;
486 int stripeHeight;
487 int remainingLines;
488 SkTDivMod(height, numStripes, &stripeHeight, &remainingLines);
489
490 bm.eraseColor(SK_ColorYELLOW);
491
492 result = codec->startScanlineDecode(info);
493 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
494
495 // Odd stripes
496 for (int i = 1; i < numStripes; i += 2) {
497 // Skip the even stripes
498 bool skipResult = codec->skipScanlines(stripeHeight);
499 REPORTER_ASSERT(r, skipResult);
500
501 int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
502 bm.rowBytes());
503 REPORTER_ASSERT(r, linesDecoded == stripeHeight);
504 }
505
506 // Even stripes
507 result = codec->startScanlineDecode(info);
508 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
509
510 for (int i = 0; i < numStripes; i += 2) {
511 int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
512 bm.rowBytes());
513 REPORTER_ASSERT(r, linesDecoded == stripeHeight);
514
515 // Skip the odd stripes
516 if (i + 1 < numStripes) {
517 bool skipResult = codec->skipScanlines(stripeHeight);
518 REPORTER_ASSERT(r, skipResult);
519 }
520 }
521
522 // Remainder at the end
523 if (remainingLines > 0) {
524 result = codec->startScanlineDecode(info);
525 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
526
527 bool skipResult = codec->skipScanlines(height - remainingLines);
528 REPORTER_ASSERT(r, skipResult);
529
530 int linesDecoded = codec->getScanlines(bm.getAddr(0, height - remainingL ines),
531 remainingLines, bm.rowBytes());
532 REPORTER_ASSERT(r, linesDecoded == remainingLines);
533 }
534
535 compare_to_good_digest(r, digest, bm);
536 }
537
538 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) { 517 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) {
539 // Neither of these calls should return a codec. Bots should catch us if we leaked anything. 518 // Neither of these calls should return a codec. Bots should catch us if we leaked anything.
540 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e)); 519 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e));
541 REPORTER_ASSERT(r, !codec); 520 REPORTER_ASSERT(r, !codec);
542 521
543 SkAndroidCodec* androidCodec = 522 SkAndroidCodec* androidCodec =
544 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) ); 523 SkAndroidCodec::NewFromStream(new SkMemoryStream(stream, len, false) );
545 REPORTER_ASSERT(r, !androidCodec); 524 REPORTER_ASSERT(r, !androidCodec);
546 } 525 }
547 526
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 test_invalid(r, "invalid_images/mask-bmp-ico.ico"); 649 test_invalid(r, "invalid_images/mask-bmp-ico.ico");
671 } 650 }
672 651
673 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { 652 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) {
674 SkAutoTDelete<SkStream> stream(resource(path)); 653 SkAutoTDelete<SkStream> stream(resource(path));
675 if (!stream) { 654 if (!stream) {
676 SkDebugf("Missing resource '%s'\n", path); 655 SkDebugf("Missing resource '%s'\n", path);
677 return; 656 return;
678 } 657 }
679 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release())); 658 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);
680 665
681 // This should return kSuccess because kIndex8 is supported. 666 // This should return kSuccess because kIndex8 is supported.
682 SkPMColor colorStorage[256]; 667 SkPMColor colorStorage[256];
683 int colorCount; 668 int colorCount;
684 SkCodec::Result result = decoder->startScanlineDecode( 669 SkCodec::Result result = decoder->startScanlineDecode(info, nullptr, colorSt orage,
685 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt orage, &colorCount); 670 &colorCount);
686 REPORTER_ASSERT(r, SkCodec::kSuccess == result); 671 if (SkCodec::kSuccess == result) {
687 // The rest of the test is uninteresting if kIndex8 is not supported 672 // This should return kInvalidParameters because, in kIndex_8 mode, we m ust pass in a valid
688 if (SkCodec::kSuccess != result) { 673 // colorPtr and a valid colorCountPtr.
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);
689 return; 691 return;
690 } 692 }
691 693
692 // This should return kInvalidParameters because, in kIndex_8 mode, we must pass in a valid
693 // colorPtr and a valid colorCountPtr.
694 result = decoder->startScanlineDecode(
695 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, nullptr , nullptr);
696 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
697 result = decoder->startScanlineDecode(
698 decoder->getInfo().makeColorType(kIndex_8_SkColorType));
699 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
700 } 694 }
701 695
702 DEF_TEST(Codec_Params, r) { 696 DEF_TEST(Codec_Params, r) {
703 test_invalid_parameters(r, "index8.png"); 697 test_invalid_parameters(r, "index8.png");
704 test_invalid_parameters(r, "mandrill.wbmp"); 698 test_invalid_parameters(r, "mandrill.wbmp");
705 } 699 }
706 700
707 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 701 static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
708 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); 702 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
709 if (!sk_stream->write(data, len)) { 703 if (!sk_stream->write(data, len)) {
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 // Now test an image which is too big. Any image with a larger header (i.e. 999 // Now test an image which is too big. Any image with a larger header (i.e.
1006 // has bigger width/height) is also too big. 1000 // has bigger width/height) is also too big.
1007 const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header 1001 const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header
1008 0x84, 0x80, 0x00, // W: 65536 1002 0x84, 0x80, 0x00, // W: 65536
1009 0x84, 0x80, 0x00 }; // H: 65536 1003 0x84, 0x80, 0x00 }; // H: 65536
1010 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false)); 1004 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false));
1011 codec.reset(SkCodec::NewFromStream(stream.release())); 1005 codec.reset(SkCodec::NewFromStream(stream.release()));
1012 1006
1013 REPORTER_ASSERT(r, !codec); 1007 REPORTER_ASSERT(r, !codec);
1014 } 1008 }
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
« src/codec/SkPngCodec.cpp ('K') | « tests/CodecPartial.cpp ('k') | tests/ColorSpaceTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698