diff options
author | 2013-06-14 20:39:48 +0000 | |
---|---|---|
committer | 2013-06-14 20:39:48 +0000 | |
commit | daaea2d51f145fd43221a2b923721b218c8ff777 (patch) | |
tree | 11bfda86a65bca7dac4a91f75afbb80cd4bc12a5 /src/ports | |
parent | ae72f470e0f88a44b7bda91079c8388e563c1cfc (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.cpp | 37 |
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; } |