How can I draw an image from the HTML5 File API on Canvas?
You have a File
instance which is not an image.
To get an image, use new Image()
. The src
needs to be an URL referencing to the selected File
. You can use URL.createObjectURL
to get an URL referencing to a Blob
(a File
is also a Blob
): http://jsfiddle.net/t7mv6/86/.
var ctx = document.getElementById('canvas').getContext('2d');var img = new Image;img.onload = function() { ctx.drawImage(img, 20,20); alert('the image is drawn');}img.src = URL.createObjectURL(e.target.files[0]);
Note: be sure to revoke the object url when you are done with it otherwise you'll leak memory. If you're not doing anything too crazy, you can just stick a URL.revokeObjectURL(img.src)
in the img.onload
function.
References:
function handleFiles(e) { var ctx = document.getElementById('canvas').getContext('2d'); var url = URL.createObjectURL(e.target.files[0]); var img = new Image(); img.onload = function() { ctx.drawImage(img, 20, 20); } img.src = url; }
window.URL.createObjectUrl
docs
You could also use the FileReader
instead to create the object URL.
The FileReader
has slightly better browser support.
The FileReader
approach works in FF6 / Chrome. I'm not certain whether setting Img.src
to a Blob
is valid and cross-browser though.
Creating object urls is the correct way to do it.
Edit:
As mentioned in the commment window.URL
support whilst offline seems unavailable in FF6/Chrome.
Here is a complete example (Fiddle) using FileReader
(which has better browser support as mentioned by Raynos). In this example I also scale Canvas to fit the image.
In real life example you might scale the image to some maximum so that your form will not blow up ;-). Here is an example with scaling (Fiddle).
var URL = window.webkitURL || window.URL;window.onload = function() { var input = document.getElementById('input'); input.addEventListener('change', handleFiles, false); // set original canvas dimensions as max var canvas = document.getElementById('canvas'); canvas.dataMaxWidth = canvas.width; canvas.dataMaxHeight = canvas.height;}function handleFiles(e) { var ctx = document.getElementById('canvas').getContext('2d'); var reader = new FileReader(); var file = e.target.files[0]; // load to image to get it's width/height var img = new Image(); img.onload = function() { // setup scaled dimensions var scaled = getScaledDim(img, ctx.canvas.dataMaxWidth, ctx.canvas.dataMaxHeight); // scale canvas to image ctx.canvas.width = scaled.width; ctx.canvas.height = scaled.height; // draw image ctx.drawImage(img, 0, 0 , ctx.canvas.width, ctx.canvas.height ); } // this is to setup loading the image reader.onloadend = function () { img.src = reader.result; } // this is to read the file reader.readAsDataURL(file);}// returns scaled dimensions objectfunction getScaledDim(img, maxWidth, maxHeight) { var scaled = { ratio: img.width / img.height, width: img.width, height: img.height } if (scaled.width > maxWidth) { scaled.width = maxWidth; scaled.height = scaled.width / scaled.ratio; } if (scaled.height > maxHeight) { scaled.height = maxHeight; scaled.width = scaled.height / scaled.ratio; } return scaled;}
canvas { border:1px solid black}
<input type="file" id="input"/><div> <canvas width="400" height="300" id="canvas"/></div>