Chromium Code Reviews| 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 fPng_ptr = nullptr; | 85 fPng_ptr = nullptr; |
| 86 fInfo_ptr = nullptr; | 86 fInfo_ptr = nullptr; |
| 87 } | 87 } |
| 88 | 88 |
| 89 private: | 89 private: |
| 90 png_structp fPng_ptr; | 90 png_structp fPng_ptr; |
| 91 png_infop fInfo_ptr; | 91 png_infop fInfo_ptr; |
| 92 }; | 92 }; |
| 93 #define AutoCleanPng(...) SK_REQUIRE_LOCAL_VAR(AutoCleanPng) | 93 #define AutoCleanPng(...) SK_REQUIRE_LOCAL_VAR(AutoCleanPng) |
| 94 | 94 |
| 95 static inline SkAlphaType xform_alpha_type(SkAlphaType dstAlphaType, SkAlphaType srcAlphaType) { | |
| 96 return (kOpaque_SkAlphaType == srcAlphaType) ? kOpaque_SkAlphaType : dstAlph aType; | |
| 97 } | |
| 98 | |
| 95 // Note: SkColorTable claims to store SkPMColors, which is not necessarily the c ase here. | 99 // Note: SkColorTable claims to store SkPMColors, which is not necessarily the c ase here. |
| 96 bool SkPngCodec::createColorTable(SkColorType dstColorType, bool premultiply, in t* ctableCount) { | 100 bool SkPngCodec::createColorTable(const SkImageInfo& dstInfo, int* ctableCount) { |
| 97 | 101 |
| 98 int numColors; | 102 int numColors; |
| 99 png_color* palette; | 103 png_color* palette; |
| 100 if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numColors)) { | 104 if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numColors)) { |
| 101 return false; | 105 return false; |
| 102 } | 106 } |
| 103 | 107 |
| 104 // Note: These are not necessarily SkPMColors. | 108 // Note: These are not necessarily SkPMColors. |
| 105 SkPMColor colorPtr[256]; | 109 SkPMColor colorPtr[256]; |
|
mtklein
2016/08/22 14:22:51
Just noticed it's a little odd to have an array na
msarett
2016/08/22 15:01:35
Done.
| |
| 110 SkColorType tableColorType = fColorXform ? kRGBA_8888_SkColorType : dstInfo. colorType(); | |
| 106 | 111 |
| 107 png_bytep alphas; | 112 png_bytep alphas; |
| 108 int numColorsWithAlpha = 0; | 113 int numColorsWithAlpha = 0; |
| 109 if (png_get_tRNS(fPng_ptr, fInfo_ptr, &alphas, &numColorsWithAlpha, nullptr) ) { | 114 if (png_get_tRNS(fPng_ptr, fInfo_ptr, &alphas, &numColorsWithAlpha, nullptr) ) { |
| 115 // If we are performing a color xform, it will handle the premultiply. | |
|
mtklein
2016/08/22 14:22:51
... otherwise we'll do it here.
msarett
2016/08/22 15:01:35
Done.
| |
| 116 bool needsPremul = needs_premul(dstInfo, this->getInfo()); | |
| 117 bool doPremul = needsPremul && !fColorXform; | |
|
mtklein
2016/08/22 14:22:51
Might be just as clear as
bool premultiply = !
msarett
2016/08/22 15:01:35
Done.
| |
| 118 | |
| 110 // Choose which function to use to create the color table. If the final destination's | 119 // Choose which function to use to create the color table. If the final destination's |
| 111 // colortype is unpremultiplied, the color table will store unpremultipl ied colors. | 120 // colortype is unpremultiplied, the color table will store unpremultipl ied colors. |
| 112 PackColorProc proc = choose_pack_color_proc(premultiply, dstColorType); | 121 PackColorProc proc = choose_pack_color_proc(doPremul, tableColorType); |
| 113 | 122 |
| 114 for (int i = 0; i < numColorsWithAlpha; i++) { | 123 for (int i = 0; i < numColorsWithAlpha; i++) { |
| 115 // We don't have a function in SkOpts that combines a set of alphas with a set | 124 // We don't have a function in SkOpts that combines a set of alphas with a set |
| 116 // of RGBs. We could write one, but it's hardly worth it, given tha t this | 125 // of RGBs. We could write one, but it's hardly worth it, given tha t this |
| 117 // is such a small fraction of the total decode time. | 126 // is such a small fraction of the total decode time. |
| 118 colorPtr[i] = proc(alphas[i], palette->red, palette->green, palette- >blue); | 127 colorPtr[i] = proc(alphas[i], palette->red, palette->green, palette- >blue); |
| 119 palette++; | 128 palette++; |
| 120 } | 129 } |
| 121 } | 130 } |
| 122 | 131 |
| 123 if (numColorsWithAlpha < numColors) { | 132 if (numColorsWithAlpha < numColors) { |
| 124 // The optimized code depends on a 3-byte png_color struct with the colo rs | 133 // The optimized code depends on a 3-byte png_color struct with the colo rs |
| 125 // in RGB order. These checks make sure it is safe to use. | 134 // in RGB order. These checks make sure it is safe to use. |
| 126 static_assert(3 == sizeof(png_color), "png_color struct has changed. Op ts are broken."); | 135 static_assert(3 == sizeof(png_color), "png_color struct has changed. Op ts are broken."); |
| 127 #ifdef SK_DEBUG | 136 #ifdef SK_DEBUG |
| 128 SkASSERT(&palette->red < &palette->green); | 137 SkASSERT(&palette->red < &palette->green); |
| 129 SkASSERT(&palette->green < &palette->blue); | 138 SkASSERT(&palette->green < &palette->blue); |
| 130 #endif | 139 #endif |
| 131 | 140 |
| 132 if (is_rgba(dstColorType)) { | 141 if (is_rgba(tableColorType)) { |
| 133 SkOpts::RGB_to_RGB1(colorPtr + numColorsWithAlpha, palette, | 142 SkOpts::RGB_to_RGB1(colorPtr + numColorsWithAlpha, palette, |
| 134 numColors - numColorsWithAlpha); | 143 numColors - numColorsWithAlpha); |
| 135 } else { | 144 } else { |
| 136 SkOpts::RGB_to_BGR1(colorPtr + numColorsWithAlpha, palette, | 145 SkOpts::RGB_to_BGR1(colorPtr + numColorsWithAlpha, palette, |
| 137 numColors - numColorsWithAlpha); | 146 numColors - numColorsWithAlpha); |
| 138 } | 147 } |
| 139 } | 148 } |
| 140 | 149 |
| 150 // If we are not decoding to F16, we can color xform now and store the resul ts | |
| 151 // in the color table. | |
| 152 if (fColorXform && kRGBA_F16_SkColorType != dstInfo.colorType()) { | |
| 153 SkColorType xformColorType = is_rgba(dstInfo.colorType()) ? | |
| 154 kRGBA_8888_SkColorType : kBGRA_8888_SkColorType; | |
| 155 SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), | |
| 156 this->getInfo().alphaType( )); | |
| 157 fColorXform->apply(colorPtr, colorPtr, numColors, xformColorType, xformA lphaType); | |
| 158 | |
| 159 // We have already applied the color xform. Set it to nullptr so we don 't try to | |
| 160 // use it again. | |
| 161 fColorXform = nullptr; | |
|
mtklein
2016/08/22 14:22:51
Is there not some sort of early return we can make
msarett
2016/08/22 15:01:35
Yeah this is confusing, I'll try this another way.
| |
| 162 } | |
| 163 | |
| 141 // Pad the color table with the last color in the table (or black) in the ca se that | 164 // Pad the color table with the last color in the table (or black) in the ca se that |
| 142 // invalid pixel indices exceed the number of colors in the table. | 165 // invalid pixel indices exceed the number of colors in the table. |
| 143 const int maxColors = 1 << fBitDepth; | 166 const int maxColors = 1 << fBitDepth; |
| 144 if (numColors < maxColors) { | 167 if (numColors < maxColors) { |
| 145 SkPMColor lastColor = numColors > 0 ? colorPtr[numColors - 1] : SK_Color BLACK; | 168 SkPMColor lastColor = numColors > 0 ? colorPtr[numColors - 1] : SK_Color BLACK; |
| 146 sk_memset32(colorPtr + numColors, lastColor, maxColors - numColors); | 169 sk_memset32(colorPtr + numColors, lastColor, maxColors - numColors); |
| 147 } | 170 } |
| 148 | 171 |
| 149 // Set the new color count. | 172 // Set the new color count. |
| 150 if (ctableCount != nullptr) { | 173 if (ctableCount != nullptr) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 return y; | 422 return y; |
| 400 } | 423 } |
| 401 | 424 |
| 402 void* swizzlerDstRow = dst; | 425 void* swizzlerDstRow = dst; |
| 403 size_t swizzlerDstRowBytes = rowBytes; | 426 size_t swizzlerDstRowBytes = rowBytes; |
| 404 if (fColorXform) { | 427 if (fColorXform) { |
| 405 swizzlerDstRow = fColorXformSrcRow; | 428 swizzlerDstRow = fColorXformSrcRow; |
| 406 swizzlerDstRowBytes = 0; | 429 swizzlerDstRowBytes = 0; |
| 407 } | 430 } |
| 408 | 431 |
| 409 SkAlphaType xformAlphaType = (kOpaque_SkAlphaType == this->getInfo().alp haType()) ? | 432 SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), |
| 410 kOpaque_SkAlphaType : dstInfo.alphaType(); | 433 this->getInfo().alphaType( )); |
| 411 for (; y < count; y++) { | 434 for (; y < count; y++) { |
| 412 png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); | 435 png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); |
| 413 fSwizzler->swizzle(swizzlerDstRow, fSwizzlerSrcRow); | 436 fSwizzler->swizzle(swizzlerDstRow, fSwizzlerSrcRow); |
| 414 | 437 |
| 415 if (fColorXform) { | 438 if (fColorXform) { |
| 416 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, fSwizz ler->swizzleWidth(), | 439 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, fSwizz ler->swizzleWidth(), |
| 417 dstInfo.colorType(), xformAlphaType); | 440 dstInfo.colorType(), xformAlphaType); |
| 418 dst = SkTAddOffset<void>(dst, rowBytes); | 441 dst = SkTAddOffset<void>(dst, rowBytes); |
| 419 } | 442 } |
| 420 | 443 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 } | 522 } |
| 500 | 523 |
| 501 // Swizzle and xform the rows we care about | 524 // Swizzle and xform the rows we care about |
| 502 void* swizzlerDstRow = dst; | 525 void* swizzlerDstRow = dst; |
| 503 size_t swizzlerDstRowBytes = rowBytes; | 526 size_t swizzlerDstRowBytes = rowBytes; |
| 504 if (fColorXform) { | 527 if (fColorXform) { |
| 505 swizzlerDstRow = fColorXformSrcRow; | 528 swizzlerDstRow = fColorXformSrcRow; |
| 506 swizzlerDstRowBytes = 0; | 529 swizzlerDstRowBytes = 0; |
| 507 } | 530 } |
| 508 | 531 |
| 509 SkAlphaType xformAlphaType = (kOpaque_SkAlphaType == this->getInfo().alp haType()) ? | 532 SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), |
| 510 kOpaque_SkAlphaType : dstInfo.alphaType(); | 533 this->getInfo().alphaType( )); |
| 511 srcRow = storage.get(); | 534 srcRow = storage.get(); |
| 512 for (int y = 0; y < count; y++) { | 535 for (int y = 0; y < count; y++) { |
| 513 fSwizzler->swizzle(swizzlerDstRow, srcRow); | 536 fSwizzler->swizzle(swizzlerDstRow, srcRow); |
| 514 srcRow = SkTAddOffset<uint8_t>(srcRow, fSrcRowBytes); | 537 srcRow = SkTAddOffset<uint8_t>(srcRow, fSrcRowBytes); |
| 515 | 538 |
| 516 if (fColorXform) { | 539 if (fColorXform) { |
| 517 if (fColorXform) { | 540 if (fColorXform) { |
| 518 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, | 541 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, |
| 519 fSwizzler->swizzleWidth(), dstInfo.colorT ype(), | 542 fSwizzler->swizzleWidth(), dstInfo.colorT ype(), |
| 520 xformAlphaType); | 543 xformAlphaType); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 if (needsColorXform) { | 808 if (needsColorXform) { |
| 786 switch (dstInfo.colorType()) { | 809 switch (dstInfo.colorType()) { |
| 787 case kRGBA_8888_SkColorType: | 810 case kRGBA_8888_SkColorType: |
| 788 case kBGRA_8888_SkColorType: | 811 case kBGRA_8888_SkColorType: |
| 789 case kRGBA_F16_SkColorType: | 812 case kRGBA_F16_SkColorType: |
| 790 swizzlerInfo = swizzlerInfo.makeColorType(kRGBA_8888_SkColorType ); | 813 swizzlerInfo = swizzlerInfo.makeColorType(kRGBA_8888_SkColorType ); |
| 791 if (kPremul_SkAlphaType == dstInfo.alphaType()) { | 814 if (kPremul_SkAlphaType == dstInfo.alphaType()) { |
| 792 swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaT ype); | 815 swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaT ype); |
| 793 } | 816 } |
| 794 break; | 817 break; |
| 818 case kIndex_8_SkColorType: | |
| 819 break; | |
| 795 default: | 820 default: |
| 796 return false; | 821 return false; |
| 797 } | 822 } |
| 798 | 823 |
| 799 fColorXform = SkColorSpaceXform::New(sk_ref_sp(this->getInfo().colorSpac e()), | 824 fColorXform = SkColorSpaceXform::New(sk_ref_sp(this->getInfo().colorSpac e()), |
| 800 sk_ref_sp(dstInfo.colorSpace())); | 825 sk_ref_sp(dstInfo.colorSpace())); |
| 801 | 826 |
| 802 if (!fColorXform && kRGBA_F16_SkColorType == dstInfo.colorType()) { | 827 if (!fColorXform && kRGBA_F16_SkColorType == dstInfo.colorType()) { |
| 803 return false; | 828 return false; |
| 804 } | 829 } |
| 805 } | 830 } |
| 806 | 831 |
| 807 if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { | 832 if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { |
| 808 if (!this->createColorTable(swizzlerInfo.colorType(), | 833 if (!this->createColorTable(dstInfo, ctableCount)) { |
| 809 kPremul_SkAlphaType == swizzlerInfo.alphaTyp e(), ctableCount)) { | |
| 810 return false; | 834 return false; |
| 811 } | 835 } |
| 812 } | 836 } |
| 813 | 837 |
| 814 // Copy the color table to the client if they request kIndex8 mode | 838 // Copy the color table to the client if they request kIndex8 mode |
| 815 copy_color_table(swizzlerInfo, fColorTable, ctable, ctableCount); | 839 copy_color_table(swizzlerInfo, fColorTable, ctable, ctableCount); |
| 816 | 840 |
| 817 // Create the swizzler. SkPngCodec retains ownership of the color table. | 841 // Create the swizzler. SkPngCodec retains ownership of the color table. |
| 818 const SkPMColor* colors = get_color_ptr(fColorTable.get()); | 842 const SkPMColor* colors = get_color_ptr(fColorTable.get()); |
| 819 fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, s wizzlerInfo, | 843 fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, s wizzlerInfo, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 879 SkCodec* outCodec; | 903 SkCodec* outCodec; |
| 880 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { | 904 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { |
| 881 // Codec has taken ownership of the stream. | 905 // Codec has taken ownership of the stream. |
| 882 SkASSERT(outCodec); | 906 SkASSERT(outCodec); |
| 883 streamDeleter.release(); | 907 streamDeleter.release(); |
| 884 return outCodec; | 908 return outCodec; |
| 885 } | 909 } |
| 886 | 910 |
| 887 return nullptr; | 911 return nullptr; |
| 888 } | 912 } |
| OLD | NEW |