void onDrawContent(SkCanvas* canvas) override { SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(SkIntToScalar(24)); SkAutoTUnref<SkBlurDrawLooper> looper( SkBlurDrawLooper::Create(SK_ColorBLUE, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(2)), 0, 0)); paint.setLooper(looper); SkScalar height = paint.getFontMetrics(nullptr); if (!fDecodeSucceeded) { SkString failure; if (fResPath.size() == 0) { failure.printf("resource path is required!"); } else { failure.printf("Failed to decode %s", fCurrFile.c_str()); } canvas->drawText(failure.c_str(), failure.size(), 0, height, paint); return; } // Name, size of the file, and whether or not it is premultiplied. SkString header(SkOSPath::Basename(fCurrFile.c_str())); header.appendf(" [%dx%d] %s", fBitmap.width(), fBitmap.height(), (fPremul ? "premultiplied" : "unpremultiplied")); canvas->drawText(header.c_str(), header.size(), 0, height, paint); canvas->translate(0, height); // Help messages header.printf("Press '%c' to move to the next image.'", fNextImageChar); canvas->drawText(header.c_str(), header.size(), 0, height, paint); canvas->translate(0, height); header.printf("Press '%c' to toggle premultiplied decode.", fTogglePremulChar); canvas->drawText(header.c_str(), header.size(), 0, height, paint); // Now draw the image itself. canvas->translate(height * 2, height * 2); if (!fPremul) { // A premultiplied bitmap cannot currently be drawn. SkAutoLockPixels alp(fBitmap); // Copy it to a bitmap which can be drawn, converting // to premultiplied: SkBitmap bm; bm.allocN32Pixels(fBitmap.width(), fBitmap.height()); for (int i = 0; i < fBitmap.width(); ++i) { for (int j = 0; j < fBitmap.height(); ++j) { *bm.getAddr32(i, j) = premultiply_unpmcolor(*fBitmap.getAddr32(i, j)); } } canvas->drawBitmap(bm, 0, 0); } else { canvas->drawBitmap(fBitmap, 0, 0); } }
/** * Test decoding an image in premultiplied mode and unpremultiplied mode and compare * them. */ static void compare_unpremul(skiatest::Reporter* reporter, const SkString& filename) { // Decode a resource: SkBitmap bm8888; SkBitmap bm8888Unpremul; SkFILEStream stream(filename.c_str()); SkImageDecoder::Format format = SkImageDecoder::GetStreamFormat(&stream); if (skip_image_format(format)) { return; } SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); if (NULL == decoder.get()) { SkDebugf("couldn't decode %s\n", filename.c_str()); return; } bool success = decoder->decode(&stream, &bm8888, SkBitmap::kARGB_8888_Config, SkImageDecoder::kDecodePixels_Mode); if (!success) { return; } success = stream.rewind(); REPORTER_ASSERT(reporter, success); if (!success) { return; } decoder->setRequireUnpremultipliedColors(true); success = decoder->decode(&stream, &bm8888Unpremul, SkBitmap::kARGB_8888_Config, SkImageDecoder::kDecodePixels_Mode); if (!success) { return; } bool dimensionsMatch = bm8888.width() == bm8888Unpremul.width() && bm8888.height() == bm8888Unpremul.height(); REPORTER_ASSERT(reporter, dimensionsMatch); if (!dimensionsMatch) { return; } // Only do the comparison if the two bitmaps are both 8888. if (bm8888.config() != SkBitmap::kARGB_8888_Config || bm8888Unpremul.config() != SkBitmap::kARGB_8888_Config) { return; } // Now compare the two bitmaps. for (int i = 0; i < bm8888.width(); ++i) { for (int j = 0; j < bm8888.height(); ++j) { // "c0" is the color of the premultiplied bitmap at (i, j). const SkPMColor c0 = *bm8888.getAddr32(i, j); // "c1" is the result of premultiplying the color of the unpremultiplied // bitmap at (i, j). const SkPMColor c1 = premultiply_unpmcolor(*bm8888Unpremul.getAddr32(i, j)); // Compute the difference for each component. int da = SkAbs32(SkGetPackedA32(c0) - SkGetPackedA32(c1)); int dr = SkAbs32(SkGetPackedR32(c0) - SkGetPackedR32(c1)); int dg = SkAbs32(SkGetPackedG32(c0) - SkGetPackedG32(c1)); int db = SkAbs32(SkGetPackedB32(c0) - SkGetPackedB32(c1)); // Alpha component must be exactly the same. REPORTER_ASSERT(reporter, 0 == da); // Color components may not match exactly due to rounding error. REPORTER_ASSERT(reporter, dr <= 1); REPORTER_ASSERT(reporter, dg <= 1); REPORTER_ASSERT(reporter, db <= 1); } } }