PHP & jQuery image upload and crop

Update

We are looking for new features to be added to this plugin, please leave your requests in the comments on the following page : JQuery / PHP Upload and Crop – Feature Request

NOTE: This script has been updated please see the following link PHP & jQuery image upload and crop v1.2 AND the new fully jquery’d version of it Jquery image upload and crop for PHP. Both new scripts handle JPG, GIF and PNG upload and crop!

We needed a PHP and jQuery image upload and crop tool and came up with the following. Hope it helps!

Before you start, ensure you have the following:

  • PHP 4 or Higher (It has been tested on Version 5)
  • Safe mode must be off! – A number of users have reported issues when safe mode is on.
  • PHP GD Library
  • jQuery ver 1.2.3 or Higher
  • Image Area Select plugin by Michal Wojciechowski

Our Requirement

What we needed was a way to upload a JPG image, resize it if required then crop it to given height and width.

1. Firstly we created a form to allow us to upload an image. Pretty basic, nothing flashy there.

Photo

2. Capture, rename and resize the uploaded file. (We also provided a set name for the uploaded file.)

if (isset($_POST["upload"])) {
	//Get the file information
	$userfile_name = $_FILES["image"]["name"];
	$userfile_tmp = $_FILES["image"]["tmp_name"];
	$userfile_size = $_FILES["image"]["size"];
	$filename = basename($_FILES["image"]["name"]);
	$file_ext = substr($filename, strrpos($filename, ".") + 1);

	//Only process if the file is a JPG and below the allowed limit
	if((!empty($_FILES["image"])) && ($_FILES["image"]["error"] == 0)) {
		if (($file_ext!="jpg") && ($userfile_size > $max_file)) {
			$error= "ONLY jpeg images under 1MB are accepted for upload";
		}
	}else{
		$error= "Select a jpeg image for upload";
	}
	//Everything is ok, so we can upload the image.
	if (strlen($error)==0){

		if (isset($_FILES["image"]["name"])){

			move_uploaded_file($userfile_tmp, $large_image_location);
			chmod ($large_image_location, 0777);

			$width = getWidth($large_image_location);
			$height = getHeight($large_image_location);
			//Scale the image if it is greater than the width set above
			if ($width > $max_width){
				$scale = $max_width/$width;
				$uploaded = resizeImage($large_image_location,$width,$height,$scale);
			}else{
				$scale = 1;
				$uploaded = resizeImage($large_image_location,$width,$height,$scale);
			}
			//Delete the thumbnail file so the user can create a new one
			if (file_exists($thumb_image_location)) {
				unlink($thumb_image_location);
			}
		}
		//Refresh the page to show the new uploaded image
		header("location:".$_SERVER["PHP_SELF"]);
		exit();
	}
}

3. Now that the image has been uploaded and saved to our folder we can use the “Image Area Select” plugin to crop our image.

It basically provides the coordinates to the server to handle the crop.

  • 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.

Lets break it down, we first set the imgAreaSelect function to the image we want to crop, i.e. the one we just uploaded. As you can see, the aspect ration is set to 1:1, which means we are going to get a square selection. The “onSelectChange” is a callback function which runs the preview function when a change is made to the crop.

