aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ports
diff options
context:
space:
mode:
authorGravatar scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-06-14 20:39:48 +0000
committerGravatar scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-06-14 20:39:48 +0000
commitdaaea2d51f145fd43221a2b923721b218c8ff777 (patch)
tree11bfda86a65bca7dac4a91f75afbb80cd4bc12a5 /src/ports
parentae72f470e0f88a44b7bda91079c8388e563c1cfc (diff)
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
Diffstat (limited to 'src/ports')
-rw-r--r--src/ports/SkImageDecoder_CG.cpp37
1 files changed, 26 insertions, 11 deletions
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
index 5fe6fddf90..7734ea527b 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);
+ 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;
}