aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkBitmap.cpp66
-rw-r--r--src/core/SkConfig8888.cpp63
-rw-r--r--tests/ReadPixelsTest.cpp61
3 files changed, 120 insertions, 70 deletions
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 26630860ac..c62f5f391b 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -8,6 +8,7 @@
#include "SkAtomics.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
+#include "SkConfig8888.h"
#include "SkData.h"
#include "SkFilterQuality.h"
#include "SkMallocPixelRef.h"
@@ -906,72 +907,21 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
///////////////////////////////////////////////////////////////////////////////
-static void rect_memset(uint8_t* array, U8CPU value, SkISize size, size_t rowBytes) {
- for (int y = 0; y < size.height(); ++y) {
- memset(array, value, size.width());
- array += rowBytes;
- }
-}
-
-static void get_bitmap_alpha(const SkPixmap& pmap, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
- SkColorType colorType = pmap.colorType();
- int w = pmap.width();
- int h = pmap.height();
- size_t rb = pmap.rowBytes();
-
- if (kAlpha_8_SkColorType == colorType && !pmap.isOpaque()) {
- const uint8_t* s = pmap.addr8(0, 0);
- while (--h >= 0) {
- memcpy(alpha, s, w);
- s += rb;
- alpha += alphaRowBytes;
- }
- } else if (kN32_SkColorType == colorType && !pmap.isOpaque()) {
- const SkPMColor* SK_RESTRICT s = pmap.addr32(0, 0);
- while (--h >= 0) {
- for (int x = 0; x < w; x++) {
- alpha[x] = SkGetPackedA32(s[x]);
- }
- s = (const SkPMColor*)((const char*)s + rb);
- alpha += alphaRowBytes;
- }
- } else if (kARGB_4444_SkColorType == colorType && !pmap.isOpaque()) {
- const SkPMColor16* SK_RESTRICT s = pmap.addr16(0, 0);
- while (--h >= 0) {
- for (int x = 0; x < w; x++) {
- alpha[x] = SkPacked4444ToA32(s[x]);
- }
- s = (const SkPMColor16*)((const char*)s + rb);
- alpha += alphaRowBytes;
- }
- } else if (kIndex_8_SkColorType == colorType && !pmap.isOpaque()) {
- const SkColorTable* ct = pmap.ctable();
- if (ct) {
- const SkPMColor* SK_RESTRICT table = ct->readColors();
- const uint8_t* SK_RESTRICT s = pmap.addr8(0, 0);
- while (--h >= 0) {
- for (int x = 0; x < w; x++) {
- alpha[x] = SkGetPackedA32(table[s[x]]);
- }
- s += rb;
- alpha += alphaRowBytes;
- }
- }
- } else { // src is opaque, so just fill alpha[] with 0xFF
- rect_memset(alpha, 0xFF, pmap.info().dimensions(), alphaRowBytes);
- }
-}
-
static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
SkASSERT(alpha != nullptr);
SkASSERT(alphaRowBytes >= src.width());
SkAutoPixmapUnlock apl;
if (!src.requestLock(&apl)) {
- rect_memset(alpha, 0, src.info().dimensions(), alphaRowBytes);
+ for (int y = 0; y < src.height(); ++y) {
+ memset(alpha, 0, src.width());
+ alpha += alphaRowBytes;
+ }
return false;
}
- get_bitmap_alpha(apl.pixmap(), alpha, alphaRowBytes);
+ const SkPixmap& pmap = apl.pixmap();
+ SkPixelInfo::CopyPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
+ pmap.info(), pmap.addr(), pmap.rowBytes(), pmap.ctable());
return true;
}
diff --git a/src/core/SkConfig8888.cpp b/src/core/SkConfig8888.cpp
index 31def9a92d..7c3f0214e3 100644
--- a/src/core/SkConfig8888.cpp
+++ b/src/core/SkConfig8888.cpp
@@ -167,6 +167,64 @@ static void copy_32_to_g8(void* dst, size_t dstRB, const void* src, size_t srcRB
}
}
+static bool extract_alpha(void* dst, size_t dstRB, const void* src, size_t srcRB,
+ const SkImageInfo& srcInfo, SkColorTable* ctable) {
+ uint8_t* SK_RESTRICT dst8 = (uint8_t*)dst;
+
+ const int w = srcInfo.width();
+ const int h = srcInfo.height();
+ if (srcInfo.isOpaque()) {
+ // src is opaque, so just fill alpha with 0xFF
+ for (int y = 0; y < h; ++y) {
+ memset(dst8, 0xFF, w);
+ dst8 += dstRB;
+ }
+ return true;
+ }
+ switch (srcInfo.colorType()) {
+ case kN32_SkColorType: {
+ const SkPMColor* SK_RESTRICT src32 = (const SkPMColor*)src;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ dst8[x] = SkGetPackedA32(src32[x]);
+ }
+ dst8 += dstRB;
+ src32 = (const SkPMColor*)((const char*)src32 + srcRB);
+ }
+ break;
+ }
+ case kARGB_4444_SkColorType: {
+ const SkPMColor16* SK_RESTRICT src16 = (const SkPMColor16*)src;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ dst8[x] = SkPacked4444ToA32(src16[x]);
+ }
+ dst8 += dstRB;
+ src16 = (const SkPMColor16*)((const char*)src16 + srcRB);
+ }
+ break;
+ }
+ case kIndex_8_SkColorType: {
+ if (nullptr == ctable) {
+ return false;
+ }
+ const SkPMColor* SK_RESTRICT table = ctable->readColors();
+ const uint8_t* SK_RESTRICT src8 = (const uint8_t*)src;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ dst8[x] = SkGetPackedA32(table[src8[x]]);
+ }
+ dst8 += dstRB;
+ src8 += srcRB;
+ }
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
SkColorTable* ctable) {
@@ -241,6 +299,11 @@ bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t
return true;
}
+ if (kAlpha_8_SkColorType == dstInfo.colorType() &&
+ extract_alpha(dstPixels, dstRB, srcPixels, srcRB, srcInfo, ctable)) {
+ return true;
+ }
+
// Can no longer draw directly into 4444, but we can manually whack it for a few combinations
if (kARGB_4444_SkColorType == dstInfo.colorType() &&
(kN32_SkColorType == srcInfo.colorType() || kIndex_8_SkColorType == srcInfo.colorType())) {
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
index 008781ca06..5fa7dd19f4 100644
--- a/tests/ReadPixelsTest.cpp
+++ b/tests/ReadPixelsTest.cpp
@@ -135,8 +135,14 @@ static void fill_dst_bmp_with_init_data(SkBitmap* bitmap) {
intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels());
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
- SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel());
- *pixel = get_dst_bmp_init_color(x, y, w);
+ SkPMColor initColor = get_dst_bmp_init_color(x, y, w);
+ if (kAlpha_8_SkColorType == bitmap->colorType()) {
+ uint8_t* alpha = reinterpret_cast<uint8_t*>(pixels + y * bitmap->rowBytes() + x);
+ *alpha = SkGetPackedA32(initColor);
+ } else {
+ SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel());
+ *pixel = initColor;
+ }
}
}
}
@@ -168,14 +174,13 @@ static bool check_read(skiatest::Reporter* reporter,
const SkBitmap& bitmap,
int x, int y,
bool checkCanvasPixels,
- bool checkBitmapPixels) {
- SkASSERT(4 == bitmap.bytesPerPixel());
+ bool checkBitmapPixels,
+ SkColorType ct,
+ SkAlphaType at) {
+ SkASSERT(ct == bitmap.colorType() && at == bitmap.alphaType());
SkASSERT(!bitmap.isNull());
SkASSERT(checkCanvasPixels || checkBitmapPixels);
- const SkColorType ct = bitmap.colorType();
- const SkAlphaType at = bitmap.alphaType();
-
int bw = bitmap.width();
int bh = bitmap.height();
@@ -185,6 +190,34 @@ static bool check_read(skiatest::Reporter* reporter,
clippedSrcRect.setEmpty();
}
SkAutoLockPixels alp(bitmap);
+ if (kAlpha_8_SkColorType == ct) {
+ for (int by = 0; by < bh; ++by) {
+ for (int bx = 0; bx < bw; ++bx) {
+ int devx = bx + srcRect.fLeft;
+ int devy = by + srcRect.fTop;
+ const uint8_t* alpha = bitmap.getAddr8(bx, by);
+
+ if (clippedSrcRect.contains(devx, devy)) {
+ if (checkCanvasPixels) {
+ uint8_t canvasAlpha = SkGetPackedA32(get_src_color(devx, devy));
+ if (canvasAlpha != *alpha) {
+ ERRORF(reporter, "Expected readback alpha (%d, %d) value 0x%02x, got 0x%02x. ",
+ bx, by, canvasAlpha, *alpha);
+ return false;
+ }
+ }
+ } else if (checkBitmapPixels) {
+ uint32_t origDstAlpha = SkGetPackedA32(get_dst_bmp_init_color(bx, by, bw));
+ if (origDstAlpha != *alpha) {
+ ERRORF(reporter, "Expected clipped out area of readback to be unchanged. "
+ "Expected 0x%02x, got 0x%02x", origDstAlpha, *alpha);
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
for (int by = 0; by < bh; ++by) {
for (int bx = 0; bx < bw; ++bx) {
int devx = bx + srcRect.fLeft;
@@ -249,10 +282,10 @@ static void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init,
case kTight_BitmapInit:
break;
case kRowBytes_BitmapInit:
- rowBytes = (info.width() + 16) * sizeof(SkPMColor);
+ rowBytes = SkAlign4((info.width() + 16) * info.bytesPerPixel());
break;
case kRowBytesOdd_BitmapInit:
- rowBytes = (info.width() * sizeof(SkPMColor)) + 3;
+ rowBytes = SkAlign4(info.width() * info.bytesPerPixel()) + 3;
break;
default:
SkASSERT(0);
@@ -274,6 +307,7 @@ static const struct {
{ kRGBA_8888_SkColorType, kUnpremul_SkAlphaType },
{ kBGRA_8888_SkColorType, kPremul_SkAlphaType },
{ kBGRA_8888_SkColorType, kUnpremul_SkAlphaType },
+ { kAlpha_8_SkColorType, kPremul_SkAlphaType },
};
const SkIRect gReadPixelsTestRects[] = {
// entire thing
@@ -354,7 +388,8 @@ static void test_readpixels(skiatest::Reporter* reporter, const sk_sp<SkSurface>
if (success || startsWithPixels) {
check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop,
- success, startsWithPixels);
+ success, startsWithPixels,
+ gReadPixelsConfigs[c].fColorType, gReadPixelsConfigs[c].fAlphaType);
} else {
// if we had no pixels beforehand and the readPixels
// failed then our bitmap should still not have pixels
@@ -371,7 +406,8 @@ static void test_readpixels(skiatest::Reporter* reporter, const sk_sp<SkSurface>
REPORTER_ASSERT(reporter, kN32_SkColorType == wkbmp.colorType());
REPORTER_ASSERT(reporter, kPremul_SkAlphaType == wkbmp.alphaType());
check_read(reporter, wkbmp, clippedRect.fLeft,
- clippedRect.fTop, true, false);
+ clippedRect.fTop, true, false,
+ kN32_SkColorType, kPremul_SkAlphaType);
} else {
REPORTER_ASSERT(reporter, !success);
}
@@ -427,7 +463,8 @@ static void test_readpixels_texture(skiatest::Reporter* reporter, GrTexture* tex
bmp.rowBytes(), flags);
bmp.unlockPixels();
check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop,
- success, true);
+ success, true,
+ gReadPixelsConfigs[c].fColorType, gReadPixelsConfigs[c].fAlphaType);
}
}
}