on Basics Tutorials

How to crop an image using jQuery and PHP

10 comments
photo
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon

So, your client uploaded the image into your newly, freshly developed CMS and then called you to yell about distorted image, or image that just does not look good?

That is a well known scenario. Let me explain a bit what we will achieve today. When your client uploads an image, he is taken to an Image edit area where he sees uploaded image and a smaller preview window. He just needs to drag on the larger image to select crop area and press submit.

After that you crop the image using PHP GD functionality and save the new image somewhere on disk.

Cropping refers to the removal of the outer parts of an image to improve framing, accentuate subject matter or change aspect ratio.

I will concentrate mainly on Image editor part, assuming that the client has uploaded the image. So here is our markup:

<p>Drag on the larger image to select crop area.</p>
<p>
    <img id="photo" src="photo.jpg" alt="" title="" style="margin: 0 0 0 10px;" />
 </p>

So, we have an image tag with id and some inline styling. We will help ourselves with jQuery plugin which will achieve actual client side functionality without coding it from scratch. So, please go to ImgAreaSelect jQuery plugin page and download the plugin.

Extract css and scripts folder in your working folder and put this in your HTML’s head section:

<link rel="stylesheet" type="text/css" href="css/imgareaselect-default.css" />  
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>  
<script type="text/javascript" src="scripts/jquery.imgareaselect.pack.js"></script> 

Now, you are ready to rock and roll. As I said earlier, we will show a preview to the user, so let us create it using jQuery:

$(document).ready(function () { 
    $('<div><img src="photo.jpg" style="position: relative;" /><div>') .css({ 
        float: 'left', 
        position: 'relative', 
        overflow: 'hidden', 
        width: '100px', 
        height: '100px' 
    }) .insertAfter($('#photo'));  
});

What this code does is add a div with size 100x100px and puts our image in it. Let us create some cropping functionality, so change the above code like this:

$(document).ready(function () { 
    $('<div><img src="photo.jpg" style="position: relative;" /><div>') .css({ 
        float: 'left', 
        position: 'relative', 
        overflow: 'hidden', 
        width: '100px', 
        height: '100px' 
    }) .insertAfter($('#photo')); 
    
    $('#photo').imgAreaSelect({ 
        aspectRatio: '1:1', 
        handles: true,
        onSelectChange: preview 
    }); 
});

We added a call to our plugin, set some parameters and a callback function which will preview our image in a smaller div. This function looks like this:

function preview(img, selection) { 
    var scaleX = 100 / (selection.width || 1); 
    var scaleY = 100 / (selection.height || 1); 
    $('#photo + div > img').css({ 
        width: Math.round(scaleX * 600) + 'px', 
        height: Math.round(scaleY * 400) + 'px', 
        marginLeft: '-' + Math.round(scaleX * selection.x1) + 'px', 
        marginTop: '-' + Math.round(scaleY * selection.y1) + 'px' 
    }); 
}

Let me explain a bit. Our plugin will send two parameters to out callback function, and image and selection. Selection is an object which contains width, height and borders of our selection.

Then we set scaling variables and by changing CSS properties of our preview div, we are showing the preview image to our user. Go ahead and try this. Awesome, isn’t it?

But, what now? This is useless. As much as it looks great, it does nothing. To provide cropping parameters to PHP file, we must use a form in which the parameters will be stored and then passed to PHP.

So let us add a form below our image, so our markup looks like this:

<p>
    <img id="photo" src="photo.jpg" alt="" title="" style="margin: 0 0 0 10px;" />
</p>

<form action="crop.php" method="post">
    <input type="hidden" name="x1" value="" />
    <input type="hidden" name="y1" value="" />
    <input type="hidden" name="x2" value="" />
    <input type="hidden" name="y2" value="" />
    <input type="hidden" name="w" value="" />
    <input type="hidden" name="h" value="" />
    <input type="submit" value="Crop" />
</form>

Now let us adjust our JavaScript so it writes values to our form fields. Complete code looks like this:

