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 |