Create an account on Neowin to contribute and support the site.

# [PHP] Help with imagecopyresampled

## Recommended Posts

Brian Miller    1,537

How can I crop the central part of a long image in to a square?

Say I have an image that looks like this:

I would like to crop it's center in to a square like this:

Here is the PHP code that I am using but am having no joy whatsoever.

```if(\$OriginalHeight > \$OriginalWidth){
\$StartY = \$OriginalHeight / 4;
\$StartX = 0;
\$EndY = \$StartY * 3;
\$EndX = \$OriginalWidth;
}

if(\$OriginalHeight < \$OriginalWidth){
\$StartY = 0;
\$StartX = \$OriginalWidth / 4;
\$EndY = \$OriginalHeight;
\$EndX = \$StartX * 3;
}

if(\$OriginalHeight == \$OriginalWidth){
\$StartY = 0;
\$StartX = \$OriginalWidth;
\$EndY = \$OriginalHeight;
\$EndX = \$OriginalHeight;
}

imagecopyresampled(\$NewImage, \$SrcImage, \$EndX, \$EndY, \$StartX, \$StartY, \$NewImageSize, \$NewImageSize, \$OriginalWidth, \$OriginalHeight);```

Can a PHP expert help me?

##### Share on other sites
Brian Miller    1,537

Did I post this in the right place?

##### Share on other sites
+theblazingangel    137

Your logic is flawed. If we look at the first if block where we need to reduce the height, you are always setting the top and bottom positions to 1/4 and 3/4 respectively of the height of the image, i.e. where the image is taller than it is wide, you are always trying to change the height to 1/2 of whatever it currently is, which is not going to produce the desired outcome. Instead you should be thinking, right, it's this much too tall, so I need to trim half of that excess from the top and half from the bottom. I.e.

```\$excess = \$OriginalHeight - \$OriginalWidth;
\$StartY = \$excess / 2;
\$EndY =  \$StartY + \$OriginalWidth;
\$StartX = 0;
\$EndX = \$OriginalWidth;```

Except this isn't necessarily quiet good enough, you need to consider properly what happens when excess is an ODD value. If excess is an odd value, then \$StartY and \$EndY are going to have 0.5 of a pixel that needs to be handled somehow. With the above code which doesn't do anything about this, what will happen? Is this simply going to get rounded up by a function at some point in the execution of your code, is it going to get rounded down by a function at some point, or could these non-whole numbers even cause a crash of your code by something expecting a whole number (more likely to happen in stricter languages than php)... It wouldn't reflect well on you as a programmer to simply do a little test to ensure it doesn't crash and then just leave it as that thinking I don't give a damn whether it's rounded up or down, i'll leave it to just do whatever it does; not taking the time to properly handle this now could come back to bite you later! All you need to do to handle it is first make a decision on whether you want it to round up or down (trim the extra pixel from the bottom or top respectively) and then simply round up/down:

```\$excess = \$OriginalHeight - \$OriginalWidth;

\$StartY = round((\$excess / 2), 0, PHP_ROUND_HALF_DOWN);

\$EndY =  \$StartY + \$OriginalWidth;

\$StartX = 0;

\$EndX = \$OriginalWidth;```

##### Share on other sites
+theblazingangel    137

Did I post this in the right place?

Yes!

##### Share on other sites
Brian Miller    1,537

Thanks theblazingangel, you bring up a good point.

Here is what I am now getting with your example code.

##### Share on other sites
+theblazingangel    137

Thanks theblazingangel, you bring up a good point.

Here is what I am now getting with your example code.

Right, I've never really done image manipulation in PHP before and assumed that imagecopyresampled was your own custom function and you were undoubtedly using correctly, but I see now that it's not and you're not (it was late, forgive me :p ).

You need to tell the function the portion of the original image to copy and where to in the new image. With the 5th and 6th parameters this means providing x and y for the top left corner of that source area (\$StartX and \$StartY respectively), as you have. In the 9th and 10th parameters you need to specify how wide and tall the area to copy is, for this you need to modify my if statement to capture these (capturing \$EndX and \$EndY values is pointless). For the 3rd and 4th parameters you need to specify the top left corner in the destination image to copy to. The ability to specify this allows you to build a new image from multiple pieces, in your case these should just simply both be zero though. The 7th and 8th parameters define the width and height of the area in the destination to copy to, these should be the same as the 9th and 10th parameters, if you specify anything different it would stretch/shrink the image to fit.

