andy's php projects
Script and site usage:
All of the scripts on this site are provided free for non-commercial, personal or non-profit use. If you wish to use any of these in a commercial system, please refer to the payment plan.

Support:
Support for each of the scripts is given, free of charge, on the message board. Each script has its own message board which can be accessed by clicking on the 'project forum' link (beneath the description of each project).


Proudly hosted with Dreamhost

Save $20 when signing up for Dreamhost by using the promo code amnuts20


If you find these scripts useful to you, appreciate the free support, or are just an all round nice person, then why not donate a little dosh to encourage me to continue? Every little helps!

Zend Certified Engineer logo


Drop Shadowed Thumbnail Creator

This class allows you to very easily create thumbnails of images, on which you can also apply a drop-shadow effect. You can control the colour of the background so that drop-shadow will fit better onto your page and the size of the thumbnail.

You can resize in an absolute or relative way (to a certain size or by a certain size), both as a pixel number or a percentage.

class.dropshadow.php

The main class file. Version two works considerably differently to version one. To emulate version one, see the 'class.originaldropshadow.php' file below.

<?php

//
// class.dropshadow.php
// version 2.0.0, 21st May, 2003
//
// License
//
// PHP class to create thumbnails of images and/or to add a drop shadow effect.
//
// Copyright (C) 2002 Andrew Collington, php@amnuts.com, http://php.amnuts.com/
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
// Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Description
//
// This class allows for easy creation of images with a drop shadow effect.
// Images can be read from a file or passed as a string (as you might take
// the images from a database), and they can also be resized for easy
// creation of thumbnails.  You can also change the background colour of
// the image and generate the correct colour through the shadow.
//
// Requirements
//
// PHP 4.1.0+, GD 2.0.1+
//
// Shadow images
//
// I found that the best way to create a drop shadow was to first create
// the shadow in an art program, and then split it up into 8 seperate
// pieces; top left corner, top line, top right corner, left side, right
// side, bottom left corner, bottom line, and bottom right corner.
//
// If you don't like the spacing of the drop shadow, then you could easily
// create your own drop shadows and over-write the files supplied.  The
// different sizes of the drop-shadow images should be automatically taken
// into consideration.  If you create your own shadows then you must save
// them as PNG-24 (24-bit), as that level of alpha channels is required.
//
// If no drop-shadow images can be located (or it cannot load up all of the
// images) then it will still save the image (resized if you told it to be),
// just without the drop-shadow effect.
//
//
// Andrew Collington, 2003
// php@amnuts.com, http://php.amnuts.com/
//



class dropShadow
{
    var 
$_imgOrig;       // the original image
    
var $_imgFinal;      // the final image, resized
    
var $_imgShadow;     // the final image with a drop shadow, if applied
    
var $_shadows;       // the dropshadow image array
    
var $_shadowPath;    // the path to the dropshadow images
    
var $_showDebug;     // debugging on/off (TRUE/FALSE)
    
    //
    // Constructor
    //
    

    
function dropShadow($debug FALSE)
    {
        
$this->_showDebug = ($debug TRUE FALSE);
        
$this->_imgOrig $this->_imgFinal $this->_imgFinal NULL;
        
$this->_shadows = array();
    }


    
//
    // User called functions
    //


