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

Side by Side Diff: src/images/SkPNGImageEncoder.cpp

Issue 2330053002: Encode kIndex8 to PNG more efficiently (Closed)
Patch Set: Fix loop Created 4 years, 3 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 | « no previous file | 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 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
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* SK_RESTRICT pale tte,
111 png_byte* SK_RESTRICT alphas, SkAlphaType alphaTy pe) {
112 const SkPMColor* SK_RESTRICT 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;
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.
150 int currIndex = numWithAlpha;
151 int i = 0;
152 while (currIndex != count) {
153 uint8_t alpha = SkGetPackedA32(colors[i]);
154 if (0xFF == alpha) {
155 palette[currIndex].red = SkGetPackedR32(colors[i]);
156 palette[currIndex].green = SkGetPackedG32(colors[i]);
157 palette[currIndex].blue = SkGetPackedB32(colors[i]);
158 currIndex++;
159 }
160
161 i++;
162 }
168 } 163 }
169 return num_trans; 164
165 return numWithAlpha;
170 } 166 }
171 167
172 class SkPNGImageEncoder : public SkImageEncoder { 168 class SkPNGImageEncoder : public SkImageEncoder {
173 protected: 169 protected:
174 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override; 170 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override;
175 private: 171 private:
176 bool doEncode(SkWStream* stream, const SkBitmap& bm, 172 bool doEncode(SkWStream* stream, const SkBitmap& bm,
177 SkAlphaType alphaType, int colorType, 173 SkAlphaType alphaType, int colorType,
178 int bitDepth, SkColorType ct, 174 int bitDepth, SkColorType ct,
179 png_color_8& sig_bit); 175 png_color_8& sig_bit);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(), 314 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(),
319 bitDepth, colorType, 315 bitDepth, colorType,
320 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, 316 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
321 PNG_FILTER_TYPE_BASE); 317 PNG_FILTER_TYPE_BASE);
322 318
323 // set our colortable/trans arrays if needed 319 // set our colortable/trans arrays if needed
324 png_color paletteColors[256]; 320 png_color paletteColors[256];
325 png_byte trans[256]; 321 png_byte trans[256];
326 if (kIndex_8_SkColorType == ct) { 322 if (kIndex_8_SkColorType == ct) {
327 SkColorTable* colorTable = bitmap.getColorTable(); 323 SkColorTable* colorTable = bitmap.getColorTable();
324 SkASSERT(colorTable);
328 int numTrans = pack_palette(colorTable, paletteColors, trans, alphaType) ; 325 int numTrans = pack_palette(colorTable, paletteColors, trans, alphaType) ;
329 png_set_PLTE(png_ptr, info_ptr, paletteColors, colorTable->count()); 326 png_set_PLTE(png_ptr, info_ptr, paletteColors, colorTable->count());
330 if (numTrans > 0) { 327 if (numTrans > 0) {
331 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); 328 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr);
332 } 329 }
333 } 330 }
334 331
335 png_set_sBIT(png_ptr, info_ptr, &sig_bit); 332 png_set_sBIT(png_ptr, info_ptr, &sig_bit);
336 png_write_info(png_ptr, info_ptr); 333 png_write_info(png_ptr, info_ptr);
337 334
(...skipping 18 matching lines...) Expand all
356 353
357 /////////////////////////////////////////////////////////////////////////////// 354 ///////////////////////////////////////////////////////////////////////////////
358 DEFINE_ENCODER_CREATOR(PNGImageEncoder); 355 DEFINE_ENCODER_CREATOR(PNGImageEncoder);
359 /////////////////////////////////////////////////////////////////////////////// 356 ///////////////////////////////////////////////////////////////////////////////
360 357
361 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { 358 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
362 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; 359 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr;
363 } 360 }
364 361
365 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); 362 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698