/ImageConversion/src/transformation.php
PHP | 417 lines | 172 code | 24 blank | 221 comment | 20 complexity | 088a951d528fcfb8a486fca70fc963fe MD5 | raw file
- <?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//
- * @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;
- }
- }
- ?>