We were uploading images, processing the images as data URIs on the front-end, and saving the data URIs directly into the database. This worked well enough, but our database has a 500kb limit on cell size, and storing 500kb images that are just being used as 150x150 pixel avatars seems like a bad idea, anyway. Additionally, I needed to crop image to be a square to fit in our oh-so-trendy circular avatar component.
I came up with the idea of drawing the uploaded image onto a canvas, scaled and cropped, and then pulling data URI.
My proof of concept looked like this:
The key part of this is the
cropImage() function. It takes a data URI and a width and returns a promise that resolves to the cropped and resized data URI. If you’re using it with a file input element like in the example above, I’d highly recommend tossing an
accepts="image/*" attribute on the input because loading a non-image into an
<img> tag will fail silently. I try to catch this by doing a string check on the input data URI for an image type, but I’m not 100% certain that this will catch all possible errors.
Canvas has great support and this process is pretty quick. Under a second for even several MB image files. And while this example just centers the image and crops to a square, with a little more and different math, you can use the same concept to do all sorts of basic image manipulation.