mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-02 04:39:28 +00:00
402 lines
13 KiB
PHP
402 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* File containing the ezcImageTransformation class.
|
|
*
|
|
* @see ezcImageConverter
|
|
*
|
|
* @package ImageConversion
|
|
* @version 1.3.5
|
|
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
|
|
* @license http://ez.no/licenses/new_bsd New BSD License
|
|
* @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 1.3.5
|
|
*/
|
|
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;
|
|
}
|
|
}
|
|
?>
|