function preview(img, selection) { 
    var scaleX = 100 / (selection.width || 1); 
    var scaleY = 100 / (selection.height || 1); 
    $('#photo + div > img').css({ 
        width: Math.round(scaleX * 600) + 'px', 
        height: Math.round(scaleY * 400) + 'px', 
        marginLeft: '-' + Math.round(scaleX * selection.x1) + 'px', 
        marginTop: '-' + Math.round(scaleY * selection.y1) + 'px' 
    }); 
} 

$(document).ready(function () { 
    $('<div><img src="photo.jpg" style="position: relative;" /><div>') .css({ 
        float: 'left', 
        position: 'relative', 
        overflow: 'hidden', 
        width: '100px', 
        height: '100px' 
    }) .insertAfter($('#photo')); 
    
    $('#photo').imgAreaSelect({ 
        aspectRatio: '1:1', 
        handles: true,
        onSelectChange: preview, 
        onSelectEnd: function ( image, selection ) {
            $('input[name=x1]').val(selection.x1); 
            $('input[name=y1]').val(selection.y1); 
            $('input[name=x2]').val(selection.x2); 
            $('input[name=y2]').val(selection.y2);
            $('input[name=w]').val(selection.width);
            $('input[name=h]').val(selection.height);  
        } 
    }); 
}); 

Now whenever you complete selection (release a mouse button), callback function writes 4 coordinate values into our form fields. After we click Crop button, this parameters are sent to PHP file crop.php, which will crop the image and save it to disk. This is the code in crop.php:

// Original image
$filename = 'photo.jpg';
//die(print_r($_POST));
$new_filename = 'photo1.jpg';

// Get dimensions of the original image
list($current_width, $current_height) = getimagesize($filename);

// The x and y coordinates on the original image where we
// will begin cropping the image, taken from the form
$x1    = $_POST['x1'];
$y1    = $_POST['y1'];
$x2    = $_POST['x2'];
$y2    = $_POST['y2'];
$w    = $_POST['w'];
$h    = $_POST['h'];     

//die(print_r($_POST));

// This will be the final size of the image 
$crop_width = 100;
$crop_height = 100;

// Create our small image
$new = imagecreatetruecolor($crop_width, $crop_height);
// Create original image
$current_image = imagecreatefromjpeg($filename);
// resamling (actual cropping)
imagecopyresampled($new, $current_image, 0, 0, $x1, $y1, $crop_width, $crop_height, $w, $h);
// creating our new image
imagejpeg($new, $new_filename, 95);

And that’s it. You can see the demo below. Demo only shows client side functionality for security reasons.


If you have any questions, please ask below in comments. I would love to help you.

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon



  • Pingback: Tweets that mention How to crop an image using jQuery and PHP | CodeForest -- Topsy.com

  • Pingback: Interesting things – October 15, 2010 « Daniel Botelho

  • http://falci.me/ Falci

    Sorry, but imagecopy don’t work correctly!.
    We need use imagecopyresampled, and $_POST x2, y2

    I liked this. I will post in my blog, in portuguese, ok?

    • Zvonko

      Hi Falci,

      I corrected the error. My mistake while copy/pasteing.

      You can post this, but please link back to this post.

      Thanks

  • http://falci.me/ Falci
  • Pingback: links for 2010-11-23 | Midashuang's Blog

  • Luis

    Interesting article, I’ve used it as a reference to integrate the imgAreaSelect, cakephp and a cakephp component to redimension images.
    There’s a little thing I don’t understand, are x2 and y2 needed for something or just using w and h are enough to resample?
    I haven’t finished my scripts…
    sorry for my english, greetings from Argentina :)

  • switcherdav

    Thanks for the explanation,

    In your code, the original width and height of the image is fixed (600×400)

    How can you do when the image is loaded in runtime and you don’t know is size but don’t wan’t to display a 1440px wide image ?

    • switcherdav

      Reply to myself,

      Just use img.width and img.height and set fixed width for #photo !

      Thanks again

      regards

  • http://coder-design.com/ coder-design

    Thanks for sharing. It is what I am looking for.