void onOnceBeforeDraw() override { // Copyright-free file from http://openclipart.org/detail/29213/paper-plane-by-ddoo SkString pngFilename = GetResourcePath("plane.png"); SkAutoDataUnref data(SkData::NewFromFileName(pngFilename.c_str())); if (data.get()) { // Create a cache which will boot the pixels out anytime the // bitmap is unlocked. SkAutoTUnref<SkDiscardableMemoryPool> pool( SkDiscardableMemoryPool::Create(1)); SkAssertResult(SkInstallDiscardablePixelRef(SkImageGenerator::NewFromData(data), NULL, &fBitmap, pool)); } }
// example of how Android will do this inside their BitmapFactory static SkPixelRef* install_pixel_ref(SkBitmap* bitmap, SkStreamRewindable* stream, int sampleSize, bool ditherImage) { SkASSERT(bitmap != NULL); SkASSERT(stream != NULL); SkASSERT(stream->rewind()); SkColorType colorType = bitmap->colorType(); SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType); if (SkInstallDiscardablePixelRef( SkDecodingImageGenerator::Create(stream, opts), bitmap)) { return bitmap->pixelRef(); } return NULL; }
void onDraw(SkCanvas* canvas) override { SkBitmap bm; SkString filename = GetResourcePath("mandrill_128."); filename.append(this->fileExtension()); SkAutoTUnref<SkData> fileData(SkData::NewFromFileName(filename.c_str())); if (nullptr == fileData) { SkDebugf("Could not open the file. Did you forget to set the resourcePath?\n"); return; } if (!SkInstallDiscardablePixelRef(fileData, &bm)) { SkDebugf("Could not install discardable pixel ref.\n"); return; } canvas->drawBitmap(bm, 0, 0); }
// Creates a SkBitmap that is backed by SkDiscardablePixelRef. SkBitmap DeferredImageDecoder::createBitmap(size_t index) { SkISize decodedSize = m_frameGenerator->getFullSize(); ASSERT(decodedSize.width() > 0); ASSERT(decodedSize.height() > 0); #if SK_B32_SHIFT // Little-endian RGBA pixels. (Android) const SkColorType colorType = kRGBA_8888_SkColorType; #else const SkColorType colorType = kBGRA_8888_SkColorType; #endif const SkImageInfo info = SkImageInfo::Make(decodedSize.width(), decodedSize.height(), colorType, kPremul_SkAlphaType); SkBitmap bitmap; DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenerator, info, index); bool installed = SkInstallDiscardablePixelRef(generator, &bitmap); ASSERT_UNUSED(installed, installed); bitmap.pixelRef()->setURI(labelDiscardable); generator->setGenerationId(bitmap.getGenerationID()); return bitmap; }
// Fits SkPicture::InstallPixelRefProc call signature. // Used in SkPictureData::CreateFromStream bool sk_tools::LazyDecodeBitmap(const void* src, size_t length, SkBitmap* dst) { SkAutoDataUnref data(SkData::NewWithCopy(src, length)); if (NULL == data.get()) { return false; } SkAutoTDelete<SkImageGenerator> gen(SkImageGenerator::NewFromData(data)); SkImageInfo info; if ((NULL == gen.get()) || !gen->getInfo(&info)) { return false; } SkDiscardableMemory::Factory* pool = NULL; if ((!FLAGS_useVolatileCache) || (info.width() * info.height() < 32 * 1024)) { // how to do switching with SkDiscardableMemory. pool = SkGetGlobalDiscardableMemoryPool(); // Only meaningful if platform has a default discardable // memory implementation that differs from the global DM pool. } return SkInstallDiscardablePixelRef(gen.detach(), dst, pool); }
static void check_pixelref(TestImageGenerator::TestType type, skiatest::Reporter* reporter, PixelRefType pixelRefType, SkDiscardableMemory::Factory* factory) { SkASSERT((pixelRefType >= 0) && (pixelRefType <= kLast_PixelRefType)); SkAutoTDelete<SkImageGenerator> gen(SkNEW_ARGS(TestImageGenerator, (type, reporter))); REPORTER_ASSERT(reporter, gen.get() != NULL); SkBitmap lazy; bool success; if (kSkCaching_PixelRefType == pixelRefType) { // Ignore factory; use global cache. success = SkCachingPixelRef::Install(gen.detach(), &lazy); } else { success = SkInstallDiscardablePixelRef(gen.detach(), NULL, &lazy, factory); } REPORTER_ASSERT(reporter, success); if (TestImageGenerator::kSucceedGetPixels_TestType == type) { check_test_image_generator_bitmap(reporter, lazy); } else if (TestImageGenerator::kFailGetPixels_TestType == type) { SkAutoLockPixels autoLockPixels(lazy); REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); } }
// This is the public API bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, SkBitmap* dst) { return SkInstallDiscardablePixelRef(generator, dst, NULL); }
// Returned bitmap is lazy. Only lazy bitmaps hold onto the original data. static SkBitmap bitmap_from_data(SkData* data) { SkASSERT(data); SkBitmap bm; SkInstallDiscardablePixelRef(data, &bm); return bm; }
static bool install_skDiscardablePixelRef(SkData* encoded, SkBitmap* dst) { // Use system-default discardable memory. return SkInstallDiscardablePixelRef( SkDecodingImageGenerator::Create( encoded, SkDecodingImageGenerator::Options()), dst); }
static bool install_skDiscardablePixelRef(SkData* encoded, SkBitmap* dst) { // Use system-default discardable memory. return SkInstallDiscardablePixelRef(encoded, dst); }
bool GetResourceAsBitmap(const char* resource, SkBitmap* dst) { SkString resourcePath = GetResourcePath(resource); SkAutoTUnref<SkData> resourceData( SkData::NewFromFileName(resourcePath.c_str())); return resourceData && SkInstallDiscardablePixelRef(resourceData, dst); }
/** * Given either a SkStream or a SkData, try to decode the encoded * image using the specified options and report errors. */ static void test_options(skiatest::Reporter* reporter, const SkDecodingImageGenerator::Options& opts, SkStreamRewindable* encodedStream, SkData* encodedData, bool useData, const SkString& path) { SkBitmap bm; bool success = false; if (useData) { if (NULL == encodedData) { return; } success = SkInstallDiscardablePixelRef( SkDecodingImageGenerator::Create(encodedData, opts), &bm); } else { if (NULL == encodedStream) { return; } success = SkInstallDiscardablePixelRef( SkDecodingImageGenerator::Create(encodedStream->duplicate(), opts), &bm); } if (!success) { if (opts.fUseRequestedColorType && (kARGB_4444_SkColorType == opts.fRequestedColorType)) { return; // Ignore known conversion inabilities. } // If we get here, it's a failure and we will need more // information about why it failed. ERRORF(reporter, "Bounds decode failed [sampleSize=%d dither=%s " "colorType=%s %s]", opts.fSampleSize, yn(opts.fDitherImage), options_colorType(opts), path.c_str()); return; } #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX) // Android is the only system that use Skia's image decoders in // production. For now, we'll only verify that samplesize works // on systems where it already is known to work. REPORTER_ASSERT(reporter, check_rounding(bm.height(), kExpectedHeight, opts.fSampleSize)); REPORTER_ASSERT(reporter, check_rounding(bm.width(), kExpectedWidth, opts.fSampleSize)); // The ImageDecoder API doesn't guarantee that SampleSize does // anything at all, but the decoders that this test excercises all // produce an output size in the following range: // (((sample_size * out_size) > (in_size - sample_size)) // && out_size <= SkNextPow2(((in_size - 1) / sample_size) + 1)); #endif // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX SkAutoLockPixels alp(bm); if (bm.getPixels() == NULL) { ERRORF(reporter, "Pixel decode failed [sampleSize=%d dither=%s " "colorType=%s %s]", opts.fSampleSize, yn(opts.fDitherImage), options_colorType(opts), path.c_str()); return; } SkColorType requestedColorType = opts.fRequestedColorType; REPORTER_ASSERT(reporter, (!opts.fUseRequestedColorType) || (bm.colorType() == requestedColorType)); // Condition under which we should check the decoding results: if ((kN32_SkColorType == bm.colorType()) && (!path.endsWith(".jpg")) // lossy && (opts.fSampleSize == 1)) { // scaled const SkColor* correctPixels = kExpectedPixels; SkASSERT(bm.height() == kExpectedHeight); SkASSERT(bm.width() == kExpectedWidth); int pixelErrors = 0; for (int y = 0; y < bm.height(); ++y) { for (int x = 0; x < bm.width(); ++x) { if (*correctPixels != bm.getColor(x, y)) { ++pixelErrors; } ++correctPixels; } } if (pixelErrors != 0) { ERRORF(reporter, "Pixel-level mismatch (%d of %d) " "[sampleSize=%d dither=%s colorType=%s %s]", pixelErrors, kExpectedHeight * kExpectedWidth, opts.fSampleSize, yn(opts.fDitherImage), options_colorType(opts), path.c_str()); } } }
bool SkInstallDiscardablePixelRef(SkData* encoded, SkBitmap* dst) { SkImageGenerator* generator = SkImageGenerator::NewFromEncoded(encoded); return generator ? SkInstallDiscardablePixelRef(generator, NULL, dst, NULL) : false; }