Add an option to create unpremultiplied bitmaps.
Currently they cannot be used directly by Skia, but
the pixels can be used elsewhere.

SkImageDecoder:
Add functions to require unpremultiplied output
and query the presence of the requirement

SkImageDecoder_libpng:
SkImageDecoder_libwebp:
SkImageDecoder_WIC:
Respect the requirement for unpremultiplied output.
TODO: Fix SkImageDecoder_CG.

SkScaledBitmapSampler:
Add procs to skip premultiplication and a boolean
parameter to use those procs.

ImageDecodingTest:
Test unpremultiplied bitmap decoding.

SampleUnpremul:
Add a sample which allows visually comparing between the
unpremultiplied version (copied into a premultiplied bitmap,
since drawing unpremultiplied is not currently supported)
and a premultiplied version of image files.

gm.h:
Add a getter for the resource path, so Samples can use it.

As of patch set 13, https://codereview.chromium.org/16816016/
and https://codereview.chromium.org/16983004/, which were
approved separately.

R=reed@google.com

Review URL: https://codereview.chromium.org/16410009

git-svn-id: http://skia.googlecode.com/svn/trunk@9612 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp
index 5c078ce..38aa7fd 100644
--- a/src/images/SkImageDecoder.cpp
+++ b/src/images/SkImageDecoder.cpp
@@ -40,7 +40,8 @@
     , 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 d967a69..729f871 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -80,8 +80,9 @@
     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 @@
 
     if (!reuseBitmap) {
         decodedBitmap->setConfig(config, sampler.scaledWidth(),
-                                 sampler.scaledHeight(), 0);
+                                 sampler.scaledHeight());
     }
     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
         return true;
@@ -383,7 +384,8 @@
             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 @@
     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::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 @@
         }
     }
 
-    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 @@
     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 @@
     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 @@
             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 95b9a97..9cf8449 100644
--- a/src/images/SkImageDecoder_libwebp.cpp
+++ b/src/images/SkImageDecoder_libwebp.cpp
@@ -114,7 +114,17 @@
     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 @@
     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_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_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 @@
 
     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 @@
 
     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 25b32fd..ca41de9 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 @@
     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 @@
 }
 
 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 @@
 
     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 1466309..6477db2 100644
--- a/src/images/SkScaledBitmapSampler.h
+++ b/src/images/SkScaledBitmapSampler.h
@@ -36,7 +36,7 @@
     // 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 cd7f29f..e02ac31 100644
--- a/src/ports/SkImageDecoder_WIC.cpp
+++ b/src/ports/SkImageDecoder_WIC.cpp
@@ -183,10 +183,17 @@
         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