Canvas tainted by cross-origin data
Solution 1
You cannot reset the crossOrigin flag once it is tainted, but if you know before hand what the image is you can convert it to a data url, see Drawing an image from a data URL to a canvas
But no, you cannot and should not be using getImageData() from external sources that don't support CORS
Solution 2
While the question is very old the problem remains and there is little on the web to solve it. I came up with a solution I want to share:
You can use the image (or video) without the crossorigin
attribute set first and test if you can get a HEAD request thru to the same resource via AJAX. If that fails, you cannot use the resource. if it succeeds you can add the attribute and re-set the source of the image/video with a timestamp attached which reloads it.
This workaround allows you to show your resource to the user and simply hide some functions if CORS is not supported.
HTML:
<img id="testImage" src="path/to/image.png?_t=1234">
JavaScript:
var target = $("#testImage")[0];
currentSrcUrl = target.src.split("_t=").join("_t=1"); // add a leading 1 to the ts
$.ajax({
url: currentSrcUrl,
type:'HEAD',
withCredentials: true
})
.done(function() {
// things worked out, we can add the CORS attribute and reset the source
target.crossOrigin = "anonymous";
target.src = currentSrcUrl;
console.warn("Download enabled - CORS Headers present or not required");
/* show make-image-out-of-canvas-functions here */
})
.fail(function() {
console.warn("Download disabled - CORS Headers missing");
/* ... or hide make-image-out-of-canvas-functions here */
});
Tested and working in IE10+11 and current Chrome 31, FF25, Safari 6 (Desktop). In IE10 and FF you might encounter a problem if and only if you try to access http-files from a https-script. I don't know about a workaround for that yet.
UPDATE Jan 2014:
The required CORS headers for this should be as follows (Apache config syntax):
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "referer, range, accept-encoding, x-requested-with"
the x-header is required for the ajax request only. It's not used by all but by most browsers as far as I can tell
Solution 3
Also worth noting that the CORS will apply if you are working locally regardless of if the resource is in the same directory as the index.html
file you are working with. For me this mean the CORS problems disappeared when I uploaded it to my server, since that has a domain.
Solution 4
You can use base64 of the image on canvas, While converting into base64 you can use a proxy URL (https://cors-anywhere.herokuapp.com/) before your image path to avoid cross-origin issue
check full details here
https://stackoverflow.com/a/44199382/5172571
var getDataUri = function (targetUrl, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
xhr.open('GET', proxyUrl + targetUrl);
xhr.responseType = 'blob';
xhr.send();
};
getDataUri(path, function (base64) {
// base64 availlable here
})
Comments
-
clwen almost 2 years
I'm loading a motion jpeg from third-party site, which I can trust. I'm trying to
getImageData()
but the browser (Chrome 23.0) complains that:Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
There are some similar questions on SO, but they are using local file and I'm using third party media. My script runs on a shared server and I don't own the remote server.
I tried
img.crossOrigin = 'Anonymous'
orimg.crossOrigin = ''
(see this post on the Chromium blog about CORS), but it didn't help. Any idea on how can IgetImageData
on a canvas with cross-origin data? Thanks! -
clwen over 11 yearsThanks for replying. Not sure we can apply
toDataURL()
to mjpeg, but I'll give it a try. Why no? security reason? Is there specific configuration external server should do? Or even they don't have that configuration, I can use toDataURL to do so. -
Paul Kaplan over 11 yearsHere is a fairly comprehensive guide on CORS support html5rocks.com/en/tutorials/cors. And yeah it is a large security issue.
-
Meekohi over 11 yearsCan this work even with CORS? I have not had success with it.
-
clwen over 10 yearsThanks for replying. So for "working" you meant that one could do
getImageData
on this external resource? If we do the workaround as you mentioned. -
chadpeppers over 10 yearsThis is correct as I had the same issue. I am using phpstorm to view it, which uses a mock server itself and works.
-
Tomáš Zato over 9 yearsHow do I know before hand? Imagine you've got an
<img>
tag and you have no idea what it is... How do you know if you can draw it or if you need to load it usingcrossorigin="anonymous"
? -
Noumenon almost 8 yearsI work locally by using
python -m http.server port 8080
in my working folder, then visitinghttp://localhost:8080
. -
Kristopher Ives almost 8 yearsFor PHP you can use
php --server localhost:8080
-
avocado almost 8 years@Noumenon, +1 for the python server hint
-
Kaiido over 7 yearsOld answer, but just to note that the other way around seems easier : first set the crossOrigin of your img tag, listen to its
error
event handler, set the remote src, if it fires, you know you'll taint the canvas. -
gbtimmon over 5 years@TomášZato You dont, because that is exactly what CORS is trying to prevent. It should only be allow IF you know before hand what the image is and if it is safe.
-
tmpmachine over 3 yearsHere's another option: you can cache the image with Cache API