From 935a9f6609d88b92044c2f6251bb8ff83cc8e588 Mon Sep 17 00:00:00 2001 From: reed Date: Mon, 30 Jun 2014 14:06:00 -0700 Subject: [PATCH] force opaque if kCGImageAlpha returns None BUG=skia:2424 R=caryclark@google.com Author: reed@google.com Review URL: https://codereview.chromium.org/355403003 --- src/ports/SkImageDecoder_CG.cpp | 56 +++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp index 8bf30d2cc9..7bebf394da 100644 --- a/src/ports/SkImageDecoder_CG.cpp +++ b/src/ports/SkImageDecoder_CG.cpp @@ -50,6 +50,56 @@ protected: virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode); }; +static void argb_4444_force_opaque(void* row, int count) { + uint16_t* row16 = (uint16_t*)row; + for (int i = 0; i < count; ++i) { + row16[i] |= 0xF000; + } +} + +static void argb_8888_force_opaque(void* row, int count) { + // can use RGBA or BGRA, they have the same shift for alpha + const uint32_t alphaMask = 0xFF << SK_RGBA_A32_SHIFT; + uint32_t* row32 = (uint32_t*)row; + for (int i = 0; i < count; ++i) { + row32[i] |= alphaMask; + } +} + +static void alpha_8_force_opaque(void* row, int count) { + memset(row, 0xFF, count); +} + +static void force_opaque(SkBitmap* bm) { + SkAutoLockPixels alp(*bm); + if (!bm->getPixels()) { + return; + } + + void (*proc)(void*, int); + switch (bm->colorType()) { + case kARGB_4444_SkColorType: + proc = argb_4444_force_opaque; + break; + case kRGBA_8888_SkColorType: + case kBGRA_8888_SkColorType: + proc = argb_8888_force_opaque; + break; + case kAlpha_8_SkColorType: + proc = alpha_8_force_opaque; + break; + default: + return; + } + + char* row = (char*)bm->getPixels(); + for (int y = 0; y < bm->height(); ++y) { + proc(row, bm->width()); + row += bm->rowBytes(); + } + bm->setAlphaType(kOpaque_SkAlphaType); +} + #define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast) bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { @@ -89,8 +139,10 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { case kCGImageAlphaNone: case kCGImageAlphaNoneSkipLast: case kCGImageAlphaNoneSkipFirst: - SkASSERT(SkBitmap::ComputeIsOpaque(*bm)); - bm->setAlphaType(kOpaque_SkAlphaType); + // We're opaque, but we can't rely on the data always having 0xFF + // in the alpha slot (which Skia wants), so we have to ram it in + // ourselves. + force_opaque(bm); break; default: // we don't know if we're opaque or not, so compute it.