bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& matrix, SkBitmap* result, SkIPoint*) { SkScalar scale = fScale; if (scale > SK_Scalar1 || scale <= 0) { return false; } int dstW = SkScalarRoundToInt(src.width() * scale); int dstH = SkScalarRoundToInt(src.height() * scale); if (dstW < 1) { dstW = 1; } if (dstH < 1) { dstH = 1; } SkBitmap tmp; // downsample { SkDevice* dev = proxy->createDevice(dstW, dstH); if (NULL == dev) { return false; } OwnDeviceCanvas canvas(dev); SkPaint paint; paint.setFilterBitmap(true); canvas.scale(scale, scale); canvas.drawBitmap(src, 0, 0, &paint); tmp = dev->accessBitmap(false); } // upscale { SkDevice* dev = proxy->createDevice(src.width(), src.height()); if (NULL == dev) { return false; } OwnDeviceCanvas canvas(dev); SkRect r = SkRect::MakeWH(SkIntToScalar(src.width()), SkIntToScalar(src.height())); canvas.drawBitmapRect(tmp, NULL, r, NULL); *result = dev->accessBitmap(false); } return true; }
static void make_bitmap(SkBitmap* bitmap, GrContext* ctx) { SkCanvas canvas; if (ctx) { SkDevice* dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, 64, 64); canvas.setDevice(dev)->unref(); *bitmap = dev->accessBitmap(false); } else { bitmap->setConfig(SkBitmap::kARGB_8888_Config, 64, 64); bitmap->allocPixels(); canvas.setBitmapDevice(*bitmap); } canvas.drawColor(SK_ColorRED); SkPaint paint; paint.setAntiAlias(true); const SkPoint pts[] = { { 0, 0 }, { 64, 64 } }; const SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE }; paint.setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode))->unref(); canvas.drawCircle(32, 32, 32, paint); }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); Vector<char> encodedImage, base64Data; SkDevice* device = context()->platformContext()->canvas()->getDevice(); if (!encodeImage(device->accessBitmap(false), mimeType, quality, &encodedImage)) return "data:,"; base64Encode(encodedImage, base64Data); return "data:" + mimeType + ";base64," + base64Data; }
bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, SkIPoint* loc) { if (fCount < 1) { return false; } const SkIRect srcBounds = SkIRect::MakeXYWH(loc->x(), loc->y(), src.width(), src.height()); SkIRect bounds; if (!this->filterBounds(srcBounds, ctm, &bounds)) { return false; } const int x0 = bounds.left(); const int y0 = bounds.top(); SkDevice* dst = proxy->createDevice(bounds.width(), bounds.height()); if (NULL == dst) { return false; } OwnDeviceCanvas canvas(dst); SkPaint paint; for (int i = 0; i < fCount; ++i) { SkBitmap tmp; const SkBitmap* srcPtr; SkIPoint pos = *loc; SkImageFilter* filter = fFilters[i]; if (filter) { if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) { return false; } srcPtr = &tmp; } else { srcPtr = &src; } if (fModes) { paint.setXfermodeMode((SkXfermode::Mode)fModes[i]); } else { paint.setXfermode(NULL); } canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint); } loc->set(bounds.left(), bounds.top()); *result = dst->accessBitmap(false); return true; }
/// M: added for HTML5-benchmark performance @{ PassRefPtr<Image> ImageBuffer::getContextImageRef() const { SkCanvas* canvas = imageBufferCanvas(this); if (!canvas) return 0; SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); SkBitmapRef* ref = new SkBitmapRef(orig); RefPtr<Image> image = BitmapImage::create(ref, 0); ref->unref(); return image; }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { SkDevice* device = context()->platformContext()->canvas()->getDevice(); SkBitmap bitmap = device->accessBitmap(false); // if we can't see the pixels directly, call readPixels() to get a copy. // this could happen if the device is backed by a GPU. bitmap.lockPixels(); // balanced by our destructor, or explicitly if getPixels() fails if (!bitmap.getPixels()) { bitmap.unlockPixels(); SkIRect bounds = SkIRect::MakeWH(device->width(), device->height()); if (!device->readPixels(bounds, &bitmap)) return "data:,"; } return ImageToDataURL(bitmap, mimeType, quality); }
PassRefPtr<Image> ImageBuffer::copyImage() const { ASSERT(context()); SkCanvas* canvas = imageBufferCanvas(this); if (!canvas) return 0; SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); SkBitmap copy; if (PlatformBridge::canSatisfyMemoryAllocation(orig.getSize())) orig.copyTo(©, orig.config()); SkBitmapRef* ref = new SkBitmapRef(copy); RefPtr<Image> image = BitmapImage::create(ref, 0); ref->unref(); return image; }
static void make_bitmap(SkBitmap* bitmap, GrContext* ctx, SkIRect* center) { SkDevice* dev; SkCanvas canvas; const int kFixed = 28; const int kStretchy = 8; const int kSize = 2*kFixed + kStretchy; #if SK_SUPPORT_GPU if (ctx) { dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, kSize, kSize); *bitmap = dev->accessBitmap(false); } else #endif { bitmap->setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize); bitmap->allocPixels(); dev = new SkDevice(*bitmap); } canvas.setDevice(dev)->unref(); canvas.clear(0); SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize)); const SkScalar strokeWidth = SkIntToScalar(6); const SkScalar radius = SkIntToScalar(kFixed) - strokeWidth/2; center->setXYWH(kFixed, kFixed, kStretchy, kStretchy); SkPaint paint; paint.setAntiAlias(true); paint.setColor(0xFFFF0000); canvas.drawRoundRect(r, radius, radius, paint); r.setXYWH(SkIntToScalar(kFixed), 0, SkIntToScalar(kStretchy), SkIntToScalar(kSize)); paint.setColor(0x8800FF00); canvas.drawRect(r, paint); r.setXYWH(0, SkIntToScalar(kFixed), SkIntToScalar(kSize), SkIntToScalar(kStretchy)); paint.setColor(0x880000FF); canvas.drawRect(r, paint); }
SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) { #ifdef SK_SUPPORT_GL #ifndef USE_OFFSCREEN aglSetWindowRef(gAGLContext, NULL); #endif #endif switch (fCanvasType) { case kRaster_CanvasType: canvas = this->INHERITED::beforeChildren(canvas); break; case kPicture_CanvasType: fPicture = new SkPicture; canvas = fPicture->beginRecording(9999, 9999); break; #ifdef SK_SUPPORT_GL case kOpenGL_CanvasType: { //SkGLCanvas::DeleteAllTextures(); // just for testing SkDevice* device = canvas->getDevice(); const SkBitmap& bitmap = device->accessBitmap(true); // first clear the raster bitmap, so we don't see any leftover bits bitmap.eraseColor(0); // now setup our glcanvas setup_offscreen_gl(bitmap, (WindowRef)this->getHWND()); fGLCanvas = new SkGLCanvas; fGLCanvas->setViewport(bitmap.width(), bitmap.height()); canvas = fGLCanvas; break; } #endif } if (fUseClip) { canvas->drawColor(0xFFFF88FF); canvas->clipPath(fClipPath); } return canvas; }
PassRefPtr<Image> ImageBuffer::copyImage() const { ASSERT(context() && context()->platformContext()); #if ENABLE(ACCELERATED_2D_CANVAS) context()->syncSoftwareCanvas(); #endif // Request for canvas bitmap; conversion required. if (context()->platformContext()->isRecording()) context()->platformContext()->convertToNonRecording(); SkCanvas* canvas = context()->platformContext()->mCanvas; SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); SkBitmap copy; if (PlatformBridge::canSatisfyMemoryAllocation(orig.getSize())) orig.copyTo(©, orig.config()); SkBitmapRef* ref = new SkBitmapRef(copy); RefPtr<Image> image = BitmapImage::create(ref, 0); ref->unref(); return image; }
CGContextRef BitLockerSkia::cgContext() { SkDevice* device = m_canvas->getDevice(); ASSERT(device); if (!device) return 0; releaseIfNeeded(); const SkBitmap& bitmap = device->accessBitmap(true); bitmap.lockPixels(); void* pixels = bitmap.getPixels(); m_cgContext = CGBitmapContextCreate(pixels, device->width(), device->height(), 8, bitmap.rowBytes(), CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst); // Apply device matrix. CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1); contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -device->height()); CGContextConcatCTM(m_cgContext, contentsTransform); // Apply clip in device coordinates. CGMutablePathRef clipPath = CGPathCreateMutable(); SkRegion::Iterator iter(m_canvas->getTotalClip()); for (; !iter.done(); iter.next()) { IntRect rect = iter.rect(); CGPathAddRect(clipPath, 0, rect); } CGContextAddPath(m_cgContext, clipPath); CGContextClip(m_cgContext); CGPathRelease(clipPath); // Apply content matrix. const SkMatrix& skMatrix = m_canvas->getTotalMatrix(); CGAffineTransform affine = SkMatrixToCGAffineTransform(skMatrix); CGContextConcatCTM(m_cgContext, affine); return m_cgContext; }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(context() && context()->platformContext()); // Request for canvas bitmap; conversion required. if (context()->platformContext()->isRecording()) context()->platformContext()->convertToNonRecording(); // CAPPFIX_WEB_WEBGL SkCanvas* canvas = imageBufferCanvas(this); // CAPPFIX_WEB_WEBGL_END SkDevice* device = canvas->getDevice(); SkBitmap bitmap = device->accessBitmap(false); // if we can't see the pixels directly, call readPixels() to get a copy. // this could happen if the device is backed by a GPU. bitmap.lockPixels(); // balanced by our destructor, or explicitly if getPixels() fails if (!bitmap.getPixels()) { bitmap.unlockPixels(); SkIRect bounds = SkIRect::MakeWH(device->width(), device->height()); if (!canvas->readPixels(bounds, &bitmap)) return "data:,"; } return ImageToDataURL(bitmap, mimeType, quality); }
bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& matrix, SkBitmap* result, SkIPoint* loc) { SkColorFilter* cf = fColorFilter; if (NULL == cf) { *result = src; return true; } SkDevice* dev = proxy->createDevice(src.width(), src.height()); if (NULL == dev) { return false; } OwnDeviceCanvas canvas(dev); SkPaint paint; paint.setXfermodeMode(SkXfermode::kSrc_Mode); paint.setColorFilter(fColorFilter); canvas.drawSprite(src, 0, 0, &paint); *result = dev->accessBitmap(false); return true; }
PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkCanvas& srcCanvas, const IntSize& size) { RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4); SkDevice* srcDevice = srcCanvas.getDevice(); SkBitmap::Config srcConfig = srcDevice->accessBitmap(false).config(); if (srcConfig == SkBitmap::kNo_Config) { // This is an empty SkBitmap that could not be configured. ASSERT(!size.width() || !size.height()); return result.release(); } unsigned char* data = result->data(); if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height()) memset(data, 0, result->length()); int originX = rect.x(); int destX = 0; if (originX < 0) { destX = -originX; originX = 0; } int endX = rect.maxX(); if (endX > size.width()) endX = size.width(); int numColumns = endX - originX; if (numColumns <= 0) return result.release(); int originY = rect.y(); int destY = 0; if (originY < 0) { destY = -originY; originY = 0; } int endY = rect.maxY(); if (endY > size.height()) endY = size.height(); int numRows = endY - originY; if (numRows <= 0) return result.release(); ASSERT(srcConfig == SkBitmap::kARGB_8888_Config); unsigned destBytesPerRow = 4 * rect.width(); SkBitmap srcBitmap; srcBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, destBytesPerRow); srcBitmap.setPixels(data); //srcDevice.readPixels(SkIRect::MakeXYWH(originX, originY, numColumns, numRows), &srcBitmap, SkCanvas::kNative_Premul_Config8888); SkCanvas::Config8888 config8888; if (multiplied == Premultiplied) config8888 = SkCanvas::kRGBA_Premul_Config8888; else config8888 = SkCanvas::kRGBA_Unpremul_Config8888; srcCanvas.readPixels(&srcBitmap, originX, originY, SkCanvas::kNative_Premul_Config8888); unsigned char* destRow = data + destY * destBytesPerRow + destX * 4; // Do conversion of byte order and alpha divide (if necessary) for (int y = 0; y < numRows; ++y) { SkPMColor* srcBitmapRow = srcBitmap.getAddr32(0, y); for (int x = 0; x < numColumns; ++x) { SkPMColor srcPMColor = srcBitmapRow[x]; unsigned char* destPixel = &destRow[x * 4]; if (multiplied == Unmultiplied) { unsigned char a = SkGetPackedA32(srcPMColor); destPixel[0] = a ? SkGetPackedR32(srcPMColor) * 255 / a : 0; destPixel[1] = a ? SkGetPackedG32(srcPMColor) * 255 / a : 0; destPixel[2] = a ? SkGetPackedB32(srcPMColor) * 255 / a : 0; destPixel[3] = a; } else { // Input and output are both pre-multiplied, we just need to re-arrange the // bytes from the bitmap format to RGBA. destPixel[0] = SkGetPackedR32(srcPMColor); destPixel[1] = SkGetPackedG32(srcPMColor); destPixel[2] = SkGetPackedB32(srcPMColor); destPixel[3] = SkGetPackedA32(srcPMColor); } } destRow += destBytesPerRow; } return result.release(); }
static void blowup(SkCanvas* canvas, const SkIRect& src, const SkRect& dst) { SkDevice* device = canvas->getDevice(); const SkBitmap& bm = device->accessBitmap(false); canvas->drawBitmapRect(bm, &src, dst, NULL); }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { m_context->platformContext()->makeGrContextCurrent(); SkDevice* device = context()->platformContext()->canvas()->getDevice(); return ImageToDataURL(device->accessBitmap(false), mimeType, quality); }