aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkBitmap.h18
-rw-r--r--src/core/SkBitmap.cpp75
-rw-r--r--src/ports/SkImageDecoder_CG.cpp3
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;
}