I want to integrate Dropzone.js
with a Client Side Image Resizing. I know that there is a function to resize the thumbnail, but I would like to create a function to resize the main image before upload. Anyone could help me please?
Image resizing in JavaScript - Using canvas element. The HTML <canvas> element is used to draw graphics, on the fly, via JavaScript. Resizing images in browser using canvas is relatively simple. drawImage function allows us to render and scale images on canvas element.
Dropzone. js is 'a light weight JavaScript library that turns an HTML element into a "dropzone"'. Users can drag and drop a file onto an area of the page, uploading to a server. If you would like to read more how all of this works skim through the Dropzone.
Here's how to do it without uploading file from addedfile
.
Important thing is to set autoQueue
option to false
, that way dropzone
will not auto upload files selected by a user.
var dropzone = new Dropzone (".dropzone", {
...
autoQueue: false,
...
});
Next step is to do resizing and enqueue resized versions in addedfile
event.
dropzone.on("addedfile", function(origFile) {
var MAX_WIDTH = 800;
var MAX_HEIGHT = 600;
var reader = new FileReader();
// Convert file to img
reader.addEventListener("load", function(event) {
var origImg = new Image();
origImg.src = event.target.result;
origImg.addEventListener("load", function(event) {
var width = event.target.width;
var height = event.target.height;
// Don't resize if it's small enough
if (width <= MAX_WIDTH && height <= MAX_HEIGHT) {
dropzone.enqueueFile(origFile);
return;
}
// Calc new dims otherwise
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
// Resize
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(origImg, 0, 0, width, height);
var resizedFile = base64ToFile(canvas.toDataURL(), origFile);
// Replace original with resized
var origFileIndex = dropzone.files.indexOf(origFile);
dropzone.files[origFileIndex] = resizedFile;
// Enqueue added file manually making it available for
// further processing by dropzone
dropzone.enqueueFile(resizedFile);
});
});
reader.readAsDataURL(origFile);
});
Here's a function for converting dataURL
to a dropzone
file. Process could be simpler if you use canvas.toBlob() instead of canvas.toDataURL(), to get the content of resized file, but latter isn't supported well by all browsers.
It is just modified version of this function.
function base64ToFile(dataURI, origFile) {
var byteString, mimestring;
if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
byteString = atob(dataURI.split(',')[1]);
} else {
byteString = decodeURI(dataURI.split(',')[1]);
}
mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0];
var content = new Array();
for (var i = 0; i < byteString.length; i++) {
content[i] = byteString.charCodeAt(i);
}
var newFile = new File(
[new Uint8Array(content)], origFile.name, {type: mimestring}
);
// Copy props set by the dropzone in the original file
var origProps = [
"upload", "status", "previewElement", "previewTemplate", "accepted"
];
$.each(origProps, function(i, p) {
newFile[p] = origFile[p];
});
return newFile;
}
The Dropzone documentation on the pre-upload resize feature is confusing. The way it reads, you can either limit the width, limit the height, or limit both and sacrifice Aspect Ratio, distorting the image. This is not the case. This:
resizeWidth: 1000, resizeHeight: 1000,
resizeMethod: 'contain', resizeQuality: 1.0,
Limits either width or height to a max of 1000px - whichever is larger. The other will get reduced in accord with the Aspect Ratio, without distorting the image. So for example, in my test I uploaded a 2688x1512 image. Dropzone cropped and resized the Thumbnail to its default 120x120, but the file sent to the server was resized separately by Dropzone, to 1000x562, then sent to the server.
There is an interesting caveat here. JPEGs are going to be recompressed, lossy, so even a resizeQuality of 1.0 is going to result in loss. I see this feature as a method of preventing insanely large files, but you should be careful of resizing twice if you can avoid it (once on server once on client).
If this isn't enough for you - and you really wanted to overload the transform method - it's worth noting that following the code path inside Dropzone is a little confusing, because the createThumbnail
codepath is used twice every upload, once to create a thumbnail like you'd expect, and again to pre-resize the image here before passing it to the server. Likewise, the resize
method is confusingly named; while resizeWidth etc refer to prepping the image for upload, resize refers to resizing for the thumbnail, and does nothing to the image sent to the server.
Dropzone version 5 is recently released, so if you upgrade to dropzone 5, then you can simply use resizeWidth
and resizeHeigh
to compress your image on the client side.
If you provide only one of them, then dropzone will respect the original aspect ratio, for example if you just add the option: resizeWidth: 800
then your image will be compressed to width=800
pixels and your original image's aspect ration will be respected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With