Image resizing, good library needed
First of all - the problem
I am developing a web application that allows the user to take a picture using a smartphone, tablet, or simply view the image on their PC. I need to upload this file to my database which works fine IF , the image is small enough.
After experimenting a bit with some photos, I found out that a smartphone takes a picture of at least 1MB in size, and this is a way to upload a lot to my database.
Loading is done as follows:
1. Convert the image to Base64 encoding.
2. Send string to array (containing string in chunks) in WebAPI
3. Append strings to one and convert them to byte array.
I noticed that if the file is around 70-90KB, this will be the maximum file size that can be inserted into the database. The moment I have a file larger than 100kb the insert failed.
So I am looking for a good resizing library to resize the selected image. I don't know if this is possible, but everything should be done on the client side.
Technology
I am using Javascript / jQuery and AngularJS for the client side and VB.NET for my WebAPI. This is because I am doing an internship and have no other choice to use VB.NET.
But that has nothing to do with the problem, I just need to find a way to shrink / resize / minimize the selected file so that it can be loaded into the database.
Loading is done via $ http.post () from AngularJS.
If anyone can advise a library, take care to help the second programmer with some basic code example? I am mostly having problems with how to use a plugin or library because I am completely new to this. And I would appreciate it if you guys could provide me with at least some information to get me on track.
Thanks in advance!
Sorry I couldn't provide any code or anything else, this is more of an informative question than a coding issue. It might show up if I have a library that I can use. Also, if there are any comments, I will consider them because I have a deadline and little time to start fixing small problems. Most of them still work, except for the problem with this image.
source to share
You can use an HTML5 canvas element to frame an image and then resize it accordingly.
You create canvas
on the fly and perform pixel operations on it - so don't worry about it not showing up anywhere in the DOM - think of it like a virtual canvas
Here's a little script I wrote a while ago (with some help from another SO question that I don't really remember) - it allows you to do this while maintaining the aspect ratio of an image:
Arguments
- You provide
image
directly to it - You provide
maxWidth
/maxHeight
and keep at least one of 2 - It also allows you to rotate the image by defining a parameter
degrees
(which would be really useful on mobile devices, as various devices provide randomly rotated images - you will find out about this difficult soon if you are dealing with mobile devices)
Returns
function resizeImg(img, maxWidth, maxHeight, degrees) {
var imgWidth = img.width,
imgHeight = img.height;
var ratio = 1,
ratio1 = 1,
ratio2 = 1;
ratio1 = maxWidth / imgWidth;
ratio2 = maxHeight / imgHeight;
// Use the smallest ratio that the image best fit into the maxWidth x maxHeight box.
if (ratio1 < ratio2) {
ratio = ratio1;
} else {
ratio = ratio2;
}
var canvas = document.createElement("canvas");
var canvasContext = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
var canvasCopy2 = document.createElement("canvas");
var copyContext2 = canvasCopy2.getContext("2d");
canvasCopy.width = imgWidth;
canvasCopy.height = imgHeight;
copyContext.drawImage(img, 0, 0);
// init
canvasCopy2.width = imgWidth;
canvasCopy2.height = imgHeight;
copyContext2.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvasCopy2.width, canvasCopy2.height);
var rounds = 1;
var roundRatio = ratio * rounds;
for (var i = 1; i <= rounds; i++) {
// tmp
canvasCopy.width = imgWidth * roundRatio / i;
canvasCopy.height = imgHeight * roundRatio / i;
copyContext.drawImage(canvasCopy2, 0, 0, canvasCopy2.width, canvasCopy2.height, 0, 0, canvasCopy.width, canvasCopy.height);
// copy back
canvasCopy2.width = imgWidth * roundRatio / i;
canvasCopy2.height = imgHeight * roundRatio / i;
copyContext2.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvasCopy2.width, canvasCopy2.height);
} // end for
canvas.width = imgWidth * roundRatio / rounds;
canvas.height = imgHeight * roundRatio / rounds;
canvasContext.drawImage(canvasCopy2, 0, 0, canvasCopy2.width, canvasCopy2.height, 0, 0, canvas.width, canvas.height);
if (degrees == 90 || degrees == 270) {
canvas.width = canvasCopy2.height;
canvas.height = canvasCopy2.width;
} else {
canvas.width = canvasCopy2.width;
canvas.height = canvasCopy2.height;
}
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
if (degrees == 90 || degrees == 270) {
canvasContext.translate(canvasCopy2.height / 2, canvasCopy2.width / 2);
} else {
canvasContext.translate(canvasCopy2.width / 2, canvasCopy2.height / 2);
}
canvasContext.rotate(degrees * Math.PI / 180);
canvasContext.drawImage(canvasCopy2, -canvasCopy2.width / 2, -canvasCopy2.height / 2);
var dataURL = canvas.toDataURL();
return dataURL;
}
And here's a piece of working code that lets you load from your filesystem and resize on the fly:
/*
-------------------------------
-------HANDLE FILE UPLOAD------
-------------------------------
*/
var input = document.getElementById('input');
input.addEventListener('change', handleFiles);
function handleFiles(e) {
var img = new Image;
img.src = URL.createObjectURL(e.target.files[0]);
img.onload = function() {
var base64String = resizeImg(img, 300, 300, 0); //HERE IS WHERE THE FUNCTION RESIZE IS CALLED!!!!
alert(base64String);
document.getElementById('previewImg').src = base64String;
}
}
/*
-------------------------------
-------RESIZING FUNCTION-------
-------------------------------
*/
function resizeImg(img, maxWidth, maxHeight, degrees) {
var imgWidth = img.width,
imgHeight = img.height;
var ratio = 1,
ratio1 = 1,
ratio2 = 1;
ratio1 = maxWidth / imgWidth;
ratio2 = maxHeight / imgHeight;
// Use the smallest ratio that the image best fit into the maxWidth x maxHeight box.
if (ratio1 < ratio2) {
ratio = ratio1;
} else {
ratio = ratio2;
}
var canvas = document.createElement("canvas");
var canvasContext = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
var canvasCopy2 = document.createElement("canvas");
var copyContext2 = canvasCopy2.getContext("2d");
canvasCopy.width = imgWidth;
canvasCopy.height = imgHeight;
copyContext.drawImage(img, 0, 0);
// init
canvasCopy2.width = imgWidth;
canvasCopy2.height = imgHeight;
copyContext2.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvasCopy2.width, canvasCopy2.height);
var rounds = 1;
var roundRatio = ratio * rounds;
for (var i = 1; i <= rounds; i++) {
// tmp
canvasCopy.width = imgWidth * roundRatio / i;
canvasCopy.height = imgHeight * roundRatio / i;
copyContext.drawImage(canvasCopy2, 0, 0, canvasCopy2.width, canvasCopy2.height, 0, 0, canvasCopy.width, canvasCopy.height);
// copy back
canvasCopy2.width = imgWidth * roundRatio / i;
canvasCopy2.height = imgHeight * roundRatio / i;
copyContext2.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvasCopy2.width, canvasCopy2.height);
} // end for
canvas.width = imgWidth * roundRatio / rounds;
canvas.height = imgHeight * roundRatio / rounds;
canvasContext.drawImage(canvasCopy2, 0, 0, canvasCopy2.width, canvasCopy2.height, 0, 0, canvas.width, canvas.height);
if (degrees == 90 || degrees == 270) {
canvas.width = canvasCopy2.height;
canvas.height = canvasCopy2.width;
} else {
canvas.width = canvasCopy2.width;
canvas.height = canvasCopy2.height;
}
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
if (degrees == 90 || degrees == 270) {
canvasContext.translate(canvasCopy2.height / 2, canvasCopy2.width / 2);
} else {
canvasContext.translate(canvasCopy2.width / 2, canvasCopy2.height / 2);
}
canvasContext.rotate(degrees * Math.PI / 180);
canvasContext.drawImage(canvasCopy2, -canvasCopy2.width / 2, -canvasCopy2.height / 2);
var dataURL = canvas.toDataURL();
return dataURL;
}
/*
-------------------------------
-------UNNECESSARY CSS---------
-------------------------------
*/
@import url(http://fonts.googleapis.com/css?family=Lato);
.container {
margin: 0 auto;
width: 400px;
height: 400px;
box-shadow: 1px 1px 1px 1px gray;
}
h3,
h4,
h5,
h6 {
margin: 4px !important;
}
.container,
.container * {
display: block;
margin: 12px auto;
font-family: 'Lato';
}
.header {
background-color: #2196F3;
padding: 12px;
color: #fff;
}
.container input {
width: 128px;
height: 32px;
cursor: pointer;
}
.container img {
display: block;
margin: 12px auto;
}
<div class="container">
<div class="header">
<h3>Choose a file</h3>
<h6>and I will alert back to you the base64 string of it resized version</h6>
</div>
<input type="file" id="input" />
<hr>
<h5>Image Preview:</h5>
<img id="previewImg" src="" />
</div>
source to share