Making & Cropping Thumbnails Square Using PHP & GD

/ PHP / by Paul Robinson / 39 Comments
This post was published back on February 21, 2009 and may be outdated. Please use caution when following older tutorials or using older code. After reading be sure to check for newer procedures or updates to code.

Recently I made an image uploader for my other website & I noticed that there isn’t a lot of tutorials around on how to crop thumbnails into squares. This tutorial requires that GD is enabled in PHP, I’m not sure whether you need GD2 or not but I don’t see any reason for it not to work in older versions of GD.

Copy The Large Image

Just incase you don’t know how to do it, you can copy the original image across like this.

Let’s Get Onto The Thumbnails

Ok now let’s get onto the code for the thumbnails.

We create a copy of the image using imagecreatefromjpeg(). A quick note here is that this code will only work for uploads of jpg & jpeg file types. You could have a switcher checking for the mime type and use imagecreatefromjpeg, imagecreatefromgif & imagecreatefrompng to also do those file types. The switcher could be created by putting the image through getimagesize and handing the returned arrays ‘mime’ value through image_type_to_mime_type, but that’s not what this tutorial is about.

Mmmk. So first we set a width & height for our cropped thumbnails. They don’t have to be square, but for layout purposes square thumbnails create a nice foundation. We grab the image’s width & height. We create a ratio by dividing the new width by the original width, we do the same for the height too.

Next we do a check to see what shape our image is landscape, portrait or square. If the image is checked we use the ratio to get the right size for either the width or height. If it’s square it doesn’t matter. Really with a square thumbnail the check doesn’t matter since in our case the $crop_w & $crop_h variables should always be 120, but if you chose rectangular cropped thumbnails then it is very important or your images will be out of proportion.

Finally we create a blank image at the size of our thumbnail and then use imagecopyresampled to place our copied image into the blank image with the new crop sizes.

There’s only one more thing left to do & that is to save our image somewhere.

As I said before, this part of the script will only work with jpg and jpegs. If you want other formats you would need to use a switcher. If it was successful we destroy all the images used to free up memory.

That’s It

Yep, that’s it. You should end up with a nice cropped thumbnail at your desired size. If you have any problems let me know and I’ll see what I can do to help. 🙂

A Little Tip

Just a little after thought. In the code to copy the full image I just use the copy function. If you are going to use that instead of move_uploaded_file it is probably a good idea to make sure the file was uploaded via a form using is_uploaded_file. You could use something like this to cover all bases.

How To Center The Square Cropping Effect

There have been a few requests about how to take the square crop from the center of an image. Here’s how to do it. To do that we need to calculate the X & Y positions. This requires the code to be altered slightly.

Here is what we are doing. We need to figure out the X & Y positions from which to crop the image, to do that we do some math. If the image is landscape we work out the X position using the sum ((new image width / 2) – (thumbnail width /2)). We set the height to 0 as it has already been set to the height of the thumbnail.

We do the same again for portrait images except we do the sum on the height and set the width to 0. If the image is square we don’t need to do anything since it will fit straight into the square thumbnail with no cropping.

I hope that helps with centering the crop when cropping square thumbnails. Thank you to Elpres, and Deryk Wenaus in the comments for the sum to work out the X & Y positions.

Resizing Images Held In A Directory

Huge thanks to Ray for contributing this snippet of code in the comments:

PEAR Modules

A few people have asked me why I don’t use the two PEAR modules HTTP_Upload & Image_Transform… Well one reason is that HTTP_Upload is (according to the PEAR directory) without any maintainers at the moment. Also my host & quite a few others don’t allow you to install additional PEAR packages. I am lucky enough in that my host will however allow me to set up my own PEAR install which will then allow me to install additional packages, but this tutorial is useful for those who do not have that option. It might be

39 Comments

Author’s gravatar

nice. but i’m not really a PHP guy and have no idea for to execute this to do it’s thing.
Could you help ?

Reply
Author’s gravatar

You need to install php. Recommended to install on a web server. Then executed via a browser.

Author’s gravatar

Not quite sure I understand. All the code is there. Just join all the parts together in a file call it something like upload.php & then create a form on the page you want images to be uploaded on. A standard form like this:

In the part of the PHP script you copied that looks like this:

Change it to this:

Change path/to/upload/complete/file.html to a file you want to show if the file was uploaded successfully. That’s about all there is too it. You might need to seek out some code for image type validation, but that isn’t in the scope of this tutorial.

Reply
Author’s gravatar

Thanks for the tutorial and source code! I’m searching for this code for quite some times already. 🙂

Reply
Author’s gravatar

The image is not centered when you require a square thumbnail from a non-square image, it starts at the top-left of the image. To get around this you’ll need to change the code to calculate how far you need to start in either X or Y axis:

1-(width or height of new resized-image / 2) – (width of thumb/2)

Reply
Author’s gravatar

Ok, thanks for the help, but where do we use that?

Author’s gravatar author

Hey,

you would need to add a little bit to the code. I’ll sort out how to do it for you and add it to the bottom of the post.

Check back soon. 😉

Author’s gravatar author

I’ve updated the bottom of the post so it explains how to center the crop. I hope that helps. 😉

Author’s gravatar

Oh! Thankyou so much! You were so fast!
It works perfectly.

Author’s gravatar author

No problem. A big thanks to Deryk too for pointing out the mistake I make the first time. 😉

Author’s gravatar author

