Resize and crop image from center with PHP

Sometimes I need to not only resize the image, but also to change its size by removing unnecessary edges for new size. This function changes image size and if the height or width is too large after resizing then the edges are cut off from the center. Input image formats are jpeg, gif, png.

//resize and crop image by center
function resize_crop_image($max_width, $max_height, $source_file, $dst_dir, $quality = 80){
	$imgsize = getimagesize($source_file);
	$width = $imgsize[0];
	$height = $imgsize[1];
	$mime = $imgsize['mime'];

	switch($mime){
		case 'image/gif':
			$image_create = "imagecreatefromgif";
			$image = "imagegif";
			break;

		case 'image/png':
			$image_create = "imagecreatefrompng";
			$image = "imagepng";
			$quality = 7;
			break;

		case 'image/jpeg':
			$image_create = "imagecreatefromjpeg";
			$image = "imagejpeg";
			$quality = 80;
			break;

		default:
			return false;
			break;
	}
	
	$dst_img = imagecreatetruecolor($max_width, $max_height);
	$src_img = $image_create($source_file);
	
	$width_new = $height * $max_width / $max_height;
	$height_new = $width * $max_height / $max_width;
	//if the new width is greater than the actual width of the image, then the height is too large and the rest cut off, or vice versa
	if($width_new > $width){
		//cut point by height
		$h_point = (($height - $height_new) / 2);
		//copy image
		imagecopyresampled($dst_img, $src_img, 0, 0, 0, $h_point, $max_width, $max_height, $width, $height_new);
	}else{
		//cut point by width
		$w_point = (($width - $width_new) / 2);
		imagecopyresampled($dst_img, $src_img, 0, 0, $w_point, 0, $max_width, $max_height, $width_new, $height);
	}
	
	$image($dst_img, $dst_dir, $quality);

	if($dst_img)imagedestroy($dst_img);
	if($src_img)imagedestroy($src_img);
}
//usage example
resize_crop_image(100, 100, "test.jpg", "test.jpg");
This entry was posted in Programming and tagged , , , .

