| Index: src/images/SkImageDecoder_libpng.cpp
|
| diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
|
| index d59a67bf8ef8090e4268de40a788c04086e7d087..4c44b9109caadc6deba3cbea737c15239dbf7aff 100644
|
| --- a/src/images/SkImageDecoder_libpng.cpp
|
| +++ b/src/images/SkImageDecoder_libpng.cpp
|
| @@ -42,18 +42,24 @@ extern "C" {
|
|
|
| class SkPNGImageIndex {
|
| public:
|
| - SkPNGImageIndex(png_structp png_ptr, png_infop info_ptr) {
|
| - this->png_ptr = png_ptr;
|
| - this->info_ptr = info_ptr;
|
| + SkPNGImageIndex(SkStream* stream, png_structp png_ptr, png_infop info_ptr)
|
| + : fStream(stream)
|
| + , fPng_ptr(png_ptr)
|
| + , fInfo_ptr(info_ptr)
|
| + , fConfig(SkBitmap::kNo_Config) {
|
| + SkASSERT(stream != NULL);
|
| + stream->ref();
|
| }
|
| ~SkPNGImageIndex() {
|
| - if (NULL != png_ptr) {
|
| - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
| + if (NULL != fPng_ptr) {
|
| + png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
|
| }
|
| }
|
|
|
| - png_structp png_ptr;
|
| - png_infop info_ptr;
|
| + SkAutoTUnref<SkStream> fStream;
|
| + png_structp fPng_ptr;
|
| + png_infop fInfo_ptr;
|
| + SkBitmap::Config fConfig;
|
| };
|
|
|
| class SkPNGImageDecoder : public SkImageDecoder {
|
| @@ -261,10 +267,6 @@ bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp,
|
| png_set_expand_gray_1_2_4_to_8(png_ptr);
|
| }
|
|
|
| - /* Make a grayscale image into RGB. */
|
| - if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
| - png_set_gray_to_rgb(png_ptr);
|
| - }
|
| return true;
|
| }
|
|
|
| @@ -326,11 +328,6 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
|
|
|
| SkAutoLockPixels alp(*decodedBitmap);
|
|
|
| - /* Add filler (or alpha) byte (before/after each RGB triplet) */
|
| - if (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_GRAY) {
|
| - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
| - }
|
| -
|
| /* Turn on interlace handling. REQUIRED if you are not using
|
| * png_read_image(). To see how to handle interlacing passes,
|
| * see the png_read_row() method below:
|
| @@ -344,7 +341,11 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
|
| */
|
| png_read_update_info(png_ptr, info_ptr);
|
|
|
| - if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
|
| + if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config)
|
| + && 1 == sampleSize) {
|
| + // A8 is only allowed if the original was GRAY.
|
| + SkASSERT(config != SkBitmap::kA8_Config
|
| + || PNG_COLOR_TYPE_GRAY == colorType);
|
| for (int i = 0; i < number_passes; i++) {
|
| for (png_uint_32 y = 0; y < origHeight; y++) {
|
| uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
|
| @@ -358,6 +359,11 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
|
| if (colorTable != NULL) {
|
| sc = SkScaledBitmapSampler::kIndex;
|
| srcBytesPerPixel = 1;
|
| + } else if (SkBitmap::kA8_Config == config) {
|
| + // A8 is only allowed if the original was GRAY.
|
| + SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
|
| + sc = SkScaledBitmapSampler::kGray;
|
| + srcBytesPerPixel = 1;
|
| } else if (hasAlpha) {
|
| sc = SkScaledBitmapSampler::kRGBA;
|
| } else {
|
| @@ -436,8 +442,10 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
|
|
|
|
|
| bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
|
| - SkBitmap::Config *configp, bool * SK_RESTRICT hasAlphap,
|
| - bool *doDitherp, SkPMColor *theTranspColorp) {
|
| + SkBitmap::Config* SK_RESTRICT configp,
|
| + bool* SK_RESTRICT hasAlphap,
|
| + bool* SK_RESTRICT doDitherp,
|
| + SkPMColor* SK_RESTRICT theTranspColorp) {
|
| png_uint_32 origWidth, origHeight;
|
| int bitDepth, colorType;
|
| png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
|
| @@ -510,7 +518,14 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
|
| PNG_COLOR_TYPE_GRAY_ALPHA == colorType) {
|
| *hasAlphap = true;
|
| }
|
| - *configp = this->getPrefConfig(k32Bit_SrcDepth, *hasAlphap);
|
| +
|
| + SrcDepth srcDepth = k32Bit_SrcDepth;
|
| + if (PNG_COLOR_TYPE_GRAY == colorType) {
|
| + srcDepth = k8BitGray_SrcDepth;
|
| + SkASSERT(!*hasAlphap);
|
| + }
|
| +
|
| + *configp = this->getPrefConfig(srcDepth, *hasAlphap);
|
| // now match the request against our capabilities
|
| if (*hasAlphap) {
|
| if (*configp != SkBitmap::kARGB_4444_Config) {
|
| @@ -518,7 +533,8 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
|
| }
|
| } else {
|
| if (*configp != SkBitmap::kRGB_565_Config &&
|
| - *configp != SkBitmap::kARGB_4444_Config) {
|
| + *configp != SkBitmap::kARGB_4444_Config &&
|
| + *configp != SkBitmap::kA8_Config) {
|
| *configp = SkBitmap::kARGB_8888_Config;
|
| }
|
| }
|
| @@ -546,6 +562,33 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
|
| if (this->getRequireUnpremultipliedColors() && *hasAlphap) {
|
| *configp = SkBitmap::kARGB_8888_Config;
|
| }
|
| +
|
| + if (fImageIndex != NULL) {
|
| + if (SkBitmap::kNo_Config == fImageIndex->fConfig) {
|
| + // This is the first time for this subset decode. From now on,
|
| + // all decodes must be in the same config.
|
| + fImageIndex->fConfig = *configp;
|
| + } else if (fImageIndex->fConfig != *configp) {
|
| + // Requesting a different config for a subsequent decode is not
|
| + // supported. Report failure before we make changes to png_ptr.
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType
|
| + && *configp != SkBitmap::kA8_Config;
|
| +
|
| + // Unless the user is requesting A8, convert a grayscale image into RGB.
|
| + // GRAY_ALPHA will always be converted to RGB
|
| + if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
| + png_set_gray_to_rgb(png_ptr);
|
| + }
|
| +
|
| + // Add filler (or alpha) byte (after each RGB triplet) if necessary.
|
| + if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
|
| + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
| + }
|
| +
|
| return true;
|
| }
|
|
|
| @@ -647,7 +690,7 @@ bool SkPNGImageDecoder::onBuildTileIndex(SkStream* sk_stream, int *width, int *h
|
| if (fImageIndex) {
|
| SkDELETE(fImageIndex);
|
| }
|
| - fImageIndex = SkNEW_ARGS(SkPNGImageIndex, (png_ptr, info_ptr));
|
| + fImageIndex = SkNEW_ARGS(SkPNGImageIndex, (sk_stream, png_ptr, info_ptr));
|
|
|
| return true;
|
| }
|
| @@ -657,8 +700,8 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
|
| return false;
|
| }
|
|
|
| - png_structp png_ptr = fImageIndex->png_ptr;
|
| - png_infop info_ptr = fImageIndex->info_ptr;
|
| + png_structp png_ptr = fImageIndex->fPng_ptr;
|
| + png_infop info_ptr = fImageIndex->fInfo_ptr;
|
| if (setjmp(png_jmpbuf(png_ptr))) {
|
| return false;
|
| }
|
| @@ -724,11 +767,6 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
|
| }
|
| SkAutoLockPixels alp(decodedBitmap);
|
|
|
| - /* Add filler (or alpha) byte (before/after each RGB triplet) */
|
| - if (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_GRAY) {
|
| - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
| - }
|
| -
|
| /* Turn on interlace handling. REQUIRED if you are not using
|
| * png_read_image(). To see how to handle interlacing passes,
|
| * see the png_read_row() method below:
|
| @@ -752,7 +790,12 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
|
|
|
| int actualTop = rect.fTop;
|
|
|
| - if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
|
| + if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config)
|
| + && 1 == sampleSize) {
|
| + // A8 is only allowed if the original was GRAY.
|
| + SkASSERT(config != SkBitmap::kA8_Config
|
| + || PNG_COLOR_TYPE_GRAY == colorType);
|
| +
|
| for (int i = 0; i < number_passes; i++) {
|
| png_configure_decoder(png_ptr, &actualTop, i);
|
| for (int j = 0; j < rect.fTop - actualTop; j++) {
|
| @@ -772,6 +815,11 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
|
| if (colorTable != NULL) {
|
| sc = SkScaledBitmapSampler::kIndex;
|
| srcBytesPerPixel = 1;
|
| + } else if (SkBitmap::kA8_Config == config) {
|
| + // A8 is only allowed if the original was GRAY.
|
| + SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
|
| + sc = SkScaledBitmapSampler::kGray;
|
| + srcBytesPerPixel = 1;
|
| } else if (hasAlpha) {
|
| sc = SkScaledBitmapSampler::kRGBA;
|
| } else {
|
|
|