5
votes

EDIT: I dont want to show the image on the client, the purpose is to shrink the image and scale...

Im having some trouble resizing an image which is selected using a file input in a form before it must be uploaded to the server.

I have the following code monitoring my file input:

// monitor file inputs and trigger event
$(document).on('change', '.btn-file :file', function() {

    var F = this.files;
    if(!isImage( F[0] ))
    {
        alert("Not an image file"); 
    }

    var fileurl = resizeImage(F[0]);
    console.log(fileurl);               

    var input = $(this),label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
    input.trigger('fileselect', [label]);
});

This function will call resizeImage which looks like this:

function resizeImage(file)
{
    var MAX_WIDTH = 800;
    var MAX_HEIGHT = 600;

    var img = document.createElement("img");
    img.src = window.URL.createObjectURL(file);
    console.log(img.width);         

    var canvas = document.createElement('canvas');

    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);
    console.log(ctx);       
    var dataurl = canvas.toDataURL("image/png");
    return dataurl;
}

Problem is, that my console log tells me that the return value from my resize function is "data:,". I then started to console.log my way out of it, to narrow down where the problem is hiding. In my resizeImage function i logged the WIDTH of my img element which gave me a width of 0 which should not be correct ? .. I can't figure out what i have done wrong..

1
why are you trying to do this with JS and not CSS? - fred randall
@COOOL how is it possible to shrink/resize an image with css ? .. - DTH
Use background-image and background-size: cover or background-size: contain (depending on your need)? - Terry
Use PHP server-side. PHP can do this very easily. Javascript cannot. - user4639281
@DTH, If the img you draw onto canvas does not originate on the same domain as the webpage, then toDataURL will return an empty url. This prohibition against cross-domain is a results of security concerns. - markE

1 Answers

13
votes

If your target browser supports the file input attribute, then you can use URL.createObjectURL to create an image source that you can manipulate with the canvas element.

Given a maximum desired size of maxW x maxH you can calculate the scaling factor that will resize the image while maintaining the original aspect ratio like this:

var scale=Math.min((maxW/img.width),(maxH/img.height));

Here's example code and a Demo.

Note that the demo does draw the image to the canvas, but you could just as easily substitute an in-memory canvas with document.createElement('canvas').

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

// limit the image to 150x100 maximum size
var maxW=150;
var maxH=100;

var input = document.getElementById('input');
input.addEventListener('change', handleFiles);

function handleFiles(e) {
  var img = new Image;
  img.onload = function() {
    var iw=img.width;
    var ih=img.height;
    var scale=Math.min((maxW/iw),(maxH/ih));
    var iwScaled=iw*scale;
    var ihScaled=ih*scale;
    canvas.width=iwScaled;
    canvas.height=ihScaled;
    ctx.drawImage(img,0,0,iwScaled,ihScaled);
    alert(canvas.toDataURL());
  }
  img.src = URL.createObjectURL(e.target.files[0]);
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<input type="file" id="input"/>
<br>
<canvas id="canvas" width=300 height=300></canvas>