diff options
-rw-r--r-- | include/core/SkBitmap.h | 18 | ||||
-rw-r--r-- | src/core/SkBitmap.cpp | 75 | ||||
-rw-r--r-- | src/ports/SkImageDecoder_CG.cpp | 3 |
3 files changed, 96 insertions, 0 deletions
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h index 9c81e836f2..ef4cdd9c9a 100644 --- a/include/core/SkBitmap.h +++ b/include/core/SkBitmap.h @@ -223,6 +223,24 @@ public: static size_t ComputeSize(Config, int width, int height); /** + * This will brute-force return true if all of the pixels in the bitmap + * are opaque. If it fails to read the pixels, or encounters an error, + * it will return false. + * + * Since this can be an expensive operation, the bitmap stores a flag for + * this (isOpaque, setIsOpaque). Only call this if you need to compute this + * value from "unknown" pixels. + */ + static bool ComputeIsOpaque(const SkBitmap&); + + /** + * Calls ComputeIsOpaque, and passes its result to setIsOpaque(). + */ + void computeAndSetOpaquePredicate() { + this->setIsOpaque(ComputeIsOpaque(*this)); + } + + /** * Return the bitmap's bounds [0, 0, width, height] as an SkRect */ void getBounds(SkRect* bounds) const; diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index faf6e0353d..458cb615e6 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -668,6 +668,81 @@ SkColor SkBitmap::getColor(int x, int y) const { return 0; } +bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { + SkAutoLockPixels alp(bm); + if (!bm.getPixels()) { + return false; + } + + const int height = bm.height(); + const int width = bm.width(); + + switch (bm.config()) { + case SkBitmap::kA1_Config: { + // TODO + } break; + case SkBitmap::kA8_Config: { + unsigned a = 0xFF; + for (int y = 0; y < height; ++y) { + const uint8_t* row = bm.getAddr8(0, y); + for (int x = 0; x < width; ++x) { + a &= row[x]; + } + if (0xFF != a) { + return false; + } + } + return true; + } break; + case kRLE_Index8_Config: + case SkBitmap::kIndex8_Config: { + SkAutoLockColors alc(bm); + const SkPMColor* table = alc.colors(); + if (!table) { + return false; + } + SkPMColor c = ~0; + for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) { + c &= table[i]; + } + return 0xFF == SkGetPackedA32(c); + } break; + case SkBitmap::kRGB_565_Config: + return true; + break; + case SkBitmap::kARGB_4444_Config: { + unsigned c = 0xFFFF; + for (int y = 0; y < height; ++y) { + const SkPMColor16* row = bm.getAddr16(0, y); + for (int x = 0; x < width; ++x) { + c &= row[x]; + } + if (0xF != SkGetPackedA4444(c)) { + return false; + } + } + return true; + } break; + case SkBitmap::kARGB_8888_Config: { + SkPMColor c = ~0; + for (int y = 0; y < height; ++y) { + const SkPMColor* row = bm.getAddr32(0, y); + for (int x = 0; x < width; ++x) { + c &= row[x]; + } + if (0xFF != SkGetPackedA32(c)) { + return false; + } + } + return true; + } + default: + break; + } + return false; +} + + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp index bcd3e3741c..ba7a89c91e 100644 --- a/src/ports/SkImageDecoder_CG.cpp +++ b/src/ports/SkImageDecoder_CG.cpp @@ -6,6 +6,7 @@ * found in the LICENSE file. */ +#include "SkColorPriv.h" #include "SkImageDecoder.h" #include "SkImageEncoder.h" @@ -86,6 +87,8 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image); CGContextRelease(cg); + // since CGImage won't tell us if it is opaque, we have to compute it. + bm->computeAndSetOpaquePredicate(); bm->unlockPixels(); return true; } |