Файл: core/asido/class.driver.php
Строк: 332
<?php
/**
* @author Kaloyan K. Tsvetkov <kaloyan@kaloyan.info>
* @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License Version 2.1
* @package Asido
* @subpackage Asido.Driver
* @version $Id: class.driver.php 7 2007-04-09 21:09:09Z mrasnika $
*/
/////////////////////////////////////////////////////////////////////////////
/**
* Asido abstract driver
*
* @package Asido
* @subpackage Asido.Driver
* @abstract
*/
Class Asido_Driver {
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    /**
    * Maps to supported mime types
    * @var array
    * @access protected
    */
    var $__mime = array(
        // support reading
        //
        'read' => array(
            ),
        // support writing
        //
        'write' => array(
            ),
        );
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    /**
    * Checks whether the environment is compatible with this driver
    *
    * @return boolean
    * @access public
    * @abstract
    */
    function is_compatible() {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    
    /**
    * Resize an image
    *
    * @param Asido_TMP &$tmp
    * @param integer $width
    * @param integer $height
    * @param mixed $mode
    * @return boolean
    * @access public
    */
    function resize(&$tmp, $width, $height, $mode) {
        
        // no params ?
        //
        if (!$width && !$height) {
            trigger_error(
                sprintf(
                    'Neither width nor height provided '
                        . ' for resizing operation '
                        . ' of "%s" ',
                    $tmp->source_filename
                    ),
                E_USER_WARNING
                );
            return false;
            }
        // resize by only one parameter ?
        //
        if (!$width || !$height) {
            $mode = ASIDO_RESIZE_PROPORTIONAL;
            
            if (!$width) {
                $width = floor(
                    $tmp->image_width * $height / $tmp->image_height
                    );
                }
            if (!$height) {
                $height = floor(
                    $tmp->image_height * $width / $tmp->image_width
                    );
                }
            }
        // stretch or proportional
        //
        switch ($mode) {
            case ASIDO_RESIZE_STRETCH:
                $p_width = $width;
                $p_height = $height;
                break;
                
            case ASIDO_RESIZE_FIT:
                
                if (($tmp->image_height <= $height) && ($tmp->image_width <= $width)) {
                    $p_width = $tmp->image_width;
                    $p_height = $tmp->image_height;
                    
                    // break the switchcase
                    //
                    break;
                    }
                // if indeed has to be resized, fall
                // back to the proportional resize
                //
                ;
            default:
            case ASIDO_RESIZE_PROPORTIONAL:
                
                $p1_width = $width;
                $p1_height = round(
                    $tmp->image_height * $width / $tmp->image_width
                    );
                if ($p1_height - $height > 1) {
                    $p_height = $height;
                    $p_width = round(
                        $tmp->image_width * $height / $tmp->image_height
                        );
                    } else {
                    $p_width = $p1_width;
                    $p_height = $p1_height;
                    }
                break;
            }
        // do the resize
        //
        $r = $this->__resize($tmp, $p_width, $p_height);
    
        // new dimensions ?
        //
        $tmp->image_width = $p_width;
        $tmp->image_height = $p_height;
        
        return $r;
        }
    /**
    * Convert an image from one file-type to another
    *
    * @param Asido_TMP &$tmp
    * @param string $mime_type
    * @return boolean
    * @access public
    */
    function convert(&$tmp, $mime_type) {
        
        $mime_type = strToLower($mime_type);
        
        // supported format ? (for writing)
        //
        if (!$this->supported($mime_type, ASIDO_SUPPORT_WRITE)) {
            trigger_error(
                sprintf(
                    'Requested conversion format "%s" is not supported',
                    $mime_type
                    ),
                E_USER_WARNING
                );
            return false;
            }
        $tmp->save = $mime_type;
        return true;
        }
    /**
    * Watermark an image 
    *
    * @param Asido_TMP &$tmp
    * @param string $watermark_image
    * @param mixed $position
    * @param mixed $scalable
    * @param float $scalable_factor
    * @return boolean
    * @access public
    */
    function watermark(&$tmp, $watermark_image, $position, $scalable, $scalable_factor) {
        
        // open
        //
        $wi = new Asido_Image();
        if (!@$wi->source($watermark_image)) {
            trigger_error(
                sprintf(
                    'Watermark image "%s" is '
                        . ' either missing or '
                        . ' is not readable',
                    $watermark_image
                    ),
                E_USER_WARNING
                );
            return false;
            }
        
        $wt = $this->prepare($wi);
        // dimensions
        //
        $target_width = $tmp->image_width;
        $target_height = $tmp->image_height;
        $watermark_width =& $wt->image_width;
        $watermark_height =& $wt->image_height;
        
        // watermark scalable ?
        //
        if ((ASIDO_WATERMARK_SCALABLE_ENABLED == $scalable)
                && ($watermark_width > $target_width * $scalable_factor
                    || $watermark_height > $target_height * $scalable_factor)
            ){
            
            // jump thru tha loop
            //
            $t2 = $this->__tmpimage($wt->source);
            
            if ($this->resize(&$t2,
                    intval($target_width * $scalable_factor),
                    intval($target_height * $scalable_factor),
                    ASIDO_RESIZE_PROPORTIONAL)
                ){
                @unlink($t2->source_filename);
                $this->__destroy_target($wt);
                // new watermark created, destroy old
                //
                $this->__destroy_source($wt);
                // copy new watermark
                //
                $wt->source = $t2->target;
                $this->__destroy_source($t2);
                    // ^
                    // DO NOT UNSET $t2->target!!!
                // adjust watermark dimensions
                //
                $watermark_width = $t2->image_width;
                $watermark_height =$t2->image_height;
                }
            }
        
        
        // position
        //
        switch ($position) {
            
            // tile watermark
            //
            case ASIDO_WATERMARK_TILE :
                $watermark_x = 1;
                $watermark_y = 1;
                
                // create tile
                //
                for ($x = 0; $x < ceil($target_width / $watermark_width); $x++) {
                    for ($y = 0; $y < ceil($target_height / $watermark_height); $y++) {
                        
                        // skip the first one
                        //
                        if (!$x && !$y) continue;
                        
                        // copy the watermark
                        //
                        $this->__copy($tmp, $wt,
                            $watermark_x + $x*$watermark_width,
                            $watermark_y + $y*$watermark_height
                            );
                        }
                    }
                break;
            
            // top left, north west
            //
            case ASIDO_WATERMARK_TOP_LEFT :
                $watermark_x = 1;
                $watermark_y = 1;
                break;
            
            // top center, north
            //
            case ASIDO_WATERMARK_TOP_CENTER :
                $watermark_x = ($target_width - $watermark_width)/2;
                $watermark_y = 1;
                break;
            
            // top right, north east
            //
            case ASIDO_WATERMARK_TOP_RIGHT :
                $watermark_x = $target_width - $watermark_width ;
                $watermark_y = 1;
                break;
            
            // middle left, west
            //
            case ASIDO_WATERMARK_MIDDLE_LEFT :
                $watermark_x = 1;
                $watermark_y = ($target_height - $watermark_height)/2;
                break;
            
            // middle center, center
            //
            case ASIDO_WATERMARK_MIDDLE_CENTER :
                $watermark_x = ($target_width - $watermark_width)/2;
                $watermark_y = ($target_height - $watermark_height)/2;
                break;
            
            // middle right, east
            //
            case ASIDO_WATERMARK_MIDDLE_RIGHT :
                $watermark_x = $target_width - $watermark_width ;
                $watermark_y = ($target_height - $watermark_height)/2;
                break;
            
            // bottom left, south west
            //
            case ASIDO_WATERMARK_BOTTOM_LEFT :
                $watermark_x = 1;
                $watermark_y = $target_height - $watermark_height ;
                break;
            
            // bottom center, south
            //
            case ASIDO_WATERMARK_BOTTOM_CENTER :
                $watermark_x = ($target_width - $watermark_width)/2;
                $watermark_y = $target_height - $watermark_height ;
                break;
            
            default :
            
            // bottom right, south east
            //
            case ASIDO_WATERMARK_BOTTOM_RIGHT :
                $watermark_x = $target_width - $watermark_width ;
                $watermark_y = $target_height - $watermark_height ;
                break;
            }
        // copy the watermark
        //
        $this->__copy($tmp, $wt, $watermark_x, $watermark_y);
        
        // destroy watermark image
        //
        $this->__destroy_source($wt);
        return true;
        }
    /**
    * Make the image greyscale
    *
    * @param Asido_TMP &$tmp
    * @return boolean
    * @access public
    */
    function grayscale(&$tmp) {
        return $this->__grayscale($tmp);
        }
    /**
    * Rotate the image clockwise
    *
    * @param Asido_TMP &$tmp
    * @param float $angle
    * @param Asido_Color $color
    * @return boolean
    * @access public
    */
    function rotate(&$tmp, $angle, $color=null) {
        
        // color ?
        //
        if (!is_a($color, 'Asido_Color')) {
            $color = new Asido_Color;
            $color->set(255, 255, 255);
            }
        
        return $this->__rotate($tmp, $angle, $color);
        }
    /**
    * Resize an image by "framing" it with the provided width and height
    *
    * @param Asido_Tmp &$tmp
    * @param integer $width
    * @param integer $height
    * @param Asido_Color $color
    * @return boolean
    * @access public
    */
    function frame(&$tmp, $width, $height, $color=null) {
        
        // color ?
        //
        if (!is_a($color, 'Asido_Color')) {
            $color = new Asido_Color;
            $color->set(255, 255, 255);
            }
        
        // resize it
        //
        if (!$this->resize($tmp, $width, $height, ASIDO_RESIZE_FIT)) {
            return false;
            }
        
        // get canvas
        //
        if (!$t2 = $this->__canvas($width, $height, $color)) {
            trigger_error(
                sprintf(
                    'Unable to get a canvas '
                        . ' with %s pixels '
                        . ' width and %s '
                        . ' pixels height',
                    $width, $height
                    ),
                E_USER_WARNING
                );
            return false;
            }
        
        // target
        //
        $t3 = new Asido_TMP;
        $t3->source =& $tmp->target;
        $t3->image_width = $tmp->image_width;
        $t3->image_height = $tmp->image_height;
        
        // apply the image
        //
        if (!$this->__copy(
            $t2, $t3,
            round(($t2->image_width - $t3->image_width)/2),
            round(($t2->image_height - $t3->image_height)/2)
            )) {
            trigger_error(
                'Failed to copy to the passepartout image',
                E_USER_WARNING
                );
            return false;
            }
        
        // cook the result
        //
        $this->__destroy_target($tmp);
        $tmp->target = $t2->target;
        $tmp->image_width = $t2->image_width;
        $tmp->image_height = $t2->image_height;
        
        return true;
        }
    /**
    * Resize an image by "framing" it with the provided width and height
    *
    * @param Asido_Tmp &$tmp
    * @param string $applied_image    filepath to the image that is going to be copied
    * @param integer $x
    * @param integer $y
    * @return boolean
    * @access public
    */
    function copy(&$tmp, $applied_image, $x, $y) {
        // open
        //
        $ci = new Asido_Image;
        if (!@$ci->source($applied_image)) {
            trigger_error(
                sprintf(
                    'The image that is going to '
                        . ' be copied "%s" is '
                        . ' either missing or '
                        . ' is not readable',
                    $applied_image
                    ),
                E_USER_WARNING
                );
            return false;
            }
        
        $ct = $this->prepare($ci);
        if (!$this->__copy($tmp, $ct, $x, $y)) {
            trigger_error(
                'Failed to copy the image',
                E_USER_WARNING
                );
            return false;
            }
        
        $this->__destroy_source($ct);
        $this->__destroy_target($ct);
        return true;
        }
    /**
    * Crop the image 
    *
    * @param Asido_TMP &$tmp
    * @param integer $x
    * @param integer $y
    * @param integer $width
    * @param integer $height
    * @return boolean
    * @access public
    */
    function crop(&$tmp, $x, $y, $width, $height) {
        return $this->__crop($tmp, $x, $y, $width, $height);
        }
    /**
    * Vertically mirror (flip) the image
    * 
    * @param Asido_TMP &$tmp
    * @return boolean
    * @access public
    */
    function flip(&$tmp) {
        return $this->__flip(&$tmp);
        }
    /**
    * Horizontally mirror (flop) the image
    * 
    * @param Asido_TMP &$tmp
    * @return boolean
    * @access public
    */
    function flop(&$tmp) {
        return $this->__flop(&$tmp);
        }
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    /**
    * Prepare an image for processing it
    *
    * @param Asido_Image &$image
    * @return boolean
    * @access public
    */
    function prepare(&$image) {
        // create new temporary object
        //
        $tmp = new Asido_TMP;
        $tmp->source_filename = $image->source();
        $tmp->target_filename = $image->target();
        // failed opening ?
        //
        if (!$this->__open($tmp)) {
            trigger_error(
                'Unable to open source image',
                E_USER_WARNING
                );
            return false;
            }
        
        return $tmp;
        }
    /**
    * Save an image after being processed
    *
    * @param Asido_Image &$image
    * @return boolean
    * @access public
    */
    function save(&$image) {
        return $this->__write($image);
        }
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    /**
    * Copy one image to another
    *
    * @param Asido_TMP &$tmp_target
    * @param Asido_TMP &$tmp_source
    * @param integer $destination_x
    * @param integer $destination_y
    * @return boolean
    * @access protected
    * @abstract
    */
    function __copy(&$tmp_target, &$tmp_source, $destination_x, $destination_y) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Do the actual resize of an image
    *
    * @param Asido_TMP &$tmp
    * @param integer $width
    * @param integer $height
    * @return boolean
    * @access protected
    * @abstract
    */
    function __resize(&$tmp, $width, $height) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Make the image greyscale
    *
    * @param Asido_TMP &$tmp
    * @return boolean
    * @access protected
    * @abstract
    */
    function __grayscale(&$tmp) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Rotate the image clockwise
    *
    * @param Asido_TMP &$tmp
    * @param float $angle
    * @param Asido_Color $color
    * @return boolean
    * @access protected
    * @abstract
    */
    function __rotate(&$tmp, $angle, $color) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Get canvas
    *
    * @param integer $width
    * @param integer $height
    * @param Asido_Color $color
    * @return Asido_TMP
    * @access protected
    * @abstract
    */
    function __canvas($width, $height, $color) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Crop the image 
    *
    * @param Asido_TMP &$tmp
    * @param integer $x
    * @param integer $y
    * @param integer $width
    * @param integer $height
    * @return boolean
    * @access protected
    * @abstract
    */
    function __crop(&$tmp, $x, $y, $width, $height) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Vertically mirror (flip) the image
    * 
    * @param Asido_TMP &$tmp
    * @return boolean
    * @access protected
    * @abstract
    */
    function __flip(&$tmp) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Horizontally mirror (flop) the image
    * 
    * @param Asido_Image &$image
    * @return boolean
    * @access protected
    * @abstract
    */
    function __flop(&$tmp) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    /**
    * Get supported mime-types
    *
    * @param mixed $mode
    * @return array
    * @access public
    */    
    function get_supported_types($mode) {
        
        switch ($mode) {
            
            case 'ASIDO_SUPPORT_READ':
                return array_unique(
                    array_values($this->__mime['read'])
                    );
                break;
                
            case 'ASIDO_SUPPORT_WRITE':
                return array_unique(
                    array_values($this->__mime['write'])
                    );
                break;
                
            default :
            case 'ASIDO_SUPPORT_READ_WRITE' :
                return array_unique(
                    array_intersect(
                        array_values($this->__mime['write']),
                        array_values($this->__mime['read'])
                        )
                    );
                break;
            }
        }
    /**
    * Returnes whether an image format is supported or not
    *
    * @param string $mime_type
    * @param mixed $mode
    * @return boolean
    * @access public
    */
    function supported($mime_type, $mode) {
        return in_array(
            strToLower($mime_type),
            $this->get_supported_types($mode)
            );
        }
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    /**
    * Open the source and target image for processing it
    *
    * @param Asido_TMP &$tmp
    * @return boolean
    * @access protected
    * @abstract
    */
    function __open(&$tmp) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Write the image after being processed
    *
    * @param Asido_Image &$image
    * @return boolean
    * @access protected
    * @abstract
    */
    function __write(&$image) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    
    /**
    * Return a name for a temporary file
    * @return string
    * @access protected
    */
    function __tmpfile() {
        return tempnam(-1, null) . '.PNG';
        }
    
    /**
    * Generate a temporary object for the provided argument
    *
    * @param mixed &$handler
    * @param string $filename the filename will be automatically generated 
    *    on the fly, but if you want you can use the filename provided by 
    *    this argument
    * @return Asido_TMP
    * @access protected
    * @abstract
    */
    function __tmpimage(&$handler, $filename=null) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    /**
    * Destroy the source for the provided temporary object
    *
    * @param Asido_TMP &$tmp
    * @return boolean
    * @access protected
    * @abstract
    */    
    function __destroy_source(&$tmp) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    /**
    * Destroy the target for the provided temporary object
    *
    * @param Asido_TMP &$tmp
    * @return boolean
    * @access protected
    * @abstract
    */    
    function __destroy_target(&$tmp) {
        asido::trigger_abstract_error(
            __CLASS__,
            __FUNCTION__
            );
        }
    
    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    
//--end-of-class--    
}
/////////////////////////////////////////////////////////////////////////////
?>