Resize image from input to upload - javascript

I've been struggled with this problem for couple hours. I want to resize an image from an input tag and then upload it to the server. Here is my attempt.
My input element:
<Input type="file" name="file" onChange={this.handleLoadAvatar} />
My handleLoadAvatar function:
handleLoadAvatar(e) {
var file = e.target.files[0];
var img = document.createElement("img");
var reader = new FileReader();
reader.onload = (e) => {
img.src = e.target.result;
}
reader.readAsDataURL(file);
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 300;
var MAX_HEIGHT = 300;
var width = img.width; // GET STUCK HERE
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");
this.setState({previewSrc: dataurl});
}
I'm using ReactJS for my project. I got stuck at the line with the comment above where I can't get the image's width. I tried this solution at HTML5 Pre-resize images before uploading but this seems not to work for me. Can anybody point out what's wrong with my code and how to fix it? Thanks a bunch!

The problem is that you aren't waiting for the image to load before accessing its width and height.
As you are waiting for the reader, you should do the same for the img:
handleLoadAvatar(e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = (e) => {
var img = document.createElement("img");
img.onload = () => {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 300;
var MAX_HEIGHT = 300;
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");
this.setState({previewSrc: dataurl});
}
img.src = e.target.result;
}
reader.readAsDataURL(file);
}

Related

Javascript resize image before upload - read from canvas - image there, width and height 0

I am currently trying to resize images before the upload and to achieve this I am using JS/Jquery, has to be client side. On my server I simply deny all requests which are bigger then 30MB.
I am using this code:
$( "input[type='file']" ).change(function() {
console.log("function works");
// from an input element
var filesToUpload = this.files;
console.log(filesToUpload);
var img = document.createElement("img");
img.src = window.URL.createObjectURL(this.files[0]);
console.log("image: ", img);
console.log("the image is: ", img.width);
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 = $("#uploading_canvas").get(0);;
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
var dataurl = canvas[0].toDataURL("image/png");
//var file = canvas.mozGetAsFile("foo.png");
});
The first console.log output shows that the image is there, but somehow it has no width or height. Uploading an image with this code doesnt change anything atm.
Here are the console log outputs:
DataToUrl is undefined because the image is missing?
As #ymz explained in the comments the image needs time to load, so wrapping the image related code into an additional onload function solved the issue.
The solution looks like this:
$( img ).load(function() {
canvas = $("#uploading_canvas").get(0);
var MAX_WIDTH = 600;
var MAX_HEIGHT = 450;
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");
});

Preview resized Image in Iframe

I have created a image select and resize (Client side) and upload to server. What I am asking for help is with image preview in iframe(resized) but cannot figure out. I will be only using Chrome desktop for this application. Qusetion is please help me with displaying resized image within my iframe here are my scripts below
HTML
<input type="file" input id="input" onchange="ClientSideResize()" name="Image" value="%%%img%%%"/>
HTML iframe
<img src="" id="image">
<iframe name="my_iframe" src="" id="my_iframe" style="visibility: hidden;"></iframe>
SCRIPT
<script>
function ClientSideResize(){
var dataurl = null;
var uniq = 'id' + (new Date()).getTime();
var filesToUpload = document.getElementById('input').files;
var file = filesToUpload[0];
// Create an image
var img = document.createElement("img");
// Create a file reader
var reader = new FileReader();
// Set the image once loaded into file reader
reader.onload = function(e)
{
img.src = e.target.result;
img.onload = function () {
canvas = document.createElement("canvas");
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 200;
var MAX_HEIGHT = 400;
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);
dataurl = canvas.toDataURL("image/jpeg",100);
var blobBin = atob(dataurl.split(',')[1]);
var array = [];
for(var i = 0; i < blobBin.length; i++) {
array.push(blobBin.charCodeAt(i));
}
files = new Blob([new Uint8Array(array)], {type: 'image/jpg', name: "Sample"});
} // img.onload
}
// Load files into file reader
reader.readAsDataURL(file);
}
</script>
Giving you a few other tips along the way... filereader is not the preferred way. and the way you build your blob afterwards is no good, use canvas#toBlob directly instead.
function ClientSideResize () {
// var uniq = 'id' + Date.now() // never used
var filesToUpload = document.getElementById('input').files
var file = filesToUpload[0]
// Create an image
var img = new Image
img.onload = () => {
const MAX_WIDTH = 200
const MAX_HEIGHT = 400
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
var width = img.width
var height = img.height
// figure out new width and hight while keeping proportionally
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
}
}
// set diminsion
canvas.width = width
canvas.height = height
// draw resized image
ctx.drawImage(img, 0, 0, width, height)
// get it as a blob
canvas.toBlob(blob => {
// Do something with blob
// let file = new File([blob], 'filename.png', {type: blob.type})
let iframe = document.querySelector('iframe')
iframe.contentWindow.postMessage(blob, '*')
}, 'image/jpeg', 100)
} // img.onload
img.src = URL.createObjectURL(file)
}
// on iframe
window.onmessage = event => {
console.log(event) // will contain your blob object
}

