File Manager

Current Directory: /home/astoriaah/www/old15/components/com_jce/editor/libraries/pro/classes/image
Viewing File: /home/astoriaah/www/old15/components/com_jce/editor/libraries/pro/classes/image/imagick.php
<?php /** * @copyright Copyright (c) 2009-2017 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('_JEXEC') or die; require_once dirname(__FILE__) . '/imagick/filter.php'; /** * Class to manipulate an image. */ class WFImageImagick { /** * @var resource The image resource handle * */ protected $handle; /** * @var string The source image path * */ protected $path = null; protected $type; /** * Class constructor. * * @param mixed $source Either a file path for a source image or a GD resource handler for an image * * @throws RuntimeException */ public function __construct($source = null) { // Verify that GD support for PHP is available. if (!extension_loaded('imagick')) { throw new RuntimeException('The Imagick extension for PHP is not available.'); } // If the source input is a resource, set it as the image handle. if (is_resource($source) && (get_resource_type($source) == 'imagick')) { $this->handle = &$source; } elseif (!empty($source) && is_string($source)) { // If the source input is not empty, assume it is a path and populate the image handle. $this->loadFile($source); } } /** * Method to apply a filter to the image by type. Two examples are: grayscale and sketchy. * * @param string $type The name of the image filter to apply * @param array $options An array of options for the filter * * @return WFImage * * @see WFImageFilter * * @throws LogicException * @throws RuntimeException */ public function filter($type, array $options = array()) { // Get the image filter instance. $filter = $this->getFilterInstance($type); // Execute the image filter. $filter->execute($options); } /** * Method to get the height of the image in pixels. * * @return int * * @throws LogicException */ public function getHeight() { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } return $this->handle->getImageHeight(); } /** * Method to get the width of the image in pixels. * * @return int * * @throws LogicException */ public function getWidth() { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } return $this->handle->getImageWidth(); } /** * Method to return the path. * * @return string * */ public function getPath() { return $this->path; } /** * Method to determine whether or not an image has been loaded into the object. * * @return bool * * @since 11.3 */ public function isLoaded() { // Make sure the resource handle is valid. if (!is_object($this->handle) || ($this->handle instanceof Imagick === false)) { return false; } return true; } /** * Method to load a file into the JImage object as the resource. * * @param string $path The filesystem path to load as an image * * @throws InvalidArgumentException * @throws RuntimeException */ public function loadFile($path) { // Make sure the file exists. if (!file_exists($path)) { throw new InvalidArgumentException('The image file does not exist.'); } $this->handle = new Imagick($path); // Set the filesystem path to the source image. $this->path = $path; // set type $this->setType(exif_imagetype($path)); } /** * Method to load a file into the JImage object as the resource. * * @param string $path The filesystem path to load as an image * * @throws InvalidArgumentException * @throws RuntimeException */ public function loadString($string) { $this->handle = new Imagick(); if ($this->isLoaded()) { $this->handle->readImageBlob($string); } else { $this->destroy(); throw new RuntimeException('Attempting to load an image of unsupported type.'); } } private function watermarkText($options) { if (is_file($options->font_style)) { $watermark = new ImagickDraw(); $watermark->setFontSize((int) $options->font_size); $options->font_color = '#' . preg_replace('#[^a-z0-9]+#i', '', $options->font_color); if ($options->opacity > 1) { $options->opacity = $options->opacity / 100; } switch ($options->position) { default: case 'center': $watermark->setGravity(Imagick::GRAVITY_CENTER); break; case 'top-left': $watermark->setGravity(Imagick::GRAVITY_NORTHEAST); break; case 'top-right': $watermark->setGravity(Imagick::GRAVITY_NORTHEAST); break; case 'center-left': $watermark->setGravity(Imagick::GRAVITY_WEST); break; case 'center-right': $watermark->setGravity(Imagick::GRAVITY_EAST); break; case 'top-center': $watermark->setGravity(Imagick::GRAVITY_NORTH); break; case 'bottom-center': $watermark->setGravity(Imagick::GRAVITY_SOUTH); break; case 'bottom-left': $watermark->setGravity(Imagick::GRAVITY_SOUTHWEST); break; case 'bottom-right': $watermark->setGravity(Imagick::GRAVITY_SOUTHEAST); break; } $watermark->setFillColor($options->font_color); $watermark->setFillOpacity((float) $options->opacity); $watermark->setFont($options->font_style); $this->handle->annotateImage($watermark, (int) $options->margin, (int) $options->margin, 0, $options->text); } } public function watermark($options) { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } if ($options->opacity > 1) { $options->opacity = $options->opacity / 100; } if ($options->type == 'text' && isset($options->text)) { $this->watermarkText($options); } elseif (isset($options->image)) { $watermark = new Imagick($options->image); $width = $this->getWidth(); $height = $this->getHeight(); $mw = $watermark->getImageWidth(); $mh = $watermark->getImageHeight(); switch ($options->position) { default: case 'center': $x = floor(($width - $mw) / 2); $y = floor(($height - $mh) / 2); break; case 'top-left': $x = $options->margin; $y = floor($mh / 2) + $options->margin; break; case 'top-right': $x = $width - $mw - $options->margin; $y = floor($mh / 2) + $options->margin; break; case 'center-left': $x = 0 + $options->margin; $y = floor(($height - $mh) / 2); break; case 'center-right': $x = $width - $mw - $options->margin; $y = floor(($height - $mh) / 2); break; case 'top-center': $x = floor(($width - $mw) / 2); $y = floor($mh / 2) + $options->margin; break; case 'bottom-center': $x = floor(($width - $mw) / 2); $y = $height - $mh - $options->margin; break; case 'bottom-left': $x = 0 + $options->margin; $y = $height - $mh - $options->margin; break; case 'bottom-right': $x = $width - $mw - $options->margin; $y = $height - $mh - $options->margin; break; } if ($watermark->getImageFormat() == 'PNG') { $watermark->evaluateImage(Imagick::EVALUATE_MULTIPLY, (float) $options->opacity, Imagick::CHANNEL_ALPHA); } else { $watermark->setImageOpacity((float) $options->opacity); } $this->handle->compositeImage($watermark, imagick::COMPOSITE_OVER, $x, $y); } return $this; } /** * Set image resolution. * * @param type $resolution * * @return \WFImageImagick */ public function resample($resolution) { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } return $this->handle->setImageResolution((float) $resolution, (float) $resolution); } /** * 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 WFImage * * @throws LogicException */ public function resize($width, $height, $createNew = false) { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } // If we are resizing to a new image, create a new Imagick object. if ($createNew) { $this->handle = $this->handle->clone(); } return $this->handle->resizeImage($width, $height, imagick::FILTER_LANCZOS, 1); } /** * 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 WFImage * * @throws LogicException */ public function crop($width, $height, $left, $top, $createNew = false) { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } // If we are cropping to a new image, create a new JImage object. if ($createNew) { $this->handle = $this->handle->clone(); // @codeCoverageIgnoreEnd } // Create the new truecolor image handle. $this->handle->cropImage($width, $height, $left, $top); } /** * 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 WFImage * * @throws LogicException */ public function rotate($angle, $createNew = false) { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } if ($createNew) { $this->handle = $this->handle->clone(); } $this->handle->rotateImage(new ImagickPixel(), $angle); } /** * 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 WFImage * * @throws LogicException */ public function flip($mode, $createNew = false) { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } if ($createNew) { $this->handle = $this->handle->clone(); } switch ((int) $mode) { case IMAGE_FLIP_HORIZONTAL: $this->handle->flopImage(); break; case IMAGE_FLIP_VERTICAL: $this->handle->flipImage(); break; case IMAGE_FLIP_BOTH: $this->handle->flipImage(); $this->handle->flopImage(); break; } } private function removeExif() { $rotate = 0; $orientation = $this->handle->getImageOrientation(); // Fix Orientation switch ($orientation) { case imagick::ORIENTATION_BOTTOMRIGHT: $rotate = 180; break; case imagick::ORIENTATION_RIGHTTOP: $rotate = 90; break; case imagick::ORIENTATION_LEFTBOTTOM: $rotate = 270; break; } if ($rotate) { $this->handle->rotateImage(new ImagickPixel(), $rotate); } // get iptcc //$iptcc = $img->getImageProfile('iptcc'); $this->handle->stripImage(); // add back iptcc /*if (!empty($iptcc)) { $img->profileImage($iptcc); }*/ } /** * 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 * * @throws LogicException */ public function toFile($path, $type = 'jpeg', array $options = array()) { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded.'); } // resample if (!empty($options['resampleImage'])) { $this->handle->setImageResolution(72, 72); } // set format $this->handle->setImageFormat($type); // remove exif data if (!empty($options['removeExif'])) { $this->removeExif(); } switch ($type) { case 'png': $this->handle->setImageCompression(imagick::COMPRESSION_ZIP); $quality = (array_key_exists('quality', $options)) ? $options['quality'] : 0; // get as value from 0-9 if ($quality) { // png compression is a value from 0 (none) to 9 (max) $quality = 100 - $quality; // convert to value between 0 - 9 $quality = min(floor($quality / 10), 9); } $this->handle->setImageCompressionQuality($quality); break; case 'jpeg': case 'jpg': $this->handle->setImageCompression(Imagick::COMPRESSION_JPEG); $this->handle->setImageCompressionQuality((array_key_exists('quality', $options)) ? $options['quality'] : 100); } $result = $this->handle->writeImage($path); $this->destroy(); return $result; } /** * 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 * * @throws LogicException */ public function toString($type = 'jpeg', array $options = array()) { // Make sure the resource handle is valid. if (!$this->isLoaded()) { throw new LogicException('No valid image was loaded'); } // resample if (!empty($options['resampleImage'])) { $this->handle->setImageResolution(72, 72); } // set format $this->handle->setImageFormat($type); // remove exif data if (!empty($options['removeExif'])) { $this->removeExif(); } switch ($type) { case IMAGETYPE_PNG: $this->handle->setImageCompression(imagick::COMPRESSION_ZIP); $quality = (array_key_exists('quality', $options)) ? $options['quality'] : 0; // get as value from 0-9 if ($quality) { // png compression is a value from 0 (none) to 9 (max) $quality = 100 - $quality; // convert to value between 0 - 9 $quality = min(floor($quality / 10), 9); } $this->handle->setImageCompressionQuality($quality); break; case IMAGETYPE_JPEG: default: $this->handle->setImageCompression(Imagick::COMPRESSION_JPEG); $this->handle->setImageCompressionQuality((array_key_exists('quality', $options)) ? $options['quality'] : 100); } echo $this->handle->getImageBlob(); $this->destroy(); } /** * Method to get an image filter instance of a specified type. * * @param string $type The image filter type to get * * @return WFImageImagickFilter * * @throws RuntimeException */ protected function getFilterInstance($type) { // Sanitize the filter type. $type = strtolower(preg_replace('#[^A-Z0-9_]#i', '', $type)); // load the filter require_once dirname(__FILE__) . '/imagick/filters/' . $type . '.php'; // Verify that the filter type exists. $className = 'WFImageImagickFilter' . ucfirst($type); if (!class_exists($className)) { throw new RuntimeException('The ' . ucfirst($type) . ' image filter is not available.'); } // Instantiate the filter object. $instance = new $className($this->handle); // Verify that the filter type is valid. if (!($instance instanceof WFImageImagickFilter)) { throw new RuntimeException('The ' . ucfirst($type) . ' image filter is not valid.'); } return $instance; } public function getType() { return $this->type; } public function setType($type) { $this->type = $type; } public function destroy() { $this->handle->clear(); $this->handle->destroy(); } }