##### Share on other sites
Brian Miller    1,537

Yes, I was using the built in function. Here is the manual for imagecopyresampled:

##### Share on other sites
Brian Miller    1,537

I hope you don't mind writing that last line out for me? I got a little confused.

##### Share on other sites
DeathByPenguin    0

This code is a bit messy it's from a big image uploading class I made a while ago which I'm considering putting on GitHub or something. I probably should it does reszing, cropping etc all in a php class and it'll choose between Imagick or GD depending on what's available. I'm not sure if this is all of what ya need tbh.I'm very tired right now and I may have missed something. This is pretty much the math you need though. It also resizes the image, you'd need to edit this to take out that feature if ya don't need it.

```	// For \$ImageLocation you may want to use something like
// \$_FILES["file"]["tmp_name"]
list(\$width, \$height) = getimagesize(\$YourImageLocation);

\$maxWidth	= 50;
\$maxHeight	= 50;
\$xRatio		= \$maxWidth / \$width;
\$yRatio		= \$maxHeight / \$height;

if(\$width > \$maxWidth || \$height > \$maxHeight) {
if (\$xRatio * \$height < \$maxHeight) {
// Resize the image based on width
\$tnHeight	= ceil(\$xRatio * \$height);
\$tnWidth	= \$maxWidth;
} else {
// Resize the image based on height
\$tnWidth	= ceil(\$yRatio * \$width);
\$tnHeight	= \$maxHeight;
}
} else {
\$tnWidth = \$width;
\$tnHeight = \$height;
}

// Create Medium sized thumbnails and small thumbnails
// We need to crop, so we set both offsets to 0 first
\$offsetX = \$offsetY = 0;

// What ratio do we want to crop the image to, e.g. 16:9
// Both thumbnails will be cropped so we do that first.
\$cropRatio = "1:1";
\$cropRatio = explode(':', (string) \$cropRatio);

\$cropRatioComputed	= (float) \$cropRatio[0] / (float) \$cropRatio[1];
\$cropRatioComputed =  round(\$cropRatioComputed);

if (\$tnHeight > \$tnWidth) {
// Image is too tall so we will crop the top and bottom
\$height		= \$tnWidth / \$cropRatioComputed;
\$offsetY	= (\$origHeight - \$height) / 2;

} else if (\$tnWidth > \$tnHeight) {
// Image is too wide so we will crop off the left and right sides
\$width		= \$tnHeight * \$cropRatioComputed;
\$offsetX	= (\$origWidth - \$width) / 2;
}

ImageCopyResampled(\$NewImage, \$SrcImage, 0, 0, \$offsetX, \$offsetY, \$tnWidth, \$tnHeight, \$width, \$height);
```

##### Share on other sites
+theblazingangel    137

I hope you don't mind writing that last line out for me? I got a little confused.

I was hoping you could do it yourself to help you learn, I'll do it a bit later when I'm home if you still need me to. see below...

##### Share on other sites
+theblazingangel    137

I hope you don't mind writing that last line out for me? I got a little confused.

here:

```if (\$OriginalHeight > \$OriginalWidth) {
\$excess = \$OriginalHeight - \$OriginalWidth;
\$StartY = round((\$excess / 2), 0, PHP_ROUND_HALF_DOWN);
\$StartX = 0;
\$NewWidth = \$NewHeight = \$OriginalWidth;

} elseif (\$OriginalHeight < \$OriginalWidth) {

\$excess = \$OriginalWidth - \$OriginalHeight;
\$StartX = round((\$excess / 2), 0, PHP_ROUND_HALF_DOWN);
\$StartY = 0;
\$NewWidth = \$NewHeight = \$OriginalHeight;

} else {

\$StartY = \$StartX = 0;
\$NewWidth = \$NewHeight = \$OriginalWidth;
}

imagecopyresampled(\$NewImage, \$SrcImage, 0, 0, \$StartX, \$StartY, \$NewWidth, \$NewHeight, \$NewWidth, \$NewHeight);```

##### Share on other sites
Brian Miller    1,537

Thank you theblazingangel :)