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. */ | |
scroggo
2013/10/02 17:05:04
Nit: Shouldn't this go above the code it applies t
| |
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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 which means we will find more matches than we should. The real | 518 which means we will find more matches than we should. The real |
489 fix seems to be to see the actual 16bit components, do the | 519 fix seems to be to see the actual 16bit components, do the |
490 compare, and then knock it down to 8bits ourselves. | 520 compare, and then knock it down to 8bits ourselves. |
491 */ | 521 */ |
492 if (colorType & PNG_COLOR_MASK_COLOR) { | 522 if (colorType & PNG_COLOR_MASK_COLOR) { |
493 if (16 == bitDepth) { | 523 if (16 == bitDepth) { |
494 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, | 524 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, |
495 transpColor->green >> 8, | 525 transpColor->green >> 8, |
496 transpColor->blue >> 8); | 526 transpColor->blue >> 8); |
497 } else { | 527 } else { |
498 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red, | 528 /* We apply the mask because in a very small |
499 transpColor->green, | 529 number of corrupt PNGs, (transpColor->red > 255) |
500 transpColor->blue); | 530 and (bitDepth == 8), for certain versions of libpng. */ |
531 *theTranspColorp = SkPackARGB32(0xFF, | |
532 0xFF & (transpColor->red), | |
533 0xFF & (transpColor->green), | |
534 0xFF & (transpColor->blue)); | |
501 } | 535 } |
502 } else { // gray | 536 } else { // gray |
503 if (16 == bitDepth) { | 537 if (16 == bitDepth) { |
504 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8 , | 538 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8 , |
505 transpColor->gray >> 8, | 539 transpColor->gray >> 8, |
506 transpColor->gray >> 8); | 540 transpColor->gray >> 8); |
507 } else { | 541 } else { |
508 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray, | 542 /* We apply the mask because in a very small |
509 transpColor->gray, | 543 number of corrupt PNGs, (transpColor->red > |
510 transpColor->gray); | 544 255) and (bitDepth == 8), for certain versions |
545 of libpng. For safety we assume the same could | |
546 happen with a grayscale PNG. */ | |
547 *theTranspColorp = SkPackARGB32(0xFF, | |
548 0xFF & (transpColor->gray), | |
549 0xFF & (transpColor->gray), | |
550 0xFF & (transpColor->gray)); | |
511 } | 551 } |
512 } | 552 } |
513 } | 553 } |
514 | 554 |
515 if (valid || | 555 if (valid || |
516 PNG_COLOR_TYPE_RGB_ALPHA == colorType || | 556 PNG_COLOR_TYPE_RGB_ALPHA == colorType || |
517 PNG_COLOR_TYPE_GRAY_ALPHA == colorType) { | 557 PNG_COLOR_TYPE_GRAY_ALPHA == colorType) { |
518 *hasAlphap = true; | 558 *hasAlphap = true; |
519 } | 559 } |
520 | 560 |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1196 return SkImageDecoder::kUnknown_Format; | 1236 return SkImageDecoder::kUnknown_Format; |
1197 } | 1237 } |
1198 | 1238 |
1199 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1239 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
1200 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1240 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
1201 } | 1241 } |
1202 | 1242 |
1203 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); | 1243 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); |
1204 static SkImageDecoder_FormatReg gFormatReg(get_format_png); | 1244 static SkImageDecoder_FormatReg gFormatReg(get_format_png); |
1205 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 1245 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
OLD | NEW |