static void test_interlaced_gif_data(skiatest::Reporter* r, void* data, size_t size) { SkBitmap bm; bool imageDecodeSuccess = decode_memory(data, size, &bm); REPORTER_ASSERT(r, imageDecodeSuccess); REPORTER_ASSERT(r, bm.width() == 9); REPORTER_ASSERT(r, bm.height() == 9); REPORTER_ASSERT(r, !(bm.empty())); if (!(bm.empty())) { REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xffff0000); REPORTER_ASSERT(r, bm.getColor(1, 0) == 0xffffff00); REPORTER_ASSERT(r, bm.getColor(2, 0) == 0xff00ffff); REPORTER_ASSERT(r, bm.getColor(0, 2) == 0xffffffff); REPORTER_ASSERT(r, bm.getColor(1, 2) == 0xffff00ff); REPORTER_ASSERT(r, bm.getColor(2, 2) == 0xff0000ff); REPORTER_ASSERT(r, bm.getColor(0, 4) == 0xff808080); REPORTER_ASSERT(r, bm.getColor(1, 4) == 0xff000000); REPORTER_ASSERT(r, bm.getColor(2, 4) == 0xff00ff00); REPORTER_ASSERT(r, bm.getColor(0, 6) == 0xffff0000); REPORTER_ASSERT(r, bm.getColor(1, 6) == 0xffffff00); REPORTER_ASSERT(r, bm.getColor(2, 6) == 0xff00ffff); REPORTER_ASSERT(r, bm.getColor(0, 8) == 0xffffffff); REPORTER_ASSERT(r, bm.getColor(1, 8) == 0xffff00ff); REPORTER_ASSERT(r, bm.getColor(2, 8) == 0xff0000ff); } }
static void test_gif_data_no_colormap(skiatest::Reporter* r, void* data, size_t size) { SkBitmap bm; bool imageDecodeSuccess = decode_memory(data, size, &bm); REPORTER_ASSERT(r, imageDecodeSuccess); REPORTER_ASSERT(r, bm.width() == 1); REPORTER_ASSERT(r, bm.height() == 1); REPORTER_ASSERT(r, !(bm.empty())); if (!(bm.empty())) { REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xFF000000); } }
/** This function tests three differently encoded images against the original bitmap */ static void test_three_encodings(skiatest::Reporter* reporter, InstallEncoded install) { SkBitmap original; make_test_image(&original); REPORTER_ASSERT(reporter, !original.empty()); REPORTER_ASSERT(reporter, !original.isNull()); if (original.empty() || original.isNull()) { return; } static const SkImageEncoder::Type types[] = { SkImageEncoder::kPNG_Type, SkImageEncoder::kJPEG_Type, SkImageEncoder::kWEBP_Type }; for (size_t i = 0; i < SK_ARRAY_COUNT(types); i++) { SkImageEncoder::Type type = types[i]; SkAutoDataUnref encoded(create_data_from_bitmap(original, type)); REPORTER_ASSERT(reporter, encoded.get() != NULL); if (NULL == encoded.get()) { continue; } SkBitmap lazy; bool installSuccess = install(encoded.get(), &lazy); REPORTER_ASSERT(reporter, installSuccess); if (!installSuccess) { continue; } REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); { SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. REPORTER_ASSERT(reporter, lazy.getPixels()); if (NULL == lazy.getPixels()) { continue; } } // pixels should be gone! REPORTER_ASSERT(reporter, NULL == lazy.getPixels()); { SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. REPORTER_ASSERT(reporter, lazy.getPixels()); if (NULL == lazy.getPixels()) { continue; } } bool comparePixels = (SkImageEncoder::kPNG_Type == type); compare_bitmaps(reporter, original, lazy, comparePixels); } }
static SkCanvas* create_canvas_from_canvas_layer(const SkCanvasLayerState& layerState) { SkASSERT(kRaster_CanvasBackend == layerState.type); SkBitmap bitmap; SkColorType colorType = layerState.raster.config == kARGB_8888_RasterConfig ? kN32_SkColorType : layerState.raster.config == kRGB_565_RasterConfig ? kRGB_565_SkColorType : kUnknown_SkColorType; if (colorType == kUnknown_SkColorType) { return nullptr; } bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height, colorType, kPremul_SkAlphaType), layerState.raster.pixels, (size_t) layerState.raster.rowBytes); SkASSERT(!bitmap.empty()); SkASSERT(!bitmap.isNull()); SkAutoTUnref<SkCanvas> canvas(new SkCanvas(bitmap)); // setup the matrix and clip setup_canvas_from_MC_state(layerState.mcState, canvas.get()); return canvas.release(); }
sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) { #if SK_SUPPORT_GPU if (!context) { return nullptr; } if (GrTexture* peek = as_SIB(this)->onPeekTexture()) { return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr; } SkBitmap bmp; if (!this->internal_getBM(&bmp)) { return nullptr; } if (bmp.empty()) { return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props()); } SkAutoTUnref<GrTexture> resultTex( GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter())); if (!resultTex) { return nullptr; } SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()), this->uniqueID(), resultTex, &this->props(), at); #else return nullptr; #endif }
/** * First, make sure that writing an 8-bit RGBA KTX file and then * reading it produces the same bitmap. */ DEF_TEST(KtxReadWrite, reporter) { // Random number generator with explicit seed for reproducibility SkRandom rand(0x1005cbad); SkBitmap bm8888; bool pixelsAllocated = bm8888.allocN32Pixels(128, 128); REPORTER_ASSERT(reporter, pixelsAllocated); uint8_t *pixels = reinterpret_cast<uint8_t*>(bm8888.getPixels()); REPORTER_ASSERT(reporter, NULL != pixels); if (NULL == pixels) { return; } uint8_t *row = pixels; for (int y = 0; y < bm8888.height(); ++y) { for (int x = 0; x < bm8888.width(); ++x) { uint8_t a = rand.nextRangeU(0, 255); uint8_t r = rand.nextRangeU(0, 255); uint8_t g = rand.nextRangeU(0, 255); uint8_t b = rand.nextRangeU(0, 255); SkPMColor &pixel = *(reinterpret_cast<SkPMColor*>(row + x*sizeof(SkPMColor))); pixel = SkPreMultiplyARGB(a, r, g, b); } row += bm8888.rowBytes(); } REPORTER_ASSERT(reporter, !(bm8888.empty())); SkAutoDataUnref encodedData(SkImageEncoder::EncodeData(bm8888, SkImageEncoder::kKTX_Type, 0)); REPORTER_ASSERT(reporter, NULL != encodedData); SkAutoTUnref<SkMemoryStream> stream(SkNEW_ARGS(SkMemoryStream, (encodedData))); REPORTER_ASSERT(reporter, NULL != stream); SkBitmap decodedBitmap; bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap); REPORTER_ASSERT(reporter, imageDecodeSuccess); REPORTER_ASSERT(reporter, decodedBitmap.colorType() == bm8888.colorType()); REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == bm8888.alphaType()); REPORTER_ASSERT(reporter, decodedBitmap.width() == bm8888.width()); REPORTER_ASSERT(reporter, decodedBitmap.height() == bm8888.height()); REPORTER_ASSERT(reporter, !(decodedBitmap.empty())); uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels()); REPORTER_ASSERT(reporter, NULL != decodedPixels); REPORTER_ASSERT(reporter, decodedBitmap.getSize() == bm8888.getSize()); if (NULL == decodedPixels) { return; } REPORTER_ASSERT(reporter, memcmp(decodedPixels, pixels, decodedBitmap.getSize()) == 0); }
static void test_gif_data_dims(skiatest::Reporter* r, void* data, size_t size, int width, int height) { SkBitmap bm; bool imageDecodeSuccess = decode_memory(data, size, &bm); REPORTER_ASSERT(r, imageDecodeSuccess); REPORTER_ASSERT(r, bm.width() == width); REPORTER_ASSERT(r, bm.height() == height); REPORTER_ASSERT(r, !(bm.empty())); }
/** * Next test is to see whether or not reading an unpremultiplied KTX file accurately * creates a premultiplied buffer... */ DEF_TEST(KtxReadUnpremul, reporter) { static const uint8_t kHalfWhiteKTX[] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, // First twelve bytes is magic 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A, // KTX identifier string 0x01, 0x02, 0x03, 0x04, // Then magic endian specifier 0x01, 0x14, 0x00, 0x00, // uint32_t fGLType; 0x01, 0x00, 0x00, 0x00, // uint32_t fGLTypeSize; 0x08, 0x19, 0x00, 0x00, // uint32_t fGLFormat; 0x58, 0x80, 0x00, 0x00, // uint32_t fGLInternalFormat; 0x08, 0x19, 0x00, 0x00, // uint32_t fGLBaseInternalFormat; 0x02, 0x00, 0x00, 0x00, // uint32_t fPixelWidth; 0x02, 0x00, 0x00, 0x00, // uint32_t fPixelHeight; 0x00, 0x00, 0x00, 0x00, // uint32_t fPixelDepth; 0x00, 0x00, 0x00, 0x00, // uint32_t fNumberOfArrayElements; 0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfFaces; 0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfMipmapLevels; 0x00, 0x00, 0x00, 0x00, // uint32_t fBytesOfKeyValueData; 0x10, 0x00, 0x00, 0x00, // image size: 2x2 image of RGBA = 4 * 4 = 16 bytes 0xFF, 0xFF, 0xFF, 0x80, // Pixel 1 0xFF, 0xFF, 0xFF, 0x80, // Pixel 2 0xFF, 0xFF, 0xFF, 0x80, // Pixel 3 0xFF, 0xFF, 0xFF, 0x80};// Pixel 4 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(kHalfWhiteKTX, sizeof(kHalfWhiteKTX))); REPORTER_ASSERT(reporter, stream); SkBitmap decodedBitmap; bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap); if (!imageDecodeSuccess) { ERRORF(reporter, "failed to decode the KTX stream"); return; } REPORTER_ASSERT(reporter, decodedBitmap.colorType() == kN32_SkColorType); REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == kPremul_SkAlphaType); REPORTER_ASSERT(reporter, decodedBitmap.width() == 2); REPORTER_ASSERT(reporter, decodedBitmap.height() == 2); REPORTER_ASSERT(reporter, !(decodedBitmap.empty())); uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels()); REPORTER_ASSERT(reporter, decodedPixels); uint8_t *row = decodedPixels; for (int j = 0; j < decodedBitmap.height(); ++j) { for (int i = 0; i < decodedBitmap.width(); ++i) { SkPMColor pixel = *(reinterpret_cast<SkPMColor*>(row + i*sizeof(SkPMColor))); REPORTER_ASSERT(reporter, SkPreMultiplyARGB(0x80, 0xFF, 0xFF, 0xFF) == pixel); } row += decodedBitmap.rowBytes(); } }
static void compare_bitmaps(skiatest::Reporter* reporter, const SkBitmap& b1, const SkBitmap& b2, bool pixelPerfect = true) { REPORTER_ASSERT(reporter, b1.empty() == b2.empty()); REPORTER_ASSERT(reporter, b1.width() == b2.width()); REPORTER_ASSERT(reporter, b1.height() == b2.height()); REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); SkAutoLockPixels autoLockPixels1(b1); SkAutoLockPixels autoLockPixels2(b2); REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); if (b1.isNull() || b1.empty()) { return; } REPORTER_ASSERT(reporter, b1.getPixels()); REPORTER_ASSERT(reporter, b2.getPixels()); if ((!(b1.getPixels())) || (!(b2.getPixels()))) { return; } if ((b1.width() != b2.width()) || (b1.height() != b2.height())) { return; } if (!pixelPerfect) { return; } int pixelErrors = 0; for (int y = 0; y < b2.height(); ++y) { for (int x = 0; x < b2.width(); ++x) { if (b1.getColor(x, y) != b2.getColor(x, y)) { ++pixelErrors; } } } REPORTER_ASSERT(reporter, 0 == pixelErrors); }
sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) { #if SK_SUPPORT_GPU if (!context) { return nullptr; } if (GrContext* curContext = as_SIB(this)->onGetContext()) { return curContext == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr; } auto proxyProvider = context->contextPriv().proxyProvider(); SkBitmap bmp; // At this point, we are definitely not texture-backed, so we must be raster or generator // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that // we are strictly raster-backed (i.e. generator images become raster when they are specialized) // in which case getROPixels could turn into peekPixels... if (!this->getROPixels(&bmp)) { return nullptr; } if (bmp.empty()) { return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props()); } // TODO: this is a tight copy of 'bmp' but it doesn't have to be (given SkSpecialImage's // semantics). Since this is cached though we would have to bake the fit into the cache key. sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(proxyProvider, bmp); if (!proxy) { return nullptr; } const SkIRect rect = SkIRect::MakeWH(proxy->width(), proxy->height()); // GrMakeCachedBitmapProxy has uploaded only the specified subset of 'bmp' so we need not // bother with SkBitmap::getSubset return SkSpecialImage::MakeDeferredFromGpu(context, rect, this->uniqueID(), std::move(proxy), sk_ref_sp(this->getColorSpace()), &this->props(), this->alphaType()); #else return nullptr; #endif }
void svg_renderer::update_drawing (const QTransform &transform, const QRectF &rect_to_update, int cache_object_type) { m_cache->lock (); DO_ON_EXIT (m_cache->unlock ()); double cache_zoom_x = m_cache->zoom_x (); double cache_zoom_y = m_cache->zoom_y (); double cur_zoom_x = transform.m11 (); double cur_zoom_y = transform.m22 (); QRectF rect_to_draw = rect_to_update; QTransform real_transform = transform; SkBitmap bitmap; bitmap.setConfig (SkBitmap::kARGB_8888_Config, rect_to_draw.width (), rect_to_draw.height ()); bitmap.allocPixels (); SkBitmapDevice device (bitmap); SkCanvas canvas (&device); if (!are_equal (cache_zoom_x, cur_zoom_x) || !are_equal (cache_zoom_y, cur_zoom_y)) { QTransform scale_transform = QTransform::fromScale (cache_zoom_x / cur_zoom_x, cache_zoom_y / cur_zoom_y); real_transform = real_transform * scale_transform; canvas.setMatrix (qt2skia::matrix (scale_transform.inverted ())); rect_to_draw = scale_transform.mapRect (rect_to_draw); } canvas.drawColor (SK_ColorTRANSPARENT, SkXfermode::kSrc_Mode); pair<render_cache_id, render_cache_id> it_pair = render_cache_id::get_id_for_pixel_rect (real_transform, rect_to_draw, cache_object_type); for (int x = it_pair.first.x (); x <= it_pair.second.x (); x++) for (int y = it_pair.first.y (); y <= it_pair.second.y (); y++) { render_cache_id cur_id (x, y, cache_object_type); SkBitmap bitmap = m_cache->bitmap (cur_id); if (bitmap.empty ()) continue; QRectF pixel_rect = cur_id.pixel_rect (real_transform); canvas.drawBitmap (bitmap, SkFloatToScalar (pixel_rect.x ()), SkFloatToScalar (pixel_rect.y ())); } m_cache->set_current_screen (bitmap, cache_object_type); }
/** * This test contains basic sanity checks concerning bitmaps. */ DEF_TEST(Bitmap, reporter) { // Zero-sized bitmaps are allowed for (int width = 0; width < 2; ++width) { for (int height = 0; height < 2; ++height) { SkBitmap bm; bool setConf = bm.setInfo(SkImageInfo::MakeN32Premul(width, height)); REPORTER_ASSERT(reporter, setConf); if (setConf) { bm.allocPixels(); } REPORTER_ASSERT(reporter, SkToBool(width & height) != bm.empty()); } } test_bigwidth(reporter); test_allocpixels(reporter); test_bigalloc(reporter); test_peekpixels(reporter); }
sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) { #if SK_SUPPORT_GPU if (!context) { return nullptr; } if (GrTexture* peek = as_SIB(this)->onPeekTexture()) { return peek->getContext() == context ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr; } SkBitmap bmp; // At this point, we are definitely not texture-backed, so we must be raster or generator // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that // we are strictly raster-backed (i.e. generator images become raster when they are specialized) // in which case getROPixels could turn into peekPixels... if (!this->getROPixels(&bmp)) { return nullptr; } if (bmp.empty()) { return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props()); } sk_sp<GrTexture> resultTex(GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter(), SkSourceGammaTreatment::kRespect)); if (!resultTex) { return nullptr; } SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()), this->uniqueID(), resultTex, sk_ref_sp(this->getColorSpace()), &this->props(), at); #else return nullptr; #endif }