4

I am putting together HTML+JS code to resize picture before automatically submitting form to the server. I initially wrote code for automatic form submission and then added logic for image resizing. Automatic form submission works but image resizing is not working. Please provide guidance. Thank you in advance.

<!DOCTYPE html>
<html>
<head>
<title>Flask App</title>    
<meta name="viewport" content="width=device-width, initial-scale=1, user-
scalable=no">  
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script> 
<script src="http://malsup.github.com/jquery.form.js"></script> 

<script type="text/javascript">
$(function(){
    //JS Code snippet 1 - Automatic form submission on file selection
    $("#file_select").change(function(){
    $("#upload_form").submit();  
    $("#upload_form_div").hide();
    $("#loading").show();

    //JS Code snippet 2 - Image Resizing
    var filesToUpload = inputs.files;

    var img = document.createElement("img");
    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 = 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.width = width;
    canvas.height = height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, width, height);

    var xhr = new XMLHttpRequest();
    xhr.open("POST", "upload");
    xhr.send(ctx.toDataURL());

});
});

 </script>

 </head>

 <body>
  <h1 class="logo">Upload Picture</h1>
  <div id="upload_form_div">
   <form id="upload_form" method="POST" enctype="multipart/form-data" action="upload">
    <input type="file" name="file" capture="camera" id="file_select"/>
   </form>
  </div>

  <div id="loading" style="display:none;"> 
     Uploading your picture...
  </div>

 </body>
</html>

UPDATES - (3/28/2014) -Combined code from @yuhua and 'uploader' function in JIC library. Updated code is below

When I open my webapp in chrome browser on laptop, everything works fine. However, my resized image is not coming out as expected when I upload image from camera by opening my webapp in chrome browser on iPhone 4s. Please find below original and resized image. Please correct what I am doing wrong.

$("#file_select").change(function (e) {
 var fileReader = new FileReader();
 fileReader.onload = function (e) {
    var img = new Image();
    img.onload = function () {
        var MAX_WIDTH = 3264;
        var MAX_HEIGHT = 2448;
        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;
            }
        }

        var canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;
        canvas.getContext("2d").drawImage(this, 0, 0, width, height);

        this.src = canvas.toDataURL();
        //document.body.appendChild(this);//remove this if you don't want to show it

        var newImageData = canvas.toDataURL("image/png", 70/100);
         var result_image_obj = new Image();
         result_image_obj.src = newImageData;

          //======= Step 2 - Upload compressed image to server =========

          //Here we set the params like endpoint, var name (server side) and filename
          var server_endpoint = 'upload',
              server_var_name = 'file',
              filename = "new.jpg";

          //This is the callback that will be triggered once the upload is completed
          var callback = function(response){ console.log(response); }

          //Here goes the magic
          $("#result").load(jic.upload(result_image_obj, server_endpoint, server_var_name, filename, callback));



    }
    img.src = e.target.result;
    console.log(img);

}
fileReader.readAsDataURL(e.target.files[0]);
});

Original Image Resized Image being uploaded to server

user1146904
  • 243
  • 2
  • 6
  • 13

2 Answers2

5

I think your browser might not be supported with .mozGetAsFile() . and i modified your code for an example here:

$("#file_select").change(function (e) {
    var fileReader = new FileReader();
    fileReader.onload = function (e) {
        var img = new Image();
        img.onload = function () {
            var MAX_WIDTH = 100;
            var MAX_HEIGHT = 100;
            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;
                }
            }

            var canvas = document.createElement("canvas");
            canvas.width = width;
            canvas.height = height;
            canvas.getContext("2d").drawImage(this, 0, 0, width, height);
            this.src = canvas.toDataURL();
            document.body.appendChild(this);//remove this if you don't want to show it
        }
        img.src = e.target.result;
    }
    fileReader.readAsDataURL(e.target.files[0]);
});

this is a reference: outputting HTML5 canvas as an image, howto?

UPDATE:

Take a look bottom of page (Browser support)

https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement

