Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: src/images/SkImageDecoder_libpng.cpp

Issue 14645018: Support for libpng > 1.2. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Avoid touching png_ptr->pass on Android w/ libpng > 1.2. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698