diff options
author | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-06-14 20:39:48 +0000 |
---|---|---|
committer | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-06-14 20:39:48 +0000 |
commit | daaea2d51f145fd43221a2b923721b218c8ff777 (patch) | |
tree | 11bfda86a65bca7dac4a91f75afbb80cd4bc12a5 | |
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
-rw-r--r-- | src/ports/SkImageDecoder_CG.cpp | 37 | ||||
-rw-r--r-- | tests/ImageDecodingTest.cpp | 11 |
2 files changed, 31 insertions, 17 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; } diff --git a/tests/ImageDecodingTest.cpp b/tests/ImageDecodingTest.cpp index f30a0b25b7..9a5d45bcfa 100644 --- a/tests/ImageDecodingTest.cpp +++ b/tests/ImageDecodingTest.cpp @@ -123,12 +123,11 @@ static void compare_unpremul(skiatest::Reporter* reporter, const SkString& filen // Alpha component must be exactly the same. REPORTER_ASSERT(reporter, 0 == da); - // Other components may differ if rounding is done differently, - // but currently that is not the case. If an image fails here - // in the future, we can change these to account for differences. - REPORTER_ASSERT(reporter, 0 == dr); - REPORTER_ASSERT(reporter, 0 == dg); - REPORTER_ASSERT(reporter, 0 == db); + + // Color components may not match exactly due to rounding error. + REPORTER_ASSERT(reporter, dr <= 1); + REPORTER_ASSERT(reporter, dg <= 1); + REPORTER_ASSERT(reporter, db <= 1); } } } |