Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/codec/SkPngCodec.cpp

Issue 2246143002: Support color xforms for kIndex8 pngs (Closed) Base URL: https://skia.googlesource.com/skia.git@xformpremul
Patch Set: Force legacy mode as default Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/codec/SkPngCodec.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/codec/SkPngCodec.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698