File Manager

Current Directory: /home/astoriaah/www/components/com_jce/editor/libraries/pro/classes/image
Viewing File: /home/astoriaah/www/components/com_jce/editor/libraries/pro/classes/image/image.php
<?php /** * @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved * @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * JCE is free software. This version may have been modified pursuant * to the GNU General Public License, and as distributed it includes or * is derivative of works licensed under the GNU General Public License or * other free or open source software licenses. * * Based on JImage library from Joomla.Platform 11.3 */ defined('JPATH_PLATFORM') or die; define('IMAGE_FLIP_HORIZONTAL', 1); define('IMAGE_FLIP_VERTICAL', 2); define('IMAGE_FLIP_BOTH', 3); // http://www.php.net/manual/en/function.exif-imagetype.php#80383 if (!function_exists('exif_imagetype')) { function exif_imagetype($filename) { if ((list($width, $height, $type, $attr) = getimagesize($filename)) !== false) { return $type; } return false; } } /** * Class to manipulate an image. */ class WFImage { /** * @const integer * * @since 2.1 */ const SCALE_FILL = 1; /** * @const integer * * @since 2.1 */ const SCALE_INSIDE = 2; /** * @const integer * * @since 2.1 */ const SCALE_OUTSIDE = 3; /** * @var string The source image path * * @since 2.1 */ protected $path = null; /** * @var array An array of image resource backups * */ protected $backups = array(); /** * @var string The image library object * * @since 2.1 */ protected static $driver = null; /** * @var bool Use IMagick if available * * @since 2.1 */ protected static $preferImagick = true; /** * @var bool REmove EXIF data from JPEG and PNG images * * @since 2.1 */ protected static $removeExif = false; /** * @var int Resample the image to 72dpi * * @since 2.1 */ protected static $resampleImage = true; /** * Class constructor. * * @param mixed $source A file path for a source image * * @since 2.1 */ public function __construct($source = null, $options = array()) { if (isset($options['preferImagick'])) { self::$preferImagick = (bool) $options['preferImagick']; } if (isset($options['removeExif'])) { self::$removeExif = (bool) $options['removeExif']; } if (isset($options['resampleImage'])) { self::$resampleImage = (bool) $options['resampleImage']; } // create image library instance self::getDriver(); if ($source && is_file($source)) { $this->loadFile($source); } } /** * Get the available Graphics Library. * * @return object Graphics Library Instance * * @throws RuntimeException */ public static function getDriver() { if (!isset(self::$driver)) { if (extension_loaded('imagick')) { $driver = 'Imagick'; } elseif (extension_loaded('gd')) { $driver = 'GD'; } else { throw new RuntimeException('No supported Image library available.'); } if ($driver == 'Imagick' && self::$preferImagick === false) { $driver = 'GD'; } require_once __DIR__ . '/' . strtolower($driver) . '.php'; $class = 'WFImage' . $driver; if (class_exists($class)) { self::$driver = new $class(); } else { throw new RuntimeException('Class ' . $class . ' not found'); } } return self::$driver; } /** * Method to return a properties object for an image given a filesystem path. The * result object has values for image width, height, type, attributes, mime type, bits, * and channels. * * @param string $path The filesystem path to the image for which to get properties * * @return object * * @since 2.1 * * @throws InvalidArgumentException * @throws RuntimeException */ public static function getImageFileProperties($path) { // Make sure the file exists. if (!file_exists($path)) { throw new InvalidArgumentException('The image file does not exist.'); } // Get the image file information. $info = getimagesize($path); if (!$info) { throw new RuntimeException('Unable to get properties for the image.'); } // Build the response object. $properties = (object) array( 'width' => $info[0], 'height' => $info[1], 'type' => $info[2], 'attributes' => $info[3], 'bits' => isset($info['bits']) ? $info['bits'] : null, 'channels' => isset($info['channels']) ? $info['channels'] : null, 'mime' => $info['mime'], ); return $properties; } /** * Method to get the height of the image in pixels. * * @return int * * @since 2.1 */ public function getHeight() { return self::getDriver()->getHeight(); } /** * Method to get the width of the image in pixels. * * @return int * * @since 2.1 */ public function getWidth() { return self::getDriver()->getWidth(); } /** * Method to load a file into the Graphics Libary object as the resource. * * @param string $path The filesystem path to load as an image * * @since 2.1 */ public function loadFile($path) { self::getDriver()->loadFile($path); } /** * Method to load a string into the Graphics Library object as the resource. * * @param string $string The image string * * @since 2.1 * * @throws InvalidArgumentException */ public function loadString($string) { if (strlen($string) < 128) { throw new InvalidArgumentException('String does not contain image data.'); } self::getDriver()->loadString($string); } protected function getBox($dw, $dh) { $sw = (int) $this->getWidth(); $sh = (int) $this->getHeight(); $sx = 0; $sy = 0; $w = $dw; $h = $dh; if ($w / $h > $sw / $w) { $h = floor($h * ($sw / $w)); $w = $sw; if ($h > $sh) { $w = floor($w * ($sh / $h)); $h = $sh; } } else { $w = floor($w * ($sh / $h)); $h = $sh; if ($w > $sw) { $h = floor($h * ($sw / $w)); $w = $sw; } } if ($w < $sw) { $sx = floor(($sw - $w) / 2); } else { $sx = 0; } if ($h < $sh) { $sy = floor(($sh - $h) / 2); } else { $sy = 0; } return array('sx' => $sx, 'sy' => $sy, 'sw' => $w, 'sh' => $h); } public function resample($resolution = 72) { return self::getDriver()->resample($resolution); } public function watermark($options = array()) { if (empty($options)) { throw new InvalidArgumentException('No watermark options set'); } if (array_key_exists('text', $options) === false || array_key_exists('image', $options) === false) { //throw new InvalidArgumentException('No watermark text or image'); } $options = (object) array( 'type' => $options['type'], 'text' => $options['text'], 'image' => $options['image'], 'font_style' => isset($options['font_style']) ? $options['font_style'] : 'sans-serif', 'font_size' => isset($options['font_size']) ? $options['font_size'] : '36', 'font_color' => isset($options['font_color']) ? $options['font_color'] : '#FFFFFF', 'opacity' => isset($options['opacity']) ? $options['opacity'] : 50, 'position' => isset($options['position']) ? $options['position'] : 'center', 'margin' => isset($options['margin']) ? (int) $options['margin'] : 10, 'angle' => isset($options['angle']) ? (int) $options['angle'] : 0, ); return self::getDriver()->watermark($options); } /** * Method to resize the current image. * * @param mixed $width The width of the resized image in pixels or a percentage * @param mixed $height The height of the resized image in pixels or a percentage * @param bool $createNew If true the current image will be cloned, resized and returned; else * the current image will be resized and returned * @param int $scaleMethod Which method to use for scaling * * @return bool * * @since 2.1 */ public function resize($width, $height, $createNew = false, $scaleMethod = self::SCALE_INSIDE) { // Sanitize width. $width = $this->sanitizeWidth($width, $height); // Sanitize height. $height = $this->sanitizeHeight($height, $width); // Prepare the dimensions for the resize operation. $dimensions = $this->prepareDimensions($width, $height, $scaleMethod); return self::getDriver()->resize($dimensions->width, $dimensions->height, $createNew); } public function fit($width, $height, $createNew = false, $scaleMethod = self::SCALE_INSIDE) { // Sanitize width. $width = $this->sanitizeWidth($width, $height); // Sanitize height. $height = $this->sanitizeHeight($height, $width); $box = $this->getBox($width, $height); $this->crop($box['sw'], $box['sh'], $box['sx'], $box['sy']); return $this->resize($width, $height, $createNew); } /** * Method to crop the current image. * * @param mixed $width The width of the image section to crop in pixels or a percentage * @param mixed $height The height of the image section to crop in pixels or a percentage * @param int $left The number of pixels from the left to start cropping * @param int $top The number of pixels from the top to start cropping * @param bool $createNew If true the current image will be cloned, cropped and returned; else * the current image will be cropped and returned * * @return bool * * @since 2.1 */ public function crop($width, $height, $left, $top, $createNew = false) { // Sanitize width. $width = $this->sanitizeWidth($width, $height); // Sanitize height. $height = $this->sanitizeHeight($height, $width); // Sanitize left. $left = $this->sanitizeOffset($left); // Sanitize top. $top = $this->sanitizeOffset($top); return self::getDriver()->crop($width, $height, $left, $top, $createNew); } /** * Method to rotate the current image. * * @param mixed $angle The angle of rotation for the image * @param int $background The background color to use when areas are added due to rotation * @param bool $createNew If true the current image will be cloned, rotated and returned; else * the current image will be rotated and returned * * @return bool * * @since 2.1 */ public function rotate($angle, $background = -1, $createNew = false) { // Sanitize input $angle = floatval($angle); return self::getDriver()->rotate($angle, $background, $createNew); } /** * Method to rotate the current image. * * @param mixed $angle The angle of rotation for the image * @param int $background The background color to use when areas are added due to rotation * @param bool $createNew If true the current image will be cloned, rotated and returned; else * the current image will be rotated and returned * * @return bool * * @since 2.1 */ public function flip($direction, $createNew = false) { if (empty($direction)) { throw new InvalidArgumentException('No flip direction set'); } switch ($direction) { case 'horizontal': $direction = IMAGE_FLIP_HORIZONTAL; break; case 'vertical': $direction = IMAGE_FLIP_VERTICAL; break; case 'both': $direction = IMAGE_FLIP_BOTH; break; } return self::getDriver()->flip($direction, $createNew); } public function orientate() { return self::getDriver()->orientate(); } public function removeExif() { return self::getDriver()->removeExif(); } /** * Method to write the current image out to a file. * * @param string $path The filesystem path to save the image * @param int $type The image type to save the file as * @param array $options The image type options to use in saving the file * * @return bool * * @since 2.1 */ public function toFile($path, $type = 'jpeg', array $options = array()) { // remove exif data before saving? $options['removeExif'] = self::$removeExif; // resample on saving? $options['resampleImage'] = self::$resampleImage; return self::getDriver()->toFile($path, $type, $options); } /** * Method to write the current image out to a string. * * @param int $type The image type to save the file as * @param array $options The image type options to use in saving the file * * @return bool * * @since 2.1 */ public function toString($type = 'jpeg', array $options = array()) { ob_start(); // remove exif data before saving? $options['removeExif'] = self::$removeExif; // resample on saving? $options['resampleImage'] = self::$resampleImage; self::getDriver()->toString($type, $options); return ob_get_clean(); } /** * Method to get the new dimensions for a resized image. * * @param int $width The width of the resized image in pixels * @param int $height The height of the resized image in pixels * @param int $scaleMethod The method to use for scaling * * @return object * * @since 11.3 * * @throws InvalidArgumentException */ protected function prepareDimensions($width, $height, $scaleMethod) { // Instantiate variables. $dimensions = new stdClass(); switch ($scaleMethod) { case self::SCALE_FILL: $dimensions->width = intval(round($width)); $dimensions->height = intval(round($height)); break; case self::SCALE_INSIDE: case self::SCALE_OUTSIDE: $rx = $this->getWidth() / $width; $ry = $this->getHeight() / $height; if ($scaleMethod == self::SCALE_INSIDE) { $ratio = ($rx > $ry) ? $rx : $ry; } else { $ratio = ($rx < $ry) ? $rx : $ry; } $dimensions->width = intval(round($this->getWidth() / $ratio)); $dimensions->height = intval(round($this->getHeight() / $ratio)); break; default: throw new InvalidArgumentException('Invalid scale method.'); break; } return $dimensions; } /** * Method to sanitize a height value. * * @param mixed $height The input height value to sanitize * @param mixed $width The input width value for reference * * @return int * * @since 11.3 */ protected function sanitizeHeight($height, $width) { // If no height was given we will assume it is a square and use the width. $height = ($height === null) ? $width : $height; // If we were given a percentage, calculate the integer value. if (preg_match('/^[0-9]+(\.[0-9]+)?\%$/', $height)) { $height = intval(round($this->getHeight() * floatval(str_replace('%', '', $height)) / 100)); } // Else do some rounding so we come out with a sane integer value. else { $height = intval(round(floatval($height))); } return $height; } /** * Method to sanitize an offset value like left or top. * * @param mixed $offset An offset value * * @return int * * @since 11.3 */ protected function sanitizeOffset($offset) { return intval(round(floatval($offset))); } /** * Method to sanitize a width value. * * @param mixed $width The input width value to sanitize * @param mixed $height The input height value for reference * * @return int * * @since 11.3 */ protected function sanitizeWidth($width, $height) { // If no width was given we will assume it is a square and use the height. $width = ($width === null) ? $height : $width; // If we were given a percentage, calculate the integer value. if (preg_match('/^[0-9]+(\.[0-9]+)?\%$/', $width)) { $width = intval(round($this->getWidth() * floatval(str_replace('%', '', $width)) / 100)); } // Else do some rounding so we come out with a sane integer value. else { $width = intval(round(floatval($width))); } return $width; } public static function getImageType($string) { switch ($string) { case 'jpeg': case 'jpg': default: return IMAGETYPE_JPEG; break; case 'png': return IMAGETYPE_PNG; break; case 'tiff': return IMAGETYPE_TIFF_II; break; case 'gif': return IMAGETYPE_GIF; break; case 'webp': return IMAGETYPE_WEBP; break; } } public function destroy() { self::getDriver()->destroy(); } public function getType() { self::getDriver()->getType(); } public function setType($type) { // convert extension to image type constant $type = self::getImageType($type); // set type self::getDriver()->setType($type); } public function backup($name = null) { $name = is_null($name) ? 'default' : $name; $resource = self::getDriver()->backup(); $this->backups[$name] = $resource; return $resource; } public function restore($name = null) { $name = is_null($name) ? 'default' : $name; if (array_key_exists($name, $this->backups)) { $resource = $this->backups[$name]; if ($resource) { self::getDriver()->restore($resource); } } } }