| 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 |