Index: src/ports/SkImageDecoder_CG.cpp |
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp |
index 5fe6fddf90835dda53a0cc7c57417d1ff7c56693..7734ea527b3610573b1aa56ec3f5396f41ff8f52 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 @@ protected: |
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); |
reed1
2013/06/14 19:38:20
possibly only do this if a is != 0xFF and a != 0 ?
|
+ 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 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
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 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
// 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; |
} |