markf
markf

Reputation: 83

Use PHP to create thumbnails. (Cropped to square)

I have a php script im currently using that creates thumbnails based on a max width and height. However, I'd like it to always create square images and crop the images when needed.

Here is what I'm using now:

    function makeThumb( $filename, $type ) {
  global $max_width, $max_height;
  if ( $type == 'jpg' ) {
   $src = imagecreatefromjpeg("blocks/img/gallery/" . $filename);
  } else if ( $type == 'png' ) {
   $src = imagecreatefrompng("blocks/img/gallery/" . $filename);
  } else if ( $type == 'gif' ) {
   $src = imagecreatefromgif("blocks/img/gallery/" . $filename);
  }
  if ( ($oldW = imagesx($src)) < ($oldH = imagesy($src)) ) {
   $newW = $oldW * ($max_width / $oldH);
   $newH = $max_height;
  } else {
   $newW = $max_width;
   $newH = $oldH * ($max_height / $oldW);
  }
  $new = imagecreatetruecolor($newW, $newH);
  imagecopyresampled($new, $src, 0, 0, 0, 0, $newW, $newH, $oldW, $oldH);
  if ( $type == 'jpg' ) {
   imagejpeg($new, 'blocks/img/gallery/thumbs/'.$filename);
  } else if ( $type == 'png' ) {
   imagepng($new, 'blocks/img/gallery/thumbs/'.$filename);
  } else if ( $type == 'gif' ) {
   imagegif($new, 'blocks/img/gallery/thumbs/'.$filename);
  }
  imagedestroy($new);
  imagedestroy($src);
 }

How would I alter this to accomplish what I want (Square thumbs)?

Thanks in advance.

Upvotes: 3

Views: 14734

Answers (5)

Luke Stevenson
Luke Stevenson

Reputation: 10341

function makeThumb( $filename , $thumbSize=100 ){
  global $max_width, $max_height;

  // Set Filenames
  $srcFile = 'blocks/img/gallery/'.$filename;
  $thumbFile = 'blocks/img/gallery/thumbs/'.$filename;

  // Determine the File Type
  $type = substr( $filename , strrpos( $filename , '.' )+1 );

  // Create the Source Image
  switch( $type ){
    case 'jpg' :
    case 'jpeg' :
      $src = imagecreatefromjpeg( $srcFile ); break;
    case 'png' :
      $src = imagecreatefrompng( $srcFile ); break;
    case 'gif' :
      $src = imagecreatefromgif( $srcFile ); break;
  }

  // Determine the Image Dimensions
  $oldW = imagesx( $src );
  $oldH = imagesy( $src );

  // Calculate the New Image Dimensions
  $limiting_dim = 0;

  if( $oldH > $oldW ){
    // Portrait
    $limiting_dim = $oldW;
  }else{
    // Landscape
    $limiting_dim = $oldH;
  }

  // Create the New Image
  $new = imagecreatetruecolor( $thumbSize , $thumbSize );

  // Transcribe the Source Image into the New (Square) Image
  imagecopyresampled( $new , $src , 0 , 0 , ($oldW-$limiting_dim )/2 , ( $oldH-$limiting_dim )/2 , $thumbSize , $thumbSize , $limiting_dim , $limiting_dim );

  // Output the image to the file
  switch( $type ){
    case 'jpg' :
    case 'jpeg' :
      $src = imagejpeg( $new , $thumbFile ); break;
    case 'png' :
      $src = imagepng( $new , $thumbFile ); break;
    case 'gif' :
      $src = imagegif( $new , $thumbFile ); break;
  }

  // Free up the memory
  imagedestroy( $new );
  imagedestroy( $src );
}

Hat Tip to @Sam Wan for the adjusted solution. Sorry it took me so long to incorporate it into this answer.

Upvotes: 15

luba
luba

Reputation: 122

Since we have multiple partial solutions here (credits to Luke Stevenson and Sam Wan) I felt the need to put the pieces together. This is a complete solution of the two answers plus some additional features:

  • Additional function params like the base + thumb dir names.

  • An overwrite bool param in order to fastload the page when thumbnails exist already.

  • Check if the thumb dir exists; if not it is created.

  • Fix of the imagedestroy($src); issue.

/**
 * Function to create a thumbnail of an image.
 * See https://stackoverflow.com/questions/2686000/use-php-to-create-thumbnails-cropped-to-square
 * @param $basePath
 * @param $filename
 * @param string $thumbDirName
 * @param int $thumbSize
 * @param bool $overwrite
 * @return bool|null
 */
