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

Side by Side Diff: src/codec/SkPngCodec.cpp

Issue 1671003004: Skip memcpy() swizzles in SkPngCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Try making a single call to read_rows Created 4 years, 10 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 | « src/codec/SkPngCodec.h ('k') | no next file » | 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 "SkCodecPriv.h" 8 #include "SkCodecPriv.h"
9 #include "SkColorPriv.h" 9 #include "SkColorPriv.h"
10 #include "SkColorTable.h" 10 #include "SkColorTable.h"
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, nullptr); 366 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, nullptr);
367 fPng_ptr = nullptr; 367 fPng_ptr = nullptr;
368 fInfo_ptr = nullptr; 368 fInfo_ptr = nullptr;
369 } 369 }
370 } 370 }
371 371
372 /////////////////////////////////////////////////////////////////////////////// 372 ///////////////////////////////////////////////////////////////////////////////
373 // Getting the pixels 373 // Getting the pixels
374 /////////////////////////////////////////////////////////////////////////////// 374 ///////////////////////////////////////////////////////////////////////////////
375 375
376 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, 376 void SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, const Opti ons& options) {
377 const Options& options, 377 const SkPMColor* colors = get_color_ptr(fColorTable.get());
378 SkPMColor ctable[], 378 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , options));
379 int* ctableCount) { 379 SkASSERT(fSwizzler);
380 }
381
382 SkCodec::Result SkPngCodec::prepareToDecode(const SkImageInfo& requestedInfo,
383 const Options& options,
384 SkPMColor ctable[],
385 int* ctableCount) {
380 // FIXME: Could we use the return value of setjmp to specify the type of 386 // FIXME: Could we use the return value of setjmp to specify the type of
381 // error? 387 // error?
382 if (setjmp(png_jmpbuf(fPng_ptr))) { 388 if (setjmp(png_jmpbuf(fPng_ptr))) {
383 SkCodecPrintf("setjmp long jump!\n"); 389 SkCodecPrintf("setjmp long jump!\n");
384 return kInvalidInput; 390 return kInvalidInput;
385 } 391 }
386 png_read_update_info(fPng_ptr, fInfo_ptr); 392 png_read_update_info(fPng_ptr, fInfo_ptr);
387 393
388 // suggestedColorType was determined in read_header() based on the encodedCo lorType 394 // suggestedColorType was determined in read_header() based on the encodedCo lorType
389 const SkColorType suggestedColorType = this->getInfo().colorType(); 395 const SkColorType suggestedColorType = this->getInfo().colorType();
390 396
397 // If the conversion provided by the swizzler would be a no-op, we may be ab le
398 // to skip the swizzle step.
399 bool skipSwizzle = false;
400
391 switch (suggestedColorType) { 401 switch (suggestedColorType) {
392 case kIndex_8_SkColorType: 402 case kIndex_8_SkColorType:
393 //decode palette to Skia format
394 fSrcConfig = SkSwizzler::kIndex; 403 fSrcConfig = SkSwizzler::kIndex;
404 skipSwizzle = (kIndex_8_SkColorType == requestedInfo.colorType());
405
406 // Decode palette to Skia format
395 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaT ype(), 407 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaT ype(),
396 ctableCount)) { 408 ctableCount)) {
397 return kInvalidInput; 409 return kInvalidInput;
398 } 410 }
399 break; 411 break;
400 case kGray_8_SkColorType: 412 case kGray_8_SkColorType:
401 fSrcConfig = SkSwizzler::kGray; 413 fSrcConfig = SkSwizzler::kGray;
414 skipSwizzle = (kGray_8_SkColorType == requestedInfo.colorType());
402 break; 415 break;
403 case kN32_SkColorType: { 416 case kN32_SkColorType: {
404 const uint8_t encodedColorType = png_get_color_type(fPng_ptr, fInfo_ ptr); 417 const uint8_t encodedColorType = png_get_color_type(fPng_ptr, fInfo_ ptr);
405 if (PNG_COLOR_TYPE_GRAY_ALPHA == encodedColorType || 418 if (PNG_COLOR_TYPE_GRAY_ALPHA == encodedColorType ||
406 PNG_COLOR_TYPE_GRAY == encodedColorType) { 419 PNG_COLOR_TYPE_GRAY == encodedColorType) {
407 // If encodedColorType is GRAY, there must be a transparent chun k. 420 // If encodedColorType is GRAY, there must be a transparent chun k.
408 // Otherwise, suggestedColorType would be kGray. We have alread y 421 // Otherwise, suggestedColorType would be kGray. We have alread y
409 // instructed libpng to convert the transparent chunk to alpha, 422 // instructed libpng to convert the transparent chunk to alpha,
410 // so we can treat both GRAY and GRAY_ALPHA as kGrayAlpha. 423 // so we can treat both GRAY and GRAY_ALPHA as kGrayAlpha.
411 SkASSERT(encodedColorType == PNG_COLOR_TYPE_GRAY_ALPHA || 424 SkASSERT(encodedColorType == PNG_COLOR_TYPE_GRAY_ALPHA ||
412 png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)); 425 png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS));
413 426
414 fSrcConfig = SkSwizzler::kGrayAlpha; 427 fSrcConfig = SkSwizzler::kGrayAlpha;
415 } else { 428 } else {
416 if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { 429 if (this->getInfo().alphaType() == kOpaque_SkAlphaType) {
417 fSrcConfig = SkSwizzler::kRGB; 430 fSrcConfig = SkSwizzler::kRGB;
418 } else { 431 } else {
419 fSrcConfig = SkSwizzler::kRGBA; 432 fSrcConfig = SkSwizzler::kRGBA;
433 #ifdef SK_PMCOLOR_IS_RGBA
434 skipSwizzle = (kUnpremul_SkAlphaType == this->getInfo().alph aType());
435 #endif
420 } 436 }
421 } 437 }
422 break; 438 break;
423 } 439 }
424 default: 440 default:
425 // We will always recommend one of the above colorTypes. 441 // We will always recommend one of the above colorTypes.
426 SkASSERT(false); 442 SkASSERT(false);
427 } 443 }
428 444
429 // Copy the color table to the client if they request kIndex8 mode 445 // Copy the color table to the client if they request kIndex8 mode
430 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); 446 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount);
431 447
448 // If this is a subset decode, we will need a swizzler.
449 if (options.fSubset) {
450 skipSwizzle = false;
451 }
452
432 // Create the swizzler. SkPngCodec retains ownership of the color table. 453 // Create the swizzler. SkPngCodec retains ownership of the color table.
433 const SkPMColor* colors = get_color_ptr(fColorTable.get()); 454 if (!skipSwizzle) {
434 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , options)); 455 this->initializeSwizzler(requestedInfo, options);
435 SkASSERT(fSwizzler); 456 }
436 457
437 return kSuccess; 458 return kSuccess;
438 } 459 }
439 460
461 SkSampler* SkPngCodec::getSampler(bool createIfNecessary) {
462 if (!createIfNecessary || fSwizzler) {
463 return fSwizzler;
464 }
465
466 this->initializeSwizzler(this->dstInfo(), this->options());
467 return fSwizzler;
468 }
440 469
441 bool SkPngCodec::onRewind() { 470 bool SkPngCodec::onRewind() {
442 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header 471 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header
443 // succeeds, they will be repopulated, and if it fails, they will 472 // succeeds, they will be repopulated, and if it fails, they will
444 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will 473 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will
445 // come through this function which will rewind and again attempt 474 // come through this function which will rewind and again attempt
446 // to reinitialize them. 475 // to reinitialize them.
447 this->destroyReadStruct(); 476 this->destroyReadStruct();
448 477
449 png_structp png_ptr; 478 png_structp png_ptr;
(...skipping 14 matching lines...) Expand all
464 int* rowsDecoded) { 493 int* rowsDecoded) {
465 if (!conversion_possible(requestedInfo, this->getInfo())) { 494 if (!conversion_possible(requestedInfo, this->getInfo())) {
466 return kInvalidConversion; 495 return kInvalidConversion;
467 } 496 }
468 if (options.fSubset) { 497 if (options.fSubset) {
469 // Subsets are not supported. 498 // Subsets are not supported.
470 return kUnimplemented; 499 return kUnimplemented;
471 } 500 }
472 501
473 // Note that ctable and ctableCount may be modified if there is a color tabl e 502 // Note that ctable and ctableCount may be modified if there is a color tabl e
474 const Result result = this->initializeSwizzler(requestedInfo, options, ctabl e, ctableCount); 503 const Result result = this->prepareToDecode(requestedInfo, options, ctable, ctableCount);
475 if (result != kSuccess) { 504 if (result != kSuccess) {
476 return result; 505 return result;
477 } 506 }
507
508 const int width = requestedInfo.width();
509 const int height = requestedInfo.height();
510 const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig);
511
478 // FIXME: Could we use the return value of setjmp to specify the type of 512 // FIXME: Could we use the return value of setjmp to specify the type of
479 // error? 513 // error?
480 int row = 0; 514 int row = 0;
481 // This must be declared above the call to setjmp to avoid memory leaks on i ncomplete images. 515 // This must be declared above the call to setjmp to avoid memory leaks on i ncomplete images.
482 SkAutoTMalloc<uint8_t> storage; 516 SkAutoTMalloc<uint8_t> storage;
483 if (setjmp(png_jmpbuf(fPng_ptr))) { 517 if (setjmp(png_jmpbuf(fPng_ptr))) {
484 // Assume that any error that occurs while reading rows is caused by an incomplete input. 518 // Assume that any error that occurs while reading rows is caused by an incomplete input.
485 if (fNumberPasses > 1) { 519 if (fNumberPasses > 1) {
486 // FIXME (msarett): Handle incomplete interlaced pngs. 520 // FIXME (msarett): Handle incomplete interlaced pngs.
487 return kInvalidInput; 521 return row == height ? kSuccess : kInvalidInput;
488 } 522 }
489 // FIXME: We do a poor job on incomplete pngs compared to other decoders (ex: Chromium, 523 // FIXME: We do a poor job on incomplete pngs compared to other decoders (ex: Chromium,
490 // Ubuntu Image Viewer). This is because we use the default buffer size in libpng (8192 524 // Ubuntu Image Viewer). This is because we use the default buffer size in libpng (8192
491 // bytes), and if we can't fill the buffer, we immediately fail. 525 // bytes), and if we can't fill the buffer, we immediately fail.
492 // For example, if we try to read 8192 bytes, and the image (incorrectly ) only contains 526 // For example, if we try to read 8192 bytes, and the image (incorrectly ) only contains
493 // half that, which may have been enough to contain a non-zero number of lines, we fail 527 // half that, which may have been enough to contain a non-zero number of lines, we fail
494 // when we could have decoded a few more lines and then failed. 528 // when we could have decoded a few more lines and then failed.
495 // The read function that we provide for libpng has no way of indicating that we have 529 // The read function that we provide for libpng has no way of indicating that we have
496 // made a partial read. 530 // made a partial read.
497 // Making our buffer size smaller improves our incomplete decodes, but w hat impact does 531 // Making our buffer size smaller improves our incomplete decodes, but w hat impact does
498 // it have on regular decode performance? Should we investigate using a different API 532 // it have on regular decode performance? Should we investigate using a different API
499 // instead of png_read_row(s)? Chromium uses png_process_data. 533 // instead of png_read_row(s)? Chromium uses png_process_data.
500 *rowsDecoded = row; 534 *rowsDecoded = row;
501 return kIncompleteInput; 535 return row == height ? kSuccess : kIncompleteInput;
502 } 536 }
503 537
504 // FIXME: We could split these out based on subclass. 538 // FIXME: We could split these out based on subclass.
505 void* dstRow = dst;
506 if (fNumberPasses > 1) { 539 if (fNumberPasses > 1) {
507 const int width = requestedInfo.width();
508 const int height = requestedInfo.height();
509 const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig);
510 const size_t srcRowBytes = width * bpp; 540 const size_t srcRowBytes = width * bpp;
541 const size_t rowBytes = fSwizzler ? srcRowBytes : dstRowBytes;
542 uint8_t* const base = fSwizzler ? storage.reset(width * height * bpp) : (uint8_t*) dst;
543 for (int i = 0; i < fNumberPasses; i++) {
544 uint8_t* rowPtr = base;
545 for (int y = 0; y < height; y++) {
546 png_read_rows(fPng_ptr, &rowPtr, nullptr, 1);
547 rowPtr += rowBytes;
548 }
549 }
511 550
512 storage.reset(width * height * bpp); 551 // Swizzle if necessary.
513 uint8_t* const base = storage.get(); 552 if (fSwizzler) {
514
515 for (int i = 0; i < fNumberPasses; i++) {
516 uint8_t* srcRow = base; 553 uint8_t* srcRow = base;
517 for (int y = 0; y < height; y++) { 554 for (int y = 0; y < height; y++) {
518 uint8_t* bmRow = srcRow; 555 fSwizzler->swizzle(dst, srcRow);
519 png_read_rows(fPng_ptr, &bmRow, nullptr, 1); 556 dst = SkTAddOffset<void>(dst, dstRowBytes);
520 srcRow += srcRowBytes; 557 srcRow += srcRowBytes;
521 } 558 }
522 } 559 }
523 560 } else {
524 // Now swizzle it. 561 if (fSwizzler) {
525 uint8_t* srcRow = base; 562 uint8_t* rowPtr = storage.reset(width * bpp);
526 for (int y = 0; y < height; y++) { 563 for (; row < requestedInfo.height(); row++) {
527 fSwizzler->swizzle(dstRow, srcRow); 564 png_read_rows(fPng_ptr, &rowPtr, nullptr, 1);
528 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); 565 fSwizzler->swizzle(dst, rowPtr);
529 srcRow += srcRowBytes; 566 dst = SkTAddOffset<void>(dst, dstRowBytes);
567 }
568 } else {
569 uint8_t* rowPtr = (uint8_t*) dst;
570 SkAutoMalloc storage(sizeof(uint8_t*) * requestedInfo.height());
571 uint8_t** ptrs = (uint8_t**) storage.get();
572 for (int i = 0; i < requestedInfo.height(); i++) {
573 ptrs[i] = rowPtr;
574 rowPtr += dstRowBytes;
575 }
576 png_read_rows(fPng_ptr, ptrs, nullptr, requestedInfo.height());
530 } 577 }
531 } else {
532 storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(fSrcConf ig));
533 uint8_t* srcRow = storage.get();
534 for (; row < requestedInfo.height(); row++) {
535 png_read_rows(fPng_ptr, &srcRow, nullptr, 1);
536 // FIXME: Only call IsOpaque once, outside the loop. Same for onGetS canlines.
537 fSwizzler->swizzle(dstRow, srcRow);
538 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
539 }
540 }
541
542 if (setjmp(png_jmpbuf(fPng_ptr))) {
543 // We've already read all the scanlines. This is a success.
544 return kSuccess;
545 } 578 }
546 579
547 // read rest of file, and get additional comment and time chunks in info_ptr 580 // read rest of file, and get additional comment and time chunks in info_ptr
548 png_read_end(fPng_ptr, fInfo_ptr); 581 png_read_end(fPng_ptr, fInfo_ptr);
549 582
550 return kSuccess; 583 return kSuccess;
551 } 584 }
552 585
553 uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const { 586 uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const {
554 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 587 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
(...skipping 11 matching lines...) Expand all
566 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1 ) 599 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1 )
567 , fSrcRow(nullptr) 600 , fSrcRow(nullptr)
568 {} 601 {}
569 602
570 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 603 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
571 SkPMColor ctable[], int* ctableCount) override { 604 SkPMColor ctable[], int* ctableCount) override {
572 if (!conversion_possible(dstInfo, this->getInfo())) { 605 if (!conversion_possible(dstInfo, this->getInfo())) {
573 return kInvalidConversion; 606 return kInvalidConversion;
574 } 607 }
575 608
576 const Result result = this->initializeSwizzler(dstInfo, options, ctable, 609 const Result result = this->prepareToDecode(dstInfo, options, ctable, ct ableCount);
577 ctableCount);
578 if (result != kSuccess) { 610 if (result != kSuccess) {
579 return result; 611 return result;
580 } 612 }
581 613
582 fStorage.reset(this->getInfo().width() * SkSwizzler::BytesPerPixel(this- >srcConfig())); 614 fStorage.reset(this->getInfo().width() * SkSwizzler::BytesPerPixel(this- >srcConfig()));
583 fSrcRow = fStorage.get(); 615 fSrcRow = fStorage.get();
584 616
585 return kSuccess; 617 return kSuccess;
586 } 618 }
587 619
588 int onGetScanlines(void* dst, int count, size_t rowBytes) override { 620 int onGetScanlines(void* dst, int count, size_t rowBytes) override {
589 // Assume that an error in libpng indicates an incomplete input. 621 // Assume that an error in libpng indicates an incomplete input.
590 int row = 0; 622 int row = 0;
591 if (setjmp(png_jmpbuf(this->png_ptr()))) { 623 if (setjmp(png_jmpbuf(this->png_ptr()))) {
592 SkCodecPrintf("setjmp long jump!\n"); 624 SkCodecPrintf("setjmp long jump!\n");
593 return row; 625 return row;
594 } 626 }
595 627
596 void* dstRow = dst; 628 uint8_t* rowPtr;
629 if (this->swizzler()) {
630 rowPtr = fSrcRow;
631 } else {
632 // Write decoded pixels directly to dst.
633 rowPtr = (uint8_t*) dst;
634 }
635
597 for (; row < count; row++) { 636 for (; row < count; row++) {
598 png_read_rows(this->png_ptr(), &fSrcRow, nullptr, 1); 637 png_read_rows(this->png_ptr(), &rowPtr, nullptr, 1);
599 this->swizzler()->swizzle(dstRow, fSrcRow); 638
600 dstRow = SkTAddOffset<void>(dstRow, rowBytes); 639 if (this->swizzler()) {
640 this->swizzler()->swizzle(dst, rowPtr);
641 dst = SkTAddOffset<void>(dst, rowBytes);
642 } else {
643 rowPtr += rowBytes;
644 }
601 } 645 }
602 646
603 return row; 647 return row;
604 } 648 }
605 649
606 bool onSkipScanlines(int count) override { 650 bool onSkipScanlines(int count) override {
607 // Assume that an error in libpng indicates an incomplete input. 651 // Assume that an error in libpng indicates an incomplete input.
608 if (setjmp(png_jmpbuf(this->png_ptr()))) { 652 if (setjmp(png_jmpbuf(this->png_ptr()))) {
609 SkCodecPrintf("setjmp long jump!\n"); 653 SkCodecPrintf("setjmp long jump!\n");
610 return false; 654 return false;
(...skipping 26 matching lines...) Expand all
637 { 681 {
638 SkASSERT(numberPasses != 1); 682 SkASSERT(numberPasses != 1);
639 } 683 }
640 684
641 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 685 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
642 SkPMColor ctable[], int* ctableCount) override { 686 SkPMColor ctable[], int* ctableCount) override {
643 if (!conversion_possible(dstInfo, this->getInfo())) { 687 if (!conversion_possible(dstInfo, this->getInfo())) {
644 return kInvalidConversion; 688 return kInvalidConversion;
645 } 689 }
646 690
647 const Result result = this->initializeSwizzler(dstInfo, options, ctable, 691 const Result result = this->prepareToDecode(dstInfo, options, ctable, ct ableCount);
648 ctableCount);
649 if (result != kSuccess) { 692 if (result != kSuccess) {
650 return result; 693 return result;
651 } 694 }
652 695
653 fHeight = dstInfo.height(); 696 fHeight = dstInfo.height();
654 // FIXME: This need not be called on a second call to onStartScanlineDec ode. 697 // FIXME: This need not be called on a second call to onStartScanlineDec ode.
655 fSrcRowBytes = this->getInfo().width() * SkSwizzler::BytesPerPixel(this- >srcConfig()); 698 fSrcRowBytes = this->getInfo().width() * SkSwizzler::BytesPerPixel(this- >srcConfig());
656 fGarbageRow.reset(fSrcRowBytes); 699 fGarbageRow.reset(fSrcRowBytes);
657 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); 700 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get());
658 fCanSkipRewind = true; 701 fCanSkipRewind = true;
(...skipping 24 matching lines...) Expand all
683 this->updateCurrScanline(currScanline); 726 this->updateCurrScanline(currScanline);
684 } 727 }
685 728
686 if (setjmp(png_jmpbuf(this->png_ptr()))) { 729 if (setjmp(png_jmpbuf(this->png_ptr()))) {
687 SkCodecPrintf("setjmp long jump!\n"); 730 SkCodecPrintf("setjmp long jump!\n");
688 // FIXME (msarett): Returning 0 is pessimistic. If we can complete a single pass, 731 // FIXME (msarett): Returning 0 is pessimistic. If we can complete a single pass,
689 // we may be able to report that all of the memory has been initiali zed. Even if we 732 // we may be able to report that all of the memory has been initiali zed. Even if we
690 // fail on the first pass, we can still report than some scanlines a re initialized. 733 // fail on the first pass, we can still report than some scanlines a re initialized.
691 return 0; 734 return 0;
692 } 735 }
693 SkAutoTMalloc<uint8_t> storage(count * fSrcRowBytes); 736 SkAutoTMalloc<uint8_t> storage;
694 uint8_t* storagePtr = storage.get(); 737 uint8_t* const base = this->swizzler() ?
695 uint8_t* srcRow; 738 storage.reset(count * fSrcRowBytes) : (uint8_t*) dst;
739 const size_t rowBytes = this->swizzler() ? fSrcRowBytes : dstRowBytes;
696 const int startRow = this->nextScanline(); 740 const int startRow = this->nextScanline();
697 for (int i = 0; i < this->numberPasses(); i++) { 741 for (int i = 0; i < this->numberPasses(); i++) {
698 // read rows we planned to skip into garbage row 742 // read rows we planned to skip into garbage row
699 for (int y = 0; y < startRow; y++){ 743 for (int y = 0; y < startRow; y++){
700 png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1); 744 png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1);
701 } 745 }
702 // read rows we care about into buffer 746 // read rows we care about into buffer
703 srcRow = storagePtr; 747 uint8_t* rowPtr = base;
704 for (int y = 0; y < count; y++) { 748 for (int y = 0; y < count; y++) {
705 png_read_rows(this->png_ptr(), &srcRow, nullptr, 1); 749 png_read_rows(this->png_ptr(), &rowPtr, nullptr, 1);
706 srcRow += fSrcRowBytes; 750 rowPtr += rowBytes;
707 } 751 }
708 // read rows we don't want into garbage buffer 752 // read rows we don't want into garbage buffer
709 for (int y = 0; y < fHeight - startRow - count; y++) { 753 for (int y = 0; y < fHeight - startRow - count; y++) {
710 png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1); 754 png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1);
711 } 755 }
712 } 756 }
713 //swizzle the rows we care about 757
714 srcRow = storagePtr; 758 // Swizzle if necessary
715 void* dstRow = dst; 759 if (this->swizzler()) {
716 for (int y = 0; y < count; y++) { 760 uint8_t* srcRow = storage.get();
717 this->swizzler()->swizzle(dstRow, srcRow); 761 void* dstRow = dst;
718 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); 762 for (int y = 0; y < count; y++) {
719 srcRow += fSrcRowBytes; 763 this->swizzler()->swizzle(dstRow, srcRow);
764 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
765 srcRow += fSrcRowBytes;
766 }
720 } 767 }
721 768
722 return count; 769 return count;
723 } 770 }
724 771
725 bool onSkipScanlines(int count) override { 772 bool onSkipScanlines(int count) override {
726 // The non-virtual version will update fCurrScanline. 773 // The non-virtual version will update fCurrScanline.
727 return true; 774 return true;
728 } 775 }
729 776
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 } 810 }
764 811
765 if (1 == numberPasses) { 812 if (1 == numberPasses) {
766 return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunk Reader, 813 return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunk Reader,
767 png_ptr, info_ptr, bitDepth); 814 png_ptr, info_ptr, bitDepth);
768 } 815 }
769 816
770 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader, 817 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader,
771 png_ptr, info_ptr, bitDepth, numbe rPasses); 818 png_ptr, info_ptr, bitDepth, numbe rPasses);
772 } 819 }
OLDNEW
« no previous file with comments | « src/codec/SkPngCodec.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698