Fixes for unpremul decode.

SkImageDecoder_CG.cpp:
If a non opaque bitmap was decoded, and the caller wants
unpremultiplied, unpremultiply the colors.

Always use the RGB colorspace, since the other colorspaces
do not match the desired bitmap format.

ImageDecodingTest:
Allow for a difference of 1 in each color component when comparing
the result of premultiplying the unpremultiplied decode with the
premultiplied decode, since I found an image (in WEBP format) where
the unpremultiplied colors did not compare perfectly in my comparison.

R=reed@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@9628 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
index 5fe6fdd..7734ea5 100644
--- a/src/ports/SkImageDecoder_CG.cpp
+++ b/src/ports/SkImageDecoder_CG.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2008 The Android Open Source Project
  *
@@ -6,14 +5,14 @@
  * found in the LICENSE file.
  */
 
+#include "SkCGUtils.h"
 #include "SkColorPriv.h"
-
 #include "SkImageDecoder.h"
 #include "SkImageEncoder.h"
 #include "SkMovie.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
-#include "SkCGUtils.h"
+#include "SkUnPreMultiply.h"
 
 #ifdef SK_BUILD_FOR_MAC
 #include <ApplicationServices/ApplicationServices.h>
@@ -50,6 +49,17 @@
     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
 };
 
+// Returns an unpremultiplied version of color. It will have the same ordering and size as an
+// SkPMColor, but the alpha will not be premultiplied.
+static SkPMColor unpremultiply_pmcolor(SkPMColor color) {
+    U8CPU a = SkGetPackedA32(color);
+    const SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(a);
+    return SkPackARGB32NoCheck(a,
+                               SkUnPreMultiply::ApplyScale(scale, SkGetPackedR32(color)),
+                               SkUnPreMultiply::ApplyScale(scale, SkGetPackedG32(color)),
+                               SkUnPreMultiply::ApplyScale(scale, SkGetPackedB32(color)));
+}
+
 #define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
 
 bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
@@ -80,15 +90,10 @@
     bm->lockPixels();
     bm->eraseColor(SK_ColorTRANSPARENT);
 
-    // use the same colorspace, so we don't change the pixels at all
-    CGColorSpaceRef cs = CGImageGetColorSpace(image);
+    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
     CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO);
-    if (NULL == cg) {
-        // perhaps the image's colorspace does not work for a context, so try just rgb
-        cs = CGColorSpaceCreateDeviceRGB();
-        cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO);
-        CFRelease(cs);
-    }
+    CFRelease(cs);
+
     CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image);
     CGContextRelease(cg);
 
@@ -104,6 +109,16 @@
             // we don't know if we're opaque or not, so compute it.
             bm->computeAndSetOpaquePredicate();
     }
+    if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) {
+        // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied.
+        // Convert to unpremultiplied.
+        for (int i = 0; i < width; ++i) {
+            for (int j = 0; j < height; ++j) {
+                uint32_t* addr = bm->getAddr32(i, j);
+                *addr = unpremultiply_pmcolor(*addr);
+            }
+        }
+    }
     bm->unlockPixels();
     return true;
 }