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

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: Use aligned memory in swizzler test 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 | « bench/subset/SubsetZoomBench.cpp ('k') | gyp/codec.gyp » ('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 "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 an incomplete image. This ensures any uniniti alized
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());
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(currentSubsetWidth, current SubsetHeight); 437 SkIRect bounds = SkIRect::MakeWH(currentSubsetWidth, current SubsetHeight);
445 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun ds)); 438 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun ds));
446 SkAutoLockPixels autlockSubsetBm(subsetBm, true); 439 SkAutoLockPixels autlockSubsetBm(subsetBm, true);
447 const SkCodec::Result subsetResult = 440 codec->getScanlines(buffer, currentSubsetHeight, rowBytes);
448 codec->getScanlines(buffer, currentSubsetHeight, row Bytes); 441
449 switch (subsetResult) {
450 case SkCodec::kSuccess:
451 case SkCodec::kIncompleteInput:
452 break;
453 default:
454 return SkStringPrintf("%s failed with error message %d",
455 fPath.c_str(), (int) subsetResult);
456 }
457 const size_t bpp = decodeInfo.bytesPerPixel(); 442 const size_t bpp = decodeInfo.bytesPerPixel();
458 /*
459 * we copy all the lines at once becuase when calling getSca nlines for
460 * interlaced pngs the entire image must be read regardless of the number
461 * of lines requested. Reading an interlaced png in a loop, line-by-line, would
462 * decode the entire image height times, which is very slow
463 * it is aknowledged that copying each line as you read it i n a loop
464 * may be faster for other types of images. Since this is a correctness test
465 * that's okay.
466 */
467 char* bufferRow = buffer; 443 char* bufferRow = buffer;
468 for (int subsetY = 0; subsetY < currentSubsetHeight; ++subse tY) { 444 for (int subsetY = 0; subsetY < currentSubsetHeight; ++subse tY) {
469 memcpy(subsetBm.getAddr(0, subsetY), bufferRow + x*bpp, 445 memcpy(subsetBm.getAddr(0, subsetY), bufferRow + x*bpp,
470 currentSubsetWidth*bpp); 446 currentSubsetWidth*bpp);
471 bufferRow += rowBytes; 447 bufferRow += rowBytes;
472 } 448 }
473 449
474 subsetBm.notifyPixelsChanged(); 450 subsetBm.notifyPixelsChanged();
475 canvas->drawBitmap(subsetBm, SkIntToScalar(x), SkIntToScalar (y)); 451 canvas->drawBitmap(subsetBm, SkIntToScalar(x), SkIntToScalar (y));
476 } 452 }
477 } 453 }
478 break; 454 break;
479 } 455 }
480 case kStripe_Mode: { 456 case kStripe_Mode: {
481 const int height = decodeInfo.height(); 457 const int height = decodeInfo.height();
482 // This value is chosen arbitrarily. We exercise more cases by choo sing a value that 458 // This value is chosen arbitrarily. We exercise more cases by choo sing a value that
483 // does not align with image blocks. 459 // does not align with image blocks.
484 const int stripeHeight = 37; 460 const int stripeHeight = 37;
485 const int numStripes = (height + stripeHeight - 1) / stripeHeight; 461 const int numStripes = (height + stripeHeight - 1) / stripeHeight;
486 462
487 // Decode odd stripes 463 // Decode odd stripes
488 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL , colorPtr, 464 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL , colorPtr,
489 colorCountPtr) 465 colorCountPtr)
490 || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOr der()) { 466 || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOr der()) {
491 // This mode was designed to test the new skip scanlines API in libjpeg-turbo. 467 // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
492 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting 468 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
493 // to run this test for image types that do not have this scanli ne ordering. 469 // to run this test for image types that do not have this scanli ne ordering.
494 return Error::Nonfatal("Could not start top-down scanline decode r"); 470 return Error::Nonfatal("Could not start top-down scanline decode r");
495 } 471 }
472
496 for (int i = 0; i < numStripes; i += 2) { 473 for (int i = 0; i < numStripes; i += 2) {
497 // Skip a stripe 474 // Skip a stripe
498 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe Height); 475 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe Height);
499 SkCodec::Result result = codec->skipScanlines(linesToSkip); 476 codec->skipScanlines(linesToSkip);
500 switch (result) {
501 case SkCodec::kSuccess:
502 case SkCodec::kIncompleteInput:
503 break;
504 default:
505 return SkStringPrintf("Cannot skip scanlines for %s.", f Path.c_str());
506 }
507 477
508 // Read a stripe 478 // Read a stripe
509 const int startY = (i + 1) * stripeHeight; 479 const int startY = (i + 1) * stripeHeight;
510 const int linesToRead = SkTMin(stripeHeight, height - startY); 480 const int linesToRead = SkTMin(stripeHeight, height - startY);
511 if (linesToRead > 0) { 481 if (linesToRead > 0) {
512 result = codec->getScanlines(bitmap.getAddr(0, startY), 482 codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
513 linesToRead, bitmap.rowBytes());
514 switch (result) {
515 case SkCodec::kSuccess:
516 case SkCodec::kIncompleteInput:
517 break;
518 default:
519 return SkStringPrintf("Cannot get scanlines for %s." , fPath.c_str());
520 }
521 } 483 }
522 } 484 }
523 485
524 // Decode even stripes 486 // Decode even stripes
525 const SkCodec::Result startResult = codec->startScanlineDecode(decod eInfo, nullptr, 487 const SkCodec::Result startResult = codec->startScanlineDecode(decod eInfo, nullptr,
526 colorPtr, colorCountPtr); 488 colorPtr, colorCountPtr);
527 if (SkCodec::kSuccess != startResult) { 489 if (SkCodec::kSuccess != startResult) {
528 return "Failed to restart scanline decoder with same parameters. "; 490 return "Failed to restart scanline decoder with same parameters. ";
529 } 491 }
530 for (int i = 0; i < numStripes; i += 2) { 492 for (int i = 0; i < numStripes; i += 2) {
531 // Read a stripe 493 // Read a stripe
532 const int startY = i * stripeHeight; 494 const int startY = i * stripeHeight;
533 const int linesToRead = SkTMin(stripeHeight, height - startY); 495 const int linesToRead = SkTMin(stripeHeight, height - startY);
534 SkCodec::Result result = codec->getScanlines(bitmap.getAddr(0, s tartY), 496 codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitm ap.rowBytes());
535 linesToRead, bitmap.rowBytes());
536 switch (result) {
537 case SkCodec::kSuccess:
538 case SkCodec::kIncompleteInput:
539 break;
540 default:
541 return SkStringPrintf("Cannot get scanlines for %s.", fP ath.c_str());
542 }
543 497
544 // Skip a stripe 498 // Skip a stripe
545 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight); 499 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
546 if (linesToSkip > 0) { 500 if (linesToSkip > 0) {
547 result = codec->skipScanlines(linesToSkip); 501 codec->skipScanlines(linesToSkip);
548 switch (result) {
549 case SkCodec::kSuccess:
550 case SkCodec::kIncompleteInput:
551 break;
552 default:
553 return SkStringPrintf("Cannot skip scanlines for %s. ", fPath.c_str());
554 }
555 } 502 }
556 } 503 }
557 canvas->drawBitmap(bitmap, 0, 0); 504 canvas->drawBitmap(bitmap, 0, 0);
558 break; 505 break;
559 } 506 }
560 case kSubset_Mode: { 507 case kSubset_Mode: {
561 // Arbitrarily choose a divisor. 508 // Arbitrarily choose a divisor.
562 int divisor = 2; 509 int divisor = 2;
563 // Total width/height of the image. 510 // Total width/height of the image.
564 const int W = codec->getInfo().width(); 511 const int W = codec->getInfo().width();
(...skipping 20 matching lines...) Expand all
585 for (int x = 0; x < W; x += w) { 532 for (int x = 0; x < W; x += w) {
586 int top = 0; 533 int top = 0;
587 for (int y = 0; y < H; y+= h) { 534 for (int y = 0; y < H; y+= h) {
588 // Do not make the subset go off the edge of the image. 535 // Do not make the subset go off the edge of the image.
589 const int preScaleW = SkTMin(w, W - x); 536 const int preScaleW = SkTMin(w, W - x);
590 const int preScaleH = SkTMin(h, H - y); 537 const int preScaleH = SkTMin(h, H - y);
591 subset.setXYWH(x, y, preScaleW, preScaleH); 538 subset.setXYWH(x, y, preScaleW, preScaleH);
592 // And scale 539 // And scale
593 // FIXME: Should we have a version of getScaledDimensions th at takes a subset 540 // FIXME: Should we have a version of getScaledDimensions th at takes a subset
594 // into account? 541 // into account?
595 decodeInfo = decodeInfo.makeWH(SkScalarRoundToInt(preScaleW * fScale), 542 decodeInfo = decodeInfo.makeWH(
596 SkScalarRoundToInt(preScaleH * fScale)); 543 SkTMax(1, SkScalarRoundToInt(preScaleW * fScale)),
544 SkTMax(1, SkScalarRoundToInt(preScaleH * fScale)));
597 size_t rowBytes = decodeInfo.minRowBytes(); 545 size_t rowBytes = decodeInfo.minRowBytes();
598 if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, co lorTable.get(), 546 if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, co lorTable.get(),
599 nullptr, nullptr)) { 547 nullptr, nullptr)) {
600 return SkStringPrintf("could not install pixels for %s." , fPath.c_str()); 548 return SkStringPrintf("could not install pixels for %s." , fPath.c_str());
601 } 549 }
602 const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes, 550 const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes,
603 &opts, colorPtr, colorCountPtr); 551 &opts, colorPtr, colorCountPtr);
604 switch (result) { 552 switch (result) {
605 case SkCodec::kSuccess: 553 case SkCodec::kSuccess:
606 case SkCodec::kIncompleteInput: 554 case SkCodec::kIncompleteInput:
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 skr.visit<void>(i, drawsAsSingletonPictures); 1204 skr.visit<void>(i, drawsAsSingletonPictures);
1257 } 1205 }
1258 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); 1206 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture());
1259 1207
1260 canvas->drawPicture(macroPic); 1208 canvas->drawPicture(macroPic);
1261 return ""; 1209 return "";
1262 }); 1210 });
1263 } 1211 }
1264 1212
1265 } // namespace DM 1213 } // namespace DM
OLDNEW
« no previous file with comments | « bench/subset/SubsetZoomBench.cpp ('k') | gyp/codec.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698