CakePHP Image helper

22/04/2008 Written by: Chris

I wrote this image helper cause i needed it on my site, there was another one allready available on the bakery. However this did not meet my needs, this image helper has a resize for thumbnails, and a resize and crop which will cut off the top and bottm or left and right if it does fit the entered size. It also saves transparent png's which the other did not and caches the images.

Here is how you can use it.

  1. <?php
  2. echo $image->resizeAndCrop($file['filename'], 150, 100, array('class' => 'thumb'));  
  3. ?>

Or if you just want a normal resize of the picture without cropping it.

  1. <?php
  2. echo $image->resize($file['filename'], 150, 100, array('class' => 'thumb'));  
  3. ?>

It's easy as that, just make sure you have a 'uploaded' directory in the webroot that is writable, and a 'imagecache' directory in the img directory. These are defined in.

  1. <?php
  2. $this->imgpath = WWW_ROOT.'uploaded'.DS;
  3. $this->imgCachePath = IMAGES.'imagecache'.DS;
  4. ?>

Ok enough jiba jaba.. here is the code.

  1. <?php
  2. /**
  3.  * Helper to modify images, create thumbnails etc
  4.  ** PHP version 5
  5.  *
  6.  * @author Chris de Kok http://www.mech7.net
  7.  * @version $Rev$
  8.  *
  9.  */
  10. class ImageHelper {
  11.         /**
  12.          * Other helpers used only html
  13.          *
  14.          * @var array
  15.          */
  16.         public $helpers = array('Html');
  17.        
  18.         /**
  19.          * Path to the image directory
  20.          *
  21.          * @var string
  22.          */
  23.         public $imgpath;
  24.         /**
  25.          * Path to the image cache directory
  26.          *
  27.          * @var string
  28.          */
  29.         public $imgCachePath;
  30.         /**
  31.          * Relative path to the cached image
  32.          */
  33.         public $relativeImgPath;
  34.        
  35.         /**
  36.          * Old image
  37.          */
  38.         private $oldImage;
  39.         /**
  40.          * Working image
  41.          */
  42.         private $workingImage;
  43.         /**
  44.          * New image
  45.          */
  46.         private $newImage;
  47.         /**
  48.          * Current size of image after editing contains an array
  49.          * with width / height
  50.          * @var array
  51.          */
  52.         private $currentSize = array();
  53.         /**
  54.          * Contains the filetype for the image either JPG, PNG, GIF or false
  55.          */
  56.         private $fileType;
  57.         /**
  58.          * Class constructor check if gd is installed
  59.          *
  60.          */
  61.         public function __construct(){
  62.                
  63.                 // Setup paths
  64.                 $this->imgpath = WWW_ROOT.'uploaded'.DS;
  65.                 $this->imgCachePath = IMAGES.'imagecache'.DS;
  66.                 $this->relativeImgPath = 'imagecache/';
  67.                
  68.                 if(!function_exists("gd_info")) {
  69.                         echo 'You do not have the GD Library installed.  This class requires the GD library to function properly.' . "\n";
  70.                         echo 'visit http://us2.php.net/manual/en/ref.image.php for more information';
  71.                         exit;
  72.                 }              
  73.                
  74.                 if (!is_dir($this->imgCachePath)) {
  75.                         echo 'Cache directory does not exists: '. $this->imgCachePath;
  76.                         exit()
  77.                 }
  78.                 if (!is_writable($this->imgCachePath)) {
  79.                         echo 'Cache directory is not writable: '.$this->imgCachePath;
  80.                         exit();
  81.                 }
  82.         }
  83.         /**
  84.          * Method to resize an image it will resize to the largest possible value if $largest
  85.          * is set to true. This is used in the crop function will it will cut the rest of the
  86.          * top / bottom if you need it. $return to true, saves the image to the cache and
  87.          * returns the html.
  88.          *
  89.          * @access public
  90.          * @param string $file
  91.          * @param integer $width
  92.          * @param integer $height
  93.          * @param array $htmlAttributes
  94.          * @param boolean $largest
  95.          * @param booelean $return
  96.          */
  97.         public function resize($file, $width, $height, $htmlAttributes = false, $largest = false, $return = true){
  98.                 $file_path = $this->imgpath.$file;             
  99.                 $file_type = $this->checkFile($file_path);
  100.                 if($this->fileType){
  101.                
  102.                         // Get new dimensions
  103.                         list($width_orig, $height_orig) = getimagesize($file_path);
  104.                         $ratio_orig = $width_orig/$height_orig;
  105.                         if($largest){
  106.                                 if ($width/$height < $ratio_orig) {
  107.                                         $width = $height*$ratio_orig;
  108.                                 } else {
  109.                                         $height = $width/$ratio_orig;
  110.                                 }
  111.                         } else {
  112.                                 if ($width/$height > $ratio_orig) {
  113.                                         $width = $height*$ratio_orig;
  114.                                 } else {
  115.                                         $height = $width/$ratio_orig;
  116.                                 }
  117.                         }
  118.                         $this->currentSize['width'] = $width;
  119.                         $this->currentSize['height'] = $height;
  120.                         /**
  121.                          * If file is allready cached return html
  122.                          */
  123.                         $cache_filename = 'r_'.$width.'_'.$height.'_'.$file;                   
  124.                         if($return && $this->checkCache($file_path, $cache_filename)){                 
  125.                                 return $this->Html->image($this->relativeImgPath.$cache_filename, $htmlAttributes);
  126.                         }                      
  127.                         switch($this->fileType) {
  128.                                 case 'GIF':
  129.                                         $this->oldImage = ImageCreateFromGif($file_path);
  130.                                         break;
  131.                                 case 'JPG':
  132.                                         $this->oldImage = ImageCreateFromJpeg($file_path);
  133.                                         break;
  134.                                 case 'PNG':
  135.                                         $this->oldImage = ImageCreateFromPng($file_path);
  136.                                         break;
  137.                         }
  138.                         $this->workingImage = imagecreatetruecolor($this->currentSize['width'], $this->currentSize['height']);
  139.                         if($this->fileType == 'PNG'){
  140.                                 imagesavealpha($this->workingImage, true);
  141.                         $trans_colour = imagecolorallocatealpha($this->workingImage, 0, 0, 0, 127);
  142.                         imagefill($this->workingImage, 0, 0, $trans_colour);
  143.                         }
  144.                        
  145.                         imagecopyresampled($this->workingImage, $this->oldImage, 0, 0, 0, 0, $this->currentSize['width'], $this->currentSize['height'], $width_orig, $height_orig);
  146.                         if($return){                           
  147.                                 // Save image to cache and return html
  148.                                 $this->newImage = $this->workingImage;
  149.                                 $this->saveFile($this->imgCachePath.$cache_filename);                          
  150.                                 return $this->Html->image($this->relativeImgPath.$cache_filename, $htmlAttributes);
  151.                         }
  152.                 }
  153.         }
  154.         /**
  155.          * Method to resize and crop the image if height and width are larger than the
  156.          * values from the parameters
  157.          *
  158.          * @param string $file
  159.          * @param integer $width
  160.          * @param integer $height
  161.          * @param array $htmlAttributes
  162.          */
  163.         public function resizeAndCrop($file, $width = 150, $height = 100, $htmlAttributes = false){
  164.                 $file_path = $this->imgpath.DS.$file;
  165.                 $cache_filename = 'rc_'.$width.'_'.$height.'_'.$file;          
  166.                 $file_type = $this->checkFile($file_path);
  167.                 if($this->fileType){
  168.                         /**
  169.                          * Image is cached allready return html with image
  170.                          */
  171.                         if($this->checkCache($file_path, $cache_filename)){                            
  172.                                 return $this->Html->image($this->relativeImgPath.$cache_filename, $htmlAttributes);
  173.                         }
  174.                         $this->resize($file, $width, $height, false, true, false);
  175.                         $cropX = intval(($this->currentSize['width'] - $width) / 2);
  176.                         $cropY = intval(($this->currentSize['height'] - $height) / 2);
  177.                          
  178.                         $this->newImage = imagecreatetruecolor ($width, $height);
  179.                        
  180.                         if($this->fileType == 'PNG'){
  181.                                 imagesavealpha($this->newImage, true);
  182.                         $trans_colour = imagecolorallocatealpha($this->newImage, 0, 0, 0, 127);
  183.                         imagefill($this->newImage, 0, 0, $trans_colour);
  184.                         }
  185.                         imagecopyresampled ($this->newImage, $this->workingImage, 0, 0, $cropX, $cropY, $this->currentSize['width'], $this->currentSize['height'], $this->currentSize['width'], $this->currentSize['height']);
  186.                         $this->saveFile($this->imgCachePath.$cache_filename);
  187.                         return $this->Html->image($this->relativeImgPath.$cache_filename, $htmlAttributes);
  188.                 }
  189.         }
  190.         /**
  191.          * Method to check filetype and if it is readable and exists
  192.          * return false or PNG, GIF, JPG depending on filetype
  193.          *
  194.          * @param string $file
  195.          */
  196.         public function checkFile($file = false){
  197.                 if($file){
  198.                         //check to see if file exists
  199.                         if(!file_exists($file) OR !is_readable($file)) {
  200.                                 return false;
  201.                         }
  202.                         //check if gif
  203.                         if(stristr(strtolower($file),'.gif')){
  204.                                 $this->fileType = 'GIF';
  205.                         }
  206.                         //check if jpg
  207.                         elseif(stristr(strtolower($file),'.jpg') || stristr(strtolower($file),'.jpeg')){
  208.                                 $this->fileType = 'JPG';
  209.                         }
  210.                         //check if png
  211.                         elseif(stristr(strtolower($file),'.png')){
  212.                                 $this->fileType = 'PNG';
  213.                         }
  214.                         //unknown file format
  215.                         else {
  216.                                 $this->fileType = false;
  217.                         }
  218.                 }
  219.         }
  220.         /**
  221.          * Method to check if the file is allready saved in the cache
  222.          * returns false or true wether the file needs to be saved.
  223.          * The first param $file needs to be the name to the original file,
  224.          * the second param $cached_file is the what the cached filename
  225.          * should be
  226.          *
  227.          * @access private
  228.          * @param string $file
  229.          * @param string $cached_file
  230.          * @return boolean;
  231.          */
  232.         private function checkCache($file = null, $cache_file = null){         
  233.                 if($file && $cache_file){                      
  234.                         // Original file
  235.                         $file = $this->imgpath.DS.$file;
  236.                         // Cached file
  237.                         $cachefile = $this->imgCachePath.$cache_file;
  238.                         if (file_exists($cachefile)) {
  239.                                 if (@filemtime($cachefile) < @filemtime($file)){
  240.                                         return false;
  241.                                 }
  242.                         } else {
  243.                                 return false;
  244.                         }
  245.                         return true;
  246.                 }
  247.         }
  248.         /**
  249.          * Method to save the file to the cache
  250.          *
  251.          * @param string $file_name
  252.          */
  253.         public function saveFile($file_name){
  254.                 switch($this->fileType) {
  255.                         case 'GIF':
  256.                                 ImageGif($this->newImage,$file_name);
  257.                                 break;
  258.                         case 'JPG':
  259.                                 ImageJpeg($this->newImage,$file_name,100);
  260.                                 break;
  261.                         case 'PNG':
  262.                                 ImagePng($this->newImage,$file_name);
  263.                                 break;
  264.                 }
  265.         }
  266.         /**
  267.          * Class destructor
  268.          *
  269.          */
  270.         public function __destruct() {
  271.                 if(is_resource($this->newImage)) @ImageDestroy($this->newImage);
  272.                 if(is_resource($this->oldImage)) @ImageDestroy($this->oldImage);
  273.                 if(is_resource($this->workingImage)) @ImageDestroy($this->workingImage);
  274.         }
  275. }
  276. ?>

Related tags