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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 SkColorType fColorType; | 69 SkColorType fColorType; |
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 }; | 80 }; |
80 | 81 |
81 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { | 82 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { |
82 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { | 83 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { |
83 return gMap[i].fProc; | 84 return gMap[i].fProc; |
84 } | 85 } |
85 } | 86 } |
86 sk_throw(); | 87 sk_throw(); |
87 return nullptr; | 88 return nullptr; |
88 } | 89 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 typedef SkImageEncoder INHERITED; | 172 typedef SkImageEncoder INHERITED; |
172 }; | 173 }; |
173 | 174 |
174 bool SkPNGImageEncoder::onEncode(SkWStream* stream, | 175 bool SkPNGImageEncoder::onEncode(SkWStream* stream, |
175 const SkBitmap& originalBitmap, | 176 const SkBitmap& originalBitmap, |
176 int /*quality*/) { | 177 int /*quality*/) { |
177 SkBitmap copy; | 178 SkBitmap copy; |
178 const SkBitmap* bitmap = &originalBitmap; | 179 const SkBitmap* bitmap = &originalBitmap; |
179 switch (originalBitmap.colorType()) { | 180 switch (originalBitmap.colorType()) { |
180 case kIndex_8_SkColorType: | 181 case kIndex_8_SkColorType: |
| 182 case kGray_8_SkColorType: |
181 case kN32_SkColorType: | 183 case kN32_SkColorType: |
182 case kARGB_4444_SkColorType: | 184 case kARGB_4444_SkColorType: |
183 case kRGB_565_SkColorType: | 185 case kRGB_565_SkColorType: |
184 break; | 186 break; |
185 default: | 187 default: |
186 // TODO(scroggo): support 8888-but-not-N32 natively. | 188 // TODO(scroggo): support 8888-but-not-N32 natively. |
187 // TODO(scroggo): support kGray_8 directly. | |
188 // TODO(scroggo): support Alpha_8 as Grayscale(black)+Alpha | 189 // TODO(scroggo): support Alpha_8 as Grayscale(black)+Alpha |
189 if (originalBitmap.copyTo(©, kN32_SkColorType)) { | 190 if (originalBitmap.copyTo(©, kN32_SkColorType)) { |
190 bitmap = © | 191 bitmap = © |
191 } | 192 } |
192 } | 193 } |
193 SkColorType ct = bitmap->colorType(); | 194 SkColorType ct = bitmap->colorType(); |
194 | 195 |
195 const bool hasAlpha = !bitmap->isOpaque(); | 196 const bool hasAlpha = !bitmap->isOpaque(); |
196 int colorType = PNG_COLOR_MASK_COLOR; | |
197 int bitDepth = 8; // default for color | 197 int bitDepth = 8; // default for color |
198 png_color_8 sig_bit; | 198 png_color_8 sig_bit; |
| 199 sk_bzero(&sig_bit, sizeof(png_color_8)); |
199 | 200 |
| 201 int colorType; |
200 switch (ct) { | 202 switch (ct) { |
201 case kIndex_8_SkColorType: | 203 case kIndex_8_SkColorType: |
202 colorType |= PNG_COLOR_MASK_PALETTE; | 204 sig_bit.red = 8; |
203 // fall through to the ARGB_8888 case | 205 sig_bit.green = 8; |
| 206 sig_bit.blue = 8; |
| 207 sig_bit.alpha = 8; |
| 208 colorType = PNG_COLOR_TYPE_PALETTE; |
| 209 break; |
| 210 case kGray_8_SkColorType: |
| 211 sig_bit.gray = 8; |
| 212 colorType = PNG_COLOR_TYPE_GRAY; |
| 213 SkASSERT(!hasAlpha); |
| 214 break; |
204 case kN32_SkColorType: | 215 case kN32_SkColorType: |
205 sig_bit.red = 8; | 216 sig_bit.red = 8; |
206 sig_bit.green = 8; | 217 sig_bit.green = 8; |
207 sig_bit.blue = 8; | 218 sig_bit.blue = 8; |
208 sig_bit.alpha = 8; | 219 sig_bit.alpha = 8; |
| 220 colorType = hasAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB
; |
209 break; | 221 break; |
210 case kARGB_4444_SkColorType: | 222 case kARGB_4444_SkColorType: |
211 sig_bit.red = 4; | 223 sig_bit.red = 4; |
212 sig_bit.green = 4; | 224 sig_bit.green = 4; |
213 sig_bit.blue = 4; | 225 sig_bit.blue = 4; |
214 sig_bit.alpha = 4; | 226 sig_bit.alpha = 4; |
| 227 colorType = hasAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB
; |
215 break; | 228 break; |
216 case kRGB_565_SkColorType: | 229 case kRGB_565_SkColorType: |
217 sig_bit.red = 5; | 230 sig_bit.red = 5; |
218 sig_bit.green = 6; | 231 sig_bit.green = 6; |
219 sig_bit.blue = 5; | 232 sig_bit.blue = 5; |
220 sig_bit.alpha = 0; | 233 colorType = PNG_COLOR_TYPE_RGB; |
| 234 SkASSERT(!hasAlpha); |
221 break; | 235 break; |
222 default: | 236 default: |
223 return false; | 237 return false; |
224 } | 238 } |
225 | 239 |
226 if (hasAlpha) { | |
227 // don't specify alpha if we're a palette, even if our ctable has alpha | |
228 if (!(colorType & PNG_COLOR_MASK_PALETTE)) { | |
229 colorType |= PNG_COLOR_MASK_ALPHA; | |
230 } | |
231 } else { | |
232 sig_bit.alpha = 0; | |
233 } | |
234 | |
235 SkAutoLockPixels alp(*bitmap); | 240 SkAutoLockPixels alp(*bitmap); |
236 // readyToDraw checks for pixels (and colortable if that is required) | 241 // readyToDraw checks for pixels (and colortable if that is required) |
237 if (!bitmap->readyToDraw()) { | 242 if (!bitmap->readyToDraw()) { |
238 return false; | 243 return false; |
239 } | 244 } |
240 | 245 |
241 // we must do this after we have locked the pixels | 246 // we must do this after we have locked the pixels |
242 SkColorTable* ctable = bitmap->getColorTable(); | 247 SkColorTable* ctable = bitmap->getColorTable(); |
243 if (ctable) { | 248 if (ctable) { |
244 if (ctable->count() == 0) { | 249 if (ctable->count() == 0) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 png_color paletteColors[256]; | 304 png_color paletteColors[256]; |
300 png_byte trans[256]; | 305 png_byte trans[256]; |
301 if (kIndex_8_SkColorType == ct) { | 306 if (kIndex_8_SkColorType == ct) { |
302 SkColorTable* ct = bitmap.getColorTable(); | 307 SkColorTable* ct = bitmap.getColorTable(); |
303 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); | 308 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); |
304 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 309 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
305 if (numTrans > 0) { | 310 if (numTrans > 0) { |
306 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); | 311 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); |
307 } | 312 } |
308 } | 313 } |
309 #ifdef PNG_sBIT_SUPPORTED | 314 |
310 png_set_sBIT(png_ptr, info_ptr, &sig_bit); | 315 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
311 #endif | |
312 png_write_info(png_ptr, info_ptr); | 316 png_write_info(png_ptr, info_ptr); |
313 | 317 |
314 const char* srcImage = (const char*)bitmap.getPixels(); | 318 const char* srcImage = (const char*)bitmap.getPixels(); |
315 SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2); | 319 SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2); |
316 char* storage = rowStorage.get(); | 320 char* storage = rowStorage.get(); |
317 transform_scanline_proc proc = choose_proc(ct, hasAlpha); | 321 transform_scanline_proc proc = choose_proc(ct, hasAlpha); |
318 | 322 |
319 for (int y = 0; y < bitmap.height(); y++) { | 323 for (int y = 0; y < bitmap.height(); y++) { |
320 png_bytep row_ptr = (png_bytep)storage; | 324 png_bytep row_ptr = (png_bytep)storage; |
321 proc(srcImage, bitmap.width(), storage); | 325 proc(srcImage, bitmap.width(), storage); |
(...skipping 10 matching lines...) Expand all Loading... |
332 | 336 |
333 /////////////////////////////////////////////////////////////////////////////// | 337 /////////////////////////////////////////////////////////////////////////////// |
334 DEFINE_ENCODER_CREATOR(PNGImageEncoder); | 338 DEFINE_ENCODER_CREATOR(PNGImageEncoder); |
335 /////////////////////////////////////////////////////////////////////////////// | 339 /////////////////////////////////////////////////////////////////////////////// |
336 | 340 |
337 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 341 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
338 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; | 342 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; |
339 } | 343 } |
340 | 344 |
341 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 345 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
OLD | NEW |