Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "SkCodec_libpng.h" | 8 #include "SkCodec_libpng.h" |
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 } | 464 } |
| 465 break; | 465 break; |
| 466 default: | 466 default: |
| 467 //would have exited before now if the colorType was supported by png | 467 //would have exited before now if the colorType was supported by png |
| 468 SkASSERT(false); | 468 SkASSERT(false); |
| 469 } | 469 } |
| 470 | 470 |
| 471 // Copy the color table to the client if they request kIndex8 mode | 471 // Copy the color table to the client if they request kIndex8 mode |
| 472 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); | 472 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); |
| 473 | 473 |
| 474 int sampleX = this->getInfo().width() / requestedInfo.width(); | |
|
scroggo
2015/07/30 17:53:01
This should also be in some central place, to be s
| |
| 475 | |
| 474 // Create the swizzler. SkPngCodec retains ownership of the color table. | 476 // Create the swizzler. SkPngCodec retains ownership of the color table. |
| 475 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; | 477 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; |
| 476 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , | 478 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , |
| 477 dst, rowBytes, options.fZeroInitialized)); | 479 dst, rowBytes, options.fZeroInitialized, sampleX)); |
| 478 if (!fSwizzler) { | 480 if (!fSwizzler) { |
| 479 // FIXME: CreateSwizzler could fail for another reason. | 481 // FIXME: CreateSwizzler could fail for another reason. |
| 480 return kUnimplemented; | 482 return kUnimplemented; |
| 481 } | 483 } |
| 482 return kSuccess; | 484 return kSuccess; |
| 483 } | 485 } |
| 484 | 486 |
| 485 | 487 |
| 486 bool SkPngCodec::handleRewind() { | 488 bool SkPngCodec::handleRewind() { |
| 487 switch (this->rewindIfNeeded()) { | 489 switch (this->rewindIfNeeded()) { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 return kSuccess; | 592 return kSuccess; |
| 591 } | 593 } |
| 592 | 594 |
| 593 class SkPngScanlineDecoder : public SkScanlineDecoder { | 595 class SkPngScanlineDecoder : public SkScanlineDecoder { |
| 594 public: | 596 public: |
| 595 SkPngScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec) | 597 SkPngScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec) |
| 596 : INHERITED(dstInfo) | 598 : INHERITED(dstInfo) |
| 597 , fCodec(codec) | 599 , fCodec(codec) |
| 598 , fHasAlpha(false) | 600 , fHasAlpha(false) |
| 599 { | 601 { |
| 600 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig)); | 602 fStorage.reset(fCodec->getInfo().width() * SkSwizzler::BytesPerPixel(fCo dec->fSrcConfig)); |
| 601 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | 603 fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
| 602 } | 604 } |
| 603 | 605 |
| 604 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { | 606 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { |
| 605 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 607 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
| 606 SkCodecPrintf("setjmp long jump!\n"); | 608 SkCodecPrintf("setjmp long jump!\n"); |
| 607 return SkCodec::kInvalidInput; | 609 return SkCodec::kInvalidInput; |
| 608 } | 610 } |
| 609 | 611 |
| 610 for (int i = 0; i < count; i++) { | 612 for (int i = 0; i < count; i++) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 627 //calling png_read_rows in a loop is insignificantly slower than calling it once with count | 629 //calling png_read_rows in a loop is insignificantly slower than calling it once with count |
| 628 //as png_read_rows has it's own loop which calls png_read_row count time s. | 630 //as png_read_rows has it's own loop which calls png_read_row count time s. |
| 629 for (int i = 0; i < count; i++) { | 631 for (int i = 0; i < count; i++) { |
| 630 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); | 632 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); |
| 631 } | 633 } |
| 632 return SkCodec::kSuccess; | 634 return SkCodec::kSuccess; |
| 633 } | 635 } |
| 634 | 636 |
| 635 bool onReallyHasAlpha() const override { return fHasAlpha; } | 637 bool onReallyHasAlpha() const override { return fHasAlpha; } |
| 636 | 638 |
| 639 bool onIsHardToSample() override { | |
| 640 return false; | |
| 641 } | |
| 642 | |
| 637 private: | 643 private: |
| 638 SkAutoTDelete<SkPngCodec> fCodec; | 644 SkAutoTDelete<SkPngCodec> fCodec; |
| 639 bool fHasAlpha; | 645 bool fHasAlpha; |
| 640 SkAutoMalloc fStorage; | 646 SkAutoMalloc fStorage; |
| 641 uint8_t* fSrcRow; | 647 uint8_t* fSrcRow; |
| 642 | 648 |
| 643 typedef SkScanlineDecoder INHERITED; | 649 typedef SkScanlineDecoder INHERITED; |
| 644 }; | 650 }; |
| 645 | 651 |
| 646 | 652 |
| 647 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { | 653 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { |
| 648 public: | 654 public: |
| 649 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec ) | 655 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec ) |
| 650 : INHERITED(dstInfo) | 656 : INHERITED(dstInfo) |
| 651 , fCodec(codec) | 657 , fCodec(codec) |
| 652 , fHasAlpha(false) | 658 , fHasAlpha(false) |
| 653 , fCurrentRow(0) | 659 , fCurrentRow(0) |
| 654 , fHeight(dstInfo.height()) | 660 , fHeight(dstInfo.height()) |
| 655 { | 661 { |
| 656 fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig); | 662 fSrcRowBytes = codec->getInfo().width() * SkSwizzler::BytesPerPixel(fCod ec->fSrcConfig); |
| 657 fGarbageRow.reset(fSrcRowBytes); | 663 fGarbageRow.reset(fSrcRowBytes); |
| 658 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); | 664 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); |
| 659 } | 665 } |
| 660 | 666 |
| 661 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove rride { | 667 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove rride { |
| 662 //rewind stream if have previously called onGetScanlines, | 668 //rewind stream if have previously called onGetScanlines, |
| 663 //since we need entire progressive image to get scanlines | 669 //since we need entire progressive image to get scanlines |
| 664 if (!fCodec->handleRewind()) { | 670 if (!fCodec->handleRewind()) { |
| 665 return SkCodec::kCouldNotRewind; | 671 return SkCodec::kCouldNotRewind; |
| 666 } | 672 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 } | 707 } |
| 702 | 708 |
| 703 SkCodec::Result onSkipScanlines(int count) override { | 709 SkCodec::Result onSkipScanlines(int count) override { |
| 704 //when ongetScanlines is called it will skip to fCurrentRow | 710 //when ongetScanlines is called it will skip to fCurrentRow |
| 705 fCurrentRow += count; | 711 fCurrentRow += count; |
| 706 return SkCodec::kSuccess; | 712 return SkCodec::kSuccess; |
| 707 } | 713 } |
| 708 | 714 |
| 709 bool onReallyHasAlpha() const override { return fHasAlpha; } | 715 bool onReallyHasAlpha() const override { return fHasAlpha; } |
| 710 | 716 |
| 717 bool onIsHardToSample() override { | |
| 718 return true; | |
| 719 } | |
| 720 | |
| 711 private: | 721 private: |
| 712 SkAutoTDelete<SkPngCodec> fCodec; | 722 SkAutoTDelete<SkPngCodec> fCodec; |
| 713 bool fHasAlpha; | 723 bool fHasAlpha; |
| 714 int fCurrentRow; | 724 int fCurrentRow; |
| 715 int fHeight; | 725 int fHeight; |
| 716 size_t fSrcRowBytes; | 726 size_t fSrcRowBytes; |
| 717 SkAutoMalloc fGarbageRow; | 727 SkAutoMalloc fGarbageRow; |
| 718 uint8_t* fGarbageRowPtr; | 728 uint8_t* fGarbageRowPtr; |
| 719 | 729 |
| 720 typedef SkScanlineDecoder INHERITED; | 730 typedef SkScanlineDecoder INHERITED; |
| 721 }; | 731 }; |
| 722 | 732 |
| 723 | 733 |
| 724 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, | 734 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, |
| 725 const Options& options, SkPMColor ctable[], int* ctableCount) { | 735 const Options& options, SkPMColor ctable[], int* ctableCount) { |
| 726 if (!conversion_possible(dstInfo, this->getInfo())) { | 736 if (!conversion_possible(dstInfo, this->getInfo())) { |
| 727 SkCodecPrintf("no conversion possible\n"); | 737 SkCodecPrintf("no conversion possible\n"); |
| 728 return NULL; | 738 return NULL; |
| 729 } | 739 } |
| 740 Options scaledOptions = options; | |
|
scroggo
2015/07/30 17:53:01
It looks like we do not modify scaledOptions, so w
emmaleer
2015/07/30 22:27:55
Acknowledged.
| |
| 730 // Check to see if scaling was requested. | 741 // Check to see if scaling was requested. |
| 731 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 742 if(dstInfo.dimensions() != this->getInfo().dimensions()) { |
| 732 return NULL; | 743 // the caller is sampling |
| 744 // heights must be equal as SkCodec_libpng has no native y sampling | |
|
scroggo
2015/07/30 17:53:01
What about widths? We don't want them to request a
emmaleer
2015/07/30 22:27:55
Good point. I've added a check to only allow small
| |
| 745 if (dstInfo.height() != this->getInfo().height()) { | |
| 746 return NULL; | |
| 747 } | |
| 733 } | 748 } |
| 734 // Create a new SkPngCodec, to be owned by the scanline decoder. | 749 // Create a new SkPngCodec, to be owned by the scanline decoder. |
| 735 SkStream* stream = this->stream()->duplicate(); | 750 SkStream* stream = this->stream()->duplicate(); |
| 736 if (!stream) { | 751 if (!stream) { |
| 737 return NULL; | 752 return NULL; |
| 738 } | 753 } |
| 739 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro mStream(stream))); | 754 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro mStream(stream))); |
| 740 if (!codec) { | 755 if (!codec) { |
| 741 return NULL; | 756 return NULL; |
| 742 } | 757 } |
| 743 | 758 |
| 744 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded, | 759 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded, |
| 745 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to | 760 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to |
| 746 // be at least dstInfo.minRowBytes. | 761 // be at least dstInfo.minRowBytes. |
| 747 if (codec->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, ctable, | 762 if (codec->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), scaledOp tions, ctable, |
| 748 ctableCount) != kSuccess) { | 763 ctableCount) != kSuccess) { |
| 749 SkCodecPrintf("failed to initialize the swizzler.\n"); | 764 SkCodecPrintf("failed to initialize the swizzler.\n"); |
| 750 return NULL; | 765 return NULL; |
| 751 } | 766 } |
| 752 | 767 |
| 753 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); | 768 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); |
| 754 if (codec->fNumberPasses > 1) { | 769 if (codec->fNumberPasses > 1) { |
| 755 // interlaced image | 770 // interlaced image |
| 756 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach ())); | 771 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach ())); |
| 757 } | 772 } |
| 758 | 773 |
| 759 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach())); | 774 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach())); |
| 760 } | 775 } |
| 761 | 776 |
| OLD | NEW |