Javascript Image-Resize before upload - javascript

I'm trying to resize big/large images on client and upload the smaller image. This works perfectly with one or ten images. But i want to upload mybe 50+ images. This will work but it slows down my cpu and memory. The code for the resized images is this:
var MAX_WIDTH = 1920;
var MAX_HEIGHT = 1920;
var loaded = 0;
var URL = window.URL || window.webkitURL;
function loadImage(file) {
var mime = file.type;
var src = URL.createObjectURL(file);
var img = new Image();
img.onload = (function (image) {
return function () {
var newHeight = MAX_WIDTH;
var newWidth = MAX_HEIGHT;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
canvas.width = newWidth;
canvas.height = newHeight;
ctx.drawImage(image, 0, 0, this.width, this.height, 0, 0, newWidth, newHeight);
URL.revokeObjectURL(this.src);
var dataURI = canvas.toDataURL(mime);
var blob = dataURLToBlob(dataURI);
imagesToUpload.push(blob);
loaded++;
if (loaded < checkedFiles.length) {
loadImage(checkedFiles[loaded]);
} else {
//DO UPLOAD
input.value = "";
}
}
})(img);
img.src = src;
image = null;
}
loadImage(checkedFiles[0]);
While resizing and uploading, i want to show a loading animation. And this anmiation is very slow.
I think the problem is while resizing the image on the canvas-object, but i have no idea to solve this issue.
The MAX-PICTURE-WITH is 1920px and the MAX-PICTURE-HEIGHT is 1920px.
It would be great if someone can give me a clue?

Related

canvas.toDataURL() results black image by trying to resize base64 string

I am currently trying to resize base64 images, since the image files are too big to be processed later on with php. I've found a way to achieve this by resizing the image using canvas. Unfortunately the image I get is just a black field which is 300px wide and 150px high. Maybe it has something to do with img.onload and canvas.toDataURL() order, or I am just using the wrong event (img.onload). Any idea where the mistake can be?
function exportImg(val){
var imageData = $('#image-cropper').cropit('export', {originalSize: true});
imageData = imageData.replace(/^data:image\/[a-z]+;base64,/, "");
var imageDataRes = resize(imageData);
$.post('php/upload.php', { imageDataRes: imageDataRes });
}
function resize(base64){
// Max size for thumbnail
var maxWidth = 900;
var maxHeight = 900;
// Create and initialize two canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
// Create original image
var img = new Image();
img.src = base64;
img.onload = function(){
// Determine new ratio based on max size
var ratio = 1;
if(img.width > maxWidth) {
ratio = maxWidth / img.width;
}
else if(img.height > maxHeight) {
ratio = maxHeight / img.height;
}
// Draw original image in second canvas
canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);
// Copy and resize second canvas to first canvas
canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
}
alert(canvas.toDataURL());
return canvas.toDataURL();
}
EDIT:
What is async in this case and how to solve it? Sorry, but unfortunately I don't see how this could help me further. The $.post works perfectly, I get the images. I just don't get the idea of img.onload and toDataURL() and how I should parse them from one function to another. At first, I got a blank result, with no string at all (just data,), but by adding this img.onload I got finally some base64 string...but it was just black screen.
You will need to wait onload event after that use global variable to save data and call upload function on the end .
Try this :
function exportImg(val){
var imageData = $('#image-cropper').cropit('export', {originalSize: true});
imageData = imageData.replace(/^data:image\/[a-z]+;base64,/, "");
resize(imageData);
}
var SendWhenisReady = function(imageDataRes){
$.post('php/upload.php', { imageDataRes: imageDataRes });
};
function resize(base64){
// Max size for thumbnail
var maxWidth = 900;
var maxHeight = 900;
// Create and initialize two canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
// Create original image
var img = new Image();
img.src = base64;
img.onload = function(){
// Determine new ratio based on max size
var ratio = 1;
if(img.width > maxWidth) {
ratio = maxWidth / img.width;
}
else if(img.height > maxHeight) {
ratio = maxHeight / img.height;
}
// Draw original image in second canvas
canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);
// Copy and resize second canvas to first canvas
canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
alert(canvas.toDataURL());
window['imageDataRes'] = canvas.toDataURL();
SendWhenisReady(window['imageDataRes'])
}
}

Drawing ends up all black

I'm trying to resize an image via HTML canvas, but when I display it, it displays all black.
My code
function onSuccess(imageData) {
var img = new Image();
img.src = imageData;
window.setTimeout(function() {
var maxSize = 200;
var canvas = document.createElement("canvas");
canvas.width = maxSize;
canvas.height = maxSize;
var ctx = canvas.getContext("2d");
ctx.drawImage(img.src, 0, 0, maxSize, maxSize);
dataurl = canvas.toDataURL("image/jpeg");
alert(dataurl);
}, 1000);
}
I'm not exactly sure what it is I'm doing incorrectly. Thanks for the help!

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;

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);
}
}

Javascript FileReader eats up all the memory when reads local images

I'm working on a concent to show the thumbnail of a large number of images from the local drive.
With HTML5 File API is seems quite possible, but whn I try to load a big number of images the memory usage of the browser goes over the roof and the collapses.
I think the problem is that the FileReader doesn't releases the memory after a file read.
Originally I had a new instance of FileReader and a simple loop to iterate through the images.
To solve this memory problem I replaced this to have one FileReader only, but it did not really help.
Here is the relevand code block:
<script>
var areader = new FileReader();
var counter=0;
function loadImage(file) {
var canvas = document.createElement("canvas");
areader.onload = function (event) {
var img = new Image;
img.onload = function () {
canvas.width = img.width / 100;
canvas.height = img.height / 100;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width / 100, img.height / 100);
var browse = document.getElementById("uploadInput");
if (browse.files.length > counter) {
counter++;
areader.result = null;//I don't think this makes any difference
loadImage(browse.files[counter]);
}
};
img.src = event.target.result;
};
areader.readAsDataURL(file);
preview.appendChild(canvas);
}
function showImages() {
loadImage(document.getElementById("uploadInput").files[0]);
}
If anybody come across this problem the I do something very stupid could you reply.
Thanks,
Tamas
It's not the file reader but you are using the entire image's data in base64 as the src property of the image, which will actually take 133% of the image's size in memory.
You should use Blob URLs instead:
var URL = window.URL || window.webkitURL;
function loadImage( file ) {
var canvas = document.createElement("canvas"),
img = new Image();
img.onload = function() {
canvas.width = img.width / 100;
canvas.height = img.height / 100;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width / 100, img.height / 100);
URL.revokeObjectURL( img.src );
img = null;
var browse = document.getElementById("uploadInput");
if (browse.files.length > counter) {
counter++;
loadImage(browse.files[counter]);
}
};
img.src = URL.createObjectURL( file );
preview.appendChild(canvas);
}

Categories