I want to join multiple canvases to make a single image.
So is there any method to covert more than one canvases to toDataURL to make a single image?
create a function that takes multiple arguments (canvas elements), puts them on one blank canvas, then returns the dataurl for the newly made canvas.
var getImadeData = function () {
var i = arguments.length,
tempCanvas = document.createElement("canvas"),
ctx = tempCanvas.getContext("2d");
while (i--) {
ctx.drawImage(arguments[i], 0, 0);
};
return tempCanvas.toDataURL();
};
Now just feed the function multiple canvas elements you want to put into one dataurl like so.
var newData = getImageData(canvas1, canvas2, canvas3);
In this example, the last canvas is placed on the blank canvas first so make sure to order your canvas elements appropriately.
Yes, the drawImage method on the canvas 2d rendering context accepts canvas elements as image elements. So all you have to do is:
Create a new canvas
Get its context
Draw all other canvases to it with drawImage
Extract the final image from this new canvas
try this example hope it will help see here
//html block
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #c3c3c3;">
</canvas>
<canvas id="myCanvas1" width="200" height="100" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<canvas id="Canvasimage" width="500" height="100" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<img id="finalimage" width="500" height="100" style="border:1px solid #c3c3c3;"/>
//script block
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for (var src in sources) {
numImages++;
}
for (var src in sources) {
images[src] = new Image();
images[src].onload = function () {
if (++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
window.onload = function (images) {
//Canvas first here
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 200, 100);
//Canvas second here
var c1 = document.getElementById("myCanvas1");
var ctx1 = c1.getContext("2d");
ctx1.fillStyle = "#00FF00";
ctx1.fillRect(0, 0, 200, 100);
//Canvas final here.
var canvas = document.getElementById("Canvasimage");
var context = canvas.getContext("2d");
var sources = {
darthVader: c.toDataURL("image/png"),
yoda: c1.toDataURL("image/png")
};
loadImages(sources, function (images) {
context.drawImage(images.darthVader, 100, 30, 200, 137);
context.drawImage(images.yoda, 350, 55, 93, 104);
//finalimage here which has two canvas data
var finalimage = document.getElementById("finalimage");
finalimage.src = canvas.toDataURL("image/png");
});
};
Related
I have a piece of HTML code with a canvas I'd like to duplicate by the click of a button. I've tried this code so far but I'm a bit clueless about what's missing. If you could include any piece of code it would be really useful to me as I'm a beginner
Thank you
<canvas id="myCanvas" width="800px" height="800px"></canvas>
<script>
var oldCnv = document.getElementById("myCanvas");
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;
//append the new canvas on the page
document.body.appendChild(newCanvas);
}
</script>
<button onclick="cloneCanvas(oldCnv)">add canvas</button>
You can't pass the parameter oldCnv in an onclick action to the function. Besides that, after you return newCanvas the document.body.appendChild(newCanvas) won't get called.
The following will work.
Use this code:
<canvas id="myCanvas" width="800px" height="800px"></canvas>
<script>
var oldCanvas = document.getElementById("myCanvas");
function cloneCanvas() {
//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
//append the new canvas on the page
document.body.appendChild(newCanvas);
}
</script>
<button onclick="cloneCanvas()">add canvas</button>
I have an image which is loaded from server and contains 4 bands in RGB format. Because of the alpha band which causes the image to look transparently, then I need to crop this alpha band and save it as JPEG format. One way I can think is using canvas, however, I'm not sure it possible or not as the test I did show that the image is the same.
<p>Image to use:</p>
<img id="scream" src="data/with_alpha.png" alt="The Scream">
<p>Canvas:</p>
<canvas id="myCanvas" width="2400" height="2097" style="border:1px solid #d3d3d3;">
</canvas>
window.onload = function() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.globalAlpha = 1;
var img = document.getElementById("scream");
ctx.drawImage(img, 0, 0);
// This ones does not do anything to remove the alpha band
c.toDataURL("image/jpeg", 0.0);
}
I found the answer from http://sunbox.github.io/image-to-canvas-to-image/ it can be like this to convert canvas to image:
// Get the image
var sampleImage = document.getElementById("ringoImage"),
canvas = convertImageToCanvas(sampleImage),
image = convertCanvasToImage(canvas);
// Actions
document.getElementById("pngHolder").appendChild(image);
// Converts image to canvas; returns new canvas element
function convertImageToCanvas(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
return canvas;
}
// Converts canvas to an image
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/jpeg");
return image;
}
I have a canvas image, and I want to store that as local storage, then I want to load a canvas on all canvas names in HTML.thanks
var img = new Image();
//Wait for image to load before doing something with content
img.onload = function() {
var canvas = document.querySelectorAll("canvas[name=myCanvas]");
for (var i = 0; i < canvas.length; i++) {
canvas[i].getContext("2d").drawImage(img,10,10);
}
};
img.src = 'http://i.imgur.com/VdXQ7z6.png';
localStorage.setItem("img", img);
<p>Image to use:</p>
<img id="scream" onload="draw(this)" src="http://i.imgur.com/VdXQ7z6.png" alt="The Scream" width="220" height="277">
<p>Canvas:</p>
<canvas name="myCanvas" width="250" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<canvas name="myCanvas" width="250" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<canvas name="myCanvas" width="250" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
You could store the image URL instead of the image object. localStorage can only store strings, not arbitrary data.
If you want to use base64 encoding, here's a demo on JSFiddle. I was going to do it on a stack snippet but there's too many restrictions when dealing with image data, so instead, here's all the JavaScript code:
var input = document.getElementById('upload');
var canvas1 = document.getElementById('disp');
var context1 = canvas1.getContext('2d');
var canvas2 = document.getElementById('test');
var context2 = canvas2.getContext('2d');
function processBlob(blob, callback) {
console.log('generating image from blob');
var blobURL = URL.createObjectURL(blob);
var img = new Image();
img.addEventListener('load', function () {
console.log('blob url loaded');
URL.revokeObjectURL(blobURL);
// 'this' is img
callback.apply(this, arguments);
});
img.src = blobURL;
}
function drawImage(canvas, context, image) {
console.log('drawing image to ' + canvas.id);
var width = image.naturalWidth;
var height = image.naturalHeight;
canvas.width = width;
canvas.height = height;
context.drawImage(image, 0, 0, width, height);
}
function storeImage(canvas, itemName) {
console.log('storing image from ' +
canvas.id + ' to ' + itemName);
// remove 22 byte header from base64
var dataURL = canvas.toDataURL('image/png').slice(22);
localStorage.setItem(itemName, dataURL);
}
function loadImage(itemName, callback) {
console.log('loading image from ' + itemName);
var dataURL = localStorage.getItem(itemName);
var binary = atob(dataURL);
var uint8 = new Uint8Array(binary.length);
for (var i = 0; i < binary.length; i++) {
uint8[i] = binary.charCodeAt(i);
}
var blob = new Blob([uint8], { type: 'image/png' });
processBlob(blob, callback);
}
console.log('start of program');
input.addEventListener('change', function () {
var file = this.files[0];
console.log('processing ' + file.name);
processBlob(file, function () {
console.log('callback for file image');
drawImage(canvas1, context1, this);
storeImage(canvas1, 'myImage');
loadImage('myImage', function () {
console.log('callback for localStorage image');
drawImage(canvas2, context2, this);
});
});
});
I would like to clone canvas with fabric js and continue editing existing fabric js object in the clone canvas but it is not working. It shows that setBackgroundImage is undefined.
$('#btnClick').on('click touchstart', function () {
var canvas = document.getElementsByTagName("canvas");
// canvas context
var context = canvas[0].getContext("2d");
// get the current ImageData for the canvas
var data = context.getImageData(0, 0, canvas[0].width, canvas[0].height);
// store the current globalCompositeOperation
var compositeOperation = context.globalCompositeOperation;
// set to draw behind current content
context.globalCompositeOperation = "destination-over";
//set background color
context.fillStyle = "#FFFFFF";
// draw background/rectangle on entire canvas
context.fillRect(0,0,canvas[0].width,canvas[0].height);
var tempCanvas = document.createElement("canvas"),
tCtx = tempCanvas.getContext("2d");
tempCanvas.width = 640;
tempCanvas.height = 480;
tempCanvas.setBackgroundImage('');
}
<canvas><canvas>
The idea of using the fabric library is to use its methods to simplify your work. You will not interact with canvas element directly.
The canvas loadFromJSON and toJSON method is what you can use to clone a copy of your canvas including the backgroundimage.
var canvas = new fabric.Canvas('canvas');
var canvas2 = new fabric.Canvas('canvas2');
$(document).ready(function() {
var rect = new fabric.Rect({width: 100, height:200, fill: 'red'});
canvas.add(rect);
var circle = new fabric.Circle({radius: 80, fill: 'blue'});
canvas.add(circle);
$('#clone').click(
function(){canvas2.loadFromJSON(JSON.stringify(canvas), function(){canvas2.renderAll()}); })
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id='canvas' width="500" height="400" style="border:#000 1px solid;">
</canvas>
<input id="clone" type="button" value="clone canvas">
<canvas id='canvas2' width="500" height="400" style="border:#000 1px solid;">
</canvas>
Looks like getImageData works when I use FillRect to create a rect on the canvas, but it doesn't work when I draw a gif on the canvas despite it drawing correctly and everything. Have no idea why that is - is it a security risk? Help?
<html>
<body>
<p>Image to use:</p>
<img id="scream" width="230" height="60" src="http://www.thekitmaker.com/image/3.gif" alt="The Scream">
<p>Canvas:</p>
<canvas id="myCanvas" width="230" height="60" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
function getPixel(imgData, index) {
var i = index*4, d = imgData.data;
return [d[i],d[i+1],d[i+2],d[i+3]] // [R,G,B,A]
}
// AND/OR
function getPixelXY(imgData, x, y) {
return getPixel(imgData, y*imgData.width+x);
}
window.onload = function() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//draw on canvas
var img = document.getElementById("scream");
ctx.drawImage(img,10,10,50,50);//,0,0);// c.width,c.height);
//ctx.fillStyle = "red";
//ctx.fillRect(10, 10, 50, 50);
//get image data
alert("h");
var imgData = ctx.getImageData(10, 10, 50, 50);
alert("h2");
// The magicĀ®
//getPixel(idt, 852); // returns array [red, green, blue, alpha]
alert("p:"+getPixelXY(idt,1,1)[0]); // same pixel using x,y
}
</script>
</body>
</html>
You are correct that it is because of security reasons. If you draw an image from a different origin onto a canvas, the canvas will be marked as "tainted" and you can no longer get image data from it, among other things.
Reference: http://www.w3.org/TR/html51/semantics.html#security-with-canvas-elements