Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: src/images/SkImageDecoder_libpng.cpp

Issue 16410009: Add an option to create unpremultiplied bitmaps. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Fix for andriod only code. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/images/SkImageDecoder.cpp ('k') | src/images/SkImageDecoder_libwebp.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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);
OLDNEW
« no previous file with comments | « src/images/SkImageDecoder.cpp ('k') | src/images/SkImageDecoder_libwebp.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698