How to Copy Contents of One Canvas to Another Canvas Locally

How to Copy Contents of One Canvas to Another Canvas Locally

Actually you don't have to create an image at all. drawImage() will accept a Canvas as well as an Image object.

//grab the context from your destination canvas
var destCtx = destinationCanvas.getContext('2d');

//call its drawImage() function passing it the source canvas directly
destCtx.drawImage(sourceCanvas, 0, 0);

Way faster than using an ImageData object or Image element.

Note that sourceCanvas can be a HTMLImageElement, HTMLVideoElement, or a HTMLCanvasElement. As mentioned by Dave in a comment below this answer, you cannot use a canvas drawing context as your source. If you have a canvas drawing context instead of the canvas element it was created from, there is a reference to the original canvas element on the context under context.canvas.

Here is a jsPerf to demonstrate why this is the only right way to clone a canvas: http://jsperf.com/copying-a-canvas-element

Copying and pasting one canvas inside another canvas's corner

The way you are drawing the first canvas on the second one is not correct. You can directly draw a canvas on another canvas using drawImage() method.

var first = document.getElementById('first').getContext('2d');var sec = document.getElementById('second').getContext('2d');
// draw on first canvasfirst.fillStyle = '#07C';first.fillRect(0, 0, first.canvas.width, first.canvas.height);
// draw image on second canvasvar img = new Image();img.src = "http://lorempixel.com/300/300";img.onload = function() { sec.drawImage(img, 0, 0, sec.canvas.width, sec.canvas.height); sec.drawImage(first.canvas, 100, 100, 100, 100); // draw first canvas on a portion of second canvas};
body {display: flex}
<canvas id="first" width="200" height="200"></canvas><canvas id="second" width="200" height="200"></canvas>

Display canvas image from one canvas to another canvas using base64

You shouldn't use base64 to copy the canvas. You can pass the source canvas into the destination canvas' context method, drawImage.

Otherwise you will suffer a serious performance hit. See my jsperf test at http://jsperf.com/copying-a-canvas-element.

drawImage() will accept a Canvas as well as an Image object.

Try this:

//grab the context from your destination canvas
var destCtx = destinationCanvas.getContext('2d');

//call its drawImage() function passing it the source canvas directly
destCtx.drawImage(sourceCanvas, 0, 0);

Can you copy only a specific area from one Canvas to another?

getImageData(sx, sy, sw, sh)

allows you to extract image data based on a X/Y coordinate and a width & height, and

putImageData(imageData, dx, dy)

allows you to place it at a X/Y coordinate.

Or use drawImage, that allows you to use the existing canvas as "input" directly, and you can specify X/Y and width/height for both the origin and the target:

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

How to copy contents of one canvas to another?

Here's example code which lets you paint on the left side and which mirrors the canvas at runtime on the right side.

import java.util.Random;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Main extends Application {

private static double SCENE_WIDTH = 1280;
private static double SCENE_HEIGHT = 720;

static Random random = new Random();

Canvas canvas;
Canvas copyCanvas;
GraphicsContext graphicsContext;
GraphicsContext copyGraphicsContext;

AnimationTimer loop;

Point2D mouseLocation = new Point2D( 0, 0);
boolean mousePressed = false;
Point2D prevMouseLocation = new Point2D( 0, 0);

Scene scene;

Image brush = createBrush( 30.0, Color.CHOCOLATE);
double brushWidthHalf = brush.getWidth() / 2.0;
double brushHeightHalf = brush.getHeight() / 2.0;



@Override
public void start(Stage primaryStage) {

BorderPane root = new BorderPane();

canvas = new Canvas( SCENE_WIDTH / 2, SCENE_HEIGHT);
graphicsContext = canvas.getGraphicsContext2D();

copyCanvas = new Canvas( SCENE_WIDTH / 2, SCENE_HEIGHT);
copyGraphicsContext = canvas.getGraphicsContext2D();

HBox hBox = new HBox();
hBox.getChildren().addAll(canvas, copyCanvas);

root.setCenter(hBox);

scene = new Scene(root, SCENE_WIDTH, SCENE_HEIGHT);

primaryStage.setScene(scene);
primaryStage.show();

addListeners();

startAnimation();


}

private void startAnimation() {

loop = new AnimationTimer() {

@Override
public void handle(long now) {

if( mousePressed) {

// try this
// graphicsContext.drawImage( brush, mouseLocation.getX() - brushWidthHalf, mouseLocation.getY() - brushHeightHalf);

// then this
bresenhamLine( prevMouseLocation.getX(), prevMouseLocation.getY(), mouseLocation.getX(), mouseLocation.getY());

}

prevMouseLocation = new Point2D( mouseLocation.getX(), mouseLocation.getY());

copyCanvas();
}
};

loop.start();

}

private void copyCanvas() {

SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.TRANSPARENT);
WritableImage image = canvas.snapshot(params, null);
copyCanvas.getGraphicsContext2D().drawImage(image, 0, 0);

}

