0

When trying to draw an image onto a canvas, and then saving the canvas to an image, I get the following error:

Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported

var picture = new Image();
picture.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/800px-Smiley.svg.png";
var canvas = document.getElementById("background");
var context = canvas.getContext("2d");
function generate(){
 var ctx = document.createElement("canvas").getContext("2d");
  ctx.canvas.width = canvas.width;
  ctx.canvas.height = canvas.height;
 ctx.fillStyle = "red"; 
 ctx.rect (0, 0, 40, 40);
 ctx.fill();

 ctx.drawImage(picture,0,0);
 
 image = new Image();
 image.setAttribute('crossOrigin', 'anonymous');
 image.src = ctx.canvas.toDataURL("image/png");  
}
function draw(){
 context.clearRect(0, 0, canvas.width, canvas.height);
 context.drawImage(image, 0,0,100,100,0,0,100,100); 
}
function play(){
  generate();
  setInterval(function(){draw();}, 0.0333);
}

window.onload = function(){
 if(picture.complete)play();
 else picture.onload = play; 
}
<canvas id="background" width=500 height=500></canvas>

I know it's to do with drawing the image on the canvas because when that line is removed everything's okay and you can see the red box:

var picture = new Image();
picture.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/800px-Smiley.svg.png";
var canvas = document.getElementById("background");
var context = canvas.getContext("2d");
function generate(){
 var ctx = document.createElement("canvas").getContext("2d");
  ctx.canvas.width = canvas.width;
  ctx.canvas.height = canvas.height;
 ctx.fillStyle = "red"; 
 ctx.rect (0, 0, 40, 40);
 ctx.fill();
 
 image = new Image();
 image.setAttribute('crossOrigin', 'anonymous');
 image.src = ctx.canvas.toDataURL("image/png");  
}
function draw(){
 context.clearRect(0, 0, canvas.width, canvas.height);
 context.drawImage(image, 0,0,100,100,0,0,100,100); 
}
function play(){
  generate();
  setInterval(function(){draw();}, 0.0333);
}

window.onload = function(){
 if(picture.complete)play();
 else picture.onload = play; 
}
<canvas id="background" width=500 height=500></canvas>
So it's drawImage that causes this to fail.

I've read other questions and the solutions were "just add image.setAttribute('crossOrigin', 'anonymous');" (which I've done) or to put them in the same directory (I tried this by placing both files on desktop) but neither seemed to solve it for me.

Is there a fix or an alternative method? All I want to do is draw multiple images onto one image. (The red box was just for show.)

jaunt
  • 4,978
  • 4
  • 33
  • 54

1 Answers1

6

I tried this by placing both files on desktop

No. You need a web server and to open your files in http:// (or https://) for them to be considered of the same origin. When you open your files in file://, they're not considered of the same origin, even if you serve them from the same directory.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 1
    @dystroy. Yep, it makes sense to load a light web server on your Dev computer. Actually, during development you can (most often) avoid CORS errors by placing both the web page code (.html, .css, .js, etc) on the desktop along with the images (.jpg, .png). In this desktop "hack" you would not set the image.crossOrigin property or the hack fails. ;-) – markE Jan 17 '16 at 19:26