| 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" |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 // Check for supported color types | 418 // Check for supported color types |
| 419 switch (dst.colorType()) { | 419 switch (dst.colorType()) { |
| 420 case kN32_SkColorType: | 420 case kN32_SkColorType: |
| 421 return true; | 421 return true; |
| 422 default: | 422 default: |
| 423 return dst.colorType() == src.colorType(); | 423 return dst.colorType() == src.colorType(); |
| 424 } | 424 } |
| 425 } | 425 } |
| 426 | 426 |
| 427 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, | 427 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, |
| 428 void* dst, size_t rowBytes, | |
| 429 const Options& options, | 428 const Options& options, |
| 430 SkPMColor ctable[], | 429 SkPMColor ctable[], |
| 431 int* ctableCount) { | 430 int* ctableCount) { |
| 432 // FIXME: Could we use the return value of setjmp to specify the type of | 431 // FIXME: Could we use the return value of setjmp to specify the type of |
| 433 // error? | 432 // error? |
| 434 if (setjmp(png_jmpbuf(fPng_ptr))) { | 433 if (setjmp(png_jmpbuf(fPng_ptr))) { |
| 435 SkCodecPrintf("setjmp long jump!\n"); | 434 SkCodecPrintf("setjmp long jump!\n"); |
| 436 return kInvalidInput; | 435 return kInvalidInput; |
| 437 } | 436 } |
| 438 fNumberPasses = png_set_interlace_handling(fPng_ptr); | 437 fNumberPasses = png_set_interlace_handling(fPng_ptr); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 467 //would have exited before now if the colorType was supported by png | 466 //would have exited before now if the colorType was supported by png |
| 468 SkASSERT(false); | 467 SkASSERT(false); |
| 469 } | 468 } |
| 470 | 469 |
| 471 // Copy the color table to the client if they request kIndex8 mode | 470 // Copy the color table to the client if they request kIndex8 mode |
| 472 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); | 471 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); |
| 473 | 472 |
| 474 // Create the swizzler. SkPngCodec retains ownership of the color table. | 473 // Create the swizzler. SkPngCodec retains ownership of the color table. |
| 475 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; | 474 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; |
| 476 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo
, | 475 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo
, |
| 477 dst, rowBytes, options.fZeroInitialized)); | 476 options.fZeroInitialized)); |
| 478 if (!fSwizzler) { | 477 if (!fSwizzler) { |
| 479 // FIXME: CreateSwizzler could fail for another reason. | 478 // FIXME: CreateSwizzler could fail for another reason. |
| 480 return kUnimplemented; | 479 return kUnimplemented; |
| 481 } | 480 } |
| 482 return kSuccess; | 481 return kSuccess; |
| 483 } | 482 } |
| 484 | 483 |
| 485 | 484 |
| 486 bool SkPngCodec::handleRewind() { | 485 bool SkPngCodec::handleRewind() { |
| 487 switch (this->rewindIfNeeded()) { | 486 switch (this->rewindIfNeeded()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 505 } | 504 } |
| 506 return false; | 505 return false; |
| 507 } | 506 } |
| 508 default: | 507 default: |
| 509 SkASSERT(false); | 508 SkASSERT(false); |
| 510 return false; | 509 return false; |
| 511 } | 510 } |
| 512 } | 511 } |
| 513 | 512 |
| 514 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
dst, | 513 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
dst, |
| 515 size_t rowBytes, const Options& options, | 514 size_t dstRowBytes, const Options& optio
ns, |
| 516 SkPMColor ctable[], int* ctableCount) { | 515 SkPMColor ctable[], int* ctableCount) { |
| 517 if (!conversion_possible(requestedInfo, this->getInfo())) { | 516 if (!conversion_possible(requestedInfo, this->getInfo())) { |
| 518 return kInvalidConversion; | 517 return kInvalidConversion; |
| 519 } | 518 } |
| 520 if (options.fSubset) { | 519 if (options.fSubset) { |
| 521 // Subsets are not supported. | 520 // Subsets are not supported. |
| 522 return kUnimplemented; | 521 return kUnimplemented; |
| 523 } | 522 } |
| 524 if (requestedInfo.dimensions() != this->getInfo().dimensions()) { | 523 if (requestedInfo.dimensions() != this->getInfo().dimensions()) { |
| 525 return kInvalidScale; | 524 return kInvalidScale; |
| 526 } | 525 } |
| 527 if (!this->handleRewind()) { | 526 if (!this->handleRewind()) { |
| 528 return kCouldNotRewind; | 527 return kCouldNotRewind; |
| 529 } | 528 } |
| 530 | 529 |
| 531 // Note that ctable and ctableCount may be modified if there is a color tabl
e | 530 // Note that ctable and ctableCount may be modified if there is a color tabl
e |
| 532 const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes, | 531 const Result result = this->initializeSwizzler(requestedInfo, options, |
| 533 options, ctable, ctableCount)
; | 532 ctable, ctableCount); |
| 534 if (result != kSuccess) { | 533 if (result != kSuccess) { |
| 535 return result; | 534 return result; |
| 536 } | 535 } |
| 537 // FIXME: Could we use the return value of setjmp to specify the type of | 536 // FIXME: Could we use the return value of setjmp to specify the type of |
| 538 // error? | 537 // error? |
| 539 if (setjmp(png_jmpbuf(fPng_ptr))) { | 538 if (setjmp(png_jmpbuf(fPng_ptr))) { |
| 540 SkCodecPrintf("setjmp long jump!\n"); | 539 SkCodecPrintf("setjmp long jump!\n"); |
| 541 return kInvalidInput; | 540 return kInvalidInput; |
| 542 } | 541 } |
| 543 | 542 |
| 544 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); | 543 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); |
| 545 SkAutoMalloc storage; | 544 SkAutoMalloc storage; |
| 545 void* dstRow = dst; |
| 546 if (fNumberPasses > 1) { | 546 if (fNumberPasses > 1) { |
| 547 const int width = requestedInfo.width(); | 547 const int width = requestedInfo.width(); |
| 548 const int height = requestedInfo.height(); | 548 const int height = requestedInfo.height(); |
| 549 const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig); | 549 const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig); |
| 550 const size_t rowBytes = width * bpp; | 550 const size_t srcRowBytes = width * bpp; |
| 551 | 551 |
| 552 storage.reset(width * height * bpp); | 552 storage.reset(width * height * bpp); |
| 553 uint8_t* const base = static_cast<uint8_t*>(storage.get()); | 553 uint8_t* const base = static_cast<uint8_t*>(storage.get()); |
| 554 | 554 |
| 555 for (int i = 0; i < fNumberPasses; i++) { | 555 for (int i = 0; i < fNumberPasses; i++) { |
| 556 uint8_t* row = base; | 556 uint8_t* srcRow = base; |
| 557 for (int y = 0; y < height; y++) { | 557 for (int y = 0; y < height; y++) { |
| 558 uint8_t* bmRow = row; | 558 uint8_t* bmRow = srcRow; |
| 559 png_read_rows(fPng_ptr, &bmRow, png_bytepp_NULL, 1); | 559 png_read_rows(fPng_ptr, &bmRow, png_bytepp_NULL, 1); |
| 560 row += rowBytes; | 560 srcRow += srcRowBytes; |
| 561 } | 561 } |
| 562 } | 562 } |
| 563 | 563 |
| 564 // Now swizzle it. | 564 // Now swizzle it. |
| 565 uint8_t* row = base; | 565 uint8_t* srcRow = base; |
| 566 for (int y = 0; y < height; y++) { | 566 for (int y = 0; y < height; y++) { |
| 567 fReallyHasAlpha |= !SkSwizzler::IsOpaque(fSwizzler->next(row)); | 567 fReallyHasAlpha |= !SkSwizzler::IsOpaque(fSwizzler->swizzle(dstRow,
srcRow)); |
| 568 row += rowBytes; | 568 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |
| 569 srcRow += srcRowBytes; |
| 569 } | 570 } |
| 570 } else { | 571 } else { |
| 571 storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(fSrcConf
ig)); | 572 storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(fSrcConf
ig)); |
| 572 uint8_t* srcRow = static_cast<uint8_t*>(storage.get()); | 573 uint8_t* srcRow = static_cast<uint8_t*>(storage.get()); |
| 573 for (int y = 0; y < requestedInfo.height(); y++) { | 574 for (int y = 0; y < requestedInfo.height(); y++) { |
| 574 png_read_rows(fPng_ptr, &srcRow, png_bytepp_NULL, 1); | 575 png_read_rows(fPng_ptr, &srcRow, png_bytepp_NULL, 1); |
| 575 fReallyHasAlpha |= !SkSwizzler::IsOpaque(fSwizzler->next(srcRow)); | 576 fReallyHasAlpha |= !SkSwizzler::IsOpaque(fSwizzler->swizzle(dstRow,
srcRow)); |
| 577 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |
| 576 } | 578 } |
| 577 } | 579 } |
| 578 | 580 |
| 579 // FIXME: do we need substituteTranspColor? Note that we cannot do it for | 581 // FIXME: do we need substituteTranspColor? Note that we cannot do it for |
| 580 // scanline decoding, but we could do it here. Alternatively, we could do | 582 // scanline decoding, but we could do it here. Alternatively, we could do |
| 581 // it as we go, instead of in post-processing like SkPNGImageDecoder. | 583 // it as we go, instead of in post-processing like SkPNGImageDecoder. |
| 582 | 584 |
| 583 if (setjmp(png_jmpbuf(fPng_ptr))) { | 585 if (setjmp(png_jmpbuf(fPng_ptr))) { |
| 584 // We've already read all the scanlines. This is a success. | 586 // We've already read all the scanlines. This is a success. |
| 585 return kSuccess; | 587 return kSuccess; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 600 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig)); | 602 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig)); |
| 601 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | 603 fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
| 602 } | 604 } |
| 603 | 605 |
| 604 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { | 606 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { |
| 605 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 607 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
| 606 SkCodecPrintf("setjmp long jump!\n"); | 608 SkCodecPrintf("setjmp long jump!\n"); |
| 607 return SkCodec::kInvalidInput; | 609 return SkCodec::kInvalidInput; |
| 608 } | 610 } |
| 609 | 611 |
| 612 void* dstRow = dst; |
| 610 for (int i = 0; i < count; i++) { | 613 for (int i = 0; i < count; i++) { |
| 611 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); | 614 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); |
| 612 fCodec->fSwizzler->setDstRow(dst); | 615 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->swizzle(dstRow
, fSrcRow)); |
| 613 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->next(fSrcRow))
; | 616 dstRow = SkTAddOffset<void>(dstRow, rowBytes); |
| 614 dst = SkTAddOffset<void>(dst, rowBytes); | |
| 615 } | 617 } |
| 616 return SkCodec::kSuccess; | 618 return SkCodec::kSuccess; |
| 617 } | 619 } |
| 618 | 620 |
| 619 SkCodec::Result onSkipScanlines(int count) override { | 621 SkCodec::Result onSkipScanlines(int count) override { |
| 620 // FIXME: Could we use the return value of setjmp to specify the type of | 622 // FIXME: Could we use the return value of setjmp to specify the type of |
| 621 // error? | 623 // error? |
| 622 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 624 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
| 623 SkCodecPrintf("setjmp long jump!\n"); | 625 SkCodecPrintf("setjmp long jump!\n"); |
| 624 return SkCodec::kInvalidInput; | 626 return SkCodec::kInvalidInput; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 png_read_rows(fCodec->fPng_ptr, &srcRow, png_bytepp_NULL, 1); | 685 png_read_rows(fCodec->fPng_ptr, &srcRow, png_bytepp_NULL, 1); |
| 684 srcRow += fSrcRowBytes; | 686 srcRow += fSrcRowBytes; |
| 685 } | 687 } |
| 686 //read rows we don't want into garbage buffer | 688 //read rows we don't want into garbage buffer |
| 687 for (int y = 0; y < fHeight - fCurrentRow - count; y++) { | 689 for (int y = 0; y < fHeight - fCurrentRow - count; y++) { |
| 688 png_read_rows(fCodec->fPng_ptr, &fGarbageRowPtr, png_bytepp_NULL
, 1); | 690 png_read_rows(fCodec->fPng_ptr, &fGarbageRowPtr, png_bytepp_NULL
, 1); |
| 689 } | 691 } |
| 690 } | 692 } |
| 691 //swizzle the rows we care about | 693 //swizzle the rows we care about |
| 692 srcRow = storagePtr; | 694 srcRow = storagePtr; |
| 695 void* dstRow = dst; |
| 693 for (int y = 0; y < count; y++) { | 696 for (int y = 0; y < count; y++) { |
| 694 fCodec->fSwizzler->setDstRow(dst); | 697 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->swizzle(dstRow
, srcRow)); |
| 695 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->next(srcRow)); | 698 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |
| 696 dst = SkTAddOffset<void>(dst, dstRowBytes); | |
| 697 srcRow += fSrcRowBytes; | 699 srcRow += fSrcRowBytes; |
| 698 } | 700 } |
| 699 fCurrentRow += count; | 701 fCurrentRow += count; |
| 700 return SkCodec::kSuccess; | 702 return SkCodec::kSuccess; |
| 701 } | 703 } |
| 702 | 704 |
| 703 SkCodec::Result onSkipScanlines(int count) override { | 705 SkCodec::Result onSkipScanlines(int count) override { |
| 704 //when ongetScanlines is called it will skip to fCurrentRow | 706 //when ongetScanlines is called it will skip to fCurrentRow |
| 705 fCurrentRow += count; | 707 fCurrentRow += count; |
| 706 return SkCodec::kSuccess; | 708 return SkCodec::kSuccess; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 734 // Create a new SkPngCodec, to be owned by the scanline decoder. | 736 // Create a new SkPngCodec, to be owned by the scanline decoder. |
| 735 SkStream* stream = this->stream()->duplicate(); | 737 SkStream* stream = this->stream()->duplicate(); |
| 736 if (!stream) { | 738 if (!stream) { |
| 737 return NULL; | 739 return NULL; |
| 738 } | 740 } |
| 739 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro
mStream(stream))); | 741 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro
mStream(stream))); |
| 740 if (!codec) { | 742 if (!codec) { |
| 741 return NULL; | 743 return NULL; |
| 742 } | 744 } |
| 743 | 745 |
| 744 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee
ded, | 746 if (codec->initializeSwizzler(dstInfo, options, ctable, ctableCount) != kSuc
cess) { |
| 745 // since we'll be manually updating the dstRow, but the SkSwizzler requires
it to | |
| 746 // be at least dstInfo.minRowBytes. | |
| 747 if (codec->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options,
ctable, | |
| 748 ctableCount) != kSuccess) { | |
| 749 SkCodecPrintf("failed to initialize the swizzler.\n"); | 747 SkCodecPrintf("failed to initialize the swizzler.\n"); |
| 750 return NULL; | 748 return NULL; |
| 751 } | 749 } |
| 752 | 750 |
| 753 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); | 751 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); |
| 754 if (codec->fNumberPasses > 1) { | 752 if (codec->fNumberPasses > 1) { |
| 755 // interlaced image | 753 // interlaced image |
| 756 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach
())); | 754 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach
())); |
| 757 } | 755 } |
| 758 | 756 |
| 759 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach())); | 757 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach())); |
| 760 } | 758 } |
| 761 | 759 |
| OLD | NEW |