blob: 68e7d936b8982d9369524bbed33c25c7427c814c [file] [log] [blame]
<?php
/**
* This file contains the ezcImageGdBaseHandler 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//
* @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
*/
/**
* ezcImageHandler implementation for the GD2 extension of PHP.
* This class only implements the base funtionality of handling GD images. If
* you want to manipulate images using ext/GD in your application, you should
* use the {@link ezcImageGdHandler}.
*
* You can use this base class to implement your own filter set on basis of
* ext/GD, but you can also use {@link ezcImageGdHandler} for this and profit
* from its already implemented filters.
*
* @see ezcImageConverter
* @see ezcImageHandler
*
* @package ImageConversion
* @version //autogentag//
*/
class ezcImageGdBaseHandler extends ezcImageMethodcallHandler
{
/**
* 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.
*
* @param ezcImageHandlerSettings $settings
* Settings for the handler.
*
* @throws ezcImageHandlerNotAvailableException
* If the precondition for the handler is not fulfilled.
*/
public function __construct( ezcImageHandlerSettings $settings )
{
if ( !ezcBaseFeatures::hasExtensionSupport( 'gd' ) )
{
throw new ezcImageHandlerNotAvailableException( "ezcImageGdHandler", "PHP extension 'GD' not available." );
}
$this->determineTypes();
parent::__construct( $settings );
}
/**
* Load an image file.
* 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.
*
* @see ezcImageAnalyzer
*
* @throws ezcBaseFileNotFoundException
* If the given file does not exist.
* @throws ezcImageMimeTypeUnsupportedException
* If the type of the given file is not recognized
* @throws ezcImageFileNotProcessableException
* If the given file is not processable using this handler.
* @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, isset( $mime ) ? $mime : null );
$loadFunction = $this->getLoadFunction( $this->getReferenceData( $ref, 'mime' ) );
if ( !ezcBaseFeatures::hasFunction( $loadFunction ) || ( $handle = @$loadFunction( $file ) ) === false )
{
throw new ezcImageFileNotProcessableException( $file, "File could not be opened using $loadFunction." );
}
$this->setReferenceData( $ref, $handle, 'resource' );
return $ref;
}
/**
* Save an image file.
* 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.
* @return void
*
* @throws ezcImageFileNotProcessableException
* If the given file could not be saved with the given MIME type.
* @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 )
{
$options = ( $options === null ) ? new ezcImageSaveOptions() : $options;
if ( $newFile !== null )
{
$this->checkFileName( $newFile );
}
// Check is transparency must be converted
if ( $this->needsTransparencyConversion( $this->getReferenceData( $image, 'mime' ), $mime ) && $options->transparencyReplacementColor !== null )
{
$this->replaceTransparency( $image, $options->transparencyReplacementColor );
}
$this->saveCommon( $image, isset( $newFile ) ? $newFile : null, isset( $mime ) ? $mime : null );
$saveFunction = $this->getSaveFunction( $this->getReferenceData( $image, 'mime' ) );
$saveParams = array(
$this->getReferenceData( $image, 'resource' ),
$this->getReferenceData( $image, 'file' ),
);
switch ( $saveFunction )
{
case "imagejpeg":
if ( $options->quality !== null )
{
$saveParams[] = $options->quality;
}
break;
case "imagepng":
if ( $options->compression !== null )
{
$saveParams[] = $options->compression;
}
break;
}
if ( !ezcBaseFeatures::hasFunction( $saveFunction ) ||
call_user_func_array( $saveFunction, $saveParams ) === false )
{
throw new ezcImageFileNotProcessableException( $file, "Unable to save file '{$file}' of type '{$mime}'." );
}
}
/**
* Replaces a transparent background with the given color.
*
* This method is used to replace the transparent background of an image
* with an opaque color when converting from a transparency supporting MIME
* type (e.g. image/png) to a MIME type that does not support transparency.
*
* The color
*
* @param mixed $image
* @param mixed $color
* @return void
*/
protected function replaceTransparency( $image, array $color )
{
$oldResource = $this->getReferenceData( $image, 'resource' );
$width = imagesx( $oldResource );
$height = imagesy( $oldResource );
if ( imageistruecolor( $oldResource ) )
{
$newResource = imagecreatetruecolor( $width, $height );
}
else
{
$newResource = imagecreate( $width, $height );
}
$bgColor = imagecolorallocate( $newResource, $color[0], $color[1], $color[2] );
imagefill( $newResource, 0, 0, $bgColor );
// $res = imagecopyresampled(
$res = imagecopyresampled(
$newResource, // destination resource
$oldResource, // source resource
0, // destination x coord
0, // destination y coord
0, // source x coord
0, // source y coord
$width, // destination width
$height, // destination height
$width, // source witdh
$height // source height
);
if ( $res === false )
{
throw new ezcImageFilterFailedException( 'crop', 'Resampling of image failed.' );
}
imagedestroy( $oldResource );
$this->setReferenceData( $image, $newResource, 'resource' );
}
/**
* 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.
* @return void
*/
public function close( $image )
{
$res = $this->getReferenceData( $image, 'resource' );
if ( is_resource( $res ) )
{
imagedestroy( $res );
}
$this->closeCommon( $image );
}
/**
* Determine, the image types the available GD extension is able to process.
*
* @return void
*/
private function determineTypes()
{
$possibleTypes = array(
IMG_GIF => 'image/gif',
IMG_JPG => 'image/jpeg',
IMG_PNG => 'image/png',
IMG_WBMP => 'image/wbmp',
IMG_XPM => 'image/xpm',
);
$imageTypes = imagetypes();
foreach ( $possibleTypes as $bit => $mime )
{
if ( $imageTypes & $bit )
{
$this->inputTypes[] = $mime;
$this->outputTypes[] = $mime;
}
}
}
/**
* Generate imagecreatefrom* function out of a MIME type.
*
* @param string $mime MIME type in format "image/<type>".
* @return string imagecreatefrom* function name.
*
* @throws ezcImageMimeTypeUnsupportedException
* If the load function for a given MIME type does not exist.
*/
private function getLoadFunction( $mime )
{
if ( !$this->allowsInput( $mime ) )
{
throw new ezcImageMimeTypeUnsupportedException( $mime, 'input' );
}
return 'imagecreatefrom' . substr( strstr( $mime, '/' ), 1 );
}
/**
* Generate image* function out of a MIME type.
*
* @param string $mime MIME type in format "image/<type>".
* @return string image* function name for saving.
*
* @throws ezcImageImagemagickHandler
* If the save function for a given MIME type does not exist.
*/
private function getSaveFunction( $mime )
{
if ( !$this->allowsOutput( $mime ) )
{
throw new ezcImageMimeTypeUnsupportedException( $mime, 'output' );
}
return 'image' . substr( strstr( $mime, '/' ), 1 );
}
/**
* Creates default settings for the handler and returns it.
* The reference name will be set to 'GD'.
*
* @return ezcImageHandlerSettings
*/
static public function defaultSettings()
{
return new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' );
}
}
?>