1

I'm using JQuery to crop an image.

  <link href="/public/css/jquery.Jcrop.min.css" rel="stylesheet" type="text/css" />

        <!-- add scripts -->
       <script src="http://code.jquery.com/jquery-1.9.0.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.0.0.js"></script>
        <script src="/public/js/jquery.Jcrop.min.js"></script>
        <script src="/public/js/script.js"></script>

    <form id="upload_form" enctype="multipart/form-data" method="post" action="upload.php" onsubmit="return checkForm()">
                    <!-- hidden crop params -->
                    <input type="hidden" id="x1" name="x1" />
                    <input type="hidden" id="y1" name="y1" />
                    <input type="hidden" id="x2" name="x2" />
                    <input type="hidden" id="y2" name="y2" />

                    <h2>Step1: Please select image file</h2>
                    <div><input type="file" name="image_file" id="image_file" onchange="fileSelectHandler()" /></div>

                    <div class="error"></div>

                    <div class="step2">
                        <h2>Step2: Please select a crop region</h2>
                        <img id="preview" />

                        <div class="info">
                            <label>File size</label> <input type="text" id="filesize" name="filesize" />
                            <label>Type</label> <input type="text" id="filetype" name="filetype" />
                            <label>Image dimension</label> <input type="text" id="filedim" name="filedim" />
                            <label>W</label> <input type="text" id="w" name="w" />
                            <label>H</label> <input type="text" id="h" name="h" />
                        </div>

                        <input type="submit" value="Upload" onclick="return checkForm()"/>
                    </div>

For the above code I have an x, y co-ordinations, width and height of crop image and in the backend I am using the multer module in Node.JS. In that I don't know how can I pass x and y coordinates to that multer code. In my main file app.js I declare the module like

var FormData = require('form-data');
var multer  = require('multer');
var upload = multer({ dest: 'uploads/' });

and in the controller i used like this

BASE.APP.post('/profile', BASE.upload.single('avatar'), function (req, res, next) {
  // req.file is the `avatar` file
  // req.body will hold the text fields, if there were any

    //console.log(req.file);

    BASE.FS.readFile(req.file.path, function read(err, data) {
    if (err) {
        throw err;
    }

In this way the file is uploaded but not the cropped one.

MatejMecka
  • 1,448
  • 2
  • 24
  • 37
Sumit Aggarwal
  • 831
  • 2
  • 16
  • 29

1 Answers1

0

This should do what you want it to. I like to use sharp for image manipulation. Scrap that, saw you needed to crop and not resize! Use gm for this.

(EDIT: Lovell pointed out in the comments that sharp can be used - "sharp supports region extraction, similar to the crop feature, of gm, via its extract operation". See his comment for more info.)

HTML for getting form image size:

<form method="post" action="/">
    <input type="hidden" id="x1" name="x1" />
    <input type="hidden" id="y1" name="y1" />
    <input type="hidden" id="x2" name="x2" />
    <input type="hidden" id="y2" name="y2" />
    <input type="submit" value="Submit">
</form>

JS:

var FormData = require('form-data');
var qs = require('querystring');
var multer  = require('multer');
var gm = require('gm');

function (request, response) {
  if (request.method == 'POST') {
    let body = '';

    request.on('data', function (data) {
      body += data;

      // Too much POST data, kill the connection!
      // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
      if (body.length > 1e6) request.connection.destroy();
    });

    request.on('end', function () {
      // The POST variables are now within the `var post`
      const post = qs.parse(body);
      const x1 = post["x1"];
      const x2 = post["x2"];
      const y1 = post["y1"];
      const y2 = post["y2"];

      let upload = multer({
        dest: 'uploads/'
      });

      BASE.APP.post('/profile', BASE.upload.single('avatar'), function(req, res, next) {
        const imagePath = req.file.path;
        const imageOutputPath = "/some/other/path";

        gm(imagePath)
          .crop(x1, y1, x2, y2)
          .write(imageOutputPath, function (err) {
            if (!err) console.log('done');
          });
      });
    });
  }
});

While this does what you've asked, also consider user input errors, such as specifying too large of a crop area for a particular image (e.g., trying to crop a 200px square region from a 50px square image - that's not possible). I'll leave that to you!

Nick Bull
  • 9,518
  • 6
  • 36
  • 58
  • here you are fix the size 128 by 128 in my case user will decide what size of image he wants. He used to crop functionality to crop that image – Sumit Aggarwal Jul 05 '16 at 10:10
  • That's okay - just make sure you pass the form's data in POST, then use the variables from the request. See http://stackoverflow.com/questions/4295782/how-do-you-extract-post-data-in-node-js for more information - I'll try update the answer – Nick Bull Jul 05 '16 at 10:37
  • Please see the updated answer, which hasn't been tested. I've used `querystring` module, a non-import from `node`'s core that lets you request POST parameters. The code can now use POST'ed parameters as the avatar size. Always remember to sanitize POST data from users for security reasons. – Nick Bull Jul 05 '16 at 10:52
  • its give me error: [Error: Could not execute GraphicsMagick/ImageMagick: gm "convert" "uploads/0e845b0387db7ce041dda1c4ae04909c" "-crop" "296x797+419+419" "uploads/crop/" this most likely means the gm/convert binaries can't be found – Sumit Aggarwal Jul 05 '16 at 12:40
  • Have you installed the `gm` package using `npm`? Please make sure you've done that. `npm install gm --save-dev` – Nick Bull Jul 05 '16 at 13:00
  • Yes i have intsalled that is working but the cropping is not working fine. Its crop the image with wrong dimesions – Sumit Aggarwal Jul 06 '16 at 07:42
  • @SumitAggarwal what happens exactly? You'll hae to be far more specific for me to be able to help you - how are the output cropping dimensions incorrect, and can you give examples of inputs and corresponding outputs? How are you getting the dimensions, i.e., exactly what code are you using? Maybe we can start a discussion instead of loads of comments here. – Nick Bull Jul 07 '16 at 13:46
  • 1
    @NickBull `sharp` supports region extraction, similar to the `crop` feature, of `gm`, via its `extract` operation - see http://sharp.dimens.io/en/stable/api/#extract-left-left-top-top-width-width-height-height – Lovell Fuller Jul 08 '16 at 20:27
  • @LovellFuller that's awesome, didn't know that! Gotta love node's versatility :) – Nick Bull Jul 08 '16 at 21:05