Use Html5 to Resize an Image Before Upload

Use HTML5 to resize an image before upload

Here is what I ended up doing and it worked great.

First I moved the file input outside of the form so that it is not submitted:

<input name="imagefile[]" type="file" id="takePictureField" accept="image/*" onchange="uploadPhotos(\'#{imageUploadUrl}\')" />
<form id="uploadImageForm" enctype="multipart/form-data">
<input id="name" value="#{name}" />
... a few more inputs ...
</form>

Then I changed the uploadPhotos function to handle only the resizing:

window.uploadPhotos = function(url){
// Read in file
var file = event.target.files[0];

// Ensure it's an image
if(file.type.match(/image.*/)) {
console.log('An image has been loaded');

// Load the image
var reader = new FileReader();
reader.onload = function (readerEvent) {
var image = new Image();
image.onload = function (imageEvent) {

// Resize the image
var canvas = document.createElement('canvas'),
max_size = 544,// TODO : pull max size from a site config
width = image.width,
height = image.height;
if (width > height) {
if (width > max_size) {
height *= max_size / width;
width = max_size;
}
} else {
if (height > max_size) {
width *= max_size / height;
height = max_size;
}
}
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(image, 0, 0, width, height);
var dataUrl = canvas.toDataURL('image/jpeg');
var resizedImage = dataURLToBlob(dataUrl);
$.event.trigger({
type: "imageResized",
blob: resizedImage,
url: dataUrl
});
}
image.src = readerEvent.target.result;
}
reader.readAsDataURL(file);
}
};

As you can see I'm using canvas.toDataURL('image/jpeg'); to change the resized image into a dataUrl adn then I call the function dataURLToBlob(dataUrl); to turn the dataUrl into a blob that I can then append to the form. When the blob is created, I trigger a custom event. Here is the function to create the blob:

/* Utility function to convert a canvas to a BLOB */
var dataURLToBlob = function(dataURL) {
var BASE64_MARKER = ';base64,';
if (dataURL.indexOf(BASE64_MARKER) == -1) {
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[1];
var raw = parts[1];

return new Blob([raw], {type: contentType});
}

var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;

var uInt8Array = new Uint8Array(rawLength);

for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}

return new Blob([uInt8Array], {type: contentType});
}
/* End Utility function to convert a canvas to a BLOB */

Finally, here is my event handler that takes the blob from the custom event, appends the form and then submits it.

/* Handle image resized events */
$(document).on("imageResized", function (event) {
var data = new FormData($("form[id*='uploadImageForm']")[0]);
if (event.blob && event.url) {
data.append('image_data', event.blob);

$.ajax({
url: event.url,
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
//handle errors...
}
});
}
});

HTML5 Pre-resize images before uploading

Yes, use the File API, then you can process the images with the canvas element.

This Mozilla Hacks blog post walks you through most of the process. For reference here's the assembled source code from the blog post:

// from an input element
var filesToUpload = input.files;
var file = filesToUpload[0];

var img = document.createElement("img");
var reader = new FileReader();
reader.onload = function(e) {img.src = e.target.result}
reader.readAsDataURL(file);

var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);

var MAX_WIDTH = 800;
var MAX_HEIGHT = 600;
var width = img.width;
var height = img.height;

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;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);

var dataurl = canvas.toDataURL("image/png");

//Post dataurl to the server with AJAX

Image resize before upload without preview javascript

In my experience you cannot manipulate the image on the client side then upload the manipulated image in tact via a file input in a form.

The way I have done what you are trying to do in the past involves a few steps.

  1. Select image using a file input
  2. Read the file as a dataURL
  3. Use canvas to manipulate the image as needed
  4. Export the new image as a dataUrl
  5. Use ajax to upload the image to the server as a dataURL
  6. Use server side functions to convert the dataUrl to an image and store

https://jsfiddle.net/0hmhumL1/

function resizeInCanvas(img){
///////// 3-3 manipulate image
var perferedWidth = 2700;
var ratio = perferedWidth / img.width;
var canvas = $("<canvas>")[0];
canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0,0,canvas.width, canvas.height);
//////////4. export as dataUrl
return canvas.toDataURL();
}

When uploading as a dataUrl you increase the size (bandwidth required) of the manipulated image by about 20% so you may not see the savings you are looking for unless you are changing the image size considerably.

Resize images with canvas before uploading

(#2-3) Resizing the source image onto a canvas

  • Calculate the scaling factor required to fit MAX dimensions without overflow
  • Create a new canvas with the scaled dimensions
  • Scale the original image and draw it onto the canvas

Important! Be sure the source image is coming from the same domain as your web page or else toDataURL will fail for security reasons.

(#4) You can convert the canvas from #3 to an image with resizedImg.src=context.toDataURL

Example annotated code and a Demo:

var MAX_WIDTH = 400;        var MAX_HEIGHT = 300;
var img=new Image();img.crossOrigin='anonymous';img.onload=start;img.src="https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg";function start(){
var canvas=fitImageOntoCanvas(img,MAX_WIDTH,MAX_HEIGHT);
// #4 // convert the canvas to an img var imgResized=new Image(); imgResized.onload=function(){ // Use the new imgResized as you desire // For this demo, just add resized img to page document.body.appendChild(imgResized); } imgResized.src=canvas.toDataURL(); }
// #3function fitImageOntoCanvas(img,MAX_WIDTH,MAX_HEIGHT){
// calculate the scaling factor to resize new image to // fit MAX dimensions without overflow var scalingFactor=Math.min((MAX_WIDTH/img.width),(MAX_HEIGHT/img.height))
// calc the resized img dimensions var iw=img.width*scalingFactor; var ih=img.height*scalingFactor;
// create a new canvas var c=document.createElement('canvas'); var ctx=c.getContext('2d');
// resize the canvas to the new dimensions c.width=iw; c.height=ih;
// scale & draw the image onto the canvas ctx.drawImage(img,0,0,iw,ih); // return the new canvas with the resized image return(c);}
body{ background-color:white; }img{border:1px solid red;}


Related Topics



Leave a reply



Submit