    //
    // loads the original image.  If no extension is passed to $forceext then it will attempt
    // to load the correct type based on the $filename.
    //
    
function loadImage($filename$forceext '')
    {
        if (!@
file_exists($filename))
        {
            
$this->_debug('loadImage'"The supplied file name '$filename' does not point to an existing file.");
            return 
FALSE;
        }
        
        
$ext = ($forceext == '' $this->_getExtension($filename) : $forceext);
        if (
$ext == 'jpg'$ext 'jpeg';

        
$func "imagecreatefrom$ext";
        
        if (!@
function_exists($func))
        {
            
$this->_debug('loadImage'"That file cannot be loaded with the function '$func'.");
            return 
FALSE;
        }
        
        
$this->_imgOrig = @$func($filename);
        
        if (
$this->_imgOrig == NULL)
        {
            
$this->_debug('loadImage''The image could not be loaded.');
            return 
FALSE;
        }
        
        return 
TRUE;
    }
    
    
//
    // load an image from a string, for example, from a database row
    //
    
function loadImageFromString($string)
    {
        
$this->_imgOrig = @ImageCreateFromString($string);
        if (
$this->_imgOrig == NULL)
        {
            
$this->_debug('loadImageFromString''The image could not be loaded.');
            return 
FALSE;
        }
        
        return 
TRUE;
    }

    
//
    // saves the final image resource to the file system.  If no extension is given for $forceext
    // then it will attempt to save based on the file name.
    // $quality is a value from 1 to 100, inclusive, and only used when outputting as a jpg
    //
    
function saveFinal($filename$forcetype ''$quality 80)
    {
        return (
$this->_saveImage($filename$this->_imgFinal$forcetype$quality));
    }

    
//
    // saves the final image resource to the file system.  If no extension is given for $forceext
    // then it will attempt to save based on the file name.
    // $quality is a value from 1 to 100, inclusive, and only used when outputting as a jpg
    //
    
function saveShadow($filename$forcetype ''$quality 80)
    {
        return (
$this->_saveImage($filename$this->_imgShadow$forcetype$quality));
    }

    
//
    // show the final image as either a png or jpg
    // $quality is a value from 1 to 100, inclusive, and only used when outputting as a jpg
    //
    
function showFinal($type 'png'$quality 80)
    {
        return (
$this->_showImage($this->_imgFinal$type$quality));
    }
    
    
//
    // show the final shadowed image as either a png or jpg
    // $quality is a value from 1 to 100, inclusive, and only used when outputting as a jpg
    //
    
function showShadow($type 'png'$quality 100)
    {
        return (
$this->_showImage($this->_imgShadow$type$quality));
    }

    
//
    // allows you to set where the drop-shadow images will be located
    //
    
function setShadowPath($path '.')
    {
        
$this->_shadowPath realpath($path);
        if (
$this->_shadowPath[strlen($this->_shadowPath)-1] != '/'$this->_shadowPath .= '/';
    }

    
//
    // resize the original image by a certain pixel size
    // if 0 is supplied for $x or $y then the resize will be proportional
    //
    
function resizeBySize($x$y)
    {
        
$nx = @ImageSX($this->_imgOrig) - $x;
        
$ny = @ImageSY($this->_imgOrig) - $y;
        if (
$x == 0) list($nx$ny) = $this->_getProportionalSize(0$ny);
        if (
$y == 0) list($nx$ny) = $this->_getProportionalSize($nx0);
        
$this->_debug('resizeBySize'"Image size is $nx / $ny");
        return (
$this->_resizeImage($nx$ny'resizeBySize'));
    }

    
//
    // resize the original image to a certain pixel size
    // if 0 is supplied for $x or $y then the resize will be proportional
    //
    
function resizeToSize($x$y)
    {
        
$nx $x;
        
$ny $y;
        if (
$x == 0) list($nx$ny) = $this->_getProportionalSize(0$y);
        if (
$y == 0) list($nx$ny) = $this->_getProportionalSize($x0);
        
$this->_debug('resizeToSize'"Image size is $nx / $ny");
        return (
$this->_resizeImage($nx$ny'resizeToSize'));
    }

    
//
    // resize the original image by a certain percent of the original
    // if 0 is supplied for $percentx or $percenty then the resize will be proportional
    //
    
function resizeByPercent($percentx$percenty)
    {
        
$nx = @ImageSX($this->_imgOrig) - (($percentx 100) * @ImageSX($this->_imgOrig));
        
$ny = @ImageSY($this->_imgOrig) - (($percenty 100) * @ImageSY($this->_imgOrig));
        if (
$percentx == 0) list($nx$ny) = $this->_getProportionalSize(0$ny);
        if (
$percenty == 0) list($nx$ny) = $this->_getProportionalSize($nx0);
        
$this->_debug('resizeByPercent'"Image size is $nx / $ny");
        return (
$this->_resizeImage($nx$ny'resizeByPercent'));
    }

    
//
    // resize the original image to a certain percent of the original
    // if 0 is supplied for $percentx or $percenty then the resize will be proportional
    //
    
function resizeToPercent($percentx$percenty)
    {
        
$nx = ($percentx 100) * @ImageSX($this->_imgOrig);
        
$ny = ($percenty 100) * @ImageSY($this->_imgOrig);
        if (
$percentx == 0) list($nx$ny) = $this->_getProportionalSize(0$ny);
        if (
$percenty == 0) list($nx$ny) = $this->_getProportionalSize($nx0);
        
$this->_debug('resizeToPercent'"Image size is $nx / $ny");
        return (
$this->_resizeImage($nx$ny'resizeToPercent'));
    }

    
//
    // apply the drop shadow to the final image resource
    // this will overwrite the final image resource with the drop-shadowed version
    // the background colour can be changed by passing an HTML hex value (with or without the #)
    //
    
function applyShadow($bgcolour 'FFFFFF')
    {
        
// make sure we have the image resource
        
if ($this->_imgFinal == NULL)
        {
            
$this->_debug('applyShadow''There is no resized image, so the original image is being used.');
            if (
$this->_imgOrig == NULL)
            {
                
$this->_debug('applyShadow''There is no original image loaded.');
                return 
FALSE;
            }
            
$this->_resizeImage(@ImageSX($this->_imgOrig), @ImageSY($this->_imgOrig), 'applyShadow');
            if (
$this->_imgFinal == NULL)
            {
                
$this->_debug('applyShadow''The destination image could not be created.');
                return 
FALSE;
            }
        }

        
// attempt to load the drop shadow array
        
if ($this->_shadows['l']  == NULL$this->_shadows['l']  = @ImageCreateFromPNG($this->_shadowPath "ds_left.png");
        if (
$this->_shadows['r']  == NULL$this->_shadows['r']  = @ImageCreateFromPNG($this->_shadowPath "ds_right.png");
        if (
$this->_shadows['t']  == NULL$this->_shadows['t']  = @ImageCreateFromPNG($this->_shadowPath "ds_top.png");
        if (
$this->_shadows['b']  == NULL$this->_shadows['b']  = @ImageCreateFromPNG($this->_shadowPath "ds_bottom.png");
        if (
$this->_shadows['tl'] == NULL$this->_shadows['tl'] = @ImageCreateFromPNG($this->_shadowPath "ds_tlcorner.png");
        if (
$this->_shadows['tr'] == NULL$this->_shadows['tr'] = @ImageCreateFromPNG($this->_shadowPath "ds_trcorner.png");
        if (
$this->_shadows['bl'] == NULL$this->_shadows['bl'] = @ImageCreateFromPNG($this->_shadowPath "ds_blcorner.png");
        if (
$this->_shadows['br'] == NULL$this->_shadows['br'] = @ImageCreateFromPNG($this->_shadowPath "ds_brcorner.png");

        
// verify all is well
        
foreach($this->_shadows as $key => $val)
        {
            if (
$val == NULL)
            {
                
$this->_debug('applyShadow''The shadow files could not be loaded.');
                return 
FALSE;
            }
        }

        
// create go-between image
        
$ox = @ImageSX($this->_imgFinal);
        
$oy = @ImageSY($this->_imgFinal);
        
$nx = @ImageSX($this->_shadows['l']) + @ImageSX($this->_shadows['r']) + @ImageSX($this->_imgFinal);
        
$ny = @ImageSY($this->_shadows['t']) + @ImageSY($this->_shadows['b']) + @ImageSY($this->_imgFinal);

        
$this->_debug('applyShadow'"Original image size = $ox/$oy : Drop shadowed image size = $nx/$ny");

        
$this->_imgShadow = @ImageCreateTrueColor($nx$ny);
        if (
$this->_imgShadow == NULL)
        {
            
$this->_debug('applyShadow''The drop-shadowed image resource could not be created.');
            return 
FALSE;
        }

        
// pre-process the image
        
$background $this->_htmlHexToBinArray($bgcolour);
        @
ImageAlphaBlending($this->_imgShadowTRUE);
        @
ImageFill($this->_imgShadow00, @ImageColorAllocate($this->_imgShadow$background[0], $background[1], $background[2]));

        
// apply the shadow

        // top left corner
        
@ImageCopyResampled($this->_imgShadow$this->_shadows['tl'],
                        
0000,
                        @
ImageSX($this->_shadows['tl']), @ImageSY($this->_shadows['tl']), @ImageSX($this->_shadows['tl']), @ImageSY($this->_shadows['tl']));
        
// top shadow
        
@ImageCopyResampled($this->_imgShadow$this->_shadows['t'],
                        @
ImageSX($this->_shadows['l']), 000,
                        
$ox, @ImageSY($this->_shadows['t']), @ImageSX($this->_shadows['t']), @ImageSY($this->_shadows['t']));
        
// top right corner
        
@ImageCopyResampled($this->_imgShadow$this->_shadows['tr'],
                        (
$nx - @ImageSX($this->_shadows['r'])), 000,
                        @
ImageSX($this->_shadows['tr']), @ImageSY($this->_shadows['tr']), @ImageSX($this->_shadows['tr']), @ImageSY($this->_shadows['tr']));
        
// left shadow
        
@ImageCopyResampled($this->_imgShadow$this->_shadows['l'],
                        
0, @ImageSY($this->_shadows['t']),    00,
                        @
ImageSX($this->_shadows['l']), $oy, @ImageSX($this->_shadows['l']), @ImageSY($this->_shadows['l']));
        
// right shadow
        
@ImageCopyResampled($this->_imgShadow$this->_shadows['r'],
                        (
$nx - @ImageSX($this->_shadows['r'])), @ImageSY($this->_shadows['tl']), 00,
                        @
ImageSX($this->_shadows['r']), $oy, @ImageSX($this->_shadows['r']), @ImageSY($this->_shadows['r']));
        
// bottom left corner
        
@ImageCopyResampled($this->_imgShadow$this->_shadows['bl'],
                        
0, ($ny - @ImageSY($this->_shadows['b'])), 00,
                        @
ImageSX($this->_shadows['bl']), @ImageSY($this->_shadows['bl']), @ImageSX($this->_shadows['bl']), @ImageSY($this->_shadows['bl']));
        
// bottom shadow
        
@ImageCopyResampled($this->_imgShadow$this->_shadows['b'],
                        @
ImageSX($this->_shadows['l']), ($ny - @ImageSY($this->_shadows['b'])), 00,
                        
$ox, @ImageSY($this->_shadows['b']), @ImageSX($this->_shadows['b']), @ImageSY($this->_shadows['b']));
        
// bottom right corner
        
@ImageCopyResampled($this->_imgShadow$this->_shadows['br'],
                        (
$nx - @ImageSX($this->_shadows['r'])), ($ny - @ImageSY($this->_shadows['b'])), 00,
                        @
ImageSX($this->_shadows['br']), @ImageSY($this->_shadows['br']), @ImageSX($this->_shadows['br']), @ImageSY($this->_shadows['br']));

        
// apply the picture
        
@ImageCopyResampled($this->_imgShadow$this->_imgFinal,
                        @
ImageSX($this->_shadows['l']), @ImageSY($this->_shadows['t']), 00,
                        
$ox$oy, @ImageSX($this->_imgFinal), @ImageSY($this->_imgFinal));

        return 
TRUE;
    }

    
//
    // clean up image resources
    // 0 = original image only
    // 1 = final image only
    // 2 = shadow images only
    // 3 = all images
    //
    
function flushImages($which 5)
    {
        switch (
$which)
        {
            case 
0:
                @
ImageDestroy($this->_imgOrig);
                
$this->_imgOrig NULL;
                break;
            case 
1:
                @
ImageDestroy($this->_imgFinal);
                
$this->_imgFinal NULL;
                break;
            case 
3:
                @
ImageDestroy($this->_imgShadow);
                
$this->_imgShadow NULL;
                break;
            case 
4:
                @
ImageDestroy($this->_shadows['l']);
                @
ImageDestroy($this->_shadows['r']);
                @
ImageDestroy($this->_shadows['t']);
                @
ImageDestroy($this->_shadows['b']);
                @
ImageDestroy($this->_shadows['tl']);
                @
ImageDestroy($this->_shadows['tr']);
                @
ImageDestroy($this->_shadows['bl']);
                @
ImageDestroy($this->_shadows['br']);
                unset(
$this->_shadows);
                break;
            case 
5:
                @
ImageDestroy($this->_imgOrig);
                @
ImageDestroy($this->_imgFinal);
                @
ImageDestroy($this->_imgShadow);
                @
ImageDestroy($this->_shadows['l']);
                @
ImageDestroy($this->_shadows['r']);
                @
ImageDestroy($this->_shadows['t']);
                @
ImageDestroy($this->_shadows['b']);
                @
ImageDestroy($this->_shadows['tl']);
                @
ImageDestroy($this->_shadows['tr']);
                @
ImageDestroy($this->_shadows['bl']);
                @
ImageDestroy($this->_shadows['br']);
                
$this->_imgOrig $this->_imgFinal $this->_imgShadow NULL;
                unset(
$this->_shadows);
                break;
        }
    }


    
    
//
    // Internal functions
    //


    //
    // get the file extension of the given filename
    //
    
function _getExtension($filename)
    {
        
$ext  strtolower(substr($filename, (strrpos($filename'.') ? strrpos($filename'.') + strlen($filename)), strlen($filename)));
        if (
$ext == 'jpg'$ext 'jpeg';
        return 
$ext;
    }
    
    
//
    // if only the width is supplied, get the height based on the original image size
    // if only the height is supplied, get the width based on the original image size
    //
    
function _getProportionalSize($x$y)
    {
        if (!
$x$x = ($y ImageSY($this->_imgOrig)) * ImageSX($this->_imgOrig);
        else 
$y ImageSY($this->_imgOrig) / (ImageSX($this->_imgOrig) / $x);
        return array(
$x$y);
    }

    
//
    // core functionality for the resizing of an image
    //
    
function _resizeImage($nx$ny$function)
    {
        if (
$this->_imgOrig == NULL)
        {
            
$this->_debug($function'The original image has not been loaded.');
            return 
FALSE;
        }
        if ((
$nx 0) || ($ny 0))
        {
            
$this->_debug($function'The image could not be resized because the size given is not valid.');
            return 
FALSE;
        }
        if (
$this->_imgFinal$this->flushImages(1);
        
$this->_imgFinal = @ImageCreateTrueColor($nx$ny);
        @
ImageCopyResampled($this->_imgFinal$this->_imgOrig0000$nx$ny, @ImageSX($this->_imgOrig), @ImageSY($this->_imgOrig));
    }

    
//
    // show the final image as either a png or jpg
    // $quality is a value from 1 to 100, inclusive, and only used when outputting as a jpg
    //
    
function _showImage($resource$type$quality)
    {
        if (
$resource == NULL)
        {
            
$this->_debug('_showImage''There is no processed image to show.');
            return 
FALSE;
        }
        if (
$type == 'png')
        {
            
header('Content-Type: image/png');
            echo @
ImagePNG($resource);
            return 
TRUE;
        }
        else if (
$type == 'jpg' || $type == 'jpeg')
        {
            
header('Content-Type: image/jpeg');
            echo @
ImageJPEG($resource''$quality);
            return 
TRUE;
        }
        else
        {
            
$this->_debug('_showImage'"Could not show the output file as a $type.");
            return 
FALSE;
        }
    }

    
//
    // saves the image resource to the file system.  If no extension is given for $type
    // then it will attempt to save based on the file name.
    // $quality is a value from 1 to 100, inclusive, and only used when outputting as a jpg
    // $img is the image resource
    //
    
function _saveImage($filename$img$type$quality)
    {
        if (
$img == NULL)
        {
            
$this->_debug('_saveImage''There is no processed image to save.');
            return 
FALSE;
        }

        
$ext = ($type == '' $this->_getExtension($filename) : $type);
        if (
$ext == 'jpg'$ext 'jpeg';
        
$func "image$ext";
        
        if (!@
function_exists($func))
        {
            
$this->_debug('_saveImage'"That file cannot be saved with the function '$func'.");
            return 
FALSE;
        }

        if (
$ext == 'png'$saved = @$func($img$filename);
        if (
$ext == 'jpeg'$saved = @$func($img$filename$quality);
        if (
$saved == FALSE)
        {
            
$this->_debug('_saveImage'"Could not save the output file '$filename' as a $ext.");
            return 
FALSE;
        }
        else
        {
            return 
TRUE;
        }
    }

    
//
    // convert HTML hex value into integer array
    //
    
function _htmlHexToBinArray($hex)
    {
        
$hex = @preg_replace('/^#/'''$hex);
        for (
$i=0$i<3$i++)
        {
            
$foo substr($hex2*$i2); 
            
$rgb[$i] = 16 hexdec(substr($foo01)) + hexdec(substr($foo11)); 
        }
        return 
$rgb;
    }

    
//
    // write out some debugging information to screen
    //
    
function _debug($function$string)
    {
        if (
$this->_showDebug)
        {
            echo 
"<p><strong style=\"color:#FF0000\">Debug message from function $function:</strong> $string</p>\n";
        }
    }

}

?>
17.84kb in size
last modified May 6, 2006 at 9:54pm
14633 views, 12658 downloads

class.originaldropshadow.php

This is an extension of the main class file to emulate version 1.x of the script.

3.6kb in size
last modified May 6, 2006 at 9:54pm
5696 views, 7518 downloads

ds_blcorner.png

230b in size
last modified May 6, 2006 at 9:54pm
8619 views, 8854 downloads

ds_bottom.png

419b in size
last modified May 6, 2006 at 9:54pm
6591 views, 8234 downloads

ds_brcorner.png

288b in size
last modified May 6, 2006 at 9:54pm
5340 views, 8327 downloads

ds_left.png

730b in size
last modified May 6, 2006 at 9:54pm
5009 views, 8097 downloads

ds_right.png

864b in size
last modified May 6, 2006 at 9:54pm
4858 views, 8070 downloads

ds_tlcorner.png

163b in size
last modified May 6, 2006 at 9:54pm
4781 views, 8019 downloads

ds_top.png

224b in size
last modified May 6, 2006 at 9:55pm
4659 views, 8087 downloads

ds_trcorner.png

203b in size
last modified May 6, 2006 at 9:55pm
5134 views, 7976 downloads

test.dropshadow.php

231b in size
last modified May 6, 2006 at 9:55pm
8189 views, 8527 downloads

test.originaldropshadow.php

1.45kb in size
last modified May 6, 2006 at 9:55pm
6277 views, 7546 downloads
list all projects :: this project's forum :: script in action
added Sep 20, 2002 at 5:44pm :: updated May 22, 2003 at 5:19am :: 12 files :: 61519 views

© Andrew Collington, 2002-2007.