Apache Zeta Components Manual :: File Source for imagemagick_base.php
Source for file imagemagick_base.php
Documentation is available at imagemagick_base.php
* This file contains the ezcImageImagemagickBaseHandler 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
* @package ImageConversion
* @version //autogentag//
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* ezcImageHandler implementation for ImageMagick.
* This class only implements the base funtionality of handling images with
* ImageMagick. If you want to manipulate images using ImageMagick in your
* application, you should use the {@link ezcImageImagemagickHandler}.
* You can use this base class to implement your own filter set on basis of
* ImageMagick, but you can also use {@link ezcImageImagemagickHandler} for
* this and profit from its already implemented filters.
* @package ImageConversion
* @version //autogentag//
* Path to the convert binary.
* Map of MIME types to convert tags.
* @var array(string=>string)
private $tagMap =
array();
* Filter options per reference.
* @var array(string=>array)
private $filterOptions =
array();
* Composite image setting per reference.
* @var array(string=>bool)
private $compositeImages =
array();
* Create a new image handler.
* Creates an image handler. This should never be done directly,
* but only through the manager for configuration reasons. One can
* get a direct reference through manager afterwards.
* This handler has an option 'binary' available, which allows you to
* explicitly set the path to your ImageMagicks "convert" binary (this
* may be necessary on Windows, since there may be an obscure "convert.exe"
* in the $PATH variable available, which has nothing to do with
* @throws ezcImageHandlerNotAvailableException
* If the ImageMagick binary is not found.
* @param ezcImageHandlerSettings $settings Settings for the handler.
public function __construct( ezcImageHandlerSettings $settings )
$this->checkImageMagick( $settings );
parent::__construct( $settings );
* Loads an image file and returns a reference to it.
* @param string $file File to load.
* @param string $mime The MIME type of the file.
* @return string Reference to the file in this handler.
* @throws ezcBaseFileNotFoundException
* If the desired file does not exist.
* @throws ezcImageMimeTypeUnsupportedException
* If the desired file has a not recognized type.
* @throws ezcImageFileNameInvalidException
* If an invalid character (", ', $) is found in the file name.
public function load( $file, $mime =
null )
$this->checkFileName( $file );
$ref =
$this->loadCommon( $file, $mime );
$this->setReferenceData( $ref, $fileTmp, 'resource' );
* Saves a given open file. Can optionally save to a new file name.
* @see ezcImageHandler::load()
* @param string $image File reference created through load().
* @param string $newFile Filename to save the image to.
* @param string $mime New MIME type, if differs from initial one.
* @param ezcImageSaveOptions $options Save options.
* @throws ezcBaseFilePermissionException
* If the desired file exists and is not writeable.
* @throws ezcImageMimeTypeUnsupportedException
* If the desired MIME type is not recognized.
* @throws ezcImageFileNameInvalidException
* If an invalid character (", ', $) is found in the file name.
public function save( $image, $newFile =
null, $mime =
null, ezcImageSaveOptions $options =
null )
$this->checkFileName( $newFile );
// Check is transparency must be converted
if ( $this->needsTransparencyConversion( $this->getReferenceData( $image, 'mime' ), $mime ) &&
$options->transparencyReplacementColor !==
null )
$this->saveCommon( $image, $newFile, $mime );
switch ( $this->getReferenceData( $image, 'mime' ) )
if ( $options->quality !==
null )
if ( $options->compression !==
null )
// ImageMagick uses qualtiy options here and incorporates filter options
// Prepare ImageMagick command
// Here we need a work around, because older ImageMagick versions do not
// support this option order
if ( isset
( $this->compositeImages[$image] ) )
$command =
$this->binary .
' ' .
( isset
( $this->filterOptions[$image] ) ?
implode( ' ', $this->filterOptions[$image] ) :
'' ) .
' ' .
escapeshellarg( $this->getReferenceData( $image, 'resource' ) ) .
' ' .
implode( ' ', $this->compositeImages[$image] ) .
' ' .
escapeshellarg( $this->tagMap[$this->getReferenceData( $image, 'mime' )] .
':' .
$this->getReferenceData( $image, 'resource' ) );
$command =
$this->binary .
' ' .
escapeshellarg( $this->getReferenceData( $image, 'resource' ) ) .
' ' .
( isset
( $this->filterOptions[$image] ) ?
implode( ' ', $this->filterOptions[$image] ) :
'' ) .
' ' .
escapeshellarg( $this->tagMap[$this->getReferenceData( $image, 'mime' )] .
':' .
$this->getReferenceData( $image, 'resource' ) );
// Prepare to run ImageMagick command
// Open ImageMagick process
$imageProcess =
proc_open( $command, $descriptors, $pipes );
$outputString .=
rtrim( fgets( $pipes[1], 1024 ), "\n" );
$errorString .=
rtrim( fgets( $pipes[2], 1024 ), "\n" );
} while ( !feof( $pipes[2] ) );
// Wait for process to terminate and store return value
while ( $status['running'] !==
false )
// Sleep 1/100 second to wait for convert to exit
// Process potential errors
// Exit code may be messed up with -1, especially on Windoze
if ( ( $status['exitcode'] !=
0 &&
$status['exitcode'] != -
1 ) ||
strlen( $errorString ) >
0 )
$this->getReferenceData( $image, 'resource' ),
"The command '{$command}' resulted in an error ({$status['exitcode']}): '{$errorString}'. Output: '{$outputString}'"
// Finish atomic file operation
copy( $this->getReferenceData( $image, 'resource' ), $this->getReferenceData( $image, 'file' ) );
* Returns a string representation of the given color array.
* ImageConversion uses arrays to represent color values, in the format:
* This array represents the color red.
* This method takes such a color array and converts it into a string
* representation usable by the convert binary. For the above examle it
* @throws ezcBaseValueException
* if one of the color values in the array is invalid (not integer,
* smaller than 0 or larger than 255).
foreach ( $color as $id =>
$colorVal )
if ( !is_int( $colorVal ) ||
$colorVal <
0 ||
$colorVal >
255 )
$colorString .=
sprintf( '%02x', $colorVal );
* Close the file referenced by $image.
* Frees the image reference. You should call close() before.
* @see ezcImageHandler::load()
* @see ezcImageHandler::save()
* @param string $image The image reference.
public function close( $image )
unlink( $this->getReferenceData( $image, 'resource' ) );
$this->setReferenceData( $image, false, 'resource' );
$this->closeCommon( $image );
* Add a filter option to a given reference
* @param string $reference The reference to add a filter for.
* @param string $name The option name.
* @param string $parameter The option parameter.
$this->filterOptions[$reference][] =
$name .
( $parameter !==
null ?
' ' .
escapeshellarg( $parameter ) :
'' );
* Add an image to composite with the given reference.
* @param string $reference The reference to add an image to
* @param string $file The file to composite with the image.
$this->compositeImages[$reference][] =
$file;
* Determines the supported input/output types supported by handler.
* Set's various attributes to reflect the MIME types this handler is
* @apichange Faulty MIME type "image/svg" will be removed and replaced by
* correct MIME type image/svg+xml.
private function determineTypes()
'application/pcl' =>
'PCL',
'application/pdf' =>
'PDF',
'application/postscript' =>
'PS',
'application/vnd.palm' =>
'PDB',
'application/x-icb' =>
'ICB',
'application/x-mif' =>
'MIFF',
'image/pjpeg' =>
'PJPEG',
'image/svg+xml' =>
'SVG',
// Left over for BC reasons
'image/vnd.wap.wbmp' =>
'WBMP',
'image/x-fits' =>
'FITS',
'image/x-palm' =>
'PALM',
'image/x-ptiff' =>
'PTIF',
'image/x-viff' =>
'VIFF',
'image/x-xbitmap' =>
'XPM',
$this->inputTypes =
$types;
$this->outputTypes =
$types;
* Checks for ImageMagick on the system.
* @param ezcImageHandlerSettings $settings The settings object of the current handler instance.
* @throws ezcImageHandlerNotAvailableException
* If the ImageMagick binary is not found.
private function checkImageMagick( ezcImageHandlerSettings $settings )
if ( !isset
( $settings->options['binary'] ) )
else if ( file_exists( $settings->options['binary'] ) )
$this->binary =
$settings->options['binary'];
if ( $this->binary ===
null )
'ezcImageImagemagickHandler',
'ImageMagick not installed or not available in PATH variable.'
// Prepare to run ImageMagick command
// Open ImageMagick process
$imageProcess =
proc_open( $this->binary, $descriptors, $pipes );
$outputString .=
rtrim( fgets( $pipes[1], 1024 ), "\n" );
} while ( !feof( $pipes[1] ) );
$errorString .=
rtrim( fgets( $pipes[2], 1024 ), "\n" );
} while ( !feof( $pipes[2] ) );
// Wait for process to terminate and store return value
// Process potential errors
if ( strlen( $errorString ) >
0 ||
strpos( $outputString, 'ImageMagick' ) ===
false )
* Creates default settings for the handler and returns it.
* The reference name will be set to 'ImageMagick'.
* @return ezcImageHandlerSettings