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 extern "C" { | 22 extern "C" { |
23 #include "png.h" | 23 #include "png.h" |
24 } | 24 } |
25 | 25 |
26 /* These were dropped in libpng >= 1.4 */ | |
27 #ifndef png_infopp_NULL | |
28 #define png_infopp_NULL NULL | |
29 #endif | |
30 | |
31 #ifndef png_bytepp_NULL | |
32 #define png_bytepp_NULL NULL | |
33 #endif | |
34 | |
35 #ifndef int_p_NULL | |
36 #define int_p_NULL NULL | |
37 #endif | |
38 | |
39 #ifndef png_flush_ptr_NULL | |
40 #define png_flush_ptr_NULL NULL | |
41 #endif | |
42 | |
26 class SkPNGImageIndex { | 43 class SkPNGImageIndex { |
27 public: | 44 public: |
28 SkPNGImageIndex(png_structp png_ptr, png_infop info_ptr) { | 45 SkPNGImageIndex(png_structp png_ptr, png_infop info_ptr) { |
29 this->png_ptr = png_ptr; | 46 this->png_ptr = png_ptr; |
30 this->info_ptr = info_ptr; | 47 this->info_ptr = info_ptr; |
31 } | 48 } |
32 ~SkPNGImageIndex() { | 49 ~SkPNGImageIndex() { |
33 if (NULL != png_ptr) { | 50 if (NULL != png_ptr) { |
34 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); | 51 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); |
35 } | 52 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {} | 100 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {} |
84 ~PNGAutoClean() { | 101 ~PNGAutoClean() { |
85 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); | 102 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); |
86 } | 103 } |
87 private: | 104 private: |
88 png_structp png_ptr; | 105 png_structp png_ptr; |
89 png_infop info_ptr; | 106 png_infop info_ptr; |
90 }; | 107 }; |
91 | 108 |
92 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { | 109 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { |
93 SkStream* sk_stream = (SkStream*) png_ptr->io_ptr; | 110 SkStream* sk_stream = (SkStream*) png_get_io_ptr(png_ptr); |
94 size_t bytes = sk_stream->read(data, length); | 111 size_t bytes = sk_stream->read(data, length); |
95 if (bytes != length) { | 112 if (bytes != length) { |
96 png_error(png_ptr, "Read Error!"); | 113 png_error(png_ptr, "Read Error!"); |
97 } | 114 } |
98 } | 115 } |
99 | 116 |
100 #ifdef SK_BUILD_FOR_ANDROID | 117 #ifdef SK_BUILD_FOR_ANDROID |
101 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) { | 118 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) { |
102 SkStream* sk_stream = (SkStream*) png_ptr->io_ptr; | 119 SkStream* sk_stream = (SkStream*) png_get_io_ptr(png_ptr); |
103 sk_stream->rewind(); | 120 sk_stream->rewind(); |
104 (void)sk_stream->skip(offset); | 121 (void)sk_stream->skip(offset); |
105 } | 122 } |
106 #endif | 123 #endif |
107 | 124 |
108 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { | 125 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { |
109 SkImageDecoder::Peeker* peeker = | 126 SkImageDecoder::Peeker* peeker = |
110 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); | 127 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); |
111 // peek() returning true means continue decoding | 128 // peek() returning true means continue decoding |
112 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? | 129 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 if (bitDepth == 16) { | 250 if (bitDepth == 16) { |
234 png_set_strip_16(png_ptr); | 251 png_set_strip_16(png_ptr); |
235 } | 252 } |
236 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single | 253 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single |
237 * byte into separate bytes (useful for paletted and grayscale images). */ | 254 * byte into separate bytes (useful for paletted and grayscale images). */ |
238 if (bitDepth < 8) { | 255 if (bitDepth < 8) { |
239 png_set_packing(png_ptr); | 256 png_set_packing(png_ptr); |
240 } | 257 } |
241 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ | 258 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ |
242 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { | 259 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { |
243 png_set_gray_1_2_4_to_8(png_ptr); | 260 png_set_expand_gray_1_2_4_to_8(png_ptr); |
244 } | 261 } |
245 | 262 |
246 /* Make a grayscale image into RGB. */ | 263 /* Make a grayscale image into RGB. */ |
247 if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALP HA) { | 264 if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALP HA) { |
248 png_set_gray_to_rgb(png_ptr); | 265 png_set_gray_to_rgb(png_ptr); |
249 } | 266 } |
250 return true; | 267 return true; |
251 } | 268 } |
252 | 269 |
253 bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, | 270 bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
430 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, | 447 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, |
431 SkBitmap::Config *configp, bool *hasAlph ap, | 448 SkBitmap::Config *configp, bool *hasAlph ap, |
432 bool *doDitherp, SkPMColor *theTranspCol orp) { | 449 bool *doDitherp, SkPMColor *theTranspCol orp) { |
433 png_uint_32 origWidth, origHeight; | 450 png_uint_32 origWidth, origHeight; |
434 int bitDepth, colorType; | 451 int bitDepth, colorType; |
435 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 452 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
436 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 453 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); |
437 | 454 |
438 // check for sBIT chunk data, in case we should disable dithering because | 455 // check for sBIT chunk data, in case we should disable dithering because |
439 // our data is not truely 8bits per component | 456 // our data is not truely 8bits per component |
440 if (*doDitherp) { | 457 png_color_8p sig_bit; |
458 if (*doDitherp && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { | |
441 #if 0 | 459 #if 0 |
442 SkDebugf("----- sBIT %d %d %d %d\n", info_ptr->sig_bit.red, | 460 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, |
443 info_ptr->sig_bit.green, info_ptr->sig_bit.blue, | 461 sig_bit->blue, sig_bit->alpha); |
444 info_ptr->sig_bit.alpha); | |
445 #endif | 462 #endif |
446 // 0 seems to indicate no information available | 463 // 0 seems to indicate no information available |
447 if (pos_le(info_ptr->sig_bit.red, SK_R16_BITS) && | 464 if (pos_le(sig_bit->red, SK_R16_BITS) && |
448 pos_le(info_ptr->sig_bit.green, SK_G16_BITS) && | 465 pos_le(sig_bit->green, SK_G16_BITS) && |
449 pos_le(info_ptr->sig_bit.blue, SK_B16_BITS)) { | 466 pos_le(sig_bit->blue, SK_B16_BITS)) { |
450 *doDitherp = false; | 467 *doDitherp = false; |
451 } | 468 } |
452 } | 469 } |
453 | 470 |
454 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 471 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
455 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); | 472 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); |
456 *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha); | 473 *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha); |
457 // now see if we can upscale to their requested config | 474 // now see if we can upscale to their requested config |
458 if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) { | 475 if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) { |
459 *configp = SkBitmap::kIndex8_Config; | 476 *configp = SkBitmap::kIndex8_Config; |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
702 * png_read_image(). To see how to handle interlacing passes, | 719 * png_read_image(). To see how to handle interlacing passes, |
703 * see the png_read_row() method below: | 720 * see the png_read_row() method below: |
704 */ | 721 */ |
705 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? | 722 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? |
706 png_set_interlace_handling(png_ptr) : 1; | 723 png_set_interlace_handling(png_ptr) : 1; |
707 | 724 |
708 /* Optional call to gamma correct and add the background to the palette | 725 /* Optional call to gamma correct and add the background to the palette |
709 * and update info structure. REQUIRED if you are expecting libpng to | 726 * and update info structure. REQUIRED if you are expecting libpng to |
710 * update the palette for you (ie you selected such a transform above). | 727 * update the palette for you (ie you selected such a transform above). |
711 */ | 728 */ |
729 | |
730 // Direct access to png_ptr fields is deprecated in libpng > 1.2. | |
731 #if defined(PNG_1_0_X) || defined (PNG_1_2_X) | |
712 png_ptr->pass = 0; | 732 png_ptr->pass = 0; |
scroggo
2013/05/02 15:06:37
There is a function call png_set_interlaced_pass,
| |
733 #else | |
734 // FIXME: Figure out what (if anything) to do when Android moves to | |
735 // libpng > 1.2. | |
736 #endif | |
713 png_read_update_info(png_ptr, info_ptr); | 737 png_read_update_info(png_ptr, info_ptr); |
714 | 738 |
715 int actualTop = rect.fTop; | 739 int actualTop = rect.fTop; |
716 | 740 |
717 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { | 741 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { |
718 for (int i = 0; i < number_passes; i++) { | 742 for (int i = 0; i < number_passes; i++) { |
719 png_configure_decoder(png_ptr, &actualTop, i); | 743 png_configure_decoder(png_ptr, &actualTop, i); |
720 for (int j = 0; j < rect.fTop - actualTop; j++) { | 744 for (int j = 0; j < rect.fTop - actualTop; j++) { |
721 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); | 745 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); |
722 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | 746 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
810 return true; | 834 return true; |
811 } | 835 } |
812 #endif | 836 #endif |
813 | 837 |
814 /////////////////////////////////////////////////////////////////////////////// | 838 /////////////////////////////////////////////////////////////////////////////// |
815 | 839 |
816 #include "SkColorPriv.h" | 840 #include "SkColorPriv.h" |
817 #include "SkUnPreMultiply.h" | 841 #include "SkUnPreMultiply.h" |
818 | 842 |
819 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { | 843 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { |
820 SkWStream* sk_stream = (SkWStream*)png_ptr->io_ptr; | 844 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); |
821 if (!sk_stream->write(data, len)) { | 845 if (!sk_stream->write(data, len)) { |
822 png_error(png_ptr, "sk_write_fn Error!"); | 846 png_error(png_ptr, "sk_write_fn Error!"); |
823 } | 847 } |
824 } | 848 } |
825 | 849 |
826 static transform_scanline_proc choose_proc(SkBitmap::Config config, | 850 static transform_scanline_proc choose_proc(SkBitmap::Config config, |
827 bool hasAlpha) { | 851 bool hasAlpha) { |
828 // we don't care about search on alpha if we're kIndex8, since only the | 852 // we don't care about search on alpha if we're kIndex8, since only the |
829 // colortable packing cares about that distinction, not the pixels | 853 // colortable packing cares about that distinction, not the pixels |
830 if (SkBitmap::kIndex8_Config == config) { | 854 if (SkBitmap::kIndex8_Config == config) { |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1110 return SkImageDecoder::kUnknown_Format; | 1134 return SkImageDecoder::kUnknown_Format; |
1111 } | 1135 } |
1112 | 1136 |
1113 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1137 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
1114 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1138 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
1115 } | 1139 } |
1116 | 1140 |
1117 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto ry); | 1141 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto ry); |
1118 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png) ; | 1142 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png) ; |
1119 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); | 1143 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); |
OLD | NEW |