can not get canvas.getContext('2d').getImageData(x,x,x,x) - javascript

can not get the imageData
the browser console "Unable to get image data from canvas because the canvas has been tainted by cross-origin data."

In order to prevent shenanigans, the browser keeps track of image data. When you put an image from a different domain on your canvas, the canvas becomes "tainted" and the browser won't let you look at its pixels anymore.
This is necessary to prevent a variety of XSS/CSRF attacks.

See Pointy's answer for an explanation. This can be an annoying problem when testing files from the local filesystem. On Google Chrome / Chromium there's a workaround: Call it with the following command line option:
chromium-browser --allow-file-access-from-files

Related

Why is canvas not rendering properly?

I am rather familiar with making games using the HTML5 <canvas> tag. When I try to run my games from Komodo Edit 9 it works perfectly.
However, when I try to upload my game to ANY web hosting service, it never works properly. Like the following garridpunching.neocities.org.
The problem is that once the canvas renders, everything appears for a split second before disappearing instantly, leaving only a blank black canvas.
Google debugger returns the following error for all five hostings I tried: Uncaught InvalidStateError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.
The error is thrown on the line ctx.drawImage(sprite.cursor, cursor.x, cursor.y, 40, 40);, which works perfectly when I run the html file directly from localhost.
What does this mean and how do I fix it? Thanks in advance.
This could be related to an img not loading properly. Check the paths to your images, maybe you didn't copy some of them when deploying to the hosting service of you have a path somewhere that works on your local computer but not on the remote site.
Also: Do you load all your images from the same domain as the js? If this isn't the case it could also be triggered by a Cross-Origin Resource Sharing (CORS) issue.
This could be because you are calling step, i.e. beginning the 'game' before all the images have loaded. The solution would be to wait for sprite's images to be loaded before calling step.
load();
window.onload = step; // may need inline .onload() calls on sprite's imgs
The reason this wouldn't be happening locally is because it will load the requested images instantly, as it doesn't have to download them or anything like that.

Security error when attempting to manipulate image data of SVG in canvas

http://jsfiddle.net/5emz372r/
I am programmatically generating an SVG data URI, then rendering it in the canvas. Any attempts to use getImageData from that point on throw this error:
SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.
Does drawing an SVG to canvas automatically taint the canvas?
Side note: My ultimate goal here is to render a custom webfont (loaded by data URI) onto the canvas; is there an alternate way of doing this?
Your fiddle is broken, keeps crashing when I go to it.
The likely cause of this issue is you are trying to access a photo, or file, that is located on another domain. Browser security wont let you do this in most cases.
SECURITY_ERR: DOM Exception 18 when applying document.domain on both sites. How do I resolve this?

KineticJS: Kinetic warning: Unable to get data URL

I have two Kineticjs canvases and when trying to create an image in one canvas from the other canvas I get this error after calling toImage() on the canvas with the new image:
Kinetic warning: Unable to get data URL. Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported
I am pretty sure the reason why I am getting this error is because the "toImage()
method requires that the image is hosted on a web server with the same domain as the code executing it." How can I get around this warning so that I can create objects from one canvas and add them to another?
The app I am creating will run locally and will never run online so I don't have to worry about security issues. Also I read around that I can enable cross origin resource sharing but that seems a little complex and over the top since they require the setting up of a web server I think.
So is there any trick I can do to make one canvas able to create an image in another canvas for a Chrome kineticjs web app? And then being able to successfully call toImage()?
Here is how I am creating the image in the canvas:
var folderImage = new Image();
//folderImage.crossOrigin="anonymous"; // gives me file error if unchecked
folderImage.onload = function() {
var folderPic = new Kinetic.Image({
x: 0,
y: 0,
image: folderImage,
width: sideLen,
height: sideLen
});
subFolderGroup.add(folderPic);
subTextGroup.moveToTop();
mainBody4Dynamic.draw();
};
folderImage.src = 'assets/images/folder.png';
And when I call toImage() in the other layer all I am calling is the layer.toImage()
The browser treats the user's local drive as other-domain. That's good because you don't want your browser "getting friendly" with your banking records on your hard drive.
This means running locally with local images will taint the canvas (a CORS violation).
The simplest workaround is to install a web-server on your local machine and host the web-page plus images on a single domain. (=== automatic CORS compliance). PHP and IIS both work well on a dev machine.
Another workaround is complying with CORS restrictions by hosting your images on an internet imaging host that has configured its server to deliver images in a CORS compliant manor. Then all you have to do is add myImage.crossOrigin="anonymous". I believe dropbox.com does this--or they used to.
While in development, it sometimes works to put both your .html and your images on the desktop.

