PX : code

(Drop Shadowed) Thumbnail Creator by Andrew Collington
Download this code


<?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";
        }
    }

}

?>

Comments or questions?
PX is running PHP 5.2.17
Thanks to Miranda Productions for hosting and bandwidth.
Use of any code from PX is at your own risk.