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 bool *reallyHasAlphap, SkColorTable **colorTablep); | 84 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, |
| 85 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) |
94 #endif | 95 #endif |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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) { |
313 decodedBitmap->setConfig(config, sampler.scaledWidth(), | 314 decodedBitmap->setConfig(config, sampler.scaledWidth(), |
314 sampler.scaledHeight(), 0); | 315 sampler.scaledHeight()); |
315 } | 316 } |
316 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 317 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
317 return true; | 318 return true; |
318 } | 319 } |
319 | 320 |
320 // from here down we are concerned with colortables and pixels | 321 // from here down we are concerned with colortables and pixels |
321 | 322 |
322 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 323 // 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 | 324 // 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 | 325 // draw lots faster if we can flag the bitmap has being opaque |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 skip_src_rows(png_ptr, srcRow, origHeight - read); | 429 skip_src_rows(png_ptr, srcRow, origHeight - read); |
429 } | 430 } |
430 } | 431 } |
431 | 432 |
432 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ | 433 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ |
433 png_read_end(png_ptr, info_ptr); | 434 png_read_end(png_ptr, info_ptr); |
434 | 435 |
435 if (0 != theTranspColor) { | 436 if (0 != theTranspColor) { |
436 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); | 437 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); |
437 } | 438 } |
| 439 if (reallyHasAlpha && this->getRequireUnpremultipliedColors() && |
| 440 SkBitmap::kARGB_8888_Config != decodedBitmap->config()) { |
| 441 // If the caller wants an unpremultiplied bitmap, and we let them get |
| 442 // away with a config other than 8888, and it has alpha after all, |
| 443 // return false, since the result will have premultiplied colors. |
| 444 return false; |
| 445 } |
438 decodedBitmap->setIsOpaque(!reallyHasAlpha); | 446 decodedBitmap->setIsOpaque(!reallyHasAlpha); |
439 if (reuseBitmap) { | 447 if (reuseBitmap) { |
440 decodedBitmap->notifyPixelsChanged(); | 448 decodedBitmap->notifyPixelsChanged(); |
441 } | 449 } |
442 return true; | 450 return true; |
443 } | 451 } |
444 | 452 |
445 | 453 |
446 | 454 |
447 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, | 455 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, |
448 SkBitmap::Config *configp, bool *hasAlph
ap, | 456 SkBitmap::Config *configp, bool * SK_RES
TRICT hasAlphap, |
449 bool *doDitherp, SkPMColor *theTranspCol
orp) { | 457 bool *doDitherp, SkPMColor *theTranspCol
orp) { |
450 png_uint_32 origWidth, origHeight; | 458 png_uint_32 origWidth, origHeight; |
451 int bitDepth, colorType; | 459 int bitDepth, colorType; |
452 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 460 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
453 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 461 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); |
454 | 462 |
455 // check for sBIT chunk data, in case we should disable dithering because | 463 // check for sBIT chunk data, in case we should disable dithering because |
456 // our data is not truely 8bits per component | 464 // our data is not truely 8bits per component |
457 png_color_8p sig_bit; | 465 png_color_8p sig_bit; |
458 if (*doDitherp && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { | 466 if (*doDitherp && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 size.setMul(origWidth, origHeight); | 547 size.setMul(origWidth, origHeight); |
540 if (size.isNeg() || !size.is32()) { | 548 if (size.isNeg() || !size.is32()) { |
541 return false; | 549 return false; |
542 } | 550 } |
543 // now check that if we are 4-bytes per pixel, we also don't overflow | 551 // now check that if we are 4-bytes per pixel, we also don't overflow |
544 if (size.get32() > (0x7FFFFFFF >> 2)) { | 552 if (size.get32() > (0x7FFFFFFF >> 2)) { |
545 return false; | 553 return false; |
546 } | 554 } |
547 } | 555 } |
548 | 556 |
549 return this->chooseFromOneChoice(*configp, origWidth, origHeight); | 557 if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) { |
| 558 return false; |
| 559 } |
| 560 |
| 561 // If the image has alpha and the decoder wants unpremultiplied |
| 562 // colors, the only supported config is 8888. |
| 563 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { |
| 564 *configp = SkBitmap::kARGB_8888_Config; |
| 565 } |
| 566 return true; |
550 } | 567 } |
551 | 568 |
| 569 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); |
| 570 |
552 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, | 571 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, |
553 bool *hasAlphap, bool *reallyHasAlphap, | 572 bool *hasAlphap, bool *reallyHasAlphap, |
554 SkColorTable **colorTablep) { | 573 SkColorTable **colorTablep) { |
555 int numPalette; | 574 int numPalette; |
556 png_colorp palette; | 575 png_colorp palette; |
557 png_bytep trans; | 576 png_bytep trans; |
558 int numTrans; | 577 int numTrans; |
559 bool reallyHasAlpha = false; | 578 bool reallyHasAlpha = false; |
560 SkColorTable* colorTable = NULL; | 579 SkColorTable* colorTable = NULL; |
561 | 580 |
(...skipping 18 matching lines...) Expand all Loading... |
580 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOp
aque_Flag); | 599 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOp
aque_Flag); |
581 } | 600 } |
582 // check for bad images that might make us crash | 601 // check for bad images that might make us crash |
583 if (numTrans > numPalette) { | 602 if (numTrans > numPalette) { |
584 numTrans = numPalette; | 603 numTrans = numPalette; |
585 } | 604 } |
586 | 605 |
587 int index = 0; | 606 int index = 0; |
588 int transLessThanFF = 0; | 607 int transLessThanFF = 0; |
589 | 608 |
| 609 // Choose which function to use to create the color table. If the final dest
ination's |
| 610 // config is unpremultiplied, the color table will store unpremultiplied col
ors. |
| 611 PackColorProc proc; |
| 612 if (this->getRequireUnpremultipliedColors()) { |
| 613 proc = &SkPackARGB32NoCheck; |
| 614 } else { |
| 615 proc = &SkPreMultiplyARGB; |
| 616 } |
590 for (; index < numTrans; index++) { | 617 for (; index < numTrans; index++) { |
591 transLessThanFF |= (int)*trans - 0xFF; | 618 transLessThanFF |= (int)*trans - 0xFF; |
592 *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green,
palette->blue); | 619 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue
); |
593 palette++; | 620 palette++; |
594 } | 621 } |
595 reallyHasAlpha |= (transLessThanFF < 0); | 622 reallyHasAlpha |= (transLessThanFF < 0); |
596 | 623 |
597 for (; index < numPalette; index++) { | 624 for (; index < numPalette; index++) { |
598 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->
blue); | 625 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->
blue); |
599 palette++; | 626 palette++; |
600 } | 627 } |
601 | 628 |
602 // see BUGGY IMAGE WORKAROUND comment above | 629 // 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 | 699 SkPMColor theTranspColor = 0; // 0 tells us not to try to match |
673 | 700 |
674 if (!getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither, &theT
ranspColor)) { | 701 if (!getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither, &theT
ranspColor)) { |
675 return false; | 702 return false; |
676 } | 703 } |
677 | 704 |
678 const int sampleSize = this->getSampleSize(); | 705 const int sampleSize = this->getSampleSize(); |
679 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); | 706 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); |
680 | 707 |
681 SkBitmap decodedBitmap; | 708 SkBitmap decodedBitmap; |
682 decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(
), 0); | 709 decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(
)); |
683 | 710 |
684 // from here down we are concerned with colortables and pixels | 711 // from here down we are concerned with colortables and pixels |
685 | 712 |
686 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 713 // 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 | 714 // 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 | 715 // draw lots faster if we can flag the bitmap has being opaque |
689 bool reallyHasAlpha = false; | 716 bool reallyHasAlpha = false; |
690 SkColorTable* colorTable = NULL; | 717 SkColorTable* colorTable = NULL; |
691 | 718 |
692 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 719 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
693 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable
); | 720 decodePalette(png_ptr, info_ptr, config, &hasAlpha, &reallyHasAlpha, &co
lorTable); |
694 } | 721 } |
695 | 722 |
696 SkAutoUnref aur(colorTable); | 723 SkAutoUnref aur(colorTable); |
697 | 724 |
698 // Check ahead of time if the swap(dest, src) is possible. | 725 // 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. | 726 // 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. | 727 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. |
701 int w = rect.width() / sampleSize; | 728 int w = rect.width() / sampleSize; |
702 int h = rect.height() / sampleSize; | 729 int h = rect.height() / sampleSize; |
703 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && | 730 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; | 1164 return SkImageDecoder::kUnknown_Format; |
1138 } | 1165 } |
1139 | 1166 |
1140 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1167 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
1141 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1168 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
1142 } | 1169 } |
1143 | 1170 |
1144 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto
ry); | 1171 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto
ry); |
1145 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png)
; | 1172 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png)
; |
1146 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); | 1173 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); |
OLD | NEW |