| 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 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 fXformWidth, fXformAlphaType)); | 451 fXformWidth, fXformAlphaType)); |
| 452 break; | 452 break; |
| 453 } | 453 } |
| 454 } | 454 } |
| 455 | 455 |
| 456 class SkPngNormalDecoder : public SkPngCodec { | 456 class SkPngNormalDecoder : public SkPngCodec { |
| 457 public: | 457 public: |
| 458 SkPngNormalDecoder(const SkEncodedInfo& info, const SkImageInfo& imageInfo,
SkStream* stream, | 458 SkPngNormalDecoder(const SkEncodedInfo& info, const SkImageInfo& imageInfo,
SkStream* stream, |
| 459 SkPngChunkReader* reader, png_structp png_ptr, png_infop info_ptr, i
nt bitDepth) | 459 SkPngChunkReader* reader, png_structp png_ptr, png_infop info_ptr, i
nt bitDepth) |
| 460 : INHERITED(info, imageInfo, stream, reader, png_ptr, info_ptr, bitDepth
) | 460 : INHERITED(info, imageInfo, stream, reader, png_ptr, info_ptr, bitDepth
) |
| 461 , fLinesDecoded(0) | |
| 462 , fRowsWrittenToOutput(0) | 461 , fRowsWrittenToOutput(0) |
| 463 , fDst(nullptr) | 462 , fDst(nullptr) |
| 464 , fRowBytes(0) | 463 , fRowBytes(0) |
| 465 , fFirstRow(0) | 464 , fFirstRow(0) |
| 466 , fLastRow(0) | 465 , fLastRow(0) |
| 467 {} | 466 {} |
| 468 | 467 |
| 469 static void AllRowsCallback(png_structp png_ptr, png_bytep row, png_uint_32
rowNum, int /*pass*/) { | 468 static void AllRowsCallback(png_structp png_ptr, png_bytep row, png_uint_32
rowNum, int /*pass*/) { |
| 470 GetDecoder(png_ptr)->allRowsCallback(row, rowNum); | 469 GetDecoder(png_ptr)->allRowsCallback(row, rowNum); |
| 471 } | 470 } |
| 472 | 471 |
| 473 static void RowCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowN
um, int /*pass*/) { | 472 static void RowCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowN
um, int /*pass*/) { |
| 474 GetDecoder(png_ptr)->rowCallback(row, rowNum); | 473 GetDecoder(png_ptr)->rowCallback(row, rowNum); |
| 475 } | 474 } |
| 476 | 475 |
| 477 #ifdef SK_GOOGLE3_PNG_HACK | 476 #ifdef SK_GOOGLE3_PNG_HACK |
| 478 static void RereadInfoCallback(png_structp png_ptr, png_infop) { | 477 static void RereadInfoCallback(png_structp png_ptr, png_infop) { |
| 479 GetDecoder(png_ptr)->rereadInfoCallback(); | 478 GetDecoder(png_ptr)->rereadInfoCallback(); |
| 480 } | 479 } |
| 481 #endif | 480 #endif |
| 482 | 481 |
| 483 private: | 482 private: |
| 484 // This represents the number of lines reported by libpng, minus any we skip
ped at the | |
| 485 // beginning. Only used when we are skipping lines (i.e. not in decodeAllRow
s). | |
| 486 int fLinesDecoded; | |
| 487 // While fLinesDecoded include lines that we skipped, this only includes lin
es written to the | |
| 488 // output so we can report it to the caller for filling. | |
| 489 // FIXME: Can we remove fLinesDecoded and just rely on fRowsWrittenToOutput? | |
| 490 int fRowsWrittenToOutput; | 483 int fRowsWrittenToOutput; |
| 491 void* fDst; | 484 void* fDst; |
| 492 size_t fRowBytes; | 485 size_t fRowBytes; |
| 493 | 486 |
| 494 // Variables for partial decode | 487 // Variables for partial decode |
| 495 int fFirstRow; // FIXME: Move to baseclass? | 488 int fFirstRow; // FIXME: Move to baseclass? |
| 496 int fLastRow; | 489 int fLastRow; |
| 490 int fRowsNeeded; |
| 497 | 491 |
| 498 typedef SkPngCodec INHERITED; | 492 typedef SkPngCodec INHERITED; |
| 499 | 493 |
| 500 static SkPngNormalDecoder* GetDecoder(png_structp png_ptr) { | 494 static SkPngNormalDecoder* GetDecoder(png_structp png_ptr) { |
| 501 return static_cast<SkPngNormalDecoder*>(png_get_progressive_ptr(png_ptr)
); | 495 return static_cast<SkPngNormalDecoder*>(png_get_progressive_ptr(png_ptr)
); |
| 502 } | 496 } |
| 503 | 497 |
| 504 Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) override
{ | 498 Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) override
{ |
| 505 const int height = this->getInfo().height(); | 499 const int height = this->getInfo().height(); |
| 506 png_progressive_info_ptr callback = nullptr; | 500 png_progressive_info_ptr callback = nullptr; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) overrid
e { | 532 void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) overrid
e { |
| 539 png_progressive_info_ptr callback = nullptr; | 533 png_progressive_info_ptr callback = nullptr; |
| 540 #ifdef SK_GOOGLE3_PNG_HACK | 534 #ifdef SK_GOOGLE3_PNG_HACK |
| 541 callback = RereadInfoCallback; | 535 callback = RereadInfoCallback; |
| 542 #endif | 536 #endif |
| 543 png_set_progressive_read_fn(this->png_ptr(), this, callback, RowCallback
, nullptr); | 537 png_set_progressive_read_fn(this->png_ptr(), this, callback, RowCallback
, nullptr); |
| 544 fFirstRow = firstRow; | 538 fFirstRow = firstRow; |
| 545 fLastRow = lastRow; | 539 fLastRow = lastRow; |
| 546 fDst = dst; | 540 fDst = dst; |
| 547 fRowBytes = rowBytes; | 541 fRowBytes = rowBytes; |
| 548 fLinesDecoded = 0; | |
| 549 fRowsWrittenToOutput = 0; | 542 fRowsWrittenToOutput = 0; |
| 543 fRowsNeeded = fLastRow - fFirstRow + 1; |
| 550 } | 544 } |
| 551 | 545 |
| 552 SkCodec::Result decode(int* rowsDecoded) override { | 546 SkCodec::Result decode(int* rowsDecoded) override { |
| 547 if (this->swizzler()) { |
| 548 const int sampleY = this->swizzler()->sampleY(); |
| 549 fRowsNeeded = get_scaled_dimension(fLastRow - fFirstRow + 1, sampleY
); |
| 550 } |
| 553 this->processData(); | 551 this->processData(); |
| 554 | 552 |
| 555 if (fLinesDecoded == fLastRow - fFirstRow + 1) { | 553 if (fRowsWrittenToOutput == fRowsNeeded) { |
| 556 return SkCodec::kSuccess; | 554 return SkCodec::kSuccess; |
| 557 } | 555 } |
| 558 | 556 |
| 559 if (rowsDecoded) { | 557 if (rowsDecoded) { |
| 560 *rowsDecoded = fRowsWrittenToOutput; | 558 *rowsDecoded = fRowsWrittenToOutput; |
| 561 } | 559 } |
| 562 | 560 |
| 563 return SkCodec::kIncompleteInput; | 561 return SkCodec::kIncompleteInput; |
| 564 } | 562 } |
| 565 | 563 |
| 566 void rowCallback(png_bytep row, int rowNum) { | 564 void rowCallback(png_bytep row, int rowNum) { |
| 567 if (rowNum < fFirstRow) { | 565 if (rowNum < fFirstRow) { |
| 568 // Ignore this row. | 566 // Ignore this row. |
| 569 return; | 567 return; |
| 570 } | 568 } |
| 571 | 569 |
| 572 SkASSERT(rowNum <= fLastRow); | 570 SkASSERT(rowNum <= fLastRow); |
| 571 SkASSERT(fRowsWrittenToOutput < fRowsNeeded); |
| 573 | 572 |
| 574 // If there is no swizzler, all rows are needed. | 573 // If there is no swizzler, all rows are needed. |
| 575 if (!this->swizzler() || this->swizzler()->rowNeeded(fLinesDecoded)) { | 574 if (!this->swizzler() || this->swizzler()->rowNeeded(rowNum - fFirstRow)
) { |
| 576 this->applyXformRow(fDst, row); | 575 this->applyXformRow(fDst, row); |
| 577 fDst = SkTAddOffset<void>(fDst, fRowBytes); | 576 fDst = SkTAddOffset<void>(fDst, fRowBytes); |
| 578 fRowsWrittenToOutput++; | 577 fRowsWrittenToOutput++; |
| 579 } | 578 } |
| 580 | 579 |
| 581 fLinesDecoded++; | 580 if (fRowsWrittenToOutput == fRowsNeeded) { |
| 582 | |
| 583 if (rowNum == fLastRow) { | |
| 584 // Fake error to stop decoding scanlines. | 581 // Fake error to stop decoding scanlines. |
| 585 longjmp(PNG_JMPBUF(this->png_ptr()), kStopDecoding); | 582 longjmp(PNG_JMPBUF(this->png_ptr()), kStopDecoding); |
| 586 } | 583 } |
| 587 } | 584 } |
| 588 }; | 585 }; |
| 589 | 586 |
| 590 class SkPngInterlacedDecoder : public SkPngCodec { | 587 class SkPngInterlacedDecoder : public SkPngCodec { |
| 591 public: | 588 public: |
| 592 SkPngInterlacedDecoder(const SkEncodedInfo& info, const SkImageInfo& imageIn
fo, | 589 SkPngInterlacedDecoder(const SkEncodedInfo& info, const SkImageInfo& imageIn
fo, |
| 593 SkStream* stream, SkPngChunkReader* reader, png_structp png_ptr, png
_infop info_ptr, | 590 SkStream* stream, SkPngChunkReader* reader, png_structp png_ptr, png
_infop info_ptr, |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 SkCodec::Result decode(int* rowsDecoded) override { | 712 SkCodec::Result decode(int* rowsDecoded) override { |
| 716 this->processData(); | 713 this->processData(); |
| 717 | 714 |
| 718 // Now apply Xforms on all the rows that were decoded. | 715 // Now apply Xforms on all the rows that were decoded. |
| 719 if (!fLinesDecoded) { | 716 if (!fLinesDecoded) { |
| 720 if (rowsDecoded) { | 717 if (rowsDecoded) { |
| 721 *rowsDecoded = 0; | 718 *rowsDecoded = 0; |
| 722 } | 719 } |
| 723 return SkCodec::kIncompleteInput; | 720 return SkCodec::kIncompleteInput; |
| 724 } | 721 } |
| 725 const int lastRow = fLinesDecoded + fFirstRow - 1; | |
| 726 SkASSERT(lastRow <= fLastRow); | |
| 727 | 722 |
| 723 const int sampleY = this->swizzler() ? this->swizzler()->sampleY() : 1; |
| 724 const int rowsNeeded = get_scaled_dimension(fLastRow - fFirstRow + 1, sa
mpleY); |
| 728 int rowsWrittenToOutput = 0; | 725 int rowsWrittenToOutput = 0; |
| 729 | 726 |
| 730 // FIXME: For resuming interlace, we may swizzle a row that hasn't chang
ed. But it | 727 // FIXME: For resuming interlace, we may swizzle a row that hasn't chang
ed. But it |
| 731 // may be too tricky/expensive to handle that correctly. | 728 // may be too tricky/expensive to handle that correctly. |
| 732 png_bytep srcRow = fInterlaceBuffer.get(); | 729 png_bytep srcRow = fInterlaceBuffer.get(); |
| 733 const int sampleY = this->swizzler() ? this->swizzler()->sampleY() : 1; | |
| 734 void* dst = fDst; | 730 void* dst = fDst; |
| 735 for (int rowNum = fFirstRow; rowNum <= lastRow; rowNum += sampleY) { | 731 for (int rowNum = fFirstRow + get_start_coord(sampleY); rowsWrittenToOut
put < rowsNeeded; |
| 732 rowNum += sampleY) { |
| 736 this->applyXformRow(dst, srcRow); | 733 this->applyXformRow(dst, srcRow); |
| 737 dst = SkTAddOffset<void>(dst, fRowBytes); | 734 dst = SkTAddOffset<void>(dst, fRowBytes); |
| 738 srcRow = SkTAddOffset<png_byte>(srcRow, fPng_rowbytes * sampleY); | 735 srcRow = SkTAddOffset<png_byte>(srcRow, fPng_rowbytes * sampleY); |
| 739 rowsWrittenToOutput++; | 736 rowsWrittenToOutput++; |
| 740 } | 737 } |
| 741 | 738 |
| 742 if (fInterlacedComplete) { | 739 if (fInterlacedComplete) { |
| 743 return SkCodec::kSuccess; | 740 return SkCodec::kSuccess; |
| 744 } | 741 } |
| 745 | 742 |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 SkCodec* outCodec = nullptr; | 1256 SkCodec* outCodec = nullptr; |
| 1260 if (read_header(streamDeleter.get(), chunkReader, &outCodec, nullptr, nullpt
r)) { | 1257 if (read_header(streamDeleter.get(), chunkReader, &outCodec, nullptr, nullpt
r)) { |
| 1261 // Codec has taken ownership of the stream. | 1258 // Codec has taken ownership of the stream. |
| 1262 SkASSERT(outCodec); | 1259 SkASSERT(outCodec); |
| 1263 streamDeleter.release(); | 1260 streamDeleter.release(); |
| 1264 return outCodec; | 1261 return outCodec; |
| 1265 } | 1262 } |
| 1266 | 1263 |
| 1267 return nullptr; | 1264 return nullptr; |
| 1268 } | 1265 } |
| OLD | NEW |