| <?php |
| /** |
| * File containing the ezcImageTransformation 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. |
| * |
| * @see ezcImageConverter |
| * |
| * @package ImageConversion |
| * @version //autogentag// |
| * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved. |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| * @filesource |
| */ |
| |
| /** |
| * Provides transformations on images using filters and MIME conversions. |
| * Objects of this class group MIME type conversion and filtering of images |
| * into transformations of images. Transformations can be chained by referencing |
| * to another transformation so that multiple transformations will be produced |
| * after each other. |
| * |
| * <code> |
| * $filters = array( |
| * new ezcImageFilter( 'scaleDownByWidth', |
| * array( |
| * 'width' => 100 |
| * ) |
| * ), |
| * new ezcImageFilter( 'crop', |
| * array( |
| * 'x' => 0, |
| * 'y' => 0, |
| * 'width' => 100, |
| * 'height' => 100, |
| * ) |
| * ), |
| * ); |
| * $mimeTypes = array( 'image/jpeg', 'image/png' ); |
| * |
| * // ezcImageTransformation object returned for further manipulation |
| * $thumbnail = $converter->createTransformation( |
| * 'thumbnail', |
| * $filters, |
| * $mimeTypes |
| * ); |
| * |
| * $converter->transform( 'thumbnail', 'var/storage/myOriginal1.jpg', |
| * 'var/storage/myThumbnail1' ); // res: image/jpeg |
| * $converter->transform( 'thumbnail', 'var/storage/myOriginal2.png', |
| * 'var/storage/myThumbnail2' ); // res: image/png |
| * $converter->transform( 'thumbnail', 'var/storage/myOriginal3.gif', |
| * 'var/storage/myThumbnail3' ); // res: image/.png |
| * |
| * // Animated GIF, will simply be copied! |
| * $converter->transform( 'thumbnail', 'var/storage/myOriginal4.gif', |
| * 'var/storage/myThumbnail4' ); // res: image/gif |
| * </code> |
| * |
| * @see ezcImageConverter |
| * |
| * @package ImageConversion |
| * @version //autogentag// |
| */ |
| class ezcImageTransformation |
| { |
| /** |
| * Array of MIME types allowed as output for this transformation. |
| * Leave empty, for all MIME types to be allowed. |
| * |
| * @var array(string) |
| */ |
| protected $mimeOut; |
| |
| /** |
| * Stores the filters utilized by a transformation. |
| * |
| * @var array(ezcImageFilter) |
| */ |
| protected $filters; |
| |
| /** |
| * Stores the name of this transformation. |
| * |
| * @var string |
| */ |
| protected $name; |
| |
| /** |
| * The ezcImageConverter |
| * |
| * @var ezcImageConverter |
| */ |
| protected $converter; |
| |
| /** |
| * The handler last used for filtering. |
| * |
| * @var ezcImageHandler |
| */ |
| protected $lastHandler; |
| |
| /** |
| * Options for the final save step. |
| * |
| * @var ezcSaveOptions |
| */ |
| protected $saveOptions; |
| |
| /** |
| * Initialize transformation. |
| * |
| * @param ezcImageConverter $converter The global converter. |
| * @param string $name Name for the transformation. |
| * @param array(ezcImageFilter) $filters Filters to apply. |
| * @param array(string) $mimeOut Output MIME types. |
| * @param ezcImageSaveOptions $saveOptions Options for saving images. |
| * |
| * @throws ezcImageFiltersException |
| * On invalid filter or filter settings error. |
| * @throws ezcImageMimeTypeUnsupportedException |
| * If the output type is unsupported. |
| */ |
| public function __construct( ezcImageConverter $converter, $name, array $filters = array(), array $mimeOut = array(), ezcImageSaveOptions $saveOptions = null ) |
| { |
| $this->converter = $converter; |
| $this->name = $name; |
| $this->setFilters( $filters ); |
| $this->setMimeOut( $mimeOut ); |
| $this->setSaveOptions( $saveOptions !== null ? $saveOptions : new ezcImageSaveOptions() ); |
| } |
| |
| /** |
| * Add a filter to the conversion. |
| * Adds a filter with the specific settings. Filters can be added either |
| * before an existing filter or at the end (leave out $before parameter). |
| * |
| * @param ezcImageFilter $filter The filter definition. |
| * @param int $before Where to add the filter |
| * @return void |
| * |
| * @throws ezcImageFilterNotAvailableException |
| * If the given filter is not available. |
| */ |
| public function addFilter( ezcImageFilter $filter, $before = null ) |
| { |
| if ( $this->converter->hasFilter( $filter->name ) === false ) |
| { |
| throw new ezcImageFilterNotAvailableException( $filter->name ); |
| } |
| if ( isset( $before ) && isset( $this->filters[$before] ) ) |
| { |
| array_splice( $this->filters, $before, 0, array( $filter ) ); |
| return; |
| } |
| $this->filters[] = $filter; |
| } |
| |
| /** |
| * Determine output MIME type |
| * Returns the MIME type that the transformation will output. |
| * |
| * @param string $fileIn File that should deal as input for the transformation. |
| * @param string $mimeIn Specify the MIME type, so method does not need to. |
| * |
| * @return string MIME type the transformation will output. |
| * |
| * @throws ezcImageAnalyzerException If the input type is unsupported. |
| */ |
| public function getOutMime( $fileIn, $mimeIn = null ) |
| { |
| if ( !isset( $mimeIn ) ) |
| { |
| $analyzer = new ezcImageAnalyzer( $fileIn ); |
| $mimeIn = $analyzer->mime; |
| } |
| $mimeOut = $this->converter->getMimeOut( $mimeIn ); |
| // Is output type allowed by this transformation? Else use first allowed one... |
| return in_array( $mimeOut, $this->mimeOut ) ? $mimeOut : reset( $this->mimeOut ); |
| } |
| |
| /** |
| * Apply the given filters for the transformation. |
| * Applies the conversion as defined to the given file and saves it as |
| * defined. |
| * |
| * @param string $fileIn The file to transform. |
| * @param string $fileOut The file to save the transformed image to. |
| * @return void |
| * |
| * @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( $fileIn, $fileOut ) |
| { |
| // Sanity checks |
| if ( !is_file( $fileIn ) ) |
| { |
| throw new ezcBaseFileNotFoundException( $fileIn ); |
| } |
| if ( !is_readable( $fileIn ) ) |
| { |
| throw new ezcBaseFilePermissionException( $fileIn, ezcBaseFileException::READ ); |
| } |
| |
| // Start atomic file operation |
| $fileTmp = tempnam( dirname( $fileOut ) . DIRECTORY_SEPARATOR, '.'. basename( $fileOut ) ); |
| copy( $fileIn, $fileTmp ); |
| |
| try |
| { |
| // MIME types |
| $analyzer = new ezcImageAnalyzer( $fileTmp ); |
| |
| // Do not process animated GIFs |
| if ( $analyzer->data->isAnimated ) |
| { |
| copy( $fileTmp, $fileOut ); |
| unlink( $fileTmp ); |
| return; |
| } |
| |
| $mimeIn = $analyzer->mime; |
| } |
| catch ( ezcImageAnalyzerException $e ) |
| { |
| // Clean up |
| unlink( $fileTmp ); |
| // Rethrow |
| throw new ezcImageTransformationException( $e ); |
| } |
| |
| $outMime = $this->getOutMime( $fileTmp, $mimeIn ); |
| |
| $ref = ''; |
| |
| // Catch exceptions for cleanup |
| try |
| { |
| // Apply the filters |
| foreach ( $this->filters as $filter ) |
| { |
| // Avoid reopening in same handler |
| if ( isset( $this->lastHandler ) ) |
| { |
| if ( $this->lastHandler->hasFilter( $filter->name ) ) |
| { |
| $this->lastHandler->applyFilter( $ref, $filter ); |
| continue; |
| } |
| else |
| { |
| // Handler does not support filter, save file |
| $this->lastHandler->save( $ref ); |
| $this->lastHandler->close( $ref ); |
| } |
| } |
| // Get handler to perform filter correctly |
| $this->lastHandler = $this->converter->getHandler( $filter->name, $mimeIn ); |
| $ref = $this->lastHandler->load( $fileTmp, $mimeIn ); |
| $this->lastHandler->applyFilter( $ref, $filter ); |
| } |
| |
| // When no filters are performed by a transformation, we might have no last handler here |
| if ( !isset( $this->lastHandler ) ) |
| { |
| $this->lastHandler = $this->converter->getHandler( null, $mimeIn, $outMime ); |
| $ref = $this->lastHandler->load( $fileTmp, $mimeIn ); |
| } |
| |
| // Perform conversion |
| if ( $this->lastHandler->allowsOutput( ( $outMime ) ) ) |
| { |
| $this->lastHandler->convert( $ref, $outMime ); |
| } |
| else |
| { |
| // Close in last handler |
| $this->lastHandler->save( $ref ); |
| $this->lastHandler->close( $ref ); |
| // Destroy invalid reference (has been closed) |
| $ref = null; |
| // Retreive correct handler |
| $this->lastHandler = $this->converter->getHandler( null, $mimeIn, $outMime ); |
| // Load in new handler |
| $ref = $this->lastHandler->load( $fileTmp ); |
| // Perform conversion |
| $this->lastHandler->convert( $ref, $outMime ); |
| } |
| // Everything done, save and close |
| $this->lastHandler->save( $ref, null, null, $this->saveOptions ); |
| $this->lastHandler->close( $ref ); |
| } |
| catch ( ezcImageException $e ) |
| { |
| // Cleanup |
| if ( $ref !== null ) |
| { |
| $this->lastHandler->close( $ref ); |
| } |
| if ( file_exists( $fileTmp ) ) |
| { |
| unlink( $fileTmp ); |
| } |
| $this->lastHandler = null; |
| // Rethrow |
| throw new ezcImageTransformationException( $e ); |
| } |
| |
| // Cleanup |
| $this->lastHandler = null; |
| |
| // Finalize atomic file operation |
| if ( ezcBaseFeatures::os() === 'Windows' && file_exists( $fileOut ) ) |
| { |
| // Windows does not allows overwriting files using rename, |
| // therefore the file is unlinked here first. |
| if ( unlink( $fileOut ) === false ) |
| { |
| // Cleanup |
| unlink( $fileTmp ); |
| throw new ezcImageFileNotProcessableException( $fileOut, 'The file exists and could not be unlinked.' ); |
| } |
| } |
| if ( @rename( $fileTmp, $fileOut ) === false ) |
| { |
| unlink( $fileTmp ); |
| throw new ezcImageFileNotProcessableException( $fileOut, "The temporary file {$fileTmp} could not be renamed to {$fileOut}." ); |
| } |
| } |
| |
| /** |
| * Set the filters for this transformation. |
| * Checks if the filters defined are available and saves them to the created |
| * transformation if everything is okay. |
| * |
| * @param array(ezcImageFilter) $filters Array of {@link ezcImageFilter filter objects}. |
| * @return void |
| * |
| * @throws ezcImageFilterNotAvailableException |
| * If a filter is not available. |
| * @throws ezcBaseFileException |
| * If the filter array contains invalid object entries. |
| */ |
| protected function setFilters( array $filters ) |
| { |
| foreach ( $filters as $id => $filter ) |
| { |
| if ( !$filter instanceof ezcImageFilter ) |
| { |
| throw new ezcBaseSettingValueException( 'filters', 'array( int => ' . get_class( $filter ) . ' )', 'array( int => ezcImageFilter )' ); |
| } |
| if ( !$this->converter->hasFilter( $filter->name ) ) |
| { |
| throw new ezcImageFilterNotAvailableException( $filter->name ); |
| } |
| } |
| $this->filters = $filters; |
| } |
| |
| /** |
| * Sets the MIME types which are allowed for output. |
| * |
| * @param array $mime MIME types to allow output for. |
| * @return void |
| * |
| * @throws ezcImageMimeTypeUnsupportedException |
| * If the MIME types cannot be used as output of any of the |
| * handlers in the converter. |
| */ |
| protected function setMimeOut( array $mime ) |
| { |
| foreach ( $mime as $mimeType ) |
| { |
| if ( !$this->converter->allowsOutput( $mimeType ) ) |
| { |
| throw new ezcImageMimeTypeUnsupportedException( $mimeType, 'output' ); |
| } |
| } |
| $this->mimeOut = $mime; |
| } |
| |
| /** |
| * Sets the save options. |
| * Sets the save options, that are used for the final save step of the |
| * transformation. |
| * |
| * {@link ezcImageSaveOptions} |
| * |
| * @param ezcImageSaveOptions $options Save options. |
| * @return void |
| */ |
| public function setSaveOptions( ezcImageSaveOptions $options ) |
| { |
| $this->saveOptions = $options; |
| } |
| } |
| ?> |