Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas.toDataURL() working in all browsers except IE10

I'm working on a project that uses a canvas to automatically crop an image, then return its data URL. It uses images from an external server, which has the appropriate CORS headers to allow the images to be converted to data URIs after they are cropped even though they are cross-origin.

The code works perfectly (and without security errors!) in all browsers except IE 10, in which it throws 'SCRIPT5022: SecurityError' when canvas.toDataURL() is called.

Is this a bug in IE or something I need to do differently in my code to make it work in Idiot Exploder? Thanks. -Scott

EDIT Here is (most of) the code I'm using to create and draw the canvas;

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = imageServerURL + '?id=' + imageIdToGet; // imageServerURL points to a different domain but the server has headers allowing requests from my domain
/*
    code here that defines the cropping area, in variables like ulX, lrY, etc.
*/
ctx.beginPath();
ctx.moveTo(ulX, ulY);
ctx.lineTo(urX, urY);
ctx.lineTo(lrX, lrY);
ctx.lineTo(llX, llY);
ctx.closePath();
ctx.clip();
ctx.drawImage(img, 0, 0);
var url = canvas.toDataURL(); // This succeeds in all other browsers but throws a SecurityError in IE
like image 517
Scott Odle Avatar asked Aug 07 '13 19:08

Scott Odle


2 Answers

I don't believe IE10 has CORS support for images. This MDN article seems to back that up.

As the article states:

Although you can use images without CORS approval in your canvas, doing so taints the canvas. Once a canvas has been tainted, you can no longer pull data back out of the canvas. For example, you can no longer use the canvas toBlob(), toDataURL(), or getImageData() methods; doing so will throw a security error.

So, it looks like you'll have to proxy the image from the same origin/domain as the one hosting the code in question before attempting to do this, at least for IE10 and Opera.

To deal with browsers that do not have CORS support for images, you'll need to proxy the image server-side. You can do this pretty easily by sending the source of the image to a known endpoint on your local server, and passing in the source url of the image as a query parameter.

For example:

var sourceImageUrl = "https://www.google.com/images/srpr/logo4w.png",  
    localProxyEndpoint = "/imageproxy",   
    image = new Image();   

image.src = localProxyEndpoint + "?source=" + encodeURIComponent(sourceImageUrl);

Now, server-side, you'll handle this GET request, rip off the value of the source parameter from the URI, grab the image from the source, and return it in your response.

like image 66
Ray Nicholus Avatar answered Oct 18 '22 01:10

Ray Nicholus


Unfortunately, IE10 still remains the only popular browser that doesn't support CORS for image drawn to Canvas even when CORS headers are properly set. But there is workaround for that via XMLHttpRequest even without proxying image on server-side:

var xhr = new XMLHttpRequest();
xhr.onload = function () {
    var url = URL.createObjectURL(this.response);
    img.src = url;

    // here you can use img for drawing to canvas and handling

    // don't forget to free memory up when you're done (you can do this as soon as image is drawn to canvas)
    URL.revokeObjectURL(url);
};
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.send();
like image 21
RReverser Avatar answered Oct 18 '22 02:10

RReverser