[javascript] Image resizing client-side with JavaScript before upload to the server

I am looking for a way to resize an image client-side with JavaScript (really resize, not just change width and height).
I know it's possible to do it in Flash but I would like to avoid it if possible.

Is there any open source algorithm somewhere on the web?

This question is related to javascript image resize client-side

The answer is


Here's a gist which does this: https://gist.github.com/dcollien/312bce1270a5f511bf4a

(an es6 version, and a .js version which can be included in a script tag)

You can use it as follows:

<input type="file" id="select">
<img id="preview">
<script>
document.getElementById('select').onchange = function(evt) {
    ImageTools.resize(this.files[0], {
        width: 320, // maximum width
        height: 240 // maximum height
    }, function(blob, didItResize) {
        // didItResize will be true if it managed to resize it, otherwise false (and will return the original file as 'blob')
        document.getElementById('preview').src = window.URL.createObjectURL(blob);
        // you can also now upload this blob using an XHR.
    });
};
</script>

It includes a bunch of support detection and polyfills to make sure it works on as many browsers as I could manage.

(it also ignores gif images - in case they're animated)


Yes, with modern browsers this is totally doable. Even doable to the point of uploading the file specifically as a binary file having done any number of canvas alterations.

http://jsfiddle.net/bo40drmv/

(this answer is a improvement of the accepted answer here)

Keeping in mind to catch process the result submission in the PHP with something akin to:

//File destination
$destination = "/folder/cropped_image.png";
//Get uploaded image file it's temporary name
$image_tmp_name = $_FILES["cropped_image"]["tmp_name"][0];
//Move temporary file to final destination
move_uploaded_file($image_tmp_name, $destination);

If one worries about Vitaly's point, you can try some of the cropping and resizing on the working jfiddle.


The answer to this is yes - in HTML 5 you can resize images client-side using the canvas element. You can also take the new data and send it to a server. See this tutorial:

http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/


Perhaps with the canvas tag (though it's not portable). There's a blog about how to rotate an image with canvas here, I suppose if you can rotate it, you can resize it. Maybe it can be a starting point.

See this library also.


http://nodeca.github.io/pica/demo/

In modern browser you can use canvas to load/save image data. But you should keep in mind several things if you resize image on the client:

  1. You will have only 8bits per channel (jpeg can have better dynamic range, about 12 bits). If you don't upload professional photos, that should not be a problem.
  2. Be careful about resize algorithm. The most of client side resizers use trivial math, and result is worse than it could be.
  3. You may need to sharpen downscaled image.
  4. If you wish do reuse metadata (exif and other) from original - don't forget to strip color profile info. Because it's applied when you load image to canvas.

If you were resizing before uploading I just found out this http://www.plupload.com/

It does all the magic for you in any imaginable method.

Unfortunately HTML5 resize only is supported with Mozilla browser, but you can redirect other browsers to Flash and Silverlight.

I just tried it and it worked with my android!

I was using http://swfupload.org/ in flash, it does the job very well, but the resize size is very small. (cannot remember the limit) and does not go back to html4 when flash is not available.


You can use a javascript image processing framework for client-side image processing before uploading the image to the server.

Below I used MarvinJ to create a runnable code based on the example in the following page: "Processing images in client-side before uploading it to a server"

Basically I use the method Marvin.scale(...) to resize the image. Then, I upload the image as a blob (using the method image.toBlob()). The server answers back providing a URL of the received image.

_x000D_
_x000D_
/***********************************************_x000D_
 * GLOBAL VARS_x000D_
 **********************************************/_x000D_
var image = new MarvinImage();_x000D_
_x000D_
/***********************************************_x000D_
 * FILE CHOOSER AND UPLOAD_x000D_
 **********************************************/_x000D_
 $('#fileUpload').change(function (event) {_x000D_
 form = new FormData();_x000D_
 form.append('name', event.target.files[0].name);_x000D_
 _x000D_
 reader = new FileReader();_x000D_
 reader.readAsDataURL(event.target.files[0]);_x000D_
 _x000D_
 reader.onload = function(){_x000D_
  image.load(reader.result, imageLoaded);_x000D_
 };_x000D_
 _x000D_
});_x000D_
_x000D_
function resizeAndSendToServer(){_x000D_
  $("#divServerResponse").html("uploading...");_x000D_
 $.ajax({_x000D_
  method: 'POST',_x000D_
  url: 'https://www.marvinj.org/backoffice/imageUpload.php',_x000D_
  data: form,_x000D_
  enctype: 'multipart/form-data',_x000D_
  contentType: false,_x000D_
  processData: false,_x000D_
  _x000D_
    _x000D_
  success: function (resp) {_x000D_
       $("#divServerResponse").html("SERVER RESPONSE (NEW IMAGE):<br/><img src='"+resp+"' style='max-width:400px'></img>");_x000D_
  },_x000D_
  error: function (data) {_x000D_
   console.log("error:"+error);_x000D_
   console.log(data);_x000D_
  },_x000D_
  _x000D_
 });_x000D_
};_x000D_
_x000D_
/***********************************************_x000D_
 * IMAGE MANIPULATION_x000D_
 **********************************************/_x000D_
function imageLoaded(){_x000D_
  Marvin.scale(image.clone(), image, 120);_x000D_
  form.append("blob", image.toBlob());_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<script src="https://www.marvinj.org/releases/marvinj-0.8.js"></script>_x000D_
<form id="form" action='/backoffice/imageUpload.php' style='margin:auto;' method='post' enctype='multipart/form-data'>_x000D_
    <input type='file' id='fileUpload' class='upload' name='userfile'/>_x000D_
</form><br/>_x000D_
<button type="button" onclick="resizeAndSendToServer()">Resize and Send to Server</button><br/><br/>_x000D_
<div id="divServerResponse">_x000D_
</div>
_x000D_
_x000D_
_x000D_


In my experience, this example has been the best solution for uploading a resized picture: https://zocada.com/compress-resize-images-javascript-browser/

It uses the HTML5 Canvas feature.

The code is as 'simple' as this:

compress(e) {
    const fileName = e.target.files[0].name;
    const reader = new FileReader();
    reader.readAsDataURL(e.target.files[0]);
    reader.onload = event => {
        const img = new Image();
        img.src = event.target.result;
        img.onload = () => {
                const elem = document.createElement('canvas');
                const width = Math.min(800, img.width);
                const scaleFactor = width / img.width;
                elem.width = width;
                elem.height = img.height * scaleFactor;

                const ctx = elem.getContext('2d');
                // img.width and img.height will contain the original dimensions
                ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);
                ctx.canvas.toBlob((blob) => {
                    const file = new File([blob], fileName, {
                        type: 'image/jpeg',
                        lastModified: Date.now()
                    });
                }, 'image/jpeg', 1);
            },
            reader.onerror = error => console.log(error);
    };
}

There are two downsides with this solution.

The first one is related with the image rotation, due to ignoring EXIF data. I couldn't tackle this issue, and wasn't so important in my use case, but will be glad to hear any feedback.

The second downside is the lack of support foe IE/Edge (not the Chrome based version though), and I won't put any time on that.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to image

Reading images in python Numpy Resize/Rescale Image Convert np.array of type float64 to type uint8 scaling values Extract a page from a pdf as a jpeg How do I stretch an image to fit the whole background (100% height x 100% width) in Flutter? Angular 4 img src is not found How to make a movie out of images in python Load local images in React.js How to install "ifconfig" command in my ubuntu docker image? How do I display local image in markdown?

Examples related to resize

Numpy Resize/Rescale Image AngularJS $watch window resize inside directive Input type "number" won't resize How can I make all images of different height and width the same via CSS? How to get full width in body element Rerender view on browser resize with React How to resize image automatically on browser width resize but keep same height? PHPExcel auto size column width Automatically resize images with browser size using CSS Change form size at runtime in C#

Examples related to client-side

Getting query parameters from react-router hash fragment Single Page Application: advantages and disadvantages How to export JavaScript array info to csv (on client side)? Best practice for localization and globalization of strings and labels How can you use php in a javascript function How to create a file in memory for user to download, but not through server? Pass request headers in a jQuery AJAX GET call Image resizing client-side with JavaScript before upload to the server Print directly from browser without print popup window Sending emails with Javascript