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 |