source: trunk/lib/ImageThumb.inc.php @ 122

Last change on this file since 122 was 121, checked in by scdev, 18 years ago

Q - Added "sc-" to all css class selectors; Finished reworking Upload and ImageThumb? (now with GD support!); More PHP 5 upgrades.

File size: 29.2 KB
RevLine 
[1]1<?php
2/**
[42]3 * ImageThumb.inc.php
[1]4 * Code by Strangecode :: www.strangecode.com :: This document contains copyrighted information
5 *
6 * @author   Quinn Comendant <quinn@strangecode.com>
[119]7 * @requires Netpbm <http://sourceforge.net/projects/netpbm/> and libjpeg or GD.
8 * @version  2.0
[1]9 */
10
[119]11// Image resize options.
[1]12define('IMAGETHUMB_FIT_WIDTH', 1);
13define('IMAGETHUMB_FIT_HEIGHT', 2);
14define('IMAGETHUMB_FIT_LARGER', 3);
15define('IMAGETHUMB_STRETCH', 4);
16define('IMAGETHUMB_NO_SCALE', 5);
[119]17define('IMAGETHUMB_METHOD_NETPBM', 6);
18define('IMAGETHUMB_METHOD_GD', 7);
[1]19
20class ImageThumb {
[119]21   
22    // General object parameters.
23    var $_params = array(
24        // The location for images to create thumbnails from.
25        'source_dir' => null,
[42]26
[119]27        // Existing files will be overwritten when there is a name conflict?
28        'allow_overwriting' => false,
[42]29
[119]30        // The file permissions of the uploaded files. Remember, files will be owned by the web server user.
31        'dest_file_perms' => 0600,
[42]32
[119]33        // Permissions of autocreated directories. Must be at least 0700 with owner=apache.
34        'dest_dir_perms' => 0777,
[42]35
[119]36        // Require file to have one of the following file name extentions.
37        'valid_file_extensions' => array('jpg', 'jpeg', 'gif', 'png'),
38       
39        // Method to use for resizing. (IMAGETHUMB_METHOD_NETPBM or IMAGETHUMB_METHOD_GD)
40        'resize_method' => IMAGETHUMB_METHOD_NETPBM,
[1]41
[119]42        // Netpbm and libjpeg binary locations.
43        'anytopnm_binary' => '/usr/bin/anytopnm',
44        'pnmscale_binary' => '/usr/bin/pnmscale',
45        'cjpeg_binary' => '/usr/bin/cjpeg',
[42]46
[119]47        // Which messages do we pass to raiseMsg? Use one of the MSG_* constants or false to disable.
48        'display_messages' => MSG_ALL,
49    );
50   
51    // Default image size specs.
52    var $default_image_specs = array(
53        // The destination for an image thumbnail size. Path relative to source_dir (eg: ../thumbs).
54        'dest_dir' => null,
[120]55       
56        // Destination file types. (IMG_JPG, IMG_PNG, IMG_GIF, IMG_WBMP)
57        'dest_file_type' => IMG_JPG,
58
59        // Destination file types. ('jpg', 'png', 'gif', 'wbmp')
60        'dest_file_extention' => 'jpg',
61       
[119]62        // Type of scaling to perform, and sizes used to calculate max dimentions.
63        'scaling_type' => IMAGETHUMB_FIT_LARGER,
64        'width' => null,
65        'height' => null,
[120]66
[119]67        // Percentage quality of image compression output 0-100.
68        'quality' => 65,
[120]69
[119]70        // Create progressive jpegs?
71        'progressive' => false,
[120]72
73        // If using GD method, apply sharpen filter. Requires PHP > 5.1.
74        'sharpen' => true,
75       
76        // Integers between 1-100, useful values are 65-85.
77        'sharpen_value' => 75,
78
[119]79        // If source image is smaller than thumbnail, allow upscaling?
80        'allow_upscaling' => false,
[120]81
[119]82        // If thumb exists and filesize is smaller than this, do not overwrite the thumb.
83        'keep_filesize' => null,
84    );
[1]85
[119]86    // Final specifications for image sizes, set with setSpec().
87    var $image_specs = array();
88
[1]89    /**
[119]90     * Set (or overwrite existing) parameters by passing an array of new parameters.
[1]91     *
[119]92     * @access public
93     * @param  array    $params     Array of parameters (key => val pairs).
[1]94     */
[119]95    function setParam($params)
[1]96    {
[119]97        if (isset($params) && is_array($params)) {
98
99            // Enforce valid upload_path parameter.
100            if (isset($params['source_dir'])) {
101                $params['source_dir'] = realpath($params['source_dir']);
102                // Must be directory.
103                if (!is_dir($params['source_dir'])) {
104                    App::logMsg(sprintf('Source directory invalid: %s', $params['source_dir']), LOG_ERR, __FILE__, __LINE__);
105                    trigger_error(sprintf('Source directory invalid: %s', $params['source_dir']), E_USER_ERROR);
106                }
107                // Must be readable.
108                if (!is_readable($params['source_dir'])) {
109                    App::logMsg(sprintf('Source directory not readable: %s', $params['source_dir']), LOG_ERR, __FILE__, __LINE__);
110                    trigger_error(sprintf('Source directory not readable: %s', $params['source_dir']), E_USER_ERROR);
111                }
112            }
113
114            // Merge new parameters with old overriding only those passed.
115            $this->_params = array_merge($this->_params, $params);
116        } else {
117            App::logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__);
[1]118        }
119    }
120
121    /**
[119]122     * Return the value of a parameter, if it exists.
[1]123     *
[119]124     * @access public
125     * @param string $param        Which parameter to return.
126     * @return mixed               Configured parameter value.
[1]127     */
[119]128    function getParam($param)
[1]129    {
[119]130        if (isset($this->_params[$param])) {
131            return $this->_params[$param];
132        } else {
133            App::logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__);
134            return null;
[1]135        }
136    }
137
138    /**
139     * Set the specification of thumbnails.
140     *
141     * @access  public
[119]142     * @param   array $spec The specifications for a size of output image.
[1]143     */
[120]144    function setSpec($spec, $index=null)
[1]145    {
[119]146        // A little sanity checking.
147        if (!isset($spec['dest_dir']) || '' == $spec['dest_dir']) {
148            App::logMsg('setSpec error: dest_dir not specified.', LOG_ERR, __FILE__, __LINE__);
[1]149        }
[120]150        if (isset($spec['dest_file_type'])) {
151            switch ($spec['dest_file_type']) {
152            case IMG_JPG :
153                if (imagetypes() & IMG_JPG == 0) {
154                    App::logMsg(sprintf('IMG_JPG is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
155                }
156                $spec['dest_file_extention'] = 'jpg';
157                break;
158            case IMG_PNG :
159                if (imagetypes() & IMG_PNG == 0) {
160                    App::logMsg(sprintf('IMG_PNG is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
161                }
162                $spec['dest_file_extention'] = 'png';
163                break;
164            case IMG_GIF :
165                if (imagetypes() & IMG_GIF == 0) {
166                    App::logMsg(sprintf('IMG_GIF is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
167                }
168                $spec['dest_file_extention'] = 'gif';
169                break;
170            case IMG_WBMP :
171                if (imagetypes() & IMG_WBMP == 0) {
172                    App::logMsg(sprintf('IMG_WBMP is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
173                }
174                $spec['dest_file_extention'] = 'wbmp';
175                break;
176            default :
177                App::logMsg(sprintf('Invalid dest_file_type: %s', $spec['dest_file_type']), LOG_ERR, __FILE__, __LINE__);
178                break;
179            }
180        }
[119]181        if (!isset($spec['width']) || !is_int($spec['width'])) {
182            App::logMsg('setSpec error: width not specified.', LOG_ERR, __FILE__, __LINE__);
183        }
184        if (!isset($spec['height']) || !is_int($spec['height'])) {
185            App::logMsg('setSpec error: height not specified.', LOG_ERR, __FILE__, __LINE__);
186        }
[120]187        if (isset($spec['quality']) && IMG_JPG != $spec['dest_file_type']) {
[119]188            App::logMsg('The "quality" specification is not used unless IMG_JPG is the dest_file_type.', LOG_INFO, __FILE__, __LINE__);
189        }
[120]190        if (isset($spec['progressive']) && IMG_JPG != $spec['dest_file_type']) {
[119]191            App::logMsg('The "progressive" specification is not used unless IMG_JPG is the dest_file_type.', LOG_INFO, __FILE__, __LINE__);
192        }
[120]193       
194        if (isset($index) && isset($this->image_specs[$index])) {
195            // Merge with previous.
[121]196            $final_spec = array_merge($this->image_specs[$index], $spec);
197            $this->image_specs[$index] = $final_spec;
[120]198        } else {
199            // Merge with defaults.
[121]200            $final_spec = array_merge($this->default_image_specs, $spec);           
201            $this->image_specs[] = $final_spec;
[120]202        }
[121]203       
204        return $final_spec;
[1]205    }
206
207    /**
[119]208     * Process an entire directory of images.
[1]209     *
210     * @access  public
211     * @return  bool true on success, false on failure.
212     */
[121]213    function processAll($runtime_specs=null)
[1]214    {
215        // Ensure we have a source.
[119]216        if ('' == $this->getParam('source_dir')) {
217            App::logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
[1]218            return false;
219        }
[119]220
221        // Get all files in source directory.
222        $dir_handle = opendir($this->getParam('source_dir'));
223        while ($dir_handle && ($file = readdir($dir_handle)) !== false) {
224            // If the file name does not start with a dot (. or .. or .htaccess).
225            if (!preg_match('/^\./', $file) && in_array(strtolower(substr($file, strrpos($file, '.') + 1)), $this->getParam('valid_file_extensions'))) {
226                $files[] = $file;
[1]227            }
228        }
[42]229
[119]230        // Process each found file.
231        if (is_array($files) && !empty($files)) {
232            $return_val = 0;
233            foreach ($files as $file_name) {
[121]234                $return_val += $this->processFile($file_name, $runtime_specs);
[119]235            }
[120]236            $this->_raiseMsg(sprintf(_("Resized %s images."), sizeof($files)), MSG_SUCCESS, __FILE__, __LINE__);
[119]237            return 0 === $return_val;
238        } else {
239            App::logMsg(sprintf('No images found to thumbnail in directory %s.', $this->getParam('source_dir')), LOG_NOTICE, __FILE__, __LINE__);
240            return false;
241        }
[1]242    }
243
244    /**
245     * Generate thumbnails for the specified file.
246     *
247     * @access  public
248     * @param   string $file_name Name of file with extention.
[121]249     * @param   array $runtime_specs Array of specifications that will override all configured specifications.
[1]250     * @return  bool true on success, false on failure.
251     */
[121]252    function processFile($file_name, $runtime_specs=null)
[1]253    {
[119]254        // Source file determinted by provided file_name.
255        $source_file = realpath(sprintf('%s/%s', $this->getParam('source_dir'), $file_name));
256       
257        // Ensure we have a source.
258        if (sizeof($this->image_specs) < 1) {
[121]259            if (is_array($runtime_specs)) {
260                $this->setSpec($runtime_specs, 0);
261            } else {
262                App::logMsg(sprintf('Image specifications not set before processing.'), LOG_ERR, __FILE__, __LINE__);
263                return false;               
264            }
[1]265        }
[42]266
[1]267        // Ensure we have a source.
[119]268        if ('' == $this->getParam('source_dir')) {
[1]269            App::logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
270            return false;
271        }
[42]272
[1]273        // Confirm source image exists.
[119]274        if (!file_exists($source_file)) {
[120]275            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s was not found."), $file_name), MSG_ERR, __FILE__, __LINE__);
[121]276            App::logMsg(sprintf('Source image not found: %s', $source_file), LOG_ALERT, __FILE__, __LINE__);
[1]277            return false;
278        }
[42]279
[1]280        // Confirm source image is readable.
[119]281        if (!is_readable($source_file)) {
[120]282            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s is not readable."), $file_name), MSG_ERR, __FILE__, __LINE__);
[121]283            App::logMsg(sprintf('Source image not readable: %s', $source_file), LOG_ALERT, __FILE__, __LINE__);
[1]284            return false;
285        }
[42]286
[1]287        // Confirm source image contains data.
[119]288        if (filesize($source_file) <= 0) {
[120]289            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s is zero bytes."), $file_name), MSG_ERR, __FILE__, __LINE__);
[121]290            App::logMsg(sprintf('Source image is zero bytes: %s', $source_file), LOG_ALERT, __FILE__, __LINE__);
[1]291            return false;
292        }
[42]293
[1]294        // Confirm source image has a valid file extension.
[119]295        if (!$this->_validFileExtension($file_name)) {
[120]296            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s not a valid type. It must have one of the following file name extensions: %s"), $file_name, join(', ', $this->getParam('valid_file_extensions'))), MSG_ERR, __FILE__, __LINE__);
[121]297            App::logMsg(sprintf('Image resizing failed: source image not of valid type: %s', $source_file), LOG_ERR, __FILE__, __LINE__);
[1]298            return false;
299        }
[42]300
[119]301        // Ensure destination directories are created. This will only be called once per page load.
302        $this->_createDestDirs();
303       
304        // To keep this script running even if user tries to stop browser.
305        ignore_user_abort(true);
[121]306        ini_set('max_execution_time', 300);
307        ini_set('max_input_time', 300);
[1]308
309        // This remains zero until something goes wrong.
[119]310        $return_val = 0;
[42]311
[121]312        foreach ($this->image_specs as $index => $spec) {
[119]313           
[121]314            if (is_array($runtime_specs)) {
315                // Override with runtime specs.
316                $spec = $this->setSpec($runtime_specs, $index);
317            }
318           
[119]319            // Destination filename uses the extention defined by dest_file_extention.
[120]320            $dest_file = realpath(sprintf('%s/%s/%s.%s', $this->getParam('source_dir'), $spec['dest_dir'], substr($file_name, 0, strrpos($file_name, '.')), $spec['dest_file_extention']));
[42]321
[119]322            // Skip existing thumbnails with file size below $spec['keep_filesize'].
323            if (isset($spec['keep_filesize']) && file_exists($dest_file)) {
324                $file_size = filesize($dest_file);
325                if (false !== $file_size && $file_size < $spec['keep_filesize']) {
326                    App::logMsg(sprintf('Skipping thumbnail %s. File already exists and file size is less than %s bytes.', $spec['dest_dir'] . '/' . $file_name, $spec['keep_filesize']), LOG_DEBUG, __FILE__, __LINE__);
[1]327                    continue;
328                }
329            }
[42]330
[119]331            // Determine if original file size is smaller than specified thumbnail size. Do not scale-up if $spec['allow_upscaling'] config is set to false.
332            $image_size = getimagesize($source_file);
333            if ($image_size['0'] <= $spec['width'] && $image_size['1'] <= $spec['height'] && !$spec['allow_upscaling']) {
334                $spec['scaling_type'] = IMAGETHUMB_NO_SCALE;
335                App::logMsg(sprintf('Image %s smaller than specified %s thumbnail size. Keeping original size.', $file_name, $spec['dest_dir']), LOG_DEBUG, __FILE__, __LINE__);
[1]336            }
[42]337
[119]338            // DO IT! Based on available method.
339            if (IMAGETHUMB_METHOD_NETPBM === $this->getParam('resize_method') && file_exists($this->getParam('anytopnm_binary')) && file_exists($this->getParam('pnmscale_binary')) && file_exists($this->getParam('cjpeg_binary'))) {
340                // Resize using Netpbm binaries.
341                App::logMsg(sprintf('Resizing with Netpbm...', null), LOG_DEBUG, __FILE__, __LINE__);
342                $return_val += $this->_resizeWithNetpbm($source_file, $dest_file, $spec);
343            } else if (IMAGETHUMB_METHOD_GD === $this->getParam('resize_method') && extension_loaded('gd')) {
344                // Resize with GD.
345                App::logMsg(sprintf('Resizing with GD...', null), LOG_DEBUG, __FILE__, __LINE__);
346                $return_val += $this->_resizeWithGD($source_file, $dest_file, $spec);
[1]347            } else {
[119]348                App::logMsg(sprintf('Image thumbnailing failed. Neither Netpbm or GD is available.', null), LOG_DEBUG, __FILE__, __LINE__);
349                return false;
[1]350            }
[119]351        }
[42]352
[119]353        // If > 0, there was a problem thumb-nailing.
354        return 0 === $return_val;
355    }
356   
357    /*
358    * Use the Netpbm and libjpg cjpeg tools to generate a rescaled compressed image.
359    * This is the preferred method over GD which has (supposedly) less quality.
360    *
361    * @access   private
362    * @param    string  $source_file    Full path to source image file.
363    * @param    string  $dest_file      Full path to destination image file.
364    * @param    array   $spec           Array of image size specifications.
[120]365    * @return   int                     0 if no error, n > 0 if errors.
[119]366    * @author   Quinn Comendant <quinn@strangecode.com>
367    * @version  1.0
368    * @since    19 May 2006 13:55:46
369    */
370    function _resizeWithNetpbm($source_file, $dest_file, $spec)
371    {
372        // Define pnmscale arguments.
373        switch ($spec['scaling_type']) {
374        case IMAGETHUMB_FIT_WIDTH :
375            $pnmscale_args = sprintf(' -width %s ', escapeshellarg($spec['width']));
376            break;
377        case IMAGETHUMB_FIT_HEIGHT :
378            $pnmscale_args = sprintf(' -height %s ', escapeshellarg($spec['height']));
379            break;
380        case IMAGETHUMB_FIT_LARGER :
381            $pnmscale_args = sprintf(' -xysize %s %s ', escapeshellarg($spec['width']), escapeshellarg($spec['height']));
382            break;
383        case IMAGETHUMB_STRETCH :
384            $pnmscale_args = sprintf(' -width %s -height %s ', escapeshellarg($spec['width']), escapeshellarg($spec['height']));
385            break;
386        case IMAGETHUMB_NO_SCALE :
387        default :
388            $pnmscale_args = ' 1 ';
389            break;
[1]390        }
[42]391
[119]392        // Define cjpeg arguments.
393        $cjpeg_args = sprintf(' -optimize -quality %s ', escapeshellarg($spec['quality']));
394        $cjpeg_args .= (true === $spec['progressive']) ? ' -progressive ' : '';
395
396        // Format the command that creates the thumbnail.
397        $command = sprintf('%s %s | %s %s | %s %s > %s/%s',
398            escapeshellcmd($this->getParam('anytopnm_binary')),
399            escapeshellcmd($source_file),
400            escapeshellcmd($this->getParam('pnmscale_binary')),
401            escapeshellcmd($pnmscale_args),
402            escapeshellcmd($this->getParam('cjpeg_binary')),
403            escapeshellcmd($cjpeg_args),
404            escapeshellcmd($dest_file),
405            escapeshellcmd($file_name)
406        );
407        App::logMsg(sprintf('ImageThumb Netpbm command: %s', $command), LOG_DEBUG, __FILE__, __LINE__);
408       
409        // Execute!
410        exec($command, $output, $return_val);
411
412        if (0 === $return_val) {
413            // Success!
414            // Make the thumbnail writable so the user can delete it over ftp without being 'apache'.
415            chmod($dest_file, $this->getParam('dest_file_perms'));
[120]416            App::logMsg(sprintf('Successfully resized image %s', $spec['dest_dir'] . '/' . basename($dest_file), $return_val), LOG_DEBUG, __FILE__, __LINE__);
[119]417        } else {
418            // An error occurred.
[120]419            App::logMsg(sprintf('Image %s failed resizing with return value: %s%s', $spec['dest_dir'] . '/' . basename($dest_file), $return_val, empty($output) ? '' : ' (' . getDump($output) . ')'), LOG_ERR, __FILE__, __LINE__);
[119]420        }
421
422        // Return from the command will be > 0 if there was an error.
423        return $return_val;
[1]424    }
425
[119]426    /*
427    * Use PHP's built-in GD tools to generate a rescaled compressed image.
428    *
429    * @access   private
430    * @param    string  $source_file    Full path to source image file.
431    * @param    string  $dest_file      Full path to destination image file.
432    * @param    array   $spec           Array of image size specifications.
[120]433    * @return   int                     0 if no error, n > 0 if errors.
[119]434    * @author   Quinn Comendant <quinn@strangecode.com>
435    * @version  1.0
436    * @since    19 May 2006 15:46:02
437    */
438    function _resizeWithGD($source_file, $dest_file, $spec)
[1]439    {
[119]440        // Get original file dimensions and type.
441        list($source_image_width, $source_image_height, $source_image_type) = getimagesize($source_file);
442
443        // Define destination image dimentions.
444        switch ($spec['scaling_type']) {
445        case IMAGETHUMB_FIT_WIDTH :
[120]446            $dest_image_width = $spec['width'];
[119]447            $dest_image_height = $source_image_height * ($spec['width'] / $source_image_width);
448            break;
449        case IMAGETHUMB_FIT_HEIGHT :
[120]450            $dest_image_height = $spec['height'];
[119]451            $dest_image_width = $source_image_width * ($spec['height'] / $source_image_height);
452            break;
453        case IMAGETHUMB_FIT_LARGER :
[120]454            if (($source_image_width * ($spec['height'] / $source_image_height)) <= $spec['width']) {
455                // Height is larger.
456                $dest_image_height = $spec['height'];
457                $dest_image_width = $source_image_width * ($spec['height'] / $source_image_height);
[119]458            } else {
[120]459                // Width is larger.
460                $dest_image_width = $spec['width'];
461                $dest_image_height = $source_image_height * ($spec['width'] / $source_image_width);
[119]462            }
463            break;
464        case IMAGETHUMB_STRETCH :
465            $dest_image_width = $spec['width'];
466            $dest_image_height = $spec['height'];
467            break;
468        case IMAGETHUMB_NO_SCALE :
469        default :
470            $dest_image_width = $source_image_width;
471            $dest_image_height = $source_image_height;
472            break;
473        }
474
475        // Create source image data in memory.
476        switch ($source_image_type) {
477        case IMAGETYPE_JPEG :
[120]478            $source_image_resource = imagecreatefromjpeg($source_file);
[119]479            break;
480        case IMAGETYPE_PNG :
[120]481            $source_image_resource = imagecreatefrompng($source_file);
[119]482            break;
483        case IMAGETYPE_GIF :
[120]484            $source_image_resource = imagecreatefromgif($source_file);
[119]485            break;
486        case IMAGETYPE_WBMP :
[120]487            $source_image_resource = imagecreatefromwbmp($source_file);
[119]488        default :
489            App::logMsg(sprintf('Source image type %s not supported.', $source_image_type), LOG_WARNING, __FILE__, __LINE__);
[120]490            return 1;
[119]491            break;
[1]492        }
[120]493        if (!$source_image_resource) {
[119]494            App::logMsg(sprintf('Error creating %s image in memory from %s', $source_image_type, $source_file), LOG_WARNING, __FILE__, __LINE__);
[120]495            return 1;
[119]496        }
497       
498        // Create destination image data in memory.
[120]499        $dest_image_resource = imagecreatetruecolor($dest_image_width, $dest_image_height);
[42]500
[119]501        // Resample!
[120]502        if (!imagecopyresampled($dest_image_resource, $source_image_resource, 0, 0, 0, 0, $dest_image_width, $dest_image_height, $source_image_width, $source_image_height)) {
[119]503            App::logMsg(sprintf('Error resampling image %s', $source_file), LOG_WARNING, __FILE__, __LINE__);
[120]504            return 1;
[1]505        }
[120]506       
507        // Sharpen image using a custom filter matrix.
508        if (phpversion() > '5.1' && true === $spec['sharpen'] && $spec['sharpen_value'] > 0) {
509            $sharpen_value = round((((48 - 10) / (100 - 1)) * (100 - $spec['sharpen_value'])) + 10);
510            imageconvolution($dest_image_resource, array(array(-1,-1,-1),array(-1,$sharpen_value,-1),array(-1,-1,-1)), ($sharpen_value - 8), 0);
511        }
[42]512
[119]513        // Save image.
514        $return_val = true;
[120]515        switch ($spec['dest_file_type']) {
[119]516        case IMG_JPG :
[120]517            imageinterlace($dest_image_resource, (true == $spec['progressive'] ? 1 : 0));
518            $return_val = imagejpeg($dest_image_resource, $dest_file, $spec['quality']);
[119]519            break;
520        case IMG_PNG :
[120]521            $return_val = imagepng($dest_image_resource, $dest_file);
[119]522            break;
523        case IMG_GIF :
[120]524            $return_val = imagegif($dest_image_resource, $dest_file);
[119]525            break;
526        case IMG_WBMP :
[120]527            $return_val = imagewbmp($dest_image_resource, $dest_file);
[119]528            break;
529        default :
[120]530            App::logMsg(sprintf('Destination image type %s not supported for image %s.', $spec['dest_file_type'], $dest_file), LOG_WARNING, __FILE__, __LINE__);
531            return 1;
[119]532            break;
533        }
534
535        if ($return_val) {
536            // Success!
537            // Make the thumbnail writable so the user can delete it over ftp without being 'apache'.
[120]538            chmod($dest_file, $this->getParam('dest_file_perms'));
[119]539            App::logMsg(sprintf('Successfully resized image %s', $dest_file), LOG_DEBUG, __FILE__, __LINE__);
[120]540            return 0;
[1]541        } else {
[119]542            // An error occurred.
543            App::logMsg(sprintf('Image %s failed resizing.', $dest_file), LOG_ERR, __FILE__, __LINE__);
[120]544            return 1;
[1]545        }
546    }
547
548    /**
549     * Delete the thumbnails for the specified file name.
550     *
551     * @access  public
552     * @param   string $file_name The file name to delete, with extention.
553     * @return  bool true on success, false on failure.
554     */
555    function deleteThumbs($file_name)
556    {
557        // Ensure we have a source.
[119]558        if ('' == $this->getParam('source_dir')) {
[1]559            App::logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
560            return false;
561        }
[42]562
[119]563        $return_val = 0;
564        foreach ($this->image_specs as $spec) {
[120]565            $dest_file = realpath(sprintf('%s/%s/%s.%s', $this->getParam('source_dir'), $spec['dest_dir'], substr($file_name, 0, strrpos($file_name, '.')), $spec['dest_file_extention']));
[119]566            if (file_exists($dest_file)) {
567                if (!unlink($dest_file)) {
568                    $return_val++;
569                    App::logMsg(sprintf(_("Delete thumbs failed: %s"), $dest_file), LOG_WARNING, __FILE__, __LINE__);
[1]570                }
571            }
572        }
[121]573        $this->_raiseMsg(sprintf(_("The thumbnails for file %s have been deleted."), $file_name), MSG_SUCCESS, __FILE__, __LINE__);
[119]574        return 0 === $return_val;
[1]575    }
576
577    /**
578     * Delete the source image with the specified file name.
579     *
580     * @access  public
581     * @param   string $file_name The file name to delete, with extention.
582     * @return  bool true on success, false on failure.
583     */
584    function deleteOriginal($file_name)
585    {
586        // Ensure we have a source.
[119]587        if ('' == $this->getParam('source_dir')) {
[1]588            App::logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
589            return false;
590        }
[42]591
[119]592        $source_file = realpath(sprintf('%s/%s', $this->getParam('source_dir'), $file_name));
593        if (!unlink($source_file)) {
594            App::logMsg(sprintf(_("Delete original failed: %s"), $source_file), LOG_WARNING, __FILE__, __LINE__);
[1]595            return false;
596        }
[121]597        $this->_raiseMsg(sprintf(_("The original file %s has been deleted."), $file_name), MSG_SUCCESS, __FILE__, __LINE__);
[1]598        return true;
599    }
[42]600
[1]601    /**
602     * Returns true if file exists.
603     *
604     * @access  public
605     * @param   string $file_name The file name to test, with extention.
606     * @return  bool true on success, false on failure.
607     */
608    function exists($file_name)
609    {
610        // Ensure we have a source.
[119]611        if ('' == $this->getParam('source_dir')) {
[1]612            App::logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
613            return false;
614        }
[42]615
[119]616        $source_file = realpath(sprintf('%s/%s', $this->getParam('source_dir'), $file_name));
617        return file_exists($source_file);
[1]618    }
[42]619
[1]620    /**
621     * Tests if extention of $file_name is in the array valid_file_extensions.
622     *
623     * @access  public
624     * @param   string  $file_name  A file name.
625     * @return  bool    True on success, false on failure.
626     */
[119]627    function _validFileExtension($file_name)
[1]628    {
629        preg_match('/.*?\.(\w+)$/i', $file_name, $ext);
[121]630        return !empty($ext) && in_array(strtolower($ext[1]), $this->getParam('valid_file_extensions'));       
[1]631    }
[42]632
[1]633    /**
[119]634     * Make directory for each specified thumbnail size, if it doesn't exist.
[1]635     *
[119]636     * @access  public
637     * @return  bool true on success, false on failure.
638     */
639    function _createDestDirs()
640    {
641        static $already_checked = false;
642
643        if (!$already_checked) {
644            // Ensure we have a source.
645            if ('' == $this->getParam('source_dir')) {
646                App::logMsg(sprintf('Source directory not set before creating destination directories.'), LOG_ERR, __FILE__, __LINE__);
647                return false;
648            }
649       
650            // Loop through specs and ensure all dirs are created.
651            $return_val = 0;
652            foreach ($this->image_specs as $spec) {
653                if (!file_exists($this->getParam('source_dir') . '/' . $spec['dest_dir'])) {
654                    if (!mkdir($this->getParam('source_dir') . '/' . $spec['dest_dir'], $this->getParam('dest_dir_perms'))) {
655                        $return_val++;
656                        App::logMsg(sprintf('mkdir failure: %s', $this->getParam('source_dir') . '/' . $spec['dest_dir']), LOG_ERR, __FILE__, __LINE__);
657                    }
658                }
659            }
660
661            // If > 0, there was a problem creating dest dirs.
662            return 0 === $return_val;
663        }
664
665        $already_checked = true;
666    }
667
668    /**
669     * An alias for App::raiseMsg that only sends messages configured by display_messages.
670     *
[1]671     * @access public
672     *
673     * @param string $message The text description of the message.
674     * @param int    $type    The type of message: MSG_NOTICE,
675     *                        MSG_SUCCESS, MSG_WARNING, or MSG_ERR.
676     * @param string $file    __FILE__.
677     * @param string $line    __LINE__.
678     */
[119]679    function _raiseMsg($message, $type, $file, $line)
[1]680    {
[119]681        if ($this->getParam('display_messages') === true || (is_int($this->getParam('display_messages')) && $this->getParam('display_messages') & $type > 0)) {
[1]682            App::raiseMsg($message, $type, $file, $line);
683        }
684    }
685
686} // End of class.
687?>
Note: See TracBrowser for help on using the repository browser.