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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 // implemented to guess sRGB in this case. | 350 // implemented to guess sRGB in this case. |
351 return nullptr; | 351 return nullptr; |
352 } | 352 } |
353 | 353 |
354 static int bytes_per_pixel(int bitsPerPixel) { | 354 static int bytes_per_pixel(int bitsPerPixel) { |
355 // Note that we will have to change this implementation if we start | 355 // Note that we will have to change this implementation if we start |
356 // supporting outputs from libpng that are less than 8-bits per component. | 356 // supporting outputs from libpng that are less than 8-bits per component. |
357 return bitsPerPixel / 8; | 357 return bitsPerPixel / 8; |
358 } | 358 } |
359 | 359 |
| 360 static bool png_conversion_possible(const SkImageInfo& dst, const SkImageInfo& s
rc) { |
| 361 // Ensure the alpha type is valid |
| 362 if (!valid_alpha(dst.alphaType(), src.alphaType())) { |
| 363 return false; |
| 364 } |
| 365 |
| 366 // Check for supported color types |
| 367 switch (dst.colorType()) { |
| 368 case kRGBA_8888_SkColorType: |
| 369 case kBGRA_8888_SkColorType: |
| 370 case kRGBA_F16_SkColorType: |
| 371 return true; |
| 372 case kRGB_565_SkColorType: |
| 373 return kOpaque_SkAlphaType == src.alphaType(); |
| 374 default: |
| 375 return dst.colorType() == src.colorType(); |
| 376 } |
| 377 } |
| 378 |
360 void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) { | 379 void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) { |
361 switch (fXformMode) { | 380 switch (fXformMode) { |
362 case kSwizzleOnly_XformMode: | 381 case kSwizzleOnly_XformMode: |
363 fStorage.reset(SkAlign4(fSrcRowBytes)); | 382 fStorage.reset(SkAlign4(fSrcRowBytes)); |
364 fSwizzlerSrcRow = fStorage.get(); | 383 fSwizzlerSrcRow = fStorage.get(); |
365 break; | 384 break; |
366 case kColorOnly_XformMode: | 385 case kColorOnly_XformMode: |
367 // Intentional fall through. A swizzler hasn't been created yet, bu
t one will | 386 // Intentional fall through. A swizzler hasn't been created yet, bu
t one will |
368 // be created later if we are sampling. We'll go ahead and allocate | 387 // be created later if we are sampling. We'll go ahead and allocate |
369 // enough memory to swizzle if necessary. | 388 // enough memory to swizzle if necessary. |
(...skipping 26 matching lines...) Expand all Loading... |
396 class SkPngNormalCodec : public SkPngCodec { | 415 class SkPngNormalCodec : public SkPngCodec { |
397 public: | 416 public: |
398 SkPngNormalCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageI
nfo, | 417 SkPngNormalCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageI
nfo, |
399 SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr
, | 418 SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr
, |
400 png_infop info_ptr, int bitDepth) | 419 png_infop info_ptr, int bitDepth) |
401 : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_p
tr, bitDepth, 1) | 420 : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_p
tr, bitDepth, 1) |
402 {} | 421 {} |
403 | 422 |
404 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
ons, | 423 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
ons, |
405 SkPMColor ctable[], int* ctableCount) override { | 424 SkPMColor ctable[], int* ctableCount) override { |
406 if (!conversion_possible(dstInfo, this->getInfo()) || | 425 if (!png_conversion_possible(dstInfo, this->getInfo()) || |
407 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) | 426 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) |
408 { | 427 { |
409 return kInvalidConversion; | 428 return kInvalidConversion; |
410 } | 429 } |
411 | 430 |
412 this->allocateStorage(dstInfo); | 431 this->allocateStorage(dstInfo); |
413 return kSuccess; | 432 return kSuccess; |
414 } | 433 } |
415 | 434 |
416 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou
nt, int startRow) | 435 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou
nt, int startRow) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 png_infop info_ptr, int bitDepth, int numberPasses) | 482 png_infop info_ptr, int bitDepth, int numberPasses) |
464 : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_p
tr, bitDepth, | 483 : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_p
tr, bitDepth, |
465 numberPasses) | 484 numberPasses) |
466 , fCanSkipRewind(false) | 485 , fCanSkipRewind(false) |
467 { | 486 { |
468 SkASSERT(numberPasses != 1); | 487 SkASSERT(numberPasses != 1); |
469 } | 488 } |
470 | 489 |
471 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
ons, | 490 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
ons, |
472 SkPMColor ctable[], int* ctableCount) override { | 491 SkPMColor ctable[], int* ctableCount) override { |
473 if (!conversion_possible(dstInfo, this->getInfo()) || | 492 if (!png_conversion_possible(dstInfo, this->getInfo()) || |
474 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) | 493 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) |
475 { | 494 { |
476 return kInvalidConversion; | 495 return kInvalidConversion; |
477 } | 496 } |
478 | 497 |
479 this->allocateStorage(dstInfo); | 498 this->allocateStorage(dstInfo); |
480 fCanSkipRewind = true; | 499 fCanSkipRewind = true; |
481 return SkCodec::kSuccess; | 500 return SkCodec::kSuccess; |
482 } | 501 } |
483 | 502 |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 SkCodecPrintf("Failed on png_read_update_info.\n"); | 800 SkCodecPrintf("Failed on png_read_update_info.\n"); |
782 return false; | 801 return false; |
783 } | 802 } |
784 png_read_update_info(fPng_ptr, fInfo_ptr); | 803 png_read_update_info(fPng_ptr, fInfo_ptr); |
785 | 804 |
786 // Reset fSwizzler and fColorXform. We can't do this in onRewind() because
the | 805 // Reset fSwizzler and fColorXform. We can't do this in onRewind() because
the |
787 // interlaced scanline decoder may need to rewind. | 806 // interlaced scanline decoder may need to rewind. |
788 fSwizzler.reset(nullptr); | 807 fSwizzler.reset(nullptr); |
789 fColorXform = nullptr; | 808 fColorXform = nullptr; |
790 | 809 |
791 if (needs_color_xform(dstInfo, this->getInfo())) { | 810 bool needsColorXform = needs_color_xform(dstInfo, this->getInfo()); |
| 811 if (needsColorXform) { |
| 812 if (kGray_8_SkColorType == dstInfo.colorType() || |
| 813 kRGB_565_SkColorType == dstInfo.colorType()) |
| 814 { |
| 815 return false; |
| 816 } |
| 817 |
792 fColorXform = SkColorSpaceXform::New(sk_ref_sp(this->getInfo().colorSpac
e()), | 818 fColorXform = SkColorSpaceXform::New(sk_ref_sp(this->getInfo().colorSpac
e()), |
793 sk_ref_sp(dstInfo.colorSpace())); | 819 sk_ref_sp(dstInfo.colorSpace())); |
794 SkASSERT(fColorXform); | 820 |
| 821 if (!fColorXform && kRGBA_F16_SkColorType == dstInfo.colorType()) { |
| 822 return false; |
| 823 } |
795 } | 824 } |
796 | 825 |
797 // If the image is RGBA and we have a color xform, we can skip the swizzler. | 826 // If the image is RGBA and we have a color xform, we can skip the swizzler. |
798 // FIXME (msarett): | 827 // FIXME (msarett): |
799 // Support more input types to fColorXform (ex: RGB, Gray) and skip the swiz
zler more often. | 828 // Support more input types to fColorXform (ex: RGB, Gray) and skip the swiz
zler more often. |
800 if (fColorXform && SkEncodedInfo::kRGBA_Color == this->getEncodedInfo().colo
r() && | 829 if (fColorXform && SkEncodedInfo::kRGBA_Color == this->getEncodedInfo().colo
r() && |
801 !options.fSubset) | 830 !options.fSubset) |
802 { | 831 { |
803 fXformMode = kColorOnly_XformMode; | 832 fXformMode = kColorOnly_XformMode; |
804 return true; | 833 return true; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 | 900 |
872 fPng_ptr = png_ptr; | 901 fPng_ptr = png_ptr; |
873 fInfo_ptr = info_ptr; | 902 fInfo_ptr = info_ptr; |
874 return true; | 903 return true; |
875 } | 904 } |
876 | 905 |
877 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, | 906 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, |
878 size_t rowBytes, const Options& options, | 907 size_t rowBytes, const Options& options, |
879 SkPMColor ctable[], int* ctableCount, | 908 SkPMColor ctable[], int* ctableCount, |
880 int* rowsDecoded) { | 909 int* rowsDecoded) { |
881 if (!conversion_possible(dstInfo, this->getInfo()) || | 910 if (!png_conversion_possible(dstInfo, this->getInfo()) || |
882 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) | 911 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) |
883 { | 912 { |
884 return kInvalidConversion; | 913 return kInvalidConversion; |
885 } | 914 } |
886 | 915 |
887 if (options.fSubset) { | 916 if (options.fSubset) { |
888 return kUnimplemented; | 917 return kUnimplemented; |
889 } | 918 } |
890 | 919 |
891 this->allocateStorage(dstInfo); | 920 this->allocateStorage(dstInfo); |
(...skipping 20 matching lines...) Expand all Loading... |
912 SkCodec* outCodec; | 941 SkCodec* outCodec; |
913 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { | 942 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { |
914 // Codec has taken ownership of the stream. | 943 // Codec has taken ownership of the stream. |
915 SkASSERT(outCodec); | 944 SkASSERT(outCodec); |
916 streamDeleter.release(); | 945 streamDeleter.release(); |
917 return outCodec; | 946 return outCodec; |
918 } | 947 } |
919 | 948 |
920 return nullptr; | 949 return nullptr; |
921 } | 950 } |
OLD | NEW |