| <?php |
| /** |
| * File containing the ezcImageConverter class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package ImageConversion |
| * @version //autogentag// |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| * @filesource |
| */ |
| |
| /** |
| * Class to manage conversion and filtering of image files. |
| * This class is highly recommended to be used with an external |
| * singleton pattern to have just 1 converter in place over the whole |
| * application. |
| * |
| * As back-ends 2 handler classes are available, of which at least 1 has to be |
| * configured during the instantiation of the ezcImageConverter. Both handlers |
| * utilize different image manipulation tools and are capable of different |
| * sets of filters: |
| * |
| * <ul> |
| * <li>ezcImageGdHandler |
| * <ul> |
| * <li>Uses PHP's GD extension for image manipulation.</li> |
| * <li>Implements the following filter interfaces |
| * <ul> |
| * <li>{@link ezcImageGeometryFilters}</li> |
| * <li>{@link ezcImageColorspaceFilters}</li> |
| * </ul> |
| * </li> |
| * </ul> |
| * </li> |
| * <li>ezcImageImagemagickHandler |
| * <ul> |
| * <li>Uses the external "convert" program, contained in ImageMagick</li> |
| * <li>Implements the following interfaces: |
| * <ul> |
| * <li>{@link ezcImageGeometryFilters}</li> |
| * <li>{@link ezcImageColorspaceFilters}</li> |
| * <li>{@link ezcImageEffectFilters}</li> |
| * </ul> |
| * </li> |
| * </ul> |
| * </li> |
| * </ul> |
| * |
| * A general example, how to use ezcImageConversion to convert images: |
| * <code> |
| * // Prepare settings for ezcImageConverter |
| * // Defines the handlers to utilize and auto conversions. |
| * $settings = new ezcImageConverterSettings( |
| * array( |
| * new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ), |
| * new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ), |
| * ), |
| * array( |
| * 'image/gif' => 'image/png', |
| * 'image/bmp' => 'image/jpeg', |
| * ) |
| * ); |
| * |
| * // Create the converter itself. |
| * $converter = new ezcImageConverter( $settings ); |
| * |
| * // Define a transformation |
| * $filters = array( |
| * new ezcImageFilter( |
| * 'scaleWidth', |
| * array( |
| * 'width' => 100, |
| * 'direction' => ezcImageGeometryFilters::SCALE_BOTH, |
| * ) |
| * ), |
| * new ezcImageFilter( |
| * 'colorspace', |
| * array( |
| * 'space' => ezcImageColorspaceFilters::COLORSPACE_GREY, |
| * ) |
| * ), |
| * ); |
| * |
| * // Which MIME types the conversion may output |
| * $mimeTypes = array( 'image/jpeg', 'image/png' ); |
| * |
| * // Create the transformation inside the manager |
| * $converter->createTransformation( 'thumbnail', $filters, $mimeTypes ); |
| * |
| * // Transform an image. |
| * $converter->transform( 'thumbnail', dirname(__FILE__).'/jpeg.jpg', dirname(__FILE__).'/jpeg_thumb.jpg' ); |
| * </code> |
| * |
| * It's recommended to create only a single ezcImageConverter instance in your |
| * application to avoid creating multiple instances of it's internal objects. |
| * You can implement a singleton pattern for this, which might look similar to |
| * the following example: |
| * <code> |
| * function getImageConverterInstance() |
| * { |
| * if ( !isset( $GLOBALS['_ezcImageConverterInstance'] ) ) |
| * { |
| * // Prepare settings for ezcImageConverter |
| * // Defines the handlers to utilize and auto conversions. |
| * $settings = new ezcImageConverterSettings( |
| * array( |
| * new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ), |
| * new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ), |
| * ), |
| * array( |
| * 'image/gif' => 'image/png', |
| * 'image/bmp' => 'image/jpeg', |
| * ) |
| * ); |
| * |
| * |
| * // Create the converter itself. |
| * $converter = new ezcImageConverter( $settings ); |
| * |
| * // Define a transformation |
| * $filters = array( |
| * new ezcImageFilter( |
| * 'scale', |
| * array( |
| * 'width' => 100, |
| * 'height' => 300, |
| * 'direction' => ezcImageGeometryFilters::SCALE_BOTH, |
| * ) |
| * ), |
| * new ezcImageFilter( |
| * 'colorspace', |
| * array( |
| * 'space' => ezcImageColorspaceFilters::COLORSPACE_SEPIA, |
| * ) |
| * ), |
| * new ezcImageFilter( |
| * 'border', |
| * array( |
| * 'width' => 5, |
| * 'color' => array(255, 0, 0), |
| * ) |
| * ), |
| * ); |
| * |
| * // Which MIME types the conversion may output |
| * $mimeTypes = array( 'image/jpeg', 'image/png' ); |
| * |
| * // Create the transformation inside the manager |
| * $converter->createTransformation( 'funny', $filters, $mimeTypes ); |
| * |
| * // Assign singleton instance |
| * $GLOBALS['_ezcImageConverterInstance'] = $converter; |
| * } |
| * |
| * // Return singleton instance |
| * return $GLOBALS['_ezcImageConverterInstance']; |
| * } |
| * |
| * // ... |
| * // Somewhere else in the code... |
| * // Transform an image. |
| * getImageConverterInstance()->transform( 'funny', dirname(__FILE__).'/jpeg.jpg', dirname(__FILE__).'/jpeg_singleton.jpg' ); |
| * |
| * </code> |
| * |
| * @see ezcImageHandler |
| * @see ezcImageTransformation |
| * |
| * @package ImageConversion |
| * @version //autogentag// |
| * @mainclass |
| */ |
| class ezcImageConverter |
| { |
| /** |
| * Manager settings |
| * Settings basis for all image manipulations. |
| * |
| * @var ezcImageConverterSettings |
| */ |
| protected $settings; |
| |
| /** |
| * Keeps the handlers used by the converter. |
| * |
| * @var array(ezcImageHandler) |
| */ |
| protected $handlers = array(); |
| |
| /** |
| * Stores transformation registered with this converter. |
| * |
| * @var array |
| */ |
| protected $transformations = array(); |
| |
| /** |
| * Initialize converter with settings object. |
| * The ezcImageConverter can be directly instantiated, but it's |
| * highly recommended to use a manual singleton implementation |
| * to have just 1 instance of a ezcImageConverter per Request. |
| * |
| * ATTENTION: The ezcImageConverter does not support animated |
| * GIFs. Animated GIFs will simply be ignored by all filters and |
| * conversions. |
| * |
| * @param ezcImageConverterSettings $settings Settings for the converter. |
| * |
| * @throws ezcImageHandlerSettingsInvalidException |
| * If handler settings are invalid. |
| * @throws ezcImageMimeTypeUnsupportedException |
| * If a given MIME type is not supported. |
| */ |
| public function __construct( ezcImageConverterSettings $settings ) |
| { |
| // Initialize handlers |
| foreach ( $settings->handlers as $i => $handlerSettings ) |
| { |
| if ( !$handlerSettings instanceof ezcImageHandlerSettings ) |
| { |
| throw new ezcImageHandlerSettingsInvalidException(); |
| } |
| $handlerClass = $handlerSettings->className; |
| if ( !ezcBaseFeatures::classExists( $handlerClass ) ) |
| { |
| throw new ezcImageHandlerNotAvailableException( $handlerClass ); |
| } |
| $handler = new $handlerClass( $handlerSettings ); |
| $this->handlers[$handlerSettings->referenceName] = $handler; |
| } |
| // Check implicit conversions |
| foreach ( $settings->conversions as $mimeIn => $mimeOut ) |
| { |
| if ( !$this->allowsInput( $mimeIn ) ) |
| { |
| throw new ezcImageMimeTypeUnsupportedException( $mimeIn, 'input' ); |
| } |
| if ( !$this->allowsOutput( $mimeOut ) ) |
| { |
| throw new ezcImageMimeTypeUnsupportedException( $mimeOut, 'output' ); |
| } |
| } |
| $this->settings = $settings; |
| } |
| |
| /** |
| * Create a transformation in the manager. |
| * |
| * Creates a transformation and stores it in the manager. A reference to the |
| * transformation is returned by this method for further manipulation and |
| * to set options on it. The $name can later be used to remove a |
| * transfromation using {@link removeTransformation()} or to execute it |
| * using {@link transform()}. The $filters and $mimeOut parameters specify |
| * the transformation actions as described with {@link |
| * ezcImageTransformation::__construct()}. The $saveOptions are used when |
| * the finally created image is saved and can configure compression and |
| * quality options. |
| * |
| * @param string $name Name for the transformation. |
| * @param array(ezcImageFilter) $filters Filters. |
| * @param array(string) $mimeOut Output MIME types. |
| * @param ezcImageSaveOptions $saveOptions Save options. |
| * |
| * @return ezcImageTransformation |
| * |
| * @throws ezcImageFiltersException |
| * If a given filter does not exist. |
| * @throws ezcImageTransformationAlreadyExists |
| * If a transformation with the given name does already exist. |
| */ |
| public function createTransformation( $name, array $filters, array $mimeOut, ezcImageSaveOptions $saveOptions = null ) |
| { |
| if ( isset( $this->transformations[$name] ) ) |
| { |
| throw new ezcImageTransformationAlreadyExistsException( $name ); |
| } |
| $this->transformations[$name] = new ezcImageTransformation( $this, $name, $filters, $mimeOut, $saveOptions ); |
| return $this->transformations[$name]; |
| } |
| |
| /** |
| * Removes a transformation from the manager. |
| * |
| * @param string $name Name of the transformation to remove |
| * |
| * @return ezcImageTransformation The removed transformation |
| * |
| * @throws ezcImageTransformationNotAvailableExeption |
| * If the requested transformation is unknown. |
| */ |
| public function removeTransformation( $name ) |
| { |
| if ( !isset( $this->transformations[$name] ) ) |
| { |
| throw new ezcImageTransformationNotAvailableException( $name ); |
| } |
| unset( $this->transformations[$name] ); |
| } |
| |
| /** |
| * Apply transformation on a file. |
| * This applies the given transformation to the given file. |
| * |
| * @param string $name Name of the transformation to perform |
| * @param string $inFile The file to transform |
| * @param string $outFile The file to save transformed version to |
| * |
| * @throws ezcImageTransformationNotAvailableExeption |
| * If the requested transformation is unknown. |
| * @throws ezcImageTransformationException If an error occurs during the |
| * transformation. The returned exception contains the exception |
| * the problem resulted from in it's public $parent attribute. |
| * @throws ezcBaseFileNotFoundException If the file you are trying to |
| * transform does not exists. |
| * @throws ezcBaseFilePermissionException If the file you are trying to |
| * transform is not readable. |
| */ |
| public function transform( $name, $inFile, $outFile ) |
| { |
| if ( !isset( $this->transformations[$name] ) ) |
| { |
| throw new ezcImageTransformationNotAvailableException( $name ); |
| } |
| $this->transformations[$name]->transform( $inFile, $outFile ); |
| } |
| |
| /** |
| * Returns if a handler is found, supporting the given MIME type for output. |
| * |
| * @param string $mime The MIME type to check for. |
| * @return bool Whether the MIME type is supported. |
| */ |
| public function allowsInput( $mime ) |
| { |
| foreach ( $this->handlers as $handler ) |
| { |
| if ( $handler->allowsInput( $mime ) ) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns if a handler is found, supporting the given MIME type for output. |
| * |
| * @param string $mime The MIME type to check for. |
| * @return bool Whether the MIME type is supported. |
| */ |
| public function allowsOutput( $mime ) |
| { |
| foreach ( $this->handlers as $handler ) |
| { |
| if ( $handler->allowsOutput( $mime ) ) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns the MIME type that will be outputted for a given input type. |
| * Checks whether the given input type can be processed. If not, an |
| * exception is thrown. Checks then, if an implicit conversion for that |
| * MIME type is defined. If so, outputs the given output MIME type. In |
| * every other case, just outputs the MIME type given, because no |
| * conversion is implicitly required. |
| * |
| * @param string $mimeIn Input MIME type. |
| * @return string Output MIME type. |
| * |
| * @throws ezcImageMimeTypeUnsupportedException |
| * If the input MIME type is not supported. |
| */ |
| public function getMimeOut( $mimeIn ) |
| { |
| if ( $this->allowsInput( $mimeIn ) === false ) |
| { |
| throw new ezcImageMimeTypeUnsupportedException( $mimeIn, 'input' ); |
| } |
| if ( isset( $this->settings->conversions[$mimeIn] ) ) |
| { |
| return $this->settings->conversions[$mimeIn]; |
| } |
| return $mimeIn; |
| } |
| |
| /** |
| * Returns if a given filter is available. |
| * Returns either an array of handler names this filter |
| * is available in or false if the filter is not enabled. |
| * |
| * @param string $name Name of the filter to query existance for |
| * |
| * @return mixed Array of handlers on success, otherwise false. |
| */ |
| public function hasFilter( $name ) |
| { |
| foreach ( $this->handlers as $handler ) |
| { |
| if ( $handler->hasFilter( $name ) ) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns a list of enabled filters. |
| * Gives you an overview on filters enabled in the manager. |
| * Format is: |
| * <code> |
| * array( |
| * '<filterName>', |
| * ); |
| * </code> |
| * |
| * @return array(string) |
| */ |
| public function getFilterNames() |
| { |
| $filters = array(); |
| foreach ( $this->handlers as $handler ) |
| { |
| $filters = array_merge( $filters, $handler->getFilterNames() ); |
| } |
| return array_unique( $filters ); |
| } |
| |
| /** |
| * Apply a single filter to an image. |
| * Applies just a single filter to an image. Optionally you can select |
| * a handler yourself, which is not recommended, but possible. If the |
| * specific handler does not have that filter, ImageConverter will try |
| * to fall back on another handler. |
| * |
| * @param ezcImageFilter $filter Filter object to apply. |
| * @param string $inFile Name of the input file. |
| * @param string $outFile Name of the output file. |
| * @param string $handlerName |
| * To choose a specific handler, this is the reference named passed |
| * to {@link ezcImageHandlerSettings}. |
| * @return void |
| * |
| * |
| * @throws ezcImageHandlerNotAvailableException |
| * If fitting handler is not available. |
| * @throws ezcImageFilterNotAvailableException |
| * If filter is not available. |
| * @throws ezcImageFileNameInvalidException |
| * If an invalid character (", ', $) is found in the file name. |
| */ |
| public function applyFilter( ezcImageFilter $filter, $inFile, $outFile, $handlerName = null ) |
| { |
| $handlerObj = false; |
| // Do we have an explicit handler given? |
| if ( $handlerName !== null ) |
| { |
| if ( !isset( $this->handlers[$handlerName] ) ) |
| { |
| throw new ezcImageHandlerNotAvailableException( $handlerName ); |
| } |
| if ( $this->handlers[$handlerName]->hasFilter( $filter->name ) === true ) |
| { |
| $handlerObj = $this->handlers[$handlerName]; |
| } |
| } |
| // Either no handler explicitly given or try to fall back. |
| if ( $handlerObj === false ) |
| { |
| foreach ( $this->handlers as $regHandler ) |
| { |
| if ( $regHandler->hasFilter( $filter->name ) ) |
| { |
| $handlerObj = $regHandler; |
| break; |
| } |
| } |
| } |
| // No handler found to apply filter with. |
| if ( $handlerObj === false ) |
| { |
| throw new ezcImageFilterNotAvailableException( $filter->name ); |
| } |
| $imgRef = $handlerObj->load( $inFile ); |
| $handlerObj->applyFilter( $imgRef, $filter ); |
| $handlerObj->save( $imgRef, $outFile ); |
| } |
| |
| /** |
| * Returns a handler object for direct use. |
| * Returns the handler with the highest priority, that supports the given |
| * filter, MIME input type and MIME output type. All parameters are |
| * optional, if none is specified, the highest prioritized handler is |
| * returned. |
| * |
| * If no handler is found, that supports the criteria named, an exception |
| * of type {@link ezcImageHandlerNotAvailableException} will be thrown. |
| * |
| * @param string $filterName Name of the filter to search for. |
| * @param string $mimeIn Input MIME type. |
| * @param string $mimeOut Output MIME type. |
| * |
| * @return ezcImageHandler |
| * |
| * @throws ezcImageHandlerNotAvailableException |
| * If a handler for the given specification could not be found. |
| */ |
| public function getHandler( $filterName = null, $mimeIn = null, $mimeOut = null ) |
| { |
| foreach ( $this->handlers as $handler ) |
| { |
| if ( ( !isset( $filterName ) || $handler->hasFilter( $filterName ) ) |
| && ( !isset( $mimeIn ) || $handler->allowsInput( $mimeIn ) ) |
| && ( !isset( $mimeOut ) || $handler->allowsOutput( $mimeOut ) ) |
| ) |
| { |
| return $handler; |
| } |
| } |
| throw new ezcImageHandlerNotAvailableException( 'unknown' ); |
| } |
| } |
| ?> |