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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 return kSuccess; | 593 return kSuccess; |
593 } | 594 } |
594 | 595 |
595 class SkPngScanlineDecoder : public SkScanlineDecoder { | 596 class SkPngScanlineDecoder : public SkScanlineDecoder { |
596 public: | 597 public: |
597 SkPngScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec) | 598 SkPngScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec) |
598 : INHERITED(dstInfo) | 599 : INHERITED(dstInfo) |
599 , fCodec(codec) | 600 , fCodec(codec) |
600 , fHasAlpha(false) | 601 , fHasAlpha(false) |
601 { | 602 { |
602 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig)); | 603 fStorage.reset(fCodec->getInfo().width() * SkSwizzler::BytesPerPixel(fCo
dec->fSrcConfig)); |
603 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | 604 fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
604 } | 605 } |
605 | 606 |
606 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { | 607 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { |
607 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 608 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
608 SkCodecPrintf("setjmp long jump!\n"); | 609 SkCodecPrintf("setjmp long jump!\n"); |
609 return SkCodec::kInvalidInput; | 610 return SkCodec::kInvalidInput; |
610 } | 611 } |
611 | 612 |
612 void* dstRow = dst; | 613 void* dstRow = dst; |
(...skipping 16 matching lines...) Expand all Loading... |
629 //calling png_read_rows in a loop is insignificantly slower than calling
it once with count | 630 //calling png_read_rows in a loop is insignificantly slower than calling
it once with count |
630 //as png_read_rows has it's own loop which calls png_read_row count time
s. | 631 //as png_read_rows has it's own loop which calls png_read_row count time
s. |
631 for (int i = 0; i < count; i++) { | 632 for (int i = 0; i < count; i++) { |
632 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); | 633 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); |
633 } | 634 } |
634 return SkCodec::kSuccess; | 635 return SkCodec::kSuccess; |
635 } | 636 } |
636 | 637 |
637 bool onReallyHasAlpha() const override { return fHasAlpha; } | 638 bool onReallyHasAlpha() const override { return fHasAlpha; } |
638 | 639 |
| 640 bool onIsHardToSample() override { |
| 641 return false; |
| 642 } |
| 643 |
639 private: | 644 private: |
640 SkAutoTDelete<SkPngCodec> fCodec; | 645 SkAutoTDelete<SkPngCodec> fCodec; |
641 bool fHasAlpha; | 646 bool fHasAlpha; |
642 SkAutoMalloc fStorage; | 647 SkAutoMalloc fStorage; |
643 uint8_t* fSrcRow; | 648 uint8_t* fSrcRow; |
644 | 649 |
645 typedef SkScanlineDecoder INHERITED; | 650 typedef SkScanlineDecoder INHERITED; |
646 }; | 651 }; |
647 | 652 |
648 | 653 |
649 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { | 654 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { |
650 public: | 655 public: |
651 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec
) | 656 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec
) |
652 : INHERITED(dstInfo) | 657 : INHERITED(dstInfo) |
653 , fCodec(codec) | 658 , fCodec(codec) |
654 , fHasAlpha(false) | 659 , fHasAlpha(false) |
655 , fCurrentRow(0) | 660 , fCurrentRow(0) |
656 , fHeight(dstInfo.height()) | 661 , fHeight(dstInfo.height()) |
657 { | 662 { |
658 fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig); | 663 fSrcRowBytes = codec->getInfo().width() * SkSwizzler::BytesPerPixel(fCod
ec->fSrcConfig); |
659 fGarbageRow.reset(fSrcRowBytes); | 664 fGarbageRow.reset(fSrcRowBytes); |
660 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); | 665 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); |
661 } | 666 } |
662 | 667 |
663 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove
rride { | 668 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove
rride { |
664 //rewind stream if have previously called onGetScanlines, | 669 //rewind stream if have previously called onGetScanlines, |
665 //since we need entire progressive image to get scanlines | 670 //since we need entire progressive image to get scanlines |
666 if (!fCodec->handleRewind()) { | 671 if (!fCodec->handleRewind()) { |
667 return SkCodec::kCouldNotRewind; | 672 return SkCodec::kCouldNotRewind; |
668 } | 673 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 } | 708 } |
704 | 709 |
705 SkCodec::Result onSkipScanlines(int count) override { | 710 SkCodec::Result onSkipScanlines(int count) override { |
706 //when ongetScanlines is called it will skip to fCurrentRow | 711 //when ongetScanlines is called it will skip to fCurrentRow |
707 fCurrentRow += count; | 712 fCurrentRow += count; |
708 return SkCodec::kSuccess; | 713 return SkCodec::kSuccess; |
709 } | 714 } |
710 | 715 |
711 bool onReallyHasAlpha() const override { return fHasAlpha; } | 716 bool onReallyHasAlpha() const override { return fHasAlpha; } |
712 | 717 |
| 718 bool onIsHardToSample() override { |
| 719 return true; |
| 720 } |
| 721 |
713 private: | 722 private: |
714 SkAutoTDelete<SkPngCodec> fCodec; | 723 SkAutoTDelete<SkPngCodec> fCodec; |
715 bool fHasAlpha; | 724 bool fHasAlpha; |
716 int fCurrentRow; | 725 int fCurrentRow; |
717 int fHeight; | 726 int fHeight; |
718 size_t fSrcRowBytes; | 727 size_t fSrcRowBytes; |
719 SkAutoMalloc fGarbageRow; | 728 SkAutoMalloc fGarbageRow; |
720 uint8_t* fGarbageRowPtr; | 729 uint8_t* fGarbageRowPtr; |
721 | 730 |
722 typedef SkScanlineDecoder INHERITED; | 731 typedef SkScanlineDecoder INHERITED; |
723 }; | 732 }; |
724 | 733 |
725 | 734 |
726 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, | 735 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, |
727 const Options& options, SkPMColor ctable[], int* ctableCount) { | 736 const Options& options, SkPMColor ctable[], int* ctableCount) { |
728 if (!conversion_possible(dstInfo, this->getInfo())) { | 737 if (!conversion_possible(dstInfo, this->getInfo())) { |
729 SkCodecPrintf("no conversion possible\n"); | 738 SkCodecPrintf("no conversion possible\n"); |
730 return NULL; | 739 return NULL; |
731 } | 740 } |
732 // Check to see if scaling was requested. | 741 // Check to see if scaling was requested. |
733 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 742 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
734 return NULL; | 743 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstI
nfo)) { |
| 744 return NULL; |
| 745 } |
735 } | 746 } |
736 // Create a new SkPngCodec, to be owned by the scanline decoder. | 747 // Create a new SkPngCodec, to be owned by the scanline decoder. |
737 SkStream* stream = this->stream()->duplicate(); | 748 SkStream* stream = this->stream()->duplicate(); |
738 if (!stream) { | 749 if (!stream) { |
739 return NULL; | 750 return NULL; |
740 } | 751 } |
741 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro
mStream(stream))); | 752 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro
mStream(stream))); |
742 if (!codec) { | 753 if (!codec) { |
743 return NULL; | 754 return NULL; |
744 } | 755 } |
745 | 756 |
746 if (codec->initializeSwizzler(dstInfo, options, ctable, ctableCount) != kSuc
cess) { | 757 if (codec->initializeSwizzler(dstInfo, options, ctable, ctableCount) != kSuc
cess) { |
747 SkCodecPrintf("failed to initialize the swizzler.\n"); | 758 SkCodecPrintf("failed to initialize the swizzler.\n"); |
748 return NULL; | 759 return NULL; |
749 } | 760 } |
750 | 761 |
751 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); | 762 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); |
752 if (codec->fNumberPasses > 1) { | 763 if (codec->fNumberPasses > 1) { |
753 // interlaced image | 764 // interlaced image |
754 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach
())); | 765 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach
())); |
755 } | 766 } |
756 | 767 |
757 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach())); | 768 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach())); |
758 } | 769 } |
759 | 770 |
OLD | NEW |