30 Responses to Resize and crop image from center with PHP

  1. Carlos

    It's just what I was looking for!! Thank you very much!!

    • You are welcome! I just found there is not set quality for jpeg, so I added $quality = 80; in line 23, else imagejpeg function will use default value 75.

  2. hungdungktv

    good!

  3. Thanks a lot !
    Works great from scratch. Adjusted it for my project with success. 🙂

  4. berhane

    Thanx buddy for this! haven't implemented it yet, but seems as others have had great success with it.

    Thanks for sharing - highly appreciated!

  5. Van

    Good JOB

  6. Dino

    Just perfect!

  7. Works perfect, thank you

  8. Tim

    I've made a JQuery/HTML5 image preview before upload which can see on JSFiddle here: http://jsfiddle.net/qohtqje5/

    If possible, how would I call:

    resize_crop_image(100, 100, "test.jpg", "test.jpg");

    replacing "test.jpg" with the users local image then upload to img/thumbs/ please?

    • To call resize_crop_image you need upload image to server so php can access image.

      • Tim

        Thank you Aleksandras, I've not set my image to upload to the temp location $_FILES["file"]["tmp_name"]. My full script can be seen here with a password set to *********.

        How do I call upon your script to crop to a square then resize to 120x120px?

        • Tim

          I tired adding your script then the following which did not work:resize_crop_image(120, 120, $_FILES["file"]["tmp_name"], "../Desktop/IMG/BananzaNews/Thumbs/");

          • $dst_dir must be file name or path to file, but you set just directory. You can use functon just after image uploaded and moved:

            if(isset($_POST['submitted'])){
            	$file = 'D:/www/home/polyetilen/test/'.$_FILES['file']['name'];
            	move_uploaded_file($_FILES['file']['tmp_name'], $file);
            	resize_crop_image(120, 120, $file, $file);
            }
            
            • Tim

              How would I modify your script to be implemented in this part;

              // preserve file from temporary directory
              $success = move_uploaded_file($myFile["tmp_name"],
              	UPLOAD_DIR . $name);
              	$img = "http://www.rafflebananza.com/Desktop/IMG/BananzaNews/Thumbs/" . $_FILES["file"]["name"];
              if (!$success) { 
              	echo "Unable to save file.";
              	exit;
              }
              

              Thank you for your help so far, I am very appreciative! This is my most advanced suite so far for my charity. My first database, submitting, reading and whatnot. It'll click with me one day! 🙂

              • Tim

                Oh and how do I wrap code nicely like you have done? I tried wrapping in code tags but it didn't seem to work?

              • You can make thumb just after expression:

                // preserve file from temporary directory
                $success = move_uploaded_file($myFile["tmp_name"], UPLOAD_DIR . $name);
                $img = "http://www.rafflebananza.com/Desktop/IMG/BananzaNews/Thumbs/" . $_FILES["file"]["name"];
                if (!$success) {
                	echo "Unable to save file.";
                	exit;
                }
                resize_crop_image(120, 120, UPLOAD_DIR . $name, $img);
                

                I wrap code with [ php ]code[ /php ] without spaces

                • Tim

                  Well at long last the uploaded image is now in fact 120x120px! I uploaded this image and the outcome can be found here however it did not keep the transparency...

  9. how to keep image max height with original instead of fixed defined image height width ?

    • Get original image height and send to function:

      //get image original height
      $source_file = 'test.jpg';
      $imgsize = getimagesize($source_file);
      $height = $imgsize[1];
      //crop and keep image original height
      resize_crop_image(100, $height, $source_file, "cropped.jpg");
      
  10. ankit

    Thanks for function,,it really helpful for me...

    improve function

    function resize_crop_image($max_width, $max_height, $source_file, $dst_dir, $quality = 80) {
        $imgsize = getimagesize($source_file);
        $width = $imgsize[0];
        $height = $imgsize[1];
        $mime = $imgsize['mime'];
    
        switch ($mime) {
            case 'image/gif':
                $image_create = "imagecreatefromgif";
                $image = "imagegif";
                break;
    
            case 'image/png':
                $image_create = "imagecreatefrompng";
                $image = "imagepng";
                $quality = 7;
                break;
    
            case 'image/jpeg':
                $image_create = "imagecreatefromjpeg";
                $image = "imagejpeg";
                $quality = 80;
                break;
    
            default:
                return false;
                break;
        }
    
        $dst_img = imagecreatetruecolor($max_width, $max_height);
        ///////////////
    
        imagealphablending($dst_img, false);
        imagesavealpha($dst_img, true);
        $transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127);
        imagefilledrectangle($dst_img, 0, 0, $max_width, $max_height, $transparent);
    
    
        /////////////
        $src_img = $image_create($source_file);
    
        $width_new = $height * $max_width / $max_height;
        $height_new = $width * $max_height / $max_width;
        //if the new width is greater than the actual width of the image, then the height is too large and the rest cut off, or vice versa
        if ($width_new > $width) {
            //cut point by height
            $h_point = (($height - $height_new) / 2);
            //copy image
            imagecopyresampled($dst_img, $src_img, 0, 0, 0, $h_point, $max_width, $max_height, $width, $height_new);
        } else {
            //cut point by width
            $w_point = (($width - $width_new) / 2);
            imagecopyresampled($dst_img, $src_img, 0, 0, $w_point, 0, $max_width, $max_height, $width_new, $height);
        }
    
        $image($dst_img, $dst_dir, $quality);
    
        if ($dst_img)
            imagedestroy($dst_img);
        if ($src_img)
            imagedestroy($src_img);
    }
    
    //usage example
    resize_crop_image(400, 500, "videos/thumb.png", "fd/image2.jpg");
    
  11. Gorki

    I Really Like Your Script, thnx for it
    but what i need is after Cropping image just display to browser, not save to disk..???
    is it Possible.. How?

    • Yes, it is possible. Just add header for each image format and for filename ($dst_dir) use null, so this line

      $image($dst_img, $dst_dir, $quality);
      

      for jpg image change to:

      header('Content-Type: image/jpeg');
      $image($dst_img, null, $quality);
      

      You can add header selection for each image format in switch statement or echo it before function.

  12. FRED

    Thanks ... saved me hours of work

  13. Danilo de Oliveira

    Perfect!
    I love you, guy!

  14. red hat

    Thank you !! you saved my day

  15. Ruth

    Muchas gracias por compartir. Funciona perfecto!

  16. Rodrigo Barbosa

    Great.
    Work perfectly.
    Thank you!!!

  17. Todo perfecto a nivel de navegador y visiblemente funciona muy bien.
    Sin embargo en PHP 8.3 en el error_log me sale "obsoleto": La conversión implícita de float (nro) a int pierde precisión en (...)
    La linea de error da exactamente en: imagecopyresampled();

    Como se podria solucionar eso? No me agrada que el servidor me genere los error_log's. Aunque aparentemente me funcione perfecto.

    • Wolfgang

      Solucionado:
      $h_point = (($height - $height_new) / 2);
      $h_point = intval($h_point);
      y en
      $w_point = (($width - $width_new) / 2);
      $w_point = intval($w_point);

Leave a Reply

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.