// https://de.wikipedia.org/wiki/Bresenham-Algorithmus
private void bresenhamLine(double x0, double y0, double x1, double y1)
{
double dx = Math.abs(x1-x0), sx = x0<x1 ? 1. : -1.;
double dy = -Math.abs(y1-y0), sy = y0<y1 ? 1. : -1.;
double err = dx+dy, e2; /* error value e_xy */

while( true){
graphicsContext.drawImage( brush, x0 - brushWidthHalf, y0 - brushHeightHalf);
if (x0==x1 && y0==y1) break;
e2 = 2.*err;
if (e2 > dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
}
}


private void addListeners() {

scene.addEventFilter(MouseEvent.ANY, e -> {

mouseLocation = new Point2D(e.getX(), e.getY());

mousePressed = e.isPrimaryButtonDown();

});


}


public static Image createImage(Node node) {

WritableImage wi;

SnapshotParameters parameters = new SnapshotParameters();
parameters.setFill(Color.TRANSPARENT);

int imageWidth = (int) node.getBoundsInLocal().getWidth();
int imageHeight = (int) node.getBoundsInLocal().getHeight();

wi = new WritableImage(imageWidth, imageHeight);
node.snapshot(parameters, wi);

return wi;

}


public static Image createBrush( double radius, Color color) {

// create gradient image with given color
Rectangle brush = new Rectangle(0,0,1,1);
brush.setStroke(Color.RED);
brush.setFill(Color.RED);

// create image
return createImage(brush);

}


public static void main(String[] args) {
launch(args);
}
}

Your code is in copyCanvas().

Sample Image

Tested with JavaFX 8u40, Win7. Although the antialiasing isn't as intense, the copy isn't a 1:1 copy. If you compare 2 lines on a pixel-level, you'll get this:

Sample Image

If you remove the

params.setFill(Color.TRANSPARENT);  

you'll get a 1:1 copy:

Sample Image

So it seems to have something to do with the transparent fill color in the SnapshotParameters.

How to copy from one canvas to another

A Canvas is always used to draw either on screen or onto a Bitmap. The solution of using Bitmaps works perfectly well: create a Bitmap, create a Canvas to draw onto that Bitmap, then draw the Bitmap onto another Canvas. You also record all drawing commands in a Picture and replay them on a different Canvas.

Copy user selection from one canvas to another

The following guide might be helpful.

http://www.i-programmer.info/programming/graphics-and-imaging/2078-canvas-bitmap-operations-bitblt-in-javascript.html

It mentions you can draw a section of the image using

drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)

Where s is source, and d is destination.

From there you just have to determine the position of the click and drag to work out the co-ordinates and width/heights.

I've updated your fiddle just to demonstrate. It's very crude, so just click once somewhere in the top left of the image, then click again somewhere in the bottom right.

http://jsfiddle.net/treerock/1zpc8fz0/



Related Topics



Leave a reply



Submit