Reland "add getAlphaf() to pixmap/bitmap"
This is a reland of f3ebd312f21325f9afc4479fd7a4e90a32ffb920
PS 2: use faster half->float routine
PS 3: relax tolerance to 2^-10 for half, keeping others 2^-12
Original change's description:
> add getAlphaf() to pixmap/bitmap
>
> Convenient for just extracting alpha (and more efficient than getColor()) and
> works for super-normal formats w/o loss of precision.
>
> Somewhat inspired by examining multiple chrome call-sites for getColor(), where
> chrome only really cared about the alpha. This new method runs about twice
> as fast as getColor() for the simple cases (i.e. no colorspace xforms), and
> even faster in the complex cases (since retrieving alpha doesn't care about
> colorspaces).
>
> Bug: skia:
> Change-Id: I7cd5a2c7f78de781aaa69dd1aa0dba3c532fcb73
> Reviewed-on: https://skia-review.googlesource.com/155606
> Commit-Queue: Mike Reed <reed@google.com>
> Reviewed-by: Mike Klein <mtklein@google.com>
Cq-Include-Trybots: skia.primary:Test-Android-Clang-Nexus7-CPU-Tegra3-arm-Debug-All-Android,Test-Debian9-Clang-GCE-CPU-AVX2-x86_64-Release-All-SK_CPU_LIMIT_SSE2,Test-Debian9-GCC-GCE-CPU-AVX2-x86_64-Release-All,Test-Win2016-MSVC-GCE-CPU-AVX2-x86_64-Release-All,Test-Win8-Clang-Golo-CPU-AVX-x86_64-Debug-All
Bug: skia:
Change-Id: Ie94e5c89e185fde12cbd6c56ed4026c4dc5a1623
Reviewed-on: https://skia-review.googlesource.com/156242
Commit-Queue: Ravi Mistry <rmistry@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/tests/BitmapTest.cpp b/tests/BitmapTest.cpp
index 439136d..70dde59 100644
--- a/tests/BitmapTest.cpp
+++ b/tests/BitmapTest.cpp
@@ -263,3 +263,103 @@
REPORTER_ASSERT(r, bm.getColor(0,0) != 0x00000000);
}
}
+
+static void check_alphas(skiatest::Reporter* reporter, const SkBitmap& bm,
+ bool (*pred)(float expected, float actual)) {
+ SkASSERT(bm.width() == 16);
+ SkASSERT(bm.height() == 16);
+
+ int alpha = 0;
+ for (int y = 0; y < 16; ++y) {
+ for (int x = 0; x < 16; ++x) {
+ float expected = alpha / 255.0f;
+ float actual = bm.getAlphaf(x, y);
+ if (!pred(expected, actual)) {
+ ERRORF(reporter, "got %g, want %g\n", actual, expected);
+ }
+ alpha += 1;
+ }
+ }
+}
+
+static bool unit_compare(float expected, float actual, float tol = 1.0f/(1<<12)) {
+ SkASSERT(expected >= 0 && expected <= 1);
+ SkASSERT( actual >= 0 && actual <= 1);
+ if (expected == 0 || expected == 1) {
+ return actual == expected;
+ } else {
+ return SkScalarNearlyEqual(expected, actual, tol);
+ }
+}
+
+static float unit_discretize(float value, float scale) {
+ SkASSERT(value >= 0 && value <= 1);
+ if (value == 1) {
+ return 1;
+ } else {
+ return sk_float_floor(value * scale + 0.5f) / scale;
+ }
+}
+
+DEF_TEST(getalphaf, reporter) {
+ SkImageInfo info = SkImageInfo::MakeN32Premul(16, 16);
+ SkBitmap bm;
+ bm.allocPixels(info);
+
+ int alpha = 0;
+ for (int y = 0; y < 16; ++y) {
+ for (int x = 0; x < 16; ++x) {
+ *bm.getAddr32(x, y) = alpha++ << 24;
+ }
+ }
+
+ auto nearly = [](float expected, float actual) -> bool {
+ return unit_compare(expected, actual);
+ };
+ auto nearly4bit = [](float expected, float actual) -> bool {
+ expected = unit_discretize(expected, 15);
+ return unit_compare(expected, actual);
+ };
+ auto nearly2bit = [](float expected, float actual) -> bool {
+ expected = unit_discretize(expected, 3);
+ return unit_compare(expected, actual);
+ };
+ auto opaque = [](float expected, float actual) -> bool {
+ return actual == 1.0f;
+ };
+
+ auto nearly_half = [](float expected, float actual) -> bool {
+ return unit_compare(expected, actual, 1.0f/(1<<10));
+ };
+
+ const struct {
+ SkColorType fColorType;
+ bool (*fPred)(float, float);
+ } recs[] = {
+ { kRGB_565_SkColorType, opaque },
+ { kGray_8_SkColorType, opaque },
+ { kRGB_888x_SkColorType, opaque },
+ { kRGB_101010x_SkColorType, opaque },
+
+ { kAlpha_8_SkColorType, nearly },
+ { kRGBA_8888_SkColorType, nearly },
+ { kBGRA_8888_SkColorType, nearly },
+ { kRGBA_F16_SkColorType, nearly_half },
+ { kRGBA_F32_SkColorType, nearly },
+
+ { kRGBA_1010102_SkColorType, nearly2bit },
+
+ { kARGB_4444_SkColorType, nearly4bit },
+ };
+
+ for (const auto& rec : recs) {
+ SkBitmap tmp;
+ tmp.allocPixels(bm.info().makeColorType(rec.fColorType));
+ if (bm.readPixels(tmp.pixmap())) {
+ check_alphas(reporter, tmp, rec.fPred);
+ } else {
+ SkDebugf("can't readpixels\n");
+ }
+ }
+}
+