Mashup Application : Image Uploader + Cropper using jQuery + PHP
Learn how to create an Image uploader + Cropper using JQuery and PHP.
Its been a week since WDC was launched, and people have been asking me, where are the mashups ?? So today, I would like to introduce to you the first mashup here at WDC Image Uploader + Cropper using jQuery,PHP
First, for people who don`t know what Mashups are
In web development, a mashup is a web page or application that combines data or functionality from two or more external sources to create a new service.
- Wikipedia
Introduction
So now that you know what Mashups are, this tutorial is going to guide you in creating a complete application. You must have followed many tutorials to help you upload files using PHP or AJAX, or must have followed tutorials to crop an image. Now we combine both of these elements to create one complete application, an Image Uploader + Cropper
Now there are 2 variants in this, i.e
- A normal Image cropper. An image is uploaded, then a portion of image can be cropped. (this tutorial helps you get this result)
- A Fixed Image Cropper with Preview. An Image is uploaded, then any area of the image selected will be cropped and resized to a fixed size (in our demo it is 200px)
Pre-Requistes
- Basic Knowledge in PHP
- Basic HTML Knowledge
- A little experience with jQuery
Mashup Result
We will we be using ?
- jQuery Library – Website
- JCrop Plugin for jQuery (to do the cropping) – Website
- Ajax Upload Plugin for jQuery (to help us upload an image)
We will we be doing ?
- Create directory structure and the files for our mashup
- Create HTML and include all our Javascript libraries
- Create HTML Upload Form
- Write Javascript to perform Upload
- Write PHP function to upload Image
- Make Image Selectable
- Create HTML Cropping Form
- Write Javascript to do teh cropping
- Write PHP function to crop Image
- Complete Code of
index.phpandfunctions.php
1. Create directory structure and the files for our mashup

Directory Strcuture of our Mashup
Okay, as you can see from the image, this is our directory structure.
assets contains the css + required images for the cropper
js contains jQuery, jCrop and ajaxfileupload
uploads will hold our uploaded image files
2 main files in the root viz
functions.php – which contains our upload and crop function
index.php – which contains our HTML interface and all Javascript functions.
2. Create HTML and include all our Javascript libraries
As the previous step stated, our interface file is index.php, so all our HTML content will go inside it. Use your favourite text editor (I use Dreamweaver and more recently Netbeans IDE), create an empty file and add all the HTML content inside it.
In the following code, you will notice that I have allocated space for our interface. I have written comments as to which block does what. In the coming steps we will be filling up these areas with code.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Upload Crop</title>
<link rel="stylesheet" href="assets/jcrop.css" type="text/css" />
<script src="js/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="js/jquery.Jcrop.js"></script>
<script type="text/javascript" src="js/ajaxfileupload.js"></script>
<script type="text/javascript"> // our javascript functions </script>
<style>
body { margin:0; padding:0; font-family:Tahoma, Geneva, sans-serif }
#content { width:500px; margin:3em auto; border:3px solid #ccc; padding:1em; text-align:center; }
#image { text-align:center;}
#content form input,button { font-size:18px; font-family:Tahoma, Geneva, sans-serif }
#crop_preview { display:none; overflow:hidden; border:2px solid #ccc; }
</style>
</head>
<body>
<div id="content">
<img id="loading" src="assets/loading.gif" style="display:none;">
<div id="crop_preview"><!-- after cropping, show final result --></div>
<div id="image" style="display:none;">
<!-- after upload, show image and crop button -->
</div>
<div id="upload"> <!-- upload form --> </div>
</div>
</body>
</html>
3. Create HTML Upload Form
Okay, once we have our basic HTML ready, its time to create our upload form. Its pretty straightforward. Since we will be using AJAX uploading (not actually AJAX), the variables in the form are very important.
Just replace the <div id="upload"> <!-- upload form --> </div> with the following form
<!-- upload form --> <div id="upload"> <form id="form1" action="" method="post" enctype="multipart/form-data"> <input type="file" name="file" id="file" /> <input type="button" id="buttonUpload" value="Upload Image" onClick="return ajaxFileUpload();" /> </form> </div>
If you noticed <input type="button" id="buttonUpload" value="Upload Image" onClick="return ajaxFileUpload();" />, this means that when the button is clicked, a javascript function ajaxFileUpload() will be called.
4. Write Javascript to perform Upload
Now since in the above step, we have written a call to a javascript function when the upload button is clicked, so lets we write the ajaxFileUpload() javascript function.
function ajaxFileUpload()
{
//shows/hides the ajax loading image while requests are being made
$("#loading").ajaxStart(function(){
$(this).show();
}).ajaxComplete(function(){
$(this).hide();
});
$.ajaxFileUpload
(
{
url:'functions.php?action=upload', //our url
secureuri:false,
fileElementId:'file', //input form id ?
dataType: 'json', //retrieves json type data from php
success: function (data, status) {
//if error
if(typeof(data.error) != 'undefined') {
alert(data.error);
//if no error
} else {
//show the image once upload is complete.
$("#image").append($(document.createElement("img")).attr({src: "uploads/"+data.msg,id:"jcrop"})).show(); // create image and append the html inside <div id=#image>
//hide the upload form once upload is complete
$("#upload").slideUp();
}
}
}
)
return false;
}
The above code, is pretty straightforward,
- Request is made to
functions.php?action=upload(which we will create in the next step) - once upload is complete, the php function will return the filename to javascript in JSON format (
data.msg), on success, the javascript will show the image by creating an<img>and hiding the existing upload form.
5. Write PHP function to upload Image
Lets create our functions file and name it functions.php. We will be using the switch function to differentiate between our 2 functions.
The 2 functions in this file are,
- upload
- crop
Using $action = $_GET['action']; will return upload for the following URL = functions.php?action=upload.
Similarly for URL = functions.php?action=crop. $action = $_GET['action']; will return crop
<?php
$action = $_GET['action'];
switch($action) {
case 'upload':
$upload_name = "file"; //id of the file input in the form
$max_file_size_in_bytes = 1024*1024; //max size 1MB
$extension_whitelist = array("jpg", "gif", "png"); //allows only jpg, gif, png
/* checking extensions */
$path_info = pathinfo($_FILES[$upload_name]['name']);
$file_extension = $path_info["extension"];
$is_valid_extension = false;
foreach ($extension_whitelist as $extension) {
if (strcasecmp($file_extension, $extension) == 0) {
$is_valid_extension = true;
break;
}
}
if (!$is_valid_extension) {
echo "{";
echo "error: 'Extension not valid'\n";
echo "}";
exit(0);
}
/* file size check */
$file_size = @filesize($_FILES[$upload_name]["tmp_name"]);
if (!$file_size || $file_size > $max_file_size_in_bytes) {
echo "{";
echo "error: 'File Exceeds maximum limit'\n";
echo "}";
exit(0);
}
if(isset($_FILES[$upload_name]))
if ($_FILES[$upload_name]["error"] > 0) {
echo "Error: " . $_FILES["file"]["error"] . "<br />";
} else {
$userfile = stripslashes($_FILES[$upload_name]['name']);
$file_size = $_FILES[$upload_name]['size'];
$file_temp = $_FILES[$upload_name]['tmp_name'];
$file_type = $_FILES[$upload_name]["type"];
$file_err = $_FILES[$upload_name]['error'];
$file_name = $userfile;
if(move_uploaded_file($file_temp, "uploads/".$file_name)) {
echo "{";
echo "msg: '".$file_name."'\n";
echo "}";
}
}
break;
case 'crop':
// will write a function later
break;
}
?>
BREAK !
Now try out the application. If you have coded properly, you will be able to upload an image and when successful, the image will be displayed. Now we have to write the cropping functions, so we can crop out parts from this image.
6. Make Image Selectable
Now since we have a working upload form, we can goto our next important step. Enabling the uploaded image to be croppable !
- JCrop allows you to make an image croppable by using this simple syntax
$(image selector).Jcrop(); - In our case we will invoke JCrop using
$("#jcrop").Jcrop();wherejcropis the id of our image.
So obviously, jCrop needs to be invoked after the image is uploaded and displayed, so lets go back to our ajaxFileUpload() function. As you know, this function uploads the image and when successful, creates an <img> with id=jcrop and displays it.
Thus we will add the JCrop invokation for our uploaded image. This is how ajaxFileUpload() looks after adding the jCrop invokation.
function ajaxFileUpload()
{
//shows/hides the ajax loading image while requests are being made
$("#loading").ajaxStart(function(){
$(this).show();
}).ajaxComplete(function(){
$(this).hide();
});
$.ajaxFileUpload
(
{
url:'functions.php?action=upload', //our url,
secureuri:false,
fileElementId:'file', //input form id ?,
dataType: 'json', //retrieves json type data from php
success: function (data, status) {
//if error
if(typeof(data.error) != 'undefined') {
alert(data.error);
//if no error
} else {
//show the image once upload is complete.
$("#image").append($(document.createElement("img")).attr({src: "uploads/"+data.msg,id:"jcrop"})).show(); // create image and append the html inside <div id=#image>
/**************/
$("#jcrop").JCrop();
/**************/
//hide the upload form once upload is complete
$("#upload").slideUp();
}
}
}
)
return false;
}
Now If you try the mashup, you will notcie that, you can select an area around the image.
Obviously, we can`t crop anything yet, since we don`t have a Crop button to do our job, so our next step would be to add a Crop button.
7. Create HTML Cropping Form
Just add the following form inside <div id="image">
<div id="image" style="display:none;"> <!-- after upload, show image and crop button --> <form action="" method="post" id="crop_details"> <input type="hidden" id="x" name="x" /> <input type="hidden" id="y" name="y" /> <input type="hidden" id="w" name="w" /> <input type="hidden" id="h" name="h" /> <input type="hidden" id="fname" name="fname" /> <input type="button" value="Crop Image" onclick="return crop();" /> </form> </div>
The form contains a “Crop Image” button along with 5 hidden inputs.
These 5 hidden types contain
- x = x1,y1 co-ordinate of selection
- y = x2,y2 co-ordinate of selection
- w = width of selection
- h = height of selection
- fname = filename of image
Why do we require these values ?? for the php function ofcourse. We will be using PHP image functions to cut a portion of the original image, so we require the above variables, thus we have put it in the form.
- The above values will be written by a javascript function called
updateCoords(c)as the user makes a selection on the image. When a user is selecting a part of an image, JCrop sends the x,y,w,h information “if required” to another function. This function will beupdateCoords(c) - In short
updateCoords(c)will retrieve co-ordinates from jCrop and write em to the form hidden inputs to be given to our php function.
When the “Crop Image” button is clicked, an AJAX call will be made to functions.php?action=crop. This AJAX function will be written inside crop(), thus
<input onclick="return crop();" type="button" value="Crop Image" />
8. Write Javascript to do perform the cropping
There are 3 parts in this step.
-
First write javacript for updateCoords(c)
Add this function below
funtion ajaxFileUpload() { }function updateCoords(c) { $('#x').val(c.x); $('#y').val(c.y); $('#w').val(c.w); $('#h').val(c.h); } -
Inform jCrop about updateCoords(c)
Go back to
ajaxFileUpload()and replace$("#jcrop").Jcrop();with the following$("#jcrop").Jcrop({ onChange: updateCoords, onSelect: updateCoords, aspectRatio: 1, boxWidth: 475 //maximum width of image }); -
Write AJAX function crop()
This function will make a AJAX call to
functions.php?action=cropwith the form values and returns the cropped image.
Add the following function belowfuntion updateCoords() { }/* * function crop() * ajax function which returns the cropped image */ function crop() { $.ajax({ type: "POST", url:"functions.php?action=crop", data: {x: $('#x').val(),y: $('#y').val(),w: $('#w').val(),h: $('#h').val(),fname:$('#fname').val(),size:200}, success: function(msg){ $("#crop_preview").html($(document.createElement("img")).attr("src","crop.jpg")).show(); $("#crop_preview").after("Here is your Cropped Image ").show(); $("#image").slideUp(); } }); }
9. Write PHP function to crop Image
We have got the cropper form ready, along with the AJAX call. Now the only thing left is to write the respective crop PHP function.
Open up functions.php and edit our case 'crop'
case 'crop':
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$jpeg_quality = 90;
$src = "uploads/".$_POST['fname'];
$img_r = imagecreatefromjpeg($src);
$targ_w = $targ_h = $_POST['size'];
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );
imagecopyresampled($dst_r,$img_r,0,0,$_POST['x'],$_POST['y'],
$targ_w,$targ_h,$_POST['w'],$_POST['h']);
imagejpeg($dst_r,"crop.jpg",$jpeg_quality);
unlink($src); //deletes source after upload
echo 1;
}
break;
10. Complete Code of index.php and functions.php
index.php
Upload Crop
<script src="js/jquery-1.3.2.min.js" type="text/javascript"></script> <script src="js/jquery.Jcrop.js"></script>
<script src="js/ajaxfileupload.js" type="text/javascript"></script> <script type="text/javascript">// <![CDATA[
// our javascript functions
function ajaxFileUpload()
{
//shows/hides the ajax loading image while requests are being made
$("#loading").ajaxStart(function(){
$(this).show();
}).ajaxComplete(function(){
$(this).hide();
});
$.ajaxFileUpload
(
{
url:'functions.php?action=upload', //our url,
secureuri:false,
fileElementId:'file', //input form id ?,
dataType: 'json', //retrieves json type data from php
success: function (data, status) {
//if error
if(typeof(data.error) != 'undefined') {
alert(data.error);
//if no error
} else {
//show the image once upload is complete.
$("#image").append($(document.createElement("img")).attr({src: "uploads/"+data.msg,id:"jcrop"})).show(); // create image and append the html inside
<div id=#image>
/**************/
$("#jcrop").Jcrop({
onChange: updateCoords,
onSelect: updateCoords,
aspectRatio: 1,
boxWidth: 475 //maximum width of image
});
/**************/
//hide the upload form once upload is complete
$("#upload").slideUp();
}
}
}
)
return false;
}
function updateCoords(c) {
$('#x').val(c.x);
$('#y').val(c.y);
$('#w').val(c.w);
$('#h').val(c.h);
}
/*
* function crop()
* ajax function which returns the cropped image
*/
function crop() {
$.ajax({
type: "POST",
url:"functions.php?action=crop",
data: {x: $('#x').val(),y: $('#y').val(),w: $('#w').val(),h: $('#h').val(),fname:$('#fname').val(),size:200},
success: function(msg){
$("#crop_preview").html($(document.createElement("img")).attr("src","crop.jpg")).show();
$("#crop_preview").after("Here is your Cropped Image ").show();
$("#image").slideUp();
}
});
}
// ]]></script>
<!--
body { margin:0; padding:0; font-family:Tahoma, Geneva, sans-serif }
#content { width:500px; margin:3em auto; border:3px solid #ccc; padding:1em; text-align:center; }
#image { text-align:center;}
#content form input,button { font-size:18px; font-family:Tahoma, Geneva, sans-serif }
#crop_preview { display:none; overflow:hidden; border:2px solid #ccc; }
-->
<div id="content">
<img id="loading" style="display:none;" src="assets/loading.gif" alt="" />
<div id="crop_preview"><!-- after cropping, show final result --></div>
<div id="image" style="display:none;"><!-- after upload, show image and crop button -->
<form id="crop_details" method="post"> <input id="x" name="x" type="hidden" /> <input id="y" name="y" type="hidden" /> <input id="w" name="w" type="hidden" /> <input id="h" name="h" type="hidden" /> <input id="fname" name="fname" type="hidden" /> <input onclick="return crop();" type="button" value="Crop Image" /> </form></div>
<!-- upload form -->
<div id="upload"><form id="form1" enctype="multipart/form-data" method="post"> <input id="file" name="file" type="file" /> <input id="buttonUpload" onclick="return ajaxFileUpload();" type="button" value="Upload Image" /> </form></div>
</div>
functions.php
<?php
$action = $_GET['action'];
switch($action) {
case 'upload':
$upload_name = "file";
$max_file_size_in_bytes = 1024*1024;
$extension_whitelist = array("jpg", "gif", "png");
/* checking extensions */
$path_info = pathinfo($_FILES[$upload_name]['name']);
$file_extension = $path_info["extension"];
$is_valid_extension = false;
foreach ($extension_whitelist as $extension) {
if (strcasecmp($file_extension, $extension) == 0) {
$is_valid_extension = true;
break;
}
}
if (!$is_valid_extension) {
echo "{";
echo "error: 'Extension not valid'\n";
echo "}";
exit(0);
}
/* file size check */
$file_size = @filesize($_FILES[$upload_name]["tmp_name"]);
if (!$file_size || $file_size > $max_file_size_in_bytes) {
echo "{";
echo "error: 'File Exceeds maximum limit'\n";
echo "}";
exit(0);
}
if(isset($_FILES[$upload_name]))
if ($_FILES[$upload_name]["error"] > 0) {
echo "Error: " . $_FILES["file"]["error"] . "<br />";
} else {
$userfile = stripslashes($_FILES[$upload_name]['name']);
$file_size = $_FILES[$upload_name]['size'];
$file_temp = $_FILES[$upload_name]['tmp_name'];
$file_type = $_FILES[$upload_name]["type"];
$file_err = $_FILES[$upload_name]['error'];
$file_name = $userfile;
if(move_uploaded_file($file_temp, "uploads/".$file_name)) {
echo "{";
echo "msg: '".$file_name."'\n";
echo "}";
}
}
break;
case 'crop':
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$jpeg_quality = 90;
$src = "uploads/".$_POST['fname'];
$img_r = imagecreatefromjpeg($src);
if($_POST['fixed'] == 0) {
$targ_w = $_POST['w'];
$targ_h = $_POST['h'];
}
else {
$targ_w = $targ_h = $_POST['size'];
}
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );
imagecopyresampled($dst_r,$img_r,0,0,$_POST['x'],$_POST['y'],
$targ_w,$targ_h,$_POST['w'],$_POST['h']);
imagejpeg($dst_r,"crop.jpg",$jpeg_quality);
unlink($src);
echo 1;
}
break;
}
Conclusion
I hope you guys liked this tutorial. I have`nt gone much deep into PHP image functions, how to AJAX in jquery etc. I am assuming you have a fair idea abotu all of this. As always, if you have any questions, post em here

















