Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize image, need a good library [closed]

First of all - The problem


I am developing a web application that enables the user to take a picture with their smartphone, tablet or just browse for a picture on their pc. I need to upload this file to my database, which is working perfectly IF the picture is small enough.

After experimenting a bit with certain photos, I found out that a smartphone takes a picture with a size of at least 1MB and this is way to big too upload to my database.

The uploading goes as following:
1. Convert the image to a Base64 encoded string.
2. Send the string in an array (contains string in pieces) to WebAPI
3. Join the strings into one and convert this into byte array.

I noticed that if a file is around 70-90kb, this would be the maximum size of a file that can be inserted in the database. The moment I have a file that is bigger then 100kb, the inserting fails.

So I am searching for a good resizing library to resize the picture that was chosen. I don't know if this is even possible, but everything has to be done client-side.

Technology


I am using Javascript/jQuery and AngularJS for the client side and VB.NET for my WebAPI. This is because I'm doing an internship and don't have another choice to use VB.NET.

But this has nothing to do with the issue, I just need to find a way to compress/resize/minimize the chosen file, so this can be uploaded to the database.

The upload is happening via the $http.post() from AngularJS.

If someone could advice a library, care to help a fellow programmer out with some basic example code? I mostly have trouble figuring out how to use a plugin or library, because I'm quite new to all 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 that I couldn't provide any code or something other, it's more an informative question than a coding problem. This might popup when I have a library that I can use. Also, if there are any remarks, I'll consider them, because I have a deadline and don't have much time left to start fixing small problems. Most of it works by now, except for that image problem.

like image 468
Jorrex Avatar asked Oct 14 '25 04:10

Jorrex


1 Answers

You can use the HTML5 Canvas element to blit your image on it and then resize it appropriately

You create a canvas on-the-fly and perform pixel operations on it - so don't worry it's not visible anywhere on the DOM - think of it like a virtual canvas

Here is a little script I've written a while ago(with some help from another S.O question which I don't really remember) - that allows you to do this - whilst keeping the aspect ratios of the image:

Arguments

  • You provide an image directly into it
  • You provide a maxWidth/maxHeight and it will preserve at least one of the 2
  • It allows you to also rotate the image by defining the degrees parameter(which would be really useful on mobile devices since different devices provide arbitrarily rotated images - you will find out about this the hard way soon if you are dealing with mobile devices)

Returns

  • It returns a Base64 string of the resized image

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 working code snippet that allows you to upload 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's resized version</h6>
  </div>
  <input type="file" id="input" />
  <hr>
  <h5>Image Preview:</h5>
  <img id="previewImg" src="" />

</div>
like image 162
nicholaswmin Avatar answered Oct 16 '25 16:10

nicholaswmin