Any way to clone HTML5 canvas element with its content? - javascript

Is there any way to create a deep copy of a canvas element with all drawn content?

Actually the correct way to copy the canvas data is to pass the old canvas to the new blank canvas. Try this function.
function cloneCanvas(oldCanvas) {
//create a new canvas
var newCanvas = document.createElement('canvas');
var context = newCanvas.getContext('2d');
//set dimensions
newCanvas.width = oldCanvas.width;
newCanvas.height = oldCanvas.height;
//apply the old canvas to the new one
context.drawImage(oldCanvas, 0, 0);
//return the new canvas
return newCanvas;
}
Using getImageData is for pixel data access, not for copying canvases. Copying with it is very slow and hard on the browser. It should be avoided.

You can call
context.getImageData(0, 0, context.canvas.width, context.canvas.height);
which will return an ImageData object. This has a property named data of type CanvasPixelArray which contains the rgb and transparency values of all the pixels. These values are not references to the canvas so can be changed without affecting the canvas.
If you also want a copy of the element, you could create a new canvas element and then copy all attributes to the new canvas element. After that you can use the
context.putImageData(imageData, 0, 0);
method to draw the ImageData object onto the new canvas element.
See this answer for more detail getPixel from HTML Canvas? on manipulating the pixels.
You might find this mozilla article useful as well https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Drawing_shapes

Related

HTML Canvas imageData array all 0's

var img, imageData,width,height;
var c = canvasEle.getContext("2d");
width = canvasEle.width;
height = canvasEle.height;
img = document.getElementById("id");
c.drawImage(img,0,0);
imageData = c.createImageData(width, height);
After I draw the image onto the context, then create an imageData array, the values of the array are all 0.
I have been struggling with this for hours and couldn't find any solution. The image is shown on the canvas after I draw it, but the imageData of the context says all the pixels are white. This doesn't make any sense to me.
With createImageData you are creating new image data for an empty image. Please use getImageData to get the image data from an already existing canvas

Fabricjs copy part of canvas to another canvas

I am trying to copy part of a fabricjs canvas to another canvas.I am not sure if fabric has a method suitable for doing it (please let me know if that's the case) and after some searching I decided to do it without using fabric. But the canvas was already created using fabricjs. new fabric.Canvas(). Now when I try to copy a part of this canvas using context.drawImage(), I get a TypeError. I tried replacing the canvas with a img or a canvas created without using fabric and that works. So, I am guessing I may have to use the fabric canvas object a bit differently.
If you want to copy a rectangular zone from the canvas in order to export it as an image you could use the following:
canvas.deactivateAll();
canvas.renderAll();
var ctx = canvas.getContext("2d");
var myImageData = ctx.getImageData(box.x, box.y, box.w, box.h);
var buffer = document.createElement('canvas');
var bufferCtx = buffer.getContext("2d");
buffer.width = box.w;
buffer.height = box.h;
bufferCtx.putImageData(myImageData, 0, 0);
window.open(buffer.toDataURL('image/png'));

drawImage() implementation

I have two canvases that are different sizes. My goal is copy the user's drawing from the main canvas to a second canvas as a scaled down version. So far the drawImage() and scale appear to be working, but the second canvas keeps the old version of the main drawing along with the new copy. I tried clearing it each time before calling drawImage(), but that doesn't appear to do anything. How can I copy just the current image to my secondary canvas each time the function runs?
$('#hand').dblclick(function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var imageData = context.getImageData(0, 0, 100, 100);
var newCanvas = document.getElementById('scaledCanvas');
var destCtx = newCanvas.getContext('2d');
destCtx.clearRect(0, 0, newCanvas.width, newCanvas.height);
destCtx.scale(.5,.5);
destCtx.drawImage(canvas, 0, 0);
});
I can include more code if necessary. I also just realized that scale keeps getting called; this explains why the new copied image would get smaller each time as well, so that might be another problem.
It's quite simple actually, you're using what's called a transform (translate, rotate, or scale).
In order to use them "freshly" each time you must save and restore the canvas state each time.
$('#hand').dblclick(function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var imageData = context.getImageData(0, 0, 100, 100);
var newCanvas = document.getElementById('scaledCanvas');
var destCtx = newCanvas.getContext('2d');
destCtx.clearRect(0, 0, newCanvas.width, newCanvas.height);
//save the current state of this canvas' drawing mode
destCtx.save();
destCtx.scale(.5,.5);
destCtx.drawImage(canvas, 0, 0);
//restore destCtx to a 1,1 scale (and also 0,0 origin and 0 rotation)
destCtx.restore();
});
It's also important to note you can push several times before calling restore, in order to perform many cool geometric tricks using recursive functions etc...
Take a look at this explanation of states and transformations:
https://developer.mozilla.org/en-US/docs/HTML/Canvas/Tutorial/Transformations
Hope this helps you understand canvas transforms a bit better.

Transparent pixels using HTML5 canvas and getImageData?

In my application I need to get some images, process them, and save for later use. So I'm drawing them to a temporary canvas, then getting with getImageData function. But in output transparency is lost...
Here is my code:
var tempCanvas = document.createElement('canvas');
var tempContext = tempCanvas.getContext('2d');
tempContext.drawImage(image, 0, 0);
var imageData = tempContext.getImageData(0, 0, image.width, image.height);
My image has some transparent pixels but after this there are no transparent pixels in imageData how can I solve this issue?
Is there any way to convert Html Image to ImageData, so I can process it and then draw to canvas?
your imageData should contain alpha channel.
However, putImageData will replace the pixel value in the context.
It won't merge it with the previous value of the pixel in the context, it will replace it. So, what you should see is the pixel behind the canvas (in most of cases, the pixel color of the body tag of your html page).
What you have to do:
use a temporaty canvas to get image data is the good way
modifiy the imageData as you need
don't try to put this imageData back in the conetext with a putImageData, it won't behave as you wish
but create a new Image object and give it the imageData as source (yes, it works :))
use drawImage to draw back the image
example of code:
var tempCanvas = document.createElement('canvas');
var tempContext = tempCanvas.getContext('2d');
tempContext.drawImage(image, 0, 0);
var imageData = tempContext.getImageData(0, 0, image.width, image.height);
//modify here the imageData as you need
var img = new Image();
img.src = imageData;
context.drawImage(img, 0, 0); //the true context of the canvas
It should works.

HTML Canvas: draw image without anti-aliasing

I want to do pixel-true rendering of some images on my Canvas. Right now, I obtain the images through Javascript, so my images are HTMLImageElement instances. I can draw these on the Canvas' rendering context with drawImage. However, this performs anti-aliasing on the image, which I don't want.
There appears to be a lower-level image manipulation method named putImageData, operating on ImageData objects. Does this method perform any anti-aliasing? If not, it's a fine candidate for what I'm looking for, but I haven't found out how I can convert or blit an HTMLImageElement to an ImageData instance.
Any advice would be welcome!
Edit: my original problem was solved, I accidentally had a coordinate that was fractional, which forces anti-aliasing. The conversion-to-image-data question still stands though.
The only way to convert an image into an ImageData object is to draw it to a canvas first, so you'll need to create a temporary canvas, draw the image on it, and get the image data from there.
function imageToImageData(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0);
return ctx.getImageData(0, 0, canvas.width, canvas.height);
}
Note though, that the same-origin policy prevents you from calling getImageData if you draw an image from a different domain to the canvas, so this will only work on images from the same domain as the document. If you need to draw images from other domains, your only option is to call drawImage on the context for you main canvas directly, making sure there are no transformations that will affect the accuracy.

Categories

Resources