Working with canvas on images loaded from different domain

SecurityError: The operation is insecure. canvas issue

  • Share

Recently I'we been working with HTML canvas by using cropper jQuery plugin http://fengyuanchen.github.io/cropper. It was working fine until I had to load images from Facebook.

As soon as I loaded image from facebook, script was crashing with a security error:

Canvas Security

After sometime Google-ing for the issue description I run to a few document explaining that canvas cannot work with images loaded from a different domain and this plugin was heavily relying on canvas and transformations on it.

Apparently to enable that an additional attribute crossOrigin="Anonymous" needs to be added to image element.

<img src="https://scontent-a.xx.fbcdn.net/hphotos-xfp1/t31.0-8/p180x540/328381_10150310813908951_2028472084_o.jpg" crossOrigin="Anonymous" alt="" />
    

The issue is that if you are loading local image this attribute might cause some issues with your canvas object. Therefore before adding this attribute additional check needs to be made to determine whether image is loaded from local or not.

There are two approaches to do this. Basically you need to compare parts of the loaded page URL and the URL of the image loaded. This can be done by involving DOM and adding anchor tag and then comparing location of that temporary anchor tag with window location.

function isCrossDomain(url){
	if (url.indexOf("data:") != 0) {
		var a = document.createElement('a');
		a.href = url;
		if (location.protocol != a.protocol || location.hostname != a.hostname || location.port != a.port) {
			return true;
		}
	}
	return false;
}
    

Another way is to parse the URL of the image with regular expression

function isCrossDomain(url) {
    var parts = url.match(/^(https?:)\/\/([\w\.]+):?(\d*)/);
    if ((parts && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port))) {
        return true;
    }
    return false;
}
    

Both methods are working properly, but if used in a loop my opinion is to go with regular expression as it might be faster than DOM approach. As we are going to check all images in a document it will involve loop.

$(document).ready(function(){
	$("img").each(function(){
		var self = $(this);
		if(isCrossDomain($(self).attr("src")){
			$(self).attr("crossOrigin","Anonymous");
		}
	}
});
    

This script will check all images on the page, but to make the code faster you can filter the images by involving css class or ID filter and apply the check and necessary attribute adding only on the required images on which you might use canvas element.

References

  • Share

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.

Comments for this article

comments powered by Disqus