$(window).load(function () {
	$("#thumbnail").imgAreaSelect({ aspectRatio: "1:1", 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 = 100 / selection.width;
	var scaleY = 100 / selection.height; 

	$("#thumbnail + div > img").css({
		width: Math.round(scaleX * 200) + "px",
		height: Math.round(scaleY * 300) + "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 = 100/$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();
}

That is pretty much it, and all it took was 2 javascript files! Take a look at the demo and download a copy to see the full working code.

So far we have tested it in FireFox v2, Internet Explorer 6 and 7 with pretty good results. (Let us know if you find any issues with other browsers.)

The demo

Click here to see it in action

Download

Click here to download

136 Responses to “PHP & jQuery image upload and crop”

  1. “So far we have tested it in FireFox v2, Internet Explorer 6 and 7 with pretty good results. ”

    - Firefox 3.5.10, Opera 9.21, 9.51, 9.64 and 10.10, Safari 5.01 and Google Chrome are working fine in the Demo. Affirmative!

    Greetings,
    francky

  2. Hi,
    A wonderfull tool! And fast working too! :)

    Also a suggestion; line 11 under “2. Capture, rename and resize the uploaded file” reads:
    if (($file_ext!=”jpg”) && ($userfile_size > $max_file)) {
    $error= “ONLY jpeg images under 1MB are accepted for upload”;
    }

    I guess the error devil was walking by: the AND operator && should be the OR ||, otherwise a jpg of way > 1MB will pass easily. And a bmp of 20KB as well: the 2 conditions aren’t both true, so “no error”.
    In the jquery_upload_crop.zip I saw the upload_crop.php has the same && (line 103).

    Cordially,
    francky

  3. Exactly what I was looking for. Thank you!

  4. thanks for crop scripts but im also having the same issue. its not showing up with I.E 8 and the image came out wrong. any help?

  5. hello…

    thanks for the customized crop script. but it is not working in I.E-8. even image is not uploading. any help?

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

    Thanks!

  7. This is great solution.
    I am impressed with true solution.

  8. Is there any possibility to make a rectangle, not a square thumb with this or you have to modify the code?

  9. There’s another issue if the script is used in an iframe (Facebook) app, due to third party cookie restrictions in some browsers and some user settings.

    In this situation the script accepts an image upload only in the second attemp.

    If you are not concerned about session highjacking the following code additions makes the script more reliable. So the session ID can be handled without cookies.

    //Refresh the page to show the new uploaded image
    header(“location:”.$_SERVER["PHP_SELF"].”?PHPSESSID=”.session_id( ));

    and the second change…

    //Reload the page again to view the thumbnail
    header(“location:”.$_SERVER["PHP_SELF"].”?PHPSESSID=”.session_id( ));

  10. Script var working in my previous hosting but with the new one it doesnt. I select picture and hit upload but nothing is happening :(
    This two sites are mine and working on the same server.
    I couldnt understand the problem do you have any idea?

    phpinfo: http://www.gogoostick.com/
    uploadscript: http://www.eniyi5.net/crop2/index.php

  11. I have the same problem as Johnny. It works like a charm on one server, on one host, on the other – 1&1 running Plesk – I have the same prob,

  12. is it possible that the upload doesnt work in the downloadable file? I always get a time-out

  13. I have added the script and upload a picture. The picture saves to the upload directory but when the page refreshes there is no picture no error nothing. The image saves as resize_(randomnumbers).jpg.jpg

    When i upload another pic, the first pic is gone from the directory.

    So to rephrase. When i upload a pic, it uploads to the directory but no other actions take place on webpage. It just resets to what it originally looks like before an image upload. When i upload a second image it replaces the first in the directory with the same results on the upload page.

    Any help would be appreciated. I’m trying to build this thing now and will most likely move to a different script in 24 hours time. Thanks in advance!

  14. 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

  15. Hi,

    I type all this for the second time – great product, just what we are looking for to allow end-users to easily upload and create thumbnail images.

    There is one problem with the thumbnail preview, when an area is selected the preview window sometimes displays the top portion of the main image invading the bottom portion of the preview (at a rate roughly double the rate of mouse drag).

    This seems only to happen when the image is quite deep, i.e. deeper than a 4:3 image

    PS – its annoying to lose an entire technical comment just because I missed the CAPTCHA!

  16. It could be very useful to have a parameter to change the aspect ratio of the cropped image (currently i can only get square thumbnails) or to specify a fixed width & height for the cropped image. Can anyone help with this? How can i change the script to work in this way?

    regards,

  17. @jj, it seems you may not have the GD2 graphics manipulation library, you can check this out looking at the output of phpinfo(); If the file does exist, it must be enabled in php.ini by adding the following lines in the file:

    [PHP_GD2]
    extension=php_gd2.dll

  18. Hi,

    This is perfectly useful.
    But I am getting an error message
    “Fatal error: Call to undefined function imagecreatetruecolor()”.
    Please help me to sort it out

  19. Oh man! This script is awesome!
    Congratulations, it helped me a lot!!!

  20. First, this is a pretty neat plugin. Thanks for it.

    I’m having a problem with implementation. As a standalone version, it works just fine, but when I incorporate it it into my website, it breaks. I think it has to do with the jquery-pack. It occurs to me it already includes jQuery 1.2.6. My site is heavily reliant on jQuery, and I use a lot of different plugins. I already use goggleapi for my whole site (maybe thirty pages.) Do you have a version that doesn’t include the jQuery library, and just the jQ scripts needed for your plugin?

    Again, thanks for the script, and in advance for any help you might give.

  21. Hi all,

    This is great!

    I was wondering if anyone knows how to create multiple versions of the cropped image for example: a large, medium and small version of the generated thumbnail?

    Much appreciated,

    Thanks! k

  22. Works really nicely. Thanks for sharing.

    Is it possible to let the user specify the dimensions of the cropped image? Say pass a width and height using an input alongside the upload form? That would be really cool.

  23. I want to have the original file name and extension. In this way now i can use only one image, that I always overwrite.
    Anyone can tell me how to fix this? (will this be in the newer version?)
    Just keep the file name

  24. thanks man, this is really a great script

  25. hi,
    thanks for the great script.

    my problem is eventough folder permissions on server is correct and script works flawless on a local test machine. i cant upload images(or cant create them) to server.

    any suggestions appreciated.

    have nice day.

  26. Thank you for your amazing script! It works like a charm. However, I came over with a problem when integrating it with a jQuery uploader rotine.

    Problem is that, after I upload the image and dinamically display it inside a div, the “preview” function seems not to find the large image, doing nothing with the thumbnail preview. Here is a bit of the code:

    onComplete: function(file, response){
    button.text(‘Upload’);

    window.clearInterval(interval);

    // enable upload button
    this.enable();

    // add file to the list
    $(”).appendTo(‘#example1 .files’).text(file);
    $(‘#origImage’).prepend(”);
    $(‘#thumbImage’).prepend(”);
    $(‘#thumbnail’).imgAreaSelect({ aspectRatio: ’1:1′, onSelectChange: preview });

    }

    Note that I just call the “preview” function, after having completed the upload and displayed the image.

    Do you have any idea about what I am doing wrong on it? Any help would be very appreciated. Thank you!

  27. Excellent !!

    Thanks for a very nice post. I implemented this and found it quite simple and nice. Currently I am making some image gallery with CakePhp and eager to implement this feature.

    Please let me know if there is any implementation of this or any other feature in the same fashion with in CakePhp.

    Regards,

    Amjad Shaick

  28. @keithics, Yes you can, you would need to call the resize function to obviously resize the thumbnails in the various sizes you want.

    e.g. Call this function again but change the scale

    $scale = ($thumb_width)/$w;
    $cropped = resizeThumbnailImage($thumb_image_location, $large_image_location,$w,$h,$x1,$y1,$scale);

    Saying this, you will have to give the new thumbnail a different name otherwise it will continue to get overwritten by the script. Remember to include the folder it has to be stored in too!

    $scale = ($thumb_width*2)/$w;
    $cropped = resizeThumbnailImage($upload_path.’my_new_thumbnail1′.$_SESSION['user_file_ext'], $large_image_location,$w,$h,$x1,$y1,$scale);

    This should give you a new thumbnail that is twice the size of the width set at the very top. Although this has not been tested.

  29. @Dac, please note all copyright notices must stay intact to use this solution

  30. nice script! thanks. Is there a way I can make multiple thumbnails? it would be great.

  31. Hi! I wonder if you’re allowed to use this solution on -any- website?

  32. this is a great script but i’m having a problem modifying it.

    how can i make the upload directory change dyamically based on a $_GET variable posted from a url, i have tried modifying $upload_dir = “../images/”.$_GET['folder']; in image_functions but it posts it to the folder images/ instead ignoring the $_GET['folder']

    Thanks

  33. When I upload an image it saves the image like resize_34242.jpg.jpg

    And i don’t want the images to be named resize_34242…
    i want my images to be named like resize_(original file name).(file extension)

    so much for the next version

    Can’t get it to work, because of the file extension problem, probably because PHP version… don’t know what version is on, probably 4.x

  34. @vishnu, if the large image is too big for the width then the thumbnail will not sit side by side. Either make the width of your site wider or make your larger image smaller to fit the screen.

    @helio, ensure the upload directory has write permissions (CHMOD 777), you can comment out the error reporting line to see what errors may be causing this error:
    change
    error_reporting (E_ALL ^ E_NOTICE);
    to
    #error_reporting (E_ALL ^ E_NOTICE);

Trackbacks/Pingbacks