PHP & jQuery image upload and crop v1.1
Update
Due to popular demand, further updates have been made to this script, to allow upload of JPG, GIFs and PNG images! Same great functionality now even more useful.
Please note the old script is still available at PHP & jQuery image upload and crop.
If you are not familiar with the concept, it may be worth reading the old article first.
Fixes
- You can now upload different types of images, JPG, GIFs and PNG
- You can now upload images and have a random file name (this fixes the caching issue some of you have had)
- The image upload error check has been fixed (thanks to DevWooty)
As with the previous script, ensure you have the following:
- PHP 4 or Higher (It has been tested on Version 5)
- PHP GD Library
- jQuery ver 1.2.3 or Higher
- Image Area Select plugin by Michal Wojciechowski
Basic overview
1. We will be using the session variable to hold the random file name (in our case the timestamp).
We are now also storing the file extension that is passed through the script, to ensure we are dealing with the right type of image.
//only assign a new timestamp if the session variable is empty
if (strlen($_SESSION['random_key'])==0){
$_SESSION['random_key'] = strtotime(date('Y-m-d H:i:s')); //assign the timestamp to the session variable
$_SESSION['user_file_ext']= "";
}
NOTE: Once the thumbnail is created we set the session variable to equal nothing, this will then allow a new image to be uploaded along with a new name.
2. Capture, rename and resize the uploaded file.
The validation section has also been updated and been made more secure by checking the mime type as well as the image extension.
foreach ($allowed_image_types as $mime_type => $ext) {
//loop through the specified image types and if they match the extension then break out
//everything is ok so go and check file size
if($file_ext==$ext && $userfile_type==$mime_type){
$error = "";
break;
}else{
$error = "Only ".$image_ext." images accepted for upload";
}
}
//check if the file size is above the allowed limit
if ($userfile_size > ($max_file*1048576)) {
$error.= "Images must be under ".$max_file."MB in size";
}
3. Same as before, we grab the coordinates using the imgAreaSelect plugin and send the details to the server.
- x1, y1 = coordinates of the top left corner of the initial selection area
- x2, y2 = coordinates of the bottom right corner of the initial selection area
- width = crop selection width
- height = crop selection height
There are a number of options with this plugin which you can see using the link above. We opted for an aspect ratio of 1:1 (height and width of 100px) along with a preview of what we are actually going to crop.
NOTE: Using the php calculation below makes the script that much more dynamic, all you now have to do is set the height and width of your thumbnail and the script will calculate the ratio/preview sizes for you! (Thanks to Long for the tip.)
$(window).load(function () {
$("#thumbnail").imgAreaSelect({ aspectRatio: "1:thumb_height/thumb_width", onSelectChange: preview });
});
The preview function below, is run as soon as you create your selection. This places the right part of the image into the preview window. The second part of the function populates hidden fields which are later passed to the server.
function preview(img, selection) {
var scaleX = / selection.width;
var scaleY = / selection.height;
$('#thumbnail + div > img').css({
width: Math.round(scaleX * ) + 'px',
height: Math.round(scaleY * ) + 'px',
marginLeft: '-' + Math.round(scaleX * selection.x1) + 'px',
marginTop: '-' + Math.round(scaleY * selection.y1) + 'px'
});
$('#x1').val(selection.x1);
$('#y1').val(selection.y1);
$('#x2').val(selection.x2);
$('#y2').val(selection.y2);
$('#w').val(selection.width);
$('#h').val(selection.height);
}
This function is not really required, but helps by checking to see if the user has made a crop selection. In our case it is a required step. The form is submitted if the values exist, i.e. a selection has been made.
$(document).ready(function () {
$("#save_thumb").click(function() {
var x1 = $("#x1").val();
var y1 = $("#y1").val();
var x2 = $("#x2").val();
var y2 = $("#y2").val();
var w = $("#w").val();
var h = $("#h").val();
if(x1=="" || y1=="" || x2=="" || y2=="" || w=="" || h==""){
alert("You must make a selection first");
return false;
}else{
return true;
}
});
});
4. Finally it’s time to handle these new coordinates and generate our new cropped thumbnail.
if (isset($_POST["upload_thumbnail"])) {
//Get the new coordinates to crop the image.
$x1 = $_POST["x1"];
$y1 = $_POST["y1"];
$x2 = $_POST["x2"]; // not really required
$y2 = $_POST["y2"]; // not really required
$w = $_POST["w"];
$h = $_POST["h"];
//Scale the image to the 100px by 100px
$scale = $thumb_width/$w;
$cropped = resizeThumbnailImage($thumb_image_location, $large_image_location,$w,$h,$x1,$y1,$scale);
//Reload the page again to view the thumbnail
header("location:".$_SERVER["PHP_SELF"]);
exit();
}
Take a look at the demo and download a copy to see the full working code.
So far we have tested it in FireFox 2 and 3, Internet Explorer 6 and 7 and Safari 3.1.2 with pretty good results. The only issue we found was when uploading transparent gifs and pngs results in a black background.
The demo
Click here to see it in action
Download
Click here to download v1.2 [JPG, GIF, PNG]
Click here to download v1.1 [JPG ONLY]
Found this article useful? Did it save you time?
Tags: crop, gd, image, Jquery, PHP, upload
Blogsphere: TechnoratiFeedsterBloglines
Bookmark: Del.icio.usSpurlFurlSimpyBlinkDigg
RSS feed for comments on this post