Yes, I know. This tutorial only gives info on how to create square cropped thumbnails of a certain size. For the purpose I was using them it wasn’t needed to center them. Using the top-left of the image gave some form of mystery & that’s exactly what was needed.

Thanks for telling everyone how to center then though. 😉 However it is a lot easier using imagemagick it’s a shame it isn’t supported as well by hosting providers as it should be. 🙁

Reply
Author’s gravatar

Thanks for this tutorial, exactly what I was looking for!

Reply
Author’s gravatar author

No problem I’m glad you found a use for it. 🙂

Author’s gravatar

I wrote a similar function that could crop the image so that it “best-fits” inside given dimension, its described here:

http://911-need-code-help.blogspot.com/2009/04/crop-to-fit-image-using-aspphp.html

I now realize its probably the same thing as yours.

Reply
Author’s gravatar author

It is indeed, but you do give an ASP version.

Since I don’t use ASP it’s great you’ve linked to it there for anyone who stumbles into my site looking for a ASP GD resize function. 🙂

Author’s gravatar

Hi, There is an error in your code for the centre square crop.

The error happens when you scale the thumbnail any degree and shifting occurs so it is not centered.

line 4 should reaad
$src_x = ceil( ( $orig_w - $orig_h ) / 2 );

likewise line 10 needs to be
$src_y = ceil( ( $orig_h - $orig_w ) / 2 );

more good examples are here: http://php.net/manual/en/function.imagecopyresampled.php

Reply
Author’s gravatar author

Hi,

Thanks for posting that correction. I never got a chance to check the code properly, and never noticed it was off center.

I’m busy doing coding for the redesign of the site. That’s teach me to rush through edits on posts, lol.

I’ve checked it, made sure it works (which it does), and updated the post. 😉

Thanks again.

Author’s gravatar

I found this useful. I integrated some of the thumbnail code into my CakePHP app. Thanks very much for the post!

Reply
Author’s gravatar

Great script, I used it for an upload form in a gallery, but now I´m trying to change the first bit to make it work as a batch script for an entire directory. @imagecreatefromjpeg($files[$curimage]) doesn´t work. Any idea? Thanks in advance

Reply
Author’s gravatar author

I’m not sure. I’ve never tried to resize images from a directory rather than an upload.

From looking at the little bit of code you have wrote I’m not sure how you are going about it, but I would think a normal loop through files & passing the path to the image to imagecreatefromjpeg() would work.

If it doesn’t you could always take off the ‘@’ to see what error it’s throwing back and work from there. I’d give it a go, but I don’t have access to my localhost at the moment to test it out.

Author’s gravatar

Got it working:
<?php
$folder=$_GET['folder'];
$thisdir = getcwd();
if (!file_exists($thisdir ."/"."$folder/thumbs")) {
mkdir($thisdir ."/"."$folder/thumbs" , 0777);}

function returnimages($dirname="") {
$pattern="(\.jpg$)|(\.png$)|(\.jpeg$)|(\.gif$)"; //valid image extensions

$handle = opendir($dirname);
while (false !== ($filename = readdir($handle))) {
if(eregi($pattern, $filename)){ //if this file is a valid image
$files[] = $filename;}
}
if (count($files)0) {
sort($files);}

$curimage=0;

while($curimage !== count($files)){
$cropfile=$dirname.’/’.$files[$curimage];echo $cropfile;
$source_img = @imagecreatefromjpeg($cropfile); //Create a copy of our image for our thumbnails…
if (!$source_img) {
echo “could not create image handle”;
exit(0);
}
$new_w = 120;
$new_h = 120;

$orig_w = imagesx($source_img);
$orig_h = imagesy($source_img);

$w_ratio = ($new_w / $orig_w);
$h_ratio = ($new_h / $orig_h);

if ($orig_w > $orig_h ) {//landscape from here new
$crop_w = round($orig_w * $h_ratio);
$crop_h = $new_h;
$src_x = ceil( ( $orig_w – $orig_h ) / 2 );
$src_y = 0;
} elseif ($orig_w

Reply
Author’s gravatar

Hi, to let it run I used these lines:

if ($orig_w > $orig_h ) {
# LandScape
$crop_w = round($orig_w * $h_ratio);
$crop_h = $new_h;
$src_x = round((($orig_w * $h_ratio) – $new_w) / 2);
$src_y = 0;
} elseif ($orig_w < $orig_h ) {
# Portrait
$crop_h = round($orig_h * $w_ratio);
$crop_w = $new_w;
$src_x = 0;
$src_y = round((($orig_h * $w_ratio) – $new_h) / 2);
} else {
# Square
$crop_w = $new_w;
$crop_h = $new_h;
$src_x = 0;
$src_y = 0;
}

Note that $new_h and $new_w in my case have different values.

Author’s gravatar

Rest of the code for those who are interested:

Paul if it fills up your blog too much you can delete the post, thanks for your reponse

Reply
Author’s gravatar author

No problems. If you could email me the code I’ll add it to the post tomorrow, that’s assuming you don’t mind of course. 😉

Author’s gravatar

I’ve been trying everything and failing.
I’m trying to integrate this code with the one found here: http://davidwalsh.name/generate-photo-gallery. How would I do that?

Reply
Author’s gravatar author

Hi Angie,

Well it would be pretty much the same except for his make_thumb() function which would change a little. It would look something like:

That should do it I think. I haven’t tested it as I’m unable too at the moment, but it should work. Just set $new_w and $new_h to the cropped size you want.

Older Comments
Newer Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

I'll keep your WordPress site up-to-date and working to its best.

Find out more