| 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 "SkImageDecoder.h" | 8 #include "SkImageDecoder.h" |
| 9 #include "SkImageEncoder.h" | 9 #include "SkImageEncoder.h" |
| 10 #include "SkColor.h" | 10 #include "SkColor.h" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 #ifdef SK_BUILD_FOR_ANDROID | 134 #ifdef SK_BUILD_FOR_ANDROID |
| 135 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) { | 135 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) { |
| 136 SkStreamRewindable* sk_stream = (SkStreamRewindable*) png_get_io_ptr(png_ptr
); | 136 SkStreamRewindable* sk_stream = (SkStreamRewindable*) png_get_io_ptr(png_ptr
); |
| 137 if (!sk_stream->rewind()) { | 137 if (!sk_stream->rewind()) { |
| 138 png_error(png_ptr, "Failed to rewind stream!"); | 138 png_error(png_ptr, "Failed to rewind stream!"); |
| 139 } | 139 } |
| 140 (void)sk_stream->skip(offset); | 140 (void)sk_stream->skip(offset); |
| 141 } | 141 } |
| 142 #endif | 142 #endif |
| 143 | 143 |
| 144 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED |
| 144 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { | 145 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { |
| 145 SkImageDecoder::Peeker* peeker = | 146 SkImageDecoder::Peeker* peeker = |
| 146 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); | 147 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); |
| 147 // peek() returning true means continue decoding | 148 // peek() returning true means continue decoding |
| 148 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? | 149 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? |
| 149 1 : -1; | 150 1 : -1; |
| 150 } | 151 } |
| 152 #endif |
| 151 | 153 |
| 152 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { | 154 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { |
| 153 SkDEBUGF(("------ png error %s\n", msg)); | 155 SkDEBUGF(("------ png error %s\n", msg)); |
| 154 longjmp(png_jmpbuf(png_ptr), 1); | 156 longjmp(png_jmpbuf(png_ptr), 1); |
| 155 } | 157 } |
| 156 | 158 |
| 157 static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) { | 159 static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) { |
| 158 for (int i = 0; i < count; i++) { | 160 for (int i = 0; i < count; i++) { |
| 159 uint8_t* tmp = storage; | 161 uint8_t* tmp = storage; |
| 160 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); | 162 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 * png_init_io() here you would call: | 261 * png_init_io() here you would call: |
| 260 */ | 262 */ |
| 261 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn); | 263 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn); |
| 262 #ifdef SK_BUILD_FOR_ANDROID | 264 #ifdef SK_BUILD_FOR_ANDROID |
| 263 png_set_seek_fn(png_ptr, sk_seek_fn); | 265 png_set_seek_fn(png_ptr, sk_seek_fn); |
| 264 #endif | 266 #endif |
| 265 /* where user_io_ptr is a structure you want available to the callbacks */ | 267 /* where user_io_ptr is a structure you want available to the callbacks */ |
| 266 /* If we have already read some of the signature */ | 268 /* If we have already read some of the signature */ |
| 267 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ ); | 269 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ ); |
| 268 | 270 |
| 271 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED |
| 269 // hookup our peeker so we can see any user-chunks the caller may be interes
ted in | 272 // hookup our peeker so we can see any user-chunks the caller may be interes
ted in |
| 270 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"",
0); | 273 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"",
0); |
| 271 if (this->getPeeker()) { | 274 if (this->getPeeker()) { |
| 272 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_rea
d_user_chunk); | 275 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_rea
d_user_chunk); |
| 273 } | 276 } |
| 274 | 277 #endif |
| 275 /* The call to png_read_info() gives us all of the information from the | 278 /* The call to png_read_info() gives us all of the information from the |
| 276 * PNG file before the first IDAT (image data chunk). */ | 279 * PNG file before the first IDAT (image data chunk). */ |
| 277 png_read_info(png_ptr, info_ptr); | 280 png_read_info(png_ptr, info_ptr); |
| 278 png_uint_32 origWidth, origHeight; | 281 png_uint_32 origWidth, origHeight; |
| 279 int bitDepth, colorType; | 282 int bitDepth, colorType; |
| 280 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 283 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
| 281 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 284 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); |
| 282 | 285 |
| 283 /* tell libpng to strip 16 bit/color files down to 8 bits/color */ | 286 /* tell libpng to strip 16 bit/color files down to 8 bits/color */ |
| 284 if (bitDepth == 16) { | 287 if (bitDepth == 16) { |
| 285 png_set_strip_16(png_ptr); | 288 png_set_strip_16(png_ptr); |
| 286 } | 289 } |
| 290 #ifdef PNG_READ_PACK_SUPPORTED |
| 287 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single | 291 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single |
| 288 * byte into separate bytes (useful for paletted and grayscale images). */ | 292 * byte into separate bytes (useful for paletted and grayscale images). */ |
| 289 if (bitDepth < 8) { | 293 if (bitDepth < 8) { |
| 290 png_set_packing(png_ptr); | 294 png_set_packing(png_ptr); |
| 291 } | 295 } |
| 296 #endif |
| 292 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ | 297 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ |
| 293 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { | 298 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { |
| 294 png_set_expand_gray_1_2_4_to_8(png_ptr); | 299 png_set_expand_gray_1_2_4_to_8(png_ptr); |
| 295 } | 300 } |
| 296 | 301 |
| 297 return true; | 302 return true; |
| 298 } | 303 } |
| 299 | 304 |
| 300 bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, | 305 bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, |
| 301 Mode mode) { | 306 Mode mode) { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 | 492 |
| 488 bool SkPNGImageDecoder::getBitmapColorType(png_structp png_ptr, png_infop info_p
tr, | 493 bool SkPNGImageDecoder::getBitmapColorType(png_structp png_ptr, png_infop info_p
tr, |
| 489 SkColorType* colorTypep, | 494 SkColorType* colorTypep, |
| 490 bool* hasAlphap, | 495 bool* hasAlphap, |
| 491 SkPMColor* SK_RESTRICT theTranspColor
p) { | 496 SkPMColor* SK_RESTRICT theTranspColor
p) { |
| 492 png_uint_32 origWidth, origHeight; | 497 png_uint_32 origWidth, origHeight; |
| 493 int bitDepth, colorType; | 498 int bitDepth, colorType; |
| 494 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 499 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
| 495 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 500 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); |
| 496 | 501 |
| 502 #ifdef PNG_sBIT_SUPPORTED |
| 497 // check for sBIT chunk data, in case we should disable dithering because | 503 // check for sBIT chunk data, in case we should disable dithering because |
| 498 // our data is not truely 8bits per component | 504 // our data is not truely 8bits per component |
| 499 png_color_8p sig_bit; | 505 png_color_8p sig_bit; |
| 500 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { | 506 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { |
| 501 #if 0 | 507 #if 0 |
| 502 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, | 508 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, |
| 503 sig_bit->blue, sig_bit->alpha); | 509 sig_bit->blue, sig_bit->alpha); |
| 504 #endif | 510 #endif |
| 505 // 0 seems to indicate no information available | 511 // 0 seems to indicate no information available |
| 506 if (pos_le(sig_bit->red, SK_R16_BITS) && | 512 if (pos_le(sig_bit->red, SK_R16_BITS) && |
| 507 pos_le(sig_bit->green, SK_G16_BITS) && | 513 pos_le(sig_bit->green, SK_G16_BITS) && |
| 508 pos_le(sig_bit->blue, SK_B16_BITS)) { | 514 pos_le(sig_bit->blue, SK_B16_BITS)) { |
| 509 this->setDitherImage(false); | 515 this->setDitherImage(false); |
| 510 } | 516 } |
| 511 } | 517 } |
| 518 #endif |
| 512 | 519 |
| 513 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 520 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
| 514 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); | 521 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); |
| 515 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); | 522 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); |
| 516 // now see if we can upscale to their requested colortype | 523 // now see if we can upscale to their requested colortype |
| 517 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { | 524 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { |
| 518 *colorTypep = kIndex_8_SkColorType; | 525 *colorTypep = kIndex_8_SkColorType; |
| 519 } | 526 } |
| 520 } else { | 527 } else { |
| 521 png_color_16p transpColor = NULL; | 528 png_color_16p transpColor = NULL; |
| (...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1210 png_color paletteColors[256]; | 1217 png_color paletteColors[256]; |
| 1211 png_byte trans[256]; | 1218 png_byte trans[256]; |
| 1212 if (kIndex_8_SkColorType == ct) { | 1219 if (kIndex_8_SkColorType == ct) { |
| 1213 SkColorTable* ct = bitmap.getColorTable(); | 1220 SkColorTable* ct = bitmap.getColorTable(); |
| 1214 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); | 1221 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); |
| 1215 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 1222 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
| 1216 if (numTrans > 0) { | 1223 if (numTrans > 0) { |
| 1217 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL); | 1224 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL); |
| 1218 } | 1225 } |
| 1219 } | 1226 } |
| 1220 | 1227 #ifdef PNG_sBIT_SUPPORTED |
| 1221 png_set_sBIT(png_ptr, info_ptr, &sig_bit); | 1228 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
| 1229 #endif |
| 1222 png_write_info(png_ptr, info_ptr); | 1230 png_write_info(png_ptr, info_ptr); |
| 1223 | 1231 |
| 1224 const char* srcImage = (const char*)bitmap.getPixels(); | 1232 const char* srcImage = (const char*)bitmap.getPixels(); |
| 1225 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); | 1233 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); |
| 1226 char* storage = (char*)rowStorage.get(); | 1234 char* storage = (char*)rowStorage.get(); |
| 1227 transform_scanline_proc proc = choose_proc(ct, hasAlpha); | 1235 transform_scanline_proc proc = choose_proc(ct, hasAlpha); |
| 1228 | 1236 |
| 1229 for (int y = 0; y < bitmap.height(); y++) { | 1237 for (int y = 0; y < bitmap.height(); y++) { |
| 1230 png_bytep row_ptr = (png_bytep)storage; | 1238 png_bytep row_ptr = (png_bytep)storage; |
| 1231 proc(srcImage, bitmap.width(), storage); | 1239 proc(srcImage, bitmap.width(), storage); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 return SkImageDecoder::kUnknown_Format; | 1276 return SkImageDecoder::kUnknown_Format; |
| 1269 } | 1277 } |
| 1270 | 1278 |
| 1271 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1279 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
| 1272 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1280 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
| 1273 } | 1281 } |
| 1274 | 1282 |
| 1275 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); | 1283 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); |
| 1276 static SkImageDecoder_FormatReg gFormatReg(get_format_png); | 1284 static SkImageDecoder_FormatReg gFormatReg(get_format_png); |
| 1277 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 1285 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
| OLD | NEW |