9

I'd like to use javascript or jQuery to crop and compress an image on the client side before uploading to the server.

WorkFlow:

  1. Select Image
  2. Crop Image to specific size
  3. Compress the crop
  4. Upload

Has anyone done this before? What plugin or what do I have to do?

I see facebook can do compressing images and automatically resizing them before uploading.

Shawn Mclean
  • 56,733
  • 95
  • 279
  • 406
  • I don't know if this is possible. Facebook likely takes any images you upload, re-sizes them on the server, and then saves them. You would then see the image re-sized on the page. If you want resizing code for PHP I have some I've developed. It's only issue is that I haven't got opacity working for PNG's that are resized. – James Jul 27 '11 at 16:48
  • The easiest way is using canvas. For example: here is npm package for it https://www.npmjs.com/package/canvas_image_processing – user3517175 Oct 09 '18 at 14:22

4 Answers4

20

You can do it using base64, look to the website I'm working with: http://www.wordirish.com all images are manipulated on client side using HTML5 or flash for old browsers.

you just need do it:

function thisFunctionShoulBeCallByTheFileuploaderButton(e){
    e.preventDefault && e.preventDefault();
    var image, canvas, i;
    var images = 'files' in e.target ? e.target.files : 'dataTransfer' in e ? e.dataTransfer.files : [];
    if(images && images.length) {
        for(i in images) {  
            if(typeof images[i] != 'object') continue;
            image = new Image();
            image.src = createObjectURL(images[i]);
            image.onload =  function(e){
                var mybase64resized = resizeCrop( e.target, 200, 150 ).toDataURL('image/jpg', 90);
                alert(mybase64resized);
            }
        }           
    }
}

function resizeCrop( src, width, height ){
    var crop = width == 0 || height == 0;
    // not resize
    if(src.width <= width && height == 0) {
        width  = src.width;
        height = src.height;
    }
    // resize
    if( src.width > width && height == 0){
        height = src.height * (width / src.width);
    }

    // check scale
    var xscale = width  / src.width;
    var yscale = height / src.height;
    var scale  = crop ? Math.min(xscale, yscale) : Math.max(xscale, yscale);
    // create empty canvas
    var canvas = document.createElement("canvas");                  
    canvas.width  = width ? width   : Math.round(src.width  * scale);
    canvas.height = height ? height : Math.round(src.height * scale);
    canvas.getContext("2d").scale(scale,scale);
    // crop it top center
    canvas.getContext("2d").drawImage(src, ((src.width * scale) - canvas.width) * -.5 , ((src.height * scale) - canvas.height) * -.5 );
    return canvas;
}

function createObjectURL(i){ 
    var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
    return URL.createObjectURL(i);
}

piece of cake ;)

doplumi
  • 2,938
  • 4
  • 29
  • 45
Adriano Spadoni
  • 4,540
  • 1
  • 25
  • 25
  • 4
    review comment: thanks for your answer and welcome to SO. Just a tip: answering is nice, but it is even more appreciated to explain every step of your solution. – m_x Jan 30 '13 at 17:58
  • The mime needs to be *jpeg* not *jpg* in *toDataURL('image/jpg', 90);*. Thanks for the great answer. – Kareem Nov 28 '17 at 18:53
6

EDIT (2014): This answer is now obsolete! JavaScript is a programming language with implementations that are deeply influenced by what browser resources are being made available to them. Three years ago when this post was made (July 2011) browsers didn't have any kind of reliable functionality which would allow OP to do what he asked for, hence my answer.
If you are still interested in how this can be done now please consult some of the many answers to this question which have appeared in the meantime on SO. But please restrain yourself from making any further comments to this answer because its obviously pointless. Thank you.

Simply put JavaScript is not meant to do what you are asking for. Whatever service you encounter that offers the ability to manipulate selected images you can bet your money that the image has been uploaded completely to the server before any other functionality was offered.

  • 1
    it definitely can be done. take a look here: http://stackoverflow.com/questions/12728188/cropping-images-in-the-browser-before-the-upload/12730031#12730031 – gion_13 Aug 31 '13 at 21:17
  • 2
    This answer was made two years ago when a lot of HTML5 stuff didn't even exist and every service in existance that was performing image manipulation did it on the server side. –  Sep 01 '13 at 12:50
  • 1
    I code js for over 6 years and i don't want to argue what could or couldn't be done about 2 years ago. The bottom line is that this thread is still a *hot* one in *our age* and it deserves an updated answer. – gion_13 Sep 01 '13 at 15:32
  • Once again, you can't use JavaScript on stuff that wasn't even implemented in browsers at the time of writing. Web technologies and standards change over night which means that its fair to expect that a fair share of questions on SO is currently obsolete. The problem is you can't tell the OP to wait two years for standards to catch up just to solve his/her problem. SO is a community driven web site. If you think you should add something to the topic then please do so but do take into account that your answer will probably be obsolete too in a year or two. –  Sep 01 '13 at 16:33
  • 3
    I agree, but put yourself in this situation: you are a newcomer to this site and you want to what the OP wants in this question... and the **correct** and **accepted** answer is: "NO! It can't be done!". I'm not saying **it was possible** back then when the question was asked, but **it is now**, and the answer should be updated. Imagine the web (and SO too) full of outdated and wrong resources on most of the topics... what a cool world would that be? – gion_13 Sep 01 '13 at 21:53
  • 2
    @gion_13, but also the answer you're referring to and the process happening there is purely what the browser does and and as holodoc says, it's still not possible with JS. It's just possible with the help of the browser – azerafati Jun 23 '14 at 13:06
  • 1
    @Bludream Oh, sorry, I must've missed the `node` or `rhino` tags in this question. Where exactly do you run your javascritp applications "without the help of the browser"? – gion_13 Jun 23 '14 at 13:32
3

You can crop them using HTML5 Canvas:

http://www.html5canvastutorials.com/tutorials/html5-canvas-image-crop/

sandstrom
  • 14,554
  • 7
  • 65
  • 62
2

Modern browsers now support a lot of image manipulation via jquery and html5 canvas. Tools that can be used to achieve this include:

Resize & Crop for Jquery (ClientSide)

Pixastic Image Processing Library

HTML5 Canvas Image Optimization

I hope that proves useful for anyone looking for similar solutions...

Chibueze Opata
  • 9,856
  • 7
  • 42
  • 65