1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkImageDecoder.h"
9#include "SkImageEncoder.h"
10#include "SkColor.h"
11#include "SkColorPriv.h"
12#include "SkDither.h"
13#include "SkMath.h"
14#include "SkRTConf.h"
15#include "SkScaledBitmapSampler.h"
16#include "SkStream.h"
17#include "SkTemplates.h"
18#include "SkUtils.h"
19#include "transform_scanline.h"
20
21#ifdef SKIA_PNG_PREFIXED
22    // this must proceed png.h
23    #include "pngprefix.h"
24#endif
25#include "png.h"
26
27/* These were dropped in libpng >= 1.4 */
28#ifndef png_infopp_NULL
29#define png_infopp_NULL NULL
30#endif
31
32#ifndef png_bytepp_NULL
33#define png_bytepp_NULL NULL
34#endif
35
36#ifndef int_p_NULL
37#define int_p_NULL NULL
38#endif
39
40#ifndef png_flush_ptr_NULL
41#define png_flush_ptr_NULL NULL
42#endif
43
44#if defined(SK_DEBUG)
45#define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS false
46#else  // !defined(SK_DEBUG)
47#define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true
48#endif  // defined(SK_DEBUG)
49SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings,
50                "images.png.suppressDecoderWarnings",
51                DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS,
52                "Suppress most PNG warnings when calling image decode "
53                "functions.");
54
55
56
57class SkPNGImageIndex {
58public:
59    // Takes ownership of stream.
60    SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop info_ptr)
61        : fStream(stream)
62        , fPng_ptr(png_ptr)
63        , fInfo_ptr(info_ptr)
64        , fColorType(kUnknown_SkColorType) {
65        SkASSERT(stream != NULL);
66    }
67    ~SkPNGImageIndex() {
68        if (fPng_ptr) {
69            png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
70        }
71    }
72
73    SkAutoTDelete<SkStreamRewindable>   fStream;
74    png_structp                         fPng_ptr;
75    png_infop                           fInfo_ptr;
76    SkColorType                         fColorType;
77};
78
79class SkPNGImageDecoder : public SkImageDecoder {
80public:
81    SkPNGImageDecoder() {
82        fImageIndex = NULL;
83    }
84    Format getFormat() const override {
85        return kPNG_Format;
86    }
87
88    virtual ~SkPNGImageDecoder() {
89        SkDELETE(fImageIndex);
90    }
91
92protected:
93#ifdef SK_BUILD_FOR_ANDROID
94    bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) override;
95    bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) override;
96#endif
97    Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
98
99private:
100    SkPNGImageIndex* fImageIndex;
101
102    bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_ptrp);
103    bool decodePalette(png_structp png_ptr, png_infop info_ptr, int bitDepth,
104                       bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap,
105                       SkColorTable **colorTablep);
106    bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha,
107                            SkPMColor* theTranspColor);
108
109    typedef SkImageDecoder INHERITED;
110};
111
112#ifndef png_jmpbuf
113#  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
114#endif
115
116#define PNG_BYTES_TO_CHECK 4
117
118/* Automatically clean up after throwing an exception */
119struct PNGAutoClean {
120    PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {}
121    ~PNGAutoClean() {
122        png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
123    }
124private:
125    png_structp png_ptr;
126    png_infop info_ptr;
127};
128
129static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) {
130    SkStream* sk_stream = (SkStream*) png_get_io_ptr(png_ptr);
131    size_t bytes = sk_stream->read(data, length);
132    if (bytes != length) {
133        png_error(png_ptr, "Read Error!");
134    }
135}
136
137#ifdef SK_BUILD_FOR_ANDROID
138static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) {
139    SkStreamRewindable* sk_stream = (SkStreamRewindable*) png_get_io_ptr(png_ptr);
140    if (!sk_stream->rewind()) {
141        png_error(png_ptr, "Failed to rewind stream!");
142    }
143    (void)sk_stream->skip(offset);
144}
145#endif
146
147#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
148static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
149    SkImageDecoder::Peeker* peeker =
150                    (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr);
151    // peek() returning true means continue decoding
152    return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ?
153            1 : -1;
154}
155#endif
156
157static void sk_error_fn(png_structp png_ptr, png_const_charp msg) {
158    SkDEBUGF(("------ png error %s\n", msg));
159    longjmp(png_jmpbuf(png_ptr), 1);
160}
161
162static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) {
163    for (int i = 0; i < count; i++) {
164        uint8_t* tmp = storage;
165        png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
166    }
167}
168
169static bool pos_le(int value, int max) {
170    return value > 0 && value <= max;
171}
172
173static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) {
174    SkASSERT(bm->colorType() == kN32_SkColorType);
175
176    bool reallyHasAlpha = false;
177
178    for (int y = bm->height() - 1; y >= 0; --y) {
179        SkPMColor* p = bm->getAddr32(0, y);
180        for (int x = bm->width() - 1; x >= 0; --x) {
181            if (match == *p) {
182                *p = 0;
183                reallyHasAlpha = true;
184            }
185            p += 1;
186        }
187    }
188    return reallyHasAlpha;
189}
190
191static bool canUpscalePaletteToConfig(SkColorType dstColorType, bool srcHasAlpha) {
192    switch (dstColorType) {
193        case kN32_SkColorType:
194        case kARGB_4444_SkColorType:
195            return true;
196        case kRGB_565_SkColorType:
197            // only return true if the src is opaque (since 565 is opaque)
198            return !srcHasAlpha;
199        default:
200            return false;
201    }
202}
203
204// call only if color_type is PALETTE. Returns true if the ctable has alpha
205static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) {
206    png_bytep trans;
207    int num_trans;
208
209    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
210        png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
211        return num_trans > 0;
212    }
213    return false;
214}
215
216void do_nothing_warning_fn(png_structp, png_const_charp) {
217    /* do nothing */
218}
219
220bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp,
221                                     png_infop *info_ptrp) {
222    /* Create and initialize the png_struct with the desired error handler
223    * functions.  If you want to use the default stderr and longjump method,
224    * you can supply NULL for the last three parameters.  We also supply the
225    * the compiler header file version, so that we know if the application
226    * was compiled with a compatible version of the library.  */
227
228    png_error_ptr user_warning_fn =
229        (c_suppressPNGImageDecoderWarnings) ? (&do_nothing_warning_fn) : NULL;
230    /* NULL means to leave as default library behavior. */
231    /* c_suppressPNGImageDecoderWarnings default depends on SK_DEBUG. */
232    /* To suppress warnings with a SK_DEBUG binary, set the
233     * environment variable "skia_images_png_suppressDecoderWarnings"
234     * to "true".  Inside a program that links to skia:
235     * SK_CONF_SET("images.png.suppressDecoderWarnings", true); */
236
237    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
238        NULL, sk_error_fn, user_warning_fn);
239    //   png_voidp user_error_ptr, user_error_fn, user_warning_fn);
240    if (png_ptr == NULL) {
241        return false;
242    }
243
244    *png_ptrp = png_ptr;
245
246    /* Allocate/initialize the memory for image information. */
247    png_infop info_ptr = png_create_info_struct(png_ptr);
248    if (info_ptr == NULL) {
249        png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
250        return false;
251    }
252    *info_ptrp = info_ptr;
253
254    /* Set error handling if you are using the setjmp/longjmp method (this is
255    * the normal method of doing things with libpng).  REQUIRED unless you
256    * set up your own error handlers in the png_create_read_struct() earlier.
257    */
258    if (setjmp(png_jmpbuf(png_ptr))) {
259        png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
260        return false;
261    }
262
263    /* If you are using replacement read functions, instead of calling
264    * png_init_io() here you would call:
265    */
266    png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn);
267#ifdef SK_BUILD_FOR_ANDROID
268    png_set_seek_fn(png_ptr, sk_seek_fn);
269#endif
270    /* where user_io_ptr is a structure you want available to the callbacks */
271    /* If we have already read some of the signature */
272//  png_set_sig_bytes(png_ptr, 0 /* sig_read */ );
273
274#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
275    // hookup our peeker so we can see any user-chunks the caller may be interested in
276    png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0);
277    if (this->getPeeker()) {
278        png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_read_user_chunk);
279    }
280#endif
281    /* The call to png_read_info() gives us all of the information from the
282    * PNG file before the first IDAT (image data chunk). */
283    png_read_info(png_ptr, info_ptr);
284    png_uint_32 origWidth, origHeight;
285    int bitDepth, colorType;
286    png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
287                 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
288
289    /* tell libpng to strip 16 bit/color files down to 8 bits/color */
290    if (bitDepth == 16) {
291        png_set_strip_16(png_ptr);
292    }
293#ifdef PNG_READ_PACK_SUPPORTED
294    /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
295     * byte into separate bytes (useful for paletted and grayscale images). */
296    if (bitDepth < 8) {
297        png_set_packing(png_ptr);
298    }
299#endif
300    /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
301    if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) {
302        png_set_expand_gray_1_2_4_to_8(png_ptr);
303    }
304
305    return true;
306}
307
308SkImageDecoder::Result SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
309                                                   Mode mode) {
310    png_structp png_ptr;
311    png_infop info_ptr;
312
313    if (!onDecodeInit(sk_stream, &png_ptr, &info_ptr)) {
314        return kFailure;
315    }
316
317    PNGAutoClean autoClean(png_ptr, info_ptr);
318
319    if (setjmp(png_jmpbuf(png_ptr))) {
320        return kFailure;
321    }
322
323    png_uint_32 origWidth, origHeight;
324    int bitDepth, pngColorType, interlaceType;
325    png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
326                 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
327
328    SkColorType         colorType;
329    bool                hasAlpha = false;
330    SkPMColor           theTranspColor = 0; // 0 tells us not to try to match
331
332    if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &theTranspColor)) {
333        return kFailure;
334    }
335
336    SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ?
337                                kUnpremul_SkAlphaType : kPremul_SkAlphaType;
338    const int sampleSize = this->getSampleSize();
339    SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
340    decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
341                                             colorType, alphaType));
342
343    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
344        return kSuccess;
345    }
346
347    // from here down we are concerned with colortables and pixels
348
349    // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
350    // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
351    // draw lots faster if we can flag the bitmap has being opaque
352    bool reallyHasAlpha = false;
353    SkColorTable* colorTable = NULL;
354
355    if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
356        decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &colorTable);
357    }
358
359    SkAutoUnref aur(colorTable);
360
361    if (!this->allocPixelRef(decodedBitmap,
362                             kIndex_8_SkColorType == colorType ? colorTable : NULL)) {
363        return kFailure;
364    }
365
366    SkAutoLockPixels alp(*decodedBitmap);
367
368    // Repeat setjmp, otherwise variables declared since the last call (e.g. alp
369    // and aur) won't get their destructors called in case of a failure.
370    if (setjmp(png_jmpbuf(png_ptr))) {
371        return kFailure;
372    }
373
374    /* Turn on interlace handling.  REQUIRED if you are not using
375    *  png_read_image().  To see how to handle interlacing passes,
376    *  see the png_read_row() method below:
377    */
378    const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ?
379                              png_set_interlace_handling(png_ptr) : 1;
380
381    /* Optional call to gamma correct and add the background to the palette
382    *  and update info structure.  REQUIRED if you are expecting libpng to
383    *  update the palette for you (ie you selected such a transform above).
384    */
385    png_read_update_info(png_ptr, info_ptr);
386
387    if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) &&
388            1 == sampleSize) {
389        if (kAlpha_8_SkColorType == colorType) {
390            // For an A8 bitmap, we assume there is an alpha for speed. It is
391            // possible the bitmap is opaque, but that is an unlikely use case
392            // since it would not be very interesting.
393            reallyHasAlpha = true;
394            // A8 is only allowed if the original was GRAY.
395            SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
396        }
397        for (int i = 0; i < number_passes; i++) {
398            for (png_uint_32 y = 0; y < origHeight; y++) {
399                uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
400                png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
401            }
402        }
403    } else {
404        SkScaledBitmapSampler::SrcConfig sc;
405        int srcBytesPerPixel = 4;
406
407        if (colorTable != NULL) {
408            sc = SkScaledBitmapSampler::kIndex;
409            srcBytesPerPixel = 1;
410        } else if (kAlpha_8_SkColorType == colorType) {
411            // A8 is only allowed if the original was GRAY.
412            SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
413            sc = SkScaledBitmapSampler::kGray;
414            srcBytesPerPixel = 1;
415        } else if (hasAlpha) {
416            sc = SkScaledBitmapSampler::kRGBA;
417        } else {
418            sc = SkScaledBitmapSampler::kRGBX;
419        }
420
421        /*  We have to pass the colortable explicitly, since we may have one
422            even if our decodedBitmap doesn't, due to the request that we
423            upscale png's palette to a direct model
424         */
425        const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL;
426        if (!sampler.begin(decodedBitmap, sc, *this, colors)) {
427            return kFailure;
428        }
429        const int height = decodedBitmap->height();
430
431        if (number_passes > 1) {
432            SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
433            uint8_t* base = (uint8_t*)storage.get();
434            size_t rowBytes = origWidth * srcBytesPerPixel;
435
436            for (int i = 0; i < number_passes; i++) {
437                uint8_t* row = base;
438                for (png_uint_32 y = 0; y < origHeight; y++) {
439                    uint8_t* bmRow = row;
440                    png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
441                    row += rowBytes;
442                }
443            }
444            // now sample it
445            base += sampler.srcY0() * rowBytes;
446            for (int y = 0; y < height; y++) {
447                reallyHasAlpha |= sampler.next(base);
448                base += sampler.srcDY() * rowBytes;
449            }
450        } else {
451            SkAutoMalloc storage(origWidth * srcBytesPerPixel);
452            uint8_t* srcRow = (uint8_t*)storage.get();
453            skip_src_rows(png_ptr, srcRow, sampler.srcY0());
454
455            for (int y = 0; y < height; y++) {
456                uint8_t* tmp = srcRow;
457                png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
458                reallyHasAlpha |= sampler.next(srcRow);
459                if (y < height - 1) {
460                    skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
461                }
462            }
463
464            // skip the rest of the rows (if any)
465            png_uint_32 read = (height - 1) * sampler.srcDY() +
466                               sampler.srcY0() + 1;
467            SkASSERT(read <= origHeight);
468            skip_src_rows(png_ptr, srcRow, origHeight - read);
469        }
470    }
471
472    /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
473    png_read_end(png_ptr, info_ptr);
474
475    if (0 != theTranspColor) {
476        reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
477    }
478    if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
479        switch (decodedBitmap->colorType()) {
480            case kIndex_8_SkColorType:
481                // Fall through.
482            case kARGB_4444_SkColorType:
483                // We have chosen not to support unpremul for these colortypes.
484                return kFailure;
485            default: {
486                // Fall through to finish the decode. This colortype either
487                // supports unpremul or it is irrelevant because it has no
488                // alpha (or only alpha).
489                // These brackets prevent a warning.
490            }
491        }
492    }
493
494    if (!reallyHasAlpha) {
495        decodedBitmap->setAlphaType(kOpaque_SkAlphaType);
496    }
497    return kSuccess;
498}
499
500
501
502bool SkPNGImageDecoder::getBitmapColorType(png_structp png_ptr, png_infop info_ptr,
503                                           SkColorType* colorTypep,
504                                           bool* hasAlphap,
505                                           SkPMColor* SK_RESTRICT theTranspColorp) {
506    png_uint_32 origWidth, origHeight;
507    int bitDepth, colorType;
508    png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
509                 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
510
511#ifdef PNG_sBIT_SUPPORTED
512    // check for sBIT chunk data, in case we should disable dithering because
513    // our data is not truely 8bits per component
514    png_color_8p sig_bit;
515    if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) {
516#if 0
517        SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green,
518                 sig_bit->blue, sig_bit->alpha);
519#endif
520        // 0 seems to indicate no information available
521        if (pos_le(sig_bit->red, SK_R16_BITS) &&
522            pos_le(sig_bit->green, SK_G16_BITS) &&
523            pos_le(sig_bit->blue, SK_B16_BITS)) {
524            this->setDitherImage(false);
525        }
526    }
527#endif
528
529    if (colorType == PNG_COLOR_TYPE_PALETTE) {
530        bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
531        *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha);
532        // now see if we can upscale to their requested colortype
533        if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) {
534            *colorTypep = kIndex_8_SkColorType;
535        }
536    } else {
537        png_color_16p transpColor = NULL;
538        int numTransp = 0;
539
540        png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor);
541
542        bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
543
544        if (valid && numTransp == 1 && transpColor != NULL) {
545            /*  Compute our transparent color, which we'll match against later.
546                We don't really handle 16bit components properly here, since we
547                do our compare *after* the values have been knocked down to 8bit
548                which means we will find more matches than we should. The real
549                fix seems to be to see the actual 16bit components, do the
550                compare, and then knock it down to 8bits ourselves.
551            */
552            if (colorType & PNG_COLOR_MASK_COLOR) {
553                if (16 == bitDepth) {
554                    *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8,
555                                                    transpColor->green >> 8,
556                                                    transpColor->blue >> 8);
557                } else {
558                    /* We apply the mask because in a very small
559                       number of corrupt PNGs, (transpColor->red > 255)
560                       and (bitDepth == 8), for certain versions of libpng. */
561                    *theTranspColorp = SkPackARGB32(0xFF,
562                                                    0xFF & (transpColor->red),
563                                                    0xFF & (transpColor->green),
564                                                    0xFF & (transpColor->blue));
565                }
566            } else {    // gray
567                if (16 == bitDepth) {
568                    *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8,
569                                                    transpColor->gray >> 8,
570                                                    transpColor->gray >> 8);
571                } else {
572                    /* We apply the mask because in a very small
573                       number of corrupt PNGs, (transpColor->red >
574                       255) and (bitDepth == 8), for certain versions
575                       of libpng.  For safety we assume the same could
576                       happen with a grayscale PNG.  */
577                    *theTranspColorp = SkPackARGB32(0xFF,
578                                                    0xFF & (transpColor->gray),
579                                                    0xFF & (transpColor->gray),
580                                                    0xFF & (transpColor->gray));
581                }
582            }
583        }
584
585        if (valid ||
586            PNG_COLOR_TYPE_RGB_ALPHA == colorType ||
587            PNG_COLOR_TYPE_GRAY_ALPHA == colorType) {
588            *hasAlphap = true;
589        }
590
591        SrcDepth srcDepth = k32Bit_SrcDepth;
592        if (PNG_COLOR_TYPE_GRAY == colorType) {
593            srcDepth = k8BitGray_SrcDepth;
594            // Remove this assert, which fails on desk_pokemonwiki.skp
595            //SkASSERT(!*hasAlphap);
596        }
597
598        *colorTypep = this->getPrefColorType(srcDepth, *hasAlphap);
599        // now match the request against our capabilities
600        if (*hasAlphap) {
601            if (*colorTypep != kARGB_4444_SkColorType) {
602                *colorTypep = kN32_SkColorType;
603            }
604        } else {
605            if (kAlpha_8_SkColorType == *colorTypep) {
606                if (k8BitGray_SrcDepth != srcDepth) {
607                    // Converting a non grayscale image to A8 is not currently supported.
608                    *colorTypep = kN32_SkColorType;
609                }
610            } else if (*colorTypep != kRGB_565_SkColorType &&
611                       *colorTypep != kARGB_4444_SkColorType) {
612                *colorTypep = kN32_SkColorType;
613            }
614        }
615    }
616
617    // sanity check for size
618    {
619        int64_t size = sk_64_mul(origWidth, origHeight);
620        // now check that if we are 4-bytes per pixel, we also don't overflow
621        if (size < 0 || size > (0x7FFFFFFF >> 2)) {
622            return false;
623        }
624    }
625
626    // If the image has alpha and the decoder wants unpremultiplied
627    // colors, the only supported colortype is 8888.
628    if (this->getRequireUnpremultipliedColors() && *hasAlphap) {
629        *colorTypep = kN32_SkColorType;
630    }
631
632    if (fImageIndex != NULL) {
633        if (kUnknown_SkColorType == fImageIndex->fColorType) {
634            // This is the first time for this subset decode. From now on,
635            // all decodes must be in the same colortype.
636            fImageIndex->fColorType = *colorTypep;
637        } else if (fImageIndex->fColorType != *colorTypep) {
638            // Requesting a different colortype for a subsequent decode is not
639            // supported. Report failure before we make changes to png_ptr.
640            return false;
641        }
642    }
643
644    bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != kAlpha_8_SkColorType;
645
646    // Unless the user is requesting A8, convert a grayscale image into RGB.
647    // GRAY_ALPHA will always be converted to RGB
648    if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
649        png_set_gray_to_rgb(png_ptr);
650    }
651
652    // Add filler (or alpha) byte (after each RGB triplet) if necessary.
653    if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
654        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
655    }
656
657    return true;
658}
659
660typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
661
662bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
663                                      int bitDepth, bool *hasAlphap,
664                                      bool *reallyHasAlphap,
665                                      SkColorTable **colorTablep) {
666    int numPalette;
667    png_colorp palette;
668    png_bytep trans;
669    int numTrans;
670
671    png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette);
672
673    SkPMColor colorStorage[256];    // worst-case storage
674    SkPMColor* colorPtr = colorStorage;
675
676    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
677        png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL);
678        *hasAlphap = (numTrans > 0);
679    } else {
680        numTrans = 0;
681    }
682
683    // check for bad images that might make us crash
684    if (numTrans > numPalette) {
685        numTrans = numPalette;
686    }
687
688    int index = 0;
689    int transLessThanFF = 0;
690
691    // Choose which function to use to create the color table. If the final destination's
692    // colortype is unpremultiplied, the color table will store unpremultiplied colors.
693    PackColorProc proc;
694    if (this->getRequireUnpremultipliedColors()) {
695        proc = &SkPackARGB32NoCheck;
696    } else {
697        proc = &SkPreMultiplyARGB;
698    }
699    for (; index < numTrans; index++) {
700        transLessThanFF |= (int)*trans - 0xFF;
701        *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue);
702        palette++;
703    }
704    bool reallyHasAlpha = (transLessThanFF < 0);
705
706    for (; index < numPalette; index++) {
707        *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->blue);
708        palette++;
709    }
710
711    /*  BUGGY IMAGE WORKAROUND
712
713        Invalid images could contain pixel values that are greater than the number of palette
714        entries. Since we use pixel values as indices into the palette this could result in reading
715        beyond the end of the palette which could leak the contents of uninitialized memory. To
716        ensure this doesn't happen, we grow the colortable to the maximum size that can be
717        addressed by the bitdepth of the image and fill it with the last palette color or black if
718        the palette is empty (really broken image).
719    */
720    int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8));
721    SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0);
722    for (; index < colorCount; index++) {
723        *colorPtr++ = lastColor;
724    }
725
726    *colorTablep = SkNEW_ARGS(SkColorTable, (colorStorage, colorCount));
727    *reallyHasAlphap = reallyHasAlpha;
728    return true;
729}
730
731#ifdef SK_BUILD_FOR_ANDROID
732
733bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *width, int *height) {
734    SkAutoTDelete<SkStreamRewindable> streamDeleter(sk_stream);
735    png_structp png_ptr;
736    png_infop   info_ptr;
737
738    if (!onDecodeInit(sk_stream, &png_ptr, &info_ptr)) {
739        return false;
740    }
741
742    if (setjmp(png_jmpbuf(png_ptr)) != 0) {
743        png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
744        return false;
745    }
746
747    png_uint_32 origWidth, origHeight;
748    int bitDepth, colorType;
749    png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
750                 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
751
752    *width = origWidth;
753    *height = origHeight;
754
755    png_build_index(png_ptr);
756
757    if (fImageIndex) {
758        SkDELETE(fImageIndex);
759    }
760    fImageIndex = SkNEW_ARGS(SkPNGImageIndex, (streamDeleter.detach(), png_ptr, info_ptr));
761
762    return true;
763}
764
765bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
766    if (NULL == fImageIndex) {
767        return false;
768    }
769
770    png_structp png_ptr = fImageIndex->fPng_ptr;
771    png_infop info_ptr = fImageIndex->fInfo_ptr;
772    if (setjmp(png_jmpbuf(png_ptr))) {
773        return false;
774    }
775
776    png_uint_32 origWidth, origHeight;
777    int bitDepth, pngColorType, interlaceType;
778    png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
779                 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
780
781    SkIRect rect = SkIRect::MakeWH(origWidth, origHeight);
782
783    if (!rect.intersect(region)) {
784        // If the requested region is entirely outside the image, just
785        // returns false
786        return false;
787    }
788
789    SkColorType         colorType;
790    bool                hasAlpha = false;
791    SkPMColor           theTranspColor = 0; // 0 tells us not to try to match
792
793    if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &theTranspColor)) {
794        return false;
795    }
796
797    const int sampleSize = this->getSampleSize();
798    SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize);
799
800    SkBitmap decodedBitmap;
801    decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
802                                            colorType, kPremul_SkAlphaType));
803
804    // from here down we are concerned with colortables and pixels
805
806    // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
807    // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
808    // draw lots faster if we can flag the bitmap has being opaque
809    bool reallyHasAlpha = false;
810    SkColorTable* colorTable = NULL;
811
812    if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
813        decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &colorTable);
814    }
815
816    SkAutoUnref aur(colorTable);
817
818    // Check ahead of time if the swap(dest, src) is possible.
819    // If yes, then we will stick to AllocPixelRef since it's cheaper with the swap happening.
820    // If no, then we will use alloc to allocate pixels to prevent garbage collection.
821    int w = rect.width() / sampleSize;
822    int h = rect.height() / sampleSize;
823    const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) &&
824                          (h == decodedBitmap.height()) && bm->isNull();
825    const bool needColorTable = kIndex_8_SkColorType == colorType;
826    if (swapOnly) {
827        if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : NULL)) {
828            return false;
829        }
830    } else {
831        if (!decodedBitmap.tryAllocPixels(NULL, needColorTable ? colorTable : NULL)) {
832            return false;
833        }
834    }
835    SkAutoLockPixels alp(decodedBitmap);
836
837    /* Turn on interlace handling.  REQUIRED if you are not using
838    * png_read_image().  To see how to handle interlacing passes,
839    * see the png_read_row() method below:
840    */
841    const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ?
842                              png_set_interlace_handling(png_ptr) : 1;
843
844    /* Optional call to gamma correct and add the background to the palette
845    * and update info structure.  REQUIRED if you are expecting libpng to
846    * update the palette for you (ie you selected such a transform above).
847    */
848
849    // Direct access to png_ptr fields is deprecated in libpng > 1.2.
850#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
851    png_ptr->pass = 0;
852#else
853    // FIXME: This sets pass as desired, but also sets iwidth. Is that ok?
854    png_set_interlaced_pass(png_ptr, 0);
855#endif
856    png_read_update_info(png_ptr, info_ptr);
857
858    int actualTop = rect.fTop;
859
860    if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType)
861        && 1 == sampleSize) {
862        if (kAlpha_8_SkColorType == colorType) {
863            // For an A8 bitmap, we assume there is an alpha for speed. It is
864            // possible the bitmap is opaque, but that is an unlikely use case
865            // since it would not be very interesting.
866            reallyHasAlpha = true;
867            // A8 is only allowed if the original was GRAY.
868            SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
869        }
870
871        for (int i = 0; i < number_passes; i++) {
872            png_configure_decoder(png_ptr, &actualTop, i);
873            for (int j = 0; j < rect.fTop - actualTop; j++) {
874                uint8_t* bmRow = decodedBitmap.getAddr8(0, 0);
875                png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
876            }
877            png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height();
878            for (png_uint_32 y = 0; y < bitmapHeight; y++) {
879                uint8_t* bmRow = decodedBitmap.getAddr8(0, y);
880                png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
881            }
882        }
883    } else {
884        SkScaledBitmapSampler::SrcConfig sc;
885        int srcBytesPerPixel = 4;
886
887        if (colorTable != NULL) {
888            sc = SkScaledBitmapSampler::kIndex;
889            srcBytesPerPixel = 1;
890        } else if (kAlpha_8_SkColorType == colorType) {
891            // A8 is only allowed if the original was GRAY.
892            SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
893            sc = SkScaledBitmapSampler::kGray;
894            srcBytesPerPixel = 1;
895        } else if (hasAlpha) {
896            sc = SkScaledBitmapSampler::kRGBA;
897        } else {
898            sc = SkScaledBitmapSampler::kRGBX;
899        }
900
901        /*  We have to pass the colortable explicitly, since we may have one
902            even if our decodedBitmap doesn't, due to the request that we
903            upscale png's palette to a direct model
904         */
905        const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL;
906        if (!sampler.begin(&decodedBitmap, sc, *this, colors)) {
907            return false;
908        }
909        const int height = decodedBitmap.height();
910
911        if (number_passes > 1) {
912            SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
913            uint8_t* base = (uint8_t*)storage.get();
914            size_t rb = origWidth * srcBytesPerPixel;
915
916            for (int i = 0; i < number_passes; i++) {
917                png_configure_decoder(png_ptr, &actualTop, i);
918                for (int j = 0; j < rect.fTop - actualTop; j++) {
919                    png_read_rows(png_ptr, &base, png_bytepp_NULL, 1);
920                }
921                uint8_t* row = base;
922                for (int32_t y = 0; y < rect.height(); y++) {
923                    uint8_t* bmRow = row;
924                    png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
925                    row += rb;
926                }
927            }
928            // now sample it
929            base += sampler.srcY0() * rb;
930            for (int y = 0; y < height; y++) {
931                reallyHasAlpha |= sampler.next(base);
932                base += sampler.srcDY() * rb;
933            }
934        } else {
935            SkAutoMalloc storage(origWidth * srcBytesPerPixel);
936            uint8_t* srcRow = (uint8_t*)storage.get();
937
938            png_configure_decoder(png_ptr, &actualTop, 0);
939            skip_src_rows(png_ptr, srcRow, sampler.srcY0());
940
941            for (int i = 0; i < rect.fTop - actualTop; i++) {
942                png_read_rows(png_ptr, &srcRow, png_bytepp_NULL, 1);
943            }
944            for (int y = 0; y < height; y++) {
945                uint8_t* tmp = srcRow;
946                png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
947                reallyHasAlpha |= sampler.next(srcRow);
948                if (y < height - 1) {
949                    skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
950                }
951            }
952        }
953    }
954
955    if (0 != theTranspColor) {
956        reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor);
957    }
958    if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
959        switch (decodedBitmap.colorType()) {
960            case kIndex_8_SkColorType:
961                // Fall through.
962            case kARGB_4444_SkColorType:
963                // We have chosen not to support unpremul for these colortypess.
964                return false;
965            default: {
966                // Fall through to finish the decode. This config either
967                // supports unpremul or it is irrelevant because it has no
968                // alpha (or only alpha).
969                // These brackets prevent a warning.
970            }
971        }
972    }
973    SkAlphaType alphaType = kOpaque_SkAlphaType;
974    if (reallyHasAlpha) {
975        if (this->getRequireUnpremultipliedColors()) {
976            alphaType = kUnpremul_SkAlphaType;
977        } else {
978            alphaType = kPremul_SkAlphaType;
979        }
980    }
981    decodedBitmap.setAlphaType(alphaType);
982
983    if (swapOnly) {
984        bm->swap(decodedBitmap);
985        return true;
986    }
987    return this->cropBitmap(bm, &decodedBitmap, sampleSize, region.x(), region.y(),
988                            region.width(), region.height(), 0, rect.y());
989}
990#endif
991
992///////////////////////////////////////////////////////////////////////////////
993
994#include "SkColorPriv.h"
995#include "SkUnPreMultiply.h"
996
997static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
998    SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
999    if (!sk_stream->write(data, len)) {
1000        png_error(png_ptr, "sk_write_fn Error!");
1001    }
1002}
1003
1004static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) {
1005    // we don't care about search on alpha if we're kIndex8, since only the
1006    // colortable packing cares about that distinction, not the pixels
1007    if (kIndex_8_SkColorType == ct) {
1008        hasAlpha = false;   // we store false in the table entries for kIndex8
1009    }
1010
1011    static const struct {
1012        SkColorType             fColorType;
1013        bool                    fHasAlpha;
1014        transform_scanline_proc fProc;
1015    } gMap[] = {
1016        { kRGB_565_SkColorType,     false,  transform_scanline_565 },
1017        { kN32_SkColorType,         false,  transform_scanline_888 },
1018        { kN32_SkColorType,         true,   transform_scanline_8888 },
1019        { kARGB_4444_SkColorType,   false,  transform_scanline_444 },
1020        { kARGB_4444_SkColorType,   true,   transform_scanline_4444 },
1021        { kIndex_8_SkColorType,     false,  transform_scanline_memcpy },
1022    };
1023
1024    for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) {
1025        if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) {
1026            return gMap[i].fProc;
1027        }
1028    }
1029    sk_throw();
1030    return NULL;
1031}
1032
1033// return the minimum legal bitdepth (by png standards) for this many colortable
1034// entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16,
1035// we can use fewer bits per in png
1036static int computeBitDepth(int colorCount) {
1037#if 0
1038    int bits = SkNextLog2(colorCount);
1039    SkASSERT(bits >= 1 && bits <= 8);
1040    // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8)
1041    return SkNextPow2(bits);
1042#else
1043    // for the moment, we don't know how to pack bitdepth < 8
1044    return 8;
1045#endif
1046}
1047
1048/*  Pack palette[] with the corresponding colors, and if hasAlpha is true, also
1049    pack trans[] and return the number of trans[] entries written. If hasAlpha
1050    is false, the return value will always be 0.
1051
1052    Note: this routine takes care of unpremultiplying the RGB values when we
1053    have alpha in the colortable, since png doesn't support premul colors
1054*/
1055static inline int pack_palette(SkColorTable* ctable,
1056                               png_color* SK_RESTRICT palette,
1057                               png_byte* SK_RESTRICT trans, bool hasAlpha) {
1058    const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : NULL;
1059    const int ctCount = ctable->count();
1060    int i, num_trans = 0;
1061
1062    if (hasAlpha) {
1063        /*  first see if we have some number of fully opaque at the end of the
1064            ctable. PNG allows num_trans < num_palette, but all of the trans
1065            entries must come first in the palette. If I was smarter, I'd
1066            reorder the indices and ctable so that all non-opaque colors came
1067            first in the palette. But, since that would slow down the encode,
1068            I'm leaving the indices and ctable order as is, and just looking
1069            at the tail of the ctable for opaqueness.
1070        */
1071        num_trans = ctCount;
1072        for (i = ctCount - 1; i >= 0; --i) {
1073            if (SkGetPackedA32(colors[i]) != 0xFF) {
1074                break;
1075            }
1076            num_trans -= 1;
1077        }
1078
1079        const SkUnPreMultiply::Scale* SK_RESTRICT table =
1080                                            SkUnPreMultiply::GetScaleTable();
1081
1082        for (i = 0; i < num_trans; i++) {
1083            const SkPMColor c = *colors++;
1084            const unsigned a = SkGetPackedA32(c);
1085            const SkUnPreMultiply::Scale s = table[a];
1086            trans[i] = a;
1087            palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c));
1088            palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32(c));
1089            palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c));
1090        }
1091        // now fall out of this if-block to use common code for the trailing
1092        // opaque entries
1093    }
1094
1095    // these (remaining) entries are opaque
1096    for (i = num_trans; i < ctCount; i++) {
1097        SkPMColor c = *colors++;
1098        palette[i].red = SkGetPackedR32(c);
1099        palette[i].green = SkGetPackedG32(c);
1100        palette[i].blue = SkGetPackedB32(c);
1101    }
1102    return num_trans;
1103}
1104
1105class SkPNGImageEncoder : public SkImageEncoder {
1106protected:
1107    bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override;
1108private:
1109    bool doEncode(SkWStream* stream, const SkBitmap& bm,
1110                  const bool& hasAlpha, int colorType,
1111                  int bitDepth, SkColorType ct,
1112                  png_color_8& sig_bit);
1113
1114    typedef SkImageEncoder INHERITED;
1115};
1116
1117bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int /*quality*/) {
1118    SkColorType ct = bitmap.colorType();
1119
1120    const bool hasAlpha = !bitmap.isOpaque();
1121    int colorType = PNG_COLOR_MASK_COLOR;
1122    int bitDepth = 8;   // default for color
1123    png_color_8 sig_bit;
1124
1125    switch (ct) {
1126        case kIndex_8_SkColorType:
1127            colorType |= PNG_COLOR_MASK_PALETTE;
1128            // fall through to the ARGB_8888 case
1129        case kN32_SkColorType:
1130            sig_bit.red = 8;
1131            sig_bit.green = 8;
1132            sig_bit.blue = 8;
1133            sig_bit.alpha = 8;
1134            break;
1135        case kARGB_4444_SkColorType:
1136            sig_bit.red = 4;
1137            sig_bit.green = 4;
1138            sig_bit.blue = 4;
1139            sig_bit.alpha = 4;
1140            break;
1141        case kRGB_565_SkColorType:
1142            sig_bit.red = 5;
1143            sig_bit.green = 6;
1144            sig_bit.blue = 5;
1145            sig_bit.alpha = 0;
1146            break;
1147        default:
1148            return false;
1149    }
1150
1151    if (hasAlpha) {
1152        // don't specify alpha if we're a palette, even if our ctable has alpha
1153        if (!(colorType & PNG_COLOR_MASK_PALETTE)) {
1154            colorType |= PNG_COLOR_MASK_ALPHA;
1155        }
1156    } else {
1157        sig_bit.alpha = 0;
1158    }
1159
1160    SkAutoLockPixels alp(bitmap);
1161    // readyToDraw checks for pixels (and colortable if that is required)
1162    if (!bitmap.readyToDraw()) {
1163        return false;
1164    }
1165
1166    // we must do this after we have locked the pixels
1167    SkColorTable* ctable = bitmap.getColorTable();
1168    if (ctable) {
1169        if (ctable->count() == 0) {
1170            return false;
1171        }
1172        // check if we can store in fewer than 8 bits
1173        bitDepth = computeBitDepth(ctable->count());
1174    }
1175
1176    return doEncode(stream, bitmap, hasAlpha, colorType, bitDepth, ct, sig_bit);
1177}
1178
1179bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap,
1180                  const bool& hasAlpha, int colorType,
1181                  int bitDepth, SkColorType ct,
1182                  png_color_8& sig_bit) {
1183
1184    png_structp png_ptr;
1185    png_infop info_ptr;
1186
1187    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn,
1188                                      NULL);
1189    if (NULL == png_ptr) {
1190        return false;
1191    }
1192
1193    info_ptr = png_create_info_struct(png_ptr);
1194    if (NULL == info_ptr) {
1195        png_destroy_write_struct(&png_ptr,  png_infopp_NULL);
1196        return false;
1197    }
1198
1199    /* Set error handling.  REQUIRED if you aren't supplying your own
1200    * error handling functions in the png_create_write_struct() call.
1201    */
1202    if (setjmp(png_jmpbuf(png_ptr))) {
1203        png_destroy_write_struct(&png_ptr, &info_ptr);
1204        return false;
1205    }
1206
1207    png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, png_flush_ptr_NULL);
1208
1209    /* Set the image information here.  Width and height are up to 2^31,
1210    * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
1211    * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
1212    * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
1213    * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
1214    * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
1215    * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
1216    */
1217
1218    png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(),
1219                 bitDepth, colorType,
1220                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
1221                 PNG_FILTER_TYPE_BASE);
1222
1223    // set our colortable/trans arrays if needed
1224    png_color paletteColors[256];
1225    png_byte trans[256];
1226    if (kIndex_8_SkColorType == ct) {
1227        SkColorTable* ct = bitmap.getColorTable();
1228        int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha);
1229        png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count());
1230        if (numTrans > 0) {
1231            png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL);
1232        }
1233    }
1234#ifdef PNG_sBIT_SUPPORTED
1235    png_set_sBIT(png_ptr, info_ptr, &sig_bit);
1236#endif
1237    png_write_info(png_ptr, info_ptr);
1238
1239    const char* srcImage = (const char*)bitmap.getPixels();
1240    SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2);
1241    char* storage = (char*)rowStorage.get();
1242    transform_scanline_proc proc = choose_proc(ct, hasAlpha);
1243
1244    for (int y = 0; y < bitmap.height(); y++) {
1245        png_bytep row_ptr = (png_bytep)storage;
1246        proc(srcImage, bitmap.width(), storage);
1247        png_write_rows(png_ptr, &row_ptr, 1);
1248        srcImage += bitmap.rowBytes();
1249    }
1250
1251    png_write_end(png_ptr, info_ptr);
1252
1253    /* clean up after the write, and free any memory allocated */
1254    png_destroy_write_struct(&png_ptr, &info_ptr);
1255    return true;
1256}
1257
1258///////////////////////////////////////////////////////////////////////////////
1259DEFINE_DECODER_CREATOR(PNGImageDecoder);
1260DEFINE_ENCODER_CREATOR(PNGImageEncoder);
1261///////////////////////////////////////////////////////////////////////////////
1262
1263static bool is_png(SkStreamRewindable* stream) {
1264    char buf[PNG_BYTES_TO_CHECK];
1265    if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
1266        !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
1267        return true;
1268    }
1269    return false;
1270}
1271
1272SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) {
1273    if (is_png(stream)) {
1274        return SkNEW(SkPNGImageDecoder);
1275    }
1276    return NULL;
1277}
1278
1279static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) {
1280    if (is_png(stream)) {
1281        return SkImageDecoder::kPNG_Format;
1282    }
1283    return SkImageDecoder::kUnknown_Format;
1284}
1285
1286SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
1287    return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
1288}
1289
1290static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory);
1291static SkImageDecoder_FormatReg gFormatReg(get_format_png);
1292static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory);
1293