Index: trunk/lib/ImageThumb.inc.php
===================================================================
--- trunk/lib/ImageThumb.inc.php	(revision 119)
+++ trunk/lib/ImageThumb.inc.php	(revision 120)
@@ -33,10 +33,4 @@
         // Permissions of autocreated directories. Must be at least 0700 with owner=apache.
         'dest_dir_perms' => 0777,
-        
-        // Destination file types. (IMG_JPG, IMG_PNG, IMG_GIF, IMG_WBMP)
-        'dest_file_type' => IMG_JPG,
-
-        // Destination file types. ('jpg', 'png', 'gif', 'wbmp')
-        'dest_file_extention' => 'jpg',
 
         // Require file to have one of the following file name extentions.
@@ -59,14 +53,31 @@
         // The destination for an image thumbnail size. Path relative to source_dir (eg: ../thumbs).
         'dest_dir' => null,
+        
+        // Destination file types. (IMG_JPG, IMG_PNG, IMG_GIF, IMG_WBMP)
+        'dest_file_type' => IMG_JPG,
+
+        // Destination file types. ('jpg', 'png', 'gif', 'wbmp')
+        'dest_file_extention' => 'jpg',
+        
         // Type of scaling to perform, and sizes used to calculate max dimentions.
         'scaling_type' => IMAGETHUMB_FIT_LARGER,
         'width' => null,
         'height' => null,
+
         // Percentage quality of image compression output 0-100.
         'quality' => 65,
+
         // Create progressive jpegs?
         'progressive' => false,
+
+        // If using GD method, apply sharpen filter. Requires PHP > 5.1.
+        'sharpen' => true,
+        
+        // Integers between 1-100, useful values are 65-85.
+        'sharpen_value' => 75,
+
         // If source image is smaller than thumbnail, allow upscaling?
         'allow_upscaling' => false,
+
         // If thumb exists and filesize is smaller than this, do not overwrite the thumb.
         'keep_filesize' => null,
@@ -100,36 +111,4 @@
                 }
             }
