SkBitmap::ComputeIsOpaque and SkBitmap::eraseColor support F16
Also add a unit test.
Change-Id: I9b6635ce9dd504788ca36b3246eaac2b37c2f3a6
Reviewed-on: https://skia-review.googlesource.com/5443
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/include/core/SkColor.h b/include/core/SkColor.h
index 8f2776d..4d54773 100644
--- a/include/core/SkColor.h
+++ b/include/core/SkColor.h
@@ -183,6 +183,7 @@
float* vec() { return &fR; }
static SkColor4f Pin(float r, float g, float b, float a);
+ /** Convert to SkColor4f, assuming SkColor is sRGB */
static SkColor4f FromColor(SkColor);
static SkColor4f FromColor3f(SkColor3f, float a);
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index e4097b4..9b11743 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -11,6 +11,7 @@
#include "SkConfig8888.h"
#include "SkData.h"
#include "SkFilterQuality.h"
+#include "SkHalf.h"
#include "SkMallocPixelRef.h"
#include "SkMask.h"
#include "SkMath.h"
@@ -622,6 +623,18 @@
}
return true;
}
+ case kRGBA_F16_SkColorType: {
+ const SkHalf* row = (const SkHalf*)pmap.addr();
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ if (row[4 * x + 3] < SK_Half1) {
+ return false;
+ }
+ }
+ row += pmap.rowBytes() >> 1;
+ }
+ return true;
+ }
default:
break;
}
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 0a1a24f..c73b918 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -5,13 +5,18 @@
* found in the LICENSE file.
*/
+#include "SkBitmap.h"
+#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkConfig8888.h"
#include "SkData.h"
+#include "SkHalf.h"
#include "SkMask.h"
-#include "SkPixmap.h"
-#include "SkUtils.h"
+#include "SkNx.h"
#include "SkPM4f.h"
+#include "SkPixmap.h"
+#include "SkSurface.h"
+#include "SkUtils.h"
void SkAutoPixmapUnlock::reset(const SkPixmap& pm, void (*unlock)(void*), void* ctx) {
SkASSERT(pm.addr() != nullptr);
@@ -206,15 +211,19 @@
}
break;
}
+ case kRGBA_F16_SkColorType:
+ // The colorspace is unspecified, so assume linear just like getColor().
+ this->erase(SkColor4f{(1 / 255.0f) * r,
+ (1 / 255.0f) * g,
+ (1 / 255.0f) * b,
+ (1 / 255.0f) * a}, &area);
+ break;
default:
return false; // no change, so don't call notifyPixelsChanged()
}
return true;
}
-#include "SkNx.h"
-#include "SkHalf.h"
-
bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const {
SkPixmap pm;
if (subset) {
@@ -238,10 +247,6 @@
return true;
}
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkSurface.h"
-
bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const {
// Can't do anthing with empty src or dst
if (this->width() <= 0 || this->height() <= 0 || dst.width() <= 0 || dst.height() <= 0) {
diff --git a/tests/BitmapTest.cpp b/tests/BitmapTest.cpp
index f939875..98b1ac4 100644
--- a/tests/BitmapTest.cpp
+++ b/tests/BitmapTest.cpp
@@ -166,3 +166,56 @@
test_erasecolor_premul(r, kRGBA_8888_SkColorType, color, color);
test_erasecolor_premul(r, kBGRA_8888_SkColorType, color, color);
}
+
+// Test that SkBitmap::ComputeOpaque() is correct for various colortypes.
+DEF_TEST(Bitmap_compute_is_opaque, r) {
+ struct {
+ SkColorType fCT;
+ SkAlphaType fAT;
+ } types[] = {
+ { kGray_8_SkColorType, kOpaque_SkAlphaType },
+ { kAlpha_8_SkColorType, kPremul_SkAlphaType },
+ { kARGB_4444_SkColorType, kPremul_SkAlphaType },
+ { kRGB_565_SkColorType, kOpaque_SkAlphaType },
+ { kBGRA_8888_SkColorType, kPremul_SkAlphaType },
+ { kRGBA_8888_SkColorType, kPremul_SkAlphaType },
+ { kRGBA_F16_SkColorType, kPremul_SkAlphaType },
+ };
+ for (auto type : types) {
+ SkBitmap bm;
+ REPORTER_ASSERT(r, !SkBitmap::ComputeIsOpaque(bm));
+
+ bm.allocPixels(SkImageInfo::Make(13, 17, type.fCT, type.fAT));
+ bm.eraseColor(SkColorSetARGB(255, 10, 20, 30));
+ REPORTER_ASSERT(r, SkBitmap::ComputeIsOpaque(bm));
+
+ bm.eraseColor(SkColorSetARGB(128, 255, 255, 255));
+ bool isOpaque = SkBitmap::ComputeIsOpaque(bm);
+ bool shouldBeOpaque = (type.fAT == kOpaque_SkAlphaType);
+ REPORTER_ASSERT(r, isOpaque == shouldBeOpaque);
+ }
+}
+
+// Test that erase+getColor round trips with RGBA_F16 pixels.
+DEF_TEST(Bitmap_erase_f16_erase_getColor, r) {
+ SkRandom random;
+ SkPixmap pm;
+ SkBitmap bm;
+ bm.allocPixels(SkImageInfo::Make(1, 1, kRGBA_F16_SkColorType, kPremul_SkAlphaType));
+ REPORTER_ASSERT(r, bm.peekPixels(&pm));
+ for (unsigned i = 0; i < 0x100; ++i) {
+ // Test all possible values of blue component.
+ SkColor color1 = (SkColor)((random.nextU() & 0xFFFFFF00) | i);
+ // Test all possible values of alpha component.
+ SkColor color2 = (SkColor)((random.nextU() & 0x00FFFFFF) | (i << 24));
+ for (SkColor color : {color1, color2}) {
+ pm.erase(color);
+ if (SkColorGetA(color) != 0) {
+ REPORTER_ASSERT(r, color == pm.getColor(0, 0));
+ } else {
+ REPORTER_ASSERT(r, 0 == SkColorGetA(pm.getColor(0, 0)));
+ }
+ }
+ }
+}
+