Get image dataUrl before file upload in Angularjs | ng-file-upload

I'm resizing the image before upload it to the server using HTML5 Canvas.
Also I use Angular's module ng-file-upload.
Stack on getting dataUrl of resized image. Console returns data:,
What could be the problem here?
HTML
<input type="file" ngf-select ng-model="files">
<img ngf-src="files[0]">
JS
$scope.upload = function (files) {
if (files && files.length==1) {
var file = files[0];
var img = document.createElement("img");
var canvas = document.createElement("canvas");
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 = 200;
var MAX_HEIGHT = 150;
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");
console.log( dataurl );
...
He had the same problem and solve it with:
$scope.upload = function (files) {
if (files && files.length==1) {
var file = files[0];
var URL = window.URL || window.webkitURL;
var srcTmp = URL.createObjectURL(file);
var img = new Image();
img.onload = function() {
alert(this.width + 'x' + this.height);
}
img.src = srcTmp;

canvas to todataurl NOT getting complete Image

I'm trying to make an image upload from where, when user browse an image from disk, the scaled image shows as a preview on the canvas. to get the scaled image from the canvas the dataurl image only shows half image. when I try to right click and view image from the canvas, i get the complete image url.
here's my code.
<html>
<head>
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
$('#fileupload').change(function(){
var MAX_WIDTH = 180;
var MAX_HEIGHT = 120;
var file = this.files[0];
var canvas = document.getElementById('canvas');
var img = document.createElement("img");
var reader = new FileReader();
reader.onload = function(e) {
img.src = e.target.result;
}
img.onload = function(){
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.scale(1,1);
ctx.drawImage(img, 0, 0, width, height);
dataurl = canvas.toDataURL("image/png");
alert(dataurl); //this path shows imcomplete image.
}
reader.readAsDataURL(file);
</script>
</head>
<body>
<input id="fileupload" type="file">
<canvas width="180" height="120" id="canvas"></canvas>
</body>
</html>

html5 canvas for multiple image uploads not uploading all images

I'm trying to resize multiple images through html5 filereader api on client side . It works fine for a single image but for multiple images , it usually uploads only one image and leave the rest and i cannot get what is the problem . Here is my code
function handleFileSelect(evt) {
var filesToUpload = evt.target.files;
for (var i = 0, f; f = filesToUpload[i]; i++) {
var img = new Image();
var reader = new FileReader();
reader.readAsDataURL(f);
reader.onload = function(e) {img.src = e.target.result;
};
img.onload = function (){ // also tried reader.onloaded here
canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 300; // 2048
var MAX_HEIGHT = 150; // 1600
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/jpeg");
var newImgs = new Image();
newImgs.src = dataurl;
document.body.appendChild(newImgs);
}
}

Categories