-            
-            if (isset($params['dest_file_type'])) {
-                switch ($params['dest_file_type']) {
-                case IMG_JPG :
-                    if (imagetypes() & IMG_JPG == 0) {
-                        App::logMsg(sprintf('IMG_JPG is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
-                    }
-                    $params['dest_file_extention'] = 'jpg';
-                    break;
-                case IMG_PNG :
-                    if (imagetypes() & IMG_PNG == 0) {
-                        App::logMsg(sprintf('IMG_PNG is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
-                    }
-                    $params['dest_file_extention'] = 'png';
-                    break;
-                case IMG_GIF :
-                    if (imagetypes() & IMG_GIF == 0) {
-                        App::logMsg(sprintf('IMG_GIF is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
-                    }
-                    $params['dest_file_extention'] = 'gif';
-                    break;
-                case IMG_WBMP :
-                    if (imagetypes() & IMG_WBMP == 0) {
-                        App::logMsg(sprintf('IMG_WBMP is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
-                    }
-                    $params['dest_file_extention'] = 'wbmp';
-                    break;
-                default :
-                    App::logMsg(sprintf('Invalid dest_file_type: %s', $params['dest_file_type']), LOG_ERR, __FILE__, __LINE__);
-                    break;
-                }
-            }
 
             // Merge new parameters with old overriding only those passed.
@@ -163,27 +142,61 @@
      * @param   array $spec The specifications for a size of output image.
      */
-    function setSpec($spec)
+    function setSpec($spec, $index=null)
     {
         // A little sanity checking.
         if (!isset($spec['dest_dir']) || '' == $spec['dest_dir']) {
             App::logMsg('setSpec error: dest_dir not specified.', LOG_ERR, __FILE__, __LINE__);
-            return false;
+        }
+        if (isset($spec['dest_file_type'])) {
+            switch ($spec['dest_file_type']) {
+            case IMG_JPG :
+                if (imagetypes() & IMG_JPG == 0) {
+                    App::logMsg(sprintf('IMG_JPG is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
+                }
+                $spec['dest_file_extention'] = 'jpg';
+                break;
+            case IMG_PNG :
+                if (imagetypes() & IMG_PNG == 0) {
+                    App::logMsg(sprintf('IMG_PNG is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
+                }
+                $spec['dest_file_extention'] = 'png';
+                break;
+            case IMG_GIF :
+                if (imagetypes() & IMG_GIF == 0) {
+                    App::logMsg(sprintf('IMG_GIF is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
+                }
+                $spec['dest_file_extention'] = 'gif';
+                break;
+            case IMG_WBMP :
+                if (imagetypes() & IMG_WBMP == 0) {
+                    App::logMsg(sprintf('IMG_WBMP is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
+                }
+                $spec['dest_file_extention'] = 'wbmp';
+                break;
+            default :
+                App::logMsg(sprintf('Invalid dest_file_type: %s', $spec['dest_file_type']), LOG_ERR, __FILE__, __LINE__);
+                break;
+            }
         }
         if (!isset($spec['width']) || !is_int($spec['width'])) {
             App::logMsg('setSpec error: width not specified.', LOG_ERR, __FILE__, __LINE__);
-            return false;
         }
         if (!isset($spec['height']) || !is_int($spec['height'])) {
             App::logMsg('setSpec error: height not specified.', LOG_ERR, __FILE__, __LINE__);
-            return false;
-        }
-        if (isset($spec['quality']) && IMG_JPG != $this->getParam('dest_file_type')) {
+        }
+        if (isset($spec['quality']) && IMG_JPG != $spec['dest_file_type']) {
             App::logMsg('The "quality" specification is not used unless IMG_JPG is the dest_file_type.', LOG_INFO, __FILE__, __LINE__);
         }
-        if (isset($spec['progressive']) && IMG_JPG != $this->getParam('dest_file_type')) {
+        if (isset($spec['progressive']) && IMG_JPG != $spec['dest_file_type']) {
             App::logMsg('The "progressive" specification is not used unless IMG_JPG is the dest_file_type.', LOG_INFO, __FILE__, __LINE__);
         }
-        // Merge defaults with provided.
-        $this->image_specs[] = array_merge($this->default_image_specs, $spec);
+        
+        if (isset($index) && isset($this->image_specs[$index])) {
+            // Merge with previous.
+            $this->image_specs[$index] = array_merge($this->image_specs[$index], $spec);
+        } else {
+            // Merge with defaults.
+            $this->image_specs[] = array_merge($this->default_image_specs, $spec);            
+        }
     }
 
@@ -217,4 +230,5 @@
                 $return_val += $this->processFile($file_name);
             }
+            $this->_raiseMsg(sprintf(_("Resized %s images."), sizeof($files)), MSG_SUCCESS, __FILE__, __LINE__);
             return 0 === $return_val;
         } else {
@@ -250,5 +264,5 @@
         // Confirm source image exists.
         if (!file_exists($source_file)) {
-            $this->_raiseMsg(sprintf(_("Image resizing failed: source image not found: <strong>%s</strong>"), $file_name), MSG_ERR, __FILE__, __LINE__);
+            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s was not found."), $file_name), MSG_ERR, __FILE__, __LINE__);
             App::logMsg(sprintf('Source image not found: %s', $file_name), LOG_ALERT, __FILE__, __LINE__);
             return false;
@@ -257,5 +271,5 @@
         // Confirm source image is readable.
         if (!is_readable($source_file)) {
-            $this->_raiseMsg(sprintf(_("Image resizing failed: source image not readable: <strong>%s</strong>"), $file_name), MSG_ERR, __FILE__, __LINE__);
+            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s is not readable."), $file_name), MSG_ERR, __FILE__, __LINE__);
             App::logMsg(sprintf('Source image not readable: %s', $file_name), LOG_ALERT, __FILE__, __LINE__);
             return false;
@@ -264,5 +278,5 @@
         // Confirm source image contains data.
         if (filesize($source_file) <= 0) {
-            $this->_raiseMsg(sprintf(_("Image resizing failed: source image corrupt: <strong>%s</strong>"), $file_name), MSG_ERR, __FILE__, __LINE__);
+            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s is zero bytes."), $file_name), MSG_ERR, __FILE__, __LINE__);
             App::logMsg(sprintf('Source image is zero bytes: %s', $file_name), LOG_ALERT, __FILE__, __LINE__);
             return false;
@@ -271,5 +285,5 @@
         // Confirm source image has a valid file extension.
         if (!$this->_validFileExtension($file_name)) {
-            $this->_raiseMsg(sprintf(_("Image resizing failed: source image not of valid type: <strong>%s</strong>"), $file_name), MSG_ERR, __FILE__, __LINE__);
+            $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__);
             App::logMsg(sprintf('Image resizing failed: source image not of valid type: %s', $file_name), LOG_ERR, __FILE__, __LINE__);
             return false;
@@ -291,5 +305,5 @@
             
             // Destination filename uses the extention defined by dest_file_extention.
-            $dest_file = realpath(sprintf('%s/%s/%s.%s', $this->getParam('source_dir'), $spec['dest_dir'], substr($file_name, 0, strrpos($file_name, '.')), $this->getParam('dest_file_extention')));
+            $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']));
 
             // Skip existing thumbnails with file size below $spec['keep_filesize'].
@@ -336,5 +350,5 @@
     * @param    string  $dest_file      Full path to destination image file.
     * @param    array   $spec           Array of image size specifications.
-    * @return   bool                    Success value.
+    * @return   int                     0 if no error, n > 0 if errors.
     * @author   Quinn Comendant <quinn@strangecode.com>
     * @version  1.0
@@ -387,8 +401,8 @@
             // Make the thumbnail writable so the user can delete it over ftp without being 'apache'.
             chmod($dest_file, $this->getParam('dest_file_perms'));
-            App::logMsg(sprintf('Successfully resized image %s', $spec['dest_dir'] . '/' . $file_name, $return_val), LOG_DEBUG, __FILE__, __LINE__);
+            App::logMsg(sprintf('Successfully resized image %s', $spec['dest_dir'] . '/' . basename($dest_file), $return_val), LOG_DEBUG, __FILE__, __LINE__);
         } else {
             // An error occurred.
-            App::logMsg(sprintf('Image %s failed resizing with return value: %s%s', $spec['dest_dir'] . '/' . $file_name, $return_val, empty($output) ? '' : ' (' . getDump($output) . ')'), LOG_ERR, __FILE__, __LINE__);
+            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__);
         }
 
@@ -404,5 +418,5 @@
     * @param    string  $dest_file      Full path to destination image file.
     * @param    array   $spec           Array of image size specifications.
-    * @return   bool                    Success value.
+    * @return   int                     0 if no error, n > 0 if errors.
     * @author   Quinn Comendant <quinn@strangecode.com>
     * @version  1.0
@@ -417,18 +431,20 @@
         switch ($spec['scaling_type']) {
         case IMAGETHUMB_FIT_WIDTH :
+            $dest_image_width = $spec['width'];
             $dest_image_height = $source_image_height * ($spec['width'] / $source_image_width);
-            $dest_image_width = $spec['width'];
             break;
         case IMAGETHUMB_FIT_HEIGHT :
+            $dest_image_height = $spec['height'];
             $dest_image_width = $source_image_width * ($spec['height'] / $source_image_height);
-            $dest_image_height = $spec['height'];
             break;
         case IMAGETHUMB_FIT_LARGER :
-            if ($source_image_width < $source_image_height) {
-               $dest_image_width = $source_image_width * ($spec['height'] / $source_image_height);
-               $dest_image_height = $source_image_height;
+            if (($source_image_width * ($spec['height'] / $source_image_height)) <= $spec['width']) {
+                // Height is larger.
+                $dest_image_height = $spec['height'];
+                $dest_image_width = $source_image_width * ($spec['height'] / $source_image_height);
             } else {
-               $dest_image_height = $source_image_height * ($spec['width'] / $source_image_width);
-               $dest_image_width = $source_image_width;
+                // Width is larger.
+                $dest_image_width = $spec['width'];
+                $dest_image_height = $source_image_height * ($spec['width'] / $source_image_width);
             }
             break;
@@ -443,62 +459,62 @@
             break;
         }
-        
-        echo '<li> sourceWidth: ' . $source_image_width;
-        echo '<li> sourceHeight: ' . $source_image_height;
-        echo '<li> Width: ' . $dest_image_width;
-        echo '<li> Height: ' . $dest_image_height;
-        die;///
 
         // Create source image data in memory.
         switch ($source_image_type) {
         case IMAGETYPE_JPEG :
-            $source_image_data = imagecreatefromjpeg($source_file);
+            $source_image_resource = imagecreatefromjpeg($source_file);
             break;
         case IMAGETYPE_PNG :
-            $source_image_data = imagecreatefrompng($source_file);
+            $source_image_resource = imagecreatefrompng($source_file);
             break;
         case IMAGETYPE_GIF :
-            $source_image_data = imagecreatefromgif($source_file);
+            $source_image_resource = imagecreatefromgif($source_file);
             break;
         case IMAGETYPE_WBMP :
-            $source_image_data = imagecreatefromwbmp($source_file);
+            $source_image_resource = imagecreatefromwbmp($source_file);
         default :
             App::logMsg(sprintf('Source image type %s not supported.', $source_image_type), LOG_WARNING, __FILE__, __LINE__);
-            return false;
-            break;
-        }
-        if (!$source_image_data) {
+            return 1;
+            break;
+        }
+        if (!$source_image_resource) {
             App::logMsg(sprintf('Error creating %s image in memory from %s', $source_image_type, $source_file), LOG_WARNING, __FILE__, __LINE__);
-            return false;
+            return 1;
         }
         
         // Create destination image data in memory.
-        $dest_image_data = imagecreatetruecolor($dest_image_width, $dest_image_height);
+        $dest_image_resource = imagecreatetruecolor($dest_image_width, $dest_image_height);
 
         // Resample!
-        if (!imagecopyresampled($dest_image_data, $source_image_data, 0, 0, 0, 0, $dest_image_width, $dest_image_height, $source_image_width, $source_image_height)) {
+        if (!imagecopyresampled($dest_image_resource, $source_image_resource, 0, 0, 0, 0, $dest_image_width, $dest_image_height, $source_image_width, $source_image_height)) {
             App::logMsg(sprintf('Error resampling image %s', $source_file), LOG_WARNING, __FILE__, __LINE__);
-            return false;
+            return 1;
+        }
+        
+        // Sharpen image using a custom filter matrix.
+        if (phpversion() > '5.1' && true === $spec['sharpen'] && $spec['sharpen_value'] > 0) {
+            $sharpen_value = round((((48 - 10) / (100 - 1)) * (100 - $spec['sharpen_value'])) + 10);
+            imageconvolution($dest_image_resource, array(array(-1,-1,-1),array(-1,$sharpen_value,-1),array(-1,-1,-1)), ($sharpen_value - 8), 0);
         }
 
         // Save image.
         $return_val = true;
-        switch ($this->getParam('dest_file_type')) {
+        switch ($spec['dest_file_type']) {
         case IMG_JPG :
-            imageinterlace($dest_image_data, (true == $spec['progressive'] ? 1 : 0));
-            $return_val = imagejpeg($dest_image_data, $dest_file, $spec['quality']);
+            imageinterlace($dest_image_resource, (true == $spec['progressive'] ? 1 : 0));
+            $return_val = imagejpeg($dest_image_resource, $dest_file, $spec['quality']);
             break;
         case IMG_PNG :
-            $return_val = imagepng($dest_image_data, $dest_file);
+            $return_val = imagepng($dest_image_resource, $dest_file);
             break;
         case IMG_GIF :
-            $return_val = imagegif($dest_image_data, $dest_file);
+            $return_val = imagegif($dest_image_resource, $dest_file);
             break;
         case IMG_WBMP :
-            $return_val = imagewbmp($dest_image_data, $dest_file);
+            $return_val = imagewbmp($dest_image_resource, $dest_file);
             break;
         default :
-            App::logMsg(sprintf('Destination image type %s not supported for image %s.', $this->getParam('dest_file_type'), $dest_file), LOG_WARNING, __FILE__, __LINE__);
-            return false;
+            App::logMsg(sprintf('Destination image type %s not supported for image %s.', $spec['dest_file_type'], $dest_file), LOG_WARNING, __FILE__, __LINE__);
+            return 1;
             break;
         }
@@ -507,11 +523,11 @@
             // Success!
             // Make the thumbnail writable so the user can delete it over ftp without being 'apache'.
-            chmod($source_file, $this->getParam('dest_file_perms'));
+            chmod($dest_file, $this->getParam('dest_file_perms'));
             App::logMsg(sprintf('Successfully resized image %s', $dest_file), LOG_DEBUG, __FILE__, __LINE__);
-            return true;
+            return 0;
         } else {
             // An error occurred.
             App::logMsg(sprintf('Image %s failed resizing.', $dest_file), LOG_ERR, __FILE__, __LINE__);
-            return false;
+            return 1;
         }
     }
@@ -534,5 +550,5 @@
         $return_val = 0;
         foreach ($this->image_specs as $spec) {
-            $dest_file = realpath(sprintf('%s/%s/%s.%s', $this->getParam('source_dir'), $spec['dest_dir'], substr($file_name, 0, strrpos($file_name, '.')), $this->getParam('dest_file_extention')));
+            $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']));
             if (file_exists($dest_file)) {
                 if (!unlink($dest_file)) {
