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