Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 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 "SkImageEncoder.h" | 8 #include "SkImageEncoder.h" |
| 9 #include "SkColor.h" | 9 #include "SkColor.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 int bits = SkNextLog2(colorCount); | 96 int bits = SkNextLog2(colorCount); |
| 97 SkASSERT(bits >= 1 && bits <= 8); | 97 SkASSERT(bits >= 1 && bits <= 8); |
| 98 // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8) | 98 // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8) |
| 99 return SkNextPow2(bits); | 99 return SkNextPow2(bits); |
| 100 #else | 100 #else |
| 101 // for the moment, we don't know how to pack bitdepth < 8 | 101 // for the moment, we don't know how to pack bitdepth < 8 |
| 102 return 8; | 102 return 8; |
| 103 #endif | 103 #endif |
| 104 } | 104 } |
| 105 | 105 |
| 106 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also | 106 /* Pack palette[] with the corresponding colors, and if the image has alpha, al so |
| 107 pack trans[] and return the number of trans[] entries written. If hasAlpha | 107 pack trans[] and return the number of alphas[] entries written. If the image is |
| 108 is false, the return value will always be 0. | 108 opaque, the return value will always be 0. |
| 109 */ | |
| 110 static inline int pack_palette(SkColorTable* ctable, png_color* palette, png_byt e* alphas, | |
| 111 SkAlphaType alphaType) { | |
| 112 const SkPMColor* colors = ctable->readColors(); | |
| 113 const int count = ctable->count(); | |
| 114 int numWithAlpha = 0; | |
| 115 if (kOpaque_SkAlphaType != alphaType) { | |
| 116 auto getUnpremulColor = [alphaType](uint8_t color, uint8_t alpha) { | |
| 117 if (kPremul_SkAlphaType == alphaType) { | |
| 118 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleT able(); | |
| 119 const SkUnPreMultiply::Scale scale = table[alpha]; | |
| 120 return (uint8_t) SkUnPreMultiply::ApplyScale(scale, color); | |
| 121 } else { | |
| 122 return color; | |
| 123 } | |
| 124 }; | |
| 109 | 125 |
| 110 Note: this routine takes care of unpremultiplying the RGB values when we | 126 // PNG requires that all non-opaque colors come first in the palette. W rite these first. |
| 111 have alpha in the colortable, since png doesn't support premul colors | 127 for (int i = 0; i < count; i++) { |
| 112 */ | 128 uint8_t alpha = SkGetPackedA32(colors[i]); |
| 113 static inline int pack_palette(SkColorTable* ctable, | 129 if (0xFF != alpha) { |
| 114 png_color* SK_RESTRICT palette, | 130 alphas[numWithAlpha] = alpha; |
|
scroggo
2016/09/12 16:40:57
Why did you remove SK_RESTRICT?
msarett
2016/09/12 16:58:31
SK_RESTRICT can sometimes allow the compiler to ma
| |
| 115 png_byte* SK_RESTRICT trans, SkAlphaType alphaTyp e) { | 131 palette[numWithAlpha].red = getUnpremulColor(SkGetPackedR32(co lors[i]), alpha); |
| 116 const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : nullpt r; | 132 palette[numWithAlpha].green = getUnpremulColor(SkGetPackedG32(co lors[i]), alpha); |
| 117 const int ctCount = ctable->count(); | 133 palette[numWithAlpha].blue = getUnpremulColor(SkGetPackedB32(co lors[i]), alpha); |
| 118 int i, num_trans = 0; | 134 numWithAlpha++; |
| 119 | |
| 120 if (kOpaque_SkAlphaType != alphaType) { | |
| 121 /* first see if we have some number of fully opaque at the end of the | |
| 122 ctable. PNG allows num_trans < num_palette, but all of the trans | |
| 123 entries must come first in the palette. If I was smarter, I'd | |
| 124 reorder the indices and ctable so that all non-opaque colors came | |
| 125 first in the palette. But, since that would slow down the encode, | |
| 126 I'm leaving the indices and ctable order as is, and just looking | |
| 127 at the tail of the ctable for opaqueness. | |
| 128 */ | |
| 129 num_trans = ctCount; | |
| 130 for (i = ctCount - 1; i >= 0; --i) { | |
| 131 if (SkGetPackedA32(colors[i]) != 0xFF) { | |
| 132 break; | |
| 133 } | |
| 134 num_trans -= 1; | |
| 135 } | |
| 136 | |
| 137 if (kPremul_SkAlphaType == alphaType) { | |
| 138 const SkUnPreMultiply::Scale* SK_RESTRICT table = SkUnPreMultiply::G etScaleTable(); | |
| 139 for (i = 0; i < num_trans; i++) { | |
| 140 const SkPMColor c = *colors++; | |
| 141 const unsigned a = SkGetPackedA32(c); | |
| 142 const SkUnPreMultiply::Scale s = table[a]; | |
| 143 trans[i] = a; | |
| 144 palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c )); | |
| 145 palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32( c)); | |
| 146 palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32( c)); | |
| 147 } | |
| 148 } else { | |
| 149 for (i = 0; i < num_trans; i++) { | |
| 150 const SkPMColor c = *colors++; | |
| 151 trans[i] = SkGetPackedA32(c); | |
| 152 palette[i].red = SkGetPackedR32(c); | |
| 153 palette[i].green = SkGetPackedG32(c); | |
| 154 palette[i].blue = SkGetPackedB32(c); | |
| 155 } | 135 } |
| 156 } | 136 } |
| 157 | 137 |
| 158 // now fall out of this if-block to use common code for the trailing | |
| 159 // opaque entries | |
| 160 } | 138 } |
| 161 | 139 |
| 162 // these (remaining) entries are opaque | 140 if (0 == numWithAlpha) { |
| 163 for (i = num_trans; i < ctCount; i++) { | 141 // All of the entries are opaque. |
| 164 SkPMColor c = *colors++; | 142 for (int i = 0; i < count; i++) { |
| 165 palette[i].red = SkGetPackedR32(c); | 143 SkPMColor c = *colors++; |
| 166 palette[i].green = SkGetPackedG32(c); | 144 palette[i].red = SkGetPackedR32(c); |
| 167 palette[i].blue = SkGetPackedB32(c); | 145 palette[i].green = SkGetPackedG32(c); |
| 146 palette[i].blue = SkGetPackedB32(c); | |
| 147 } | |
| 148 } else { | |
| 149 // We have already written the non-opaque colors. Now just write the op aque colors. | |
|
scroggo
2016/09/12 16:40:57
I think you could skip this if numWithAlpha == cou
msarett
2016/09/12 16:58:31
Yes nice catch, let's skip it.
| |
| 150 int currIndex = numWithAlpha; | |
| 151 for (int i = 0; i < count; i++) { | |
| 152 uint8_t alpha = SkGetPackedA32(colors[i]); | |
| 153 if (0xFF == alpha) { | |
| 154 palette[currIndex].red = SkGetPackedR32(colors[i]); | |
| 155 palette[currIndex].green = SkGetPackedG32(colors[i]); | |
| 156 palette[currIndex].blue = SkGetPackedB32(colors[i]); | |
| 157 currIndex++; | |
| 158 } | |
| 159 } | |
| 168 } | 160 } |
| 169 return num_trans; | 161 |
| 162 return numWithAlpha; | |
| 170 } | 163 } |
| 171 | 164 |
| 172 class SkPNGImageEncoder : public SkImageEncoder { | 165 class SkPNGImageEncoder : public SkImageEncoder { |
| 173 protected: | 166 protected: |
| 174 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override; | 167 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override; |
| 175 private: | 168 private: |
| 176 bool doEncode(SkWStream* stream, const SkBitmap& bm, | 169 bool doEncode(SkWStream* stream, const SkBitmap& bm, |
| 177 SkAlphaType alphaType, int colorType, | 170 SkAlphaType alphaType, int colorType, |
| 178 int bitDepth, SkColorType ct, | 171 int bitDepth, SkColorType ct, |
| 179 png_color_8& sig_bit); | 172 png_color_8& sig_bit); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(), | 313 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(), |
| 321 bitDepth, colorType, | 314 bitDepth, colorType, |
| 322 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, | 315 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, |
| 323 PNG_FILTER_TYPE_BASE); | 316 PNG_FILTER_TYPE_BASE); |
| 324 | 317 |
| 325 // set our colortable/trans arrays if needed | 318 // set our colortable/trans arrays if needed |
| 326 png_color paletteColors[256]; | 319 png_color paletteColors[256]; |
| 327 png_byte trans[256]; | 320 png_byte trans[256]; |
| 328 if (kIndex_8_SkColorType == ct) { | 321 if (kIndex_8_SkColorType == ct) { |
| 329 SkColorTable* ct = bitmap.getColorTable(); | 322 SkColorTable* ct = bitmap.getColorTable(); |
| 323 SkASSERT(ct); | |
| 330 int numTrans = pack_palette(ct, paletteColors, trans, alphaType); | 324 int numTrans = pack_palette(ct, paletteColors, trans, alphaType); |
| 331 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 325 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
| 332 if (numTrans > 0) { | 326 if (numTrans > 0) { |
| 333 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); | 327 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); |
| 334 } | 328 } |
| 335 } | 329 } |
| 336 | 330 |
| 337 png_set_sBIT(png_ptr, info_ptr, &sig_bit); | 331 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
| 338 png_write_info(png_ptr, info_ptr); | 332 png_write_info(png_ptr, info_ptr); |
| 339 | 333 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 358 | 352 |
| 359 /////////////////////////////////////////////////////////////////////////////// | 353 /////////////////////////////////////////////////////////////////////////////// |
| 360 DEFINE_ENCODER_CREATOR(PNGImageEncoder); | 354 DEFINE_ENCODER_CREATOR(PNGImageEncoder); |
| 361 /////////////////////////////////////////////////////////////////////////////// | 355 /////////////////////////////////////////////////////////////////////////////// |
| 362 | 356 |
| 363 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 357 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
| 364 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; | 358 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; |
| 365 } | 359 } |
| 366 | 360 |
| 367 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 361 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
| OLD | NEW |