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