Ever needed to make an app were the user has to upload an image and edit it before saving? Like upload, crop and scale your profile picture.
A few years ago you would start by uploading the image to your server. Then wait. And wait a bit more, because they just got themselves a new 11 mega-pixel camera an now they are trying to upload it straight to your server as their new profile picture because they rule. When you were finally done with their damned huge picture, you would show a scaled low quality image in the next screen and used some js library to show what you would do with there picture. This was a pretty nifty way of dealing with all the limitations of the pre-html5 time.
Since html5 we are not obliged to follow that road anymore.
The fileAPI and the Canvas element gives us the opportunity to upload and manipulate an raster-based image. And above all, we can export our result to png, jpg, bmp and send it our server.
The following code will show a quick example of this techniec.
Upload to Canvas
Lets start with the html:
We listen for a change on input and fire handleImage()
when we select an image in de file input.
var imageLoader = document.getElementById('imageLoader'); imageLoader.addEventListener('change', handleImage, false); var canvas = document.getElementById('imageCanvas'); var ctx = canvas.getContext('2d');
We will use the fileReader api for downloading the image to our dom.
function handleImage(e){ var reader = new FileReader(); reader.onload = function(event){ var img = new Image(); img.onload = function(){ ctx.drawImage(img,0,0); } img.src = event.target.result; } reader.readAsDataURL(e.target.files[0]); }
Manipulate the image
There are a lot of nice js libraries out there for manipulating an images. The best raster-based image manipulator I know of is fabric.js
Changing a few lines to add fabric js gives us the amazing ability to manipulate our image.
var imageLoader = document.getElementById('imageLoader'); imageLoader.addEventListener('change', handleImage, false); var canvas = new fabric.Canvas('imageCanvas',{backgroundColor: 'rgb(240,240,240)'}); function handleImage(e){ var reader = new FileReader(); reader.onload = function(event){ var img = new Image(); img.onload = function(){ var imgInstance = new fabric.Image(img) canvas.add(imgInstance); } img.src = event.target.result; } reader.readAsDataURL(e.target.files[0]); }

thanks to fabric js we have nice intuitive handles for manipulating our image
Save our image
Add a link to save our image.
var imageSaver = document.getElementById('imageSaver'); imageSaver.addEventListener('click', saveImage, false); function saveImage(e){ this.href = canvas.toDataURL({ format: 'jpeg', quality: 0.8 }); this.download = 'test.png' }
Test the demo on JSfiddle