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
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.
(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:
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_
* 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_
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.
Source: Stackoverflow.com