aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/images/SkImageDecoder.cpp3
-rw-r--r--src/images/SkImageDecoder_libpng.cpp47
-rw-r--r--src/images/SkImageDecoder_libwebp.cpp35
-rw-r--r--src/images/SkScaledBitmapSampler.cpp105
-rw-r--r--src/images/SkScaledBitmapSampler.h2
-rw-r--r--src/ports/SkImageDecoder_WIC.cpp9
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