| 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 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 return kSuccess; | 587 return kSuccess; |
| 588 } | 588 } |
| 589 | 589 |
| 590 // read rest of file, and get additional comment and time chunks in info_ptr | 590 // read rest of file, and get additional comment and time chunks in info_ptr |
| 591 png_read_end(fPng_ptr, fInfo_ptr); | 591 png_read_end(fPng_ptr, fInfo_ptr); |
| 592 return kSuccess; | 592 return kSuccess; |
| 593 } | 593 } |
| 594 | 594 |
| 595 class SkPngScanlineDecoder : public SkScanlineDecoder { | 595 class SkPngScanlineDecoder : public SkScanlineDecoder { |
| 596 public: | 596 public: |
| 597 SkPngScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec) | 597 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkPngCodec* codec) |
| 598 : INHERITED(dstInfo) | 598 : INHERITED(srcInfo) |
| 599 , fCodec(codec) | 599 , fCodec(codec) |
| 600 , fHasAlpha(false) | 600 , fHasAlpha(false) |
| 601 {} |
| 602 |
| 603 SkCodec::Result onStart(const SkImageInfo& dstInfo, |
| 604 const SkCodec::Options& options, |
| 605 SkPMColor ctable[], int* ctableCount) override |
| 601 { | 606 { |
| 607 if (!fCodec->handleRewind()) { |
| 608 return SkCodec::kCouldNotRewind; |
| 609 } |
| 610 |
| 611 if (!conversion_possible(dstInfo, this->getInfo())) { |
| 612 return SkCodec::kInvalidConversion; |
| 613 } |
| 614 |
| 615 // Check to see if scaling was requested. |
| 616 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
| 617 return SkCodec::kInvalidScale; |
| 618 } |
| 619 |
| 620 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio
ns, ctable, |
| 621 ctableCount); |
| 622 if (result != SkCodec::kSuccess) { |
| 623 return result; |
| 624 } |
| 625 |
| 626 fHasAlpha = false; |
| 602 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig)); | 627 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig)); |
| 603 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | 628 fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
| 629 |
| 630 return SkCodec::kSuccess; |
| 604 } | 631 } |
| 605 | 632 |
| 606 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { | 633 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { |
| 607 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 634 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
| 608 SkCodecPrintf("setjmp long jump!\n"); | 635 SkCodecPrintf("setjmp long jump!\n"); |
| 609 return SkCodec::kInvalidInput; | 636 return SkCodec::kInvalidInput; |
| 610 } | 637 } |
| 611 | 638 |
| 612 void* dstRow = dst; | 639 void* dstRow = dst; |
| 613 for (int i = 0; i < count; i++) { | 640 for (int i = 0; i < count; i++) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 641 bool fHasAlpha; | 668 bool fHasAlpha; |
| 642 SkAutoMalloc fStorage; | 669 SkAutoMalloc fStorage; |
| 643 uint8_t* fSrcRow; | 670 uint8_t* fSrcRow; |
| 644 | 671 |
| 645 typedef SkScanlineDecoder INHERITED; | 672 typedef SkScanlineDecoder INHERITED; |
| 646 }; | 673 }; |
| 647 | 674 |
| 648 | 675 |
| 649 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { | 676 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { |
| 650 public: | 677 public: |
| 651 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec
) | 678 SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkPngCodec* codec
) |
| 652 : INHERITED(dstInfo) | 679 : INHERITED(srcInfo) |
| 653 , fCodec(codec) | 680 , fCodec(codec) |
| 654 , fHasAlpha(false) | 681 , fHasAlpha(false) |
| 655 , fCurrentRow(0) | 682 , fCurrentRow(0) |
| 656 , fHeight(dstInfo.height()) | 683 , fHeight(srcInfo.height()) |
| 684 , fCanSkipRewind(false) |
| 685 {} |
| 686 |
| 687 SkCodec::Result onStart(const SkImageInfo& dstInfo, |
| 688 const SkCodec::Options& options, |
| 689 SkPMColor ctable[], int* ctableCount) override |
| 657 { | 690 { |
| 691 if (!fCodec->handleRewind()) { |
| 692 return SkCodec::kCouldNotRewind; |
| 693 } |
| 694 |
| 695 if (!conversion_possible(dstInfo, this->getInfo())) { |
| 696 return SkCodec::kInvalidConversion; |
| 697 } |
| 698 |
| 699 // Check to see if scaling was requested. |
| 700 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
| 701 return SkCodec::kInvalidScale; |
| 702 } |
| 703 |
| 704 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio
ns, ctable, |
| 705 ctableCount); |
| 706 if (result != SkCodec::kSuccess) { |
| 707 return result; |
| 708 } |
| 709 |
| 710 fHasAlpha = false; |
| 711 fCurrentRow = 0; |
| 712 fHeight = dstInfo.height(); |
| 658 fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig); | 713 fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig); |
| 659 fGarbageRow.reset(fSrcRowBytes); | 714 fGarbageRow.reset(fSrcRowBytes); |
| 660 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); | 715 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); |
| 716 fCanSkipRewind = true; |
| 717 |
| 718 return SkCodec::kSuccess; |
| 661 } | 719 } |
| 662 | 720 |
| 663 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove
rride { | 721 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove
rride { |
| 664 //rewind stream if have previously called onGetScanlines, | 722 // rewind stream if have previously called onGetScanlines, |
| 665 //since we need entire progressive image to get scanlines | 723 // since we need entire progressive image to get scanlines |
| 666 if (!fCodec->handleRewind()) { | 724 if (fCanSkipRewind) { |
| 725 // We already rewound in onStart, so there is no reason to rewind. |
| 726 // Next time onGetScanlines is called, we will need to rewind. |
| 727 fCanSkipRewind = false; |
| 728 } else if (!fCodec->handleRewind()) { |
| 667 return SkCodec::kCouldNotRewind; | 729 return SkCodec::kCouldNotRewind; |
| 668 } | 730 } |
| 731 |
| 669 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 732 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
| 670 SkCodecPrintf("setjmp long jump!\n"); | 733 SkCodecPrintf("setjmp long jump!\n"); |
| 671 return SkCodec::kInvalidInput; | 734 return SkCodec::kInvalidInput; |
| 672 } | 735 } |
| 673 const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr); | 736 const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr); |
| 674 SkAutoMalloc storage(count * fSrcRowBytes); | 737 SkAutoMalloc storage(count * fSrcRowBytes); |
| 675 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); | 738 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); |
| 676 uint8_t* srcRow; | 739 uint8_t* srcRow; |
| 677 for (int i = 0; i < number_passes; i++) { | 740 for (int i = 0; i < number_passes; i++) { |
| 678 //read rows we planned to skip into garbage row | 741 //read rows we planned to skip into garbage row |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 bool onReallyHasAlpha() const override { return fHasAlpha; } | 774 bool onReallyHasAlpha() const override { return fHasAlpha; } |
| 712 | 775 |
| 713 private: | 776 private: |
| 714 SkAutoTDelete<SkPngCodec> fCodec; | 777 SkAutoTDelete<SkPngCodec> fCodec; |
| 715 bool fHasAlpha; | 778 bool fHasAlpha; |
| 716 int fCurrentRow; | 779 int fCurrentRow; |
| 717 int fHeight; | 780 int fHeight; |
| 718 size_t fSrcRowBytes; | 781 size_t fSrcRowBytes; |
| 719 SkAutoMalloc fGarbageRow; | 782 SkAutoMalloc fGarbageRow; |
| 720 uint8_t* fGarbageRowPtr; | 783 uint8_t* fGarbageRowPtr; |
| 784 // FIXME: This imitates behavior in SkCodec::rewindIfNeeded. That function |
| 785 // is called whenever some action is taken that reads the stream and |
| 786 // therefore the next call will require a rewind. So it modifies a boolean |
| 787 // to note that the *next* time it is called a rewind is needed. |
| 788 // SkPngInterlacedScanlineDecoder has an extra wrinkle - calling onStart |
| 789 // followed by onGetScanlines does *not* require a rewind. Since |
| 790 // rewindIfNeeded does not have this flexibility, we need to add another |
| 791 // layer. |
| 792 bool fCanSkipRewind; |
| 721 | 793 |
| 722 typedef SkScanlineDecoder INHERITED; | 794 typedef SkScanlineDecoder INHERITED; |
| 723 }; | 795 }; |
| 724 | 796 |
| 725 | 797 SkScanlineDecoder* SkPngCodec::NewSDFromStream(SkStream* stream) { |
| 726 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, | |
| 727 const Options& options, SkPMColor ctable[], int* ctableCount) { | |
| 728 if (!conversion_possible(dstInfo, this->getInfo())) { | |
| 729 SkCodecPrintf("no conversion possible\n"); | |
| 730 return NULL; | |
| 731 } | |
| 732 // Check to see if scaling was requested. | |
| 733 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | |
| 734 return NULL; | |
| 735 } | |
| 736 // Create a new SkPngCodec, to be owned by the scanline decoder. | |
| 737 SkStream* stream = this->stream()->duplicate(); | |
| 738 if (!stream) { | |
| 739 return NULL; | |
| 740 } | |
| 741 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro
mStream(stream))); | 798 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro
mStream(stream))); |
| 742 if (!codec) { | 799 if (!codec) { |
| 743 return NULL; | 800 return NULL; |
| 744 } | 801 } |
| 745 | 802 |
| 746 if (codec->initializeSwizzler(dstInfo, options, ctable, ctableCount) != kSuc
cess) { | 803 codec->fNumberPasses = png_set_interlace_handling(codec->fPng_ptr); |
| 747 SkCodecPrintf("failed to initialize the swizzler.\n"); | 804 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); |
| 748 return NULL; | 805 |
| 806 const SkImageInfo& srcInfo = codec->getInfo(); |
| 807 if (codec->fNumberPasses > 1) { |
| 808 // interlaced image |
| 809 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (srcInfo, codec.detach
())); |
| 749 } | 810 } |
| 750 | 811 |
| 751 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); | 812 return SkNEW_ARGS(SkPngScanlineDecoder, (srcInfo, codec.detach())); |
| 752 if (codec->fNumberPasses > 1) { | |
| 753 // interlaced image | |
| 754 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach
())); | |
| 755 } | |
| 756 | |
| 757 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach())); | |
| 758 } | 813 } |
| 759 | 814 |
| OLD | NEW |