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     // we should communicate alphaType, even if we early-return in bounds-only-mode.
    337     if (this->getRequireUnpremultipliedColors()) {
    338         decodedBitmap->setAlphaType(kUnpremul_SkAlphaType);
    339     }
    340 
    341     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
    342         return true;
    343     }
    344 
    345     // from here down we are concerned with colortables and pixels
    346 
    347     // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
    348     // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
    349     // draw lots faster if we can flag the bitmap has being opaque
    350     bool reallyHasAlpha = false;
    351     SkColorTable* colorTable = NULL;
    352 
    353     if (colorType == PNG_COLOR_TYPE_PALETTE) {
    354         decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable);
    355     }
    356 
    357     SkAutoUnref aur(colorTable);
    358 
    359     if (!this->allocPixelRef(decodedBitmap,
    360                              SkBitmap::kIndex8_Config == config ? colorTable : NULL)) {
    361         return false;
    362     }
    363 
    364     SkAutoLockPixels alp(*decodedBitmap);
    365 
    366     /* Turn on interlace handling.  REQUIRED if you are not using
    367     *  png_read_image().  To see how to handle interlacing passes,
    368     *  see the png_read_row() method below:
    369     */
    370     const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ?
    371                               png_set_interlace_handling(png_ptr) : 1;
    372 
    373     /* Optional call to gamma correct and add the background to the palette
    374     *  and update info structure.  REQUIRED if you are expecting libpng to
    375     *  update the palette for you (ie you selected such a transform above).
    376     */
    377     png_read_update_info(png_ptr, info_ptr);
    378 
    379     if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config)
    380         && 1 == sampleSize) {
    381         if (SkBitmap::kA8_Config == config) {
    382             // For an A8 bitmap, we assume there is an alpha for speed. It is
    383             // possible the bitmap is opaque, but that is an unlikely use case
    384             // since it would not be very interesting.
    385             reallyHasAlpha = true;
    386             // A8 is only allowed if the original was GRAY.
    387             SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
    388         }
    389         for (int i = 0; i < number_passes; i++) {
    390             for (png_uint_32 y = 0; y < origHeight; y++) {
    391                 uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
    392                 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
    393             }
    394         }
    395     } else {
    396         SkScaledBitmapSampler::SrcConfig sc;
    397         int srcBytesPerPixel = 4;
    398 
    399         if (colorTable != NULL) {
    400             sc = SkScaledBitmapSampler::kIndex;
    401             srcBytesPerPixel = 1;
    402         } else if (SkBitmap::kA8_Config == config) {
    403             // A8 is only allowed if the original was GRAY.
    404             SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
    405             sc = SkScaledBitmapSampler::kGray;
    406             srcBytesPerPixel = 1;
    407         } else if (hasAlpha) {
    408             sc = SkScaledBitmapSampler::kRGBA;
    409         } else {
    410             sc = SkScaledBitmapSampler::kRGBX;
    411         }
    412 
    413         /*  We have to pass the colortable explicitly, since we may have one
    414             even if our decodedBitmap doesn't, due to the request that we
    415             upscale png's palette to a direct model
    416          */
    417         SkAutoLockColors ctLock(colorTable);
    418         if (!sampler.begin(decodedBitmap, sc, *this, ctLock.colors())) {
    419             return false;
    420         }
    421         const int height = decodedBitmap->height();
    422 
    423         if (number_passes > 1) {
    424             SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
    425             uint8_t* base = (uint8_t*)storage.get();
    426             size_t rowBytes = origWidth * srcBytesPerPixel;
    427 
    428             for (int i = 0; i < number_passes; i++) {
    429                 uint8_t* row = base;
    430                 for (png_uint_32 y = 0; y < origHeight; y++) {
    431                     uint8_t* bmRow = row;
    432                     png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
    433                     row += rowBytes;
    434                 }
    435             }
    436             // now sample it
    437             base += sampler.srcY0() * rowBytes;
    438             for (int y = 0; y < height; y++) {
    439                 reallyHasAlpha |= sampler.next(base);
    440                 base += sampler.srcDY() * rowBytes;
    441             }
    442         } else {
    443             SkAutoMalloc storage(origWidth * srcBytesPerPixel);
    444             uint8_t* srcRow = (uint8_t*)storage.get();
    445             skip_src_rows(png_ptr, srcRow, sampler.srcY0());
    446 
    447             for (int y = 0; y < height; y++) {
    448                 uint8_t* tmp = srcRow;
    449                 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
    450                 reallyHasAlpha |= sampler.next(srcRow);
    451                 if (y < height - 1) {
    452                     skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
    453                 }
    454             }
    455 
    456             // skip the rest of the rows (if any)
    457             png_uint_32 read = (height - 1) * sampler.srcDY() +
    458                                sampler.srcY0() + 1;
    459             SkASSERT(read <= origHeight);
    460             skip_src_rows(png_ptr, srcRow, origHeight - read);
    461         }
    462     }
    463 
    464     /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
    465     png_read_end(png_ptr, info_ptr);
    466 
    467     if (0 != theTranspColor) {
    468         reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
    469     }
    470     if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
    471         switch (decodedBitmap->config()) {
    472             case SkBitmap::kIndex8_Config:
    473                 // Fall through.
    474             case SkBitmap::kARGB_4444_Config:
    475                 // We have chosen not to support unpremul for these configs.
    476                 return false;
    477             default: {
    478                 // Fall through to finish the decode. This config either
    479                 // supports unpremul or it is irrelevant because it has no
    480                 // alpha (or only alpha).
    481                 // These brackets prevent a warning.
    482             }
    483         }
    484     }
    485 
    486     if (!reallyHasAlpha) {
    487         decodedBitmap->setAlphaType(kOpaque_SkAlphaType);
    488     }
    489     return true;
    490 }
    491 
    492 
    493 
    494 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
    495                                         SkBitmap::Config* SK_RESTRICT configp,
    496                                         bool* SK_RESTRICT hasAlphap,
    497                                         SkPMColor* SK_RESTRICT theTranspColorp) {
    498     png_uint_32 origWidth, origHeight;
    499     int bitDepth, colorType;
    500     png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
    501                  &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
    502 
    503     // check for sBIT chunk data, in case we should disable dithering because
    504     // our data is not truely 8bits per component
    505     png_color_8p sig_bit;
    506     if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) {
    507 #if 0
    508         SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green,
    509                  sig_bit->blue, sig_bit->alpha);
    510 #endif
    511         // 0 seems to indicate no information available
    512         if (pos_le(sig_bit->red, SK_R16_BITS) &&
    513             pos_le(sig_bit->green, SK_G16_BITS) &&
    514             pos_le(sig_bit->blue, SK_B16_BITS)) {
    515             this->setDitherImage(false);
    516         }
    517     }
    518 
    519     if (colorType == PNG_COLOR_TYPE_PALETTE) {
    520         bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
    521         *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha);
    522         // now see if we can upscale to their requested config
    523         if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) {
    524             *configp = SkBitmap::kIndex8_Config;
    525         }
    526     } else {
    527         png_color_16p transpColor = NULL;
    528         int numTransp = 0;
    529 
    530         png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor);
    531 
    532         bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
    533 
    534         if (valid && numTransp == 1 && transpColor != NULL) {
    535             /*  Compute our transparent color, which we'll match against later.
    536                 We don't really handle 16bit components properly here, since we
    537                 do our compare *after* the values have been knocked down to 8bit
    538                 which means we will find more matches than we should. The real
    539                 fix seems to be to see the actual 16bit components, do the
    540                 compare, and then knock it down to 8bits ourselves.
    541             */
    542             if (colorType & PNG_COLOR_MASK_COLOR) {
    543                 if (16 == bitDepth) {
    544                     *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8,
    545                                                     transpColor->green >> 8,
    546                                                     transpColor->blue >> 8);
    547                 } else {
    548                     /* We apply the mask because in a very small
    549                        number of corrupt PNGs, (transpColor->red > 255)
    550                        and (bitDepth == 8), for certain versions of libpng. */
    551                     *theTranspColorp = SkPackARGB32(0xFF,
    552                                                     0xFF & (transpColor->red),
    553                                                     0xFF & (transpColor->green),
    554                                                     0xFF & (transpColor->blue));
    555                 }
    556             } else {    // gray
    557                 if (16 == bitDepth) {
    558                     *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8,
    559                                                     transpColor->gray >> 8,
    560                                                     transpColor->gray >> 8);
    561                 } else {
    562                     /* We apply the mask because in a very small
    563                        number of corrupt PNGs, (transpColor->red >
    564                        255) and (bitDepth == 8), for certain versions
    565                        of libpng.  For safety we assume the same could
    566                        happen with a grayscale PNG.  */
    567                     *theTranspColorp = SkPackARGB32(0xFF,
    568                                                     0xFF & (transpColor->gray),
    569                                                     0xFF & (transpColor->gray),
    570                                                     0xFF & (transpColor->gray));
    571                 }
    572             }
    573         }
    574 
    575         if (valid ||
    576             PNG_COLOR_TYPE_RGB_ALPHA == colorType ||
    577             PNG_COLOR_TYPE_GRAY_ALPHA == colorType) {
    578             *hasAlphap = true;
    579         }
    580 
    581         SrcDepth srcDepth = k32Bit_SrcDepth;
    582         if (PNG_COLOR_TYPE_GRAY == colorType) {
    583             srcDepth = k8BitGray_SrcDepth;
    584             // Remove this assert, which fails on desk_pokemonwiki.skp
    585             //SkASSERT(!*hasAlphap);
    586         }
    587 
    588         *configp = this->getPrefConfig(srcDepth, *hasAlphap);
    589         // now match the request against our capabilities
    590         if (*hasAlphap) {
    591             if (*configp != SkBitmap::kARGB_4444_Config) {
    592                 *configp = SkBitmap::kARGB_8888_Config;
    593             }
    594         } else {
    595             if (SkBitmap::kA8_Config == *configp) {
    596                 if (k8BitGray_SrcDepth != srcDepth) {
    597                     // Converting a non grayscale image to A8 is not currently supported.
    598                     *configp = SkBitmap::kARGB_8888_Config;
    599                 }
    600             } else if (*configp != SkBitmap::kRGB_565_Config &&
    601                        *configp != SkBitmap::kARGB_4444_Config) {
    602                 *configp = SkBitmap::kARGB_8888_Config;
    603             }
    604         }
    605     }
    606 
    607     // sanity check for size
    608     {
    609         Sk64 size;
    610         size.setMul(origWidth, origHeight);
    611         if (size.isNeg() || !size.is32()) {
    612             return false;
    613         }
    614         // now check that if we are 4-bytes per pixel, we also don't overflow
    615         if (size.get32() > (0x7FFFFFFF >> 2)) {
    616             return false;
    617         }
    618     }
    619 
    620     if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) {
    621         return false;
    622     }
    623 
    624     // If the image has alpha and the decoder wants unpremultiplied
    625     // colors, the only supported config is 8888.
    626     if (this->getRequireUnpremultipliedColors() && *hasAlphap) {
    627         *configp = SkBitmap::kARGB_8888_Config;
    628     }
    629 
    630     if (fImageIndex != NULL) {
    631         if (SkBitmap::kNo_Config == fImageIndex->fConfig) {
    632             // This is the first time for this subset decode. From now on,
    633             // all decodes must be in the same config.
    634             fImageIndex->fConfig = *configp;
    635         } else if (fImageIndex->fConfig != *configp) {
    636             // Requesting a different config for a subsequent decode is not
    637             // supported. Report failure before we make changes to png_ptr.
    638             return false;
    639         }
    640     }
    641 
    642     bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType
    643                             && *configp != SkBitmap::kA8_Config;
    644 
    645     // Unless the user is requesting A8, convert a grayscale image into RGB.
    646     // GRAY_ALPHA will always be converted to RGB
    647     if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
    648         png_set_gray_to_rgb(png_ptr);
    649     }
    650 
    651     // Add filler (or alpha) byte (after each RGB triplet) if necessary.
    652     if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
    653         png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
    654     }
    655 
    656     return true;
    657 }
    658 
    659 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
    660 
    661 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
    662                                       bool *hasAlphap, bool *reallyHasAlphap,
    663                                       SkColorTable **colorTablep) {
    664     int numPalette;
    665     png_colorp palette;
    666     png_bytep trans;
    667     int numTrans;
    668 
    669     png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette);
    670 
    671     /*  BUGGY IMAGE WORKAROUND
    672 
    673         We hit some images (e.g. fruit_.png) who contain bytes that are == colortable_count
    674         which is a problem since we use the byte as an index. To work around this we grow
    675         the colortable by 1 (if its < 256) and duplicate the last color into that slot.
    676     */
    677     int colorCount = numPalette + (numPalette < 256);
    678     SkPMColor colorStorage[256];    // worst-case storage
    679     SkPMColor* colorPtr = colorStorage;
    680 
    681     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    682         png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL);
    683         *hasAlphap = (numTrans > 0);
    684     } else {
    685         numTrans = 0;
    686     }
    687 
    688     // check for bad images that might make us crash
    689     if (numTrans > numPalette) {
    690         numTrans = numPalette;
    691     }
    692 
    693     int index = 0;
    694     int transLessThanFF = 0;
    695 
    696     // Choose which function to use to create the color table. If the final destination's
    697     // config is unpremultiplied, the color table will store unpremultiplied colors.
    698     PackColorProc proc;
    699     if (this->getRequireUnpremultipliedColors()) {
    700         proc = &SkPackARGB32NoCheck;
    701     } else {
    702         proc = &SkPreMultiplyARGB;
    703     }
    704     for (; index < numTrans; index++) {
    705         transLessThanFF |= (int)*trans - 0xFF;
    706         *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue);
    707         palette++;
    708     }
    709     bool reallyHasAlpha = (transLessThanFF < 0);
    710 
    711     for (; index < numPalette; index++) {
    712         *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->blue);
    713         palette++;
    714     }
    715 
    716     // see BUGGY IMAGE WORKAROUND comment above
    717     if (numPalette < 256) {
    718         *colorPtr = colorPtr[-1];
    719     }
    720 
    721     SkAlphaType alphaType = kOpaque_SkAlphaType;
    722     if (reallyHasAlpha) {
    723         if (this->getRequireUnpremultipliedColors()) {
    724             alphaType = kUnpremul_SkAlphaType;
    725         } else {
    726             alphaType = kPremul_SkAlphaType;
    727         }
    728     }
    729 
    730     *colorTablep = SkNEW_ARGS(SkColorTable,
    731                               (colorStorage, colorCount, alphaType));
    732     *reallyHasAlphap = reallyHasAlpha;
    733     return true;
    734 }
    735 
    736 #ifdef SK_BUILD_FOR_ANDROID
    737 
    738 bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *width, int *height) {
    739     png_structp png_ptr;
    740     png_infop   info_ptr;
    741 
    742     if (!onDecodeInit(sk_stream, &png_ptr, &info_ptr)) {
    743         return false;
    744     }
    745 
    746     if (setjmp(png_jmpbuf(png_ptr)) != 0) {
    747         png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    748         return false;
    749     }
    750 
    751     png_uint_32 origWidth, origHeight;
    752     int bitDepth, colorType;
    753     png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
    754                  &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
    755 
    756     *width = origWidth;
    757     *height = origHeight;
    758 
    759     png_build_index(png_ptr);
    760 
    761     if (fImageIndex) {
    762         SkDELETE(fImageIndex);
    763     }
    764     fImageIndex = SkNEW_ARGS(SkPNGImageIndex, (sk_stream, png_ptr, info_ptr));
    765 
    766     return true;
    767 }
    768 
    769 bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
    770     if (NULL == fImageIndex) {
    771         return false;
    772     }
    773 
    774     png_structp png_ptr = fImageIndex->fPng_ptr;
    775     png_infop info_ptr = fImageIndex->fInfo_ptr;
    776     if (setjmp(png_jmpbuf(png_ptr))) {
    777         return false;
    778     }
    779 
    780     png_uint_32 origWidth, origHeight;
    781     int bitDepth, colorType, interlaceType;
    782     png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
    783                  &colorType, &interlaceType, int_p_NULL, int_p_NULL);
    784 
    785     SkIRect rect = SkIRect::MakeWH(origWidth, origHeight);
    786 
    787     if (!rect.intersect(region)) {
    788         // If the requested region is entirely outside the image, just
    789         // returns false
    790         return false;
    791     }
    792 
    793     SkBitmap::Config    config;
    794     bool                hasAlpha = false;
    795     SkPMColor           theTranspColor = 0; // 0 tells us not to try to match
    796 
    797     if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTranspColor)) {
    798         return false;
    799     }
    800 
    801     const int sampleSize = this->getSampleSize();
    802     SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize);
    803 
    804     SkBitmap decodedBitmap;
    805     decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
    806 
    807     // from here down we are concerned with colortables and pixels
    808 
    809     // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
    810     // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
    811     // draw lots faster if we can flag the bitmap has being opaque
    812     bool reallyHasAlpha = false;
    813     SkColorTable* colorTable = NULL;
    814 
    815     if (colorType == PNG_COLOR_TYPE_PALETTE) {
    816         decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable);
    817     }
    818 
    819     SkAutoUnref aur(colorTable);
    820 
    821     // Check ahead of time if the swap(dest, src) is possible.
    822     // If yes, then we will stick to AllocPixelRef since it's cheaper with the swap happening.
    823     // If no, then we will use alloc to allocate pixels to prevent garbage collection.
    824     int w = rect.width() / sampleSize;
    825     int h = rect.height() / sampleSize;
    826     const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) &&
    827                           (h == decodedBitmap.height()) && bm->isNull();
    828     const bool needColorTable = SkBitmap::kIndex8_Config == config;
    829     if (swapOnly) {
    830         if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : NULL)) {
    831             return false;
    832         }
    833     } else {
    834         if (!decodedBitmap.allocPixels(NULL, needColorTable ? colorTable : NULL)) {
    835             return false;
    836         }
    837     }
    838     SkAutoLockPixels alp(decodedBitmap);
    839 
    840     /* Turn on interlace handling.  REQUIRED if you are not using
    841     * png_read_image().  To see how to handle interlacing passes,
    842     * see the png_read_row() method below:
    843     */
    844     const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ?
    845                               png_set_interlace_handling(png_ptr) : 1;
    846 
    847     /* Optional call to gamma correct and add the background to the palette
    848     * and update info structure.  REQUIRED if you are expecting libpng to
    849     * update the palette for you (ie you selected such a transform above).
    850     */
    851 
    852     // Direct access to png_ptr fields is deprecated in libpng > 1.2.
    853 #if defined(PNG_1_0_X) || defined (PNG_1_2_X)
    854     png_ptr->pass = 0;
    855 #else
    856     // FIXME: This sets pass as desired, but also sets iwidth. Is that ok?
    857     png_set_interlaced_pass(png_ptr, 0);
    858 #endif
    859     png_read_update_info(png_ptr, info_ptr);
    860 
    861     int actualTop = rect.fTop;
    862 
    863     if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config)
    864         && 1 == sampleSize) {
    865         if (SkBitmap::kA8_Config == config) {
    866             // For an A8 bitmap, we assume there is an alpha for speed. It is
    867             // possible the bitmap is opaque, but that is an unlikely use case
    868             // since it would not be very interesting.
    869             reallyHasAlpha = true;
    870             // A8 is only allowed if the original was GRAY.
    871             SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
    872         }
    873 
    874         for (int i = 0; i < number_passes; i++) {
    875             png_configure_decoder(png_ptr, &actualTop, i);
    876             for (int j = 0; j < rect.fTop - actualTop; j++) {
    877                 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0);
    878                 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
    879             }
    880             png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height();
    881             for (png_uint_32 y = 0; y < bitmapHeight; y++) {
    882                 uint8_t* bmRow = decodedBitmap.getAddr8(0, y);
    883                 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
    884             }
    885         }
    886     } else {
    887         SkScaledBitmapSampler::SrcConfig sc;
    888         int srcBytesPerPixel = 4;
    889 
    890         if (colorTable != NULL) {
    891             sc = SkScaledBitmapSampler::kIndex;
    892             srcBytesPerPixel = 1;
    893         } else if (SkBitmap::kA8_Config == config) {
    894             // A8 is only allowed if the original was GRAY.
    895             SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
    896             sc = SkScaledBitmapSampler::kGray;
    897             srcBytesPerPixel = 1;
    898         } else if (hasAlpha) {
    899             sc = SkScaledBitmapSampler::kRGBA;
    900         } else {
    901             sc = SkScaledBitmapSampler::kRGBX;
    902         }
    903 
    904         /*  We have to pass the colortable explicitly, since we may have one
    905             even if our decodedBitmap doesn't, due to the request that we
    906             upscale png's palette to a direct model
    907          */
    908         SkAutoLockColors ctLock(colorTable);
    909         if (!sampler.begin(&decodedBitmap, sc, *this, ctLock.colors())) {
    910             return false;
    911         }
    912         const int height = decodedBitmap.height();
    913 
    914         if (number_passes > 1) {
    915             SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
    916             uint8_t* base = (uint8_t*)storage.get();
    917             size_t rb = origWidth * srcBytesPerPixel;
    918 
    919             for (int i = 0; i < number_passes; i++) {
    920                 png_configure_decoder(png_ptr, &actualTop, i);
    921                 for (int j = 0; j < rect.fTop - actualTop; j++) {
    922                     uint8_t* bmRow = (uint8_t*)decodedBitmap.getPixels();
    923                     png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
    924                 }
    925                 uint8_t* row = base;
    926                 for (int32_t y = 0; y < rect.height(); y++) {
    927                     uint8_t* bmRow = row;
    928                     png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
    929                     row += rb;
    930                 }
    931             }
    932             // now sample it
    933             base += sampler.srcY0() * rb;
    934             for (int y = 0; y < height; y++) {
    935                 reallyHasAlpha |= sampler.next(base);
    936                 base += sampler.srcDY() * rb;
    937             }
    938         } else {
    939             SkAutoMalloc storage(origWidth * srcBytesPerPixel);
    940             uint8_t* srcRow = (uint8_t*)storage.get();
    941 
    942             png_configure_decoder(png_ptr, &actualTop, 0);
    943             skip_src_rows(png_ptr, srcRow, sampler.srcY0());
    944 
    945             for (int i = 0; i < rect.fTop - actualTop; i++) {
    946                 uint8_t* bmRow = (uint8_t*)decodedBitmap.getPixels();
    947                 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
    948             }
    949             for (int y = 0; y < height; y++) {
    950                 uint8_t* tmp = srcRow;
    951                 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
    952                 reallyHasAlpha |= sampler.next(srcRow);
    953                 if (y < height - 1) {
    954                     skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
    955                 }
    956             }
    957         }
    958     }
    959 
    960     if (0 != theTranspColor) {
    961         reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor);
    962     }
    963     if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
    964         switch (decodedBitmap.config()) {
    965             case SkBitmap::kIndex8_Config:
    966                 // Fall through.
    967             case SkBitmap::kARGB_4444_Config:
    968                 // We have chosen not to support unpremul for these configs.
    969                 return false;
    970             default: {
    971                 // Fall through to finish the decode. This config either
    972                 // supports unpremul or it is irrelevant because it has no
    973                 // alpha (or only alpha).
    974                 // These brackets prevent a warning.
    975             }
    976         }
    977     }
    978     SkAlphaType alphaType = kOpaque_SkAlphaType;
    979     if (reallyHasAlpha) {
    980         if (this->getRequireUnpremultipliedColors()) {
    981             alphaType = kUnpremul_SkAlphaType;
    982         } else {
    983             alphaType = kPremul_SkAlphaType;
    984         }
    985     }
    986     decodedBitmap.setAlphaType(alphaType);
    987 
    988     if (swapOnly) {
    989         bm->swap(decodedBitmap);
    990         return true;
    991     }
    992     return this->cropBitmap(bm, &decodedBitmap, sampleSize, region.x(), region.y(),
    993                             region.width(), region.height(), 0, rect.y());
    994 }
    995 #endif
    996 
    997 ///////////////////////////////////////////////////////////////////////////////
    998 
    999 #include "SkColorPriv.h"
   1000 #include "SkUnPreMultiply.h"
   1001 
   1002 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
   1003     SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
   1004     if (!sk_stream->write(data, len)) {
   1005         png_error(png_ptr, "sk_write_fn Error!");
   1006     }
   1007 }
   1008 
   1009 static transform_scanline_proc choose_proc(SkBitmap::Config config,
   1010                                            bool hasAlpha) {
   1011     // we don't care about search on alpha if we're kIndex8, since only the
   1012     // colortable packing cares about that distinction, not the pixels
   1013     if (SkBitmap::kIndex8_Config == config) {
   1014         hasAlpha = false;   // we store false in the table entries for kIndex8
   1015     }
   1016 
   1017     static const struct {
   1018         SkBitmap::Config        fConfig;
   1019         bool                    fHasAlpha;
   1020         transform_scanline_proc fProc;
   1021     } gMap[] = {
   1022         { SkBitmap::kRGB_565_Config,    false,  transform_scanline_565 },
   1023         { SkBitmap::kARGB_8888_Config,  false,  transform_scanline_888 },
   1024         { SkBitmap::kARGB_8888_Config,  true,   transform_scanline_8888 },
   1025         { SkBitmap::kARGB_4444_Config,  false,  transform_scanline_444 },
   1026         { SkBitmap::kARGB_4444_Config,  true,   transform_scanline_4444 },
   1027         { SkBitmap::kIndex8_Config,     false,  transform_scanline_memcpy },
   1028     };
   1029 
   1030     for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) {
   1031         if (gMap[i].fConfig == config && gMap[i].fHasAlpha == hasAlpha) {
   1032             return gMap[i].fProc;
   1033         }
   1034     }
   1035     sk_throw();
   1036     return NULL;
   1037 }
   1038 
   1039 // return the minimum legal bitdepth (by png standards) for this many colortable
   1040 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16,
   1041 // we can use fewer bits per in png
   1042 static int computeBitDepth(int colorCount) {
   1043 #if 0
   1044     int bits = SkNextLog2(colorCount);
   1045     SkASSERT(bits >= 1 && bits <= 8);
   1046     // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8)
   1047     return SkNextPow2(bits);
   1048 #else
   1049     // for the moment, we don't know how to pack bitdepth < 8
   1050     return 8;
   1051 #endif
   1052 }
   1053 
   1054 /*  Pack palette[] with the corresponding colors, and if hasAlpha is true, also
   1055     pack trans[] and return the number of trans[] entries written. If hasAlpha
   1056     is false, the return value will always be 0.
   1057 
   1058     Note: this routine takes care of unpremultiplying the RGB values when we
   1059     have alpha in the colortable, since png doesn't support premul colors
   1060 */
   1061 static inline int pack_palette(SkColorTable* ctable,
   1062                                png_color* SK_RESTRICT palette,
   1063                                png_byte* SK_RESTRICT trans, bool hasAlpha) {
   1064     SkAutoLockColors alc(ctable);
   1065     const SkPMColor* SK_RESTRICT colors = alc.colors();
   1066     const int ctCount = ctable->count();
   1067     int i, num_trans = 0;
   1068 
   1069     if (hasAlpha) {
   1070         /*  first see if we have some number of fully opaque at the end of the
   1071             ctable. PNG allows num_trans < num_palette, but all of the trans
   1072             entries must come first in the palette. If I was smarter, I'd
   1073             reorder the indices and ctable so that all non-opaque colors came
   1074             first in the palette. But, since that would slow down the encode,
   1075             I'm leaving the indices and ctable order as is, and just looking
   1076             at the tail of the ctable for opaqueness.
   1077         */
   1078         num_trans = ctCount;
   1079         for (i = ctCount - 1; i >= 0; --i) {
   1080             if (SkGetPackedA32(colors[i]) != 0xFF) {
   1081                 break;
   1082             }
   1083             num_trans -= 1;
   1084         }
   1085 
   1086         const SkUnPreMultiply::Scale* SK_RESTRICT table =
   1087                                             SkUnPreMultiply::GetScaleTable();
   1088 
   1089         for (i = 0; i < num_trans; i++) {
   1090             const SkPMColor c = *colors++;
   1091             const unsigned a = SkGetPackedA32(c);
   1092             const SkUnPreMultiply::Scale s = table[a];
   1093             trans[i] = a;
   1094             palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c));
   1095             palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32(c));
   1096             palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c));
   1097         }
   1098         // now fall out of this if-block to use common code for the trailing
   1099         // opaque entries
   1100     }
   1101 
   1102     // these (remaining) entries are opaque
   1103     for (i = num_trans; i < ctCount; i++) {
   1104         SkPMColor c = *colors++;
   1105         palette[i].red = SkGetPackedR32(c);
   1106         palette[i].green = SkGetPackedG32(c);
   1107         palette[i].blue = SkGetPackedB32(c);
   1108     }
   1109     return num_trans;
   1110 }
   1111 
   1112 class SkPNGImageEncoder : public SkImageEncoder {
   1113 protected:
   1114     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK_OVERRIDE;
   1115 private:
   1116     bool doEncode(SkWStream* stream, const SkBitmap& bm,
   1117                   const bool& hasAlpha, int colorType,
   1118                   int bitDepth, SkBitmap::Config config,
   1119                   png_color_8& sig_bit);
   1120 
   1121     typedef SkImageEncoder INHERITED;
   1122 };
   1123 
   1124 bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap,
   1125                                  int /*quality*/) {
   1126     SkBitmap::Config config = bitmap.config();
   1127 
   1128     const bool hasAlpha = !bitmap.isOpaque();
   1129     int colorType = PNG_COLOR_MASK_COLOR;
   1130     int bitDepth = 8;   // default for color
   1131     png_color_8 sig_bit;
   1132 
   1133     switch (config) {
   1134         case SkBitmap::kIndex8_Config:
   1135             colorType |= PNG_COLOR_MASK_PALETTE;
   1136             // fall through to the ARGB_8888 case
   1137         case SkBitmap::kARGB_8888_Config:
   1138             sig_bit.red = 8;
   1139             sig_bit.green = 8;
   1140             sig_bit.blue = 8;
   1141             sig_bit.alpha = 8;
   1142             break;
   1143         case SkBitmap::kARGB_4444_Config:
   1144             sig_bit.red = 4;
   1145             sig_bit.green = 4;
   1146             sig_bit.blue = 4;
   1147             sig_bit.alpha = 4;
   1148             break;
   1149         case SkBitmap::kRGB_565_Config:
   1150             sig_bit.red = 5;
   1151             sig_bit.green = 6;
   1152             sig_bit.blue = 5;
   1153             sig_bit.alpha = 0;
   1154             break;
   1155         default:
   1156             return false;
   1157     }
   1158 
   1159     if (hasAlpha) {
   1160         // don't specify alpha if we're a palette, even if our ctable has alpha
   1161         if (!(colorType & PNG_COLOR_MASK_PALETTE)) {
   1162             colorType |= PNG_COLOR_MASK_ALPHA;
   1163         }
   1164     } else {
   1165         sig_bit.alpha = 0;
   1166     }
   1167 
   1168     SkAutoLockPixels alp(bitmap);
   1169     // readyToDraw checks for pixels (and colortable if that is required)
   1170     if (!bitmap.readyToDraw()) {
   1171         return false;
   1172     }
   1173 
   1174     // we must do this after we have locked the pixels
   1175     SkColorTable* ctable = bitmap.getColorTable();
   1176     if (NULL != ctable) {
   1177         if (ctable->count() == 0) {
   1178             return false;
   1179         }
   1180         // check if we can store in fewer than 8 bits
   1181         bitDepth = computeBitDepth(ctable->count());
   1182     }
   1183 
   1184     return doEncode(stream, bitmap, hasAlpha, colorType,
   1185                     bitDepth, config, sig_bit);
   1186 }
   1187 
   1188 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap,
   1189                   const bool& hasAlpha, int colorType,
   1190                   int bitDepth, SkBitmap::Config config,
   1191                   png_color_8& sig_bit) {
   1192 
   1193     png_structp png_ptr;
   1194     png_infop info_ptr;
   1195 
   1196     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn,
   1197                                       NULL);
   1198     if (NULL == png_ptr) {
   1199         return false;
   1200     }
   1201 
   1202     info_ptr = png_create_info_struct(png_ptr);
   1203     if (NULL == info_ptr) {
   1204         png_destroy_write_struct(&png_ptr,  png_infopp_NULL);
   1205         return false;
   1206     }
   1207 
   1208     /* Set error handling.  REQUIRED if you aren't supplying your own
   1209     * error handling functions in the png_create_write_struct() call.
   1210     */
   1211     if (setjmp(png_jmpbuf(png_ptr))) {
   1212         png_destroy_write_struct(&png_ptr, &info_ptr);
   1213         return false;
   1214     }
   1215 
   1216     png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, png_flush_ptr_NULL);
   1217 
   1218     /* Set the image information here.  Width and height are up to 2^31,
   1219     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
   1220     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
   1221     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
   1222     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
   1223     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
   1224     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
   1225     */
   1226 
   1227     png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(),
   1228                  bitDepth, colorType,
   1229                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
   1230                  PNG_FILTER_TYPE_BASE);
   1231 
   1232     // set our colortable/trans arrays if needed
   1233     png_color paletteColors[256];
   1234     png_byte trans[256];
   1235     if (SkBitmap::kIndex8_Config == config) {
   1236         SkColorTable* ct = bitmap.getColorTable();
   1237         int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha);
   1238         png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count());
   1239         if (numTrans > 0) {
   1240             png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL);
   1241         }
   1242     }
   1243 
   1244     png_set_sBIT(png_ptr, info_ptr, &sig_bit);
   1245     png_write_info(png_ptr, info_ptr);
   1246 
   1247     const char* srcImage = (const char*)bitmap.getPixels();
   1248     SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2);
   1249     char* storage = (char*)rowStorage.get();
   1250     transform_scanline_proc proc = choose_proc(config, hasAlpha);
   1251 
   1252     for (int y = 0; y < bitmap.height(); y++) {
   1253         png_bytep row_ptr = (png_bytep)storage;
   1254         proc(srcImage, bitmap.width(), storage);
   1255         png_write_rows(png_ptr, &row_ptr, 1);
   1256         srcImage += bitmap.rowBytes();
   1257     }
   1258 
   1259     png_write_end(png_ptr, info_ptr);
   1260 
   1261     /* clean up after the write, and free any memory allocated */
   1262     png_destroy_write_struct(&png_ptr, &info_ptr);
   1263     return true;
   1264 }
   1265 
   1266 ///////////////////////////////////////////////////////////////////////////////
   1267 DEFINE_DECODER_CREATOR(PNGImageDecoder);
   1268 DEFINE_ENCODER_CREATOR(PNGImageEncoder);
   1269 ///////////////////////////////////////////////////////////////////////////////
   1270 
   1271 static bool is_png(SkStreamRewindable* stream) {
   1272     char buf[PNG_BYTES_TO_CHECK];
   1273     if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
   1274         !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
   1275         return true;
   1276     }
   1277     return false;
   1278 }
   1279 
   1280 SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) {
   1281     if (is_png(stream)) {
   1282         return SkNEW(SkPNGImageDecoder);
   1283     }
   1284     return NULL;
   1285 }
   1286 
   1287 static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) {
   1288     if (is_png(stream)) {
   1289         return SkImageDecoder::kPNG_Format;
   1290     }
   1291     return SkImageDecoder::kUnknown_Format;
   1292 }
   1293 
   1294 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
   1295     return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
   1296 }
   1297 
   1298 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory);
   1299 static SkImageDecoder_FormatReg gFormatReg(get_format_png);
   1300 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory);
   1301