/obsolete/web_client/system/libraries/Image.php
PHP | 503 lines | 427 code | 25 blank | 51 comment | 12 complexity | 8faecadf24f1f673bec729e11dcc4eda MD5 | raw file
- <?php defined('SYSPATH') OR die('No direct access allowed.');
- /**
- * Manipulate images using standard methods such as resize, crop, rotate, etc.
- * This class must be re-initialized for every image you wish to manipulate.
- *
- * $Id: Image.php 4679 2009-11-10 01:45:52Z isaiah $
- *
- * @package Image
- * @author Kohana Team
- * @copyright (c) 2007-2009 Kohana Team
- * @license http://kohanaphp.com/license
- */
- class Image_Core {
- // Master Dimension
- const NONE = 1;
- const AUTO = 2;
- const HEIGHT = 3;
- const WIDTH = 4;
- // Flip Directions
- const HORIZONTAL = 5;
- const VERTICAL = 6;
- // Orientations
- const PORTRAIT = 7;
- const LANDSCAPE = 8;
- const SQUARE = 9;
- // Allowed image types
- public static $allowed_types = array
- (
- IMAGETYPE_GIF => 'gif',
- IMAGETYPE_JPEG => 'jpg',
- IMAGETYPE_PNG => 'png',
- IMAGETYPE_TIFF_II => 'tiff',
- IMAGETYPE_TIFF_MM => 'tiff',
- );
- // Driver instance
- protected $driver;
- // Driver actions
- protected $actions = array();
- // Reference to the current image filename
- protected $image = '';
- /**
- * Creates a new Image instance and returns it.
- *
- * @param string filename of image
- * @param array non-default configurations
- * @return object
- */
- public static function factory($image, $config = NULL)
- {
- return new Image($image, $config);
- }
- /**
- * Creates a new image editor instance.
- *
- * @throws Kohana_Exception
- * @param string filename of image
- * @param array non-default configurations
- * @return void
- */
- public function __construct($image, $config = NULL)
- {
- static $check;
- // Make the check exactly once
- ($check === NULL) and $check = function_exists('getimagesize');
- if ($check === FALSE)
- throw new Kohana_Exception('The Image library requires the getimagesize() PHP function, which is not available in your installation.');
- // Check to make sure the image exists
- if ( ! is_file($image))
- throw new Kohana_Exception('The specified image, :image:, was not found. Please verify that images exist by using file_exists() before manipulating them.', array(':image:' => $image));
- // Disable error reporting, to prevent PHP warnings
- $ER = error_reporting(0);
- // Fetch the image size and mime type
- $image_info = getimagesize($image);
- // Turn on error reporting again
- error_reporting($ER);
- // Make sure that the image is readable and valid
- if ( ! is_array($image_info) OR count($image_info) < 3)
- throw new Kohana_Exception('The file specified, :file:, is not readable or is not an image', array(':file:' => $image));
- // Check to make sure the image type is allowed
- if ( ! isset(Image::$allowed_types[$image_info[2]]))
- throw new Kohana_Exception('The specified image, :type:, is not an allowed image type.', array(':type:' => $image));
- // Image has been validated, load it
- $this->image = array
- (
- 'file' => str_replace('\\', '/', realpath($image)),
- 'width' => $image_info[0],
- 'height' => $image_info[1],
- 'type' => $image_info[2],
- 'ext' => Image::$allowed_types[$image_info[2]],
- 'mime' => $image_info['mime']
- );
- $this->determine_orientation();
- // Load configuration
- $this->config = (array) $config + Kohana::config('image');
- // Set driver class name
- $driver = 'Image_'.ucfirst($this->config['driver']).'_Driver';
- // Load the driver
- if ( ! Kohana::auto_load($driver))
- throw new Kohana_Exception('The :driver: driver for the :library: library could not be found',
- array(':driver:' => $this->config['driver'], ':library:' => get_class($this)));
- // Initialize the driver
- $this->driver = new $driver($this->config['params']);
- // Validate the driver
- if ( ! ($this->driver instanceof Image_Driver))
- throw new Kohana_Exception('The :driver: driver for the :library: library must implement the :interface: interface',
- array(':driver:' => $this->config['driver'], ':library:' => get_class($this), ':interface:' => 'Image_Driver'));
- }
- /**
- * Works out the correct orientation for the image
- *
- * @return void
- */
- protected function determine_orientation()
- {
- switch (TRUE)
- {
- case $this->image['height'] > $this->image['width']:
- $orientation = Image::PORTRAIT;
- break;
- case $this->image['height'] < $this->image['width']:
- $orientation = Image::LANDSCAPE;
- break;
- default:
- $orientation = Image::SQUARE;
- }
- $this->image['orientation'] = $orientation;
- }
- /**
- * Handles retrieval of pre-save image properties
- *
- * @param string property name
- * @return mixed
- */
- public function __get($property)
- {
- if (isset($this->image[$property]))
- {
- return $this->image[$property];
- }
- else
- {
- throw new Kohana_Exception('The :property: property does not exist in the :class: class.',
- array(':property:' => $property, ':class:' => get_class($this)));
- }
- }
- /**
- * Resize an image to a specific width and height. By default, Kohana will
- * maintain the aspect ratio using the width as the master dimension. If you
- * wish to use height as master dim, set $image->master_dim = Image::HEIGHT
- * This method is chainable.
- *
- * @throws Kohana_Exception
- * @param integer width
- * @param integer height
- * @param integer one of: Image::NONE, Image::AUTO, Image::WIDTH, Image::HEIGHT
- * @return object
- */
- public function resize($width, $height, $master = NULL)
- {
- if ( ! $this->valid_size('width', $width))
- throw new Kohana_Exception('The width you specified, :width:, is not valid.', array(':width:' => $width));
- if ( ! $this->valid_size('height', $height))
- throw new Kohana_Exception('The height you specified, :height:, is not valid.', array(':height:' => $height));
- if (empty($width) AND empty($height))
- throw new Kohana_Exception('The dimensions specified for :function: are not valid.', array(':function:' => __FUNCTION__));
- if ($master === NULL)
- {
- // Maintain the aspect ratio by default
- $master = Image::AUTO;
- }
- elseif ( ! $this->valid_size('master', $master))
- throw new Kohana_Exception('The master dimension specified is not valid.');
- $this->actions['resize'] = array
- (
- 'width' => $width,
- 'height' => $height,
- 'master' => $master,
- );
- $this->determine_orientation();
- return $this;
- }
- /**
- * Crop an image to a specific width and height. You may also set the top
- * and left offset.
- * This method is chainable.
- *
- * @throws Kohana_Exception
- * @param integer width
- * @param integer height
- * @param integer top offset, pixel value or one of: top, center, bottom
- * @param integer left offset, pixel value or one of: left, center, right
- * @return object
- */
- public function crop($width, $height, $top = 'center', $left = 'center')
- {
- if ( ! $this->valid_size('width', $width))
- throw new Kohana_Exception('The width you specified, :width:, is not valid.', array(':width:' => $width));
- if ( ! $this->valid_size('height', $height))
- throw new Kohana_Exception('The height you specified, :height:, is not valid.', array(':height:' => $height));
- if ( ! $this->valid_size('top', $top))
- throw new Kohana_Exception('The top offset you specified, :top:, is not valid.', array(':top:' => $top));
- if ( ! $this->valid_size('left', $left))
- throw new Kohana_Exception('The left offset you specified, :left:, is not valid.', array(':left:' => $left));
- if (empty($width) AND empty($height))
- throw new Kohana_Exception('The dimensions specified for :function: are not valid.', array(':function:' => __FUNCTION__));
- $this->actions['crop'] = array
- (
- 'width' => $width,
- 'height' => $height,
- 'top' => $top,
- 'left' => $left,
- );
- $this->determine_orientation();
- return $this;
- }
- /**
- * Allows rotation of an image by 180 degrees clockwise or counter clockwise.
- *
- * @param integer degrees
- * @return object
- */
- public function rotate($degrees)
- {
- $degrees = (int) $degrees;
- if ($degrees > 180)
- {
- do
- {
- // Keep subtracting full circles until the degrees have normalized
- $degrees -= 360;
- }
- while($degrees > 180);
- }
- if ($degrees < -180)
- {
- do
- {
- // Keep adding full circles until the degrees have normalized
- $degrees += 360;
- }
- while($degrees < -180);
- }
- $this->actions['rotate'] = $degrees;
- return $this;
- }
- /**
- * Overlay a second image on top of this one.
- *
- * @throws Kohana_Exception
- * @param string $overlay_file path to an image file
- * @param integer $x x offset for the overlay
- * @param integer $y y offset for the overlay
- * @param integer $transparency transparency percent
- */
- public function composite($overlay_file, $x, $y, $transparency)
- {
- $image_info = getimagesize($overlay_file);
- // Check to make sure the image type is allowed
- if ( ! isset(Image::$allowed_types[$image_info[2]]))
- throw new Kohana_Exception('The specified image, :type:, is not an allowed image type.', array(':type:' => $overlay_file));
- $this->actions['composite'] = array
- (
- 'overlay_file' => $overlay_file,
- 'mime' => $image_info['mime'],
- 'x' => $x,
- 'y' => $y,
- 'transparency' => $transparency
- );
- return $this;
- }
- /**
- * Flip an image horizontally or vertically.
- *
- * @throws Kohana_Exception
- * @param integer direction
- * @return object
- */
- public function flip($direction)
- {
- if ($direction !== Image::HORIZONTAL AND $direction !== Image::VERTICAL)
- throw new Kohana_Exception('The flip direction specified is not valid.');
- $this->actions['flip'] = $direction;
- return $this;
- }
- /**
- * Change the quality of an image.
- *
- * @param integer quality as a percentage
- * @return object
- */
- public function quality($amount)
- {
- $this->actions['quality'] = max(1, min($amount, 100));
- return $this;
- }
- /**
- * Sharpen an image.
- *
- * @param integer amount to sharpen, usually ~20 is ideal
- * @return object
- */
- public function sharpen($amount)
- {
- $this->actions['sharpen'] = max(1, min($amount, 100));
- return $this;
- }
- /**
- * Save the image to a new image or overwrite this image.
- *
- * @throws Kohana_Exception
- * @param string new image filename
- * @param integer permissions for new image
- * @param boolean keep or discard image process actions
- * @return object
- */
- public function save($new_image = FALSE, $chmod = 0644, $keep_actions = FALSE, $background = NULL)
- {
- // If no new image is defined, use the current image
- empty($new_image) and $new_image = $this->image['file'];
- // Separate the directory and filename
- $dir = pathinfo($new_image, PATHINFO_DIRNAME);
- $file = pathinfo($new_image, PATHINFO_BASENAME);
- // Normalize the path
- $dir = str_replace('\\', '/', realpath($dir)).'/';
- if ( ! is_writable($dir))
- throw new Kohana_Exception('The specified directory, :dir:, is not writable.', array(':dir:' => $dir));
- if ($status = $this->driver->process($this->image, $this->actions, $dir, $file, FALSE, $background))
- {
- if ($chmod !== FALSE)
- {
- // Set permissions
- chmod($new_image, $chmod);
- }
- }
- if ($keep_actions !== TRUE)
- {
- // Reset actions. Subsequent save() or render() will not apply previous actions.
- $this->actions = array();
- }
- return $status;
- }
- /**
- * Output the image to the browser.
- *
- * @param boolean keep or discard image process actions
- * @return object
- */
- public function render($keep_actions = FALSE, $background = NULL)
- {
- $new_image = $this->image['file'];
- // Separate the directory and filename
- $dir = pathinfo($new_image, PATHINFO_DIRNAME);
- $file = pathinfo($new_image, PATHINFO_BASENAME);
- // Normalize the path
- $dir = str_replace('\\', '/', realpath($dir)).'/';
- // Process the image with the driver
- $status = $this->driver->process($this->image, $this->actions, $dir, $file, TRUE, $background);
- if ($keep_actions !== TRUE)
- {
- // Reset actions. Subsequent save() or render() will not apply previous actions.
- $this->actions = array();
- }
- return $status;
- }
- /**
- * Sanitize a given value type.
- *
- * @param string type of property
- * @param mixed property value
- * @return boolean
- */
- protected function valid_size($type, & $value)
- {
- if (is_null($value))
- return TRUE;
- if ( ! is_scalar($value))
- return FALSE;
- switch ($type)
- {
- case 'width':
- case 'height':
- if (is_string($value) AND ! ctype_digit($value))
- {
- // Only numbers and percent signs
- if ( ! preg_match('/^[0-9]++%$/D', $value))
- return FALSE;
- }
- else
- {
- $value = (int) $value;
- }
- break;
- case 'top':
- if (is_string($value) AND ! ctype_digit($value))
- {
- if ( ! in_array($value, array('top', 'bottom', 'center')))
- return FALSE;
- }
- else
- {
- $value = (int) $value;
- }
- break;
- case 'left':
- if (is_string($value) AND ! ctype_digit($value))
- {
- if ( ! in_array($value, array('left', 'right', 'center')))
- return FALSE;
- }
- else
- {
- $value = (int) $value;
- }
- break;
- case 'master':
- if ($value !== Image::NONE AND
- $value !== Image::AUTO AND
- $value !== Image::WIDTH AND
- $value !== Image::HEIGHT)
- return FALSE;
- break;
- }
- return TRUE;
- }
- } // End Image