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" |
| 11 #include "SkColorTable.h" | 11 #include "SkColorTable.h" |
| 12 #include "SkBitmap.h" | 12 #include "SkBitmap.h" |
| 13 #include "SkMath.h" | 13 #include "SkMath.h" |
| 14 #include "SkScaledCodec.h" | |
| 14 #include "SkScanlineDecoder.h" | 15 #include "SkScanlineDecoder.h" |
| 15 #include "SkSize.h" | 16 #include "SkSize.h" |
| 16 #include "SkStream.h" | 17 #include "SkStream.h" |
| 17 #include "SkSwizzler.h" | 18 #include "SkSwizzler.h" |
| 18 | 19 |
| 19 /////////////////////////////////////////////////////////////////////////////// | 20 /////////////////////////////////////////////////////////////////////////////// |
| 20 // Helper macros | 21 // Helper macros |
| 21 /////////////////////////////////////////////////////////////////////////////// | 22 /////////////////////////////////////////////////////////////////////////////// |
| 22 | 23 |
| 23 #ifndef png_jmpbuf | 24 #ifndef png_jmpbuf |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 466 //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 |
| 467 SkASSERT(false); | 468 SkASSERT(false); |
| 468 } | 469 } |
| 469 | 470 |
| 470 // 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 |
| 471 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); | 472 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); |
| 472 | 473 |
| 473 // Create the swizzler. SkPngCodec retains ownership of the color table. | 474 // Create the swizzler. SkPngCodec retains ownership of the color table. |
| 474 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; | 475 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; |
| 475 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , | 476 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , |
| 476 options.fZeroInitialized)); | 477 options.fZeroInitialized, this->getInfo().width())); |
| 477 if (!fSwizzler) { | 478 if (!fSwizzler) { |
| 478 // FIXME: CreateSwizzler could fail for another reason. | 479 // FIXME: CreateSwizzler could fail for another reason. |
| 479 return kUnimplemented; | 480 return kUnimplemented; |
| 480 } | 481 } |
| 481 return kSuccess; | 482 return kSuccess; |
| 482 } | 483 } |
| 483 | 484 |
| 484 | 485 |
| 485 bool SkPngCodec::handleRewind() { | 486 bool SkPngCodec::handleRewind() { |
| 486 switch (this->rewindIfNeeded()) { | 487 switch (this->rewindIfNeeded()) { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 595 class SkPngScanlineDecoder : public SkScanlineDecoder { | 596 class SkPngScanlineDecoder : public SkScanlineDecoder { |
| 596 public: | 597 public: |
| 597 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkPngCodec* codec) | 598 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkPngCodec* codec) |
| 598 : INHERITED(srcInfo) | 599 : INHERITED(srcInfo) |
| 599 , fCodec(codec) | 600 , fCodec(codec) |
| 600 , fHasAlpha(false) | 601 , fHasAlpha(false) |
| 601 {} | 602 {} |
| 602 | 603 |
| 603 SkCodec::Result onStart(const SkImageInfo& dstInfo, | 604 SkCodec::Result onStart(const SkImageInfo& dstInfo, |
| 604 const SkCodec::Options& options, | 605 const SkCodec::Options& options, |
| 605 SkPMColor ctable[], int* ctableCount) override | 606 SkPMColor ctable[], int* ctableCount) override { |
| 606 { | |
| 607 if (!fCodec->handleRewind()) { | 607 if (!fCodec->handleRewind()) { |
| 608 return SkCodec::kCouldNotRewind; | 608 return SkCodec::kCouldNotRewind; |
| 609 } | 609 } |
| 610 | 610 |
| 611 if (!conversion_possible(dstInfo, this->getInfo())) { | 611 if (!conversion_possible(dstInfo, this->getInfo())) { |
| 612 return SkCodec::kInvalidConversion; | 612 return SkCodec::kInvalidConversion; |
| 613 } | 613 } |
| 614 | 614 |
| 615 // Check to see if scaling was requested. | 615 // Check to see if scaling was requested. |
| 616 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 616 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
| 617 return SkCodec::kInvalidScale; | 617 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { |
|
scroggo
2015/08/06 20:38:00
Matt has landed wbmp scanline decoding, so please
emmaleer
2015/08/07 18:38:56
Acknowledged.
| |
| 618 return SkCodec::kInvalidScale; | |
| 619 } | |
| 618 } | 620 } |
| 619 | 621 |
| 620 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable, | 622 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable, |
| 621 ctableCount); | 623 ctableCount); |
| 622 if (result != SkCodec::kSuccess) { | 624 if (result != SkCodec::kSuccess) { |
| 623 return result; | 625 return result; |
| 624 } | 626 } |
| 625 | 627 |
| 626 fHasAlpha = false; | 628 fHasAlpha = false; |
| 627 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig)); | 629 fStorage.reset(this->getInfo().width() * SkSwizzler::BytesPerPixel(fCode c->fSrcConfig)); |
| 628 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | 630 fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
| 629 | 631 |
| 630 return SkCodec::kSuccess; | 632 return SkCodec::kSuccess; |
| 631 } | 633 } |
| 632 | 634 |
| 633 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { | 635 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { |
| 634 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 636 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
| 635 SkCodecPrintf("setjmp long jump!\n"); | 637 SkCodecPrintf("setjmp long jump!\n"); |
| 636 return SkCodec::kInvalidInput; | 638 return SkCodec::kInvalidInput; |
| 637 } | 639 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 656 //calling png_read_rows in a loop is insignificantly slower than calling it once with count | 658 //calling png_read_rows in a loop is insignificantly slower than calling it once with count |
| 657 //as png_read_rows has it's own loop which calls png_read_row count time s. | 659 //as png_read_rows has it's own loop which calls png_read_row count time s. |
| 658 for (int i = 0; i < count; i++) { | 660 for (int i = 0; i < count; i++) { |
| 659 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); | 661 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); |
| 660 } | 662 } |
| 661 return SkCodec::kSuccess; | 663 return SkCodec::kSuccess; |
| 662 } | 664 } |
| 663 | 665 |
| 664 bool onReallyHasAlpha() const override { return fHasAlpha; } | 666 bool onReallyHasAlpha() const override { return fHasAlpha; } |
| 665 | 667 |
| 668 SkEncodedFormat onGetEncodedFormat() const override { | |
| 669 return kPNG_SkEncodedFormat; | |
| 670 } | |
| 671 | |
| 672 | |
| 666 private: | 673 private: |
| 667 SkAutoTDelete<SkPngCodec> fCodec; | 674 SkAutoTDelete<SkPngCodec> fCodec; |
| 668 bool fHasAlpha; | 675 bool fHasAlpha; |
| 669 SkAutoMalloc fStorage; | 676 SkAutoMalloc fStorage; |
| 670 uint8_t* fSrcRow; | 677 uint8_t* fSrcRow; |
| 671 | 678 |
| 672 typedef SkScanlineDecoder INHERITED; | 679 typedef SkScanlineDecoder INHERITED; |
| 673 }; | 680 }; |
| 674 | 681 |
| 675 | 682 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 686 | 693 |
| 687 SkCodec::Result onStart(const SkImageInfo& dstInfo, | 694 SkCodec::Result onStart(const SkImageInfo& dstInfo, |
| 688 const SkCodec::Options& options, | 695 const SkCodec::Options& options, |
| 689 SkPMColor ctable[], int* ctableCount) override | 696 SkPMColor ctable[], int* ctableCount) override |
| 690 { | 697 { |
| 691 if (!fCodec->handleRewind()) { | 698 if (!fCodec->handleRewind()) { |
| 692 return SkCodec::kCouldNotRewind; | 699 return SkCodec::kCouldNotRewind; |
| 693 } | 700 } |
| 694 | 701 |
| 695 if (!conversion_possible(dstInfo, this->getInfo())) { | 702 if (!conversion_possible(dstInfo, this->getInfo())) { |
| 696 return SkCodec::kInvalidConversion; | 703 return SkCodec::kInvalidConversion; |
| 697 } | 704 } |
| 698 | 705 |
| 699 // Check to see if scaling was requested. | 706 // Check to see if scaling was requested. |
| 700 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 707 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
| 701 return SkCodec::kInvalidScale; | 708 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { |
| 709 return SkCodec::kInvalidScale; | |
| 710 } | |
| 702 } | 711 } |
| 703 | 712 |
| 704 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable, | 713 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable, |
| 705 ctableCount); | 714 ctableCount); |
| 706 if (result != SkCodec::kSuccess) { | 715 if (result != SkCodec::kSuccess) { |
| 707 return result; | 716 return result; |
| 708 } | 717 } |
| 709 | 718 |
| 710 fHasAlpha = false; | 719 fHasAlpha = false; |
| 711 fCurrentRow = 0; | 720 fCurrentRow = 0; |
| 712 fHeight = dstInfo.height(); | 721 fHeight = dstInfo.height(); |
| 713 fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig); | 722 fSrcRowBytes = this->getInfo().width() * SkSwizzler::BytesPerPixel(fCode c->fSrcConfig); |
| 714 fGarbageRow.reset(fSrcRowBytes); | 723 fGarbageRow.reset(fSrcRowBytes); |
| 715 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); | 724 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); |
| 716 fCanSkipRewind = true; | 725 fCanSkipRewind = true; |
| 717 | 726 |
| 718 return SkCodec::kSuccess; | 727 return SkCodec::kSuccess; |
| 719 } | 728 } |
| 720 | 729 |
| 721 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove rride { | 730 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove rride { |
| 722 // rewind stream if have previously called onGetScanlines, | 731 // rewind stream if have previously called onGetScanlines, |
| 723 // since we need entire progressive image to get scanlines | 732 // since we need entire progressive image to get scanlines |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 766 } | 775 } |
| 767 | 776 |
| 768 SkCodec::Result onSkipScanlines(int count) override { | 777 SkCodec::Result onSkipScanlines(int count) override { |
| 769 //when ongetScanlines is called it will skip to fCurrentRow | 778 //when ongetScanlines is called it will skip to fCurrentRow |
| 770 fCurrentRow += count; | 779 fCurrentRow += count; |
| 771 return SkCodec::kSuccess; | 780 return SkCodec::kSuccess; |
| 772 } | 781 } |
| 773 | 782 |
| 774 bool onReallyHasAlpha() const override { return fHasAlpha; } | 783 bool onReallyHasAlpha() const override { return fHasAlpha; } |
| 775 | 784 |
| 785 bool onRequiresPostYSampling() override { | |
| 786 return true; | |
| 787 } | |
| 788 | |
| 789 SkEncodedFormat onGetEncodedFormat() const override { | |
| 790 return kPNG_SkEncodedFormat; | |
| 791 } | |
| 792 | |
| 776 private: | 793 private: |
| 777 SkAutoTDelete<SkPngCodec> fCodec; | 794 SkAutoTDelete<SkPngCodec> fCodec; |
| 778 bool fHasAlpha; | 795 bool fHasAlpha; |
| 779 int fCurrentRow; | 796 int fCurrentRow; |
| 780 int fHeight; | 797 int fHeight; |
| 781 size_t fSrcRowBytes; | 798 size_t fSrcRowBytes; |
| 782 SkAutoMalloc fGarbageRow; | 799 SkAutoMalloc fGarbageRow; |
| 783 uint8_t* fGarbageRowPtr; | 800 uint8_t* fGarbageRowPtr; |
| 784 // FIXME: This imitates behavior in SkCodec::rewindIfNeeded. That function | 801 // FIXME: This imitates behavior in SkCodec::rewindIfNeeded. That function |
| 785 // is called whenever some action is taken that reads the stream and | 802 // is called whenever some action is taken that reads the stream and |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 805 | 822 |
| 806 const SkImageInfo& srcInfo = codec->getInfo(); | 823 const SkImageInfo& srcInfo = codec->getInfo(); |
| 807 if (codec->fNumberPasses > 1) { | 824 if (codec->fNumberPasses > 1) { |
| 808 // interlaced image | 825 // interlaced image |
| 809 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (srcInfo, codec.detach ())); | 826 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (srcInfo, codec.detach ())); |
| 810 } | 827 } |
| 811 | 828 |
| 812 return SkNEW_ARGS(SkPngScanlineDecoder, (srcInfo, codec.detach())); | 829 return SkNEW_ARGS(SkPngScanlineDecoder, (srcInfo, codec.detach())); |
| 813 } | 830 } |
| 814 | 831 |
| OLD | NEW |