Community
  • 1
  • 1
yuhua
  • 1,239
  • 8
  • 18
  • I tried your solution and it appends resized image at end of document. Great! I am trying to accomplish next step which is send this resized image over 'POST' to '/upload'. At end of your snippet I added following code after fileReader.readAsDataURL but it's not submitting form. Can you please guide? fileReader.onloadend = function () { var xhr = new XMLHttpRequest(); xhr.open("POST", "upload"); xhr.send(fileReader);} – user1146904 Mar 25 '14 at 23:08
  • try this `xhr.open("POST", "upload", true);` – yuhua Mar 26 '14 at 02:55
  • maybe you could try out `$.ajax()` instead of `xhr` and invoke form submit at last line: `$("#upload_form").submit();` – yuhua Mar 26 '14 at 07:25
  • For uploading I used AJAX uploader function from JIC. Now i am able to resize and upload, however resized image is not coming out as expected. Please have a look at my updated code. – user1146904 Mar 29 '14 at 02:32
  • Your code is correct, that's a tricky problem with iPhone camera caused by EXIF image. here is the reference: http://stackoverflow.com/questions/13971491/captured-photo-automatically-rotated-during-upload-in-ios-6-0-or-iphone – yuhua Mar 31 '14 at 02:32
-1

You can try it with PHP rather than HTML and JavaScript. What we are doing is that we are storing the path of the resized image into the database.

public function Resize_image($width = 0, $height = 0, $quality = 90, $filename_in = null, $filename_out = null)
{
    $this->Filename = $filename_in;
    $this->Extension = strtolower($this->Get_file_extension($this->Filename));

    $size = getimagesize($this->Filename);
    $ratio = $size[0] / $size[1];
    if ($ratio >= 1){
        $scale = $width / $size[0];
    } else {
        $scale = $height / $size[1];
    }
    // make sure its not smaller to begin with!
    if ($width >= $size[0] && $height >= $size[1]){
        $scale = 1;
    }

    // echo $fileext;
    switch ($this->Extension)
    {
        case "jpg":
            $im_in = imagecreatefromjpeg($this->Filename);
            $im_out = imagecreatetruecolor($size[0] * $scale, $size[1] * $scale);
            imagecopyresampled($im_out, $im_in, 0, 0, 0, 0, $size[0] * $scale, $size[1] * $scale, $size[0], $size[1]);
            imagejpeg($im_out, $filename_out, $quality);
        break;
        case "gif":
            $im_in = imagecreatefromgif($this->Filename);
            $im_out = imagecreatetruecolor($size[0] * $scale, $size[1] * $scale);
            imagecopyresampled($im_out, $im_in, 0, 0, 0, 0, $size[0] * $scale, $size[1] * $scale, $size[0], $size[1]);
            imagegif($im_out, $filename_out, $quality);
        break;
        case "png":
            $im_in = imagecreatefrompng($this->Filename);
            $im_out = imagecreatetruecolor($size[0] * $scale, $size[1] * $scale);
            imagealphablending($im_in, true); // setting alpha blending on
            imagesavealpha($im_in, true); // save alphablending setting (important)
            imagecopyresampled($im_out, $im_in, 0, 0, 0, 0, $size[0] * $scale, $size[1] * $scale, $size[0], $size[1]);
            imagepng($im_out, $filename_out, 9);
        break;
    }
    imagedestroy($im_out);
    imagedestroy($im_in);
}

Now you can use this function like so to resize images and copy it to the required directory.

Resize_image($width, $height, $quality=90, $filename_in, $filename_out)

For example:

Resize_image(150, 150, 90, "Directory".$image, "Directory".$image_without_extension."_thumb.".$image_ext); //makes file_thumb.ext
Pang
  • 9,564
  • 146
  • 81
  • 122
Abhishek
  • 517
  • 3
  • 18
  • your code snippet is setting CSS for the image. It is not generating a new resized image. Please correct me if I am wrong. – user1146904 Mar 25 '14 at 06:16