Better Image Previews in HTML5

When working with an uploader it’s nice to show image previews of files before the actual upload takes place. It looks nice and verifies to the user that the correct files have been selected from their computer. Since they are local files people expect them to render immediately. This article details how I accomplished this in HTML5 without the use of flash, silverlight or any other dependent technology.

Over the last several weeks I’ve been researching Plupload for image uploads. They have a nice, ready-made widget but it didn’t quite capture the look and feel that was requested of me. I opted to rely on their API and do the interfacing myself, which included developing my own image previews.

My main requirement was for them to render quick, even with 20MB files. My project was tailored to professional photographers so big files were expected. Searching the web I tried a few techniques that seemed to perform well with small files but would max out resources for larger ones. Things became choppy. A page quickly looks cheap when buttons don’t respond to clicks, content freezes intermediately, etc. I had to come up with a different solution. Along with speed, I also wanted to keep consistent thumbnail sizes and perform ideal cropping. Image quality had to be fair and recognizable as well.

The first function handles proportional resizing. I needed to be able to retrieve lower dimensions that didn’t skew or distort an image:
In most cases you’ll end up with one property that meets the max, but the other dimension will be much smaller than its max. For thumbnails to look clean you need a consistent width and height for every image. So that means you will likely need to crop. But you don’t necessarily want to perform that action on the entire image. Everything becomes so small it becomes hard to read. Rather grab a portion of the image as your scaling down. The following function utilizes proportionalResize as it determines the best coordinates for presenting your image:
Finally, we get to the meat of the process. This function returns the preview as a <canvas> element for your page. A <canvas> tag resembles an <img> tag with one big difference. Instead of loading the image from the network it’s drawn via JavaScript. It also has a built-in cropping mechanism. If using Plupload pass the result of file.getNative(). If not refer to this resource for getting a FileList of File objects to be passed in individually. This function calls the aforementioned centerCropFit function:
Originally, I tried Filereader.readAsDataURL() which converts the entire file into base64-encoded string. Whenever I assigned it to the src of an image it would cause a big memory hit for large files. Attempts to use window.setTimeout() to get around the heavy processing did not help. I also explored Web Workers to no avail. The URL.createObjectURL() method is the nitrous behind this process and allowed the tool to perform well for the user.