Search code examples
phpgdcentercrop

PHP GD - crop image around any given point


I have the following script that successfully crops and image at the center point using php's gd:

list($source_width, $source_height, $source_type) = getimagesize($img_path);

define('IMAGE_WIDTH', 200);
define('IMAGE_HEIGHT', 300);

$ratio = $source_width / $source_height;
$desired_aspect_ratio = IMAGE_WIDTH / IMAGE_HEIGHT;

if ($ratio > $desired_aspect_ratio) {
    $temp_height = IMAGE_HEIGHT;
    $temp_width = ( int ) (IMAGE_HEIGHT * $ratio);
} else {
    $temp_width = IMAGE_WIDTH;
    $temp_height = ( int ) (IMAGE_WIDTH / $ratio);
}

$x = ($temp_width - IMAGE_WIDTH) / 2;
$y = ($temp_height - IMAGE_HEIGHT) / 2;

$cropped = imagecreatetruecolor(IMAGE_WIDTH, IMAGE_HEIGHT);
imagecopy(
    $cropped,
    $temp,
    0, 0,
    $x, $y,
    IMAGE_WIDTH, IMAGE_HEIGHT
);

Instead of this for the center:

$x = ($temp_width - IMAGE_WIDTH) / 2;
$y = ($temp_height - IMAGE_HEIGHT) / 2;

on my site users can select the 'main focus' of the image, in which i will crop the image around that. The focus will be supplied as a percentage. I already have the percentage and a way for the customer to select this, i just need to then take these values and crop around them. Can this be done? For example if i wanted my image to be cropped around the point as in the diagram below:

enter image description here


Solution

  • The below function should do what you want.

    • passing only the first argument will output what you have now: the middle of the source image cropped to 200px/200px.
    • the second and third arguments allow you to specify the X/Y percent coordinates for the centre of the crop, as you want.
    • the fourth and fifth arguments allow you to set the size of the cropped image.

    (Note that this assumes PNG, but you should be able to adapt it easily enough for other formats, if needed.)

    function crop($file, $cropX = 50, $cropY = 50, $cropW = 200, $cropH = 200)
    {
        $src = imagecreatefrompng($file);
        $dest = imagecreatetruecolor($cropW, $cropH);
    
        list($src_w, $src_h) = getimagesize($file);
    
        // calculate x/y coordinates for crop from supplied percentages.
        $src_x = (($src_w / 100) * $cropX) - ($cropW / 2);
        $src_y = (($src_h / 100) * $cropY) - ($cropH / 2);
    
        imagecopy($dest, $src, 0, 0, $src_x, $src_y, $src_w, $src_h);
    
        imagedestroy($src);
    
        return $dest;
    }
    

    Example usage (setting the crop focus of X to 70%):

    $img = crop('test.png', 70);
    header('Content-type: image/png');
    imagepng($img);
    imagedestroy($img);