OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkImageDecoder.h" | 10 #include "SkImageDecoder.h" |
11 #include "SkImageEncoder.h" | 11 #include "SkImageEncoder.h" |
12 #include "SkColor.h" | 12 #include "SkColor.h" |
13 #include "SkColorPriv.h" | 13 #include "SkColorPriv.h" |
14 #include "SkDither.h" | 14 #include "SkDither.h" |
15 #include "SkMath.h" | 15 #include "SkMath.h" |
16 #include "SkScaledBitmapSampler.h" | 16 #include "SkScaledBitmapSampler.h" |
17 #include "SkStream.h" | 17 #include "SkStream.h" |
18 #include "SkTemplates.h" | 18 #include "SkTemplates.h" |
19 #include "SkUtils.h" | 19 #include "SkUtils.h" |
20 #include "transform_scanline.h" | 20 #include "transform_scanline.h" |
21 | 21 |
| 22 #if defined(SK_DEBUG) |
| 23 #include "SkRTConf.h" // SK_CONF_DECLARE |
| 24 #endif // defined(SK_DEBUG) |
| 25 |
22 extern "C" { | 26 extern "C" { |
23 #include "png.h" | 27 #include "png.h" |
24 } | 28 } |
25 | 29 |
26 /* These were dropped in libpng >= 1.4 */ | 30 /* These were dropped in libpng >= 1.4 */ |
27 #ifndef png_infopp_NULL | 31 #ifndef png_infopp_NULL |
28 #define png_infopp_NULL NULL | 32 #define png_infopp_NULL NULL |
29 #endif | 33 #endif |
30 | 34 |
31 #ifndef png_bytepp_NULL | 35 #ifndef png_bytepp_NULL |
32 #define png_bytepp_NULL NULL | 36 #define png_bytepp_NULL NULL |
33 #endif | 37 #endif |
34 | 38 |
35 #ifndef int_p_NULL | 39 #ifndef int_p_NULL |
36 #define int_p_NULL NULL | 40 #define int_p_NULL NULL |
37 #endif | 41 #endif |
38 | 42 |
39 #ifndef png_flush_ptr_NULL | 43 #ifndef png_flush_ptr_NULL |
40 #define png_flush_ptr_NULL NULL | 44 #define png_flush_ptr_NULL NULL |
41 #endif | 45 #endif |
42 | 46 |
| 47 #if defined(SK_DEBUG) |
| 48 SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings, |
| 49 "images.png.suppressDecoderWarnings", false, |
| 50 "Suppress most PNG warnings when calling image decode functions."); |
| 51 #endif // defined(SK_DEBUG) |
| 52 |
| 53 |
43 class SkPNGImageIndex { | 54 class SkPNGImageIndex { |
44 public: | 55 public: |
45 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i
nfo_ptr) | 56 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i
nfo_ptr) |
46 : fStream(stream) | 57 : fStream(stream) |
47 , fPng_ptr(png_ptr) | 58 , fPng_ptr(png_ptr) |
48 , fInfo_ptr(info_ptr) | 59 , fInfo_ptr(info_ptr) |
49 , fConfig(SkBitmap::kNo_Config) { | 60 , fConfig(SkBitmap::kNo_Config) { |
50 SkASSERT(stream != NULL); | 61 SkASSERT(stream != NULL); |
51 stream->ref(); | 62 stream->ref(); |
52 } | 63 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 png_bytep trans; | 203 png_bytep trans; |
193 int num_trans; | 204 int num_trans; |
194 | 205 |
195 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { | 206 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
196 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); | 207 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); |
197 return num_trans > 0; | 208 return num_trans > 0; |
198 } | 209 } |
199 return false; | 210 return false; |
200 } | 211 } |
201 | 212 |
| 213 void do_nothing_warning_fn(png_structp, png_const_charp) { |
| 214 /* do nothing */ |
| 215 } |
| 216 |
202 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp, | 217 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp, |
203 png_infop *info_ptrp) { | 218 png_infop *info_ptrp) { |
204 /* Create and initialize the png_struct with the desired error handler | 219 /* Create and initialize the png_struct with the desired error handler |
205 * functions. If you want to use the default stderr and longjump method, | 220 * functions. If you want to use the default stderr and longjump method, |
206 * you can supply NULL for the last three parameters. We also supply the | 221 * you can supply NULL for the last three parameters. We also supply the |
207 * the compiler header file version, so that we know if the application | 222 * the compiler header file version, so that we know if the application |
208 * was compiled with a compatible version of the library. */ | 223 * was compiled with a compatible version of the library. */ |
| 224 |
| 225 #if defined(SK_DEBUG) |
| 226 png_error_ptr user_warning_fn = |
| 227 (c_suppressPNGImageDecoderWarnings) ? (&do_nothing_warning_fn) : NULL; |
| 228 /* NULL means to leave as default library behavior. */ |
| 229 /* c_suppressPNGImageDecoderWarnings defaults to false. */ |
| 230 /* To suppress warnings with a SK_DEBUG binary, set the |
| 231 * environment variable "skia_images_png_suppressDecoderWarnings" |
| 232 * to "true". Inside a program that links to skia: |
| 233 * SK_CONF_SET("images.png.suppressDecoderWarnings", true); */ |
| 234 #else // Always suppress in release mode |
| 235 png_error_ptr user_warning_fn = &do_nothing_warning_fn; |
| 236 #endif // defined(SK_DEBUG) |
| 237 |
209 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, | 238 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, |
210 NULL, sk_error_fn, NULL); | 239 NULL, sk_error_fn, user_warning_fn); |
211 // png_voidp user_error_ptr, user_error_fn, user_warning_fn); | 240 // png_voidp user_error_ptr, user_error_fn, user_warning_fn); |
212 if (png_ptr == NULL) { | 241 if (png_ptr == NULL) { |
213 return false; | 242 return false; |
214 } | 243 } |
| 244 |
215 *png_ptrp = png_ptr; | 245 *png_ptrp = png_ptr; |
216 | 246 |
217 /* Allocate/initialize the memory for image information. */ | 247 /* Allocate/initialize the memory for image information. */ |
218 png_infop info_ptr = png_create_info_struct(png_ptr); | 248 png_infop info_ptr = png_create_info_struct(png_ptr); |
219 if (info_ptr == NULL) { | 249 if (info_ptr == NULL) { |
220 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); | 250 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); |
221 return false; | 251 return false; |
222 } | 252 } |
223 *info_ptrp = info_ptr; | 253 *info_ptrp = info_ptr; |
224 | 254 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 which means we will find more matches than we should. The real | 521 which means we will find more matches than we should. The real |
492 fix seems to be to see the actual 16bit components, do the | 522 fix seems to be to see the actual 16bit components, do the |
493 compare, and then knock it down to 8bits ourselves. | 523 compare, and then knock it down to 8bits ourselves. |
494 */ | 524 */ |
495 if (colorType & PNG_COLOR_MASK_COLOR) { | 525 if (colorType & PNG_COLOR_MASK_COLOR) { |
496 if (16 == bitDepth) { | 526 if (16 == bitDepth) { |
497 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, | 527 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, |
498 transpColor->green >> 8, | 528 transpColor->green >> 8, |
499 transpColor->blue >> 8); | 529 transpColor->blue >> 8); |
500 } else { | 530 } else { |
501 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red, | 531 /* We apply the mask because in a very small |
502 transpColor->green, | 532 number of corrupt PNGs, (transpColor->red > 255) |
503 transpColor->blue); | 533 and (bitDepth == 8), for certain versions of libpng. */ |
| 534 *theTranspColorp = SkPackARGB32(0xFF, |
| 535 0xFF & (transpColor->red), |
| 536 0xFF & (transpColor->green), |
| 537 0xFF & (transpColor->blue)); |
504 } | 538 } |
505 } else { // gray | 539 } else { // gray |
506 if (16 == bitDepth) { | 540 if (16 == bitDepth) { |
507 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8
, | 541 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8
, |
508 transpColor->gray >> 8, | 542 transpColor->gray >> 8, |
509 transpColor->gray >> 8); | 543 transpColor->gray >> 8); |
510 } else { | 544 } else { |
511 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray, | 545 /* We apply the mask because in a very small |
512 transpColor->gray, | 546 number of corrupt PNGs, (transpColor->red > |
513 transpColor->gray); | 547 255) and (bitDepth == 8), for certain versions |
| 548 of libpng. For safety we assume the same could |
| 549 happen with a grayscale PNG. */ |
| 550 *theTranspColorp = SkPackARGB32(0xFF, |
| 551 0xFF & (transpColor->gray), |
| 552 0xFF & (transpColor->gray), |
| 553 0xFF & (transpColor->gray)); |
514 } | 554 } |
515 } | 555 } |
516 } | 556 } |
517 | 557 |
518 if (valid || | 558 if (valid || |
519 PNG_COLOR_TYPE_RGB_ALPHA == colorType || | 559 PNG_COLOR_TYPE_RGB_ALPHA == colorType || |
520 PNG_COLOR_TYPE_GRAY_ALPHA == colorType) { | 560 PNG_COLOR_TYPE_GRAY_ALPHA == colorType) { |
521 *hasAlphap = true; | 561 *hasAlphap = true; |
522 } | 562 } |
523 | 563 |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 return SkImageDecoder::kUnknown_Format; | 1242 return SkImageDecoder::kUnknown_Format; |
1203 } | 1243 } |
1204 | 1244 |
1205 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1245 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
1206 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1246 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
1207 } | 1247 } |
1208 | 1248 |
1209 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); | 1249 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); |
1210 static SkImageDecoder_FormatReg gFormatReg(get_format_png); | 1250 static SkImageDecoder_FormatReg gFormatReg(get_format_png); |
1211 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 1251 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
OLD | NEW |