Image Upload and Cropping with PHP and Jquery
Wall Script
Wall Script
Monday, June 27, 2011

Image Upload and Cropping with PHP and Jquery

Image cropping is the most important and required part in social media projects. In this post my friend Arun Kumar Shekar had implemented image cropping functionalities such as upload image file into physical location, cropping image using jquery and resizing image into small resolution. Hope you like this thanks!

Image Upload and Cropping with PHP and Jquery


Download Script     Live Demo

Developer
Arun Kumar Shekar
Arun Kumar Shekar
Engineer
Chennai, INDIA

Sample database design for Users.

Users
Contains user details username, password, email, profile_image and profile_image_small etc.
CREATE TABLE `users` (
`uid` int(11) AUTO_INCREMENT PRIMARY KEY,
`username` varchar(255) UNIQUE KEY,
`password` varchar(100),
`email` varchar(255) UNIQUE KEY,
`profile_image` varchar(200),
`profile_image_small` varchar(200),
)

index.php
Contains PHP code uploading image into uploads folder physical location and image path updating in users table set profile_image.
<?php
include('db.php');
session_start();
$session_id=$_SESSION['user'];//  Session ID
$path = "uploads/";
$valid_formats = array("jpg", "png", "gif", "bmp");
if(isset($_POST['submit']))
{
$name = $_FILES['photoimg']['name'];
$size = $_FILES['photoimg']['size'];
if(strlen($name))
{
list($txt, $ext) = explode(".", $name);
if(in_array($ext,$valid_formats) && $size<(250*1024))
{
$actual_image_name = time().substr($txt, 5).".".$ext;
$tmp = $_FILES['photoimg']['tmp_name'];
if(move_uploaded_file($tmp, $path.$actual_image_name))
{
mysql_query("UPDATE users SET profile_image='$actual_image_name' WHERE uid='$session_id'");
$image="<h1>Please drag on the image</h1><img src='uploads/".$actual_image_name."' id=\"photo\" ";
}
else
echo "failed";
}
else
echo "Invalid file formats..!";
}
else
echo "Please select image..!";
}
?>
//HTML Body
<?php echo $image; ?>
<div id="thumbs" ></div>
<div >
<form id="cropimage" method="post" enctype="multipart/form-data">
Upload your image <input type="file" name="photoimg" id="photoimg" />
<input type="hidden" name="image_name" id="image_name" value="<?php echo($actual_image_name)?>" />
<input type="submit" name="submit" value="Submit" /> 
</form>