function makeThumb($basePath, $filename, $thumbDirName = 'thumbs', $thumbSize = 150, $overwrite = false)
{
    /* Configure paths. */
    $basePath = rtrim($basePath, '/') . '/';
    $thumbDirName = trim($thumbDirName, '/') . '/';
    $srcFile = $basePath . $filename;
    $thumbBasePath = $basePath . $thumbDirName;
    
    if (!is_dir($thumbBasePath)) {
        if(!mkdir($thumbBasePath, 0755)){
            throw new RuntimeException('could not create thumb dir: ' . $thumbBasePath);
        }
    }
    
    $thumbServerPath = $thumbBasePath . $filename;
    if(!$overwrite){
        /* Check if thumbnail exists already. */
        if(file_exists($thumbServerPath)){
            return null;
        }
    }

    /* Determine the File Type */
    $type = substr($filename, strrpos($filename, '.') + 1);
    /* Create the Source Image */
    switch ($type) {
        case 'jpg' :
        case 'jpeg' :
            $src = imagecreatefromjpeg($srcFile);
            break;
        case 'png' :
            $src = imagecreatefrompng($srcFile);
            break;
        case 'gif' :
            $src = imagecreatefromgif($srcFile);
            break;
        default:
            return false;
    }
    /* Determine the Image Dimensions */
    $oldW = imagesx($src);
    $oldH = imagesy($src);

    /* Calculate the New Image Dimensions */
    $limiting_dim = $oldH; /* Landscape */
    if( $oldH > $oldW ){
        $limiting_dim = $oldW; /* Portrait */
    }

    /* Create the New Image */
    $new = imagecreatetruecolor( $thumbSize , $thumbSize );

    /* Transcribe the Source Image into the New (Square) Image */
    imagecopyresampled( $new , $src , 0 , 0 , ($oldW-$limiting_dim )/2 , ( $oldH-$limiting_dim )/2 , $thumbSize , $thumbSize , $limiting_dim , $limiting_dim );

    switch ($type) {
        case 'jpg' :
        case 'jpeg' :
            imagejpeg($new, $thumbServerPath);
            break;
        case 'png' :
            imagepng($new, $thumbServerPath);
            break;
        case 'gif' :
            imagegif($new, $thumbServerPath);
            break;
    }
    imagedestroy($new);
    imagedestroy($src);

    return true;
}

Upvotes: 0

Hector
Hector

Reputation: 682

This modified function worked great for me

public function igImagePrepare($img,$name){
    $dir = 'my-images/';
    $img_name = $name.'-'.uniqid().'.jpg';

    //Your Image
    $imgSrc = $img;

    //getting the image dimensions
    list($width, $height) = getimagesize($imgSrc);

    //saving the image into memory (for manipulation with GD Library)
    $myImage = imagecreatefromjpeg($imgSrc);

    $square_size = 400;

    $width = imagesx( $myImage );
    $height = imagesy( $myImage );


                //set dimensions
                if($width> $height) {
                        $width_t=$square_size;
                        //respect the ratio
                        $height_t=round($height/$width*$square_size);
                        //set the offset
                        $off_y=ceil(($width_t-$height_t)/2);
                        $off_x=0;
                } elseif($height> $width) {
                        $height_t=$square_size;
                        $width_t=round($width/$height*$square_size);
                        $off_x=ceil(($height_t-$width_t)/2);
                        $off_y=0;
                }
                else {
                        $width_t=$height_t=$square_size;
                        $off_x=$off_y=0;
                }


   /* Create the New Image */
    $new = imagecreatetruecolor( $square_size , $square_size );
   /* Transcribe the Source Image into the New (Square) Image */
    $bg = imagecolorallocate ( $new, 255, 255, 255 );
    imagefill ( $new, 0, 0, $bg );
    imagecopyresampled( $new , $myImage , $off_x, $off_y, 0, 0, $width_t, $height_t, $width, $height );

    //final output
    imagejpeg($new, $dir.$img_name);

    return $dir.$img_name;
  }

Upvotes: 0

Sam Wan
Sam Wan

Reputation: 196

   /* Calculate the New Image Dimensions */
   $limiting_dim = 0;
    if( $oldH > $oldW ){
     /* Portrait */
      $limiting_dim = $oldW;
    }else{
     /* Landscape */
      $limiting_dim = $oldH;
    }
   /* Create the New Image */
    $new = imagecreatetruecolor( $thumbSize , $thumbSize );
   /* Transcribe the Source Image into the New (Square) Image */
    imagecopyresampled( $new , $src , 0 , 0 , ($oldW-$limiting_dim )/2 , ( $oldH-$limiting_dim )/2 , $thumbSize , $thumbSize , $limiting_dim , $limiting_dim );

I don't have enough karma to comment on the accepted answer (Lucanos') but I found that the answer above gave black bars on the side of the thumbnail.

This code snippet (combined with the accepted answer) should copy the relevant sections of the src image without going out of bounds and producing black bars. The thumbnail is still square as per the original question.

Upvotes: 16

Rich Adams
Rich Adams

Reputation: 26574

You want to work out an offset rather than a new width/height so that the new sample stays in proportion, then use the offset when generating the new image and give it a fixed width/height so that it'll crop to a square. A quick example that would make a 100x100 thumb (note: untested),

// Get dimensions of the src image.
list($oldW, $oldH) = getimagesize($filename);

// Work out what offset to use
if ($oldH < $oldW) 
{
    $offH = 0;
    $offW = ($oldW-$oldH)/2;
    $oldW = $oldH;
} 
elseif ($oldH > $oldW) 
{
    $offW = 0;
    $offH = ($oldH-$oldW)/2;
    $oldH = $oldW;
} 
else 
{
    $offW = 0;
    $offH = 0;
}                

// Resample the image into the new dimensions.
$new = imagecreatetruecolor(100, 100);
imagecopyresampled($new, $src, 0, 0, $offW, $offH, 100, 100, $oldW, $oldH);

Upvotes: 2

Related Questions