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.
- Select image using a file input
- Read the file as a dataURL
- Use canvas to manipulate the image as needed
- Export the new image as a dataUrl
- Use ajax to upload the image to the server as a dataURL
- 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
Detect All Changes to a ≪Input Type="Text"≫ (Immediately) Using Jquery
Using HTML Script Tags to Code While They Have a Source
How to Get a File or Blob from an Object Url
How to Read the Post Request Parameters Using JavaScript
How to Save Canvas as an Image With Canvas.Todataurl()
Cross-Browser Multi-Line Text Overflow With Ellipsis Appended Within a Fixed Width and Height
Appending HTML String to the Dom
Jquery Load() Only Working in Firefox
Changing CSS Values With JavaScript
How to Change Div Content With JavaScript
How to Autosize a Textarea Using Prototype
How to Get the Pure Text Without HTML Element Using JavaScript
Restricting Input to Textbox: Allowing Only Numbers and Decimal Point