| OLD | NEW |
| 1 | |
| 2 /* | 1 /* |
| 3 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 4 * | 3 * |
| 5 * 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 |
| 6 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 7 */ | 6 */ |
| 8 | 7 |
| 9 | |
| 10 #include "SkImageDecoder.h" | 8 #include "SkImageDecoder.h" |
| 11 #include "SkImageEncoder.h" | 9 #include "SkImageEncoder.h" |
| 12 #include "SkColor.h" | 10 #include "SkColor.h" |
| 13 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
| 14 #include "SkDither.h" | 12 #include "SkDither.h" |
| 15 #include "SkMath.h" | 13 #include "SkMath.h" |
| 16 #include "SkRTConf.h" | 14 #include "SkRTConf.h" |
| 17 #include "SkScaledBitmapSampler.h" | 15 #include "SkScaledBitmapSampler.h" |
| 18 #include "SkStream.h" | 16 #include "SkStream.h" |
| 19 #include "SkTemplates.h" | 17 #include "SkTemplates.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 "functions."); | 50 "functions."); |
| 53 | 51 |
| 54 | 52 |
| 55 | 53 |
| 56 class SkPNGImageIndex { | 54 class SkPNGImageIndex { |
| 57 public: | 55 public: |
| 58 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i
nfo_ptr) | 56 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i
nfo_ptr) |
| 59 : fStream(stream) | 57 : fStream(stream) |
| 60 , fPng_ptr(png_ptr) | 58 , fPng_ptr(png_ptr) |
| 61 , fInfo_ptr(info_ptr) | 59 , fInfo_ptr(info_ptr) |
| 62 , fConfig(SkBitmap::kNo_Config) { | 60 , fColorType(kUnknown_SkColorType) { |
| 63 SkASSERT(stream != NULL); | 61 SkASSERT(stream != NULL); |
| 64 stream->ref(); | 62 stream->ref(); |
| 65 } | 63 } |
| 66 ~SkPNGImageIndex() { | 64 ~SkPNGImageIndex() { |
| 67 if (NULL != fPng_ptr) { | 65 if (NULL != fPng_ptr) { |
| 68 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); | 66 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); |
| 69 } | 67 } |
| 70 } | 68 } |
| 71 | 69 |
| 72 SkAutoTUnref<SkStreamRewindable> fStream; | 70 SkAutoTUnref<SkStreamRewindable> fStream; |
| 73 png_structp fPng_ptr; | 71 png_structp fPng_ptr; |
| 74 png_infop fInfo_ptr; | 72 png_infop fInfo_ptr; |
| 75 SkBitmap::Config fConfig; | 73 SkColorType fColorType; |
| 76 }; | 74 }; |
| 77 | 75 |
| 78 class SkPNGImageDecoder : public SkImageDecoder { | 76 class SkPNGImageDecoder : public SkImageDecoder { |
| 79 public: | 77 public: |
| 80 SkPNGImageDecoder() { | 78 SkPNGImageDecoder() { |
| 81 fImageIndex = NULL; | 79 fImageIndex = NULL; |
| 82 } | 80 } |
| 83 virtual Format getFormat() const SK_OVERRIDE { | 81 virtual Format getFormat() const SK_OVERRIDE { |
| 84 return kPNG_Format; | 82 return kPNG_Format; |
| 85 } | 83 } |
| 86 | 84 |
| 87 virtual ~SkPNGImageDecoder() { | 85 virtual ~SkPNGImageDecoder() { |
| 88 SkDELETE(fImageIndex); | 86 SkDELETE(fImageIndex); |
| 89 } | 87 } |
| 90 | 88 |
| 91 protected: | 89 protected: |
| 92 #ifdef SK_BUILD_FOR_ANDROID | 90 #ifdef SK_BUILD_FOR_ANDROID |
| 93 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h
eight) SK_OVERRIDE; | 91 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h
eight) SK_OVERRIDE; |
| 94 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVER
RIDE; | 92 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVER
RIDE; |
| 95 #endif | 93 #endif |
| 96 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 94 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
| 97 | 95 |
| 98 private: | 96 private: |
| 99 SkPNGImageIndex* fImageIndex; | 97 SkPNGImageIndex* fImageIndex; |
| 100 | 98 |
| 101 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p
trp); | 99 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p
trp); |
| 102 bool decodePalette(png_structp png_ptr, png_infop info_ptr, | 100 bool decodePalette(png_structp png_ptr, png_infop info_ptr, |
| 103 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, | 101 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, |
| 104 SkColorTable **colorTablep); | 102 SkColorTable **colorTablep); |
| 105 bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr, | 103 bool getBitmapConfig(png_structp, png_infop, SkColorType*, bool* hasAlpha, |
| 106 SkBitmap::Config *config, bool *hasAlpha, | 104 SkPMColor* theTranspColor); |
| 107 SkPMColor *theTranspColor); | |
| 108 | 105 |
| 109 typedef SkImageDecoder INHERITED; | 106 typedef SkImageDecoder INHERITED; |
| 110 }; | 107 }; |
| 111 | 108 |
| 112 #ifndef png_jmpbuf | 109 #ifndef png_jmpbuf |
| 113 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) | 110 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) |
| 114 #endif | 111 #endif |
| 115 | 112 |
| 116 #define PNG_BYTES_TO_CHECK 4 | 113 #define PNG_BYTES_TO_CHECK 4 |
| 117 | 114 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 if (match == *p) { | 176 if (match == *p) { |
| 180 *p = 0; | 177 *p = 0; |
| 181 reallyHasAlpha = true; | 178 reallyHasAlpha = true; |
| 182 } | 179 } |
| 183 p += 1; | 180 p += 1; |
| 184 } | 181 } |
| 185 } | 182 } |
| 186 return reallyHasAlpha; | 183 return reallyHasAlpha; |
| 187 } | 184 } |
| 188 | 185 |
| 189 static bool canUpscalePaletteToConfig(SkBitmap::Config dstConfig, | 186 static bool canUpscalePaletteToConfig(SkColorType dstColorType, bool srcHasAlpha
) { |
| 190 bool srcHasAlpha) { | 187 switch (dstColorType) { |
| 191 switch (dstConfig) { | 188 case kN32_SkColorType: |
| 192 case SkBitmap::kARGB_8888_Config: | 189 case kARGB_4444_SkColorType: |
| 193 case SkBitmap::kARGB_4444_Config: | |
| 194 return true; | 190 return true; |
| 195 case SkBitmap::kRGB_565_Config: | 191 case kRGB_565_SkColorType: |
| 196 // only return true if the src is opaque (since 565 is opaque) | 192 // only return true if the src is opaque (since 565 is opaque) |
| 197 return !srcHasAlpha; | 193 return !srcHasAlpha; |
| 198 default: | 194 default: |
| 199 return false; | 195 return false; |
| 200 } | 196 } |
| 201 } | 197 } |
| 202 | 198 |
| 203 // call only if color_type is PALETTE. Returns true if the ctable has alpha | 199 // 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) { | 200 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) { |
| 205 png_bytep trans; | 201 png_bytep trans; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 return false; | 306 return false; |
| 311 } | 307 } |
| 312 | 308 |
| 313 PNGAutoClean autoClean(png_ptr, info_ptr); | 309 PNGAutoClean autoClean(png_ptr, info_ptr); |
| 314 | 310 |
| 315 if (setjmp(png_jmpbuf(png_ptr))) { | 311 if (setjmp(png_jmpbuf(png_ptr))) { |
| 316 return false; | 312 return false; |
| 317 } | 313 } |
| 318 | 314 |
| 319 png_uint_32 origWidth, origHeight; | 315 png_uint_32 origWidth, origHeight; |
| 320 int bitDepth, colorType, interlaceType; | 316 int bitDepth, pngColorType, interlaceType; |
| 321 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 317 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
| 322 &colorType, &interlaceType, int_p_NULL, int_p_NULL); | 318 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); |
| 323 | 319 |
| 324 SkBitmap::Config config; | 320 SkColorType colorType; |
| 325 bool hasAlpha = false; | 321 bool hasAlpha = false; |
| 326 SkPMColor theTranspColor = 0; // 0 tells us not to try to match | 322 SkPMColor theTranspColor = 0; // 0 tells us not to try to match |
| 327 | 323 |
| 328 if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTransp
Color)) { | 324 if (!this->getBitmapConfig(png_ptr, info_ptr, &colorType, &hasAlpha, &theTra
nspColor)) { |
| 329 return false; | 325 return false; |
| 330 } | 326 } |
| 331 | 327 |
| 328 SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ? |
| 329 kUnpremul_SkAlphaType : kPremul_SkAlphaType; |
| 332 const int sampleSize = this->getSampleSize(); | 330 const int sampleSize = this->getSampleSize(); |
| 333 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); | 331 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); |
| 334 decodedBitmap->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight
()); | 332 decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scal
edHeight(), |
| 335 | 333 colorType, alphaType)); |
| 336 // we should communicate alphaType, even if we early-return in bounds-only-m
ode. | |
| 337 if (this->getRequireUnpremultipliedColors()) { | |
| 338 decodedBitmap->setAlphaType(kUnpremul_SkAlphaType); | |
| 339 } | |
| 340 | 334 |
| 341 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 335 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
| 342 return true; | 336 return true; |
| 343 } | 337 } |
| 344 | 338 |
| 345 // from here down we are concerned with colortables and pixels | 339 // from here down we are concerned with colortables and pixels |
| 346 | 340 |
| 347 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 341 // 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 | 342 // 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 | 343 // draw lots faster if we can flag the bitmap has being opaque |
| 350 bool reallyHasAlpha = false; | 344 bool reallyHasAlpha = false; |
| 351 SkColorTable* colorTable = NULL; | 345 SkColorTable* colorTable = NULL; |
| 352 | 346 |
| 353 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 347 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { |
| 354 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable
); | 348 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable
); |
| 355 } | 349 } |
| 356 | 350 |
| 357 SkAutoUnref aur(colorTable); | 351 SkAutoUnref aur(colorTable); |
| 358 | 352 |
| 359 if (!this->allocPixelRef(decodedBitmap, | 353 if (!this->allocPixelRef(decodedBitmap, |
| 360 SkBitmap::kIndex8_Config == config ? colorTable : N
ULL)) { | 354 kIndex_8_SkColorType == colorType ? colorTable : NU
LL)) { |
| 361 return false; | 355 return false; |
| 362 } | 356 } |
| 363 | 357 |
| 364 SkAutoLockPixels alp(*decodedBitmap); | 358 SkAutoLockPixels alp(*decodedBitmap); |
| 365 | 359 |
| 366 /* Turn on interlace handling. REQUIRED if you are not using | 360 /* Turn on interlace handling. REQUIRED if you are not using |
| 367 * png_read_image(). To see how to handle interlacing passes, | 361 * png_read_image(). To see how to handle interlacing passes, |
| 368 * see the png_read_row() method below: | 362 * see the png_read_row() method below: |
| 369 */ | 363 */ |
| 370 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? | 364 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? |
| 371 png_set_interlace_handling(png_ptr) : 1; | 365 png_set_interlace_handling(png_ptr) : 1; |
| 372 | 366 |
| 373 /* Optional call to gamma correct and add the background to the palette | 367 /* Optional call to gamma correct and add the background to the palette |
| 374 * and update info structure. REQUIRED if you are expecting libpng to | 368 * and update info structure. REQUIRED if you are expecting libpng to |
| 375 * update the palette for you (ie you selected such a transform above). | 369 * update the palette for you (ie you selected such a transform above). |
| 376 */ | 370 */ |
| 377 png_read_update_info(png_ptr, info_ptr); | 371 png_read_update_info(png_ptr, info_ptr); |
| 378 | 372 |
| 379 if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config) | 373 if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType)
&& |
| 380 && 1 == sampleSize) { | 374 1 == sampleSize) { |
| 381 if (SkBitmap::kA8_Config == config) { | 375 if (kAlpha_8_SkColorType == colorType) { |
| 382 // For an A8 bitmap, we assume there is an alpha for speed. It is | 376 // 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 | 377 // possible the bitmap is opaque, but that is an unlikely use case |
| 384 // since it would not be very interesting. | 378 // since it would not be very interesting. |
| 385 reallyHasAlpha = true; | 379 reallyHasAlpha = true; |
| 386 // A8 is only allowed if the original was GRAY. | 380 // A8 is only allowed if the original was GRAY. |
| 387 SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); | 381 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); |
| 388 } | 382 } |
| 389 for (int i = 0; i < number_passes; i++) { | 383 for (int i = 0; i < number_passes; i++) { |
| 390 for (png_uint_32 y = 0; y < origHeight; y++) { | 384 for (png_uint_32 y = 0; y < origHeight; y++) { |
| 391 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); | 385 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); |
| 392 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | 386 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); |
| 393 } | 387 } |
| 394 } | 388 } |
| 395 } else { | 389 } else { |
| 396 SkScaledBitmapSampler::SrcConfig sc; | 390 SkScaledBitmapSampler::SrcConfig sc; |
| 397 int srcBytesPerPixel = 4; | 391 int srcBytesPerPixel = 4; |
| 398 | 392 |
| 399 if (colorTable != NULL) { | 393 if (colorTable != NULL) { |
| 400 sc = SkScaledBitmapSampler::kIndex; | 394 sc = SkScaledBitmapSampler::kIndex; |
| 401 srcBytesPerPixel = 1; | 395 srcBytesPerPixel = 1; |
| 402 } else if (SkBitmap::kA8_Config == config) { | 396 } else if (kAlpha_8_SkColorType == colorType) { |
| 403 // A8 is only allowed if the original was GRAY. | 397 // A8 is only allowed if the original was GRAY. |
| 404 SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); | 398 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); |
| 405 sc = SkScaledBitmapSampler::kGray; | 399 sc = SkScaledBitmapSampler::kGray; |
| 406 srcBytesPerPixel = 1; | 400 srcBytesPerPixel = 1; |
| 407 } else if (hasAlpha) { | 401 } else if (hasAlpha) { |
| 408 sc = SkScaledBitmapSampler::kRGBA; | 402 sc = SkScaledBitmapSampler::kRGBA; |
| 409 } else { | 403 } else { |
| 410 sc = SkScaledBitmapSampler::kRGBX; | 404 sc = SkScaledBitmapSampler::kRGBX; |
| 411 } | 405 } |
| 412 | 406 |
| 413 /* We have to pass the colortable explicitly, since we may have one | 407 /* 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 | 408 even if our decodedBitmap doesn't, due to the request that we |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 | 479 |
| 486 if (!reallyHasAlpha) { | 480 if (!reallyHasAlpha) { |
| 487 decodedBitmap->setAlphaType(kOpaque_SkAlphaType); | 481 decodedBitmap->setAlphaType(kOpaque_SkAlphaType); |
| 488 } | 482 } |
| 489 return true; | 483 return true; |
| 490 } | 484 } |
| 491 | 485 |
| 492 | 486 |
| 493 | 487 |
| 494 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, | 488 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, |
| 495 SkBitmap::Config* SK_RESTRICT configp, | 489 SkColorType* colorTypep, |
| 496 bool* SK_RESTRICT hasAlphap, | 490 bool* hasAlphap, |
| 497 SkPMColor* SK_RESTRICT theTranspColorp)
{ | 491 SkPMColor* SK_RESTRICT theTranspColorp)
{ |
| 498 png_uint_32 origWidth, origHeight; | 492 png_uint_32 origWidth, origHeight; |
| 499 int bitDepth, colorType; | 493 int bitDepth, colorType; |
| 500 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 494 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
| 501 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 495 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); |
| 502 | 496 |
| 503 // check for sBIT chunk data, in case we should disable dithering because | 497 // check for sBIT chunk data, in case we should disable dithering because |
| 504 // our data is not truely 8bits per component | 498 // our data is not truely 8bits per component |
| 505 png_color_8p sig_bit; | 499 png_color_8p sig_bit; |
| 506 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { | 500 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { |
| 507 #if 0 | 501 #if 0 |
| 508 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, | 502 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, |
| 509 sig_bit->blue, sig_bit->alpha); | 503 sig_bit->blue, sig_bit->alpha); |
| 510 #endif | 504 #endif |
| 511 // 0 seems to indicate no information available | 505 // 0 seems to indicate no information available |
| 512 if (pos_le(sig_bit->red, SK_R16_BITS) && | 506 if (pos_le(sig_bit->red, SK_R16_BITS) && |
| 513 pos_le(sig_bit->green, SK_G16_BITS) && | 507 pos_le(sig_bit->green, SK_G16_BITS) && |
| 514 pos_le(sig_bit->blue, SK_B16_BITS)) { | 508 pos_le(sig_bit->blue, SK_B16_BITS)) { |
| 515 this->setDitherImage(false); | 509 this->setDitherImage(false); |
| 516 } | 510 } |
| 517 } | 511 } |
| 518 | 512 |
| 519 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 513 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
| 520 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); | 514 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); |
| 521 *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha); | 515 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); |
| 522 // now see if we can upscale to their requested config | 516 // now see if we can upscale to their requested config |
| 523 if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) { | 517 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { |
| 524 *configp = SkBitmap::kIndex8_Config; | 518 *colorTypep = kIndex_8_SkColorType; |
| 525 } | 519 } |
| 526 } else { | 520 } else { |
| 527 png_color_16p transpColor = NULL; | 521 png_color_16p transpColor = NULL; |
| 528 int numTransp = 0; | 522 int numTransp = 0; |
| 529 | 523 |
| 530 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); | 524 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); |
| 531 | 525 |
| 532 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); | 526 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); |
| 533 | 527 |
| 534 if (valid && numTransp == 1 && transpColor != NULL) { | 528 if (valid && numTransp == 1 && transpColor != NULL) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 *hasAlphap = true; | 572 *hasAlphap = true; |
| 579 } | 573 } |
| 580 | 574 |
| 581 SrcDepth srcDepth = k32Bit_SrcDepth; | 575 SrcDepth srcDepth = k32Bit_SrcDepth; |
| 582 if (PNG_COLOR_TYPE_GRAY == colorType) { | 576 if (PNG_COLOR_TYPE_GRAY == colorType) { |
| 583 srcDepth = k8BitGray_SrcDepth; | 577 srcDepth = k8BitGray_SrcDepth; |
| 584 // Remove this assert, which fails on desk_pokemonwiki.skp | 578 // Remove this assert, which fails on desk_pokemonwiki.skp |
| 585 //SkASSERT(!*hasAlphap); | 579 //SkASSERT(!*hasAlphap); |
| 586 } | 580 } |
| 587 | 581 |
| 588 *configp = this->getPrefConfig(srcDepth, *hasAlphap); | 582 *colorTypep = this->getPrefColorType(srcDepth, *hasAlphap); |
| 589 // now match the request against our capabilities | 583 // now match the request against our capabilities |
| 590 if (*hasAlphap) { | 584 if (*hasAlphap) { |
| 591 if (*configp != SkBitmap::kARGB_4444_Config) { | 585 if (*colorTypep != kARGB_4444_SkColorType) { |
| 592 *configp = SkBitmap::kARGB_8888_Config; | 586 *colorTypep = kN32_SkColorType; |
| 593 } | 587 } |
| 594 } else { | 588 } else { |
| 595 if (SkBitmap::kA8_Config == *configp) { | 589 if (kAlpha_8_SkColorType == *colorTypep) { |
| 596 if (k8BitGray_SrcDepth != srcDepth) { | 590 if (k8BitGray_SrcDepth != srcDepth) { |
| 597 // Converting a non grayscale image to A8 is not currently s
upported. | 591 // Converting a non grayscale image to A8 is not currently s
upported. |
| 598 *configp = SkBitmap::kARGB_8888_Config; | 592 *colorTypep = kN32_SkColorType; |
| 599 } | 593 } |
| 600 } else if (*configp != SkBitmap::kRGB_565_Config && | 594 } else if (*colorTypep != kRGB_565_SkColorType && |
| 601 *configp != SkBitmap::kARGB_4444_Config) { | 595 *colorTypep != kARGB_4444_SkColorType) { |
| 602 *configp = SkBitmap::kARGB_8888_Config; | 596 *colorTypep = kN32_SkColorType; |
| 603 } | 597 } |
| 604 } | 598 } |
| 605 } | 599 } |
| 606 | 600 |
| 607 // sanity check for size | 601 // sanity check for size |
| 608 { | 602 { |
| 609 int64_t size = sk_64_mul(origWidth, origHeight); | 603 int64_t size = sk_64_mul(origWidth, origHeight); |
| 610 // now check that if we are 4-bytes per pixel, we also don't overflow | 604 // now check that if we are 4-bytes per pixel, we also don't overflow |
| 611 if (size < 0 || size > (0x7FFFFFFF >> 2)) { | 605 if (size < 0 || size > (0x7FFFFFFF >> 2)) { |
| 612 return false; | 606 return false; |
| 613 } | 607 } |
| 614 } | 608 } |
| 615 | 609 |
| 616 if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) { | 610 if (!this->chooseFromOneChoice(*colorTypep, origWidth, origHeight)) { |
| 617 return false; | 611 return false; |
| 618 } | 612 } |
| 619 | 613 |
| 620 // If the image has alpha and the decoder wants unpremultiplied | 614 // If the image has alpha and the decoder wants unpremultiplied |
| 621 // colors, the only supported config is 8888. | 615 // colors, the only supported config is 8888. |
| 622 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { | 616 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { |
| 623 *configp = SkBitmap::kARGB_8888_Config; | 617 *colorTypep = kN32_SkColorType; |
| 624 } | 618 } |
| 625 | 619 |
| 626 if (fImageIndex != NULL) { | 620 if (fImageIndex != NULL) { |
| 627 if (SkBitmap::kNo_Config == fImageIndex->fConfig) { | 621 if (kUnknown_SkColorType == fImageIndex->fColorType) { |
| 628 // This is the first time for this subset decode. From now on, | 622 // This is the first time for this subset decode. From now on, |
| 629 // all decodes must be in the same config. | 623 // all decodes must be in the same config. |
| 630 fImageIndex->fConfig = *configp; | 624 fImageIndex->fColorType = *colorTypep; |
| 631 } else if (fImageIndex->fConfig != *configp) { | 625 } else if (fImageIndex->fColorType != *colorTypep) { |
| 632 // Requesting a different config for a subsequent decode is not | 626 // Requesting a different colortype for a subsequent decode is not |
| 633 // supported. Report failure before we make changes to png_ptr. | 627 // supported. Report failure before we make changes to png_ptr. |
| 634 return false; | 628 return false; |
| 635 } | 629 } |
| 636 } | 630 } |
| 637 | 631 |
| 638 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType | 632 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != k
Alpha_8_SkColorType; |
| 639 && *configp != SkBitmap::kA8_Config; | |
| 640 | 633 |
| 641 // Unless the user is requesting A8, convert a grayscale image into RGB. | 634 // Unless the user is requesting A8, convert a grayscale image into RGB. |
| 642 // GRAY_ALPHA will always be converted to RGB | 635 // GRAY_ALPHA will always be converted to RGB |
| 643 if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { | 636 if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { |
| 644 png_set_gray_to_rgb(png_ptr); | 637 png_set_gray_to_rgb(png_ptr); |
| 645 } | 638 } |
| 646 | 639 |
| 647 // Add filler (or alpha) byte (after each RGB triplet) if necessary. | 640 // Add filler (or alpha) byte (after each RGB triplet) if necessary. |
| 648 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) { | 641 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) { |
| 649 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); | 642 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 return false; | 760 return false; |
| 768 } | 761 } |
| 769 | 762 |
| 770 png_structp png_ptr = fImageIndex->fPng_ptr; | 763 png_structp png_ptr = fImageIndex->fPng_ptr; |
| 771 png_infop info_ptr = fImageIndex->fInfo_ptr; | 764 png_infop info_ptr = fImageIndex->fInfo_ptr; |
| 772 if (setjmp(png_jmpbuf(png_ptr))) { | 765 if (setjmp(png_jmpbuf(png_ptr))) { |
| 773 return false; | 766 return false; |
| 774 } | 767 } |
| 775 | 768 |
| 776 png_uint_32 origWidth, origHeight; | 769 png_uint_32 origWidth, origHeight; |
| 777 int bitDepth, colorType, interlaceType; | 770 int bitDepth, pngColorType, interlaceType; |
| 778 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 771 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
| 779 &colorType, &interlaceType, int_p_NULL, int_p_NULL); | 772 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); |
| 780 | 773 |
| 781 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight); | 774 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight); |
| 782 | 775 |
| 783 if (!rect.intersect(region)) { | 776 if (!rect.intersect(region)) { |
| 784 // If the requested region is entirely outside the image, just | 777 // If the requested region is entirely outside the image, just |
| 785 // returns false | 778 // returns false |
| 786 return false; | 779 return false; |
| 787 } | 780 } |
| 788 | 781 |
| 789 SkBitmap::Config config; | 782 SkColorType colorType; |
| 790 bool hasAlpha = false; | 783 bool hasAlpha = false; |
| 791 SkPMColor theTranspColor = 0; // 0 tells us not to try to match | 784 SkPMColor theTranspColor = 0; // 0 tells us not to try to match |
| 792 | 785 |
| 793 if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTransp
Color)) { | 786 if (!this->getBitmapConfig(png_ptr, info_ptr, &colorType, &hasAlpha, &theTra
nspColor)) { |
| 794 return false; | 787 return false; |
| 795 } | 788 } |
| 796 | 789 |
| 797 const int sampleSize = this->getSampleSize(); | 790 const int sampleSize = this->getSampleSize(); |
| 798 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); | 791 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); |
| 799 | 792 |
| 800 SkBitmap decodedBitmap; | 793 SkBitmap decodedBitmap; |
| 801 decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(
)); | 794 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale
dHeight(), |
| 795 colorType, kPremul_SkAlphaType)); |
| 802 | 796 |
| 803 // from here down we are concerned with colortables and pixels | 797 // from here down we are concerned with colortables and pixels |
| 804 | 798 |
| 805 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 799 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype |
| 806 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we | 800 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we |
| 807 // draw lots faster if we can flag the bitmap has being opaque | 801 // draw lots faster if we can flag the bitmap has being opaque |
| 808 bool reallyHasAlpha = false; | 802 bool reallyHasAlpha = false; |
| 809 SkColorTable* colorTable = NULL; | 803 SkColorTable* colorTable = NULL; |
| 810 | 804 |
| 811 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 805 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { |
| 812 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable
); | 806 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable
); |
| 813 } | 807 } |
| 814 | 808 |
| 815 SkAutoUnref aur(colorTable); | 809 SkAutoUnref aur(colorTable); |
| 816 | 810 |
| 817 // Check ahead of time if the swap(dest, src) is possible. | 811 // Check ahead of time if the swap(dest, src) is possible. |
| 818 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. | 812 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. |
| 819 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. | 813 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. |
| 820 int w = rect.width() / sampleSize; | 814 int w = rect.width() / sampleSize; |
| 821 int h = rect.height() / sampleSize; | 815 int h = rect.height() / sampleSize; |
| 822 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && | 816 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && |
| 823 (h == decodedBitmap.height()) && bm->isNull(); | 817 (h == decodedBitmap.height()) && bm->isNull(); |
| 824 const bool needColorTable = SkBitmap::kIndex8_Config == config; | 818 const bool needColorTable = kIndex_8_SkColorType == colorType; |
| 825 if (swapOnly) { | 819 if (swapOnly) { |
| 826 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : N
ULL)) { | 820 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : N
ULL)) { |
| 827 return false; | 821 return false; |
| 828 } | 822 } |
| 829 } else { | 823 } else { |
| 830 if (!decodedBitmap.allocPixels(NULL, needColorTable ? colorTable : NULL)
) { | 824 if (!decodedBitmap.allocPixels(NULL, needColorTable ? colorTable : NULL)
) { |
| 831 return false; | 825 return false; |
| 832 } | 826 } |
| 833 } | 827 } |
| 834 SkAutoLockPixels alp(decodedBitmap); | 828 SkAutoLockPixels alp(decodedBitmap); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 849 #if defined(PNG_1_0_X) || defined (PNG_1_2_X) | 843 #if defined(PNG_1_0_X) || defined (PNG_1_2_X) |
| 850 png_ptr->pass = 0; | 844 png_ptr->pass = 0; |
| 851 #else | 845 #else |
| 852 // FIXME: This sets pass as desired, but also sets iwidth. Is that ok? | 846 // FIXME: This sets pass as desired, but also sets iwidth. Is that ok? |
| 853 png_set_interlaced_pass(png_ptr, 0); | 847 png_set_interlaced_pass(png_ptr, 0); |
| 854 #endif | 848 #endif |
| 855 png_read_update_info(png_ptr, info_ptr); | 849 png_read_update_info(png_ptr, info_ptr); |
| 856 | 850 |
| 857 int actualTop = rect.fTop; | 851 int actualTop = rect.fTop; |
| 858 | 852 |
| 859 if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config) | 853 if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) |
| 860 && 1 == sampleSize) { | 854 && 1 == sampleSize) { |
| 861 if (SkBitmap::kA8_Config == config) { | 855 if (kAlpha_8_SkColorType == colorType) { |
| 862 // For an A8 bitmap, we assume there is an alpha for speed. It is | 856 // For an A8 bitmap, we assume there is an alpha for speed. It is |
| 863 // possible the bitmap is opaque, but that is an unlikely use case | 857 // possible the bitmap is opaque, but that is an unlikely use case |
| 864 // since it would not be very interesting. | 858 // since it would not be very interesting. |
| 865 reallyHasAlpha = true; | 859 reallyHasAlpha = true; |
| 866 // A8 is only allowed if the original was GRAY. | 860 // A8 is only allowed if the original was GRAY. |
| 867 SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); | 861 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); |
| 868 } | 862 } |
| 869 | 863 |
| 870 for (int i = 0; i < number_passes; i++) { | 864 for (int i = 0; i < number_passes; i++) { |
| 871 png_configure_decoder(png_ptr, &actualTop, i); | 865 png_configure_decoder(png_ptr, &actualTop, i); |
| 872 for (int j = 0; j < rect.fTop - actualTop; j++) { | 866 for (int j = 0; j < rect.fTop - actualTop; j++) { |
| 873 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); | 867 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); |
| 874 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | 868 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); |
| 875 } | 869 } |
| 876 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); | 870 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); |
| 877 for (png_uint_32 y = 0; y < bitmapHeight; y++) { | 871 for (png_uint_32 y = 0; y < bitmapHeight; y++) { |
| 878 uint8_t* bmRow = decodedBitmap.getAddr8(0, y); | 872 uint8_t* bmRow = decodedBitmap.getAddr8(0, y); |
| 879 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | 873 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); |
| 880 } | 874 } |
| 881 } | 875 } |
| 882 } else { | 876 } else { |
| 883 SkScaledBitmapSampler::SrcConfig sc; | 877 SkScaledBitmapSampler::SrcConfig sc; |
| 884 int srcBytesPerPixel = 4; | 878 int srcBytesPerPixel = 4; |
| 885 | 879 |
| 886 if (colorTable != NULL) { | 880 if (colorTable != NULL) { |
| 887 sc = SkScaledBitmapSampler::kIndex; | 881 sc = SkScaledBitmapSampler::kIndex; |
| 888 srcBytesPerPixel = 1; | 882 srcBytesPerPixel = 1; |
| 889 } else if (SkBitmap::kA8_Config == config) { | 883 } else if (kAlpha_8_SkColorType == colorType) { |
| 890 // A8 is only allowed if the original was GRAY. | 884 // A8 is only allowed if the original was GRAY. |
| 891 SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); | 885 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); |
| 892 sc = SkScaledBitmapSampler::kGray; | 886 sc = SkScaledBitmapSampler::kGray; |
| 893 srcBytesPerPixel = 1; | 887 srcBytesPerPixel = 1; |
| 894 } else if (hasAlpha) { | 888 } else if (hasAlpha) { |
| 895 sc = SkScaledBitmapSampler::kRGBA; | 889 sc = SkScaledBitmapSampler::kRGBA; |
| 896 } else { | 890 } else { |
| 897 sc = SkScaledBitmapSampler::kRGBX; | 891 sc = SkScaledBitmapSampler::kRGBX; |
| 898 } | 892 } |
| 899 | 893 |
| 900 /* We have to pass the colortable explicitly, since we may have one | 894 /* We have to pass the colortable explicitly, since we may have one |
| 901 even if our decodedBitmap doesn't, due to the request that we | 895 even if our decodedBitmap doesn't, due to the request that we |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); | 944 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); |
| 951 } | 945 } |
| 952 } | 946 } |
| 953 } | 947 } |
| 954 } | 948 } |
| 955 | 949 |
| 956 if (0 != theTranspColor) { | 950 if (0 != theTranspColor) { |
| 957 reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor); | 951 reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor); |
| 958 } | 952 } |
| 959 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) { | 953 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) { |
| 960 switch (decodedBitmap.config()) { | 954 switch (decodedBitmap.colorType()) { |
| 961 case SkBitmap::kIndex8_Config: | 955 case kIndex_8_SkColorType: |
| 962 // Fall through. | 956 // Fall through. |
| 963 case SkBitmap::kARGB_4444_Config: | 957 case kARGB_4444_SkColorType: |
| 964 // We have chosen not to support unpremul for these configs. | 958 // We have chosen not to support unpremul for these colortypess. |
| 965 return false; | 959 return false; |
| 966 default: { | 960 default: { |
| 967 // Fall through to finish the decode. This config either | 961 // Fall through to finish the decode. This config either |
| 968 // supports unpremul or it is irrelevant because it has no | 962 // supports unpremul or it is irrelevant because it has no |
| 969 // alpha (or only alpha). | 963 // alpha (or only alpha). |
| 970 // These brackets prevent a warning. | 964 // These brackets prevent a warning. |
| 971 } | 965 } |
| 972 } | 966 } |
| 973 } | 967 } |
| 974 SkAlphaType alphaType = kOpaque_SkAlphaType; | 968 SkAlphaType alphaType = kOpaque_SkAlphaType; |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 return SkImageDecoder::kUnknown_Format; | 1281 return SkImageDecoder::kUnknown_Format; |
| 1288 } | 1282 } |
| 1289 | 1283 |
| 1290 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1284 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
| 1291 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1285 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
| 1292 } | 1286 } |
| 1293 | 1287 |
| 1294 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); | 1288 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); |
| 1295 static SkImageDecoder_FormatReg gFormatReg(get_format_png); | 1289 static SkImageDecoder_FormatReg gFormatReg(get_format_png); |
| 1296 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 1290 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
| OLD | NEW |