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 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 case kBGRA_8888_SkColorType: | 373 case kBGRA_8888_SkColorType: |
374 case kRGBA_F16_SkColorType: | 374 case kRGBA_F16_SkColorType: |
375 return true; | 375 return true; |
376 case kRGB_565_SkColorType: | 376 case kRGB_565_SkColorType: |
377 return kOpaque_SkAlphaType == src.alphaType(); | 377 return kOpaque_SkAlphaType == src.alphaType(); |
378 default: | 378 default: |
379 return dst.colorType() == src.colorType(); | 379 return dst.colorType() == src.colorType(); |
380 } | 380 } |
381 } | 381 } |
382 | 382 |
383 void SkPngCodec::allocateStorage() { | 383 void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) { |
384 size_t colorXformBytes = fColorXform ? fSwizzler->swizzleWidth() * sizeof(ui
nt32_t) : 0; | 384 switch (fXformMode) { |
385 | 385 case kSwizzleOnly_XformMode: |
386 fStorage.reset(SkAlign4(fSrcRowBytes) + colorXformBytes); | 386 fStorage.reset(SkAlign4(fSrcRowBytes)); |
387 fSwizzlerSrcRow = fStorage.get(); | 387 fSwizzlerSrcRow = fStorage.get(); |
388 fColorXformSrcRow = | 388 break; |
389 fColorXform ? SkTAddOffset<uint32_t>(fSwizzlerSrcRow, SkAlign4(fSrcR
owBytes)) : 0; | 389 case kColorOnly_XformMode: |
| 390 // Intentional fall through. A swizzler hasn't been created yet, bu
t one will |
| 391 // be created later if we are sampling or subsetting. We'll go ahea
d and allocate |
| 392 // enough memory to swizzle if necessary. |
| 393 case kSwizzleColor_XformMode: { |
| 394 size_t colorXformBytes = dstInfo.width() * sizeof(uint32_t); |
| 395 fStorage.reset(SkAlign4(fSrcRowBytes) + colorXformBytes); |
| 396 fSwizzlerSrcRow = fStorage.get(); |
| 397 fColorXformSrcRow = SkTAddOffset<uint32_t>(fSwizzlerSrcRow, SkAlign4
(fSrcRowBytes)); |
| 398 break; |
| 399 } |
| 400 } |
390 } | 401 } |
391 | 402 |
392 static inline bool apply_xform_on_decode(SkColorType dstColorType, SkEncodedInfo
::Color srcColor) { | 403 void SkPngCodec::applyXformRow(void* dst, const void* src, SkColorType colorType
, |
393 // We will apply the color xform when reading the color table, unless F16 is
requested. | 404 SkAlphaType alphaType, int width) { |
394 return SkEncodedInfo::kPalette_Color != srcColor || kRGBA_F16_SkColorType ==
dstColorType; | 405 switch (fXformMode) { |
| 406 case kSwizzleOnly_XformMode: |
| 407 fSwizzler->swizzle(dst, (const uint8_t*) src); |
| 408 break; |
| 409 case kColorOnly_XformMode: |
| 410 fColorXform->apply(dst, (const uint32_t*) src, width, colorType, alp
haType); |
| 411 break; |
| 412 case kSwizzleColor_XformMode: |
| 413 fSwizzler->swizzle(fColorXformSrcRow, (const uint8_t*) src); |
| 414 fColorXform->apply(dst, fColorXformSrcRow, width, colorType, alphaTy
pe); |
| 415 break; |
| 416 } |
395 } | 417 } |
396 | 418 |
397 class SkPngNormalCodec : public SkPngCodec { | 419 class SkPngNormalCodec : public SkPngCodec { |
398 public: | 420 public: |
399 SkPngNormalCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageI
nfo, | 421 SkPngNormalCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageI
nfo, |
400 SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr
, | 422 SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr
, |
401 png_infop info_ptr, int bitDepth) | 423 png_infop info_ptr, int bitDepth) |
402 : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_p
tr, bitDepth, 1) | 424 : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_p
tr, bitDepth, 1) |
403 {} | 425 {} |
404 | 426 |
405 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
ons, | 427 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
ons, |
406 SkPMColor ctable[], int* ctableCount) override { | 428 SkPMColor ctable[], int* ctableCount) override { |
407 if (!png_conversion_possible(dstInfo, this->getInfo()) || | 429 if (!png_conversion_possible(dstInfo, this->getInfo()) || |
408 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) | 430 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) |
409 { | 431 { |
410 return kInvalidConversion; | 432 return kInvalidConversion; |
411 } | 433 } |
412 | 434 |
413 this->allocateStorage(); | 435 this->allocateStorage(dstInfo); |
414 return kSuccess; | 436 return kSuccess; |
415 } | 437 } |
416 | 438 |
417 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou
nt, int startRow) | 439 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou
nt, int startRow) |
418 override { | 440 override { |
419 SkASSERT(0 == startRow); | 441 SkASSERT(0 == startRow); |
420 | 442 |
421 // Assume that an error in libpng indicates an incomplete input. | 443 // Assume that an error in libpng indicates an incomplete input. |
422 int y = 0; | 444 int y = 0; |
423 if (setjmp(png_jmpbuf((png_struct*)fPng_ptr))) { | 445 if (setjmp(png_jmpbuf((png_struct*)fPng_ptr))) { |
424 SkCodecPrintf("Failed to read row.\n"); | 446 SkCodecPrintf("Failed to read row.\n"); |
425 return y; | 447 return y; |
426 } | 448 } |
427 | 449 |
428 void* swizzlerDstRow = dst; | |
429 size_t swizzlerDstRowBytes = rowBytes; | |
430 | |
431 bool colorXform = fColorXform && | |
432 apply_xform_on_decode(dstInfo.colorType(), this->getEncodedInfo(
).color()); | |
433 if (colorXform) { | |
434 swizzlerDstRow = fColorXformSrcRow; | |
435 swizzlerDstRowBytes = 0; | |
436 } | |
437 | |
438 SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), | 450 SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), |
439 this->getInfo().alphaType(
)); | 451 this->getInfo().alphaType(
)); |
| 452 int width = fSwizzler ? fSwizzler->swizzleWidth() : dstInfo.width(); |
| 453 |
440 for (; y < count; y++) { | 454 for (; y < count; y++) { |
441 png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); | 455 png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); |
442 fSwizzler->swizzle(swizzlerDstRow, fSwizzlerSrcRow); | 456 this->applyXformRow(dst, fSwizzlerSrcRow, dstInfo.colorType(), xform
AlphaType, width); |
443 | 457 dst = SkTAddOffset<void>(dst, rowBytes); |
444 if (colorXform) { | |
445 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, fSwizz
ler->swizzleWidth(), | |
446 dstInfo.colorType(), xformAlphaType); | |
447 dst = SkTAddOffset<void>(dst, rowBytes); | |
448 } | |
449 | |
450 swizzlerDstRow = SkTAddOffset<void>(swizzlerDstRow, swizzlerDstRowBy
tes); | |
451 } | 458 } |
452 | 459 |
453 return y; | 460 return y; |
454 } | 461 } |
455 | 462 |
456 int onGetScanlines(void* dst, int count, size_t rowBytes) override { | 463 int onGetScanlines(void* dst, int count, size_t rowBytes) override { |
457 return this->readRows(this->dstInfo(), dst, rowBytes, count, 0); | 464 return this->readRows(this->dstInfo(), dst, rowBytes, count, 0); |
458 } | 465 } |
459 | 466 |
460 bool onSkipScanlines(int count) override { | 467 bool onSkipScanlines(int count) override { |
(...skipping 24 matching lines...) Expand all Loading... |
485 } | 492 } |
486 | 493 |
487 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
ons, | 494 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
ons, |
488 SkPMColor ctable[], int* ctableCount) override { | 495 SkPMColor ctable[], int* ctableCount) override { |
489 if (!png_conversion_possible(dstInfo, this->getInfo()) || | 496 if (!png_conversion_possible(dstInfo, this->getInfo()) || |
490 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) | 497 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) |
491 { | 498 { |
492 return kInvalidConversion; | 499 return kInvalidConversion; |
493 } | 500 } |
494 | 501 |
495 this->allocateStorage(); | 502 this->allocateStorage(dstInfo); |
496 fCanSkipRewind = true; | 503 fCanSkipRewind = true; |
497 return SkCodec::kSuccess; | 504 return SkCodec::kSuccess; |
498 } | 505 } |
499 | 506 |
500 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou
nt, int startRow) | 507 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou
nt, int startRow) |
501 override { | 508 override { |
502 if (setjmp(png_jmpbuf((png_struct*)fPng_ptr))) { | 509 if (setjmp(png_jmpbuf((png_struct*)fPng_ptr))) { |
503 SkCodecPrintf("Failed to get scanlines.\n"); | 510 SkCodecPrintf("Failed to get scanlines.\n"); |
504 // FIXME (msarett): Returning 0 is pessimistic. If we can complete
a single pass, | 511 // FIXME (msarett): Returning 0 is pessimistic. If we can complete
a single pass, |
505 // we may be able to report that all of the memory has been initiali
zed. Even if we | 512 // we may be able to report that all of the memory has been initiali
zed. Even if we |
(...skipping 13 matching lines...) Expand all Loading... |
519 for (int y = 0; y < count; y++) { | 526 for (int y = 0; y < count; y++) { |
520 png_read_row(fPng_ptr, srcRow, nullptr); | 527 png_read_row(fPng_ptr, srcRow, nullptr); |
521 srcRow += fSrcRowBytes; | 528 srcRow += fSrcRowBytes; |
522 } | 529 } |
523 // Discard rows that we don't need. | 530 // Discard rows that we don't need. |
524 for (int y = 0; y < this->getInfo().height() - startRow - count; y++
) { | 531 for (int y = 0; y < this->getInfo().height() - startRow - count; y++
) { |
525 png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); | 532 png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); |
526 } | 533 } |
527 } | 534 } |
528 | 535 |
529 // Swizzle and xform the rows we care about | |
530 void* swizzlerDstRow = dst; | |
531 size_t swizzlerDstRowBytes = rowBytes; | |
532 | |
533 bool colorXform = fColorXform && | |
534 apply_xform_on_decode(dstInfo.colorType(), this->getEncodedInfo(
).color()); | |
535 if (colorXform) { | |
536 swizzlerDstRow = fColorXformSrcRow; | |
537 swizzlerDstRowBytes = 0; | |
538 } | |
539 | |
540 SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), | 536 SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), |
541 this->getInfo().alphaType(
)); | 537 this->getInfo().alphaType(
)); |
| 538 int width = fSwizzler ? fSwizzler->swizzleWidth() : dstInfo.width(); |
542 srcRow = storage.get(); | 539 srcRow = storage.get(); |
543 for (int y = 0; y < count; y++) { | 540 for (int y = 0; y < count; y++) { |
544 fSwizzler->swizzle(swizzlerDstRow, srcRow); | 541 this->applyXformRow(dst, srcRow, dstInfo.colorType(), xformAlphaType
, width); |
545 srcRow = SkTAddOffset<uint8_t>(srcRow, fSrcRowBytes); | 542 srcRow = SkTAddOffset<uint8_t>(srcRow, fSrcRowBytes); |
546 | 543 dst = SkTAddOffset<void>(dst, rowBytes); |
547 if (colorXform) { | |
548 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, fSwizz
ler->swizzleWidth(), | |
549 dstInfo.colorType(), xformAlphaType); | |
550 dst = SkTAddOffset<void>(dst, rowBytes); | |
551 } | |
552 | |
553 swizzlerDstRow = SkTAddOffset<void>(swizzlerDstRow, swizzlerDstRowBy
tes); | |
554 } | 544 } |
555 | 545 |
556 return count; | 546 return count; |
557 } | 547 } |
558 | 548 |
559 int onGetScanlines(void* dst, int count, size_t rowBytes) override { | 549 int onGetScanlines(void* dst, int count, size_t rowBytes) override { |
560 // rewind stream if have previously called onGetScanlines, | 550 // rewind stream if have previously called onGetScanlines, |
561 // since we need entire progressive image to get scanlines | 551 // since we need entire progressive image to get scanlines |
562 if (fCanSkipRewind) { | 552 if (fCanSkipRewind) { |
563 // We already rewound in onStartScanlineDecode, so there is no reaso
n to rewind. | 553 // We already rewound in onStartScanlineDecode, so there is no reaso
n to rewind. |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 /////////////////////////////////////////////////////////////////////////////// | 799 /////////////////////////////////////////////////////////////////////////////// |
810 | 800 |
811 bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
ions, | 801 bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
ions, |
812 SkPMColor ctable[], int* ctableCount) { | 802 SkPMColor ctable[], int* ctableCount) { |
813 if (setjmp(png_jmpbuf((png_struct*)fPng_ptr))) { | 803 if (setjmp(png_jmpbuf((png_struct*)fPng_ptr))) { |
814 SkCodecPrintf("Failed on png_read_update_info.\n"); | 804 SkCodecPrintf("Failed on png_read_update_info.\n"); |
815 return false; | 805 return false; |
816 } | 806 } |
817 png_read_update_info(fPng_ptr, fInfo_ptr); | 807 png_read_update_info(fPng_ptr, fInfo_ptr); |
818 | 808 |
819 // It's important to reset fColorXform to nullptr. We don't do this on rewi
nding | 809 // Reset fSwizzler and fColorXform. We can't do this in onRewind() because
the |
820 // because the interlaced scanline decoder may need to rewind. | 810 // interlaced scanline decoder may need to rewind. |
| 811 fSwizzler.reset(nullptr); |
821 fColorXform = nullptr; | 812 fColorXform = nullptr; |
822 SkImageInfo swizzlerInfo = dstInfo; | 813 |
823 Options swizzlerOptions = options; | |
824 bool needsColorXform = needs_color_xform(dstInfo, this->getInfo()); | 814 bool needsColorXform = needs_color_xform(dstInfo, this->getInfo()); |
825 if (needsColorXform) { | 815 if (needsColorXform) { |
826 switch (dstInfo.colorType()) { | 816 if (kGray_8_SkColorType == dstInfo.colorType()) { |
827 case kRGBA_8888_SkColorType: | 817 // FIXME (msarett): |
828 case kBGRA_8888_SkColorType: | 818 // Support color xforms for gray output? |
829 case kRGBA_F16_SkColorType: | 819 return false; |
830 swizzlerInfo = swizzlerInfo.makeColorType(kRGBA_8888_SkColorType
); | |
831 if (kPremul_SkAlphaType == dstInfo.alphaType()) { | |
832 swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaT
ype); | |
833 } | |
834 break; | |
835 case kIndex_8_SkColorType: | |
836 break; | |
837 default: | |
838 return false; | |
839 } | 820 } |
840 | 821 |
841 fColorXform = SkColorSpaceXform::New(sk_ref_sp(this->getInfo().colorSpac
e()), | 822 fColorXform = SkColorSpaceXform::New(sk_ref_sp(this->getInfo().colorSpac
e()), |
842 sk_ref_sp(dstInfo.colorSpace())); | 823 sk_ref_sp(dstInfo.colorSpace())); |
843 | 824 |
844 if (!fColorXform && kRGBA_F16_SkColorType == dstInfo.colorType()) { | 825 if (!fColorXform && kRGBA_F16_SkColorType == dstInfo.colorType()) { |
845 return false; | 826 return false; |
846 } | 827 } |
| 828 } |
847 | 829 |
848 // When there is a color xform, we swizzle into temporary memory, which
is not | 830 // If the image is RGBA and we have a color xform, we can skip the swizzler. |
849 // zero initialized. | 831 // FIXME (msarett): |
850 // FIXME (msarett): | 832 // Support more input types to fColorXform (ex: RGB, Gray) and skip the swiz
zler more often. |
851 // Is this a problem? | 833 if (fColorXform && SkEncodedInfo::kRGBA_Color == this->getEncodedInfo().colo
r() && |
852 swizzlerOptions.fZeroInitialized = kNo_ZeroInitialized; | 834 !options.fSubset) |
| 835 { |
| 836 fXformMode = kColorOnly_XformMode; |
| 837 return true; |
853 } | 838 } |
854 | 839 |
855 if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { | 840 if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { |
856 if (!this->createColorTable(dstInfo, ctableCount)) { | 841 if (!this->createColorTable(dstInfo, ctableCount)) { |
857 return false; | 842 return false; |
858 } | 843 } |
859 } | 844 } |
860 | 845 |
861 // Copy the color table to the client if they request kIndex8 mode | 846 // Copy the color table to the client if they request kIndex8 mode. |
862 copy_color_table(swizzlerInfo, fColorTable, ctable, ctableCount); | 847 copy_color_table(dstInfo, fColorTable, ctable, ctableCount); |
863 | 848 |
864 // Create the swizzler. SkPngCodec retains ownership of the color table. | 849 this->initializeSwizzler(dstInfo, options); |
| 850 return true; |
| 851 } |
| 852 |
| 853 static inline bool apply_xform_on_decode(SkColorType dstColorType, SkEncodedInfo
::Color srcColor) { |
| 854 // We will apply the color xform when reading the color table, unless F16 is
requested. |
| 855 return SkEncodedInfo::kPalette_Color != srcColor || kRGBA_F16_SkColorType ==
dstColorType; |
| 856 } |
| 857 |
| 858 void SkPngCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& o
ptions) { |
| 859 SkImageInfo swizzlerInfo = dstInfo; |
| 860 Options swizzlerOptions = options; |
| 861 fXformMode = kSwizzleOnly_XformMode; |
| 862 if (fColorXform && apply_xform_on_decode(dstInfo.colorType(), this->getEncod
edInfo().color())) { |
| 863 swizzlerInfo = swizzlerInfo.makeColorType(kRGBA_8888_SkColorType); |
| 864 if (kPremul_SkAlphaType == dstInfo.alphaType()) { |
| 865 swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType); |
| 866 } |
| 867 |
| 868 fXformMode = kSwizzleColor_XformMode; |
| 869 |
| 870 // Here, we swizzle into temporary memory, which is not zero initialized
. |
| 871 // FIXME (msarett): |
| 872 // Is this a problem? |
| 873 swizzlerOptions.fZeroInitialized = kNo_ZeroInitialized; |
| 874 } |
| 875 |
865 const SkPMColor* colors = get_color_ptr(fColorTable.get()); | 876 const SkPMColor* colors = get_color_ptr(fColorTable.get()); |
866 fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, s
wizzlerInfo, | 877 fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, s
wizzlerInfo, |
867 swizzlerOptions)); | 878 swizzlerOptions)); |
868 SkASSERT(fSwizzler); | 879 SkASSERT(fSwizzler); |
869 return true; | 880 } |
| 881 |
| 882 SkSampler* SkPngCodec::getSampler(bool createIfNecessary) { |
| 883 if (fSwizzler || !createIfNecessary) { |
| 884 return fSwizzler; |
| 885 } |
| 886 |
| 887 this->initializeSwizzler(this->dstInfo(), this->options()); |
| 888 return fSwizzler; |
870 } | 889 } |
871 | 890 |
872 bool SkPngCodec::onRewind() { | 891 bool SkPngCodec::onRewind() { |
873 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header | 892 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header |
874 // succeeds, they will be repopulated, and if it fails, they will | 893 // succeeds, they will be repopulated, and if it fails, they will |
875 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will | 894 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will |
876 // come through this function which will rewind and again attempt | 895 // come through this function which will rewind and again attempt |
877 // to reinitialize them. | 896 // to reinitialize them. |
878 this->destroyReadStruct(); | 897 this->destroyReadStruct(); |
879 | 898 |
(...skipping 15 matching lines...) Expand all Loading... |
895 if (!png_conversion_possible(dstInfo, this->getInfo()) || | 914 if (!png_conversion_possible(dstInfo, this->getInfo()) || |
896 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) | 915 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) |
897 { | 916 { |
898 return kInvalidConversion; | 917 return kInvalidConversion; |
899 } | 918 } |
900 | 919 |
901 if (options.fSubset) { | 920 if (options.fSubset) { |
902 return kUnimplemented; | 921 return kUnimplemented; |
903 } | 922 } |
904 | 923 |
905 this->allocateStorage(); | 924 this->allocateStorage(dstInfo); |
906 int count = this->readRows(dstInfo, dst, rowBytes, dstInfo.height(), 0); | 925 int count = this->readRows(dstInfo, dst, rowBytes, dstInfo.height(), 0); |
907 if (count > dstInfo.height()) { | 926 if (count > dstInfo.height()) { |
908 *rowsDecoded = count; | 927 *rowsDecoded = count; |
909 return kIncompleteInput; | 928 return kIncompleteInput; |
910 } | 929 } |
911 | 930 |
912 return kSuccess; | 931 return kSuccess; |
913 } | 932 } |
914 | 933 |
915 uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const { | 934 uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const { |
(...skipping 10 matching lines...) Expand all Loading... |
926 SkCodec* outCodec; | 945 SkCodec* outCodec; |
927 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { | 946 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { |
928 // Codec has taken ownership of the stream. | 947 // Codec has taken ownership of the stream. |
929 SkASSERT(outCodec); | 948 SkASSERT(outCodec); |
930 streamDeleter.release(); | 949 streamDeleter.release(); |
931 return outCodec; | 950 return outCodec; |
932 } | 951 } |
933 | 952 |
934 return nullptr; | 953 return nullptr; |
935 } | 954 } |
OLD | NEW |