Re: More efficient thumbnail script

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jason Pruim wrote:
> 
> On Jan 16, 2007, at 4:10 PM, Jochem Maas wrote:
> 
>> generating/resampling image data is a relatively heavy job for a script
>> to perform. there maybe optimizations available in the script itself but
>> generally caching the results the generation/resampling action is the
>> way to
>> increase performance ... you need a mechanism to check/store/retrieve
>> cached
>> images [and a way to automatically regenerate a cached image when the
>> source
>> image has changes].
>>
>> another thing to consider on top of caching is to store the cached
>> data on a
>> 'ram' drive ... on linux I often use a sub directory on /dev/shm
>> (which is
>> a part of the filesystem which actually exists only in shared memory -
>> more than
>> likely that you dont have access to this on a shared hosting environment.
> 
> Luckily I'm not in a shared hosting environment. :) I sit about 3 feet
> away from the server that is running my script. I will look into caching
> the info though to see if I can figure out what I would have to
> change/add/delete to accomplish this.

I wouldn't bother with worrying about stored cached image output on
/dev/shm until you have got caching working - although disk access is relatively
slow it's not half as slow as regenerating a thumbnail on every request.

here is a class that might help you when it comes to caching images,
assuming you can work out how it works ;-)

(I'm sure this class is not perfect but it works for me :-)

<?php

class ImageCache
{
    var $validTypes = array('png','gif','jpeg');

    var $cacheFileName;
    var $cacheFileType;
    var $cacheDir;

    var $im;

    /* you must give a valid 'cache' dir  */
    function ImageCache($cDir)
    {
        $this->cacheDir         = $cDir;
    }

    /* generate a cache file name for the image your are generating
     * if your generated output image is dependent on the values of one or more request
     * variables then you should add the names to the $args array e.g.
     *
     * your script take width/height parameter: /image.php?width=200&height=160
     *
     * $args should be the following array: array('width', 'height');
     */
    function genCacheFileName($args = array(), $type = '', $prefix = '')
    {
        /* name/val pair delimiter in the string that results in the hash for the cache id */
        $qHashMark = '%~^*';

        $qry  = array();
        $args = (array)$args; natsort($args);
        foreach ($args as $arg) {
            if (($val = $this->getR( $arg, false )) !== false) {
                $qry[] = "{$arg}=".str_replace($qHashMark,'',$val);
            }
        }

        $sep  = '-:-';
        $hash = md5($_SERVER['HTTP_HOST'] .$sep. $_SERVER['SCRIPT_NAME'] .$sep. join($qHashMark,$qry));

        if (!in_array($type, $this->validTypes)) {
            if ($type == 'jpg') {
                $type = 'jpeg';
            } else {
                $type = 'png';
            }
        }

        $this->cacheFileType = $type;

        if (!$prefix) {
            $prefix = 'cacheimg';
        }

        return ($this->cacheFileName = "{$prefix}_{$hash}.{$type}");
    }

    /* get the fullpath to the location where the cache file is saved/stored */
    function getCacheFilePath()
    {
        return $this->cacheDir . '/' . $this->cacheFileName;
    }

    /* Return true if the cache file is younger than the source file(s),
     * false otherwise.
     *
     * if this func returns true you can output the relevant cache file,
     * if false is returned it's your responsibility to generate the output file
     * and save it to the location given by $this->getCacheFilePath()
     *
     * the (array of) files passed to this function should be complete paths,
     * not just filesnames.
     */
    function checkCache( $files = array() )
    {
        $cacheState = true;

        $cf           = $this->getCacheFilePath();
        $mTime        = is_readable($cf) ? filemtime($cf): 0;
        $lastModified = gmdate("D, d M Y H:i:s ", $mTime)."GMT";
        $files        = (array) $files;

        if (!count($files) || !$mTime) {
            $cacheState = false;
        } else {
            foreach($files as $file) {
                if ($mTime < filemtime( $file )) {
                    $cacheState = false;
                    break;
                }
            }
        }

        if ($cacheState) {
            $headers = getallheaders();
            if (isset($headers['If-Modified-Since']) && ($headers['If-Modified-Since'] == $lastModified)) {
                /* The UA has the exact same image we have. */
                header("HTTP/1.1 304 Not Modified");
                exit;
            } else {
                unset($headers);
                header("Last-Modified: ".$lastModified);
                return true;
            }
        } else {
            // not cached - or cache invalidated
            // must cache the (new) data.
            return false;
        }
    }

    function showImage($type = '', $quality = 100)
    {
        header( "Content-type: image/{$this->cacheFileType}" );
        readfile( $this->getCacheFilePath() );
        exit;
    }

    function getR($v = '', $r = null, $t = null)
    {
        if (!empty($v)) { if (isset($_REQUEST[$v])) {$r=!is_null($t)?$t:$_REQUEST[$v];} }
        return $r;
    }
}

?>

> 
> Would upgrading to PHP 5* be of any help? 

not specifically in this case, but I would recommended using php5
if your starting out and developing new stuff.

php4 is not being actively developed (security & bug fixes still occur).

it's not wrong to use php4, and many people have no choice, but I recommend
trying to stay on top of whats current and given that your not (AFAICT) running
any legacy code there is nothing really stopping you.

> I've thought about upgrading
> but not knowing much about how to run the server from the command
> line(Part of what I'm learning) I didn't want to screw anything up.
> 
> 

test servers are there to be screwed up, kind of. when your learning and trying things
out thing break occasionally. ommelettes, breaking eggs, all that jazz.

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux