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