It seems that even if you set the access-control-allow-origin header to allow access from mydomain.org to an image hosted on domain example.org, the canvas' origin-clean flag gets set to false, and trying to manipulate that image's pixel data will trigger a security exception.
Shouldn't canvas' obey the access-control-allow-origin header and allow access to image's data without throwing an exception?
If the server is under your control, add the origin of the requesting site to the set of domains permitted access by adding it to the Access-Control-Allow-Origin header's value. You can also configure a site to allow any site to access it by using the * wildcard. You should only use this for public APIs.
The key is to use the crossorigin attribute by setting crossOrigin on the HTMLImageElement into which the image will be loaded. This tells the browser to request cross-origin access when trying to download the image data.
The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch to mitigate the risks of cross-origin HTTP requests.
Actually, canvas DOES honour "access-control-allow-origin" if image has "crossOrigin" attribute with value "anonymous".
Works quite well in a fixed example: http://jsfiddle.net/WLTqG/29/
var ctx = document.getElementById('c').getContext('2d'),
img = new Image();
img.crossOrigin = 'anonymous';
img.src = 'https://lh3.googleusercontent.com/-LAFgeyNL894/AAAAAAAAAAI/AAAAAAAAAAA/-CWBGs9xLXI/s96-c/photo.jpg';
img.onload = function() {
ctx.drawImage(img, 0, 0);
try {
var imgData = ctx.getImageData(0, 0, 100, 100);
$('.button').on('click', function(e) {
e.preventDefault();
applyFilter(ctx, imgData);
});
} catch(err) {
$('.button').hide();
$('body').append("Access denied");
console.log(err);
}
};
function applyFilter(ctx, data) {
for (var x = 0; x < data.width; x++) {
for (var y = 0; y < data.height; y++) {
var index = 4 * (y * data.width + x);
data.data[index] = data.data[index] - 50; //r
data.data[index+1] = data.data[index+1] - 50; //g
data.data[index+2] = data.data[index+2] - 50; //b
data.data[index+3] = data.data[index+2] - 50; //a
}
}
ctx.putImageData(data, 0, 0);
}
(I used jQuery only for DOM-manipulation and events handling)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With