| 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 |