Resizing images with Javascript

Is image resizing still a server task?

Usually when you are implementing an image upload, you have to decide whether you use GD or ImageMagic. On a Javascript heavy project, I was facing the same decision and decided to go a different path. I decided to resize the images in the client with Javascript.

If you choose this approach you must be aware that it will only work on Browsers that support Canvas. It basically boils down to the question if you need to support anything lower than IE 9. If not you are good to go. After the image is resized, you can upload it with ajax and store it on the filesystem of your server. One advantage of this approach, is of course, the smaller upload size.

Resizing an Image with Javascript is fairly simple, the key points are:

How to create an Image Object

Draw an image with a certain size on a Canvas

Fill content of a canvas into an image

The image will be filled with base64 encoded data

Demo

Thanks for this post, a simple yet effective way to do this.

There is one issue though I find worth pointing out: If there is any chance that the images will end up in mobile devices (and those chances are rising by the minute) it is definitely better advice to do the resizing on the server side. This should be an integral part of your content strategy for mobile!

Hi Memi

Why do you think? It’s especially good for mobile devices to resize it locally. The data and time spent uploading the image is smaller. I’m already using it on mobile devices, the performance is very good.

Cheers

Pascal

Ah I totally misunderstood it, of course if you’re *uploading* images it absolutely makes sense!
The only usecase where it is less apt would be when generating different versions, but that’s not the issue here…

I think you could even do it if different versions are needed:
1. Resize on client to maximal needed size
2. Upload and store on server
3. Serverside resizing for the different versions when delivering

@Alain:

Yeah I’d also go for that solution if you want to have it super nice. The only disadvantage is that resizing JPEG’s multiple time will degrade image quality but for the smaller sizes it shouldn’t be much of a big deal.

I would probably combine this approach with something where the user chan choose how the image will be cropped and then upload his selection in the maximal used size.

Very neat, and pretty simple! Another reason to additionally scale on the server is the principle to never trust uploaded data…

Wow awesome and Thank you for sharing the snippets.

Thank you for the nice post. I wasn’t thinking that the filesize of an picture can make problems. This post is also helpful for the german crowd :-)

Dude! So amazing sample. Code, demo, everything..
You saved 50 hours of my life. Thank you!!

Cool!
I find this very useful.
But I have a little question.. is it possible to save that base64 encoded image to a server?

I’m trying to do it with PHP like this

$decoded=base64_decode($encodedString);
file_put_contents(‘images/newImage.png’,$decoded);

but it doesn’t work.. any ideas?

Yes it is possible to store it with PHP

I’m doing it like this:

$img = str_replace(‘data:image/jpeg;base64,’,”, $request->request->get(‘image’));
$img = str_replace(‘ ‘,’+’, $img);
$img = base64_decode($img);

file_put_contents(“image.jpg”, $img);

Thanks Pascal this is great! I’m a beginner web dev trying to build small mobile web app for a friend and help her upload pictures from her phone.

How do you grab the image source from an upload form such as:

instead of the you have in the demo

I’ve tried $(“#fileinput”).get(0).files[0] but this gives me a GET error in the console

I will remember to use client side image resizing next time I come across this. Thanks again

I wonder resize.js line1 on demo .
Why isn’t it “var Liip = {};”
Please tell reason.

So it’s only defined if it’s not already defined. It’s a simple way to do name spacing between different modules. For this case it’s not really relevant.

Thanks. I have one more question.
Demo’s code downloaded result “Uncaught SecurityError: Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported” on Chrome.
How do I deal with this problem?

thanx!

Awesome post, now I’m planning on taking this to angular and upload to S3, that will be really cool.
My sf2 will only deal with the object-id.

Beneficial distribute Definitely. Thanks related to discussing.

That is an extremely good idea, and something I had never considered! I will be interested to see how the image compression compares to ImageMagick.

Looking further into this, it’s clear that this will revolutionise the way we deal with images on the web. We can get a data URL out of a canvas, so anything a canvas can do we can now output as a data-url and save on the server.

This is an exciting development!

Thanks for this winning script, maybe we won’t need to use S3 buckets with our angular/firebase app, taking out everything but the db for the client side love.

This also ONLY scales the Image and the Resultant dataURL is as Large as the one you would get without using canvas.toDataURL() (even if you have redrawn the image with new width and height)

This works great! Thanks for your blog!

Excellent, the only question is why so many steps, halfSize on each step, why not just one step?