Just wanna let you know that I’ve been working on a WordPress function and your previous script was a BIG help for me. I’ll be checking out this new one and see what I can improve on.
I thank you very much!
your script is so close to perfect for me. Can you help me take it one step further? Once the pic is uploaded and the user has selected the area they want to thumbnail, can you help me insert the ability to watermark it? (watermark will stay at 100 by 100 dimensions) Also, could I send the new filename into a mysql database? Please let me know how I can insert this into the script. Thanks
never mind, I got it. it was working but my png file was not saved in ‘indexed’ so it wasn’t working before.
Has anyone used this script in Konqueror (under Linux) ?
Michal’s Image Area Select plugin turns the large image black, and the crop are white during cropping.
@Dydream:
Please try the latest version (0.5.1), it should fix the problem.
@Michal we will include your updated version in the download
[...] By the way, remember the PHP image cropping tutorial I mentioned in my last post? WebMotionUK just published an updated version of it. [...]
this is perfekt work..!!!
Great work all round chaps. Looks like it will be extremely useful.
Just one thing that I ask in ignorance. I am trying to get the name of the file to be the same as the original filename. I have located the variable ($userfile_name = $_FILES['image']['name'];) but I can’t for the life of me work out where I need to insert it to make it work. Please could someone help out as I’m tearing out what little of my hair I have left!!
Many thanks in advance
@daemon & @nickstaw, thanks for the comments.
@nickstaw, you basically have to use the $large_image_location and set that to the original file name, however, you will need to pass this name throughout the script therefore saving the name of the original file in a session will do the trick.
Unfortunately it does not work all that well on google chrome, it uploads the image but does not go tot the crop image part.
hi, i tried to use it but after i load the image this is what i get “Fatal error: Call to undefined function: image_type_to_mime_type() in c:\apache\htdocs\upload_crop_v1.2.php on line 5″
what am i doing wrong?
@munky, the image_type_to_mime_type() function is a built in PHP function more details can be found here http://uk2.php.net/image_type_to_mime_type, this function has been found to create problems in PHP versions older than 4.3.
in our code, just above the image_type_to_mime_type function there is the following:
list($imagewidth, $imageheight, $imageType) = getimagesize($image);
$imageType = image_type_to_mime_type($imageType);
change it to
list($imagewidth, $imageheight, $imageType, $bits, $channels, $mime) = getimagesize($image);
$imageType = $mime;
You will need to change it in both the image resize functions
starting line: 56 – resizeImage() function and
starting line: 97 – resizeThumbnailImage() function
Hopefully that should do the trick.
It is wonderful. But we have one issue in IE 7. If we left double click on image instead of cropping area select then getting a JavaScript error “Invalid arguments”. But working fine with Firefox. Any idea to fix this issue.
Thanks in advance
Honish
In script 1.0, it was possible to re-upload a file if the uploaded picture didn’t (on the screen you resize the pic.)
In 1.2 version, it seems this feature isn’t avaible anymore. How can i solve this problem? Thanks
@nicos, could you please specify again what it is you need, your comment doesn’t really make sense. in both scripts you are able to re-upload a new image once a crop has been made.
it’s a mistake from me,sorry.
thank you for your fast reply
Is it possible to make the thumbnail overlay visible on load?
thanks
@huzzi,
Find and change the following line
$(‘#thumbnail’).imgAreaSelect({ aspectRatio: ‘1:1′, onSelectChange: preview });
to
$(‘#thumbnail’).imgAreaSelect({ x1: 120, y1: 90, x2: 280, y2: 210, aspectRatio: ‘1:1′, onSelectChange: preview });
Obvioulsy the x1,y1,x2,y2 values above are just an example and may not work on your image. Adjust as necessary.
Brilliant, thanks so much.
Nice script…
Can someone crop an image that is larger than the screen size?
Is it possible for someone to download what they just cropped?
Thanks,,,
AG
Very nice script…
I’m trying to do the same thing as huzzi – got the thumbnail overview loading up perfectly on load, but is there a way to ensure the thumbnail matches this on load (as opposed to on mouse interaction)?
Thanks,
Adrian
Thanks for the script … very useful!
I’m having an issue with the selection tool in IE7. I’m working off of your upload_crop_v1.2.php file “as is”. I was able to upload a photo, but when I go to make the selection, I get an error:
Line: 13
Char: 12949
Error: Invalid argument
Code: 0
URL: …/upload_crop_v1.2.php
Things are working fine in Firefox though. I also looked at your demo in IE7 and it works fine. Any ideas?? I could be overlooking something simple.
I’m using jquery-1.3.2.min.js and jquery.imgareaselect-0.8.js.
Hi, I am trying to use this great plugin in a JQuery Dialog but I’m having issues with z-index of the selection div,
I tried (with no result):
$(‘.imgareaselect-outer’).css(z-index:2000 !important;);
$(‘.imgareaselect-selection’).css(z-index:2000 !important;);
Do you know a way to fix this please?
@Kyaan, your css command for jquery is incorrect, please see the jquery documentation on applying css to elements,
$(“.my_element”).css(“color”,”#ffffff”)
Try
$(“.my_element”).css(“z-index”,”200″)
Thank you very much, it’s working perfectly on both IE & FF now!
webmotionuk,
Does this PHP script work in safe_mode = ON?
@dydream, safe_mode must be off for this script to work.
Brilliant
Hi webmotionuk,
I have an issue with IE 6, when i upload an image for the first time, the cropping tool isn’t visible. After i close the window with your script and reopen >> reupload >> i can see the cropping tool.
This only appears in IE6 at the moment
Any advice??
Do you know of a method to add text to uploaded images?
Thanks.
I wonder how I can crop image with different sizes.
Can anyone enlighten me how to do it?
@shin, you can crop at different sizes, however it will require you to edit the script to remove the elements that define the thumbnail size and replace it with your own. Also a preview may not be possible for images that do not have a fixed thumbnail height and width.
WOW!!!!!!!!!!!!!!
The best upload script ever, 100% customizable.
Here’s one contribution:
At the line where is the Image to Crop add “cursor:crosshair” at the style.
The changed version is:
<img src=”" style=”float: left; margin-right: 10px;cursor:crosshair” id=”thumbnail” alt=”Create Thumbnail” />
And it will show a cross when mouse is hover.
Thanks a lot
Higor
higorvaz@gmail.com
I believe I may have found a bug.
I set max_file to “5″ and max_width to “640″
I then tried to upload a 4.5 MB JPG which then returns a blank page without the crop features. I hit the back button which then reveal the original image of 2304×3072 with the crop features but these don’t work.
I was just testing how a user might realistically upload a photo after directly docking their camera. I advise that you use this same test scenario to counter the bug.
Hi,
I think this is a very cool application but would like to tweak it a little bit. I would like not to have to upload the image before making the crop selection. I can get the image in the cropping area fine and the selection works perfectly but here’s the question:
How wolud I go about changing the php-script so that it uploads a file I specified in the form posted (not in a file-type input field but a hidden one)? And then does the same cropping as the original script, of course.
Thanks in advance!
Fredrik
Hi,
Great script, thank you very much – actually it’s one of the best image upload scripts I’ve seen. However, I’m having little compatibility issues on IE8 and FF3.5.
on IE8 – works only in compatibility mode.
on FF3.5 – doesn’t get to the crop part at all.
I was wondering if anyone else is having similar issues?
Peter
Figured it out – it was obviously my mistake..
Thanks again for the great piece of code.
Peter
Hello everyone,
Thank you for promoting this script, I really like… But I have one big issue, which I’m not able to figure it out, maybe someone of you guys can help me out.
In the first step of the script I’m trying to implement a “uploadbar” which shows the process of uploading the “big”-first image… Maybe someone can share an example with me or help me with some tips?
Thanks for that!
Rolf
Hi,
I am trying to implement your code , I have a list of profiles for which i need to upload images. I have successfully implemented the upload feature and thumbnail generation. Now the problem is when i delete the image for one profile and then come back and add an image for the same profile, it always displays the previous image (cache). This works fine in FF ,but IE is loading images from cache…any idea how to solve this. I have added no cache header to the page but still it is cachin the image..
Thanks
Pradish
Really don’t expect anybody to know this, but whatever – I got it working, just about, had a problem with directories (I changed them), and it was working. Change too many file directories, stopped working at all. Buggered up so downloaded it again and now the fresh version, without any of my modifications, doesn’t work.
Files upload, and I can see them in upload_pics, but the form doesn’t bring them back to crop them.
Any ideas?
I said to myself I wasn’t going to write a comment because I hate writing comments asking for help, but I tried everything I thought of apart from… restart the browser! Obviously all the session variables etc. were still set to the old ways, so it was getting very confused. Seems to be sorted now.
What a great tool, keep up the good work.
Great tool…thanks..my images are not caching now
This is a cracking script, however im trying to upload the image path into a Mysql field at the same time, so the database can call the image using the path.
Is this possible?
I basically have a profile script and the photo is stored with the records name, email, number. I have made the fields in the table but cant figure out how to insert an image path to call up, its driving me crazy!
Ive searched google and still looking for an answer, if I find out how to insert the image path into a table ill let you guys know, any help would be much appriecated!
First off, must say that I love the script! It works just as expected, but there’s one extra thing that I think would be very helpful.
Cropping is restricted by the boundary of the picture. If you were trying to focus in on one part of the photo, you can only zoom so far.
Is it possible to zoom out passed the frame of the image? Maybe a white frame could be added to the resized image, so that the image itself is bigger allowing to zoom in farther???
Anyone know how I might achieve something like that?
i have a problem…
area-select-window is set on load. when i stretch the window, the selected portion is not getting cropped. its saves some other portion of the same image. but it shows correctly in the preview window.
it also works correctly when i dont stretch the window…
how to solve this??
Hi there… i need some help.
Everything works perfectly fine but when i i want to start skinning the template by separating the big image and the crop preview by different table cell, the preview area stops working.
Eg:
<img src="” style=”float: left; margin-right: 10px;” id=”thumbnail” alt=”Create Thumbnail” />
XXX
<div style="float:left; position:relative; overflow:hidden; width:px; height:px;”>
<img src="” style=”position: relative;” alt=”Thumbnail Preview” />
If i place a text ( XXX ) inbetween the big image and thumbnail, it work but as long as there html tags in between, error is found.
Even if i add just a inbetween, the preview area dont work.
Any idea how i could resolved this?
ops sorry.
Even if i add just a BOLD tag inbetween, the preview area dont work.
I have the same problem as Dan.
I can’t upload picture with width bigger then 1000 px. I have blank page then. when I refresh site I see crop area but when I want save the thumb it doesn.t work
Plis help..
I want to be able to have the processed images saved to a different folder. I changes the path here:
//Image Locations
$large_image_location = $upload_path.$large_image_name.$_SESSION['user_file_ext'];
$thumb_image_location = $upload_path.$thumb_image_name.$_SESSION['user_file_ext'];
but it doesn’t work. Is there an easy way to save the uploaded file and the cropped file in different places?
Is there a way to only save the cropped file?