<?php
/**
 * @version $Id: ImageResizer.class.php 531 2008-09-03 05:44:05Z hodaka $
 * @file ImageResizer.class.php
 * @package myuploader
 * @author  hodaka <hodaka@kuri3.net>
 */

if (!defined('XOOPS_ROOT_PATH')) exit();

if(!defined('OS_WINDOWS')) {
    if ('/' == DIRECTORY_SEPARATOR) {
        define('OS_WINDOWS', false);
    } else  {   // Windows
        define('OS_WINDOWS', true);
    }
}

define('LIBRARY_NONE', 'none');
define('LIBRARY_GD', 'gd');
define('LIBRARY_IMAGEMAGICK', 'imagick');
define('LIBRARY_PECL_IMAGEMAGICK', 'imagick_ext');


class ImageResizer {
    var $mSource;
    var $mTargetDir;
    var $mTarget;
    var $mLib = 'none';
    var $mTmpDir;
    var $mImageInfo;
    var $mResizeInfo;
    var $mResizeFlag = true;
    var $mSrc = null;
    var $mDst = null;
    var $mDefaultColor = array(0,0,0);
    var $mKeepAspect = true;
    var $mMakeBigger = false;
    var $mErrors = array();
    
    
    function ImageResizer($targetdir=null, $tmpdir=null) {
        if(!$this->_checkdir($targetdir)) {
            return false;
        }
        $this->mTargetDir = preg_replace("|^(.+)/$|", '$1', $targetdir);

        if($tmpdir == null) {
            $tmpdir = ini_get('upload_tmp_dir');
            if(empty($tmpdir)) {
                $tmpdir = $this->_tmpDir();
            }
        }
        if(!$this->_checkdir($tmpdir)) {
        	return false;
        }
        $this->mTmpDir = preg_replace("|^(.+)/$|", '$1', $tmpdir);

        return true;        
    }

