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 "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 break; | 508 break; |
509 } | 509 } |
510 } | 510 } |
511 | 511 |
512 class SkPngNormalDecoder : public SkPngCodec { | 512 class SkPngNormalDecoder : public SkPngCodec { |
513 public: | 513 public: |
514 SkPngNormalDecoder(const SkEncodedInfo& info, const SkImageInfo& imageInfo,
SkStream* stream, | 514 SkPngNormalDecoder(const SkEncodedInfo& info, const SkImageInfo& imageInfo,
SkStream* stream, |
515 SkPngChunkReader* reader, png_structp png_ptr, png_infop info_ptr, i
nt bitDepth) | 515 SkPngChunkReader* reader, png_structp png_ptr, png_infop info_ptr, i
nt bitDepth) |
516 : INHERITED(info, imageInfo, stream, reader, png_ptr, info_ptr, bitDepth
) | 516 : INHERITED(info, imageInfo, stream, reader, png_ptr, info_ptr, bitDepth
) |
517 , fLinesDecoded(0) | 517 , fLinesDecoded(0) |
| 518 , fRowsWrittenToOutput(0) |
518 , fDst(nullptr) | 519 , fDst(nullptr) |
519 , fRowBytes(0) | 520 , fRowBytes(0) |
520 , fFirstRow(0) | 521 , fFirstRow(0) |
521 , fLastRow(0) | 522 , fLastRow(0) |
522 {} | 523 {} |
523 | 524 |
524 static void AllRowsCallback(png_structp png_ptr, png_bytep row, png_uint_32
rowNum, int /*pass*/) { | 525 static void AllRowsCallback(png_structp png_ptr, png_bytep row, png_uint_32
rowNum, int /*pass*/) { |
525 GetDecoder(png_ptr)->allRowsCallback(row, rowNum); | 526 GetDecoder(png_ptr)->allRowsCallback(row, rowNum); |
526 } | 527 } |
527 | 528 |
528 static void RowCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowN
um, int /*pass*/) { | 529 static void RowCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowN
um, int /*pass*/) { |
529 GetDecoder(png_ptr)->rowCallback(row, rowNum); | 530 GetDecoder(png_ptr)->rowCallback(row, rowNum); |
530 } | 531 } |
531 | 532 |
532 #ifdef SK_GOOGLE3_PNG_HACK | 533 #ifdef SK_GOOGLE3_PNG_HACK |
533 static void RereadInfoCallback(png_structp png_ptr, png_infop) { | 534 static void RereadInfoCallback(png_structp png_ptr, png_infop) { |
534 GetDecoder(png_ptr)->rereadInfoCallback(); | 535 GetDecoder(png_ptr)->rereadInfoCallback(); |
535 } | 536 } |
536 #endif | 537 #endif |
537 | 538 |
538 private: | 539 private: |
539 int fLinesDecoded; // FIXME: Move to baseclass? | 540 // This represents the number of lines reported by libpng, minus any we skip
ped at the |
| 541 // beginning. Only used when we are skipping lines (i.e. not in decodeAllRow
s). |
| 542 int fLinesDecoded; |
| 543 // While fLinesDecoded include lines that we skipped, this only includes lin
es written to the |
| 544 // output so we can report it to the caller for filling. |
| 545 // FIXME: Can we remove fLinesDecoded and just rely on fRowsWrittenToOutput? |
| 546 int fRowsWrittenToOutput; |
540 void* fDst; | 547 void* fDst; |
541 size_t fRowBytes; | 548 size_t fRowBytes; |
542 | 549 |
543 // Variables for partial decode | 550 // Variables for partial decode |
544 int fFirstRow; // FIXME: Move to baseclass? | 551 int fFirstRow; // FIXME: Move to baseclass? |
545 int fLastRow; | 552 int fLastRow; |
546 | 553 |
547 typedef SkPngCodec INHERITED; | 554 typedef SkPngCodec INHERITED; |
548 | 555 |
549 static SkPngNormalDecoder* GetDecoder(png_structp png_ptr) { | 556 static SkPngNormalDecoder* GetDecoder(png_structp png_ptr) { |
550 return static_cast<SkPngNormalDecoder*>(png_get_progressive_ptr(png_ptr)
); | 557 return static_cast<SkPngNormalDecoder*>(png_get_progressive_ptr(png_ptr)
); |
551 } | 558 } |
552 | 559 |
553 Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) override
{ | 560 Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) override
{ |
554 const int height = this->getInfo().height(); | 561 const int height = this->getInfo().height(); |
555 png_progressive_info_ptr callback = nullptr; | 562 png_progressive_info_ptr callback = nullptr; |
556 #ifdef SK_GOOGLE3_PNG_HACK | 563 #ifdef SK_GOOGLE3_PNG_HACK |
557 callback = RereadInfoCallback; | 564 callback = RereadInfoCallback; |
558 #endif | 565 #endif |
559 png_set_progressive_read_fn(this->png_ptr(), this, callback, AllRowsCall
back, nullptr); | 566 png_set_progressive_read_fn(this->png_ptr(), this, callback, AllRowsCall
back, nullptr); |
560 fDst = dst; | 567 fDst = dst; |
561 fRowBytes = rowBytes; | 568 fRowBytes = rowBytes; |
562 | 569 |
563 fLinesDecoded = 0; | 570 fRowsWrittenToOutput = 0; |
564 fFirstRow = 0; | 571 fFirstRow = 0; |
565 fLastRow = height - 1; | 572 fLastRow = height - 1; |
566 | 573 |
567 this->processData(); | 574 this->processData(); |
568 | 575 |
569 if (fLinesDecoded == height) { | 576 if (fRowsWrittenToOutput == height) { |
570 return SkCodec::kSuccess; | 577 return SkCodec::kSuccess; |
571 } | 578 } |
572 | 579 |
573 if (rowsDecoded) { | 580 if (rowsDecoded) { |
574 *rowsDecoded = fLinesDecoded; | 581 *rowsDecoded = fRowsWrittenToOutput; |
575 } | 582 } |
576 | 583 |
577 return SkCodec::kIncompleteInput; | 584 return SkCodec::kIncompleteInput; |
578 } | 585 } |
579 | 586 |
580 void allRowsCallback(png_bytep row, int rowNum) { | 587 void allRowsCallback(png_bytep row, int rowNum) { |
581 SkASSERT(rowNum == fLinesDecoded); | 588 SkASSERT(rowNum == fRowsWrittenToOutput); |
582 fLinesDecoded++; | 589 fRowsWrittenToOutput++; |
583 this->applyXformRow(fDst, row); | 590 this->applyXformRow(fDst, row); |
584 fDst = SkTAddOffset<void>(fDst, fRowBytes); | 591 fDst = SkTAddOffset<void>(fDst, fRowBytes); |
585 } | 592 } |
586 | 593 |
587 void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) overrid
e { | 594 void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) overrid
e { |
588 png_progressive_info_ptr callback = nullptr; | 595 png_progressive_info_ptr callback = nullptr; |
589 #ifdef SK_GOOGLE3_PNG_HACK | 596 #ifdef SK_GOOGLE3_PNG_HACK |
590 callback = RereadInfoCallback; | 597 callback = RereadInfoCallback; |
591 #endif | 598 #endif |
592 png_set_progressive_read_fn(this->png_ptr(), this, callback, RowCallback
, nullptr); | 599 png_set_progressive_read_fn(this->png_ptr(), this, callback, RowCallback
, nullptr); |
593 fFirstRow = firstRow; | 600 fFirstRow = firstRow; |
594 fLastRow = lastRow; | 601 fLastRow = lastRow; |
595 fDst = dst; | 602 fDst = dst; |
596 fRowBytes = rowBytes; | 603 fRowBytes = rowBytes; |
597 fLinesDecoded = 0; | 604 fLinesDecoded = 0; |
| 605 fRowsWrittenToOutput = 0; |
598 } | 606 } |
599 | 607 |
600 SkCodec::Result decode(int* rowsDecoded) override { | 608 SkCodec::Result decode(int* rowsDecoded) override { |
601 this->processData(); | 609 this->processData(); |
602 | 610 |
603 if (fLinesDecoded == fLastRow - fFirstRow + 1) { | 611 if (fLinesDecoded == fLastRow - fFirstRow + 1) { |
604 return SkCodec::kSuccess; | 612 return SkCodec::kSuccess; |
605 } | 613 } |
606 | 614 |
607 if (rowsDecoded) { | 615 if (rowsDecoded) { |
608 *rowsDecoded = fLinesDecoded; | 616 *rowsDecoded = fRowsWrittenToOutput; |
609 } | 617 } |
610 | 618 |
611 return SkCodec::kIncompleteInput; | 619 return SkCodec::kIncompleteInput; |
612 } | 620 } |
613 | 621 |
614 void rowCallback(png_bytep row, int rowNum) { | 622 void rowCallback(png_bytep row, int rowNum) { |
615 if (rowNum < fFirstRow) { | 623 if (rowNum < fFirstRow) { |
616 // Ignore this row. | 624 // Ignore this row. |
617 return; | 625 return; |
618 } | 626 } |
619 | 627 |
620 SkASSERT(rowNum <= fLastRow); | 628 SkASSERT(rowNum <= fLastRow); |
621 | 629 |
622 // If there is no swizzler, all rows are needed. | 630 // If there is no swizzler, all rows are needed. |
623 if (!this->swizzler() || this->swizzler()->rowNeeded(fLinesDecoded)) { | 631 if (!this->swizzler() || this->swizzler()->rowNeeded(fLinesDecoded)) { |
624 this->applyXformRow(fDst, row); | 632 this->applyXformRow(fDst, row); |
625 fDst = SkTAddOffset<void>(fDst, fRowBytes); | 633 fDst = SkTAddOffset<void>(fDst, fRowBytes); |
| 634 fRowsWrittenToOutput++; |
626 } | 635 } |
627 | 636 |
628 fLinesDecoded++; | 637 fLinesDecoded++; |
629 | 638 |
630 if (rowNum == fLastRow) { | 639 if (rowNum == fLastRow) { |
631 // Fake error to stop decoding scanlines. | 640 // Fake error to stop decoding scanlines. |
632 longjmp(PNG_JMPBUF(this->png_ptr()), kStopDecoding); | 641 longjmp(PNG_JMPBUF(this->png_ptr()), kStopDecoding); |
633 } | 642 } |
634 } | 643 } |
635 }; | 644 }; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 // Now apply Xforms on all the rows that were decoded. | 774 // Now apply Xforms on all the rows that were decoded. |
766 if (!fLinesDecoded) { | 775 if (!fLinesDecoded) { |
767 if (rowsDecoded) { | 776 if (rowsDecoded) { |
768 *rowsDecoded = 0; | 777 *rowsDecoded = 0; |
769 } | 778 } |
770 return SkCodec::kIncompleteInput; | 779 return SkCodec::kIncompleteInput; |
771 } | 780 } |
772 const int lastRow = fLinesDecoded + fFirstRow - 1; | 781 const int lastRow = fLinesDecoded + fFirstRow - 1; |
773 SkASSERT(lastRow <= fLastRow); | 782 SkASSERT(lastRow <= fLastRow); |
774 | 783 |
| 784 int rowsWrittenToOutput = 0; |
| 785 |
775 // FIXME: For resuming interlace, we may swizzle a row that hasn't chang
ed. But it | 786 // FIXME: For resuming interlace, we may swizzle a row that hasn't chang
ed. But it |
776 // may be too tricky/expensive to handle that correctly. | 787 // may be too tricky/expensive to handle that correctly. |
777 png_bytep srcRow = fInterlaceBuffer.get(); | 788 png_bytep srcRow = fInterlaceBuffer.get(); |
778 const int sampleY = this->swizzler() ? this->swizzler()->sampleY() : 1; | 789 const int sampleY = this->swizzler() ? this->swizzler()->sampleY() : 1; |
779 void* dst = fDst; | 790 void* dst = fDst; |
780 for (int rowNum = fFirstRow; rowNum <= lastRow; rowNum += sampleY) { | 791 for (int rowNum = fFirstRow; rowNum <= lastRow; rowNum += sampleY) { |
781 this->applyXformRow(dst, srcRow); | 792 this->applyXformRow(dst, srcRow); |
782 dst = SkTAddOffset<void>(dst, fRowBytes); | 793 dst = SkTAddOffset<void>(dst, fRowBytes); |
783 srcRow = SkTAddOffset<png_byte>(srcRow, fPng_rowbytes * sampleY); | 794 srcRow = SkTAddOffset<png_byte>(srcRow, fPng_rowbytes * sampleY); |
| 795 rowsWrittenToOutput++; |
784 } | 796 } |
785 | 797 |
786 if (fInterlacedComplete) { | 798 if (fInterlacedComplete) { |
787 return SkCodec::kSuccess; | 799 return SkCodec::kSuccess; |
788 } | 800 } |
789 | 801 |
790 if (rowsDecoded) { | 802 if (rowsDecoded) { |
791 *rowsDecoded = fLinesDecoded; | 803 *rowsDecoded = rowsWrittenToOutput; |
792 } | 804 } |
793 return SkCodec::kIncompleteInput; | 805 return SkCodec::kIncompleteInput; |
794 } | 806 } |
795 | 807 |
796 void setUpInterlaceBuffer(int height) { | 808 void setUpInterlaceBuffer(int height) { |
797 fPng_rowbytes = png_get_rowbytes(this->png_ptr(), this->info_ptr()); | 809 fPng_rowbytes = png_get_rowbytes(this->png_ptr(), this->info_ptr()); |
798 fInterlaceBuffer.reset(fPng_rowbytes * height); | 810 fInterlaceBuffer.reset(fPng_rowbytes * height); |
799 fInterlacedComplete = false; | 811 fInterlacedComplete = false; |
800 } | 812 } |
801 }; | 813 }; |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 SkCodec* outCodec = nullptr; | 1316 SkCodec* outCodec = nullptr; |
1305 if (read_header(streamDeleter.get(), chunkReader, &outCodec, nullptr, nullpt
r)) { | 1317 if (read_header(streamDeleter.get(), chunkReader, &outCodec, nullptr, nullpt
r)) { |
1306 // Codec has taken ownership of the stream. | 1318 // Codec has taken ownership of the stream. |
1307 SkASSERT(outCodec); | 1319 SkASSERT(outCodec); |
1308 streamDeleter.release(); | 1320 streamDeleter.release(); |
1309 return outCodec; | 1321 return outCodec; |
1310 } | 1322 } |
1311 | 1323 |
1312 return nullptr; | 1324 return nullptr; |
1313 } | 1325 } |
OLD | NEW |