11

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?

ArtBIT
  • 3,931
  • 28
  • 39

3 Answers3

8

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)

tibalt
  • 15,201
  • 1
  • 29
  • 22
  • Wow, I had such a hard time for this. This was the key for me. – William T. Mar 29 '13 at 21:13
  • Had same problem, fixed all the headers—this was the last piece. – jerwood May 25 '13 at 00:25
  • Hmm, this doesn't seem to work in IE10 - can anyone else confirm? Anyone have a fix that works in IE10? (I have a question open with a bounty - http://stackoverflow.com/questions/16956295/ie10-and-cross-origin-resource-sharing-cors-issues – UpTheCreek Jun 10 '13 at 13:06
  • According to Mozilla's website, this is supported in Chrome 13, Firefox 8, and doesn't work at all in IE or Opera. Things may change over time: https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image – Brandon Yarbrough Aug 14 '13 at 18:08
  • Unfortunately setting `img.crossOrigin = 'anonymous';` doesn't work in Safari 9.x...which is where the security exception is preventing the image from being linked/downloaded. – cbmtrx Nov 28 '15 at 13:36
3

Unless I'm completely reading it wrong, the spec seems to suggest that it will work with canvas--see the "Not tainting the canvas element" section under Use Cases:

http://www.w3.org/TR/cors/#use-cases

It specifically talks about drawing remote images served with the access-control-allow-origin header into a canvas and then calling toDataURL() on the canvas.

Maybe browsers haven't caught up with this yet, but that's how I read the spec, at least.

Chris Bartley
  • 417
  • 1
  • 6
  • 13
2

The access-control-allow-origin header only works for cross-domain XmlHttpRequest. The <canvas> tag DOES NOT honour that attribute, and hence what you are trying will not work.

See http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#security-with-canvas-elements

The only option is to proxy the image via your own server.

Sripathi Krishnan
  • 30,948
  • 4
  • 76
  • 83
  • Right, so using an XmlHttpRequest to achieve this would not raise an exception? – ArtBIT Jul 29 '10 at 04:14
  • For a small image, you could use XMLHttpRequest to grab it and then make a data URI in JavaScript: http://jsfiddle.net/WLTqG/1/. This works in Firefox and Chrome. See http://stackoverflow.com/questions/1919972/how-do-i-access-xhr-responsebody-from-javascript for a hint for Internet Explorer. (I did not test his solution.) – PleaseStand Apr 12 '11 at 03:17
  • Downvoter - please leave a comment why you think this answer is wrong. – Sripathi Krishnan Jul 07 '11 at 07:32