static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) { const SkBitmap* bm0 = reinterpret_cast<SkBitmap*>(bm0Handle); const SkBitmap* bm1 = reinterpret_cast<SkBitmap*>(bm1Handle); if (bm0->width() != bm1->width() || bm0->height() != bm1->height() || bm0->colorType() != bm1->colorType()) { return JNI_FALSE; } SkAutoLockPixels alp0(*bm0); SkAutoLockPixels alp1(*bm1); // if we can't load the pixels, return false if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) { return JNI_FALSE; } if (bm0->colorType() == kIndex_8_SkColorType) { SkColorTable* ct0 = bm0->getColorTable(); SkColorTable* ct1 = bm1->getColorTable(); if (NULL == ct0 || NULL == ct1) { return JNI_FALSE; } if (ct0->count() != ct1->count()) { return JNI_FALSE; } SkAutoLockColors alc0(ct0); SkAutoLockColors alc1(ct1); const size_t size = ct0->count() * sizeof(SkPMColor); if (memcmp(alc0.colors(), alc1.colors(), size) != 0) { return JNI_FALSE; } } // now compare each scanline. We can't do the entire buffer at once, // since we don't care about the pixel values that might extend beyond // the width (since the scanline might be larger than the logical width) const int h = bm0->height(); const size_t size = bm0->width() * bm0->bytesPerPixel(); for (int y = 0; y < h; y++) { // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0 // and bm1 both have pixel data() (have passed NULL == getPixels() check), // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE // to warn user those 2 unrecognized config bitmaps may be different. void *bm0Addr = bm0->getAddr(0, y); void *bm1Addr = bm1->getAddr(0, y); if(bm0Addr == NULL || bm1Addr == NULL) { return JNI_FALSE; } if (memcmp(bm0Addr, bm1Addr, size) != 0) { return JNI_FALSE; } } return JNI_TRUE; }
DEF_TEST(BitmapCopy_extractSubset, reporter) { for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { SkBitmap srcOpaque, srcPremul; setup_src_bitmaps(&srcOpaque, &srcPremul, gPairs[i].fColorType); SkBitmap bitmap(srcOpaque); SkBitmap subset; SkIRect r; // Extract a subset which has the same width as the original. This // catches a bug where we cloned the genID incorrectly. r.set(0, 1, W, 3); bitmap.setIsVolatile(true); // Relies on old behavior of extractSubset failing if colortype is unknown if (kUnknown_SkColorType != bitmap.colorType() && bitmap.extractSubset(&subset, r)) { REPORTER_ASSERT(reporter, subset.width() == W); REPORTER_ASSERT(reporter, subset.height() == 2); REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType()); REPORTER_ASSERT(reporter, subset.isVolatile() == true); // Test copying an extracted subset. for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) { SkBitmap copy; bool success = subset.copyTo(©, gPairs[j].fColorType); if (!success) { // Skip checking that success matches fValid, which is redundant // with the code below. REPORTER_ASSERT(reporter, gPairs[i].fColorType != gPairs[j].fColorType); continue; } // When performing a copy of an extracted subset, the gen id should // change. REPORTER_ASSERT(reporter, copy.getGenerationID() != subset.getGenerationID()); REPORTER_ASSERT(reporter, copy.width() == W); REPORTER_ASSERT(reporter, copy.height() == 2); if (gPairs[i].fColorType == gPairs[j].fColorType) { SkAutoLockPixels alp0(subset); SkAutoLockPixels alp1(copy); // they should both have, or both not-have, a colortable bool hasCT = subset.getColorTable() != nullptr; REPORTER_ASSERT(reporter, (copy.getColorTable() != nullptr) == hasCT); } } } bitmap = srcPremul; bitmap.setIsVolatile(false); if (bitmap.extractSubset(&subset, r)) { REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType()); REPORTER_ASSERT(reporter, subset.isVolatile() == false); } } }
static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) { const SkBitmap* bm0 = reinterpret_cast<SkBitmap*>(bm0Handle); const SkBitmap* bm1 = reinterpret_cast<SkBitmap*>(bm1Handle); if (bm0->width() != bm1->width() || bm0->height() != bm1->height() || bm0->config() != bm1->config()) { return JNI_FALSE; } SkAutoLockPixels alp0(*bm0); SkAutoLockPixels alp1(*bm1); // if we can't load the pixels, return false if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) { return JNI_FALSE; } if (bm0->config() == SkBitmap::kIndex8_Config) { SkColorTable* ct0 = bm0->getColorTable(); SkColorTable* ct1 = bm1->getColorTable(); if (NULL == ct0 || NULL == ct1) { return JNI_FALSE; } if (ct0->count() != ct1->count()) { return JNI_FALSE; } SkAutoLockColors alc0(ct0); SkAutoLockColors alc1(ct1); const size_t size = ct0->count() * sizeof(SkPMColor); if (memcmp(alc0.colors(), alc1.colors(), size) != 0) { return JNI_FALSE; } } // now compare each scanline. We can't do the entire buffer at once, // since we don't care about the pixel values that might extend beyond // the width (since the scanline might be larger than the logical width) const int h = bm0->height(); const size_t size = bm0->width() * bm0->bytesPerPixel(); for (int y = 0; y < h; y++) { if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) { return JNI_FALSE; } } return JNI_TRUE; }
static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig, SkBitmap* diff) { const SkBitmap& src = canvas->getDevice()->accessBitmap(false); SkAutoLockPixels alp0(src); SkAutoLockPixels alp1(orig); for (int y = 0; y < src.height(); y++) { const void* srcP = src.getAddr(0, y); const void* origP = orig.getAddr(0, y); size_t bytes = src.width() * src.bytesPerPixel(); if (memcmp(srcP, origP, bytes)) { SkDebugf("---------- difference on line %d\n", y); return true; } } return false; }
static void TestBitmapCopy(skiatest::Reporter* reporter) { static const Pair gPairs[] = { { SkBitmap::kNo_Config, "00000000" }, { SkBitmap::kA1_Config, "01000000" }, { SkBitmap::kA8_Config, "00101110" }, { SkBitmap::kIndex8_Config, "00111110" }, { SkBitmap::kRGB_565_Config, "00101110" }, { SkBitmap::kARGB_4444_Config, "00101110" }, { SkBitmap::kARGB_8888_Config, "00101110" }, // TODO: create valid RLE bitmap to test with // { SkBitmap::kRLE_Index8_Config, "00101111" } }; const int W = 20; const int H = 33; for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) { SkBitmap src, dst; SkColorTable* ct = NULL; src.setConfig(gPairs[i].fConfig, W, H); if (SkBitmap::kIndex8_Config == src.config() || SkBitmap::kRLE_Index8_Config == src.config()) { ct = init_ctable(); } src.allocPixels(ct); ct->safeRef(); init_src(src); bool success = src.copyTo(&dst, gPairs[j].fConfig); bool expected = gPairs[i].fValid[j] != '0'; if (success != expected) { SkString str; str.printf("SkBitmap::copyTo from %s to %s. expected %s returned %s", gConfigName[i], gConfigName[j], boolStr(expected), boolStr(success)); reporter->reportFailed(str); } bool canSucceed = src.canCopyTo(gPairs[j].fConfig); if (success != canSucceed) { SkString str; str.printf("SkBitmap::copyTo from %s to %s. returned %s canCopyTo %s", gConfigName[i], gConfigName[j], boolStr(success), boolStr(canSucceed)); reporter->reportFailed(str); } if (success) { REPORTER_ASSERT(reporter, src.width() == dst.width()); REPORTER_ASSERT(reporter, src.height() == dst.height()); REPORTER_ASSERT(reporter, dst.config() == gPairs[j].fConfig); test_isOpaque(reporter, src, dst.config()); if (src.config() == dst.config()) { SkAutoLockPixels srcLock(src); SkAutoLockPixels dstLock(dst); REPORTER_ASSERT(reporter, src.readyToDraw()); REPORTER_ASSERT(reporter, dst.readyToDraw()); const char* srcP = (const char*)src.getAddr(0, 0); const char* dstP = (const char*)dst.getAddr(0, 0); REPORTER_ASSERT(reporter, srcP != dstP); REPORTER_ASSERT(reporter, !memcmp(srcP, dstP, src.getSize())); } // test extractSubset { SkBitmap subset; SkIRect r; r.set(1, 1, 2, 2); if (src.extractSubset(&subset, r)) { REPORTER_ASSERT(reporter, subset.width() == 1); REPORTER_ASSERT(reporter, subset.height() == 1); SkBitmap copy; REPORTER_ASSERT(reporter, subset.copyTo(©, subset.config())); REPORTER_ASSERT(reporter, copy.width() == 1); REPORTER_ASSERT(reporter, copy.height() == 1); REPORTER_ASSERT(reporter, copy.rowBytes() <= 4); SkAutoLockPixels alp0(subset); SkAutoLockPixels alp1(copy); // they should both have, or both not-have, a colortable bool hasCT = subset.getColorTable() != NULL; REPORTER_ASSERT(reporter, (copy.getColorTable() != NULL) == hasCT); } } } else { // dst should be unchanged from its initial state REPORTER_ASSERT(reporter, dst.config() == SkBitmap::kNo_Config); REPORTER_ASSERT(reporter, dst.width() == 0); REPORTER_ASSERT(reporter, dst.height() == 0); } } } }