Chromium Code Reviews| 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); |
|
scroggo
2013/05/01 16:09:53
Recently Derek upstreamed changes from Android tha
fmalita_google_do_not_use
2013/05/01 16:20:44
Right, it's a deprecated alias (marked as such in
| |
| 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 // FIXME: Direct access to png_ptr fields is deprecated in libpng > 1.2 | |
| 730 // and no wrapper method is provided for resetting the interlace pass. | |
|
scroggo
2013/05/01 16:09:53
Would it be possible to check the PNG version here
fmalita_google_do_not_use
2013/05/01 16:20:44
Sure, but then I wonder what (if anything) will br
scroggo
2013/05/01 17:35:03
Good question. I'm guessing this is for consecutiv
| |
| 712 png_ptr->pass = 0; | 731 png_ptr->pass = 0; |
| 713 png_read_update_info(png_ptr, info_ptr); | 732 png_read_update_info(png_ptr, info_ptr); |
| 714 | 733 |
| 715 int actualTop = rect.fTop; | 734 int actualTop = rect.fTop; |
| 716 | 735 |
| 717 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { | 736 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { |
| 718 for (int i = 0; i < number_passes; i++) { | 737 for (int i = 0; i < number_passes; i++) { |
| 719 png_configure_decoder(png_ptr, &actualTop, i); | 738 png_configure_decoder(png_ptr, &actualTop, i); |
| 720 for (int j = 0; j < rect.fTop - actualTop; j++) { | 739 for (int j = 0; j < rect.fTop - actualTop; j++) { |
| 721 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); | 740 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 return true; | 829 return true; |
| 811 } | 830 } |
| 812 #endif | 831 #endif |
| 813 | 832 |
| 814 /////////////////////////////////////////////////////////////////////////////// | 833 /////////////////////////////////////////////////////////////////////////////// |
| 815 | 834 |
| 816 #include "SkColorPriv.h" | 835 #include "SkColorPriv.h" |
| 817 #include "SkUnPreMultiply.h" | 836 #include "SkUnPreMultiply.h" |
| 818 | 837 |
| 819 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { | 838 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; | 839 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); |
| 821 if (!sk_stream->write(data, len)) { | 840 if (!sk_stream->write(data, len)) { |
| 822 png_error(png_ptr, "sk_write_fn Error!"); | 841 png_error(png_ptr, "sk_write_fn Error!"); |
| 823 } | 842 } |
| 824 } | 843 } |
| 825 | 844 |
| 826 static transform_scanline_proc choose_proc(SkBitmap::Config config, | 845 static transform_scanline_proc choose_proc(SkBitmap::Config config, |
| 827 bool hasAlpha) { | 846 bool hasAlpha) { |
| 828 // we don't care about search on alpha if we're kIndex8, since only the | 847 // 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 | 848 // colortable packing cares about that distinction, not the pixels |
| 830 if (SkBitmap::kIndex8_Config == config) { | 849 if (SkBitmap::kIndex8_Config == config) { |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1110 return SkImageDecoder::kUnknown_Format; | 1129 return SkImageDecoder::kUnknown_Format; |
| 1111 } | 1130 } |
| 1112 | 1131 |
| 1113 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1132 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
| 1114 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1133 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
| 1115 } | 1134 } |
| 1116 | 1135 |
| 1117 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto ry); | 1136 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto ry); |
| 1118 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png) ; | 1137 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png) ; |
| 1119 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); | 1138 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); |
| OLD | NEW |