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

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: 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
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 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
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
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
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
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
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);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698