diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/images/SkImageDecoder.cpp | 3 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libpng.cpp | 47 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libwebp.cpp | 35 | ||||
-rw-r--r-- | src/images/SkScaledBitmapSampler.cpp | 105 | ||||
-rw-r--r-- | src/images/SkScaledBitmapSampler.h | 2 | ||||
-rw-r--r-- | src/ports/SkImageDecoder_WIC.cpp | 9 |
6 files changed, 150 insertions, 51 deletions
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp index 5c078ce630..38aa7fda0d 100644 --- a/src/images/SkImageDecoder.cpp +++ b/src/images/SkImageDecoder.cpp @@ -40,7 +40,8 @@ SkImageDecoder::SkImageDecoder() , fDefaultPref(SkBitmap::kNo_Config) , fDitherImage(true) , fUsePrefTable(false) - , fPreferQualityOverSpeed(false) { + , fPreferQualityOverSpeed(false) + , fRequireUnpremultipliedColors(false) { } SkImageDecoder::~SkImageDecoder() { diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp index d967a69e84..729f87169a 100644 --- a/src/images/SkImageDecoder_libpng.cpp +++ b/src/images/SkImageDecoder_libpng.cpp @@ -80,8 +80,9 @@ private: SkPNGImageIndex* fImageIndex; bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_ptrp); - bool decodePalette(png_structp png_ptr, png_infop info_ptr, bool *hasAlphap, - bool *reallyHasAlphap, SkColorTable **colorTablep); + bool decodePalette(png_structp png_ptr, png_infop info_ptr, + bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, + SkColorTable **colorTablep); bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr, SkBitmap::Config *config, bool *hasAlpha, bool *doDither, SkPMColor *theTranspColor); @@ -311,7 +312,7 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, if (!reuseBitmap) { decodedBitmap->setConfig(config, sampler.scaledWidth(), - sampler.scaledHeight(), 0); + sampler.scaledHeight()); } if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; @@ -383,7 +384,8 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, upscale png's palette to a direct model */ SkAutoLockColors ctLock(colorTable); - if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) { + if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors(), + this->getRequireUnpremultipliedColors())) { return false; } const int height = decodedBitmap->height(); @@ -435,6 +437,13 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, if (0 != theTranspColor) { reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); } + if (reallyHasAlpha && this->getRequireUnpremultipliedColors() && + SkBitmap::kARGB_8888_Config != decodedBitmap->config()) { + // If the caller wants an unpremultiplied bitmap, and we let them get + // away with a config other than 8888, and it has alpha after all, + // return false, since the result will have premultiplied colors. + return false; + } decodedBitmap->setIsOpaque(!reallyHasAlpha); if (reuseBitmap) { decodedBitmap->notifyPixelsChanged(); @@ -445,7 +454,7 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, - SkBitmap::Config *configp, bool *hasAlphap, + SkBitmap::Config *configp, bool * SK_RESTRICT hasAlphap, bool *doDitherp, SkPMColor *theTranspColorp) { png_uint_32 origWidth, origHeight; int bitDepth, colorType; @@ -546,9 +555,20 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, } } - return this->chooseFromOneChoice(*configp, origWidth, origHeight); + if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) { + return false; + } + + // If the image has alpha and the decoder wants unpremultiplied + // colors, the only supported config is 8888. + if (this->getRequireUnpremultipliedColors() && *hasAlphap) { + *configp = SkBitmap::kARGB_8888_Config; + } + return true; } +typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); + bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, bool *hasAlphap, bool *reallyHasAlphap, SkColorTable **colorTablep) { @@ -587,9 +607,17 @@ bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, int index = 0; int transLessThanFF = 0; + // Choose which function to use to create the color table. If the final destination's + // config is unpremultiplied, the color table will store unpremultiplied colors. + PackColorProc proc; + if (this->getRequireUnpremultipliedColors()) { + proc = &SkPackARGB32NoCheck; + } else { + proc = &SkPreMultiplyARGB; + } for (; index < numTrans; index++) { transLessThanFF |= (int)*trans - 0xFF; - *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green, palette->blue); + *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue); palette++; } reallyHasAlpha |= (transLessThanFF < 0); @@ -679,7 +707,7 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); SkBitmap decodedBitmap; - decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0); + decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); // from here down we are concerned with colortables and pixels @@ -773,7 +801,8 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { upscale png's palette to a direct model */ SkAutoLockColors ctLock(colorTable); - if (!sampler.begin(&decodedBitmap, sc, doDither, ctLock.colors())) { + if (!sampler.begin(&decodedBitmap, sc, doDither, ctLock.colors(), + this->getRequireUnpremultipliedColors())) { return false; } const int height = decodedBitmap.height(); diff --git a/src/images/SkImageDecoder_libwebp.cpp b/src/images/SkImageDecoder_libwebp.cpp index 95b9a97878..9cf84493ad 100644 --- a/src/images/SkImageDecoder_libwebp.cpp +++ b/src/images/SkImageDecoder_libwebp.cpp @@ -114,7 +114,17 @@ protected: virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; private: + /** + * Called when determining the output config to request to webp. + * If the image does not have alpha, there is no need to premultiply. + * If the caller wants unpremultiplied colors, that is respected. + */ + bool shouldPremultiply() const { + return SkToBool(fHasAlpha) && !this->getRequireUnpremultipliedColors(); + } + bool setDecodeConfig(SkBitmap* decodedBitmap, int width, int height); + SkStream* fInputStream; int fOrigWidth; int fOrigHeight; @@ -157,18 +167,16 @@ static bool return_false(const SkBitmap& bm, const char msg[]) { return false; // must always return false } -static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, int hasAlpha) { +static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, bool premultiply) { WEBP_CSP_MODE mode = MODE_LAST; SkBitmap::Config config = decodedBitmap->config(); - // For images that have alpha, choose appropriate color mode (MODE_rgbA, - // MODE_rgbA_4444) that pre-multiplies RGB pixel values with transparency - // factor (alpha). + if (config == SkBitmap::kARGB_8888_Config) { - mode = hasAlpha ? MODE_rgbA : MODE_RGBA; + mode = premultiply ? MODE_rgbA : MODE_RGBA; } else if (config == SkBitmap::kARGB_4444_Config) { - mode = hasAlpha ? MODE_rgbA_4444 : MODE_RGBA_4444; + mode = premultiply ? MODE_rgbA_4444 : MODE_RGBA_4444; } else if (config == SkBitmap::kRGB_565_Config) { - mode = MODE_RGB_565; + mode = MODE_RGB_565; } SkASSERT(MODE_LAST != mode); return mode; @@ -224,8 +232,8 @@ static bool webp_idecode(SkStream* stream, WebPDecoderConfig* config) { static bool webp_get_config_resize(WebPDecoderConfig* config, SkBitmap* decodedBitmap, - int width, int height, int hasAlpha) { - WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap, hasAlpha); + int width, int height, bool premultiply) { + WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap, premultiply); if (MODE_LAST == mode) { return false; } @@ -251,10 +259,10 @@ static bool webp_get_config_resize(WebPDecoderConfig* config, static bool webp_get_config_resize_crop(WebPDecoderConfig* config, SkBitmap* decodedBitmap, - const SkIRect& region, int hasAlpha) { + const SkIRect& region, bool premultiply) { if (!webp_get_config_resize(config, decodedBitmap, region.width(), - region.height(), hasAlpha)) { + region.height(), premultiply)) { return false; } @@ -372,7 +380,8 @@ bool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap, SkAutoLockPixels alp(*bitmap); WebPDecoderConfig config; - if (!webp_get_config_resize_crop(&config, bitmap, rect, fHasAlpha)) { + if (!webp_get_config_resize_crop(&config, bitmap, rect, + this->shouldPremultiply())) { return false; } @@ -430,7 +439,7 @@ bool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap, WebPDecoderConfig config; if (!webp_get_config_resize(&config, decodedBitmap, origWidth, origHeight, - hasAlpha)) { + this->shouldPremultiply())) { return false; } diff --git a/src/images/SkScaledBitmapSampler.cpp b/src/images/SkScaledBitmapSampler.cpp index 25b32fd9b8..ca41de9396 100644 --- a/src/images/SkScaledBitmapSampler.cpp +++ b/src/images/SkScaledBitmapSampler.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2007 The Android Open Source Project * @@ -11,6 +10,7 @@ #include "SkBitmap.h" #include "SkColorPriv.h" #include "SkDither.h" +#include "SkTypes.h" // 8888 @@ -289,6 +289,41 @@ static bool Sample_Index_DI(void* SK_RESTRICT dstRow, return false; } +// 8888 Unpremul + +static bool Sample_Gray_D8888_Unpremul(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor[]) { + uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); + for (int x = 0; x < width; x++) { + dst[x] = SkPackARGB32NoCheck(0xFF, src[0], src[0], src[0]); + src += deltaSrc; + } + return false; +} + +// Sample_RGBx_D8888_Unpremul is no different from Sample_RGBx_D8888, since alpha +// is 0xFF + +static bool Sample_RGBA_D8888_Unpremul(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor[]) { + uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); + unsigned alphaMask = 0xFF; + for (int x = 0; x < width; x++) { + unsigned alpha = src[3]; + dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} + +// Sample_Index_D8888_Unpremul is the same as Sample_Index_D8888, since the +// color table has its colors inserted unpremultiplied. + /////////////////////////////////////////////////////////////////////////////// #include "SkScaledBitmapSampler.h" @@ -334,33 +369,44 @@ SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height, } bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither, - const SkPMColor ctable[]) { + const SkPMColor ctable[], + bool requireUnpremul) { static const RowProc gProcs[] = { // 8888 (no dither distinction) - Sample_Gray_D8888, Sample_Gray_D8888, - Sample_RGBx_D8888, Sample_RGBx_D8888, - Sample_RGBA_D8888, Sample_RGBA_D8888, - Sample_Index_D8888, Sample_Index_D8888, - NULL, NULL, + Sample_Gray_D8888, Sample_Gray_D8888, + Sample_RGBx_D8888, Sample_RGBx_D8888, + Sample_RGBA_D8888, Sample_RGBA_D8888, + Sample_Index_D8888, Sample_Index_D8888, + NULL, NULL, // 565 (no alpha distinction) - Sample_Gray_D565, Sample_Gray_D565_D, - Sample_RGBx_D565, Sample_RGBx_D565_D, - Sample_RGBx_D565, Sample_RGBx_D565_D, - Sample_Index_D565, Sample_Index_D565_D, - Sample_D565_D565, Sample_D565_D565, + Sample_Gray_D565, Sample_Gray_D565_D, + Sample_RGBx_D565, Sample_RGBx_D565_D, + Sample_RGBx_D565, Sample_RGBx_D565_D, + Sample_Index_D565, Sample_Index_D565_D, + Sample_D565_D565, Sample_D565_D565, // 4444 - Sample_Gray_D4444, Sample_Gray_D4444_D, - Sample_RGBx_D4444, Sample_RGBx_D4444_D, - Sample_RGBA_D4444, Sample_RGBA_D4444_D, - Sample_Index_D4444, Sample_Index_D4444_D, - NULL, NULL, + Sample_Gray_D4444, Sample_Gray_D4444_D, + Sample_RGBx_D4444, Sample_RGBx_D4444_D, + Sample_RGBA_D4444, Sample_RGBA_D4444_D, + Sample_Index_D4444, Sample_Index_D4444_D, + NULL, NULL, // Index8 - NULL, NULL, - NULL, NULL, - NULL, NULL, - Sample_Index_DI, Sample_Index_DI, - NULL, NULL, + NULL, NULL, + NULL, NULL, + NULL, NULL, + Sample_Index_DI, Sample_Index_DI, + NULL, NULL, + // 8888 Unpremul (no dither distinction) + Sample_Gray_D8888_Unpremul, Sample_Gray_D8888_Unpremul, + Sample_RGBx_D8888, Sample_RGBx_D8888, + Sample_RGBA_D8888_Unpremul, Sample_RGBA_D8888_Unpremul, + Sample_Index_D8888, Sample_Index_D8888, + NULL, NULL, }; + // The jump between dst configs in the table + static const int gProcDstConfigSpan = 10; + SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcs) == 5 * gProcDstConfigSpan, + gProcs_has_the_wrong_number_of_entries); fCTable = ctable; @@ -399,21 +445,28 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither, switch (dst->config()) { case SkBitmap::kARGB_8888_Config: - index += 0; + index += 0 * gProcDstConfigSpan; break; case SkBitmap::kRGB_565_Config: - index += 10; + index += 1 * gProcDstConfigSpan; break; case SkBitmap::kARGB_4444_Config: - index += 20; + index += 2 * gProcDstConfigSpan; break; case SkBitmap::kIndex8_Config: - index += 30; + index += 3 * gProcDstConfigSpan; break; default: return false; } + if (requireUnpremul) { + if (dst->config() != SkBitmap::kARGB_8888_Config) { + return false; + } + index += 4 * gProcDstConfigSpan; + } + fRowProc = gProcs[index]; fDstRow = (char*)dst->getPixels(); fDstRowBytes = dst->rowBytes(); diff --git a/src/images/SkScaledBitmapSampler.h b/src/images/SkScaledBitmapSampler.h index 1466309a77..6477db2178 100644 --- a/src/images/SkScaledBitmapSampler.h +++ b/src/images/SkScaledBitmapSampler.h @@ -36,7 +36,7 @@ public: // prepares iterator to process the src colors and write them into dst. // Returns false if the request cannot be fulfulled. bool begin(SkBitmap* dst, SrcConfig sc, bool doDither, - const SkPMColor* = NULL); + const SkPMColor* = NULL, bool requireUnPremul = false); // call with row of src pixels, for y = 0...scaledHeight-1. // returns true if the row had non-opaque alpha in it bool next(const uint8_t* SK_RESTRICT src); diff --git a/src/ports/SkImageDecoder_WIC.cpp b/src/ports/SkImageDecoder_WIC.cpp index cd7f29fae4..e02ac316d5 100644 --- a/src/ports/SkImageDecoder_WIC.cpp +++ b/src/ports/SkImageDecoder_WIC.cpp @@ -183,10 +183,17 @@ bool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes w hr = piImagingFactory->CreateFormatConverter(&piFormatConverter); } + GUID destinationPixelFormat; + if (this->getRequireUnpremultipliedColors()) { + destinationPixelFormat = GUID_WICPixelFormat32bppBGRA; + } else { + destinationPixelFormat = GUID_WICPixelFormat32bppPBGRA; + } + if (SUCCEEDED(hr)) { hr = piFormatConverter->Initialize( piBitmapSourceOriginal.get() //Input bitmap to convert - , GUID_WICPixelFormat32bppPBGRA //Destination pixel format + , destinationPixelFormat //Destination pixel format , WICBitmapDitherTypeNone //Specified dither patterm , NULL //Specify a particular palette , 0.f //Alpha threshold |