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 |