
This post will show you how to build an AJAX crop image tool using the image cropper control from YUI library and PHP.
The ImageCropper Control from the YUI library gives you an interactive interface for getting the dimensions to crop an image and using these dimensions in PHP, we can do some cropping.
The script we are going to build will
There are 3 files we are going to use
From a technical point of view, the flow will be like this :
Let's have a look at index.php
The index.php is our main file where users will be able upload images and then download the cropped ones.
We'll need the following components from the YUI library :
Of course we'll use Yahoo combo handling and add the js to our page along with the CSS needed for the above controls :
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/resize/assets/skins/sam/resize.css" /> <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/imagecropper/assets/skins/sam/imagecropper.css" /> <!-- js --> <script type="text/javascript" src="http://yui.yahooapis.com/combo?2.5.2/build/yahoo-dom-event/yahoo-dom-event.js&2.5.2/build/dragdrop/dragdrop-min.js&2.5.2/build/element/element-beta-min.js&2.5.2/build/resize/resize-beta-min.js&2.5.2/build/imagecropper/imagecropper-beta-min.js&2. 5.2/build/connection/connection-min.js&2.5.2/build/json/json-min.js"></script>
Next users must be able to upload images via AJAX, so we add a form to our page:
<form action="upload.php" enctype="multipart/form-data" method="post" name="uploadForm" id="uploadForm"> Image : <input type="file" name="uploadImage" id="uploadImage" /> <input type="button" id="uploadButton" value="Upload"/> </form>
We have an onclick event to the upload button to fire the uploading process.
// add listeners YAHOO.util.Event.on('uploadButton', 'click', uploader.carry);
We'll also need 2 containers :
<div id="imageContainer"></div> <div id="downloadLink"></div>
Both containers will be updated via innerHTML afterwards.
AJAX upload
For the AJAX upload, Code Central
has an excellent tutorial which I highly recommend. I took the code sample and modified it a bit to fit my needs. Finally I came up with a nice JSON object called uploader which has one method, carry. The latter just posts form data to a specified URL.
uploader = { carry: function(){ // set form YAHOO.util.Connect.setForm('uploadForm', true); // upload image YAHOO.util.Connect.asyncRequest('POST', 'upload.php', { upload: function(o){ // parse our json data var jsonData = YAHOO.lang.JSON.parse(o.responseText); // put image in our image container YAHOO.util.Dom.get('imageContainer').innerHTML = '<img id="yuiImg" src="' + jsonData.image + '" width="' + jsonData.width + '" height="' + jsonData.height + '" alt="" />'; // init our photoshop photoshop.init(jsonData.image); // get first cropped image photoshop.getCroppedImage(); } }); } };
When upload is complete, we get the JSON data we mentioned earlier on. For e.g :
{"image" : "images/myimage.jpg", "width" : "500", "height" : 400}
With this data and using innerHTML we update our imageContainer div to put our image which will have yuiImg as id :
YAHOO.util.Dom.get('imageContainer').innerHTML = '<img id="yuiImg" src="' + jsonData.image + '" width="' + jsonData.width + '" height="' + jsonData.height + '" alt="" />';
It's very important to specify the image width and height else the image cropper won't work.
Next we initialize another JSON object, photoshop which we'll have a look now.
Our photoshop object
photoshop = { image: null, crop: null, init: function(image){ // set our image photoshop.image = image; // our image cropper from the uploaded image photoshop.crop = new YAHOO.widget.ImageCropper('yuiImg'); photoshop.crop.on('moveEvent', function() { // get updated coordinates photoshop.getCroppedImage(); }); }, getCroppedImage: function(){ var coordinates = photoshop.getCoordinates(); var url = 'crop.php?image=' + photoshop.image + '&cropStartX=' + coordinates.left +'&cropStartY=' + coordinates.top +'&cropWidth=' + coordinates.width +'&cropHeight=' + coordinates.height; YAHOO.util.Dom.get('downloadLink').innerHTML = '<a href="' + url + '">download cropped image</a>'; }, getCoordinates: function(){ return photoshop.crop.getCropCoords(); } };
The init function iniatializes the YUI image cropper from the uploaded image which has yuiImg as id.
photoshop.crop = new YAHOO.widget.ImageCropper('yuiImg');
We also subscribe to the moveEvent for the cropper since we'll need to update the download link for the cropped image. So whenever the image cropper is moved/resized, we call the getCroppedImage function.
photoshop.crop.on('moveEvent', function() { // get updated coordinates photoshop.getCroppedImage(); });
The getCroppedImage function will generate the download link for the cropped image. To do image cropping in PHP we'll need
Fortunately the YUI cropper utility has a function which will give us what we want, it's the getCropCoords() method. So, whenever the getCroppedImage function is called, we get the coordinates of the cropped area, build a URL and finally put the download link in our downloadLink container.
// get coordinates var coordinates = photoshop.getCoordinates(); // build our url var url = 'crop.php?image=' + photoshop.image + '&cropStartX=' + coordinates.left +'&cropStartY=' + coordinates.top +'&cropWidth=' + coordinates.width +'&cropHeight=' + coordinates.height; // put download link in our page YAHOO.util.Dom.get('downloadLink').innerHTML = '<a href="' + url + '">download cropped image</a>';
This is all we need for the index page.
upload.php
if(!empty($_FILES["uploadImage"])) { // get file name $filename = basename($_FILES['uploadImage']['name']); // get extension $ext = substr($filename, strrpos($filename, '.') + 1); // check for jpg only if ($ext == "jpg") { // generate unique file name $newName = 'images/'.time().'.'.$ext; // upload files if ((move_uploaded_file($_FILES['uploadImage']['tmp_name'], $newName))) { // get height and width for image uploaded list($width, $height) = getimagesize($newName); // return json data echo '{"image" : "'.$newName.'", "height" : "'.$height.'", "width" : "'.$width.'" }'; } else { echo '{"error" : "An error occurred while moving the files"}'; } } else { echo '{"error" : "Invalid image format"}'; } }
The upload.php file too is self explanatory, we check for a jpg image only, then generate an unique filename, put it in the images folder and finally build json data which we'll use for DOM manipulation. Of course the images folder must be writable by the web server.
crop.php
// get variables $imgfile = $_GET['image']; $cropStartX = $_GET['cropStartX']; $cropStartY = $_GET['cropStartY']; $cropW = $_GET['cropWidth']; $cropH = $_GET['cropHeight']; // Create two images $origimg = imagecreatefromjpeg($imgfile); $cropimg = imagecreatetruecolor($cropW,$cropH); // Get the original size list($width, $height) = getimagesize($imgfile); // Crop imagecopyresized($cropimg, $origimg, 0, 0, $cropStartX, $cropStartY, $width, $height, $width, $height); // force download nes image header("Content-type: image/jpeg"); header('Content-Disposition: attachment; filename="'.$imgfile.'"'); imagejpeg($cropimg); // destroy the images imagedestroy($cropimg); imagedestroy($origimg);
Crop.php allows us to crop our uploaded image. First we get all the variables passed to us via the AJAX request,
// get variables $imgfile = $_GET['image']; $cropStartX = $_GET['cropStartX']; $cropStartY = $_GET['cropStartY']; $cropW = $_GET['cropWidth']; $cropH = $_GET['cropHeight'];
Then we create 2 images, the original one and the cropped one, and use the imagecopyresized function to generate the cropped image. We add some header information to tell the world it's an image and prompt for a save dialog.
[...] asvin Demo: http://htmlblog.net/demo/cropper/ Download: click here Source: http://www.htmlblog.net addthis_url = [...]
Nice example, I will have to link to it from the http://developer.yahoo.com/yui/imagecropper page ;)
Cool, thanx Dave ;-)
[...] Ballo has posted a tutorial that shows how to combine the YUI libraries with PHP to create a simple image [...]
[...] The html blog | AJAX image cropper with YUI and PHP [...]
How can we disable resize of area that is to be crop???
Rohit, you mean you want to disable the image cropper control? Try this:
photoshop.crop.destroy();
[...] of DataTable with Tooltip. A single Tooltip is reused throughout the table to improve performance.AJAX Image Cropper with YUI and PHP: Asvin Balloo has written up a tutorial on using Dav Glass’s ImageCropper Control with a PHP [...]
the demo doesn’t work for me :( i get php errors…
Hi Kovshenin
What are the errors exactly? Currently the PHP script caters only for JPG files.
Thanks for the great script!
One question: can I set the aspect ratio of the crop? I would like all user-cropped images to be the same shape.
Thanks again!
Can i add(insert) this photo in table in Mysql and retrieve it.
Please help me
Josh
You can add the following options when creating the image cropper:
initHeight
initWidth
like that:
photoshop.crop = new YAHOO.widget.ImageCropper(’yuiImg’, {initHeight:200, initWidth: 200});
Check the doc
http://developer.yahoo.com/yui/imagecropper/
Adel,
check my other blog post,
http://htmlblog.net/pixidou-an-open-source-ajax-image-editor-php-and-yui-based/
Maybe it’ll be easier for you. Let me know if you need help
Thank
pls send script for save crop image
Gajender, check my blog post,
http://htmlblog.net/pixidou-an-open-source-ajax-image-editor-php-and-yui-based/
you can download the script there.
I always wanted a script that allows me to rotate images in realtime.
Is a real pain to wait for the server to rotate and post back the image - in case you want an arbitrary angle. So I made myself a script, that allows you to rotate, zoom and reposition the image in realtime, then after you finish, you can crop the picture.
here it is: http://kroppr.rborn.info
Asvin,
I never thanked you for replying to my earlier post… Thank you! It was very helpful. Everything is working really well.
Now I have a new question: I would like to give user’s the ability to crop an image that is already stored on the server.
Here’s my methodology:
1. Bypass “uploader” object.
2. Add ” to the page.
3. Initiate “photoshop” object.
4. (Continue as normal)
I’m just not sure how to initiate the “photoshop” object. Should I use an “OnLoad” event?
Thanks again!
(the code that I included in Step 2 in the last comment was scrubbed… Here is the comment again)
Asvin,
I never thanked you for replying to my earlier post… Thank you! It was very helpful. Everything is working really well.
Now I have a new question: I would like to give user’s the ability to crop an image that is already stored on the server.
Here’s my methodology:
1. Bypass “uploader” object.
2. Add the image and what would have been JSON data for the image directly into the HTML.
3. Initiate “photoshop” object.
4. (Continue as normal)
I’m just not sure how to initiate the “photoshop” object. Should I use an “OnLoad” event?
Thanks again!
Asvin,
Okay… so I think I just answered my own question and I have it working the way I want. Thanks :)