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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 sc = SkScaledBitmapSampler::kRGBA; | 377 sc = SkScaledBitmapSampler::kRGBA; |
377 } else { | 378 } else { |
378 sc = SkScaledBitmapSampler::kRGBX; | 379 sc = SkScaledBitmapSampler::kRGBX; |
379 } | 380 } |
380 | 381 |
381 /* We have to pass the colortable explicitly, since we may have one | 382 /* We have to pass the colortable explicitly, since we may have one |
382 even if our decodedBitmap doesn't, due to the request that we | 383 even if our decodedBitmap doesn't, due to the request that we |
383 upscale png's palette to a direct model | 384 upscale png's palette to a direct model |
384 */ | 385 */ |
385 SkAutoLockColors ctLock(colorTable); | 386 SkAutoLockColors ctLock(colorTable); |
386 if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) { | 387 if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors(), |
| 388 this->getRequireUnpremultipliedColors())) { |
387 return false; | 389 return false; |
388 } | 390 } |
389 const int height = decodedBitmap->height(); | 391 const int height = decodedBitmap->height(); |
390 | 392 |
391 if (number_passes > 1) { | 393 if (number_passes > 1) { |
392 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); | 394 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); |
393 uint8_t* base = (uint8_t*)storage.get(); | 395 uint8_t* base = (uint8_t*)storage.get(); |
394 size_t rowBytes = origWidth * srcBytesPerPixel; | 396 size_t rowBytes = origWidth * srcBytesPerPixel; |
395 | 397 |
396 for (int i = 0; i < number_passes; i++) { | 398 for (int i = 0; i < number_passes; i++) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 skip_src_rows(png_ptr, srcRow, origHeight - read); | 430 skip_src_rows(png_ptr, srcRow, origHeight - read); |
429 } | 431 } |
430 } | 432 } |
431 | 433 |
432 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ | 434 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ |
433 png_read_end(png_ptr, info_ptr); | 435 png_read_end(png_ptr, info_ptr); |
434 | 436 |
435 if (0 != theTranspColor) { | 437 if (0 != theTranspColor) { |
436 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); | 438 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); |
437 } | 439 } |
| 440 if (reallyHasAlpha && this->getRequireUnpremultipliedColors() && |
| 441 SkBitmap::kARGB_8888_Config != decodedBitmap->config()) { |
| 442 // If the caller wants an unpremultiplied bitmap, and we let them get |
| 443 // away with a config other than 8888, and it has alpha after all, |
| 444 // return false, since the result will have premultiplied colors. |
| 445 return false; |
| 446 } |
438 decodedBitmap->setIsOpaque(!reallyHasAlpha); | 447 decodedBitmap->setIsOpaque(!reallyHasAlpha); |
439 if (reuseBitmap) { | 448 if (reuseBitmap) { |
440 decodedBitmap->notifyPixelsChanged(); | 449 decodedBitmap->notifyPixelsChanged(); |
441 } | 450 } |
442 return true; | 451 return true; |
443 } | 452 } |
444 | 453 |
445 | 454 |
446 | 455 |
447 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, | 456 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, |
448 SkBitmap::Config *configp, bool *hasAlph
ap, | 457 SkBitmap::Config *configp, bool * SK_RES
TRICT hasAlphap, |
449 bool *doDitherp, SkPMColor *theTranspCol
orp) { | 458 bool *doDitherp, SkPMColor *theTranspCol
orp) { |
450 png_uint_32 origWidth, origHeight; | 459 png_uint_32 origWidth, origHeight; |
451 int bitDepth, colorType; | 460 int bitDepth, colorType; |
452 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 461 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, |
453 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 462 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); |
454 | 463 |
455 // check for sBIT chunk data, in case we should disable dithering because | 464 // check for sBIT chunk data, in case we should disable dithering because |
456 // our data is not truely 8bits per component | 465 // our data is not truely 8bits per component |
457 png_color_8p sig_bit; | 466 png_color_8p sig_bit; |
458 if (*doDitherp && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { | 467 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); | 548 size.setMul(origWidth, origHeight); |
540 if (size.isNeg() || !size.is32()) { | 549 if (size.isNeg() || !size.is32()) { |
541 return false; | 550 return false; |
542 } | 551 } |
543 // now check that if we are 4-bytes per pixel, we also don't overflow | 552 // now check that if we are 4-bytes per pixel, we also don't overflow |
544 if (size.get32() > (0x7FFFFFFF >> 2)) { | 553 if (size.get32() > (0x7FFFFFFF >> 2)) { |
545 return false; | 554 return false; |
546 } | 555 } |
547 } | 556 } |
548 | 557 |
549 return this->chooseFromOneChoice(*configp, origWidth, origHeight); | 558 if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) { |
| 559 return false; |
| 560 } |
| 561 |
| 562 // If the image has alpha and the decoder wants unpremultiplied |
| 563 // colors, the only supported config is 8888. |
| 564 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { |
| 565 *configp = SkBitmap::kARGB_8888_Config; |
| 566 } |
| 567 return true; |
550 } | 568 } |
551 | 569 |
| 570 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); |
| 571 |
552 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, | 572 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, |
553 bool *hasAlphap, bool *reallyHasAlphap, | 573 bool *hasAlphap, bool *reallyHasAlphap, |
554 SkColorTable **colorTablep) { | 574 SkColorTable **colorTablep) { |
555 int numPalette; | 575 int numPalette; |
556 png_colorp palette; | 576 png_colorp palette; |
557 png_bytep trans; | 577 png_bytep trans; |
558 int numTrans; | 578 int numTrans; |
559 bool reallyHasAlpha = false; | 579 bool reallyHasAlpha = false; |
560 SkColorTable* colorTable = NULL; | 580 SkColorTable* colorTable = NULL; |
561 | 581 |
(...skipping 18 matching lines...) Expand all Loading... |
580 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOp
aque_Flag); | 600 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOp
aque_Flag); |
581 } | 601 } |
582 // check for bad images that might make us crash | 602 // check for bad images that might make us crash |
583 if (numTrans > numPalette) { | 603 if (numTrans > numPalette) { |
584 numTrans = numPalette; | 604 numTrans = numPalette; |
585 } | 605 } |
586 | 606 |
587 int index = 0; | 607 int index = 0; |
588 int transLessThanFF = 0; | 608 int transLessThanFF = 0; |
589 | 609 |
| 610 // Choose which function to use to create the color table. If the final dest
ination's |
| 611 // config is unpremultiplied, the color table will store unpremultiplied col
ors. |
| 612 PackColorProc proc; |
| 613 if (this->getRequireUnpremultipliedColors()) { |
| 614 proc = &SkPackARGB32NoCheck; |
| 615 } else { |
| 616 proc = &SkPreMultiplyARGB; |
| 617 } |
590 for (; index < numTrans; index++) { | 618 for (; index < numTrans; index++) { |
591 transLessThanFF |= (int)*trans - 0xFF; | 619 transLessThanFF |= (int)*trans - 0xFF; |
592 *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green,
palette->blue); | 620 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue
); |
593 palette++; | 621 palette++; |
594 } | 622 } |
595 reallyHasAlpha |= (transLessThanFF < 0); | 623 reallyHasAlpha |= (transLessThanFF < 0); |
596 | 624 |
597 for (; index < numPalette; index++) { | 625 for (; index < numPalette; index++) { |
598 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->
blue); | 626 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->
blue); |
599 palette++; | 627 palette++; |
600 } | 628 } |
601 | 629 |
602 // see BUGGY IMAGE WORKAROUND comment above | 630 // 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 | 700 SkPMColor theTranspColor = 0; // 0 tells us not to try to match |
673 | 701 |
674 if (!getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither, &theT
ranspColor)) { | 702 if (!getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither, &theT
ranspColor)) { |
675 return false; | 703 return false; |
676 } | 704 } |
677 | 705 |
678 const int sampleSize = this->getSampleSize(); | 706 const int sampleSize = this->getSampleSize(); |
679 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); | 707 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); |
680 | 708 |
681 SkBitmap decodedBitmap; | 709 SkBitmap decodedBitmap; |
682 decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(
), 0); | 710 decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(
)); |
683 | 711 |
684 // from here down we are concerned with colortables and pixels | 712 // from here down we are concerned with colortables and pixels |
685 | 713 |
686 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 714 // 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 | 715 // 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 | 716 // draw lots faster if we can flag the bitmap has being opaque |
689 bool reallyHasAlpha = false; | 717 bool reallyHasAlpha = false; |
690 SkColorTable* colorTable = NULL; | 718 SkColorTable* colorTable = NULL; |
691 | 719 |
692 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 720 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 sc = SkScaledBitmapSampler::kRGBA; | 794 sc = SkScaledBitmapSampler::kRGBA; |
767 } else { | 795 } else { |
768 sc = SkScaledBitmapSampler::kRGBX; | 796 sc = SkScaledBitmapSampler::kRGBX; |
769 } | 797 } |
770 | 798 |
771 /* We have to pass the colortable explicitly, since we may have one | 799 /* We have to pass the colortable explicitly, since we may have one |
772 even if our decodedBitmap doesn't, due to the request that we | 800 even if our decodedBitmap doesn't, due to the request that we |
773 upscale png's palette to a direct model | 801 upscale png's palette to a direct model |
774 */ | 802 */ |
775 SkAutoLockColors ctLock(colorTable); | 803 SkAutoLockColors ctLock(colorTable); |
776 if (!sampler.begin(&decodedBitmap, sc, doDither, ctLock.colors())) { | 804 if (!sampler.begin(&decodedBitmap, sc, doDither, ctLock.colors(), |
| 805 this->getRequireUnpremultipliedColors())) { |
777 return false; | 806 return false; |
778 } | 807 } |
779 const int height = decodedBitmap.height(); | 808 const int height = decodedBitmap.height(); |
780 | 809 |
781 if (number_passes > 1) { | 810 if (number_passes > 1) { |
782 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); | 811 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); |
783 uint8_t* base = (uint8_t*)storage.get(); | 812 uint8_t* base = (uint8_t*)storage.get(); |
784 size_t rb = origWidth * srcBytesPerPixel; | 813 size_t rb = origWidth * srcBytesPerPixel; |
785 | 814 |
786 for (int i = 0; i < number_passes; i++) { | 815 for (int i = 0; i < number_passes; i++) { |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 return SkImageDecoder::kUnknown_Format; | 1166 return SkImageDecoder::kUnknown_Format; |
1138 } | 1167 } |
1139 | 1168 |
1140 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1169 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
1141 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; | 1170 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; |
1142 } | 1171 } |
1143 | 1172 |
1144 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto
ry); | 1173 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto
ry); |
1145 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png)
; | 1174 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png)
; |
1146 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); | 1175 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); |
OLD | NEW |