    function _tmpDir() {
        if(OS_WINDOWS) {
            if($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
                return $var;
            }
            if($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
                return $var;
            }
            if($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
                return $var;
            }
            return getenv('SystemRoot') . '\temp';
        }
        if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
            return $var;
        }
        return '/tmp';
    }

    function _checkdir($dir) {
        if(empty($dir)) {
            $this->setErrors('An empty directory name was given.');
            return false;
        }
        if(!is_dir($dir)) {
            // safe_mode or not
            if(ini_get('safe_mode')) {
                $this->setErrors('Can\'t make directory on SAFE MODE unless you make it yourself.');
                return false;
            }
            if (!mkdir($dir, 0777)) {
                $this->setErrors(sprintf('Can\'t make a directory %s and make it writable. Check permissions.', htmlspecialchars($dir, ENT_QUOTES)));
                return false;
            }
        }

        if(!is_writeable($dir)) {
            if(!chmod($dir, 0777)) {
                $this->setErrors(sprintf('Can\'t make % writable. Check permissions.', htmlspecialchars($dir, ENT_QUOTES)));
                return false;
            }
        }

        return true;
    }

    function setLibrary($lib) {
        $this->mLib = $lib;
    }

    function checklib() {
        switch($this->mLib) {
            case LIBRARY_IMAGEMAGICK:
                $response = '';
                exec("convert --help", $response);
                if(!count($response )) {
                    $this->setErrors(sprintf('% library does not exists or lost in path.', 'ImageMagick')); 
                    return false;
                } else {
                    return true;
                }
                break;

            case LIBRARY_PECL_IMAGEMAGICK:
                if(!function_exists('imagick_read')) {
                    $this->setErrors(sprintf('%s module is not installed.', 'PECL_ImageMagick')); 
                    return false;
                } else {
                    return true;
                }
                break;                  
          
            case LIBRARY_GD:
            case LIBRARY_NONE:
            default:
                if(!function_exists('imagecreatetruecolor')) {
                    $this->setErrors(sprintf('% version is out of dated. Needs 2.0 or more.', 'GD')); 
                    return false;
                } else {
                    return true;
                }
                break;
        }
    }

    function load($name) {
    	$this->mSource = $name;
        if(!is_file($this->mSource)) {
        	$this->setErrors(sprintf('The source file %s does not exists.', htmlspecialchars($this->mSource, ENT_QUOTES))); 
            return false;
        }

        $this->mImageInfo = getimagesize($this->mSource);

        if(!$this->mImageInfo || $this->mImageInfo[0] == 0 || $this->mImageInfo[1] == 0) {
            $this->setErrors(sprintf('The source % is not an image file.', htmlspecialchars($this->mSource, ENT_QUOTES))); 
            return false;
        }

        // image type
        if(!in_array($this->mImageInfo[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
            $this->setErrors(sprintf('The mime of source %s is not permitted.', htmlspecialchars($this->mSource, ENT_QUOTES)));
            return false;
        }

        // set a function type
        $this->mImageInfo['funcType'] = $this->mImageInfo['ext'] = preg_replace('#image/#i', '', $this->mImageInfo['mime']);
        if($this->mImageInfo['funcType'] == 'jpg') {
        	$this->mImageInfo['funcType'] = 'jpeg';
        }
        if($this->mImageInfo['ext'] == 'jpeg') {
            $this->mImageInfo['ext'] = 'jpg';
        }
        $this->mResizeInfo = $this->mImageInfo;
        
        switch($this->mLib) {
        	case LIBRARY_NONE:
            case LIBRARY_GD:
                $funcName = 'imagecreatefrom' . $this->getNewType();
                $this->mSrc = @$funcName($this->mSource);
                if(!$this->mSrc) {
                	$this->setErrors(sprintf('The source file %s cannot be opened as an image.', htmlspecialchars($this->mSource, ENT_QUOTES))); 
                    return false;
                }
                break;               
            
            case LIBRARY_PECL_IMAGEMAGICK:
                $this->mSrc = @imagick_readimage($this->mSource);
                if(imagick_iserror($this->mSrc)) {
                    $this->setErrors(sprintf('The source file %s cannot be opened as an image.', htmlspecialchars($this->mSource, ENT_QUOTES))); 
                    return false;
                }
                break;
                
            case LIBRARY_IMAGEMAGICK:
            default:
                break;
        }

        return true;
    }

    function resize($new_w, $new_h) {
        $this->mResizeFlag = true;
        $base_w = $this->getWidth();
        $base_h = $this->getHeight();
        
        if ($this->mKeepAspect) {
            $percent = 1;
            if($base_w > $new_w || $base_h > $new_h || $this->mMakeBigger) {
                $w_percent = $new_w / $base_w;
                $h_percent = $new_h / $base_h;
                $percent = min($w_percent, $h_percent);
                $this->mResizeInfo[0] = $base_w * $percent;
                $this->mResizeInfo[1] = $base_h * $percent;
            } else {
            	$this->mResizeFlag = false;
            }
        } else {
            $this->mResizeInfo[0] = $new_w;
            $this->mResizeInfo[1] = $new_h;
        }

        // go thru if too small to resize
        if(!$this->mResizeFlag) {
            return true;
        }
        
        switch($this->mLib) {
            case LIBRARY_IMAGEMAGICK:
                break;
                
            case LIBRARY_PECL_IMAGEMAGICK:
                @imagick_set_image_quality($this->mSrc, 100);
                @imagick_resize($this->mSrc, $this->getNewWidth(), $this->getNewHeight(), IMAGICK_FILTER_UNKNOWN, 1);
                break;
                
            case LIBRARY_GD:
            case LIBRARY_NONE:
            default:
                $this->mDst = @imagecreatetruecolor($this->mResizeInfo[0], $this->mResizeInfo[1]);
                if(!$this->mDst) {
                	$this->setErrors(sprintf('Can\'t initiate a GD image from %s.', htmlspecialchars($this->mSource, ENT_QUOTES)));
                    return false;
                }
                if ($this->getNewType() == 'png' || $this->getNewType() == 'gif') { // This preserves the transparency
                    @imagealphablending($this->mDst, false);
                    @imagesavealpha($this->mDst, true);
                }/* else { // This is if converting from PNG to another image format
                    list($r, $g, $b) = $this->mDefaultColor;
                    $color = @imagecolorallocate($this->mNew, $r, $g, $b);
                    @imagefilledrectangle($this->mNew, 0, 0, $this->getNewWidth(), $this->getNewHeight(), $color);
                }*/
                @imagecopyresampled($this->mDst, $this->mSrc, 0, 0, 0, 0, $this->getNewWidth(), $this->getNewHeight(), $this->getWidth(), $this->getHeight());
                break;
        }

        return true;    	
    }


    function setTarget($name) {
        $this->mTarget = $this->mTargetDir.'/'.$name;
    }

    function save($chmod=0644) {
    	// just copy if too small to resize
        if(!$this->mResizeFlag) {
            @copy($this->mSource, $this->mTarget);
            return true;
        }
        
        switch($this->mLib) {
        	case LIBRARY_IMAGEMAGICK:
                @exec("convert -geometry {".$this->getNewWidth()."}x{".$this->getNewHeight()."} $this->mSource $this->mTarget");
                break;
                
            case LIBRARY_PECL_IMAGEMAGICK:
                @imagick_writeimage($this->mSrc, $this->mTarget);
                @imagick_destroyhandle($this->mSrc);
                break;
                
            case LIBRARY_GD:
            case LIBRARY_NONE:
            default:
                $funcName = 'image'.$this->getNewType();
                if(!function_exists($funcName)) {
                    $this->setErrors(sprintf('%s function is not supported.', htmlspecialchars($funcName, ENT_QUOTES)));
                    return false;
                }

                @$funcName($this->mDst, $this->mTarget);
                @imagedestroy($this->mDst);
                break;
        }

        if(!getimagesize($this->mTarget)) {
            $this->setErrors(sprintf('Could not resize %s into %s.', htmlspecialchars($this->mSource, ENT_QUOTES), htmlspecialchars($this->mTarget, ENT_QUOTES)));
            return false;
        }
        
        @chmod($this->mTarget, $chmod);
        
        return true;
    }

    function _sourceDir($sourcedir) {
        if(!empty($sourcedir)) {
            $dir = $sourcedir;
        } else {
            $dir = ini_get('upload_tmp_dir');
            if(empty($dir)) {
                $dir = $this->_tmpDir();
            }
        }
        $dir = preg_replace("|^(.+)/$|", '$1', $dir);
        if(!is_dir($dir)) {
        	
        }

        return $dir;
    } 

    function getWidth() {
    	return $this->mImageInfo[0];
    }

    function getHeight() {
    	return $this->mImageInfo[1];
    }

    function getNewWidth() {
        return $this->mResizeInfo[0];
    }

    function getNewHeight() {
        return $this->mResizeInfo[1];
    }

    function getNewType() {
    	return $this->mResizeInfo['funcType'];
    }

    /**
     * Add an error
     * 
     * @param   string  $error
     **/
    function setErrors($error)
    {
        $this->mErrors[] = trim($error);
    }
    /**
     * Get generated errors
     * 
     * @param   array|string
     */
    function &getErrors($ashtml = true)
    {
        if (!$ashtml) {
            return $this->mErrors;
        } else {
            $ret = '';
            if (count($this->mErrors) > 0) {
                $ret = '<h1>Errors occurred while uploading.</h1>';
                foreach ($this->mErrors as $error) {
                    $ret .= $error.'<br />';
                }
            }
            return $ret;
        }
    }

}

?>