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

Side by Side Diff: dm/DMSrcSink.cpp

Issue 1332053002: Fill incomplete images in SkCodec parent class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to comments in Patch Set 5 Created 5 years, 2 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 | « no previous file | gyp/tools.gyp » ('j') | include/codec/SkCodec.h » ('J')
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 "DMSrcSink.h" 8 #include "DMSrcSink.h"
9 #include "SamplePipeControllers.h" 9 #include "SamplePipeControllers.h"
10 #include "SkCodec.h" 10 #include "SkCodec.h"
(...skipping 10 matching lines...) Expand all
21 #include "SkPictureData.h" 21 #include "SkPictureData.h"
22 #include "SkPictureRecorder.h" 22 #include "SkPictureRecorder.h"
23 #include "SkRandom.h" 23 #include "SkRandom.h"
24 #include "SkRecordDraw.h" 24 #include "SkRecordDraw.h"
25 #include "SkRecorder.h" 25 #include "SkRecorder.h"
26 #include "SkSVGCanvas.h" 26 #include "SkSVGCanvas.h"
27 #include "SkScaledCodec.h" 27 #include "SkScaledCodec.h"
28 #include "SkStream.h" 28 #include "SkStream.h"
29 #include "SkTLogic.h" 29 #include "SkTLogic.h"
30 #include "SkXMLWriter.h" 30 #include "SkXMLWriter.h"
31 #include "SkScaledCodec.h"
32 #include "SkSwizzler.h"
31 33
32 DEFINE_bool(multiPage, false, "For document-type backends, render the source" 34 DEFINE_bool(multiPage, false, "For document-type backends, render the source"
33 " into multiple pages"); 35 " into multiple pages");
34 36
35 static bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) { 37 static bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) {
36 SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size)); 38 SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size));
37 return encoded && SkDEPRECATED_InstallDiscardablePixelRef(encoded, dst); 39 return encoded && SkDEPRECATED_InstallDiscardablePixelRef(encoded, dst);
38 } 40 }
39 41
40 namespace DM { 42 namespace DM {
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 } 335 }
334 canvas->drawBitmap(bitmap, 0, 0); 336 canvas->drawBitmap(bitmap, 0, 0);
335 break; 337 break;
336 } 338 }
337 case kScanline_Mode: { 339 case kScanline_Mode: {
338 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL , colorPtr, 340 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL , colorPtr,
339 colorCountPtr)) { 341 colorCountPtr)) {
340 return Error::Nonfatal("Could not start scanline decoder"); 342 return Error::Nonfatal("Could not start scanline decoder");
341 } 343 }
342 344
343 SkCodec::Result result = SkCodec::kUnimplemented; 345 void* dst = bitmap.getAddr(0, 0);
346 size_t rowBytes = bitmap.rowBytes();
347 uint32_t height = decodeInfo.height();
344 switch (codec->getScanlineOrder()) { 348 switch (codec->getScanlineOrder()) {
345 case SkCodec::kTopDown_SkScanlineOrder: 349 case SkCodec::kTopDown_SkScanlineOrder:
346 case SkCodec::kBottomUp_SkScanlineOrder: 350 case SkCodec::kBottomUp_SkScanlineOrder:
347 case SkCodec::kNone_SkScanlineOrder: 351 case SkCodec::kNone_SkScanlineOrder:
348 result = codec->getScanlines(bitmap.getAddr(0, 0), 352 // We do not need to check the return value. On an incomple te
349 decodeInfo.height(), bitmap.rowBytes()); 353 // image, memory will be filled with a default value.
354 codec->getScanlines(dst, height, rowBytes);
350 break; 355 break;
351 case SkCodec::kOutOfOrder_SkScanlineOrder: { 356 case SkCodec::kOutOfOrder_SkScanlineOrder: {
352 for (int y = 0; y < decodeInfo.height(); y++) { 357 for (int y = 0; y < decodeInfo.height(); y++) {
353 int dstY = codec->nextScanline(); 358 int dstY = codec->outputScanline(y);
354 void* dstPtr = bitmap.getAddr(0, dstY); 359 void* dstPtr = bitmap.getAddr(0, dstY);
355 result = codec->getScanlines(dstPtr, 1, bitmap.rowBytes( )); 360 // We complete the loop, even if this call begins to fai l
356 if (SkCodec::kSuccess != result && SkCodec::kIncompleteI nput != result) { 361 // due to incomplete image. This ensures any uninitiali zed
357 return SkStringPrintf("%s failed with error message %d", 362 // memory will be filled with the proper value.
358 fPath.c_str(), (int) result); 363 codec->getScanlines(dstPtr, 1, bitmap.rowBytes());
msarett 2015/10/01 18:14:14 Thanks for your thorough review of how the scanlin
scroggo 2015/10/01 20:48:58 I mentioned this as a response to an older comment
msarett 2015/10/01 22:34:51 Thanks for your thoughts. I'll respond to this as
359 }
360 } 364 }
361 break; 365 break;
362 } 366 }
363 } 367 }
364 368
365 switch (result) {
366 case SkCodec::kSuccess:
367 case SkCodec::kIncompleteInput:
368 break;
369 default:
370 return SkStringPrintf("%s failed with error message %d",
371 fPath.c_str(), (int) result);
372 }
373 canvas->drawBitmap(bitmap, 0, 0); 369 canvas->drawBitmap(bitmap, 0, 0);
374 break; 370 break;
375 } 371 }
376 case kScanline_Subset_Mode: { 372 case kScanline_Subset_Mode: {
377 //this mode decodes the image in divisor*divisor subsets, using a sc anline decoder 373 //this mode decodes the image in divisor*divisor subsets, using a sc anline decoder
378 const int divisor = 2; 374 const int divisor = 2;
379 const int w = decodeInfo.width(); 375 const int w = decodeInfo.width();
380 const int h = decodeInfo.height(); 376 const int h = decodeInfo.height();
381 if (divisor > w || divisor > h) { 377 if (divisor > w || divisor > h) {
382 return Error::Nonfatal(SkStringPrintf("Cannot decode subset: div isor %d is too big" 378 return Error::Nonfatal(SkStringPrintf("Cannot decode subset: div isor %d is too big"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 colorCou ntPtr) 418 colorCou ntPtr)
423 // TODO (msarett): Support this mode for all scanlin e orderings. 419 // TODO (msarett): Support this mode for all scanlin e orderings.
424 || SkCodec::kTopDown_SkScanlineOrder != codec->getSc anlineOrder()) { 420 || SkCodec::kTopDown_SkScanlineOrder != codec->getSc anlineOrder()) {
425 if (x == 0 && y == 0) { 421 if (x == 0 && y == 0) {
426 //first try, image may not be compatible 422 //first try, image may not be compatible
427 return Error::Nonfatal("Could not start top-down sca nline decoder"); 423 return Error::Nonfatal("Could not start top-down sca nline decoder");
428 } else { 424 } else {
429 return "Error scanline decoder is nullptr"; 425 return "Error scanline decoder is nullptr";
430 } 426 }
431 } 427 }
432 //skip to first line of subset 428 // Skip to the first line of subset. We ignore the result v alue here.
433 const SkCodec::Result skipResult = codec->skipScanlines(y); 429 // If the skip value fails, this will indicate an incomplete image.
434 switch (skipResult) { 430 // This means that the call to getScanlines() will also fail , but it
435 case SkCodec::kSuccess: 431 // will fill the buffer with a default value, so we can stil l draw the
436 case SkCodec::kIncompleteInput: 432 // image.
437 break; 433 codec->skipScanlines(y);
438 default: 434
439 return SkStringPrintf("%s failed after attempting to skip %d scanlines"
440 "with error message %d", fPath.c_str(), y, ( int) skipResult);
441 }
442 //create and set size of subsetBm 435 //create and set size of subsetBm
443 SkBitmap subsetBm; 436 SkBitmap subsetBm;
444 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); 437 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight);
445 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight ); 438 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight );
446 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun ds)); 439 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun ds));
447 SkAutoLockPixels autlockSubsetBm(subsetBm, true); 440 SkAutoLockPixels autlockSubsetBm(subsetBm, true);
448 const SkCodec::Result subsetResult = 441 codec->getScanlines(buffer, currentSubsetHeight, rowBytes);
449 codec->getScanlines(buffer, currentSubsetHeight, row Bytes); 442
450 switch (subsetResult) {
451 case SkCodec::kSuccess:
452 case SkCodec::kIncompleteInput:
453 break;
454 default:
455 return SkStringPrintf("%s failed with error message %d",
456 fPath.c_str(), (int) subsetResult);
457 }
458 const size_t bpp = decodeInfo.bytesPerPixel(); 443 const size_t bpp = decodeInfo.bytesPerPixel();
459 /*
460 * we copy all the lines at once becuase when calling getSca nlines for
461 * interlaced pngs the entire image must be read regardless of the number
462 * of lines requested. Reading an interlaced png in a loop, line-by-line, would
463 * decode the entire image height times, which is very slow
464 * it is aknowledged that copying each line as you read it i n a loop
465 * may be faster for other types of images. Since this is a correctness test
466 * that's okay.
467 */
468 char* bufferRow = buffer; 444 char* bufferRow = buffer;
469 for (int subsetY = 0; subsetY < currentSubsetHeight; ++subse tY) { 445 for (int subsetY = 0; subsetY < currentSubsetHeight; ++subse tY) {
470 memcpy(subsetBm.getAddr(0, subsetY), bufferRow + x*bpp, 446 memcpy(subsetBm.getAddr(0, subsetY), bufferRow + x*bpp,
471 currentSubsetWidth*bpp); 447 currentSubsetWidth*bpp);
472 bufferRow += rowBytes; 448 bufferRow += rowBytes;
473 } 449 }
474 450
475 subsetBm.notifyPixelsChanged(); 451 subsetBm.notifyPixelsChanged();
476 canvas->drawBitmap(subsetBm, SkIntToScalar(x), SkIntToScalar (y)); 452 canvas->drawBitmap(subsetBm, SkIntToScalar(x), SkIntToScalar (y));
477 } 453 }
478 } 454 }
479 break; 455 break;
480 } 456 }
481 case kStripe_Mode: { 457 case kStripe_Mode: {
482 const int height = decodeInfo.height(); 458 const int height = decodeInfo.height();
483 // This value is chosen arbitrarily. We exercise more cases by choo sing a value that 459 // This value is chosen arbitrarily. We exercise more cases by choo sing a value that
484 // does not align with image blocks. 460 // does not align with image blocks.
485 const int stripeHeight = 37; 461 const int stripeHeight = 37;
486 const int numStripes = (height + stripeHeight - 1) / stripeHeight; 462 const int numStripes = (height + stripeHeight - 1) / stripeHeight;
487 463
488 // Decode odd stripes 464 // Decode odd stripes
489 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL , colorPtr, 465 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL , colorPtr,
490 colorCountPtr) 466 colorCountPtr)
491 || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOr der()) { 467 || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOr der()) {
492 // This mode was designed to test the new skip scanlines API in libjpeg-turbo. 468 // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
493 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting 469 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
494 // to run this test for image types that do not have this scanli ne ordering. 470 // to run this test for image types that do not have this scanli ne ordering.
495 return Error::Nonfatal("Could not start top-down scanline decode r"); 471 return Error::Nonfatal("Could not start top-down scanline decode r");
496 } 472 }
473
497 for (int i = 0; i < numStripes; i += 2) { 474 for (int i = 0; i < numStripes; i += 2) {
498 // Skip a stripe 475 // Skip a stripe
499 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe Height); 476 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe Height);
500 SkCodec::Result result = codec->skipScanlines(linesToSkip); 477 codec->skipScanlines(linesToSkip);
501 switch (result) {
502 case SkCodec::kSuccess:
503 case SkCodec::kIncompleteInput:
504 break;
505 default:
506 return SkStringPrintf("Cannot skip scanlines for %s.", f Path.c_str());
507 }
508 478
509 // Read a stripe 479 // Read a stripe
510 const int startY = (i + 1) * stripeHeight; 480 const int startY = (i + 1) * stripeHeight;
511 const int linesToRead = SkTMin(stripeHeight, height - startY); 481 const int linesToRead = SkTMin(stripeHeight, height - startY);
512 if (linesToRead > 0) { 482 if (linesToRead > 0) {
513 result = codec->getScanlines(bitmap.getAddr(0, startY), 483 codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
514 linesToRead, bitmap.rowBytes());
515 switch (result) {
516 case SkCodec::kSuccess:
517 case SkCodec::kIncompleteInput:
518 break;
519 default:
520 return SkStringPrintf("Cannot get scanlines for %s." , fPath.c_str());
521 }
522 } 484 }
523 } 485 }
524 486
525 // Decode even stripes 487 // Decode even stripes
526 const SkCodec::Result startResult = codec->startScanlineDecode(decod eInfo, nullptr, 488 const SkCodec::Result startResult = codec->startScanlineDecode(decod eInfo, nullptr,
527 colorPtr, colorCountPtr); 489 colorPtr, colorCountPtr);
528 if (SkCodec::kSuccess != startResult) { 490 if (SkCodec::kSuccess != startResult) {
529 return "Failed to restart scanline decoder with same parameters. "; 491 return "Failed to restart scanline decoder with same parameters. ";
530 } 492 }
531 for (int i = 0; i < numStripes; i += 2) { 493 for (int i = 0; i < numStripes; i += 2) {
532 // Read a stripe 494 // Read a stripe
533 const int startY = i * stripeHeight; 495 const int startY = i * stripeHeight;
534 const int linesToRead = SkTMin(stripeHeight, height - startY); 496 const int linesToRead = SkTMin(stripeHeight, height - startY);
535 SkCodec::Result result = codec->getScanlines(bitmap.getAddr(0, s tartY), 497 codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitm ap.rowBytes());
536 linesToRead, bitmap.rowBytes());
537 switch (result) {
538 case SkCodec::kSuccess:
539 case SkCodec::kIncompleteInput:
540 break;
541 default:
542 return SkStringPrintf("Cannot get scanlines for %s.", fP ath.c_str());
543 }
544 498
545 // Skip a stripe 499 // Skip a stripe
546 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight); 500 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
547 if (linesToSkip > 0) { 501 if (linesToSkip > 0) {
548 result = codec->skipScanlines(linesToSkip); 502 codec->skipScanlines(linesToSkip);
549 switch (result) {
550 case SkCodec::kSuccess:
551 case SkCodec::kIncompleteInput:
552 break;
553 default:
554 return SkStringPrintf("Cannot skip scanlines for %s. ", fPath.c_str());
555 }
556 } 503 }
557 } 504 }
558 canvas->drawBitmap(bitmap, 0, 0); 505 canvas->drawBitmap(bitmap, 0, 0);
559 break; 506 break;
560 } 507 }
561 case kSubset_Mode: { 508 case kSubset_Mode: {
562 // Arbitrarily choose a divisor. 509 // Arbitrarily choose a divisor.
563 int divisor = 2; 510 int divisor = 2;
564 // Total width/height of the image. 511 // Total width/height of the image.
565 const int W = codec->getInfo().width(); 512 const int W = codec->getInfo().width();
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
1255 skr.visit<void>(i, drawsAsSingletonPictures); 1202 skr.visit<void>(i, drawsAsSingletonPictures);
1256 } 1203 }
1257 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); 1204 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture());
1258 1205
1259 canvas->drawPicture(macroPic); 1206 canvas->drawPicture(macroPic);
1260 return ""; 1207 return "";
1261 }); 1208 });
1262 } 1209 }
1263 1210
1264 } // namespace DM 1211 } // namespace DM
OLDNEW
« no previous file with comments | « no previous file | gyp/tools.gyp » ('j') | include/codec/SkCodec.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698