Polygonal Crop in Javascript

JavaScript

function polygonalCrop(options) {
	function extend(a, b){
		b=b||{};
	    for(var key in b)
    	    if(b.hasOwnProperty(key))
        	    a[key] = b[key];
	    return a;
	}

	options=extend({
		url:null,
		sides:8,
		angle:0,
		centerX:null,
		centerY:null,
		radius:null,
		outlineColor:null,
		outlineThickness:null,
		success:function(url){},
		fail:function(ev){}
	},options);
	if (!options.url) throw 'options needs an image URL as url property';
	var img=new Image();
	img.setAttribute('crossOrigin', 'anonymous');
	img.onload=function() {
		var w=this.width;
		var h=this.height;
		var canvas=document.createElement('canvas');
		canvas.width=w;
		canvas.height=h;
		var ctx=canvas.getContext('2d');
		if (options.centerX===null) {
			options.centerX=w/2;
		}
		if (options.centerY===null) {
			options.centerY=h/2;
		}
		var ang=2*Math.PI/options.sides;
		var len=Math.sin(ang/2)*2;
		if (options.radius===null) {
			options.radius=Math.min(w/2,h/2)*Math.cos(ang/2);
		}
		ctx.translate(options.centerX,options.centerY);
		ctx.rotate(options.angle);
		if (options.outlineThickness) ctx.lineWidth=options.outlineThickness;
		if (options.outlineColor) ctx.strokeStyle=options.outlineColor;
		ctx.moveTo(-len/2,-options.radius);
		for (var i=0; i<2*Math.PI; i+=ang) {
			ctx.rotate(ang);
			ctx.lineTo(len/2,-options.radius);
		}
		ctx.closePath();
		if (options.outlineThickness && options.outlineColor) ctx.stroke();
		ctx.clip(); 
		ctx.rotate(2*Math.PI-i-options.angle);
		ctx.translate(-options.centerX,-options.centerY);
		ctx.drawImage(this,0,0);
		options.success(ctx.canvas.toDataURL());
	};
	img.onerror=function() { alert('there was an error loading the image'); };
	img.src=options.url;
}

polygonalCrop({
	url:'http://placekitten.com/g/500/300',
	sides:6,
	angle:0,
	outlineThickness:2,
	outlineColor:'black',
	success:function(url) {
		var img = document.createElement('img');
		img.src=url;
		document.body.appendChild(img);
	},
	error:function(err) { alert(err); }
});