| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkImageDecoder.h" | 10 #include "SkImageDecoder.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 #ifdef SK_BUILD_FOR_ANDROID | 73 #ifdef SK_BUILD_FOR_ANDROID |
| 74 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_
OVERRIDE; | 74 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_
OVERRIDE; |
| 75 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVER
RIDE; | 75 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVER
RIDE; |
| 76 #endif | 76 #endif |
| 77 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 77 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
| 78 | 78 |
| 79 private: | 79 private: |
| 80 SkPNGImageIndex* fImageIndex; | 80 SkPNGImageIndex* fImageIndex; |
| 81 | 81 |
| 82 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p
trp); | 82 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p
trp); |
| 83 bool decodePalette(png_structp png_ptr, png_infop info_ptr, bool *hasAlphap, | 83 bool decodePalette(png_structp png_ptr, png_infop info_ptr, |
| 84 SkBitmap::Config finalConfig, bool *hasAlphap, |
| 84 bool *reallyHasAlphap, SkColorTable **colorTablep); | 85 bool *reallyHasAlphap, SkColorTable **colorTablep); |
| 85 bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr, | 86 bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr, |
| 86 SkBitmap::Config *config, bool *hasAlpha, | 87 SkBitmap::Config *config, bool *hasAlpha, |
| 87 bool *doDither, SkPMColor *theTranspColor); | 88 bool *doDither, SkPMColor *theTranspColor); |
| 88 | 89 |
| 89 typedef SkImageDecoder INHERITED; | 90 typedef SkImageDecoder INHERITED; |
| 90 }; | 91 }; |
| 91 | 92 |
| 92 #ifndef png_jmpbuf | 93 #ifndef png_jmpbuf |
| 93 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) | 94 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 void* rowptr = (void*) decodedBitmap->getPixels(); | 304 void* rowptr = (void*) decodedBitmap->getPixels(); |
| 304 bool reuseBitmap = (rowptr != NULL); | 305 bool reuseBitmap = (rowptr != NULL); |
| 305 decodedBitmap->unlockPixels(); | 306 decodedBitmap->unlockPixels(); |
| 306 if (reuseBitmap && (sampler.scaledWidth() != decodedBitmap->width() || | 307 if (reuseBitmap && (sampler.scaledWidth() != decodedBitmap->width() || |
| 307 sampler.scaledHeight() != decodedBitmap->height())) { | 308 sampler.scaledHeight() != decodedBitmap->height())) { |
| 308 // Dimensions must match | 309 // Dimensions must match |
| 309 return false; | 310 return false; |
| 310 } | 311 } |
| 311 | 312 |
| 312 if (!reuseBitmap) { | 313 if (!reuseBitmap) { |
| 314 bool premul = true; |
| 315 if (SkBitmap::kARGB_8888_Config == config && this->getRequestUnpremultip
liedColors()) { |
| 316 premul = false; |
| 317 } |
| 313 decodedBitmap->setConfig(config, sampler.scaledWidth(), | 318 decodedBitmap->setConfig(config, sampler.scaledWidth(), |
| 314 sampler.scaledHeight(), 0); | 319 sampler.scaledHeight(), 0, premul); |
| 315 } | 320 } |
| 316 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 321 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
| 317 return true; | 322 return true; |
| 318 } | 323 } |
| 319 | 324 |
| 320 // from here down we are concerned with colortables and pixels | 325 // from here down we are concerned with colortables and pixels |
| 321 | 326 |
| 322 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 327 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype |
| 323 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we | 328 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we |
| 324 // draw lots faster if we can flag the bitmap has being opaque | 329 // draw lots faster if we can flag the bitmap has being opaque |
| 325 bool reallyHasAlpha = false; | 330 bool reallyHasAlpha = false; |
| 326 SkColorTable* colorTable = NULL; | 331 SkColorTable* colorTable = NULL; |
| 327 | 332 |
| 328 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 333 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
| 329 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable
); | 334 decodePalette(png_ptr, info_ptr, config, &hasAlpha, &reallyHasAlpha, &co
lorTable); |
| 330 } | 335 } |
| 331 | 336 |
| 332 SkAutoUnref aur(colorTable); | 337 SkAutoUnref aur(colorTable); |
| 333 | 338 |
| 334 if (!reuseBitmap) { | 339 if (!reuseBitmap) { |
| 335 if (!this->allocPixelRef(decodedBitmap, | 340 if (!this->allocPixelRef(decodedBitmap, |
| 336 SkBitmap::kIndex8_Config == config ? colorTable
: NULL)) { | 341 SkBitmap::kIndex8_Config == config ? colorTable
: NULL)) { |
| 337 return false; | 342 return false; |
| 338 } | 343 } |
| 339 } | 344 } |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 } | 547 } |
| 543 // now check that if we are 4-bytes per pixel, we also don't overflow | 548 // now check that if we are 4-bytes per pixel, we also don't overflow |
| 544 if (size.get32() > (0x7FFFFFFF >> 2)) { | 549 if (size.get32() > (0x7FFFFFFF >> 2)) { |
| 545 return false; | 550 return false; |
| 546 } | 551 } |
| 547 } | 552 } |
| 548 | 553 |
| 549 return this->chooseFromOneChoice(*configp, origWidth, origHeight); | 554 return this->chooseFromOneChoice(*configp, origWidth, origHeight); |
| 550 } | 555 } |
| 551 | 556 |
| 557 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); |
| 558 |
| 552 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, | 559 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, |
| 553 bool *hasAlphap, bool *reallyHasAlphap, | 560 SkBitmap::Config finalConfig, bool *hasAlp
hap, |
| 554 SkColorTable **colorTablep) { | 561 bool *reallyHasAlphap, SkColorTable **colo
rTablep) { |
| 555 int numPalette; | 562 int numPalette; |
| 556 png_colorp palette; | 563 png_colorp palette; |
| 557 png_bytep trans; | 564 png_bytep trans; |
| 558 int numTrans; | 565 int numTrans; |
| 559 bool reallyHasAlpha = false; | 566 bool reallyHasAlpha = false; |
| 560 SkColorTable* colorTable = NULL; | 567 SkColorTable* colorTable = NULL; |
| 561 | 568 |
| 562 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); | 569 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); |
| 563 | 570 |
| 564 /* BUGGY IMAGE WORKAROUND | 571 /* BUGGY IMAGE WORKAROUND |
| (...skipping 15 matching lines...) Expand all Loading... |
| 580 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOp
aque_Flag); | 587 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOp
aque_Flag); |
| 581 } | 588 } |
| 582 // check for bad images that might make us crash | 589 // check for bad images that might make us crash |
| 583 if (numTrans > numPalette) { | 590 if (numTrans > numPalette) { |
| 584 numTrans = numPalette; | 591 numTrans = numPalette; |
| 585 } | 592 } |
| 586 | 593 |
| 587 int index = 0; | 594 int index = 0; |
| 588 int transLessThanFF = 0; | 595 int transLessThanFF = 0; |
| 589 | 596 |
| 597 // Choose which function to use to create the color table. If the final dest
ination's |
| 598 // config is unpremultiplied, the color table will store unpremultiplied col
ors. |
| 599 PackColorProc proc; |
| 600 if (SkBitmap::kARGB_8888_Config == finalConfig && this->getRequestUnpremulti
pliedColors()) { |
| 601 proc = &SkPackARGB32NoCheck; |
| 602 } else { |
| 603 proc = &SkPreMultiplyARGB; |
| 604 } |
| 590 for (; index < numTrans; index++) { | 605 for (; index < numTrans; index++) { |
| 591 transLessThanFF |= (int)*trans - 0xFF; | 606 transLessThanFF |= (int)*trans - 0xFF; |
| 592 *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green,
palette->blue); | 607 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue
); |
| 593 palette++; | 608 palette++; |
| 594 } | 609 } |
| 595 reallyHasAlpha |= (transLessThanFF < 0); | 610 reallyHasAlpha |= (transLessThanFF < 0); |
| 596 | 611 |
| 597 for (; index < numPalette; index++) { | 612 for (; index < numPalette; index++) { |
| 598 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->
blue); | 613 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->
blue); |
| 599 palette++; | 614 palette++; |
| 600 } | 615 } |
| 601 | 616 |
| 602 // see BUGGY IMAGE WORKAROUND comment above | 617 // see BUGGY IMAGE WORKAROUND comment above |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 SkPMColor theTranspColor = 0; // 0 tells us not to try to match | 687 SkPMColor theTranspColor = 0; // 0 tells us not to try to match |
| 673 | 688 |
| 674 if (!getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither, &theT
ranspColor)) { | 689 if (!getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither, &theT
ranspColor)) { |
| 675 return false; | 690 return false; |
| 676 } | 691 } |
| 677 | 692 |
| 678 const int sampleSize = this->getSampleSize(); | 693 const int sampleSize = this->getSampleSize(); |
| 679 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); | 694 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); |
| 680 | 695 |
| 681 SkBitmap decodedBitmap; | 696 SkBitmap decodedBitmap; |
| 682 decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(
), 0); | 697 bool premul = true; |
| 698 if (SkBitmap::kARGB_8888_Config == config && this->getRequestUnpremultiplied
Colors()) { |
| 699 premul = false; |
| 700 } |
| 701 decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(
), 0, premul); |
| 683 | 702 |
| 684 // from here down we are concerned with colortables and pixels | 703 // from here down we are concerned with colortables and pixels |
| 685 | 704 |
| 686 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 705 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype |
| 687 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we | 706 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we |
| 688 // draw lots faster if we can flag the bitmap has being opaque | 707 // draw lots faster if we can flag the bitmap has being opaque |
| 689 bool reallyHasAlpha = false; | 708 bool reallyHasAlpha = false; |
| 690 SkColorTable* colorTable = NULL; | 709 SkColorTable* colorTable = NULL; |
| 691 | 710 |
| 692 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 711 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
| 693 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable
); | 712 decodePalette(png_ptr, info_ptr, config, &hasAlpha, &reallyHasAlpha, &co
lorTable); |
| 694 } | 713 } |
| 695 | 714 |
| 696 SkAutoUnref aur(colorTable); | 715 SkAutoUnref aur(colorTable); |
| 697 | 716 |
| 698 // Check ahead of time if the swap(dest, src) is possible. | 717 // Check ahead of time if the swap(dest, src) is possible. |
| 699 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. | 718 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. |
| 700 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. | 719 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. |
| 701 int w = rect.width() / sampleSize; | 720 int w = rect.width() / sampleSize; |
| 702 int h = rect.height() / sampleSize; | 721 int h = rect.height() / sampleSize; |
| 703 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && | 722 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1137 return SkImageDecoder::kUnknown_Format; | 1156 return SkImageDecoder::kUnknown_Format; |
| 1138 } | 1157 } |
| 1139 | 1158 |
| 1140 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1159 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
| 1141 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1160 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
| 1142 } | 1161 } |
| 1143 | 1162 |
| 1144 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto
ry); | 1163 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto
ry); |
| 1145 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png)
; | 1164 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png)
; |
| 1146 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); | 1165 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); |
| OLD | NEW |