Hi, I found the solution to the Gif and Png problem. I simply detect the extension of the image being passed and use the necessary Php function to create from i.e. Gif -> $img_r=imagecreatefromgif($src); Png -> $img_r=imagecreatefrompng($src);
Hi,
Great effort to combine 2 scripts together! But unfortunately, the above doesn't work with Wordpress. Any idea how to implement it on WP?
Hi,
Great post! Has a solution been found to the problem of uploading and cropping .Gif and .Png files? I get a black image output when cropping these image formats.
Thanks
Is it possible to accept none fixed crop sizes and display a preview
Great post! BTW, I notice the downloaded code has a bug. I've set maximum file size limit to 4MB and now whenever I upload >2MB image, I won't be able to crop and save the image file into the designated folder. Could you please help?
Hey,
That shouldn`t be a problem, if you lemme know what exactly is happening, I might be able to help.
Regards
Hey. Great examples! I was actually hoping to implement the "Fixed Image Cropper with Preview" that you had as part of the demo, but it doesn't download as part of the package, and you don't really cover it in the tutorial. Could you post an example script for download, or give us some more info on how to do it?
Thanks!
Sam
Hello Sam,
Thanks for your comments, oops my bad,
Please open up 1.php from the download and search for
var fixed = 0;
var size = 200;
Just make fixed = 1 (for fixed image cropper with Preview) i.e
var fixed = 1; //whether to enable fixed size or not
var size = 200; //size of the preview