CORS error when reading video from canvas (tainted canvas)

I'm running an HLS stream that I want to write to a canvas; and then read pixels from the canvas.
The video gets rendered to the canvas A-ok, but it gets kicked off at:
myPixel = c.getImageData(200, 200, 1, 1).data;
where it fails with:
[Error] SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.
[Error] Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
I've set the cross-domain settings on the Wowza streaming server to:
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" to-ports="*" secure="false"/>
<allow-http-request-headers-from domain="*" headers="*" secure="false"/>
and crossOrigin="anonymous" on the client side video element.
It works and fails with different computers on the same network, all running Safari 7.0.2/Mac.
Any good ideas for debugging this?
If your modifications work on some computers and not on other identically configured computers, try clearing the cache on the misbehaving computers.
Force a reload on the misbehaving macs like this:
Hold Shift and Cmd and press R.

Can I get the data of a cross-site <img/> tag as a blob?

I am trying to save a couple of images that are linked to by a webpage to offline storage. I'm using IndexedDB on Firefox and FileSystem API on Chrome. My code is actually an extension, so on Firefox I'm running on Greasemonkey, and on Chrome as a content script. I want this to be automated.
I am running into problem when I retrieve the image file. I'm using example code from the article titled Storing images and files in IndexedDB, but I get an error: the images I'm trying to download are on a different subdomain and the XHR fails.
XMLHttpRequest cannot load http://...uxgk.JPG. Origin http://subdomain.domain.com is not allowed by Access-Control-Allow-Origin.
On Firefox I could probably use GM_xmlhttpRequest and it'd work (the code works on both browsers when I'm in same-origin URLs), but I still need to solve the problem for Chrome, in which other constraints (namely, needing to interact with frames on the host page) require me to incorporate my script in the page and forfeit my privileges.
So it comes back to that I'm trying to figure out a way to save images that are linked to (and may appear in) the page to IndexedDB and/or FileSystem API. I either need to realize how to solve the cross-origin problem in Chrome (and if it requires privileges, then I need to fix the way I'm interacting with jQuery) or some kind of reverse createObjectURL. At the end of the day I need a blob (File object, as far as I understand) to put into the IndexedDB (Firefox) or to write to FileSystem API (Chrome)
Help, anyone?
Edit: my question may actually really come down to how I can use jQuery the way I want without losing my content script privileges on Chrome. If I do, I could use cross-origin XHRs on Chrome as well. Though I'd much rather get a solution that doesn't rely on that. Specifically since I'd like this solution if I get the script incorporated into the webpage, and not require it to be a content script/userscript.
Edit: I realized that the question is only about cross-site requests. Right now I have one of three ways to get the image blob, with the help of #chris-sobolewski, these questions and some other pages (like this), which can be seen in this fiddle. However, all of these require special privileges in order to run. Alas, since I'm running on a page with frames, because of a known defect in Chrome, I can't access the frames. So I can load a script into each frame by using all_frames: true, but I really want to avoid loading the script with every frame load. Otherwise, according to this article, I need to escape the sandbox, but then it comes back to privileges.
Since you are running on Chrome and Firefox, your answer is fortunately, yes (kind of).
function base64img(i){
var canvas = document.createElement('canvas');
canvas.width = i.width;
canvas.height = i.height;
var context = canvas.getContext("2d");
context.drawImage(i, 0, 0);
var blob = canvas.toDataURL("image/png");
return blob.replace(/^data:image\/(png|jpg);base64,/, "");
}
this will return the base64 encoded image.
from there you just call the function something along these lines:
image = document.getElementById('foo')
imgBlob = base64img(image);
Then go ahead and store imgBlob.
Edit: As file size is a concern, you can also store the data as a canvasPixelArray, which is width*height*4 bytes in size.
imageArray = context.getImageData( 0, 0 ,context.canvas.width,canvasContext.canvas.height );
Then JSONify the array and save that?

Categories

Resources