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 |