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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 bool fHasAlpha; | 70 bool fHasAlpha; |
71 transform_scanline_proc fProc; | 71 transform_scanline_proc fProc; |
72 } gMap[] = { | 72 } gMap[] = { |
73 { kRGB_565_SkColorType, false, transform_scanline_565 }, | 73 { kRGB_565_SkColorType, false, transform_scanline_565 }, |
74 { kN32_SkColorType, false, transform_scanline_888 }, | 74 { kN32_SkColorType, false, transform_scanline_888 }, |
75 { kN32_SkColorType, true, transform_scanline_8888 }, | 75 { kN32_SkColorType, true, transform_scanline_8888 }, |
76 { kARGB_4444_SkColorType, false, transform_scanline_444 }, | 76 { kARGB_4444_SkColorType, false, transform_scanline_444 }, |
77 { kARGB_4444_SkColorType, true, transform_scanline_4444 }, | 77 { kARGB_4444_SkColorType, true, transform_scanline_4444 }, |
78 { kIndex_8_SkColorType, false, transform_scanline_memcpy }, | 78 { kIndex_8_SkColorType, false, transform_scanline_memcpy }, |
79 { kGray_8_SkColorType, false, transform_scanline_memcpy }, | 79 { kGray_8_SkColorType, false, transform_scanline_memcpy }, |
| 80 { kAlpha_8_SkColorType, true, transform_scanline_memcpy }, |
80 }; | 81 }; |
81 | 82 |
82 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { | 83 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { |
83 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { | 84 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { |
84 return gMap[i].fProc; | 85 return gMap[i].fProc; |
85 } | 86 } |
86 } | 87 } |
87 sk_throw(); | 88 sk_throw(); |
88 return nullptr; | 89 return nullptr; |
89 } | 90 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 }; | 174 }; |
174 | 175 |
175 bool SkPNGImageEncoder::onEncode(SkWStream* stream, | 176 bool SkPNGImageEncoder::onEncode(SkWStream* stream, |
176 const SkBitmap& originalBitmap, | 177 const SkBitmap& originalBitmap, |
177 int /*quality*/) { | 178 int /*quality*/) { |
178 SkBitmap copy; | 179 SkBitmap copy; |
179 const SkBitmap* bitmap = &originalBitmap; | 180 const SkBitmap* bitmap = &originalBitmap; |
180 switch (originalBitmap.colorType()) { | 181 switch (originalBitmap.colorType()) { |
181 case kIndex_8_SkColorType: | 182 case kIndex_8_SkColorType: |
182 case kGray_8_SkColorType: | 183 case kGray_8_SkColorType: |
| 184 case kAlpha_8_SkColorType: |
183 case kN32_SkColorType: | 185 case kN32_SkColorType: |
184 case kARGB_4444_SkColorType: | 186 case kARGB_4444_SkColorType: |
185 case kRGB_565_SkColorType: | 187 case kRGB_565_SkColorType: |
186 break; | 188 break; |
187 default: | 189 default: |
188 // TODO(scroggo): support 8888-but-not-N32 natively. | 190 // TODO(scroggo): support 8888-but-not-N32 natively. |
189 // TODO(scroggo): support Alpha_8 as Grayscale(black)+Alpha | |
190 if (originalBitmap.copyTo(©, kN32_SkColorType)) { | 191 if (originalBitmap.copyTo(©, kN32_SkColorType)) { |
191 bitmap = © | 192 bitmap = © |
192 } | 193 } |
193 } | 194 } |
194 SkColorType ct = bitmap->colorType(); | 195 SkColorType ct = bitmap->colorType(); |
195 | 196 |
196 const bool hasAlpha = !bitmap->isOpaque(); | 197 const bool hasAlpha = !bitmap->isOpaque(); |
197 int bitDepth = 8; // default for color | 198 int bitDepth = 8; // default for color |
198 png_color_8 sig_bit; | 199 png_color_8 sig_bit; |
199 sk_bzero(&sig_bit, sizeof(png_color_8)); | 200 sk_bzero(&sig_bit, sizeof(png_color_8)); |
200 | 201 |
201 int colorType; | 202 int colorType; |
202 switch (ct) { | 203 switch (ct) { |
203 case kIndex_8_SkColorType: | 204 case kIndex_8_SkColorType: |
204 sig_bit.red = 8; | 205 sig_bit.red = 8; |
205 sig_bit.green = 8; | 206 sig_bit.green = 8; |
206 sig_bit.blue = 8; | 207 sig_bit.blue = 8; |
207 sig_bit.alpha = 8; | 208 sig_bit.alpha = 8; |
208 colorType = PNG_COLOR_TYPE_PALETTE; | 209 colorType = PNG_COLOR_TYPE_PALETTE; |
209 break; | 210 break; |
210 case kGray_8_SkColorType: | 211 case kGray_8_SkColorType: |
211 sig_bit.gray = 8; | 212 sig_bit.gray = 8; |
212 colorType = PNG_COLOR_TYPE_GRAY; | 213 colorType = PNG_COLOR_TYPE_GRAY; |
213 SkASSERT(!hasAlpha); | 214 SkASSERT(!hasAlpha); |
214 break; | 215 break; |
| 216 case kAlpha_8_SkColorType: |
| 217 // This is a bit of a trick. PNG does not have an alpha-only format
, so |
| 218 // we tell libpng that we are encoding a gray image. We'll also enc
ode |
| 219 // an extra custom chunk, so our decoder knows that the image is act
ually |
| 220 // Alpha8. |
| 221 sig_bit.gray = 8; |
| 222 colorType = PNG_COLOR_TYPE_GRAY; |
| 223 SkASSERT(hasAlpha); |
| 224 break; |
215 case kN32_SkColorType: | 225 case kN32_SkColorType: |
216 sig_bit.red = 8; | 226 sig_bit.red = 8; |
217 sig_bit.green = 8; | 227 sig_bit.green = 8; |
218 sig_bit.blue = 8; | 228 sig_bit.blue = 8; |
219 sig_bit.alpha = 8; | 229 sig_bit.alpha = 8; |
220 colorType = hasAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB
; | 230 colorType = hasAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB
; |
221 break; | 231 break; |
222 case kARGB_4444_SkColorType: | 232 case kARGB_4444_SkColorType: |
223 sig_bit.red = 4; | 233 sig_bit.red = 4; |
224 sig_bit.green = 4; | 234 sig_bit.green = 4; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 if (kIndex_8_SkColorType == ct) { | 316 if (kIndex_8_SkColorType == ct) { |
307 SkColorTable* ct = bitmap.getColorTable(); | 317 SkColorTable* ct = bitmap.getColorTable(); |
308 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); | 318 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); |
309 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 319 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
310 if (numTrans > 0) { | 320 if (numTrans > 0) { |
311 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); | 321 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); |
312 } | 322 } |
313 } | 323 } |
314 | 324 |
315 png_set_sBIT(png_ptr, info_ptr, &sig_bit); | 325 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
| 326 |
| 327 if (kAlpha_8_SkColorType == ct) { |
| 328 static constexpr char key[] = "SkColorType"; |
| 329 static constexpr char value[] = "Alpha8"; |
| 330 |
| 331 png_text text; |
| 332 text.compression = 0; // Use deflate for text compression. |
| 333 text.key = const_cast<char*>(key); |
| 334 text.text = const_cast<char*>(value); |
| 335 text.text_length = sizeof(value) - 1; |
| 336 text.itxt_length = 0; |
| 337 text.lang = nullptr; |
| 338 text.lang_key = nullptr; |
| 339 png_set_text(png_ptr, info_ptr, &text, 1); |
| 340 } |
| 341 |
316 png_write_info(png_ptr, info_ptr); | 342 png_write_info(png_ptr, info_ptr); |
317 | 343 |
318 const char* srcImage = (const char*)bitmap.getPixels(); | 344 const char* srcImage = (const char*)bitmap.getPixels(); |
319 SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2); | 345 SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2); |
320 char* storage = rowStorage.get(); | 346 char* storage = rowStorage.get(); |
321 transform_scanline_proc proc = choose_proc(ct, hasAlpha); | 347 transform_scanline_proc proc = choose_proc(ct, hasAlpha); |
322 | 348 |
323 for (int y = 0; y < bitmap.height(); y++) { | 349 for (int y = 0; y < bitmap.height(); y++) { |
324 png_bytep row_ptr = (png_bytep)storage; | 350 png_bytep row_ptr = (png_bytep)storage; |
325 proc(srcImage, bitmap.width(), storage); | 351 proc(srcImage, bitmap.width(), storage); |
(...skipping 10 matching lines...) Expand all Loading... |
336 | 362 |
337 /////////////////////////////////////////////////////////////////////////////// | 363 /////////////////////////////////////////////////////////////////////////////// |
338 DEFINE_ENCODER_CREATOR(PNGImageEncoder); | 364 DEFINE_ENCODER_CREATOR(PNGImageEncoder); |
339 /////////////////////////////////////////////////////////////////////////////// | 365 /////////////////////////////////////////////////////////////////////////////// |
340 | 366 |
341 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 367 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
342 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; | 368 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; |
343 } | 369 } |
344 | 370 |
345 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 371 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
OLD | NEW |