s
Extras

How to Crop Images using GD

The following instructions are intended to accompany descriptions of resizing images in our PHP and MySQL book (they are not intended as a standalone tutorial).

The function shown below is used in the same way as the other examples in the book, and is called after a file upload has been validated (so it is only designed to work with a limited set of file types).

The four arguments for the function are:

  • $orig_path the path to the uploaded image
  • $new_path the path where the new (resized and cropped) image should be saved
  • $new_width the new width of the image
  • $new_height the new height of the image

1 GD's getimagesize() function returns an array of information about the file. Its path is stored in $orig_path.

2 $orig_width stores the width of the original image.

3 $orig_height stores the height of the original image.

4 $media_type stores the media type of the image. This is needed because GD has separate functions to open and save images that are in different formats.

5 $orig_ratio stores the ratio of the original image.

6 $new_ratio stores the ratio of the new image.

function crop_and_resize_image_gd($orig_path, $new_path, $new_width, $new_height)
{
    $image_data  = getimagesize($orig_path);                       // Get image data
    $orig_width  = $image_data[0];                                 // Image width
    $orig_height = $image_data[1];                                 // Image height
    $media_type  = $image_data['mime'];                            // Media type
    $orig_ratio  = $orig_width / $orig_height;                     // Ratio of original
    $new_ratio   = $new_width / $new_height;                       // Ratio of crop
    ...

7 If the ratio of the resized image will be less than the ratio of the original image, the full height of the original image will be used, but not all of the width.

  • $select_width (the width to select from the original picture) is the height of the original image multiplied by the ratio of the new image.
  • $select_height (the height to select from the original picture) is the height of the original image.
  • $x_offset (the distance that the crop should come in from the left hand side of the original image) is the width of the original image, minus the amount to select of that image, divided by 2.
  • $y_offset is 0 (because the full height is kept).

8 Otherwise, if the ratio of the resized image will be the same or greater than the ratio of the original image, the full width of the image will be used, but not all of its height.

  • $select_width (the width to select from the original picture) is the same as the width of the original.
  • $select height (the height to select from the original picture) is the width of the original image multiplied by the ratio of the new image.
  • $x_offset (the distance the crop should come in from the left) is 0 because the full width is kept.
  • $y_offset (the distance from the top of the image that the crop should start) is calculated by subtracting the selection height from the original height, then dividing this number by 2.
    // Calculate new size
    if ($new_ratio < $orig_ratio) {                                // If new ratio < orig
        $select_width  = $orig_height * $new_ratio;                // Calculate width
        $select_height = $orig_height;                             // Height stays same
        $x_offset      = ($orig_width - $select_width) / 2;        // Calculate X Offset
        $y_offset      = 0;                                        // Y offset = 0 (top)
    } else {                                                       // Otherwise
        $select_width  = $orig_width;                              // Width stays same
        $select_height = $orig_width * $new_ratio;                 // Calculate height
        $x_offset      = 0;                                        // X-offset = 0 (left)
        $y_offset      = ($orig_height - $select_height) / 2;      // Calculate Y Offset
    }

9 GD has separate functions that are used to open images that are different media types, so a switch statement is used to select the right function to open the image.

The condition checks the media type of the image, stored in Step 4. (In the code download, the permitted types of images are validated, so the switch statement only needs to process these media types.)

10 A blank image is created that matches the width and height of the resized image.

11 The selection of the image specified is copied, resized, and pasted into the new blank image created on the previous line of code.

12 Another switch statement is used to select the correct function to save the new cropped image.


    switch($media_type) {                                           // If media type is
        case 'image/gif' :                                          // GIF
            $orig = imagecreatefromgif($orig_path);                 // Open GIF
            break;                                                  // End of switch
        case 'image/jpeg' :                                         // JPEG
            $orig = imagecreatefromjpeg($orig_path);                // Open JPEG
            break;                                                  // End of switch
        case 'image/png' :                                          // PNG
            $orig = imagecreatefrompng($orig_path);                 // Open PNG
            break;                                                  // End of switch
    }

    $new = imagecreatetruecolor($new_width, $new_height);           // New blank image
    imagecopyresampled($new, $orig, 0, 0, $x_offset, $y_offset, $new_width, 
                       $new_height, $select_width, $select_height); // Crop and resize

    // Save the image in the correct format
    switch($media_type) {                                           // If media type is
        case 'image/gif' :                                          // GIF 
          $result = imagegif($new, $new_path);                      // Save GIF  
          break;                                                    // End of switch
        case 'image/jpeg':                                          // JPEG
          $result = imagejpeg($new, $new_path);                     // Open JPEG 
          break;                                                    // End of switch
        case 'image/png' :                                          // PNG 
          $result = imagepng($new, $new_path);                      // Open PNG  
          break;                                                    // End of switch
    }
    return $result;                                                 // Return resized image
}