Image Resize Helper

by hundleyj
I am in the process of writing an online store with Cake and needed a helper that would automatically resize images into thumbnails.
This helper resizes an image on the fly and places it in an image cache directory for later use. Make sure your imagecache directory is writable. Future editions could include a cropping function.

Helper Class:

<?php 
class ImageHelper extends Helper {

    var 
$helpers = array('Html');
    
    var 
$cacheDir 'imagecache'// relative to IMAGES_URL path
    
/**
 * Automatically resizes an image and returns formatted IMG tag
 *
 * @param string $path Path to the image file, relative to the webroot/img/ directory.
 * @param integer $width Image of returned image
 * @param integer $height Height of returned image
 * @param boolean $aspect Maintain aspect ratio (default: true)
 * @param array    $htmlAttributes Array of HTML attributes.
 * @param boolean $return Wheter this method should return a value or output it. This overrides AUTO_OUTPUT.
 * @return mixed    Either string or echos the value, depends on AUTO_OUTPUT and $return.
 * @access public
 */
    
function resize($path$width$height$aspect true$htmlAttributes = array(), $return false) {
        
        
$types = array(=> "gif""jpeg""png""swf""psd""wbmp"); // used to determine image type
        
        
$fullpath ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS.$this->themeWeb.IMAGES_URL;
    
        
$url $fullpath.$path;
        
        if (!(
$size getimagesize($url))) 
            return; 
// image doesn't exist
            
        
if ($aspect) { // adjust to aspect.
            
if (($size[1]/$height) > ($size[0]/$width))  // $size[0]:width, [1]:height, [2]:type
                
$width ceil(($size[0]/$size[1]) * $height);
            else 
                
$height ceil($width / ($size[0]/$size[1]));
        }
        
        
        
$relfile $this->webroot.$this->themeWeb.IMAGES_URL.$this->cacheDir.'/'.$width.'x'.$height.'_'.basename($path); // relative file
        
$cachefile $fullpath.$this->cacheDir.DS.$width.'x'.$height.'_'.basename($path);  // location on server
        
        
if (file_exists($cachefile)) {
            
$csize getimagesize($cachefile);
            
$cached = ($csize[0] == $width && $csize[1] == $height); // image is cached
            
if (@filemtime($cachefile) < @filemtime($url)) // check if up to date
                
$cached false;
        } else {
            
$cached false;
        }
        
        if (!
$cached) {
            
$resize = ($size[0] > $width || $size[1] > $height) || ($size[0] < $width || $size[1] < $height);
        } else {
            
$resize false;
        }
        
        if (
$resize) {
            
$image call_user_func('imagecreatefrom'.$types[$size[2]], $url);
            if (
function_exists("imagecreatetruecolor") && ($temp imagecreatetruecolor ($width$height))) {
                
imagecopyresampled ($temp$image0000$width$height$size[0], $size[1]);
              } else {
                
$temp imagecreate ($width$height);
                
imagecopyresized ($temp$image0000$width$height$size[0], $size[1]);
            }
            
call_user_func("image".$types[$size[2]], $temp$cachefile);
            
imagedestroy ($image);
            
imagedestroy ($temp);
        }         
        
        return 
$this->output(sprintf($this->Html->tags['image'], $relfile$this->Html->parseHtmlOptions($htmlAttributesnull''' ')), $return);
    }
?>

To use:

echo $image->resize('myimage.jpg', 150, 150, true);

Report

More on Helpers

Advertising

Comments

  • earthtech posted on 04/18/11 01:25:25 PM
    There is one problem. When I upload a big file and I try to display it using the helper I get the following error:

    "Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 10444 bytes) in /usr/local/psa/home/vhosts/sportschoolgekoning.nl/httpdocs/app/views/helpers/image.php on line 58"

    Is there a solution to this problem?

    Thanks
  • Michael posted on 03/09/10 07:01:05 AM
    Hi,

    Here is a small patch to the your latest ImageHelper:

    --- /home/michael/tmp/image.php 2010-03-09 13:37:25.000000000 +0200                                                                                                                     
    +++ /home/michael/tmp/image.php.patched 2010-03-09 15:02:06.000000000 +0200                                                                                                             
    @@ -158,20 +158,19 @@                                                                                                                                                                   
             if ($resize) {                                                                                                                                                                 
                 $image = call_user_func('imagecreatefrom'.$types[$size[2]], $url);                                                                                                         
                                                                                                                                                                                            
    -            if($crop)                                                                                                                                                                  
    -            {                                                                                                                                                                          
    +            if($crop) {                                                                                                                                                                
                     if (function_exists("imagecreatetruecolor") && ($tempcrop = imagecreatetruecolor ($cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1]))) {                            
    -                imagecopyresampled ($tempcrop, $image, 0, 0, $cropvars[0], $cropvars[1], $cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1], $cropvars[2] - $cropvars[0], $cropvars[3]-$cropvars[1]);                                                                                                                                                                        
    +                       imagecopyresampled ($tempcrop, $image, 0, 0, $cropvars[0], $cropvars[1], $cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1], $cropvars[2] - $cropvars[0], $cropvars[3]-$cropvars[1]);                                                                                                                                                                 
                   } else {                                                                                                                                                                 
    -                $temp = imagecreate ($cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1]);                                                                                            
    -                imagecopyresized ($tempcrop, $image, 0, 0, $cropvars[0], $cropvars[1], $cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1], $size[0], $size[1]);                      
    -            }                                                                                                                                                                          
    +                       $tempcrop = imagecreate ($cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1]);                                                                                 
    +                       imagecopyresized ($tempcrop, $image, 0, 0, $cropvars[0], $cropvars[1], $cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1], $size[0], $size[1]);               
    +               }                                                                                                                                                                       
                                                                                                                                                                                            
    -            $image = $tempcrop;                                                                                                                                                        
    -            }                                                                                                                                                                          
    +               $image = $tempcrop;                                                                                                                                                     
                                                                                                                                                                                            
    -            $size[0] = $cropvars[2] - $cropvars[0];                                                                                                                                    
    -            $size[1] = $cropvars[3] - $cropvars[1];                                                                                                                                    
    +               $size[0] = $cropvars[2] - $cropvars[0];                                                                                                                                 
    +               $size[1] = $cropvars[3] - $cropvars[1];                                                                                                                                 
    +            }                                                                                                                                                                          
                                                                                                                                                                                            
                 if (function_exists("imagecreatetruecolor") && ($temp = imagecreatetruecolor ($width, $height))) {                                                                         
                     imagecopyresampled ($temp, $image, 0, 0, 0, 0, $width, $height, $size[0], $size[1]);                                                                                   
    @@ -193,5 +192,6 @@                                                                                                                                                                     
                                                                                                                                                                                            
             return $this->output(sprintf($this->Html->tags['image'], $relfile, $this->Html->_parseAttributes($htmlAttributes, null, '', ' ')), $return);                                   
         }                                                                                                                                                                                  
    -                                                                                                                                                                                       
    +                                                                                                                                                                                       
    +}                                                                                                                                                                                      
     ?>                

    Thanks for the great helper!
  • revenantprime posted on 03/09/10 04:11:19 AM
    Fixed some bugs, here's the new code

    If you want to crop the center of an image, you'll need to supply your own logic to decide the relevant cropvars for that.

    I've also added an option autocrop which, if you just supply a width and a height for the output image (and don't set anything for cropvars), it will grab as much of the image as possible given this aspect ratio and output the resulting image. NOTE: if your crop area is bigger than the image, for some reason, it will resample the image to make it LARGER resulting in quality loss, keep that in mind.

    Say I wanted to crop an image 100x150 from a given area I'd call:

    $image->resize("blah.jpg", 100, 150, true, true, array(100, 100, 200, 250), false)

    This will crop a 100x150 area starting from position (100, 100) and ending at position (200, 250). So basically your cropvars are a set of two x,y coordinates for the start and end position of the crop, useful if you're using on the frontend say cropper.js or another script that can be used to gather coordinates for where you want to initiate the crop. Note, these coordinates can be bigger than the crop area (obviously) so that, as long as the area of the region you specify via the cropvars is the same aspect ratio, it will result in a resized sample of that portion of the image.

    If I wanted to autocrop a 100x150 area I'd call

    $image->resize("blah.jpg", 100, 150, true, true, array(), true)

    I might modify it to allow you to set say, maximum values for each dimension so that if you needed an image that could be any height but not wider than 100px you can autocrop it.

    :)


    <?php 
    class ImageHelper extends Helper {

        var 
    $helpers = array('Html');
        
        var 
    $cacheDir 'imagecache'// relative to IMAGES_URL path
        
    /**
     * Automatically resizes an image and returns formatted IMG tag
     *
     * @param string $path Path to the image file, relative to the webroot/img/ directory.
     * @param integer $width Image of returned image
     * @param integer $height Height of returned image
     * @param boolean $aspect Maintain aspect ratio (default: true)
     * @param array    $htmlAttributes Array of HTML attributes.
     * @param boolean $return Wheter this method should return a value or output it. This overrides AUTO_OUTPUT.
     * @return mixed    Either string or echos the value, depends on AUTO_OUTPUT and $return.
     * @access public
     */
        
    function resize($path$width$height$aspect true$crop false$cropvars = array(), $autocrop false$htmlAttributes = array(), $return false) {
            
            
    $types = array(=> "gif""jpeg""png""swf""psd""wbmp"); // used to determine image type
            
            
    $fullpath ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS.$this->themeWeb.IMAGES_URL;
        
            
    //$url = $fullpath.$path;
            
    $url "img/" $path;
            
            
            if (!(
    $size getimagesize($url))) 
                return; 
    // image doesn't exist
            
            
    if($autocrop)
            {
                
    $multiplier 1.0;
                while((
    $width*$multiplier<$size[0]) && ($height*$multiplier<$size[1]))
                {
                    
    $multiplier += .01;
                }
                
                
    // make SURE we don't run over
                
    $multiplier -= .01;
                
                
    $cropw floor($width $multiplier);
                
    $croph floor($height $multiplier);
                
                
    //echo("$cropw $croph $width $height $multiplier $size[0] $size[1] <br />");
                ///die();
                
                
    $xindent = ($size[0] - $cropw)/2.0;
                
    $yindent = ($size[1] - $croph)/2.0;
                
                
    $startx floor($xindent);
                
    $endx $size[0] - ceil($xindent);
                
                
    $starty floor($yindent);
                
    $endy $size[1] - ceil($yindent);
                
                
    //echo("$xindent, $yindent -> leads to: $startx, $starty start and $endx, $endy end");
                //die();
                
                
    $cropvars = array($startx$starty$endx$endy);
            }
            
            if((
    $width $size[0] || $height $size[1]) && $autocrop)
            {
                
                
    $multiplier 1.0;
                while((
    $width*$multiplier>=$size[0]) || ($height*$multiplier>=$size[1]))
                {
                    
    $multiplier -= .01;
                }
                
                
    $cropw floor($width $multiplier);
                
    $croph floor($height $multiplier);
                
                
    //echo("$cropw $croph $width $height $multiplier $size[0] $size[1] <br />");
                ///die();
                
                
    $xindent = ($size[0] - $cropw)/2.0;
                
    $yindent = ($size[1] - $croph)/2.0;
                
                
    $startx floor($xindent);
                
    $endx $size[0] - ceil($xindent);
                
                
    $starty floor($yindent);
                
    $endy $size[1] - ceil($yindent);
                
                
    //echo("$xindent, $yindent -> leads to: $startx, $starty start and $endx, $endy end");
                //die();
                
                
    $cropvars = array($startx$starty$endx$endy);
                
            }
            
            
    // check that user supplied full start and stop coordinates
            
    if(sizeof($cropvars)==4
            {
                if(
    $cropvars[0] > $size[0] || $cropvars[1] > $size[1] || $cropvars[2] > $size[0] || $cropvars[3] > $size[1] || $cropvars[0] < || $cropvars[1] < || $cropvars[2] < || $cropvars[3] < 0)
                {
                    
    $crop false;
                }
            }
            else
            {
                
    $crop false;
            }
            
            
    // temporarily set size to this for aspect checking
            
    if($crop)
            {
                
    $tempsize = array($size[0], $size[1]);
                
    $size[0] = $cropvars[2]-$cropvars[0];
                
    $size[1] = $cropvars[3]-$cropvars[1];
            }
            
            if (
    $aspect) { // adjust to aspect
                
    if (($size[1]/$height) > ($size[0]/$width))  // $size[0]:width, [1]:height, [2]:type
                    
    $width ceil(($size[0]/$size[1]) * $height);
                else 
                    
    $height ceil($width / ($size[0]/$size[1]));
            }
            
            
    // set size back
            
    if($crop)
            {
                
    $size[0] = $tempsize[0];
                
    $size[1] = $tempsize[1];
            }
            
            if(
    $crop)
            {
                
    $cropstring $cropvars[0] . $cropvars[1] . $cropvars[2] . $cropvars[3] . '_';
            }
            else
            {
                
    $cropstring '';
            }
            
            
    $relfile $this->webroot.$this->themeWeb.IMAGES_URL.$this->cacheDir.'/'.$width.'x'.$height.'_'.$cropstring.basename($path); // relative file
            
    $cachefile $fullpath.$this->cacheDir.DS.$width.'x'.$height.'_'.$cropstring.basename($path);  // location on server
            
            
    if (file_exists($cachefile)) {
                
    $csize getimagesize($cachefile);
                
    $cached = ($csize[0] == $width && $csize[1] == $height); // image is cached
                
    if (@filemtime($cachefile) < @filemtime($url)) // check if up to date
                    
    $cached false;
            } else {
                
    $cached false;
            }
            
            if (!
    $cached) {
                
    $resize = ($size[0] > $width || $size[1] > $height) || ($size[0] < $width || $size[1] < $height);
            } else {
                
    $resize false;
            }
            
            if (
    $resize) {
                
    $image call_user_func('imagecreatefrom'.$types[$size[2]], $url);
                
                if(
    $crop)
                {
                    if (
    function_exists("imagecreatetruecolor") && ($tempcrop imagecreatetruecolor ($cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1]))) {
                    
    imagecopyresampled ($tempcrop$image00$cropvars[0], $cropvars[1], $cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1], $cropvars[2] - $cropvars[0], $cropvars[3]-$cropvars[1]);
                  } else {
                    
    $temp imagecreate ($cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1]);
                    
    imagecopyresized ($tempcrop$image00$cropvars[0], $cropvars[1], $cropvars[2]-$cropvars[0], $cropvars[3]-$cropvars[1], $size[0], $size[1]);
                }
                
                
    $image $tempcrop;
                }
                
                
    $size[0] = $cropvars[2] - $cropvars[0];
                
    $size[1] = $cropvars[3] - $cropvars[1];
                
                if (
    function_exists("imagecreatetruecolor") && ($temp imagecreatetruecolor ($width$height))) {
                    
    imagecopyresampled ($temp$image0000$width$height$size[0], $size[1]);
                  } else {
                    
    $temp imagecreate ($width$height);
                    
    imagecopyresized ($temp$image0000$width$height$size[0], $size[1]);
                }
                if(
    $types[$size[2]]=="jpeg")
                {
                    
    imagejpeg($temp$cachefile90);
                }
                else
                {
                    
    call_user_func("image".$types[$size[2]], $temp$cachefile);
                }
                
    imagedestroy ($image);
                
    imagedestroy ($temp);
            }         
            
            return 
    $this->output(sprintf($this->Html->tags['image'], $relfile$this->Html->_parseAttributes($htmlAttributesnull''' ')), $return);
        }
        
    ?>

    • izikeo posted on 07/23/11 03:53:35 PM
      [quote] Fixed some bugs, here's the new code

      If you want to crop the center of an image, you'll need to supply your own logic to decide the relevant cropvars for that.

      I've also added an option autocrop which, if you just supply a width and a height for the output image (and don't set anything for cropvars), it will grab as much of the image as possible given this aspect ratio and output the resulting image. NOTE: if your crop area is bigger than the image, for some reason, it will resample the image to make it LARGER resulting in quality loss, keep that in mind.

      Say I wanted to crop an image 100x150 from a given area I'd call:

      $image->resize("blah.jpg", 100, 150, true, true, array(100, 100, 200, 250), false)

      This will crop a 100x150 area starting from position (100, 100) and ending at position (200, 250). So basically your cropvars are a set of two x,y coordinates for the start and end position of the crop, useful if you're using on the frontend say cropper.js or another script that can be used to gather coordinates for where you want to initiate the crop. Note, these coordinates can be bigger than the crop area (obviously) so that, as long as the area of the region you specify via the cropvars is the same aspect ratio, it will result in a resized sample of that portion of the image.

      If I wanted to autocrop a 100x150 area I'd call

      $image->resize("blah.jpg", 100, 150, true, true, array(), true)

      I might modify it to allow you to set say, maximum values for each dimension so that if you needed an image that could be any height but not wider than 100px you can autocrop it.

      :)
      [end quote]
      Make sure to end your functions and classes properly with their } :) You seemed to have missed one..

      Great helper though, thanks 1000x
  • Michael posted on 03/09/10 04:00:31 AM
    Thanks for the very useful helper! But I have troubles with cropvars definitions. Could somebody post a real example of cropping from the center of photo into square, please?

    Thanks in advance.
  • revenantprime posted on 02/25/10 10:16:50 PM
    Hi there,

    Thanks for this. Modified a bit to include functionality to crop the image. Basically, added a variable called $crop which you set to true, and then you must supply an array of two pairs of x,y coordinates that define where the crop starts and ends on the image. I wanted to be able to let users choose their own thumbnails for uploaded images via an ajax script, and then pass on their chosen coordinates to this function. If you set $aspect to true, it will match the aspect ratio of the CROPPED REGION, not the original image, so be careful how you specify these coordinates.

    Also, if you set aspect to true and the cropped region is smaller than the resize you specified, the function will fail.

    :)

    EDIT: see update below, fixed some bugs
  • wernerhp posted on 10/25/09 07:22:52 AM
    Hi,

    I get the following...

    Warning (2): call_user_func(imagecreatefromjpeg) [function.call-user-func]: First argument is expected to be a valid callback [APP/views/helpers/image.php, line 66]
    Fatal error: Call to undefined function imagecreate() in /home/mysite/mysite.com/app/views/helpers/image.php on line 70
    • wernerhp posted on 10/25/09 07:35:52 AM
      GDLib wasn't installed: sudo apt-get install php5-gd on Ubuntu.

      Hi,

      I get the following...

      Warning (2): call_user_func(imagecreatefromjpeg) [function.call-user-func]: First argument is expected to be a valid callback [APP/views/helpers/image.php, line 66]
      Fatal error: Call to undefined function imagecreate() in /home/mysite/mysite.com/app/views/helpers/image.php on line 70
  • cpeele posted on 03/11/09 01:22:18 PM

    I am trying to use this ImageHelper and I am getting the following errors:

    Error: The helper class ImageHelperHelper can not be found or does not exist.

    Error: Create the class below in file: app\views\helpers\image_helper.php

    Am using using CakePHP 1.2

    I put the helper in the views\helpers folder and named it "image_helper.php"

    In my Controller action I have helper being set


        function view($id = null)
        {
            $this->helpers[] = 'ImageHelper';
            
            $this->Listing->id = $id;
            $this->set('listing', $this->Listing->read());
        }

    I am using it in the view like so:


                <?php echo $image->resize($listing['Listing']['image'], 150150true); ?>

    Please Help, thank you!
  • havanna posted on 02/20/09 02:41:38 PM
    Great helper - it works perfect for me. A small tipp: Because you use
            $url = $path;  in the helper, you exclude the image directory - in this case you will got the error failed to open stream. The helper search the image in the webroot directory.
    If you set
    <? echo $image->resize('img/mypicture.jpg'7070true); ?>  it works fine. Alternate you can set your image directory in the helper correct.

    Regards Thomas
  • mechandankr posted on 02/08/09 11:13:43 PM
    i have use this helper but i am getting error:
    mkdir - [internal], line ??
    ImageHelper::resize() - APP/views/helpers/image.php, line 31
    include - APP/views/member/profile.thtml, line 100
    View::_render() - CORE/cake/libs/view/view.php, line 648
    View::render() - CORE/cake/libs/view/view.php, line 336
    Controller::render() - CORE/cake/libs/controller/controller.php, line 712
    Dispatcher::_invoke() - CORE/cake/dispatcher.php, line 272
    Dispatcher::dispatch() - CORE/cake/dispatcher.php, line 240
    [main] - APP/webroot/index.php, line 84

    please sort out this problem

    Thanks
    mechandankr@gmail.com


    getimagesize(/img/uploads/images/photos/1231843424.jpg) [function.getimagesize]: failed to open stream: No such file or directory [APP/views/helpers/image.php, line 36]
    Code | Context

    $path = "/img/uploads/images/photos/1231843424.jpg"
    $width = 125
    $height = 126
    $aspect = true
    $htmlAttributes = array(
    "alt" => "1231843424.jpg"
    )
    $return = false
    $urlonly = false
    $dir = "125x126"
    $types = array(
    "gif",
    "jpeg",
    "png",
    "swf",
    "psd",
    "wbmp"
    )
    $fullpath = "/home/httpd/vhosts/leapngo/httpdocs/app/webroot/img/"
    $percorso = "/home/httpd/vhosts/leapngo/httpdocs/app/webroot/img/cache/125x126"
    $url = "/img/uploads/images/photos/1231843424.jpg"


    Warning: implode() [function.implode]: Invalid arguments passed in /home/httpd/vhosts/leapngo/httpdocs/cake/libs/debugger.php on line 497

    getimagesize - [internal], line ??
    ImageHelper::resize() - APP/views/helpers/image.php, line 36
    include - APP/views/member/profile.thtml, line 100
    View::_render() - CORE/cake/libs/view/view.php, line 648
    View::render() - CORE/cake/libs/view/view.php, line 336
    Controller::render() - CORE/cake/libs/controller/controller.php, line 712
    Dispatcher::_invoke() - CORE/cake/dispatcher.php, line 272
    Dispatcher::dispatch() - CORE/cake/dispatcher.php, line 240
    [main] - APP/webroot/index.php, line 84
  • Toss posted on 08/13/08 11:01:15 AM
    I made 2 improvements for this great helper:
    1 -> thumbnails are saved in a subfolder, named by their dimensions (cache/320x240/yourfile.jpg). This allow to have multiple thumbnail sizes.
    2 -> possibility to have the complete image string, or just the resulting cached path.

    here's the resulting helper:

    <?php
    class ImageHelper extends Helper {

        var 
    $helpers = array('Html');

        var 
    $cacheDir 'cache'// relative to IMAGES_URL path

    /**
     * Automatically resizes an image and returns formatted IMG tag
     *
     * @param string $path Path to the image file, relative to the webroot/img/ directory.
     * @param integer $width Image of returned image
     * @param integer $height Height of returned image
     * @param boolean $aspect Maintain aspect ratio (default: true)
     * @param array    $htmlAttributes Array of HTML attributes.
     * @param boolean $urlonly Restituisce solamente l'url invece dell'immagine completa
     * @param boolean $return Wheter this method should return a value or output it. This overrides AUTO_OUTPUT.
     * @return mixed    Either string or echos the value, depends on AUTO_OUTPUT and $return.
     * @access public
     */
        
    function resize($path$width$height$aspect true$htmlAttributes = array(), $return false$urlonly false) {
            
    $dir "{$width}x{$height}";

            
    $types = array(=> "gif""jpeg""png""swf""psd""wbmp"); // used to determine image type
             
    if(empty($htmlAttributes['alt'])) $htmlAttributes['alt'] = basename($path);  // Ponemos alt default

            
    $fullpath ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS.$this->themeWeb.IMAGES_URL;
            if(!
    is_dir($fullpath.$this->cacheDir.DS.$dir))
            {
                
    $percorso str_replace(array('/''\\'), DS$fullpath.$this->cacheDir.DS.$dir);
                
    mkdir($percorso);
            }

            
    $url $path;

            if (!(
    $size getimagesize($url)))
                return; 
    // image doesn't exist

            
    if ($aspect) { // adjust to aspect.
                
    if (($size[1]/$height) > ($size[0]/$width))  // $size[0]:width, [1]:height, [2]:type
                    
    $width ceil(($size[0]/$size[1]) * $height);
                else
                    
    $height ceil($width / ($size[0]/$size[1]));
            }

            
    $relfile $this->webroot.$this->themeWeb.IMAGES_URL.$this->cacheDir.'/'.$dir.'/'.basename($path); // relative file
            
    $cachefile $fullpath.$this->cacheDir.DS.$dir.DS.basename($path);  // location on server

            
    if (file_exists($cachefile)) {
                
    $csize getimagesize($cachefile);
                
    $cached = ($csize[0] == $width && $csize[1] == $height); // image is cached
                
    if (@filemtime($cachefile) < @filemtime($url)) // check if up to date
                    
    $cached false;
            } else {
                
    $cached false;
            }

            if (!
    $cached) {
                
    $resize = ($size[0] > $width || $size[1] > $height) || ($size[0] < $width || $size[1] < $height);
            } else {
                
    $resize false;
            }

            if (
    $resize) {
                
    $image call_user_func('imagecreatefrom'.$types[$size[2]], $url);
                if (
    function_exists("imagecreatetruecolor") && ($temp imagecreatetruecolor ($width$height))) {
                    
    imagecopyresampled ($temp$image0000$width$height$size[0], $size[1]);
                  } else {
                    
    $temp imagecreate ($width$height);
                    
    imagecopyresized ($temp$image0000$width$height$size[0], $size[1]);
                }
                
    call_user_func("image".$types[$size[2]], $temp$cachefile);
                
    imagedestroy ($image);
                
    imagedestroy ($temp);
            }

            if (
    $urlonly != true)
            {
                return 
    $this->output(sprintf($this->Html->tags['image'], $relfile$this->Html->_parseAttributes($htmlAttributesnull''' ')), $return);
            } else {
                return 
    $relfile;
            }
        }
    }
    ?>

  • myog posted on 06/17/08 12:13:22 PM
    Excellent helper!
    If you have two files with the same name but in different directories (eg. img/some_dir/flower.jpg and img/some_other_dir/flower.jpg), it will be treated as same file by the helper (if you attempt to resize it to the same size).
    I modified the code, so that the created filename is constructed of path and filename (and not only filename).
    Example: a picture in 'img/some_dir/flower.jpg' will be named '200x100_img_some_dir-flower.jpg' in the cache (if resized to 200x100).

    Replace the following:

    $relfile = $this->webroot.$this->themeWeb.IMAGES_URL.$this->cacheDir.'/'.$width.'x'.$height.'_'.basename($path); // relative file
    $cachefile = $fullpath.$this->cacheDir.DS.$width.'x'.$height.'_'.basename($path); 

    with:

    $dir_path = preg_replace("/[^a-z0-9_]/", "_", strtolower(dirname($path)));  // make dirname suitable as a filename
    $dir_path .= '-'.basename($path); // append basename
            
    $relfile = $this->webroot.$this->themeWeb.IMAGES_URL.$this->cacheDir.'/'.$width.'x'.$height.'_'.$dir_path; // relative file
    $cachefile = $fullpath.$this->cacheDir.DS.$width.'x'.$height.'_'.$dir_path;  // location on server
  • vmulot posted on 06/16/08 05:36:19 AM
    when i use this helper it works great !
    now i need to use it in a controller.
    i tried to follow this :
    http://www.m3nt0r.de/blog/2007/08/12/cakephp-helpercomponent/ but it gives me some erreors :

    Notice: Undefined property: ImageHelper::$themeWeb in /mydir/views/helpers/image.php on line 30

    Notice: Undefined property: ImageHelper::$webroot in /mydir/views/helpers/image.php on line 43

    any idea on how to correct that?
  • arialdomartini posted on 05/16/08 07:42:02 AM
    For CakePHP v1.2 users: the Josh Hundley's version uses Html->parseHtmlOptions() that is not present in Cake v1.2 and must be changed to Html->_parseAttributes().

    With Jorge Orpinel's version, which uses Html->_parseAttributes and therefore works nice with 1.2, you may have some warnings when the source image cannot be find. Just change


    <?php
    if (!($size getimagesize($url))) 
          return; 
    // image doesn't exist 
    ?>

    to


    <?php
    if (!file_exists($url) || is_dir($url)  || !($size getimagesize($url))) 
          return; 
    // image doesn't exist 
    ?>


    For those who don't like using "imagecache", just change $cacheDir value: I think it may be clearer if you customize the default image cache directory using


    <?php
    Configure
    ::write('Image.imagecache''another_directory');
    ?>

    in config/core.php

    and add these few lines to the helper:


    <?php
    var $cacheDir// relative to 'img'.DS; Default to "imagecache". Defined in /config/core.php with Configure::write('Image.imagecache', 'imagecache');

     
    function __construct()
     {
         
    $this->cacheDir = (Configure::read('Image.imagecache')?Configure::read('Image.imagecache'):'imagecache');
     }
    ?>


    This is the resulting helper:



    <?php
    /**
     * @version 1.1
     * @author Josh Hundley
     * @author Jorge Orpinel <jop@levogiro.net> (changes)
     * @author Arialdo Martini <arialdomartini@bebox.it> (changes)
     */
    class ImageHelper extends Helper
    {
      var 
    $helpers = array('Html');
      
    //var $cacheDir = 'thumbs'; // relative to 'img'.DS
      
    var $cacheDir// relative to 'img'.DS; Default to "imagecache". Defined in /config/core.php with Configure::write('Image.imagecache', 'imagecache');

     
    function __construct()
     {
         
    $this->cacheDir = (Configure::read('Image.imagecache')?Configure::read('Image.imagecache'):'imagecache');
     }
      
    /**
       * Automatically resizes an image and returns formatted IMG tag
       *
       * @param string $path Path to the image file, relative to the webroot/img/ directory.
       * @param integer $width Image of returned image
       * @param integer $height Height of returned image
       * @param boolean $aspect Maintain aspect ratio (default: true)
       * @param array    $htmlAttributes Array of HTML attributes.
       * @param boolean $return Wheter this method should return a value or output it. This overrides AUTO_OUTPUT.
       * @return mixed    Either string or echos the value, depends on AUTO_OUTPUT and $return.
       * @access public
       */
      
    function resize($path$width$height$aspect true$htmlAttributes = array(), $return false) {
        
    $types = array(=> "gif""jpeg""png""swf""psd""wbmp"); // used to determine image type
        
    if(empty($htmlAttributes['alt'])) $htmlAttributes['alt'] = 'thumb';  // Ponemos alt default
        
        
    $fullpath ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS.$this->themeWeb.'img'.DS;
        
    $url $fullpath.$path;
        
        if (!
    file_exists($url) || is_dir($url)  || !($size getimagesize($url))) 
          return; 
    // image doesn't exist 
        
        
    if ($aspect) { // adjust to aspect.
          
    if (($size[1]/$height) > ($size[0]/$width))  // $size[0]:width, [1]:height, [2]:type
          
    $width ceil(($size[0]/$size[1]) * $height);
          else
          
    $height ceil($width / ($size[0]/$size[1]));
        }

        
    $relfile $this->webroot.$this->themeWeb.'img'.'/'.$this->cacheDir.'/'.$width.'x'.$height.'_'.basename($path); // relative file
        
    $cachefile $fullpath.$this->cacheDir.DS.$width.'x'.$height.'_'.basename($path);  // location on server

        
    if (file_exists($cachefile)) {
          
    $csize getimagesize($cachefile);
          
    $cached = ($csize[0] == $width && $csize[1] == $height); // image is cached
          
    if (@filemtime($cachefile) < @filemtime($url)) // check if up to date
          
    $cached false;
        } else {
          
    $cached false;
        }

        if (!
    $cached) {
          
    $resize = ($size[0] > $width || $size[1] > $height) || ($size[0] < $width || $size[1] < $height);
        } else {
          
    $resize false;
        }

        if (
    $resize) {
          
    $image call_user_func('imagecreatefrom'.$types[$size[2]], $url);
          if (
    function_exists("imagecreatetruecolor") && ($temp imagecreatetruecolor ($width$height))) {
            
    imagecopyresampled ($temp$image0000$width$height$size[0], $size[1]);
          } else {
            
    $temp imagecreate ($width$height);
            
    imagecopyresized ($temp$image0000$width$height$size[0], $size[1]);
          }
          
    call_user_func("image".$types[$size[2]], $temp$cachefile);
          
    imagedestroy ($image);
          
    imagedestroy ($temp);
          } elseif (!
    $cached) {
          
    copy($url$cachefile);
        }

        return 
    $this->output(sprintf($this->Html->tags['image'], $relfile$this->Html->_parseAttributes($htmlAttributesnull''' ')), $return);
      }
    }
    ?> 
  • jorge.orpinel posted on 10/20/07 02:38:58 AM
    Actually you MUST replace my

     ...
        } else {
          copy($url, $cachefile);
    ... 

    lines for:

     ...
        } elseif (!$cached) {
          copy($url, $cachefile);
    ... 

    Otherwise it will become really buggy! Sorry for that.
  • jorge.orpinel posted on 10/19/07 10:48:30 PM
    Been using this helper a lot and after a while I found a couple of bugs which I solve in this delivery:

    • adds alt="thumb" by default if no alt prop. sent. to make it html4/css2 copmpilant
    • The was a bug when the image being resized is allready of the desired dimentions. It simply didn't render the image. I just added 1 line to solve this.

    In the version I use I also added the functionality to render a generic image if the file isn't found but removed it in this bug report because you probably want to implement that yoursefl.


    <?php
    /**
     * @version 1.1
     * @author Josh Hundley
     * @author Jorge Orpinel <jop@levogiro.net> (changes)
     */
    class ImageHelper extends Helper
    {
      var 
    $helpers = array('Html');
      var 
    $cacheDir 'imagecache'// relative to 'img'.DS

      /**
       * Automatically resizes an image and returns formatted IMG tag
       *
       * @param string $path Path to the image file, relative to the webroot/img/ directory.
       * @param integer $width Image of returned image
       * @param integer $height Height of returned image
       * @param boolean $aspect Maintain aspect ratio (default: true)
       * @param array    $htmlAttributes Array of HTML attributes.
       * @param boolean $return Wheter this method should return a value or output it. This overrides AUTO_OUTPUT.
       * @return mixed    Either string or echos the value, depends on AUTO_OUTPUT and $return.
       * @access public
       */
      
    function resize($path$width$height$aspect true$htmlAttributes = array(), $return false) {
        
    $types = array(=> "gif""jpeg""png""swf""psd""wbmp"); // used to determine image type
        
    if(empty($htmlAttributes['alt'])) $htmlAttributes['alt'] = 'thumb';  // Ponemos alt default
        
        
    $fullpath ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS.$this->themeWeb.'img'.DS;
        
    $url $fullpath.$path;
        
        if (!(
    $size getimagesize($url))) 
          return; 
    // image doesn't exist 
        
        
    if ($aspect) { // adjust to aspect.
          
    if (($size[1]/$height) > ($size[0]/$width))  // $size[0]:width, [1]:height, [2]:type
          
    $width ceil(($size[0]/$size[1]) * $height);
          else
          
    $height ceil($width / ($size[0]/$size[1]));
        }

        
    $relfile $this->webroot.$this->themeWeb.'img'.'/'.$this->cacheDir.'/'.$width.'x'.$height.'_'.basename($path); // relative file
        
    $cachefile $fullpath.$this->cacheDir.DS.$width.'x'.$height.'_'.basename($path);  // location on server

        
    if (file_exists($cachefile)) {
          
    $csize getimagesize($cachefile);
          
    $cached = ($csize[0] == $width && $csize[1] == $height); // image is cached
          
    if (@filemtime($cachefile) < @filemtime($url)) // check if up to date
          
    $cached false;
        } else {
          
    $cached false;
        }

        if (!
    $cached) {
          
    $resize = ($size[0] > $width || $size[1] > $height) || ($size[0] < $width || $size[1] < $height);
        } else {
          
    $resize false;
        }

        if (
    $resize) {
          
    $image call_user_func('imagecreatefrom'.$types[$size[2]], $url);
          if (
    function_exists("imagecreatetruecolor") && ($temp imagecreatetruecolor ($width$height))) {
            
    imagecopyresampled ($temp$image0000$width$height$size[0], $size[1]);
          } else {
            
    $temp imagecreate ($width$height);
            
    imagecopyresized ($temp$image0000$width$height$size[0], $size[1]);
          }
          
    call_user_func("image".$types[$size[2]], $temp$cachefile);
          
    imagedestroy ($image);
          
    imagedestroy ($temp);
        } else {
          
    copy($url$cachefile);
        }

        return 
    $this->output(sprintf($this->Html->tags['image'], $relfile$this->Html->_parseAttributes($htmlAttributesnull''' ')), $return);
      }
    }
    ?>
  • thomasab posted on 10/07/07 05:47:44 AM
    Great helper!!

    There is one problem. When I upload a big file and I try to display it using the helper I get the following error:

    "Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 10444 bytes) in /usr/local/psa/home/vhosts/sportschoolgekoning.nl/httpdocs/app/views/helpers/image.php on line 58"

    Is there a solution to this problem?

    Thanks
  • pankaj_rayak posted on 09/27/07 02:11:55 AM
    Hi,
    I am getting this following error.
    Fatal error: Call to a member function resize() on a non-object in

  • GrzegorzPawlik posted on 08/24/07 10:43:46 AM
    When you try to resize image to its own size no image will be showed. This is because no image is copied to imagecache, but helper wants to show image from imagecache. Fiz that by adding after:

    if ($resize) {
                $image = call_user_func('imagecreatefrom'.$types[$size[2]], $url);
                if (function_exists("imagecreatetruecolor") && ($temp = imagecreatetruecolor ($width, $height))) {
                    imagecopyresampled ($temp, $image, 0, 0, 0, 0, $width, $height, $size[0], $size[1]);
                  } else {
                    $temp = imagecreate ($width, $height);
                    imagecopyresized ($temp, $image, 0, 0, 0, 0, $width, $height, $size[0], $size[1]);
                }
                call_user_func("image".$types[$size[2]], $temp, $cachefile);
                imagedestroy ($image);
                imagedestroy ($temp);
            }
    this:

    elseif(!$cached){
                $relfile = $this->webroot.$this->themeWeb.IMAGES_URL.$path;
        }
    This will cause helper show real image.
  • Dieter_be posted on 05/08/07 10:29:01 AM
    Cake 1.2 users should replace $this->Html->parseHtmlOptions() with $this->Html->_parseAttributes() because it has been deleted in recent revisions of cake 1.2
  • gmansilla posted on 05/08/07 10:10:35 AM
    Parse error: syntax error, unexpected ';', expecting T_FUNCTION in /...../helpers/image.php on line 72

    70. return $this->output(sprintf($this->Html->tags['image'], $relfile, $this->Html->parseHtmlOptions($htmlAttributes, null, '', ' ')), $return);
    71. }
    72. ?>
    there is a "}" missing at the end, you need to add it
  • freshdevelopment posted on 04/19/07 02:56:10 PM
    If we used app/tmp/cache for the thumbnails, would it be cleared on a regular basis? Or does the helper clear the cache (I couldn't find any code for it)?
  • Dieter_be posted on 04/12/07 09:16:13 AM
    Great job, few lines of code, and not using imagemagick :-) (imagemagick is very nice, but I think/guess/assume it's not available on most shared hosts)

    One remark though: "ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS" is a bit a lengthy description for where WWW_ROOT would be more suited :-)
    I changed the $fullpath initialization to this: "$fullpath = WWW_ROOT.$this->themeWeb.IMAGES_URL;"

    Also, do you think it would be possible to use the app/tmp/cache for the thumbnails?

    PS: Gentoo users, don't forget to enable the "gd" use-flag for dev-lang/php if you want this to work.
  • digitalknk posted on 11/30/99 12:00:00 AM
    How would I apply this to a Link? So the Thumbnail becomes a link.
    • GrzegorzPawlik posted on 11/30/99 12:00:00 AM
      How would I apply this to a Link? So the Thumbnail becomes a link. Use Html::link like that:
      $html->link($image->resize($image_path, WIDTH, HEIGHT, SMALL_FOTO_ASPECT), $target_link, array(), false, false);
      The last used parameter (false) says if function should escape title tags.
  • ncy111 posted on 11/30/99 12:00:00 AM
    this helper is excellent. thanks!
login to post a comment.