Reputation: 317
I'm nearly finished with a Javascript/HTML5-based game, and i've been testing it by using Chrome to open the HTML page on my local file system (i haven't uploaded anything anywhere). I'm using Chrome's file://
protocol to do this. But i'm running into a problem... At the beginning of the game, i display an image for a couple seconds before moving onto the menu screen. I pause the game by grabbing the canvas' pixel data, displaying that, then drawing a semi-transparent rectangle across the whole thing, with a crosshair as a custom pointer. However, Chrome is giving me trouble about a DOM Security Exception 18: "Unable to get image data from canvas because the canvas has been tainted by cross-origin data."
So i did some research on the Internet, and it turns out this is because Chrome sees that the image is grabbed from the local file system, and sees this as a security error. Using this question as a reference, i tried doing some research on Cross-Origin Resource Sharing, but quickly got lost. I figured it would be much easier to simply open the test HTML file using http://
and localhost
like the question answerer suggested. But i have no idea how to do this, either.
I'd really like to use Chrome to continue testing my game (the developer tools accessed through Ctrl-Shift-I
have proved to be invaluable), so i figured there were three solutions: Either figure out what CORS is and how to use it, learn how to open a local file using http://
, or somehow hard-code my image data as a variable in my JavaScript script file (like a XPM file in C). I don't know how to do the first two, and i'm trying to avoid the third.
Upvotes: 0
Views: 2171
Reputation: 105015
Yes, it’s probably time to download a local web server or sign up for a hosted server.
But if you want to continue testing without a server, you can sign up for a free dropbox.com account and host your images there.
Dropbox allows access to images using CORS friendly crossOrigin=”anonymous”.
Then CORS is no problem on Chrome & Mozilla. But, IE still fails to be CORS friendly—come on IE :(
Here’s how to load an image without CORS problems from dropbox (Chrome & Mozilla, not IE).
The “secret” is setting image.crossOrigin=”anonymous” before setting the image.src:
var externalImage2=document.createElement("img");
externalImage2.onload=function(){
canvas.width=externalImage2.width;
canvas.height=externalImage2.height;
ctx.drawImage(externalImage2,0,0);
// use getImageData to replace blue with yellow
var imageData=recolorImage(externalImage2,0,0,255,255,255,0);
// put the altered data back on the canvas
// this will FAIL on a CORS violation
ctxAnonymous.putImageData(imageData,0,0);
}
externalImage2.crossOrigin = "Anonymous";
externalImage2.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/YdzHT/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvasCORS=document.getElementById("canvasCORS");
var ctxCORS=canvasCORS.getContext("2d");
var canvasAnonymous=document.getElementById("canvasAnonymous");
var ctxAnonymous=canvasAnonymous.getContext("2d");
// Using image WITHOUT crossOrigin=anonymous
// Fails in all browsers
var externalImage1=new Image();
externalImage1.onload=function(){
canvas.width=externalImage1.width;
canvas.height=externalImage1.height;
ctx.drawImage(externalImage1,0,0);
// use getImageData to replace blue with yellow
var imageData=recolorImage(externalImage1,0,0,255,255,255,0);
// put the altered data back on the canvas
// this will FAIL on a CORS violation
ctxCORS.putImageData(imageData,0,0);
}
externalImage1.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";
// Using image WITH crossOrigin=anonymous
// Succeeds in Chrome+Mozilla, Still fails in IE
var externalImage2=new Image();
externalImage2.onload=function(){
canvas.width=externalImage2.width;
canvas.height=externalImage2.height;
ctx.drawImage(externalImage2,0,0);
// use getImageData to replace blue with yellow
var imageData=recolorImage(externalImage2,0,0,255,255,255,0);
// put the altered data back on the canvas
// this will FAIL on a CORS violation
ctxAnonymous.putImageData(imageData,0,0);
}
externalImage2.crossOrigin = "Anonymous";
externalImage2.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";
function recolorImage(img,oldRed,oldGreen,oldBlue,newRed,newGreen,newBlue){
var c = document.createElement('canvas');
var ctx=c.getContext("2d");
var w = img.width;
var h = img.height;
c.width = w;
c.height = h;
// draw the image on the temporary canvas
ctx.drawImage(img, 0, 0, w, h);
// pull the entire image into an array of pixel data
var imageData = ctx.getImageData(0, 0, w, h);
// examine every pixel,
// change any old rgb to the new-rgb
for (var i=0;i<imageData.data.length;i+=4)
{
// is this pixel the old rgb?
if(imageData.data[i]==oldRed &&
imageData.data[i+1]==oldGreen &&
imageData.data[i+2]==oldBlue
){
// change to your new rgb
imageData.data[i]=newRed;
imageData.data[i+1]=newGreen;
imageData.data[i+2]=newBlue;
}
}
return(imageData);
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Original external image</p>
<canvas id="canvas" width=140 height=140></canvas>
<p>.getImageData with .crossOrigin='anonymous'
<p>[Succeeds in Chrome+Mozilla, still fails in IE]</p>
<canvas id="canvasAnonymous" width=140 height=140></canvas>
<p>.getImageData without .crossOrigin='anonymous'
<p>[Fails on all browsers]</p>
<canvas id="canvasCORS" width=140 height=140></canvas>
</body>
</html>
Upvotes: 2
Reputation:
Developing using the local file system is generally not a good idea for precisely the reason you have discovered. To use the localhost
option you'll need a web server installed on your PC. Google for a WAMP package (Windows, Apache. MysQL, PHP) which should give you everything you need.
Unfortunately, CORS will only work for you if you have a web server!
[edit] You can get a WAMP server from wampserver.com, obviously!
Upvotes: 1