Javascript
$(“img#photo”).imgAreaSelect() - here photo is the ID name of image block and calling imgAreaSelect function for cropping image.
<script type="text/javascript" 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>
<script type="text/javascript">
function getSizes(im,obj)
{
var x_axis = obj.x1;
var x2_axis = obj.x2;
var y_axis = obj.y1;
var y2_axis = obj.y2;
var thumb_width = obj.width;
var thumb_height = obj.height;
if(thumb_width > 0)
{
if(confirm("Do you want to save image..!"))
{
$.ajax({
type:"GET",
url:"ajax_image.php?t=ajax&img="+$("#image_name").val()+"&w="+
thumb_width+"&h="+thumb_height+"&x1="+x_axis+"&y1="+y_axis,
cache:false,
success:function(rsponse)
{
$("#cropimage").hide();
$("#thumbs").html("");
$("#thumbs").html("<img src='uploads/"+rsponse+"' />");
}
});
}
}
else
alert("Please select portion..!");
}
$(document).ready(function ()
{
$('img#photo').imgAreaSelect({
aspectRatio: '1:1',
onSelectEnd: getSizes
});
});
</script>

ajax_image.php
Contains simple PHP code, resizing cropped image into 100 x 100 pixel and updating into users table profile_image_small.
<?php
include('db.php');
session_start();
$session_id=$_SESSION['user']; // Or Session ID
$t_width = 100; // Maximum thumbnail width
$t_height = 100; // Maximum thumbnail height
$new_name = "small".$session_id.".jpg"; // Thumbnail image name
$path = "uploads/";
if(isset($_GET['t']) and $_GET['t'] == "ajax")
{
extract($_GET);
$ratio = ($t_width/$w);
$nw = ceil($w * $ratio);
$nh = ceil($h * $ratio);
$nimg = imagecreatetruecolor($nw,$nh);
$im_src = imagecreatefromjpeg($path.$img);
imagecopyresampled($nimg,$im_src,0,0,$x1,$y1,$nw,$nh,$w,$h);
imagejpeg($nimg,$path.$new_name,90);
mysql_query("UPDATE users SET profile_image_small='$new_name' WHERE uid='$session_id'");
echo $new_name."?".time();
exit;
}
?>

db.php
PHP database configuration file
<?php
$mysql_hostname = "Host name";
$mysql_user = "UserName";
$mysql_password = "Password";
$mysql_database = "Database Name";
$bd = mysql_connect($mysql_hostname, $mysql_user, $mysql_password) or die("Could not connect database");
mysql_select_db($mysql_database, $bd) or die("Could not select database");
?>
web notification

97 comments:

  1. Sir, the save view is not showing the exact zone of selected image from the preview...

    ReplyDelete
  2. This image crop is in aspect ratio. can it be dragged without it, like facebook ?

    ReplyDelete
  3. Hi Arun, Demo not working! Please rectify the issues! Seeing forward ... Regards

    ReplyDelete
  4. Hi Arun,

    Nice article. It's working fine.

    ReplyDelete
  5. Hi man, good job ever!
    But Have you seen how the orkut.com (tag photo) works?
    It's pretty nice.
    Could be the next live demo!!
    thnks!!

    ReplyDelete
  6. hi Arun!

    good start, All the best

    ReplyDelete
  7. Hey!!! Arun, Good job...

    ReplyDelete
  8. Hey good work... but a small issue... without any data in the users table, you are writing update query. It should be rectified.

    ReplyDelete
  9. Good job, but the cropped image is not showing the exact zone of selected image from the preview.

    ReplyDelete
  10. Mr. Tamada, good job. The demo doesn´t work. I downloaded the script and run it in localhost, work very well, but Why make a users database if the scripts doen't save anything in it?
    Thank you very much.

    ReplyDelete
  11. Doesn't work in Firefox, opera...
    Only works by me in Internet Explorer.

    ReplyDelete
  12. You might want to consider indenting some of your code.

    ReplyDelete
  13. Doenst work in Firefox :(

    ReplyDelete
  14. Hi Srinivas,
    The cropping is not working fine. The saved image is not what we have selected.

    ReplyDelete
  15. very good script.
    I want to make 3 different height & width thumbnails and also want to show 3 previews.
    How this can be possible.

    ReplyDelete
  16. thanks for a script….i want the default selection on image…like when i upload an image, the script will automatically show a selection area on image…any idea how to do that

    ReplyDelete
  17. thanks for the script it's useful for me..

    ReplyDelete
  18. I wrote a script similar to this some time ago and found that if you don't limit the maximum number of pixels an image can be you'll be sorry. That or get a high memory server and really bump your php memory limit. You can upload a file that's small in file size but it's the pixel count that will get you when you least suspect it.

    ReplyDelete
  19. I tested it but following error occur:
    function.imagecreatefromjpeg]: gd-jpeg: JPEG library reports unrecoverable error: in /home/kokkoroc/public_html/demos/cropimages/ajax_image.php on line 14

    Warning: imagecreatefromjpeg() [function.imagecreatefromjpeg]: 'uploads/1309450594-pic.png' is not a valid JPEG file in /home/kokkoroc/public_html/demos/cropimages/ajax_image.php on line 14

    Warning: imagecopyresampled(): supplied argument is not a valid Image resource in /home/kokkoroc/public_html/demos/cropimages/ajax_image.php on line 15
    Sajid.jpg?1309450637' />

    ReplyDelete
  20. I got an error when upload a .jpg file.

    Invalid file formats..!

    ReplyDelete
  21. The Demo is working but i have one suggestion please check your jquery code its bug. Whenevaer you crope the image then its save wrong selection. Means to say it selects but wrong portion you can try. There is the problem in croping. But good work.

    Malik Junaid Arshad Khokhar (Software Engineer)

    ReplyDelete
  22. I just don't know why everybody is complaining. I am using firefox and this Sh**t is working and is very nice.

    Thanks to you man. That's great. You indian are genious. Maybe i should become indian too. Lol

    ReplyDelete
  23. @Kressly Thanks man! this is fantastic comment.

    ReplyDelete
  24. How would I limit the crop selection to 32px by 32px ?

    ReplyDelete
  25. Change this in ajax_image.php:
    $t_width = 100; // Maximum thumbnail width
    $t_height = 100; // Maximum thumbnail height

    ReplyDelete
  26. does anyone know how to get the right selection working? and how to take away the popup and make it a button to say "Save image"?? any help would be greatly appreciated

    ReplyDelete
  27. not working in opera

    ReplyDelete
  28. Hi Arun and Srinivas.

    this is nice and superb tutorial. I have successfully implemented this crop option for my new site. and its working perfectly.. i really like it.

    when i tested with different images with high and low resolutions it save a wrong selection then i figure out.. its because, there is max-width has given on the image so the images. should be resized to that much or increase max width. then it works perfectly.. finally i have integrated. PhpTHumb v.5 to resize to 900px width if users are uploading higher images. problem solves. its fantastic..

    thank you.

    ReplyDelete
  29. One question,can we use these scripts in commercial projects without let them know from where i got this.

    ReplyDelete
  30. I uploaded an image and cropping isn't working properly, I'm trying to cover face and it's showing hair portion, you can check it yourself.

    I uploaded this picture :- http://demos.9lessons.info/cropimages/uploads/1314066181led-2.jpg

    ReplyDelete
  31. a lot of links are not working..

    ReplyDelete
  32. hi
    Great work, it help me very much

    ReplyDelete
  33. The code works if the original image has 500 pixels width. The problem comes when the original image is bigger or smaller than 500 because the coords of selection and the selection area are calculated under an image of 500 pixels width applied to a bigger or smaller image, thus the thumbnail fails to get the right area of selection.

    Also this is pointless, because it will always return 100:

    $t_width = 100; // Maximum thumbnail width
    $t_height = 100; // Maximum thumbnail height
    $ratio = ($t_width/$w);
    $nw = ceil($w * $ratio);
    $nh = ceil($h * $ratio);

    if $ratio = 100 / $w then $w = (100/$ratio) thus:

    $nw = (100/$ratio) * $ratio --> $nw = 100. I dont see the point of this.

    Also, i modified the code from ajax_iamge.php so it gets the right proportion and area of the image like this:

    list($ancho, $alto) = getimagesize($path.$img);
    $ratio = $ancho / 500;
    $x1 = ceil($x1 * $ratio);
    $y1 = ceil($y1 * $ratio);
    $w = ceil($w * $ratio);
    $h = ceil($h * $ratio);
    $nw = 100;
    $nh = 100;
    $nimg = imagecreatetruecolor($nw,$nh);
    $im_src = imagecreatefromjpeg($path.$img);
    $new_name = "small".$img;
    imagecopyresampled($nimg,$im_src,0,0,$x1,$y1,$nw,$nh,$w,$h);

    and the rest....

    The ratio is 500, because in the drag the image part it is set to 500:

    style='max-width:500px'

    hope it helps

    ReplyDelete
  34. Thanks to Paris Bello aka Pelos. Its helpfull..

    ReplyDelete
  35. When I crop an image that is not jpg it doesn't save the resized image, any ideas why this could be happening? Thanks!

    ReplyDelete
  36. About the extensions:
    Instead of just having:
    $im_src = imagecreatefromjpeg($path.$img);

    You need to add have something like this:
    switch($extension){
    case 'bmp': $im_src = imagecreatefromwbmp($path.$img); break;
    case 'gif': $im_src = imagecreatefromgif($path.$img); break;
    case 'jpg': $im_src = imagecreatefromjpeg($path.$img); break;
    case 'png': $im_src = imagecreatefrompng($path.$img); break;
    default : return "Unsupported picture type!";
    }

    Of curse, you will need to send the extension parameter thrugh the URL, something like this:
    url:"ajax_image.php?t=ajax&img="+$("#image_name").val()+"&extension="+extFile+"&w="+thumb_width+"&h="+thumb_height+"&x1="+x_axis+"&y1="+y_axis,

    ReplyDelete
  37. after crop the image saved..but i want to crop the image number of times..all crops the image parts saved into only one frame..

    ReplyDelete
  38. i am crop the image no.of times..but image is saved only 1time..i want 2 saved the all crops image parts saved into one framework..

    ReplyDelete
  39. in my case the png image can't be uploaded
    pls help

    ReplyDelete
  40. Hi Arun,

    Please help me for jquery image upload, I want upload multiple files in my root directory and saved in the database all file names.

    Please help for this task

    ReplyDelete
  41. owesome script, but how do i get it to save only the resized/thumbnail...not saving the original imageas well.

    ReplyDelete
  42. Really awsm man .........

    9 lessons roxx !!

    ReplyDelete
  43. Thanks alot Paris Bello aka Pelos and Arun.

    ReplyDelete
  44. Dude it is absolutely right…..
    but it isnt working when i try to crop a PNG or a BMP image
    we may use the function imagecreatefrompng() for PNG image
    but what about BMP and GIF images ???
    Please Look into matter and help me !!

    ReplyDelete
  45. Thank you dear :)

    ReplyDelete
  46. Its buggy.In slection, in cropping ...both.

    ReplyDelete
  47. nice script.........

    ReplyDelete
  48. this croppping work perfectly.. but it works only with square shape... i need it in rectangle also???????

    ReplyDelete
  49. oh great i found solution and its very simple

    aspectRatio: '1:2,1:1'

    ReplyDelete
  50. the cropped image is not showing the exact zone of selected image from the preview. will you tell me why it happening.

    ReplyDelete
  51. hi please send me mail

    "the cropped image is not showing the exact zone of selected image from the preview. "

    why its happening

    ReplyDelete
  52. i find the problem that is due the width define in script 500px now problem is after saving thumb image it selected default area can we do some thing like show selected area.

    ReplyDelete
  53. hi arun.u did good job.

    ReplyDelete
  54. Your script is not cropping png files.. its just operating jpg files..

    ReplyDelete
  55. awesome stuff, but how can i upload the image without refreshing the screen?

    ReplyDelete
  56. this tutorial is great.. its so complex but after i looking this tutorial i can understand about it although ittle bite... thanx dude you're so inovative

    ReplyDelete
  57. hi
    in try to modify a code. i want to :
    1. insert form(name,adresse and foto)
    2. after user upload her foto
    3. i want to resize it immediatly before submit
    please help me.
    thanks.

    ReplyDelete
  58. In the above sample code, I found this line:

    function getSizes(im,obj)

    Shouldn't that be:

    function getSizes(img,obj)

    ReplyDelete
  59. where is the file
    scripts/jquery.imgareaselect.pack.js

    ReplyDelete
  60. please i need the login code from this script above

    ReplyDelete
  61. THere is small syntax error in .php

    see: $image="<img src='uploads/".$actual_image_name."' id=\"photo\" ";

    It's not closed.

    If it is not working for someone then please make sure you are using right path. Use $_SERVER['DOCUMENT_ROOT']


    Enjoy.

    Thanks
    Shubham Monga

    ReplyDelete
  62. The alert is pretty annoying, it's not working in my side, it allow me to select which part to crap but only the alert display nothing else, weird.

    Update the code please to make this even 90% working.

    ReplyDelete
  63. session id -- confuse plase explain me

    ReplyDelete
  64. Thanks, Paris Bello aka Pelos its amazing the updated code really works...
    thumps up man.

    ReplyDelete
  65. Hi,

    I am using jquery 1.2.6 is your crop functionality is working on this version.

    ReplyDelete
  66. Using Paris Bello's fix above with the following changes will resolve the issue of the thumbnail not being the correct selected area for images smaller than the set max-width.

    1. Obtain image height
    The code is set to restrict the max-width:500px so to account for images smaller than 500px wide you must obtain the image's width. Inside the getSizes() function add a variable set to the images width:

    var img_width = $('img#photo').width();

    Then pass this variable as a parameter in the ajax call:

    url:"cropimages/ajax_image.php?t=ajax&img="+$("#image_name").val()+"&w="+thumb_width+"&h="+thumb_height+"&x1="+x_axis+"&y1="+y_axis+"&ow="+img_width

    Now in the ajax_image.php code, change the ratio variable to use the image width you've now passed:

    $ratio = $ancho / $ow;

    Hope this helps and save you some time.

    ReplyDelete
  67. I've also resolved the issue with uploading files with any periods in the file name.

    For example, if a image is named 1234.567.jpg the code will not grab the extension properly through the explode method currently being used. I changed the code to instead grab the extension using pathinfo().

    $txt = explode(".", $name);
    $ext = pathinfo($name, PATHINFO_EXTENSION);
    if(in_array($ext,$valid_formats) && $size<(1024*1024)){
    $actual_image_name = $userid.time().substr($txt[0], 5).".".$ext;

    ReplyDelete
  68. every time check confirm function thats good but confirm function is not good

    ReplyDelete
  69. 981 px width 400px height for cropping What should I do.

    ReplyDelete
  70. Works gr8 .. thnx

    ReplyDelete
  71. how to select image store in my system php coding please give me

    ReplyDelete
  72. I guess there a something wrong in the thum crop position

    ReplyDelete
  73. nice code.helped ma a lot

    ReplyDelete
  74. for those who are having a problem regarding in preview just erase the max-width in the line 70 and it will works fine :)

    ReplyDelete
  75. Nice! Thank you for this very helpful all of the ideas :)

    ReplyDelete
  76. Anyone having problems with generating a thumbnail for a very small image? Hope this fill help:

    if ($ancho <= 500 )
    $ratio = $ancho / 500;

    if ($ancho <= 400 )
    $ratio = $ancho / 400;

    if ($ancho < 300 )
    $ratio = $ancho / 300;

    if ($ancho <= 200 )
    $ratio = $ancho / 200;

    if ($ancho >= 100 )
    $ratio = $ancho / 150;

    By the way using Paris Bello fix.

    ReplyDelete
  77. ****UPDATE*****
    Found a better solution for the aspect ratio not showing what it selects, use this instead

    if ($ancho > 500 )
    $ratio = $ancho / 500;
    else
    $ratio = $_POST['w'] / $_POST['h'];


    Just divide the posted Width with the Posted Jeight and use it as ratio. If Width is larger than 500 use 500 aspect ratio as default.

    ReplyDelete
  78. NIce article arun but problem is that width and height same in cropping

    ReplyDelete
  79. Hi Arun
    Nice tutorial. It works great. But there is one issue.After we upload .png image and when we crop the output we get is a black image. Please suggest a solution for this
    Regards
    Prasanth Prem

    ReplyDelete
  80. Croping is not currect when diffrent resolution images are uploaded..

    ReplyDelete
  81. same problem is in jcrop plugin and imaareaselect plugin

    ReplyDelete
  82. terima kasih tutorialnya ... :)
    thanks

    ReplyDelete
  83. Nice tutorial but not object oriented.

    If you are looking for object wrapper to make your code simple, cleaner use below.

    https://github.com/cygnite/File/

    Tutorial link:

    http://goo.gl/UuhFFx

    thanks!

    ReplyDelete
  84. Please add code for upload an image and then crop it and then the cropped portion merge with a png image using php and javascript etc. to create a poster

    ReplyDelete
  85. Hey Geeks!

    Arun Kumar - great job. I would make some semi-major upgrades to your code to make it more practical. Especially when it comes to ratio issue discussed above and autosaving on select end.

    INDEX
    Declare vars outside getSizes() function in SCRIPT section
    var x_axis;
    var x2_axis;
    var y_axis;
    ...
    var thumb_height;

    function getSizes() ...
    -----

    INDEX-> GETSIZES()
    cut everything ( ->> if(thumbs_width>1 ... <<- ) after thumb_height = obj.height;
    and add: return x_axis, x2_axis, y_axis, y2_axis, thumb_width, thumb_height;

    INDEX-> DOCUMENT.READY -> ADD NEW FUNCTION.
    I've added button SAVE IMAGE under the form instead of autosaving with prompt message (this was kind of annoying)

    $('#saveimagebutton').click(function() {
    if(thumbs_width>1) ... // paste this section
    }

    + in AJAX URL you have to add extra wars x2, y2 in order to get rid of ratio problem further

    And now the grand finale
    AJAX_IMAGE.PHP

    Entire IF condition updated as below :
    {
    extract($_GET);
    list($width, $height) = getimagesize($path.$img);
    $final_width = 200; // define your final target width
    $final_height = 200; // define your final target height

    // getting actual selection size:

    if($x2>$x1) // if-condition because user can select area from left to right or opposite
    $source_width = $x2-$x1;
    else
    $source_width = $x1-$x2;

    if($y1>$y2) // if-condition because user can select area from left to right or opposite
    $source_height = $y1-$y2;
    else
    $source_height = $y2-$y1;

    $new_image = imagecreatetruecolor($source_width,$source_height); // create new image basing on thumbnail selection size
    $source_image = imagecreatefromjpeg($path.$img); // generate source image for cropping

    $new_name = "newimage.jpg";

    imagecopyresampled($new_image,$source_image,0,0,$x1,$y1,$source_width, $source_height, $source_width, $source_height); // copy real-size selection from the original image
    imagejpeg($new_image,$path.$new_name,100); // create thumb image
    imagejpeg(imagescale(imagecreatefromjpeg($path.$new_name), $final_width, $final_height, IMG_BICUBIC_FIXED), $path.$new_name, 100); // scale created image to final_width and final_height and replace it

    exit;
    }

    Hope it helps.

    Cheers,
    Pawel

    ReplyDelete

mailxengine Youtueb channel
Make in India
X