NOTE: Please update your browser. We recommend using IE 7 or FireFox 3.

PHP & jQuery image upload and crop

May 15th, 2008 | Posted in Ajax, Articles, Jquery, PHP | 113 Comments »
Tags: , , , , ,

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:

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


Found this article useful? Did it save you time?



Tags: , , , , ,

Blogsphere: TechnoratiFeedsterBloglines
Bookmark: Del.icio.usSpurlFurlSimpyBlinkDigg
RSS feed for comments on this post
 |  TrackBack URI for this post

113 Comments to “PHP & jQuery image upload and crop”

  • Vishnu says:

    Hi,

    I need uploaded image and croped image display side by side at the width I have set .

    At the moment when we upload a large image it is to large for the screen. and crop image go to beneth . 2 Images side by side would work better.

    Please help me

    regards

    vishnu

  • Hélio Lourenco says:

    Hi,
    Sorry my English I’m from Brazil.
    I downloaded of this source and to test it I´m using easyPHP, when I run the source dont show any lines with errors of php but show the follows message

    “Unexpected Error

    Please try again
    Acesso Proibido! Você não tem premissão para acessar o objeto requisitado. Ele pode estar protegido contra leitura ou não ser legível pelo servidor. Se você acredita ter encontrado um problema no servidor, por favor entre em contato com o webmaster. Error 403 localhost 12/09/09 23:31:24 Apache/2.2.13 (Win32) PHP/5.3.0 ”

    What i need to do to use it without this problem??
    Thank
    Sorry my English but I want to try…

  • webmotionuk says:

    @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);

  • john doe says:

    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

  • griffin says:

    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

  • Dac says:

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

  • keithics says:

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

  • webmotionuk says:

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

  • webmotionuk says:

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

  • Amjad says:

    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

  • Edson Garrido says:

    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!

  • batur says:

    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.

  • Shooman says:

    thanks man, this is really a great script

Post comment