| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkImageDecoder.h" | 8 #include "SkImageDecoder.h" |
| 9 #include "SkImageEncoder.h" | 9 #include "SkImageEncoder.h" |
| 10 #include "SkColor.h" | 10 #include "SkColor.h" |
| 11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
| 12 #include "SkDither.h" | 12 #include "SkDither.h" |
| 13 #include "SkMath.h" | 13 #include "SkMath.h" |
| 14 #include "SkRTConf.h" | 14 #include "SkRTConf.h" |
| 15 #include "SkScaledBitmapSampler.h" | 15 #include "SkScaledBitmapSampler.h" |
| 16 #include "SkStream.h" | 16 #include "SkStream.h" |
| 17 #include "SkTemplates.h" | 17 #include "SkTemplates.h" |
| 18 #include "SkUtils.h" | 18 #include "SkUtils.h" |
| 19 #include "transform_scanline.h" | 19 #include "transform_scanline.h" |
| 20 | 20 |
| 21 #ifdef SKIA_PNG_PREFIXED | 21 #ifdef SKIA_PNG_PREFIXED |
| 22 // this must proceed png.h | 22 // this must proceed png.h |
| 23 #include "pngprefix.h" | 23 #include "pngprefix.h" |
| 24 #endif | 24 #endif |
| 25 #include "png.h" | 25 #include "png.h" |
| 26 | 26 |
| 27 /* These were dropped in libpng >= 1.4 */ | 27 /* These were dropped in libpng >= 1.4 */ |
| 28 #ifndef png_infopp_NULL | 28 #ifndef png_infopp_NULL |
| 29 #define png_infopp_NULL NULL | 29 #define png_infopp_NULL nullptr |
| 30 #endif | 30 #endif |
| 31 | 31 |
| 32 #ifndef png_bytepp_NULL | 32 #ifndef png_bytepp_NULL |
| 33 #define png_bytepp_NULL NULL | 33 #define png_bytepp_NULL nullptr |
| 34 #endif | 34 #endif |
| 35 | 35 |
| 36 #ifndef int_p_NULL | 36 #ifndef int_p_NULL |
| 37 #define int_p_NULL NULL | 37 #define int_p_NULL nullptr |
| 38 #endif | 38 #endif |
| 39 | 39 |
| 40 #ifndef png_flush_ptr_NULL | 40 #ifndef png_flush_ptr_NULL |
| 41 #define png_flush_ptr_NULL NULL | 41 #define png_flush_ptr_NULL nullptr |
| 42 #endif | 42 #endif |
| 43 | 43 |
| 44 #if defined(SK_DEBUG) | 44 #if defined(SK_DEBUG) |
| 45 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS false | 45 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS false |
| 46 #else // !defined(SK_DEBUG) | 46 #else // !defined(SK_DEBUG) |
| 47 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true | 47 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true |
| 48 #endif // defined(SK_DEBUG) | 48 #endif // defined(SK_DEBUG) |
| 49 SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings, | 49 SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings, |
| 50 "images.png.suppressDecoderWarnings", | 50 "images.png.suppressDecoderWarnings", |
| 51 DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS, | 51 DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS, |
| 52 "Suppress most PNG warnings when calling image decode " | 52 "Suppress most PNG warnings when calling image decode " |
| 53 "functions."); | 53 "functions."); |
| 54 | 54 |
| 55 | 55 |
| 56 | 56 |
| 57 class SkPNGImageIndex { | 57 class SkPNGImageIndex { |
| 58 public: | 58 public: |
| 59 // Takes ownership of stream. | 59 // Takes ownership of stream. |
| 60 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i
nfo_ptr) | 60 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i
nfo_ptr) |
| 61 : fStream(stream) | 61 : fStream(stream) |
| 62 , fPng_ptr(png_ptr) | 62 , fPng_ptr(png_ptr) |
| 63 , fInfo_ptr(info_ptr) | 63 , fInfo_ptr(info_ptr) |
| 64 , fColorType(kUnknown_SkColorType) { | 64 , fColorType(kUnknown_SkColorType) { |
| 65 SkASSERT(stream != NULL); | 65 SkASSERT(stream != nullptr); |
| 66 } | 66 } |
| 67 ~SkPNGImageIndex() { | 67 ~SkPNGImageIndex() { |
| 68 if (fPng_ptr) { | 68 if (fPng_ptr) { |
| 69 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); | 69 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); |
| 70 } | 70 } |
| 71 } | 71 } |
| 72 | 72 |
| 73 SkAutoTDelete<SkStreamRewindable> fStream; | 73 SkAutoTDelete<SkStreamRewindable> fStream; |
| 74 png_structp fPng_ptr; | 74 png_structp fPng_ptr; |
| 75 png_infop fInfo_ptr; | 75 png_infop fInfo_ptr; |
| 76 SkColorType fColorType; | 76 SkColorType fColorType; |
| 77 }; | 77 }; |
| 78 | 78 |
| 79 class SkPNGImageDecoder : public SkImageDecoder { | 79 class SkPNGImageDecoder : public SkImageDecoder { |
| 80 public: | 80 public: |
| 81 SkPNGImageDecoder() { | 81 SkPNGImageDecoder() { |
| 82 fImageIndex = NULL; | 82 fImageIndex = nullptr; |
| 83 } | 83 } |
| 84 Format getFormat() const override { | 84 Format getFormat() const override { |
| 85 return kPNG_Format; | 85 return kPNG_Format; |
| 86 } | 86 } |
| 87 | 87 |
| 88 virtual ~SkPNGImageDecoder() { delete fImageIndex; } | 88 virtual ~SkPNGImageDecoder() { delete fImageIndex; } |
| 89 | 89 |
| 90 protected: | 90 protected: |
| 91 #ifdef SK_BUILD_FOR_ANDROID | 91 #ifdef SK_BUILD_FOR_ANDROID |
| 92 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) o
verride; | 92 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) o
verride; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 return false; | 198 return false; |
| 199 } | 199 } |
| 200 } | 200 } |
| 201 | 201 |
| 202 // call only if color_type is PALETTE. Returns true if the ctable has alpha | 202 // call only if color_type is PALETTE. Returns true if the ctable has alpha |
| 203 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) { | 203 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) { |
| 204 png_bytep trans; | 204 png_bytep trans; |
| 205 int num_trans; | 205 int num_trans; |
| 206 | 206 |
| 207 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { | 207 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
| 208 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); | 208 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, nullptr); |
| 209 return num_trans > 0; | 209 return num_trans > 0; |
| 210 } | 210 } |
| 211 return false; | 211 return false; |
| 212 } | 212 } |
| 213 | 213 |
| 214 void do_nothing_warning_fn(png_structp, png_const_charp) { | 214 void do_nothing_warning_fn(png_structp, png_const_charp) { |
| 215 /* do nothing */ | 215 /* do nothing */ |
| 216 } | 216 } |
| 217 | 217 |
| 218 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp, | 218 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp, |
| 219 png_infop *info_ptrp) { | 219 png_infop *info_ptrp) { |
| 220 /* Create and initialize the png_struct with the desired error handler | 220 /* Create and initialize the png_struct with the desired error handler |
| 221 * functions. If you want to use the default stderr and longjump method, | 221 * functions. If you want to use the default stderr and longjump method, |
| 222 * you can supply NULL for the last three parameters. We also supply the | 222 * you can supply nullptr for the last three parameters. We also supply the |
| 223 * the compiler header file version, so that we know if the application | 223 * the compiler header file version, so that we know if the application |
| 224 * was compiled with a compatible version of the library. */ | 224 * was compiled with a compatible version of the library. */ |
| 225 | 225 |
| 226 png_error_ptr user_warning_fn = | 226 png_error_ptr user_warning_fn = |
| 227 (c_suppressPNGImageDecoderWarnings) ? (&do_nothing_warning_fn) : NULL; | 227 (c_suppressPNGImageDecoderWarnings) ? (&do_nothing_warning_fn) : nullptr
; |
| 228 /* NULL means to leave as default library behavior. */ | 228 /* nullptr means to leave as default library behavior. */ |
| 229 /* c_suppressPNGImageDecoderWarnings default depends on SK_DEBUG. */ | 229 /* c_suppressPNGImageDecoderWarnings default depends on SK_DEBUG. */ |
| 230 /* To suppress warnings with a SK_DEBUG binary, set the | 230 /* To suppress warnings with a SK_DEBUG binary, set the |
| 231 * environment variable "skia_images_png_suppressDecoderWarnings" | 231 * environment variable "skia_images_png_suppressDecoderWarnings" |
| 232 * to "true". Inside a program that links to skia: | 232 * to "true". Inside a program that links to skia: |
| 233 * SK_CONF_SET("images.png.suppressDecoderWarnings", true); */ | 233 * SK_CONF_SET("images.png.suppressDecoderWarnings", true); */ |
| 234 | 234 |
| 235 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, | 235 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, |
| 236 NULL, sk_error_fn, user_warning_fn); | 236 nullptr, sk_error_fn, user_warning_fn); |
| 237 // png_voidp user_error_ptr, user_error_fn, user_warning_fn); | 237 // png_voidp user_error_ptr, user_error_fn, user_warning_fn); |
| 238 if (png_ptr == NULL) { | 238 if (png_ptr == nullptr) { |
| 239 return false; | 239 return false; |
| 240 } | 240 } |
| 241 | 241 |
| 242 *png_ptrp = png_ptr; | 242 *png_ptrp = png_ptr; |
| 243 | 243 |
| 244 /* Allocate/initialize the memory for image information. */ | 244 /* Allocate/initialize the memory for image information. */ |
| 245 png_infop info_ptr = png_create_info_struct(png_ptr); | 245 png_infop info_ptr = png_create_info_struct(png_ptr); |
| 246 if (info_ptr == NULL) { | 246 if (info_ptr == nullptr) { |
| 247 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); | 247 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); |
| 248 return false; | 248 return false; |
| 249 } | 249 } |
| 250 *info_ptrp = info_ptr; | 250 *info_ptrp = info_ptr; |
| 251 | 251 |
| 252 /* Set error handling if you are using the setjmp/longjmp method (this is | 252 /* Set error handling if you are using the setjmp/longjmp method (this is |
| 253 * the normal method of doing things with libpng). REQUIRED unless you | 253 * the normal method of doing things with libpng). REQUIRED unless you |
| 254 * set up your own error handlers in the png_create_read_struct() earlier. | 254 * set up your own error handlers in the png_create_read_struct() earlier. |
| 255 */ | 255 */ |
| 256 if (setjmp(png_jmpbuf(png_ptr))) { | 256 if (setjmp(png_jmpbuf(png_ptr))) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 341 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
| 342 return kSuccess; | 342 return kSuccess; |
| 343 } | 343 } |
| 344 | 344 |
| 345 // from here down we are concerned with colortables and pixels | 345 // from here down we are concerned with colortables and pixels |
| 346 | 346 |
| 347 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 347 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype |
| 348 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we | 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 | 349 // draw lots faster if we can flag the bitmap has being opaque |
| 350 bool reallyHasAlpha = false; | 350 bool reallyHasAlpha = false; |
| 351 SkColorTable* colorTable = NULL; | 351 SkColorTable* colorTable = nullptr; |
| 352 | 352 |
| 353 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { | 353 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { |
| 354 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); | 354 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); |
| 355 } | 355 } |
| 356 | 356 |
| 357 SkAutoUnref aur(colorTable); | 357 SkAutoUnref aur(colorTable); |
| 358 | 358 |
| 359 if (!this->allocPixelRef(decodedBitmap, | 359 if (!this->allocPixelRef(decodedBitmap, |
| 360 kIndex_8_SkColorType == colorType ? colorTable : NU
LL)) { | 360 kIndex_8_SkColorType == colorType ? colorTable : nu
llptr)) { |
| 361 return kFailure; | 361 return kFailure; |
| 362 } | 362 } |
| 363 | 363 |
| 364 SkAutoLockPixels alp(*decodedBitmap); | 364 SkAutoLockPixels alp(*decodedBitmap); |
| 365 | 365 |
| 366 // Repeat setjmp, otherwise variables declared since the last call (e.g. alp | 366 // Repeat setjmp, otherwise variables declared since the last call (e.g. alp |
| 367 // and aur) won't get their destructors called in case of a failure. | 367 // and aur) won't get their destructors called in case of a failure. |
| 368 if (setjmp(png_jmpbuf(png_ptr))) { | 368 if (setjmp(png_jmpbuf(png_ptr))) { |
| 369 return kFailure; | 369 return kFailure; |
| 370 } | 370 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 395 for (int i = 0; i < number_passes; i++) { | 395 for (int i = 0; i < number_passes; i++) { |
| 396 for (png_uint_32 y = 0; y < origHeight; y++) { | 396 for (png_uint_32 y = 0; y < origHeight; y++) { |
| 397 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); | 397 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); |
| 398 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | 398 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); |
| 399 } | 399 } |
| 400 } | 400 } |
| 401 } else { | 401 } else { |
| 402 SkScaledBitmapSampler::SrcConfig sc; | 402 SkScaledBitmapSampler::SrcConfig sc; |
| 403 int srcBytesPerPixel = 4; | 403 int srcBytesPerPixel = 4; |
| 404 | 404 |
| 405 if (colorTable != NULL) { | 405 if (colorTable != nullptr) { |
| 406 sc = SkScaledBitmapSampler::kIndex; | 406 sc = SkScaledBitmapSampler::kIndex; |
| 407 srcBytesPerPixel = 1; | 407 srcBytesPerPixel = 1; |
| 408 } else if (kAlpha_8_SkColorType == colorType) { | 408 } else if (kAlpha_8_SkColorType == colorType) { |
| 409 // A8 is only allowed if the original was GRAY. | 409 // A8 is only allowed if the original was GRAY. |
| 410 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); | 410 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); |
| 411 sc = SkScaledBitmapSampler::kGray; | 411 sc = SkScaledBitmapSampler::kGray; |
| 412 srcBytesPerPixel = 1; | 412 srcBytesPerPixel = 1; |
| 413 } else if (hasAlpha) { | 413 } else if (hasAlpha) { |
| 414 sc = SkScaledBitmapSampler::kRGBA; | 414 sc = SkScaledBitmapSampler::kRGBA; |
| 415 } else { | 415 } else { |
| 416 sc = SkScaledBitmapSampler::kRGBX; | 416 sc = SkScaledBitmapSampler::kRGBX; |
| 417 } | 417 } |
| 418 | 418 |
| 419 /* We have to pass the colortable explicitly, since we may have one | 419 /* We have to pass the colortable explicitly, since we may have one |
| 420 even if our decodedBitmap doesn't, due to the request that we | 420 even if our decodedBitmap doesn't, due to the request that we |
| 421 upscale png's palette to a direct model | 421 upscale png's palette to a direct model |
| 422 */ | 422 */ |
| 423 const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL; | 423 const SkPMColor* colors = colorTable ? colorTable->readColors() : nullpt
r; |
| 424 if (!sampler.begin(decodedBitmap, sc, *this, colors)) { | 424 if (!sampler.begin(decodedBitmap, sc, *this, colors)) { |
| 425 return kFailure; | 425 return kFailure; |
| 426 } | 426 } |
| 427 const int height = decodedBitmap->height(); | 427 const int height = decodedBitmap->height(); |
| 428 | 428 |
| 429 if (number_passes > 1) { | 429 if (number_passes > 1) { |
| 430 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); | 430 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); |
| 431 uint8_t* base = (uint8_t*)storage.get(); | 431 uint8_t* base = (uint8_t*)storage.get(); |
| 432 size_t rowBytes = origWidth * srcBytesPerPixel; | 432 size_t rowBytes = origWidth * srcBytesPerPixel; |
| 433 | 433 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 #endif | 525 #endif |
| 526 | 526 |
| 527 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 527 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
| 528 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); | 528 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); |
| 529 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); | 529 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); |
| 530 // now see if we can upscale to their requested colortype | 530 // now see if we can upscale to their requested colortype |
| 531 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { | 531 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { |
| 532 *colorTypep = kIndex_8_SkColorType; | 532 *colorTypep = kIndex_8_SkColorType; |
| 533 } | 533 } |
| 534 } else { | 534 } else { |
| 535 png_color_16p transpColor = NULL; | 535 png_color_16p transpColor = nullptr; |
| 536 int numTransp = 0; | 536 int numTransp = 0; |
| 537 | 537 |
| 538 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); | 538 png_get_tRNS(png_ptr, info_ptr, nullptr, &numTransp, &transpColor); |
| 539 | 539 |
| 540 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); | 540 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); |
| 541 | 541 |
| 542 if (valid && numTransp == 1 && transpColor != NULL) { | 542 if (valid && numTransp == 1 && transpColor != nullptr) { |
| 543 /* Compute our transparent color, which we'll match against later. | 543 /* Compute our transparent color, which we'll match against later. |
| 544 We don't really handle 16bit components properly here, since we | 544 We don't really handle 16bit components properly here, since we |
| 545 do our compare *after* the values have been knocked down to 8bit | 545 do our compare *after* the values have been knocked down to 8bit |
| 546 which means we will find more matches than we should. The real | 546 which means we will find more matches than we should. The real |
| 547 fix seems to be to see the actual 16bit components, do the | 547 fix seems to be to see the actual 16bit components, do the |
| 548 compare, and then knock it down to 8bits ourselves. | 548 compare, and then knock it down to 8bits ourselves. |
| 549 */ | 549 */ |
| 550 if (colorType & PNG_COLOR_MASK_COLOR) { | 550 if (colorType & PNG_COLOR_MASK_COLOR) { |
| 551 if (16 == bitDepth) { | 551 if (16 == bitDepth) { |
| 552 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, | 552 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 return false; | 620 return false; |
| 621 } | 621 } |
| 622 } | 622 } |
| 623 | 623 |
| 624 // If the image has alpha and the decoder wants unpremultiplied | 624 // If the image has alpha and the decoder wants unpremultiplied |
| 625 // colors, the only supported colortype is 8888. | 625 // colors, the only supported colortype is 8888. |
| 626 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { | 626 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { |
| 627 *colorTypep = kN32_SkColorType; | 627 *colorTypep = kN32_SkColorType; |
| 628 } | 628 } |
| 629 | 629 |
| 630 if (fImageIndex != NULL) { | 630 if (fImageIndex != nullptr) { |
| 631 if (kUnknown_SkColorType == fImageIndex->fColorType) { | 631 if (kUnknown_SkColorType == fImageIndex->fColorType) { |
| 632 // This is the first time for this subset decode. From now on, | 632 // This is the first time for this subset decode. From now on, |
| 633 // all decodes must be in the same colortype. | 633 // all decodes must be in the same colortype. |
| 634 fImageIndex->fColorType = *colorTypep; | 634 fImageIndex->fColorType = *colorTypep; |
| 635 } else if (fImageIndex->fColorType != *colorTypep) { | 635 } else if (fImageIndex->fColorType != *colorTypep) { |
| 636 // Requesting a different colortype for a subsequent decode is not | 636 // Requesting a different colortype for a subsequent decode is not |
| 637 // supported. Report failure before we make changes to png_ptr. | 637 // supported. Report failure before we make changes to png_ptr. |
| 638 return false; | 638 return false; |
| 639 } | 639 } |
| 640 } | 640 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 665 png_colorp palette; | 665 png_colorp palette; |
| 666 png_bytep trans; | 666 png_bytep trans; |
| 667 int numTrans; | 667 int numTrans; |
| 668 | 668 |
| 669 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); | 669 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); |
| 670 | 670 |
| 671 SkPMColor colorStorage[256]; // worst-case storage | 671 SkPMColor colorStorage[256]; // worst-case storage |
| 672 SkPMColor* colorPtr = colorStorage; | 672 SkPMColor* colorPtr = colorStorage; |
| 673 | 673 |
| 674 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { | 674 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
| 675 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL); | 675 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, nullptr); |
| 676 *hasAlphap = (numTrans > 0); | 676 *hasAlphap = (numTrans > 0); |
| 677 } else { | 677 } else { |
| 678 numTrans = 0; | 678 numTrans = 0; |
| 679 } | 679 } |
| 680 | 680 |
| 681 // check for bad images that might make us crash | 681 // check for bad images that might make us crash |
| 682 if (numTrans > numPalette) { | 682 if (numTrans > numPalette) { |
| 683 numTrans = numPalette; | 683 numTrans = numPalette; |
| 684 } | 684 } |
| 685 | 685 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 | 754 |
| 755 if (fImageIndex) { | 755 if (fImageIndex) { |
| 756 delete fImageIndex; | 756 delete fImageIndex; |
| 757 } | 757 } |
| 758 fImageIndex = new SkPNGImageIndex(streamDeleter.detach(), png_ptr, info_ptr)
; | 758 fImageIndex = new SkPNGImageIndex(streamDeleter.detach(), png_ptr, info_ptr)
; |
| 759 | 759 |
| 760 return true; | 760 return true; |
| 761 } | 761 } |
| 762 | 762 |
| 763 bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { | 763 bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { |
| 764 if (NULL == fImageIndex) { | 764 if (nullptr == fImageIndex) { |
| 765 return false; | 765 return false; |
| 766 } | 766 } |
| 767 | 767 |
| 768 png_structp png_ptr = fImageIndex->fPng_ptr; | 768 png_structp png_ptr = fImageIndex->fPng_ptr; |
| 769 png_infop info_ptr = fImageIndex->fInfo_ptr; | 769 png_infop info_ptr = fImageIndex->fInfo_ptr; |
| 770 if (setjmp(png_jmpbuf(png_ptr))) { | 770 if (setjmp(png_jmpbuf(png_ptr))) { |
| 771 return false; | 771 return false; |
| 772 } | 772 } |
| 773 | 773 |
| 774 png_uint_32 origWidth, origHeight; | 774 png_uint_32 origWidth, origHeight; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 798 SkBitmap decodedBitmap; | 798 SkBitmap decodedBitmap; |
| 799 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale
dHeight(), | 799 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale
dHeight(), |
| 800 colorType, kPremul_SkAlphaType)); | 800 colorType, kPremul_SkAlphaType)); |
| 801 | 801 |
| 802 // from here down we are concerned with colortables and pixels | 802 // from here down we are concerned with colortables and pixels |
| 803 | 803 |
| 804 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 804 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype |
| 805 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we | 805 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we |
| 806 // draw lots faster if we can flag the bitmap has being opaque | 806 // draw lots faster if we can flag the bitmap has being opaque |
| 807 bool reallyHasAlpha = false; | 807 bool reallyHasAlpha = false; |
| 808 SkColorTable* colorTable = NULL; | 808 SkColorTable* colorTable = nullptr; |
| 809 | 809 |
| 810 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { | 810 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { |
| 811 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); | 811 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); |
| 812 } | 812 } |
| 813 | 813 |
| 814 SkAutoUnref aur(colorTable); | 814 SkAutoUnref aur(colorTable); |
| 815 | 815 |
| 816 // Check ahead of time if the swap(dest, src) is possible. | 816 // Check ahead of time if the swap(dest, src) is possible. |
| 817 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. | 817 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. |
| 818 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. | 818 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. |
| 819 int w = rect.width() / sampleSize; | 819 int w = rect.width() / sampleSize; |
| 820 int h = rect.height() / sampleSize; | 820 int h = rect.height() / sampleSize; |
| 821 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && | 821 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && |
| 822 (h == decodedBitmap.height()) && bm->isNull(); | 822 (h == decodedBitmap.height()) && bm->isNull(); |
| 823 const bool needColorTable = kIndex_8_SkColorType == colorType; | 823 const bool needColorTable = kIndex_8_SkColorType == colorType; |
| 824 if (swapOnly) { | 824 if (swapOnly) { |
| 825 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : N
ULL)) { | 825 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : n
ullptr)) { |
| 826 return false; | 826 return false; |
| 827 } | 827 } |
| 828 } else { | 828 } else { |
| 829 if (!decodedBitmap.tryAllocPixels(NULL, needColorTable ? colorTable : NU
LL)) { | 829 if (!decodedBitmap.tryAllocPixels(nullptr, needColorTable ? colorTable :
nullptr)) { |
| 830 return false; | 830 return false; |
| 831 } | 831 } |
| 832 } | 832 } |
| 833 SkAutoLockPixels alp(decodedBitmap); | 833 SkAutoLockPixels alp(decodedBitmap); |
| 834 | 834 |
| 835 /* Turn on interlace handling. REQUIRED if you are not using | 835 /* Turn on interlace handling. REQUIRED if you are not using |
| 836 * png_read_image(). To see how to handle interlacing passes, | 836 * png_read_image(). To see how to handle interlacing passes, |
| 837 * see the png_read_row() method below: | 837 * see the png_read_row() method below: |
| 838 */ | 838 */ |
| 839 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? | 839 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); | 875 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); |
| 876 for (png_uint_32 y = 0; y < bitmapHeight; y++) { | 876 for (png_uint_32 y = 0; y < bitmapHeight; y++) { |
| 877 uint8_t* bmRow = decodedBitmap.getAddr8(0, y); | 877 uint8_t* bmRow = decodedBitmap.getAddr8(0, y); |
| 878 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | 878 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); |
| 879 } | 879 } |
| 880 } | 880 } |
| 881 } else { | 881 } else { |
| 882 SkScaledBitmapSampler::SrcConfig sc; | 882 SkScaledBitmapSampler::SrcConfig sc; |
| 883 int srcBytesPerPixel = 4; | 883 int srcBytesPerPixel = 4; |
| 884 | 884 |
| 885 if (colorTable != NULL) { | 885 if (colorTable != nullptr) { |
| 886 sc = SkScaledBitmapSampler::kIndex; | 886 sc = SkScaledBitmapSampler::kIndex; |
| 887 srcBytesPerPixel = 1; | 887 srcBytesPerPixel = 1; |
| 888 } else if (kAlpha_8_SkColorType == colorType) { | 888 } else if (kAlpha_8_SkColorType == colorType) { |
| 889 // A8 is only allowed if the original was GRAY. | 889 // A8 is only allowed if the original was GRAY. |
| 890 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); | 890 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); |
| 891 sc = SkScaledBitmapSampler::kGray; | 891 sc = SkScaledBitmapSampler::kGray; |
| 892 srcBytesPerPixel = 1; | 892 srcBytesPerPixel = 1; |
| 893 } else if (hasAlpha) { | 893 } else if (hasAlpha) { |
| 894 sc = SkScaledBitmapSampler::kRGBA; | 894 sc = SkScaledBitmapSampler::kRGBA; |
| 895 } else { | 895 } else { |
| 896 sc = SkScaledBitmapSampler::kRGBX; | 896 sc = SkScaledBitmapSampler::kRGBX; |
| 897 } | 897 } |
| 898 | 898 |
| 899 /* We have to pass the colortable explicitly, since we may have one | 899 /* We have to pass the colortable explicitly, since we may have one |
| 900 even if our decodedBitmap doesn't, due to the request that we | 900 even if our decodedBitmap doesn't, due to the request that we |
| 901 upscale png's palette to a direct model | 901 upscale png's palette to a direct model |
| 902 */ | 902 */ |
| 903 const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL; | 903 const SkPMColor* colors = colorTable ? colorTable->readColors() : nullpt
r; |
| 904 if (!sampler.begin(&decodedBitmap, sc, *this, colors)) { | 904 if (!sampler.begin(&decodedBitmap, sc, *this, colors)) { |
| 905 return false; | 905 return false; |
| 906 } | 906 } |
| 907 const int height = decodedBitmap.height(); | 907 const int height = decodedBitmap.height(); |
| 908 | 908 |
| 909 if (number_passes > 1) { | 909 if (number_passes > 1) { |
| 910 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); | 910 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); |
| 911 uint8_t* base = (uint8_t*)storage.get(); | 911 uint8_t* base = (uint8_t*)storage.get(); |
| 912 size_t rb = origWidth * srcBytesPerPixel; | 912 size_t rb = origWidth * srcBytesPerPixel; |
| 913 | 913 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 { kARGB_4444_SkColorType, true, transform_scanline_4444 }, | 1018 { kARGB_4444_SkColorType, true, transform_scanline_4444 }, |
| 1019 { kIndex_8_SkColorType, false, transform_scanline_memcpy }, | 1019 { kIndex_8_SkColorType, false, transform_scanline_memcpy }, |
| 1020 }; | 1020 }; |
| 1021 | 1021 |
| 1022 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { | 1022 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { |
| 1023 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { | 1023 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { |
| 1024 return gMap[i].fProc; | 1024 return gMap[i].fProc; |
| 1025 } | 1025 } |
| 1026 } | 1026 } |
| 1027 sk_throw(); | 1027 sk_throw(); |
| 1028 return NULL; | 1028 return nullptr; |
| 1029 } | 1029 } |
| 1030 | 1030 |
| 1031 // return the minimum legal bitdepth (by png standards) for this many colortable | 1031 // return the minimum legal bitdepth (by png standards) for this many colortable |
| 1032 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, | 1032 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, |
| 1033 // we can use fewer bits per in png | 1033 // we can use fewer bits per in png |
| 1034 static int computeBitDepth(int colorCount) { | 1034 static int computeBitDepth(int colorCount) { |
| 1035 #if 0 | 1035 #if 0 |
| 1036 int bits = SkNextLog2(colorCount); | 1036 int bits = SkNextLog2(colorCount); |
| 1037 SkASSERT(bits >= 1 && bits <= 8); | 1037 SkASSERT(bits >= 1 && bits <= 8); |
| 1038 // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8) | 1038 // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8) |
| 1039 return SkNextPow2(bits); | 1039 return SkNextPow2(bits); |
| 1040 #else | 1040 #else |
| 1041 // for the moment, we don't know how to pack bitdepth < 8 | 1041 // for the moment, we don't know how to pack bitdepth < 8 |
| 1042 return 8; | 1042 return 8; |
| 1043 #endif | 1043 #endif |
| 1044 } | 1044 } |
| 1045 | 1045 |
| 1046 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also | 1046 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also |
| 1047 pack trans[] and return the number of trans[] entries written. If hasAlpha | 1047 pack trans[] and return the number of trans[] entries written. If hasAlpha |
| 1048 is false, the return value will always be 0. | 1048 is false, the return value will always be 0. |
| 1049 | 1049 |
| 1050 Note: this routine takes care of unpremultiplying the RGB values when we | 1050 Note: this routine takes care of unpremultiplying the RGB values when we |
| 1051 have alpha in the colortable, since png doesn't support premul colors | 1051 have alpha in the colortable, since png doesn't support premul colors |
| 1052 */ | 1052 */ |
| 1053 static inline int pack_palette(SkColorTable* ctable, | 1053 static inline int pack_palette(SkColorTable* ctable, |
| 1054 png_color* SK_RESTRICT palette, | 1054 png_color* SK_RESTRICT palette, |
| 1055 png_byte* SK_RESTRICT trans, bool hasAlpha) { | 1055 png_byte* SK_RESTRICT trans, bool hasAlpha) { |
| 1056 const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : NULL; | 1056 const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : nullpt
r; |
| 1057 const int ctCount = ctable->count(); | 1057 const int ctCount = ctable->count(); |
| 1058 int i, num_trans = 0; | 1058 int i, num_trans = 0; |
| 1059 | 1059 |
| 1060 if (hasAlpha) { | 1060 if (hasAlpha) { |
| 1061 /* first see if we have some number of fully opaque at the end of the | 1061 /* first see if we have some number of fully opaque at the end of the |
| 1062 ctable. PNG allows num_trans < num_palette, but all of the trans | 1062 ctable. PNG allows num_trans < num_palette, but all of the trans |
| 1063 entries must come first in the palette. If I was smarter, I'd | 1063 entries must come first in the palette. If I was smarter, I'd |
| 1064 reorder the indices and ctable so that all non-opaque colors came | 1064 reorder the indices and ctable so that all non-opaque colors came |
| 1065 first in the palette. But, since that would slow down the encode, | 1065 first in the palette. But, since that would slow down the encode, |
| 1066 I'm leaving the indices and ctable order as is, and just looking | 1066 I'm leaving the indices and ctable order as is, and just looking |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 } | 1175 } |
| 1176 | 1176 |
| 1177 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, | 1177 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, |
| 1178 const bool& hasAlpha, int colorType, | 1178 const bool& hasAlpha, int colorType, |
| 1179 int bitDepth, SkColorType ct, | 1179 int bitDepth, SkColorType ct, |
| 1180 png_color_8& sig_bit) { | 1180 png_color_8& sig_bit) { |
| 1181 | 1181 |
| 1182 png_structp png_ptr; | 1182 png_structp png_ptr; |
| 1183 png_infop info_ptr; | 1183 png_infop info_ptr; |
| 1184 | 1184 |
| 1185 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn, | 1185 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, sk_error_f
n, |
| 1186 NULL); | 1186 nullptr); |
| 1187 if (NULL == png_ptr) { | 1187 if (nullptr == png_ptr) { |
| 1188 return false; | 1188 return false; |
| 1189 } | 1189 } |
| 1190 | 1190 |
| 1191 info_ptr = png_create_info_struct(png_ptr); | 1191 info_ptr = png_create_info_struct(png_ptr); |
| 1192 if (NULL == info_ptr) { | 1192 if (nullptr == info_ptr) { |
| 1193 png_destroy_write_struct(&png_ptr, png_infopp_NULL); | 1193 png_destroy_write_struct(&png_ptr, png_infopp_NULL); |
| 1194 return false; | 1194 return false; |
| 1195 } | 1195 } |
| 1196 | 1196 |
| 1197 /* Set error handling. REQUIRED if you aren't supplying your own | 1197 /* Set error handling. REQUIRED if you aren't supplying your own |
| 1198 * error handling functions in the png_create_write_struct() call. | 1198 * error handling functions in the png_create_write_struct() call. |
| 1199 */ | 1199 */ |
| 1200 if (setjmp(png_jmpbuf(png_ptr))) { | 1200 if (setjmp(png_jmpbuf(png_ptr))) { |
| 1201 png_destroy_write_struct(&png_ptr, &info_ptr); | 1201 png_destroy_write_struct(&png_ptr, &info_ptr); |
| 1202 return false; | 1202 return false; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1219 PNG_FILTER_TYPE_BASE); | 1219 PNG_FILTER_TYPE_BASE); |
| 1220 | 1220 |
| 1221 // set our colortable/trans arrays if needed | 1221 // set our colortable/trans arrays if needed |
| 1222 png_color paletteColors[256]; | 1222 png_color paletteColors[256]; |
| 1223 png_byte trans[256]; | 1223 png_byte trans[256]; |
| 1224 if (kIndex_8_SkColorType == ct) { | 1224 if (kIndex_8_SkColorType == ct) { |
| 1225 SkColorTable* ct = bitmap.getColorTable(); | 1225 SkColorTable* ct = bitmap.getColorTable(); |
| 1226 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); | 1226 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); |
| 1227 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 1227 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
| 1228 if (numTrans > 0) { | 1228 if (numTrans > 0) { |
| 1229 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL); | 1229 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); |
| 1230 } | 1230 } |
| 1231 } | 1231 } |
| 1232 #ifdef PNG_sBIT_SUPPORTED | 1232 #ifdef PNG_sBIT_SUPPORTED |
| 1233 png_set_sBIT(png_ptr, info_ptr, &sig_bit); | 1233 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
| 1234 #endif | 1234 #endif |
| 1235 png_write_info(png_ptr, info_ptr); | 1235 png_write_info(png_ptr, info_ptr); |
| 1236 | 1236 |
| 1237 const char* srcImage = (const char*)bitmap.getPixels(); | 1237 const char* srcImage = (const char*)bitmap.getPixels(); |
| 1238 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); | 1238 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); |
| 1239 char* storage = (char*)rowStorage.get(); | 1239 char* storage = (char*)rowStorage.get(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1264 !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { | 1264 !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { |
| 1265 return true; | 1265 return true; |
| 1266 } | 1266 } |
| 1267 return false; | 1267 return false; |
| 1268 } | 1268 } |
| 1269 | 1269 |
| 1270 SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) { | 1270 SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) { |
| 1271 if (is_png(stream)) { | 1271 if (is_png(stream)) { |
| 1272 return new SkPNGImageDecoder; | 1272 return new SkPNGImageDecoder; |
| 1273 } | 1273 } |
| 1274 return NULL; | 1274 return nullptr; |
| 1275 } | 1275 } |
| 1276 | 1276 |
| 1277 static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) { | 1277 static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) { |
| 1278 if (is_png(stream)) { | 1278 if (is_png(stream)) { |
| 1279 return SkImageDecoder::kPNG_Format; | 1279 return SkImageDecoder::kPNG_Format; |
| 1280 } | 1280 } |
| 1281 return SkImageDecoder::kUnknown_Format; | 1281 return SkImageDecoder::kUnknown_Format; |
| 1282 } | 1282 } |
| 1283 | 1283 |
| 1284 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1284 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
| 1285 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : NULL; | 1285 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; |
| 1286 } | 1286 } |
| 1287 | 1287 |
| 1288 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); | 1288 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); |
| 1289 static SkImageDecoder_FormatReg gFormatReg(get_format_png); | 1289 static SkImageDecoder_FormatReg gFormatReg(get_format_png); |
| 1290 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 1290 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
| OLD | NEW |