EZ-Components

This commit is contained in:
Andreas Österreicher
2009-02-17 15:27:43 +00:00
parent 359c3c55c9
commit 0a8e90a8b3
572 changed files with 64490 additions and 0 deletions
@@ -0,0 +1,16 @@
CREDITS
=======
eZ Components team
------------------
- Sergey Alexeev
- Sebastian Bergmann
- Jan Borsodi
- Raymond Bosman
- Frederik Holljen
- Kore Nordmann
- Derick Rethans
- Vadym Savchuk
- Tobias Schlitt
- Alexandru Stanoi
@@ -0,0 +1,279 @@
1.3.5 - Monday 16 June 2008
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed issue #13134: Fixed array_splice() call in
ezcImageTransformation->addFilter().
1.3.4 - Monday 05 May 2008
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed issue #12592: New thumbnail filter. Documentation about the scale()
filter has been added to the thumbnail filters.
- Fixed issue #12667: ezcImageConverter doesn't pass saveOptions to
ezcImageTransformation.
- Fixed issue #12671: Unhandled exception in ezcImageTransformation. Checks to
avoid double throwing of exceptions have been introduced. Additional
parameter checks are performed.
1.3.3 - Monday 17 December 2007
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed issue #12166: Undefined attribute in ezcImageImagemagickBaseHandler.
1.3.2 - Wednesday 05 December 2007
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed issue #12126: ImageConversion test is incorrect.
- Fixed issue #12160: Conversion of transparent backgrounds does not work on
certain systems.
- Fixed issue #12171: Monochrome colorspace conversion does not work on some
systems with the ImageMagick handler.
1.3.1 - Wednesday 28 November 2007
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed issue #11029: Converting transparent PNG to JPG cause an strange
effect. A new option $transparencyReplacementColor has been introduced to
ezcImageSaveOptions, which will be utilized if a potentially tranparent
image is converted to a format that does not support a transparent
background.
1.3 - Monday 02 July 2007
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed issue #11030: The GD-Handler's watermarkPercent() calculates
incorrectly. The placement and size of the watermark are now calculated
correctly.
- Documentation updates and fixes.
1.3rc1 - Monday 25 June 2007
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed issue #10949: Rename PHP error if file already exists. If rename()
fails on Windows systems, the temporary files are cleaned up properly now.
- Documentation updates and fixes.
1.3beta2 - Thursday 31 May 2007
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed exception messages.
- Updated documentation for ezcImageThumbnailFilters.
1.3beta1 - Monday 07 May 2007
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Implemented feature #8589: JPEG quality transform for ImageConversion. A new
option class ezcImageSaveOptions supports setting a quality indicator for
JPEG and a compression indicator for PNG images.
- Implemented feature #9564: Watermark (and perhaps other filters) should
allow image placements from opposite corners. Crop filters support negative
offsets now, too.
1.2 - Monday 18 December 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed issue #9493: Convert < and > in exception messages to ' and ' for
Cache, ConsoleTools, ImageAnalysis, ImageConversion, PersistentObject,
PersistentObjectDatabaseSchemaTiein.
- Fixed issue #9520: ImageConversion test fails.
- Fixed issue #9521: Watermark tests needs some tuning.
- Fixed issue #9563: watermarkAbsolute filters requires width and height options.
- Fixed issue #9819: Let all components deal with the ezcBaseAutoloadException
properly.
1.2beta1 - Monday 20 November 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Added feature #9236: Added two new filters for adding watermarks to images.
- Fixed issue #8892: Handler / Converter destruction should remove all temp
files.
- Fixed issue #9012: Problems with open_basedir.
- Fixed issue #9013: SVG not detected in
ezcImageImagemagickBaseHandler::determineTypes().
- Fixed issue #9014: ezcImageTransformationException doesn't accept
ezcImageAnalyzerException as argument.
- Fixed issue #9440: GD scale/crop filters loose transparency.
1.1.2 - Monday 09 October 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed bug #8958: GD crop filter calculates width and height incorrect.
- Fixed bug #8959: GD and ImageMagick crop filters behave differently. The GD
driver now behaves like the ImageMagick driver and reduces the crop
dimensions, if they are larger than the source image dimensions.
1.1.1 - Monday 28 August 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed bug #8712: The x and y parameters for cropping where handled as
coordinates and not as offsets.
- Refactored to use new ezcBaseStruct and properties approach.
1.1 - Monday 12 June 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- No changes at all.
1.1rc1 - Monday 29 May 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- No changes at all.
1.1beta1 - Wednesday 19 April 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Added checks for file names that could cause potential security issues.
File names containing one of ', " or $ will be rejected to load/save with an
ezcImageFileNameInvalidException. (See
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=345238).
- Refactored internal filter handling to make ezcImageHandler classes
publically available.
- Fixed bug #8137: ImageConversion - ezcImageTransformation fails on
processing Multiple images in 1 request.
1.0.1 - Thursday 23 February 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed unreported bug: ezcImageTransformation::setFilters() threw old style
exceptions on an invalid filter class. Now throws the correct
ezcBaseSettingValueException.
- Added checks for file names that could cause potential security issues. File
names containing one of the three characters ' " or $ will be rejected to
load/save with an ezcImageFileNameInvalidException. (See
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=345238).
1.0 - Monday 30 January 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed unreported bug: ezcImageTransformation will cause an error, if no
filters are submitted, but only a MIME type conversion is set.
- Fixed unreported bug: ImageAnalysis and ImageConversion used different
MIME types for PSD files.
- Fixed unreported bug: Missing sanity checks for file existance and
reabability in ezcImageTransformation::transform().
1.0rc1 - Monday 16 January 2006
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Added more MIME types to ezcImageImagemagickHandler to be able to
transform more formats.
- Added option for ezcImageImagemagickHandler to allow the explicit setting of
ImageMagick's "convert" binary.
- Changed exception behavior. All errors will now throw a different exception
class.
- Changed OS detection of ezcImageImagemagickHandler to better detect Windows
versions.
- Changed behavior of ezcImageGeometryFilters::scale() to its
original purpose. The scale() filter now allows scaling of images to fit
into a certain rectengular box. The former behavior is still available
throug the scaleExact() filter.
- Changed execution of ImageMagick binary from exec() to proc_open(). This
avoids nasty error output on the console if something fails. Errors from
STDERR are now caught and used in the thrown exception for analysis.
- Fixed bug #7640: "createTransformation aspect ratio scaling".
The ImageMagick driver now does correct scaling, maintaining aspect ratio.
- Fixed unreported bug, that $name attribute in ezcImageMethodcallHandler is
private, but accessed by it's derived classes for error reporting.
- Fixed unreported bug in crop filter code of ezcImageImagemagickHandler, that
caused the crop to always start at the coordinates 0, 0.
1.0beta2 - Friday 23 December 2005
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Added struct for ezcImageConverter settings: ezcImageConverterSettings.
- Added new method getIdentifier() to handler classes which returns
a lowercase version of the name. The convert class uses this instead of
lowercasing the name manually.
- Added ezcImageFilter struct to keep the filter name and
options. This replaces the associative arrays and separate parameters used
throughout the various classes (mostly ezcImageTransformation).
- Changed settings handling in ezcImageConverter to new struct
ezcImageConverterSettings.
- Changed ezcImageHandler objects to get their $name and $identifier in
their constructor.
- Changed ezcImageHandlers not to automagically find the correct class name for
a filter. Instead the ezcImageFilters object is now created by the specific
ezcImageHandler class.
- Changed functions to properties:
* ezcImageHandler::getName() to property 'name'.
* ezcImageHandler::getIdentifier() to property 'identifier'.
- Changed class names:
* ezcImageHandlerGd to ezcImageGdHandler.
* ezcImageHandlerShell to ezcImageShellHandler.
* ezcImageFiltersGd to ezcImageGdFilters.
* ezcImageFiltersShell to ezcImageShellFilters.
* ezcImageFiltersInterfaceEffect to ezcImageEffectFilters.
* ezcImageFiltersInterfaceGeomtry to ezcImageGeometryFilters.
* ezcImageFiltersInterfaceColorspace to ezcImageColorspaceFilters.
* ezcImageShellHandler to ezcImageImagemagickHandler.
* ezcImageShellFilters to ezcImageImagemagickFilters.
- Changed function names:
* ezcImageHandler::listFilters() to getFilterNames().
- Changed ezcImageTransformation::transform() to throw a catch-all exception
instead of all inherited ones. The catch-all exception stores the source
exception in it's 'parent' property.
- Changed visibility of filter handling classes to private.
The code for the filter handling needs to more work before
becoming public. Any references to the filter classes from public
classes are also removed. This marks the GD and Imagemagick handlers as
private.
- Changed ezcImageHandler::listFilters() to use the getFilters() method on
the filter object to get filter list.
- Changed the way on how handlers can be referenced. The class names which are
passed in ezcImageConverterSettings are now stored in the
ezcImageHandlerSettings class:
* Added a reference name setting which are used by the converter
and handler. This allows the developer to reference the handler
with a simple name.
* Add a settings array which can be used by the handler as configuration.
- Removed 'identifier' from ezcImageHandler and uses class name of handler
for lookup in ezcImageConverter::applyFilter().
- Removed generation from class names out of values in
ezcImageConverterSettings. Instead they should now pass the full class name
to the converter. This removes the need to prefix custom made handler
classes with ezcImageHandler.
- Removed all the special code from the abstract class ezcImageHandler and
added them to ezcImageMethodcallHandler. The main handler class is now much
cleaner and exposes less special functions and properties to the public.
* Updated GD and ImageMagick handlers to extends the new class.
- Fixed createTransformation() to return the transformation object.
1.0beta1 - Thursday 24 November 2005
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Initial release of this package.
@@ -0,0 +1 @@
ImageAnalysis: 1.1.3
@@ -0,0 +1,2 @@
A set of classes to apply different filters on images, such as colour changes,
resizing and special effects.
@@ -0,0 +1 @@
- Optimization of colorspace conversions in GD handler as described here http://lists.ez.no/pipermail/components/2005-December/000819.html.
Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.3.5: http://docutils.sourceforge.net/" />
<title>eZ publish Enterprise Component: ImageConversion, Design</title>
<link rel="stylesheet" href="default.css" type="text/css" />
</head>
<body>
<h1 class="title">eZ publish Enterprise Component: ImageConversion, Design</h1>
<div class="document" id="ez-publish-enterprise-component-imageconversion-design">
<div class="section" id="introduction">
<h1><a name="introduction">Introduction</a></h1>
<p>Find more info about the requirenments on which this design is based on in the
requirenments.txt.</p>
</div>
<div class="section" id="design-description">
<h1><a name="design-description">Design description</a></h1>
<div class="section" id="ezcimagemanager">
<h2><a name="ezcimagemanager">ezcImageManager</a></h2>
<p>The main class of the component is the ezcImageManager, which implements a
singleton pattern, because only 1 manager is needed for all actions performed.
The ezcImageManager dispatches the actions performed on images, holds the
ezcImageHandler's (which actually perform the actions) and manages / defines
the ezcImageTransformations which hold conversions and ezcImageFilter's.</p>
<p>Since 1 filter/conversion can be performed by several ezcImageHandler's, the
manager has a preference list, to determine, which ezcImageHandler to take for
a conversion.</p>
</div>
<div class="section" id="ezcimagehandler">
<h2><a name="ezcimagehandler">ezcImageHandler</a></h2>
<p>This interface defines how the abstraction class for an image handler looks
like. ezcImageHandler's utilize a given backend to perform conversion and
filtering (using ezcImageFilter's). A ezcImageHandler knows by hisself, which
filters he implements. The manager will ask it for supported filters to get an
overview, which filters exist.</p>
<p>To avoid reopening an image file for every operation the ezcImageHandler has
load()/save() methods. An image must be saved before another ezcImageHandler
can perform his actions on it.</p>
</div>
<div class="section" id="ezcimagefilter">
<h2><a name="ezcimagefilter">ezcImageFilter</a></h2>
<p>This class implements a storage container for filters to keep them better
consistant than an array could do. Filters are created by the ezcImageManager
or directly through a ezcImageHandler. An ezcImageFilter knows, to which
handler he belongs and dispatches itself to the right handler, when applied.</p>
</div>
<div class="section" id="ezcimagetransformation">
<h2><a name="ezcimagetransformation">ezcImageTransformation</a></h2>
<p>ezcImageTransformation's abstract MIME types to allow the easy combination of
conversions and filters which are necessary to get a desired image type.
For conversions only the target MIME type is necessary. Beside that,
ezcImageTransformation's have a reference, which either points to another ezcImageTransformation
or to the special reference __original__ which is the image itself.</p>
<p>If a ezcImageTransformation references another one, which does not exist, yet, it will
be created, too. This enables one to create a chain of ezcImageTransformation's which
will be processed.</p>
<p>ezcImageTransformation's will be created on the fly, when the user requests them and not
during startup of the manager. A created ezcImageTransformation will be cached in the
manager for possible later use. Same applies to the filters utilized by the
ezcImageTransformation.</p>
<div class="section" id="example-1">
<h3><a name="example-1">Example 1</a></h3>
<table border="1" class="table">
<colgroup>
<col width="49%" />
<col width="51%" />
</colgroup>
<tbody valign="top">
<tr><td>Transformation:</td>
<td>Preview</td>
</tr>
<tr><td>Reference:</td>
<td>__original__</td>
</tr>
<tr><td>MIME:</td>
<td><p class="first">image/JPEG</p>
<p class="last">image/PNG</p>
</td>
</tr>
<tr><td>Filters:</td>
<td>scale 400x400</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="example-2">
<h3><a name="example-2">Example 2</a></h3>
<table border="1" class="table">
<colgroup>
<col width="49%" />
<col width="51%" />
</colgroup>
<tbody valign="top">
<tr><td>Transformation:</td>
<td>Thumbnail</td>
</tr>
<tr><td>Reference:</td>
<td>Preview</td>
</tr>
<tr><td>MIME:</td>
<td><p class="first">image/JPEG</p>
<p class="last">image/PNG</p>
</td>
</tr>
<tr><td>Filters:</td>
<td><p class="first">scale 100x100</p>
<p class="last">colorspace grey</p>
</td>
</tr>
</tbody>
</table>
<p>Will scale down the image to 100x100 pixels and convert it to greyscale.</p>
</div>
<div class="section" id="example-3">
<h3><a name="example-3">Example 3</a></h3>
<table border="1" class="table">
<colgroup>
<col width="49%" />
<col width="51%" />
</colgroup>
<tbody valign="top">
<tr><td>Transformation:</td>
<td>OldPhotos</td>
</tr>
<tr><td>Reference:</td>
<td>original</td>
</tr>
<tr><td>MIME:</td>
<td>image/JPEG</td>
</tr>
<tr><td>Filters:</td>
<td><p class="first">colorspace grey</p>
<p class="last">border 3</p>
</td>
</tr>
</tbody>
</table>
<p>Will convert the inserted image to image/JPEG, reduce the colorspace to
greyscale and add a border of 3 pixel.</p>
<div class="section" id="l">
<h4><a name="l">^L</a></h4>
<p>Local Variables:
mode: rst
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
End:
vim: et syn=rst tw=78 wrap</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,218 @@
eZ publish Enterprise Component: ImageConversion, Design
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Introduction
============
Purpose of ImageConversion package
----------------------------------
The ImageConversion package will be utilized to convert existing images
in different ways:
- Conversion between MIME types (e.g. image/BMP -> image/JPEG,...)
- Resizing image files (e.g. scaling, cropping,...)
- Filtering image content (e.g. change of color pallet, add noise,...)
Current implementation
----------------------
Currently the described functionality is implemented utilizing the following
classes, inside the library lib/ezimage/:
eZImageManager
Controller for the other classes utilized in this library. Handles
configuration, dispatches the necessary action to the different classes.
eZImageHandler
Baseclass for image handlers. Provides common methods between image
handlers and defines a common API.
eZImageGDHandler
Image handler implementation for ext/GD2. Extends eZImageHandler.
eZImageShellHandler
Image handler implementation for Image Magick. Extends eZImageHandler.
General notes
-------------
The idea behind the design chosen for this class is definitly the right one,
but it could have been much more modulized to gain a more clean code layout
and more flexibillities. Beside that, the user interface seems pretty unclear
and needs some general revision.
Requirenments
=============
Design goals
------------
Several goals have to be kept in mind while re-designing the implemented
functionality:
- Do not reduce possibilities, but enhance them.
- Create a more clean user interface and enhance usabillity.
- Raise flexibillity regarding backends and filter definition.
- Keep the code fast.
Detailed requirenments
----------------------
The ImageConversion component allows to deal with quite complex image
conversions in an easy to use ways. Beside that it handles automatic
conversions, if necessary, like converting incoming image formats to a range
of range of wanted output formats. This paragraph tries to summarize, what
exactly has to be done by ImageConversion:
Conversion between image formats
In general, ImageConversion should be able to convert images between MIME
types utilizing it's backends. Conversions must be globally defineable to
allow forcing of conversions (like for GIF -> PNG). Since some image
formats have special cases, in which a conversion is not possible (like
animated GIF), it must be possible to define exceptions for conversion.
Beside the global conversion, it has to be possible, to convert images
explicitly. Format conversions can ba parameterized (like the compression
factor for JPEG, the colorpallet for GIF,...). The conversions possible
depend on the image handlers available.
Filtering of image contents
Filtering of images can have a lot of incarnation in this case:
Geometry manipulation
down/up only, keep/change ratio, with/height only,...
Attribute manipulation (was: colorspace)
transform color space, change quality,...
Content manipulation
adding noise, swirrling, adding borders...
Which filters are available depends highly on the available image
handlers, their version and maybe other factors in respect to them (PHP
version,...).
Every filter can have a variaty of options and settings to influence its
behaviour. Options and settings maybe completly different between filters.
Definition of image formats
To reduce the overhead of manually defining, which filters have to be
applied to an image to achieve a certain goal (like "create a
thumbnail", "create a preview", "make it look like an old photo",...), the
definition of different image formats should be allowed. A format
definition can include all of the above stated transformations.
Beside that, it has to be possible to define, that a format is based on
another format (like a thumbnail should be created from a preview, to
reduce conversion ammount). If a format references another format, this
reference format will be created first (if it does not exist) and
conversion to the target format will take place afterwards. This allows to
define a tree of format conversions. Every node of the tree should be
saved for later utilization.
Currently, this formats are called aliases.
Design
======
ezcImageConverter
-----------------
The main class of the component is the ezcImageConverter, which dispatches the
actions performed on images, holds the ezcImageHandler's (which actually perform
the actions) and manages / defines the ezcImageTransformations which hold
conversions and filters.
Since 1 filter/conversion can be performed by several ezcImageHandler's, the
manager has a preference list, to determine, which ezcImageHandler to take for
a conversion.
ezcImageHandler
---------------
This interface defines how the abstraction class for an image handler looks
like. ezcImageHandler's utilize a given backend to perform conversion and
filtering (using ezcImageFilter's). A ezcImageHandler knows by hisself, which
filters he implements. The manager will ask it for supported filters to get an
overview, which filters exist.
To avoid reopening an image file for every operation the ezcImageHandler has
load()/save() methods. An image must be saved before another ezcImageHandler
can perform his actions on it.
ezcImageFilters
---------------
[[[------UPDATE NEEDED HERE!--------]]]
This class implements a storage container for filters to keep them better
consistant than an array could do. Filters are created by the ezcImageManager
or directly through a ezcImageHandler. An ezcImageFilter knows, to which
handler he belongs and dispatches itself to the right handler, when applied.
ezcImageTransformation
----------------------
ezcImageTransformation's abstract image types to allow the easy combination of
conversions between MIME types and filters which are necessary to get a desired image type.
For conversions only the target MIME type is necessary.
ezcImageTransformation's will be created on the fly, when the user requests them and not
during startup of the manager. A created ezcImageTransformation will be cached in the
manager for possible later use. Same applies to the filters utilized by the
ezcImageTransformation.
Example 1
^^^^^^^^^
====================== =======================
Transformation: Preview
MIME: image/JPEG
image/PNG
Filters: scale 400x400
====================== =======================
Example 2
^^^^^^^^^
====================== =======================
Transformation: Thumbnail
MIME: image/JPEG
image/PNG
Filters: scale 100x100
colorspace grey
====================== =======================
Will scale down the image to 100x100 pixels and convert it to greyscale.
Example 3
^^^^^^^^^
====================== =======================
Transformation: OldPhotos
MIME: image/JPEG
Filters: colorspace grey
border 3
====================== =======================
Will convert the inserted image to image/JPEG, reduce the colorspace to
greyscale and add a border of 3 pixel.
^L
..
Local Variables:
mode: rst
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 79
End:
vim: et syn=rst tw=79 wrap
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@@ -0,0 +1,66 @@
<?php
/**
* General example for the ImageConversion component.
*
* @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
*/
require_once 'Base/src/base.php';
/**
* Autoload ezc classes
*
* @param string $className
*/
function __autoload( $className )
{
ezcBase::autoload( $className );
}
// Prepare settings for ezcImageConverter
// Defines the handlers to utilize and auto conversions.
$settings = new ezcImageConverterSettings(
array(
new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
),
array(
'image/gif' => 'image/png',
'image/bmp' => 'image/jpeg',
)
);
// Create the converter itself.
$converter = new ezcImageConverter( $settings );
// Define a transformation
$filters = array(
new ezcImageFilter(
'scaleWidth',
array(
'width' => 100,
'direction' => ezcImageGeometryFilters::SCALE_BOTH,
)
),
new ezcImageFilter(
'colorspace',
array(
'space' => ezcImageColorspaceFilters::COLORSPACE_GREY,
)
),
);
// Which MIME types the conversion may output
$mimeTypes = array( 'image/jpeg', 'image/png' );
// Create the transformation inside the manager
$converter->createTransformation( 'thumbnail', $filters, $mimeTypes );
// Transform an image.
$converter->transform( 'thumbnail', dirname( __FILE__ ). '/jpeg.jpg', dirname( __FILE__ ). '/jpeg_thumb.jpg' );
echo 'Succesfully converted <'. dirname( __FILE__ ). '/jpeg.jpg> to <'.dirname( __FILE__ ). '/jpeg_thumb.jpg'.">\n";
?>
@@ -0,0 +1,90 @@
<?php
/**
* General example for the ImageConversion component.
*
* @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
*/
require_once 'Base/src/base.php';
/**
* Autoload ezc classes
*
* @param string $className
*/
function __autoload( $className )
{
ezcBase::autoload( $className );
}
function getImageConverterInstance()
{
if ( !isset( $GLOBALS['_ezcImageConverterInstance'] ) )
{
// Prepare settings for ezcImageConverter
// Defines the handlers to utilize and auto conversions.
$settings = new ezcImageConverterSettings(
array(
new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
),
array(
'image/gif' => 'image/png',
'image/bmp' => 'image/jpeg',
)
);
// Create the converter itself.
$converter = new ezcImageConverter( $settings );
// Define a transformation
$filters = array(
new ezcImageFilter(
'scale',
array(
'width' => 100,
'height' => 300,
'direction' => ezcImageGeometryFilters::SCALE_BOTH,
)
),
new ezcImageFilter(
'colorspace',
array(
'space' => ezcImageColorspaceFilters::COLORSPACE_SEPIA,
)
),
new ezcImageFilter(
'border',
array(
'width' => 5,
'color' => array( 255, 0, 0 ),
)
),
);
// Which MIME types the conversion may output
$mimeTypes = array( 'image/jpeg', 'image/png' );
// Create the transformation inside the manager
$converter->createTransformation( 'funny', $filters, $mimeTypes );
// Assign singleton instance
$GLOBALS['_ezcImageConverterInstance'] = $converter;
}
// Return singleton instance
return $GLOBALS['_ezcImageConverterInstance'];
}
// ...
// Somewhere else in the code...
// Transform an image.
getImageConverterInstance()->transform( 'funny', dirname( __FILE__ ).'/jpeg.jpg', dirname( __FILE__ ). '/jpeg_singleton.jpg' );
echo 'Succesfully converted <'. dirname( __FILE__ ). '/jpeg.jpg> to <'. dirname( __FILE__ ). '/jpeg_singleton.jpg'.">\n";
?>
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

@@ -0,0 +1,243 @@
eZ Components - ImageConversion
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. contents:: Table of Contents
:depth: 2
Introduction
============
The ImageConversion component provides image manipulation tools. It
enables you to perform filter actions (such as scaling, changing the
colorspace, adding a swirl effect) and to convert between different MIME image
types. Filters and conversions are grouped as
"transformations", which can be globally configured and accessed from anywhere
in the application. Conversions and filters can be performed through different
handlers (currently supported are PHP's GD extension and the external ImageMagick
program). ImageConversion is capable of automatically selecting an appropriate
handler. You can also set handler priorities.
Class overview
==============
This section gives you an overview of the main classes.
ezcImageConverter
This is the main class that collects all transformations, communicates with
the handlers and applies filters and conversions.
ezcImageFilter
This class is used to represent the configuration of a filter.
ezcImageTransformation
A transformation can contain any number of filters. It also specifies which
output MIME types are acceptable for the transformation.
Usage
=====
Converting MIME types
---------------------
The following example creates a very simple transformation to convert any other
image type into JPEG:
.. include:: tutorial_example_01_simpleconvert.php
:literal:
First, the settings for ezcImageConverter are defined (lines 7 to 12) using
ezcImageConverterSettings. Whenever ezcImageConverter is
instantiated, it needs to know which handlers are available. The order in the
ezcImageHandlerSettings array defines the priority of the handlers. In this
case, ezcImageConverter will check if a given filter or conversion can be
performed by the GD handler. If not, it will check the ImageMagick handler. On
line 14, ezcImageConverter is instantiated using the defined settings.
Line 16 shows how a transformation is created. The first parameter to
ezcImageConverter::createTransformation() defines the name of the
transformation, while the second parameter would usually contain filters (which
are not used here). Instead, just one output MIME type is defined as the third
parameter. As a result, this transformation returns images of the type
"image/jpeg".
On lines 21 to 24, the transformation is applied. The first
parameter to ezcImageConverter::transform() contains the name of the
transformation to apply. The second one specifies the file to transform, while the
third one specifies the desired output filename. Aside from
exceptions of the type ezcBaseFileException, the ezcImageTransformation::transform()
method can only throw exceptions of the type ezcImageTransformationException, which
we catch here to print out an error message.
The input and output images are shown below:
=================== ====================
|example_01_before| |example_01_after|
BMP version (92k) Converted JPEG (24k)
=================== ====================
.. |example_01_before| image:: img/imageconversion_example_01_before.bmp
:alt: Original BMP (92k).
.. |example_01_after| image:: img/imageconversion_example_01_after.jpg
:alt: Converted JPEG (24k).
Simple filtering
----------------
The next example shows a transformation that, in addition to the converting to
JPEG, uses a filter to scale images:
.. include:: tutorial_example_02_simpletrans.php
:literal:
After instantiating ezcImageConverter, we define the filters to apply. We apply
only one filter in this example. Each filter definition must be an instance of
ezcImageFilter. The first parameter to the constructor of ezcImageFilter
(ezcImageFilter::__construct()) is the name of the filter to use. The second
parameter is an array of settings for the filter. The filter name must
correspond to a method name for one of the filter interfaces:
- ezcImageGeometryFilters
- ezcImageColorspaceFilters
- ezcImageEffectFilters
The settings array must contain all parameters that the specific filter method
expects and the array keys must correspond to the names of the
parameters. For example, the scale filter used here is defined in
ezcImageGeometryFilters::scale(). The available image handlers support the
following filters:
- ezcImageGdFilters
* ezcImageGeometryFilters
* ezcImageColorspaceFilters
- ezcImageImagemagickFilters
* ezcImageGeometryFilters
* ezcImageColorspaceFilters
* ezcImageEffectFilters
The filter definition shown here makes ezcImageConverter scale images to a box
of 320x240 pixels. Images will only be scaled if they are larger than the
given size, but not if they are already smaller or fit exactly.
The rest of the example is pretty much the same as example 1. To keep the
example images web-friendly, we use a JPEG image as the source file here:
Original image (450x246)
++++++++++++++++++++++++
.. image:: img/imageconversion_example_02_before.jpg
:alt: Original JPEG image.
Converted image (320x175)
+++++++++++++++++++++++++
.. image:: img/imageconversion_example_02_after.jpg
:alt: Converted JPEG image.
Complex transformations
-----------------------
The next example shows a more advanced transformation and some other features:
.. include:: tutorial_example_03_complextrans.php
:literal:
In this example, there is a second parameter to the constructor of
ezcImageConverterSettings::__construct(), which defines explicit conversions
between MIME types (line 13). In this case, we define that GIF images should be
converted to PNG. When the transformation takes place, it will first check if an
explicit conversion has been defined for the input MIME type. If this is the
case, the explicit conversion will be performed. If not, the first available
output MIME type will be chosen. Note that you have to add the new MIME output
type "image/png" to the allowed output types of the transformation (see line
43).
In the transformation definition we define 3 filters. Note that the
order of filters is important here. The first filter is "scale" again,
after which the colorspace of the image is reduced to greyscale. The last
filter adds a 5-pixel border with a near-white grey value to the image.
For this web tutorial, a JPEG image is once again used as the source:
Original image (400x300):
+++++++++++++++++++++++++
.. image:: img/imageconversion_example_03_before.jpg
:alt: Original JPEG image.
Converted image (330x250):
++++++++++++++++++++++++++
.. image:: img/imageconversion_example_03_after.jpg
:alt: Converted JPEG image.
.. _`downloaded here`: img/imageconversion_example_03.bmp
Adding watermarks
-----------------
A very convenient filter is the watermark filter, which allows you to place a
your personal sign onto an image to ensure your copyright being kept:
.. include:: tutorial_example_04_watermark.php
:literal:
This code snippet creates a simple transformation to place the watermark. The
'image' parameter contains the path to the watermark image, while posX and posY
define, where the watermark will be placed on the converted image. The
positions are defined from the bottom left corner, so in this case therer will
be 10 pixel left between the watermark and the image border.
Original image (without watermark):
+++++++++++++++++++++++++++++++++++
.. image:: img/imageconversion_example_04_before.jpg
:alt: Original JPEG image without watermark.
Converted image (with watermark):
+++++++++++++++++++++++++++++++++
.. image:: img/imageconversion_example_04_after.jpg
:alt: Converted JPEG image with watermark.
It is also possible to get the size of the watermark image adjusted on the fly
and a second filter is available, which allows to define all values as
percentage values, in respect to the destination image.
Creating thumbnails
-------------------
The following example shows how to create a thumbnail from an image very
easily:
.. include:: tutorial_example_05_thumbnail.php
:literal:
While there is also a 'croppedThumbnail' filter available, which croppes
overhead from the scaled image, this filter fills the overhead from scaling
with the given fill color. The image is automatically scaled down to fit the
given thumbnail size.
Original image (original size):
+++++++++++++++++++++++++++++++
.. image:: img/imageconversion_example_05_before.jpg
:alt: Original JPEG image without watermark.
Converted image (thumbnail):
++++++++++++++++++++++++++++
.. image:: img/imageconversion_example_05_after.jpg
:alt: Converted JPEG image with watermark.
..
Local Variables:
mode: rst
fill-column: 79
End:
vim: et syn=rst tw=79
@@ -0,0 +1,20 @@
<?php
$dir = dirname( __FILE__ );
$dirParts = explode( '/', $dir );
switch ( $dirParts[count( $dirParts ) - 3] )
{
case 'doc': require_once 'ezc/Base/base.php'; break; // pear
case 'trunk': require_once "$dir/../../Base/src/base.php"; break; // svn
default: require_once "$dir/../../Base/src/base.php"; break; // bundle
}
/**
* Autoload ezc classes
*
* @param string $className
*/
function __autoload( $className )
{
ezcBase::autoload( $className );
}
?>
@@ -0,0 +1,32 @@
<?php
require_once 'tutorial_autoload.php';
$tutorialPath = dirname( __FILE__ );
$settings = new ezcImageConverterSettings(
array(
new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
)
);
$converter = new ezcImageConverter( $settings );
$converter->createTransformation( 'jpeg', array(), array( 'image/jpeg' ) );
try
{
$converter->transform(
'jpeg',
$tutorialPath.'/img/imageconversion_example_01_before.bmp',
$tutorialPath.'/img/imageconversion_example_01_after.jpg'
);
}
catch ( ezcImageTransformationException $e)
{
die( "Error transforming the image: <{$e->getMessage()}>" );
}
?>
@@ -0,0 +1,42 @@
<?php
require_once 'tutorial_autoload.php';
$tutorialPath = dirname( __FILE__ );
$settings = new ezcImageConverterSettings(
array(
new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
)
);
$converter = new ezcImageConverter( $settings );
$filters = array(
new ezcImageFilter(
'scale',
array(
'width' => 320,
'height' => 240,
'direction' => ezcImageGeometryFilters::SCALE_DOWN,
)
),
);
$converter->createTransformation( 'preview', $filters, array( 'image/jpeg' ) );
try
{
$converter->transform(
'preview',
$tutorialPath.'/img/imageconversion_example_02_before.jpg',
$tutorialPath.'/img/imageconversion_example_02_after.jpg'
);
}
catch ( ezcImageTransformationException $e)
{
die( "Error transforming the image: <{$e->getMessage()}>" );
}
?>
@@ -0,0 +1,58 @@
<?php
require_once 'tutorial_autoload.php';
$tutorialPath = dirname( __FILE__ );
$settings = new ezcImageConverterSettings(
array(
new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
),
array(
'image/gif' => 'image/png',
)
);
$converter = new ezcImageConverter( $settings );
$filters = array(
new ezcImageFilter(
'scale',
array(
'width' => 320,
'height' => 240,
'direction' => ezcImageGeometryFilters::SCALE_DOWN,
)
),
new ezcImageFilter(
'colorspace',
array(
'space' => ezcImageColorspaceFilters::COLORSPACE_GREY,
)
),
new ezcImageFilter(
'border',
array(
'width' => 5,
'color' => array( 240, 240, 240 ),
)
),
);
$converter->createTransformation( 'oldphoto', $filters, array( 'image/jpeg', 'image/png' ) );
try
{
$converter->transform(
'oldphoto',
$tutorialPath.'/img/imageconversion_example_03_before.jpg',
$tutorialPath.'/img/imageconversion_example_03_after.jpg'
);
}
catch ( ezcImageTransformationException $e)
{
die( "Error transforming the image: <{$e->getMessage()}>" );
}
?>
@@ -0,0 +1,45 @@
<?php
require_once 'tutorial_autoload.php';
$tutorialPath = dirname( __FILE__ );
$settings = new ezcImageConverterSettings(
array(
new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
),
array(
'image/gif' => 'image/png',
)
);
$converter = new ezcImageConverter( $settings );
$filters = array(
new ezcImageFilter(
'watermarkAbsolute',
array(
'image' => $tutorialPath . '/img/watermark.png',
'posX' => -52,
'posY' => -25,
)
)
);
$converter->createTransformation( 'watermark', $filters, array( 'image/jpeg', 'image/png' ) );
try
{
$converter->transform(
'watermark',
$tutorialPath.'/img/imageconversion_example_04_before.jpg',
$tutorialPath.'/img/imageconversion_example_04_after.jpg'
);
}
catch ( ezcImageTransformationException $e)
{
die( "Error transforming the image: <{$e->getMessage()}>" );
}
?>
@@ -0,0 +1,49 @@
<?php
require_once 'tutorial_autoload.php';
$tutorialPath = dirname( __FILE__ );
$settings = new ezcImageConverterSettings(
array(
new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
),
array(
'image/gif' => 'image/png',
)
);
$converter = new ezcImageConverter( $settings );
$filters = array(
new ezcImageFilter(
'filledThumbnail',
array(
'width' => 100,
'height' => 100,
'color' => array(
200,
200,
200,
),
)
)
);
$converter->createTransformation( 'thumbnail', $filters, array( 'image/jpeg', 'image/png' ) );
try
{
$converter->transform(
'thumbnail',
$tutorialPath.'/img/imageconversion_example_05_before.jpg',
$tutorialPath.'/img/imageconversion_example_05_after.jpg'
);
}
catch ( ezcImageTransformationException $e)
{
die( "Error transforming the image: <{$e->getMessage()}>" );
}
?>
@@ -0,0 +1,4 @@
[X] The class documentation for ezcImageFilter should mention (in the ctor)
where the names of the different filters can be found. Perhaps we
should add a list of all supported filters somewhere.
[X] Code coverage is pretty low, only 85%.
@@ -0,0 +1,527 @@
<?php
/**
* File containing the ezcImageConverter class.
*
* @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
*/
/**
* Class to manage conversion and filtering of image files.
* This class is highly recommended to be used with an external
* singleton pattern to have just 1 converter in place over the whole
* application.
*
* As back-ends 2 handler classes are available, of which at least 1 has to be
* configured during the instantiation of the ezcImageConverter. Both handlers
* utilize different image manipulation tools and are capable of different
* sets of filters:
*
* <ul>
* <li>ezcImageGdHandler
* <ul>
* <li>Uses PHP's GD extension for image manipulation.</li>
* <li>Implements the following filter interfaces
* <ul>
* <li>{@link ezcImageGeometryFilters}</li>
* <li>{@link ezcImageColorspaceFilters}</li>
* </ul>
* </li>
* </ul>
* </li>
* <li>ezcImageImagemagickHandler
* <ul>
* <li>Uses the external "convert" program, contained in ImageMagick</li>
* <li>Implements the following interfaces:
* <ul>
* <li>{@link ezcImageGeometryFilters}</li>
* <li>{@link ezcImageColorspaceFilters}</li>
* <li>{@link ezcImageEffectFilters}</li>
* </ul>
* </li>
* </ul>
* </li>
* </ul>
*
* A general example, how to use ezcImageConversion to convert images:
* <code>
* // Prepare settings for ezcImageConverter
* // Defines the handlers to utilize and auto conversions.
* $settings = new ezcImageConverterSettings(
* array(
* new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
* new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
* ),
* array(
* 'image/gif' => 'image/png',
* 'image/bmp' => 'image/jpeg',
* )
* );
*
* // Create the converter itself.
* $converter = new ezcImageConverter( $settings );
*
* // Define a transformation
* $filters = array(
* new ezcImageFilter(
* 'scaleWidth',
* array(
* 'width' => 100,
* 'direction' => ezcImageGeometryFilters::SCALE_BOTH,
* )
* ),
* new ezcImageFilter(
* 'colorspace',
* array(
* 'space' => ezcImageColorspaceFilters::COLORSPACE_GREY,
* )
* ),
* );
*
* // Which MIME types the conversion may output
* $mimeTypes = array( 'image/jpeg', 'image/png' );
*
* // Create the transformation inside the manager
* $converter->createTransformation( 'thumbnail', $filters, $mimeTypes );
*
* // Transform an image.
* $converter->transform( 'thumbnail', dirname(__FILE__).'/jpeg.jpg', dirname(__FILE__).'/jpeg_thumb.jpg' );
* </code>
*
* It's recommended to create only a single ezcImageConverter instance in your
* application to avoid creating multiple instances of it's internal objects.
* You can implement a singleton pattern for this, which might look similar to
* the following example:
* <code>
* function getImageConverterInstance()
* {
* if ( !isset( $GLOBALS['_ezcImageConverterInstance'] ) )
* {
* // Prepare settings for ezcImageConverter
* // Defines the handlers to utilize and auto conversions.
* $settings = new ezcImageConverterSettings(
* array(
* new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
* new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' ),
* ),
* array(
* 'image/gif' => 'image/png',
* 'image/bmp' => 'image/jpeg',
* )
* );
*
*
* // Create the converter itself.
* $converter = new ezcImageConverter( $settings );
*
* // Define a transformation
* $filters = array(
* new ezcImageFilter(
* 'scale',
* array(
* 'width' => 100,
* 'height' => 300,
* 'direction' => ezcImageGeometryFilters::SCALE_BOTH,
* )
* ),
* new ezcImageFilter(
* 'colorspace',
* array(
* 'space' => ezcImageColorspaceFilters::COLORSPACE_SEPIA,
* )
* ),
* new ezcImageFilter(
* 'border',
* array(
* 'width' => 5,
* 'color' => array(255, 0, 0),
* )
* ),
* );
*
* // Which MIME types the conversion may output
* $mimeTypes = array( 'image/jpeg', 'image/png' );
*
* // Create the transformation inside the manager
* $converter->createTransformation( 'funny', $filters, $mimeTypes );
*
* // Assign singleton instance
* $GLOBALS['_ezcImageConverterInstance'] = $converter;
* }
*
* // Return singleton instance
* return $GLOBALS['_ezcImageConverterInstance'];
* }
*
* // ...
* // Somewhere else in the code...
* // Transform an image.
* getImageConverterInstance()->transform( 'funny', dirname(__FILE__).'/jpeg.jpg', dirname(__FILE__).'/jpeg_singleton.jpg' );
*
* </code>
*
* @see ezcImageHandler
* @see ezcImageTransformation
*
* @package ImageConversion
* @version 1.3.5
* @mainclass
*/
class ezcImageConverter
{
/**
* Manager settings
* Settings basis for all image manipulations.
*
* @var ezcImageConverterSettings
*/
protected $settings;
/**
* Keeps the handlers used by the converter.
*
* @var array(ezcImageHandler)
*/
protected $handlers = array();
/**
* Stores transformation registered with this converter.
*
* @var array
*/
protected $transformations = array();
/**
* Initialize converter with settings object.
* The ezcImageConverter can be directly instantiated, but it's
* highly recommended to use a manual singleton implementation
* to have just 1 instance of a ezcImageConverter per Request.
*
* ATTENTION: The ezcImageConverter does not support animated
* GIFs. Animated GIFs will simply be ignored by all filters and
* conversions.
*
* @param ezcImageConverterSettings $settings Settings for the converter.
*
* @throws ezcImageHandlerSettingsInvalidException
* If handler settings are invalid.
* @throws ezcImageMimeTypeUnsupportedException
* If a given MIME type is not supported.
*/
public function __construct( ezcImageConverterSettings $settings )
{
// Initialize handlers
foreach ( $settings->handlers as $i => $handlerSettings )
{
if ( !$handlerSettings instanceof ezcImageHandlerSettings )
{
throw new ezcImageHandlerSettingsInvalidException();
}
$handlerClass = $handlerSettings->className;
if ( !ezcBaseFeatures::classExists( $handlerClass ) )
{
throw new ezcImageHandlerNotAvailableException( $handlerClass );
}
$handler = new $handlerClass( $handlerSettings );
$this->handlers[$handlerSettings->referenceName] = $handler;
}
// Check implicit conversions
foreach ( $settings->conversions as $mimeIn => $mimeOut )
{
if ( !$this->allowsInput( $mimeIn ) )
{
throw new ezcImageMimeTypeUnsupportedException( $mimeIn, 'input' );
}
if ( !$this->allowsOutput( $mimeOut ) )
{
throw new ezcImageMimeTypeUnsupportedException( $mimeOut, 'output' );
}
}
$this->settings = $settings;
}
/**
* Create a transformation in the manager.
*
* Creates a transformation and stores it in the manager. A reference to the
* transformation is returned by this method for further manipulation and
* to set options on it. The $name can later be used to remove a
* transfromation using {@link removeTransformation()} or to execute it
* using {@link transform()}. The $filters and $mimeOut parameters specify
* the transformation actions as described with {@link
* ezcImageTransformation::__construct()}. The $saveOptions are used when
* the finally created image is saved and can configure compression and
* quality options.
*
* @param string $name Name for the transformation.
* @param array(ezcImageFilter) $filters Filters.
* @param array(string) $mimeOut Output MIME types.
* @param ezcImageSaveOptions $saveOptions Save options.
*
* @return ezcImageTransformation
*
* @throws ezcImageFiltersException
* If a given filter does not exist.
* @throws ezcImageTransformationAlreadyExists
* If a transformation with the given name does already exist.
*/
public function createTransformation( $name, array $filters, array $mimeOut, ezcImageSaveOptions $saveOptions = null )
{
if ( isset( $this->transformations[$name] ) )
{
throw new ezcImageTransformationAlreadyExistsException( $name );
}
$this->transformations[$name] = new ezcImageTransformation( $this, $name, $filters, $mimeOut, $saveOptions );
return $this->transformations[$name];
}
/**
* Removes a transformation from the manager.
*
* @param string $name Name of the transformation to remove
*
* @return ezcImageTransformation The removed transformation
*
* @throws ezcImageTransformationNotAvailableExeption
* If the requested transformation is unknown.
*/
public function removeTransformation( $name )
{
if ( !isset( $this->transformations[$name] ) )
{
throw new ezcImageTransformationNotAvailableException( $name );
}
unset( $this->transformations[$name] );
}
/**
* Apply transformation on a file.
* This applies the given transformation to the given file.
*
* @param string $name Name of the transformation to perform
* @param string $inFile The file to transform
* @param string $outFile The file to save transformed version to
*
* @throws ezcImageTransformationNotAvailableExeption
* If the requested transformation is unknown.
* @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( $name, $inFile, $outFile )
{
if ( !isset( $this->transformations[$name] ) )
{
throw new ezcImageTransformationNotAvailableException( $name );
}
$this->transformations[$name]->transform( $inFile, $outFile );
}
/**
* Returns if a handler is found, supporting the given MIME type for output.
*
* @param string $mime The MIME type to check for.
* @return bool Whether the MIME type is supported.
*/
public function allowsInput( $mime )
{
foreach ( $this->handlers as $handler )
{
if ( $handler->allowsInput( $mime ) )
{
return true;
}
}
return false;
}
/**
* Returns if a handler is found, supporting the given MIME type for output.
*
* @param string $mime The MIME type to check for.
* @return bool Whether the MIME type is supported.
*/
public function allowsOutput( $mime )
{
foreach ( $this->handlers as $handler )
{
if ( $handler->allowsOutput( $mime ) )
{
return true;
}
}
return false;
}
/**
* Returns the MIME type that will be outputted for a given input type.
* Checks whether the given input type can be processed. If not, an
* exception is thrown. Checks then, if an implicit conversion for that
* MIME type is defined. If so, outputs the given output MIME type. In
* every other case, just outputs the MIME type given, because no
* conversion is implicitly required.
*
* @param string $mimeIn Input MIME type.
* @return string Output MIME type.
*
* @throws ezcImageMimeTypeUnsupportedException
* If the input MIME type is not supported.
*/
public function getMimeOut( $mimeIn )
{
if ( $this->allowsInput( $mimeIn ) === false )
{
throw new ezcImageMimeTypeUnsupportedException( $mimeIn, 'input' );
}
if ( isset( $this->settings->conversions[$mimeIn] ) )
{
return $this->settings->conversions[$mimeIn];
}
return $mimeIn;
}
/**
* Returns if a given filter is available.
* Returns either an array of handler names this filter
* is available in or false if the filter is not enabled.
*
* @param string $name Name of the filter to query existance for
*
* @return mixed Array of handlers on success, otherwise false.
*/
public function hasFilter( $name )
{
foreach ( $this->handlers as $handler )
{
if ( $handler->hasFilter( $name ) )
{
return true;
}
}
return false;
}
/**
* Returns a list of enabled filters.
* Gives you an overview on filters enabled in the manager.
* Format is:
* <code>
* array(
* '<filterName>',
* );
* </code>
*
* @return array(string)
*/
public function getFilterNames()
{
$filters = array();
foreach ( $this->handlers as $handler )
{
$filters = array_merge( $filters, $handler->getFilterNames() );
}
return array_unique( $filters );
}
/**
* Apply a single filter to an image.
* Applies just a single filter to an image. Optionally you can select
* a handler yourself, which is not recommended, but possible. If the
* specific handler does not have that filter, ImageConverter will try
* to fall back on another handler.
*
* @param ezcImageFilter $filter Filter object to apply.
* @param string $inFile Name of the input file.
* @param string $outFile Name of the output file.
* @param string $handlerName
* To choose a specific handler, this is the reference named passed
* to {@link ezcImageHandlerSettings}.
* @return void
*
*
* @throws ezcImageHandlerNotAvailableException
* If fitting handler is not available.
* @throws ezcImageFilterNotAvailableException
* If filter is not available.
* @throws ezcImageFileNameInvalidException
* If an invalid character (", ', $) is found in the file name.
*/
public function applyFilter( ezcImageFilter $filter, $inFile, $outFile, $handlerName = null )
{
$handlerObj = false;
// Do we have an explicit handler given?
if ( $handlerName !== null )
{
if ( !isset( $this->handlers[$handlerName] ) )
{
throw new ezcImageHandlerNotAvailableException( $handlerName );
}
if ( $this->handlers[$handlerName]->hasFilter( $filter->name ) === true )
{
$handlerObj = $this->handlers[$handlerName];
}
}
// Either no handler explicitly given or try to fall back.
if ( $handlerObj === false )
{
foreach ( $this->handlers as $regHandler )
{
if ( $regHandler->hasFilter( $filter->name ) )
{
$handlerObj = $regHandler;
break;
}
}
}
// No handler found to apply filter with.
if ( $handlerObj === false )
{
throw new ezcImageFilterNotAvailableException( $filter->name );
}
$imgRef = $handlerObj->load( $inFile );
$handlerObj->applyFilter( $imgRef, $filter );
$handlerObj->save( $imgRef, $outFile );
}
/**
* Returns a handler object for direct use.
* Returns the handler with the highest priority, that supports the given
* filter, MIME input type and MIME output type. All parameters are
* optional, if none is specified, the highest prioritized handler is
* returned.
*
* If no handler is found, that supports the criteria named, an exception
* of type {@link ezcImageHandlerNotAvailableException} will be thrown.
*
* @param string $filterName Name of the filter to search for.
* @param string $mimeIn Input MIME type.
* @param string $mimeOut Output MIME type.
*
* @return ezcImageHandler
*
* @throws ezcImageHandlerNotAvailableException
* If a handler for the given specification could not be found.
*/
public function getHandler( $filterName = null, $mimeIn = null, $mimeOut = null )
{
foreach ( $this->handlers as $handler )
{
if ( ( !isset( $filterName ) || $handler->hasFilter( $filterName ) )
&& ( !isset( $mimeIn ) || $handler->allowsInput( $mimeIn ) )
&& ( !isset( $mimeOut ) || $handler->allowsOutput( $mimeOut ) )
)
{
return $handler;
}
}
throw new ezcImageHandlerNotAvailableException( 'unknown' );
}
}
?>
@@ -0,0 +1,20 @@
<?php
/**
* Base exception for the ImageConversion package.
*
* @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
*/
/**
* General exception container for the ImageConversion component.
*
* @package ImageConversion
* @version 1.3.5
*/
abstract class ezcImageException extends ezcBaseException
{
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcImageFileNameInvalidException.
*
* @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
*/
/**
* Thrown if a given file name contains illegal characters (', ", $).
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageFileNameInvalidException extends ezcImageException
{
/**
* Creates a new ezcImageFileNameInvalidException.
*
* @param string $file The invalid file name.
* @return void
*/
function __construct( $file )
{
parent::__construct( "The file name '{$file}' contains an illegal character (', \", $)." );
}
}
?>
@@ -0,0 +1,37 @@
<?php
/**
* File containing the ezcImageFileNotProcessableException.
*
* @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
*/
/**
* Thrown if a file could not be processed by a handler.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageFileNotProcessableException extends ezcImageException
{
/**
* Creates a new ezcImageFileNotProcessableException.
*
* @param string $file The not processable file.
* @param string $reason The reason why the file could not be processed.
* @return void
*/
function __construct( $file, $reason = null )
{
$reasonPart = "";
if ( $reason )
{
$reasonPart = " $reason";
}
parent::__construct( "File '{$file}' could not be processed.{$reasonPart}" );
}
}
?>
@@ -0,0 +1,37 @@
<?php
/**
* File containing the ezcImageFilterFailedException.
*
* @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
*/
/**
* Thrown if the given filter failed.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageFilterFailedException extends ezcImageException
{
/**
* Creates a new ezcImageFilterFailedException.
*
* @param string $filterName The failed filter.
* @param string $reason The reason why the filter failed.
* @return void
*/
function __construct( $filterName, $reason = null )
{
$reasonPart = "";
if ( $reason )
{
$reasonPart = " $reason";
}
parent::__construct( "The filter '{$filterName}' failed.{$reasonPart}" );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcImageFilterNotAvailableException.
*
* @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
*/
/**
* Thrown if the given filter is not available.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageFilterNotAvailableException extends ezcImageException
{
/**
* Creates a new ezcImageFilterNotAvailableException.
*
* @param string $filterName The affected filter.
* @return void
*/
function __construct( $filterName )
{
parent::__construct( "Filter '{$filterName}' does not exist." );
}
}
?>
@@ -0,0 +1,37 @@
<?php
/**
* File containing the ezcImageHandlerNotAvailableException.
*
* @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
*/
/**
* Thrown if a specified handler class is not available.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageHandlerNotAvailableException extends ezcImageException
{
/**
* Creates a new ezcImageHandlerNotAvailableException.
*
* @param string $handlerClass Name of the affected class.
* @param string $reason Reason why it is not available.
* @return void
*/
function __construct( $handlerClass, $reason = null )
{
$reasonPart = "";
if ( $reason )
{
$reasonPart = " $reason";
}
parent::__construct( "Handler class '{$handlerClass}' not found.{$reasonPart}" );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcImageHandlerSettingsInvalidException.
*
* @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
*/
/**
* Thrown if invalid handler settings are submitted when creating an
* {@link ezcImageConverter}.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageHandlerSettingsInvalidException extends ezcImageException
{
/**
* Creates a new ezcImageHandlerSettingsInvalidException.
*
* @return void
*/
function __construct()
{
parent::__construct( "Invalid handler settings." );
}
}
?>
@@ -0,0 +1,40 @@
<?php
/**
* File containing the ezcImageInvalidFilterParameterException.
*
* @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
*/
/**
* Thrown if the given filter failed.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageInvalidFilterParameterException extends ezcImageException
{
/**
* Creates a new ezcImageInvalidFilterParameterException.
*
* @param string $filterName Name of the filter.
* @param string $parameterName Affected parameter.
* @param string $actualValue Received value.
* @param string $expectedRange Expected value range.
* @return void
*/
function __construct( $filterName, $parameterName, $actualValue, $expectedRange = null )
{
$actualValue = var_export( $actualValue, true );
$message = "Wrong value '{$actualValue}' submitted for parameter '{$parameterName}' of filter '{$filterName}'.";
if ( $expectedRange !== null )
{
$message .= " Expected parameter to be in range '{$expectedRange}'.";
}
parent::__construct( $message );
}
}
?>
@@ -0,0 +1,37 @@
<?php
/**
* File containing the ezcImageInvalidReferenceException.
*
* @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
*/
/**
* Thrown if no valid image reference could be found for an action (conversion,
* filter, load, save,...).
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageInvalidReferenceException extends ezcImageException
{
/**
* Creates a new ezcImageInvalidReferenceException.
*
* @param string $reason The reason.
* @return void
*/
function __construct( $reason = null )
{
$reasonPart = "";
if ( $reason )
{
$reasonPart = " $reason";
}
parent::__construct( "No valid reference found for action.{$reasonPart}" );
}
}
?>
@@ -0,0 +1,32 @@
<?php
/**
* File containing the ezcImageMimeTypeUnsupportedException.
*
* @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
*/
/**
* Thrown if a requested MIME type is not supported for input, output or input/output.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageMimeTypeUnsupportedException extends ezcImageException
{
/**
* Creates a new ezcImageMimeTypeUnsupportedException.
*
* @param string $mimeType Affected mime type.
* @param string $direction "input" or "output".
* @return void
*/
function __construct( $mimeType, $direction )
{
parent::__construct( "Converter does not support MIME type '{$mimeType}' for '{$direction}'." );
}
}
?>
@@ -0,0 +1,32 @@
<?php
/**
* File containing the ezcImageMissingFilterParameter.
*
* @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
*/
/**
* Thrown if an expected parameter for a filter was not submitted.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageMissingFilterParameterException extends ezcImageException
{
/**
* Creates a new ezcImageMissingFilterParameterException.
*
* @param string $filterName Affected filter.
* @param string $parameterName Affected parameter.
* @return void
*/
function __construct( $filterName, $parameterName )
{
parent::__construct( "The filter '{$filterName}' expects a parameter called '{$parameterName}' which was not submitted." );
}
}
?>
@@ -0,0 +1,55 @@
<?php
/**
* File containing the abstract class ezcImageTransformationException.
*
* @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
*/
/**
* Exception to be thrown be ezcImageTransformation classes.
*
* This is a special exception which is used in ezcImageTransformation to
* catch all transformation exceptions. Purpose is to provide a catch
* all for all transformation inherited excptions, that leaves the source
* exception in tact for logging or analysis purposes.
*
* @see ezcImageTransformation
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageTransformationException extends ezcImageException
{
/**
* Stores the parent exception.
* Each transformation exception is based on a parent, which can be any
* ezcImage* exception. The transformation exception deals as a collection
* container to catch all these exception at once.
*
* @var ezcImageException
*/
public $parent;
/**
* Creates a new ezcImageTransformationException using a parent exception.
* Creates a new ezcImageTransformationException and appends an existing
* exception to it. The ezcImageTransformationException is just the catch-
* all container. The parent is stored for logging/debugging purpose.
*
* @param ezcBaseException $e Any exception that may occur during
* transformation.
*/
public function __construct( ezcBaseException $e )
{
$this->parent = $e;
$message = $e->getMessage();
parent::__construct( "Transformation failed. '{$message}'." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcImageTransformationAlreadyExistsException.
*
* @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
*/
/**
* Thrown if a transformation with the given name already exists.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageTransformationAlreadyExistsException extends ezcImageException
{
/**
* Creates a new ezcImageTransformationAlreadyExistsException.
*
* @param string $name Name of the collision transformation.
* @return void
*/
function __construct( $name )
{
parent::__construct( "Transformation '{$name}' already exists." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcImageTransformationNotAvailableException.
*
* @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
*/
/**
* Thrown if a transformation with the given name does not exists.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageTransformationNotAvailableException extends ezcImageException
{
/**
* Creates a new ezcImageTransformationNotAvailableException.
*
* @param string $name Name of the missing transformation.
* @return void
*/
function __construct( $name )
{
parent::__construct( "Transformation '{$name}' does not exists." );
}
}
?>
@@ -0,0 +1,953 @@
<?php
/**
* This file contains the ezcImageGdHandler class.
*
* @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
*/
/**
* ezcImageHandler implementation for the GD2 extension of PHP, including filters.
* This ezcImageHandler is used when you want to manipulate images using
* ext/GD in your application.
*
* @see ezcImageConverter
* @see ezcImageHandler
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageGdHandler extends ezcImageGdBaseHandler
implements ezcImageGeometryFilters,
ezcImageColorspaceFilters,
ezcImageWatermarkFilters,
ezcImageThumbnailFilters
{
/**
* Scale filter.
* General scale filter. Scales the image to fit into a given box size,
* determined by a given width and height value, measured in pixel. This
* method maintains the aspect ratio of the given image. Depending on the
* given direction value, this method performs the following scales:
*
* - ezcImageGeometryFilters::SCALE_BOTH:
* The image will be scaled to fit exactly into the given box
* dimensions, no matter if it was smaller or larger as the box
* before.
* - ezcImageGeometryFilters::SCALE_DOWN:
* The image will be scaled to fit exactly into the given box
* only if it was larger than the given box dimensions before. If it
* is smaller, the image will not be scaled at all.
* - ezcImageGeometryFilters::SCALE_UP:
* The image will be scaled to fit exactly into the given box
* only if it was smaller than the given box dimensions before. If it
* is larger, the image will not be scaled at all. ATTENTION:
* In this case, the image does not necessarily fit into the given box
* afterwards.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
* which enables you to specify the image a filter is applied to.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @param int $direction Scale to which direction.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scale( $width, $height, $direction = ezcImageGeometryFilters::SCALE_BOTH )
{
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
$resource = $this->getActiveResource();
$oldDim = array( 'x' => imagesx( $resource ), 'y' => imagesy( $resource ) );
$widthRatio = $width / $oldDim['x'];
$heighRatio = $height / $oldDim['y'];
$ratio = min( $widthRatio, $heighRatio );
switch ( $direction )
{
case self::SCALE_DOWN:
$ratio = $ratio < 1 ? $ratio : 1;
break;
case self::SCALE_UP:
$ratio = $ratio > 1 ? $ratio : 1;
break;
case self::SCALE_BOTH:
break;
default:
throw new ezcBaseValueException( 'direction', $direction, 'self::SCALE_BOTH, self::SCALE_UP, self::SCALE_DOWN' );
break;
}
$this->performScale( round( $oldDim['x'] * $ratio ), round( $oldDim['y'] * $ratio ) );
}
/**
* Scale after width filter.
* Scales the image to a give width, measured in pixel. Scales the height
* automatically while keeping the ratio. The direction dictates, if an
* image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
* or if the scale may work in {@link self::SCALE_BOTH} directions.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
* which enables you to specify the image a filter is applied to.
*
* @param int $width Scale to width
* @param int $direction Scale to which direction
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scaleWidth( $width, $direction )
{
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
$resource = $this->getActiveResource();
$oldDim = array(
'x' => imagesx( $resource ),
'y' => imagesy( $resource ),
);
switch ( $direction )
{
case self::SCALE_BOTH:
$newDim = array(
'x' => $width,
'y' => $width / $oldDim['x'] * $oldDim['y']
);
break;
case self::SCALE_UP:
$newDim = array(
'x' => max( $width, $oldDim['x'] ),
'y' => $width > $oldDim['x'] ? round( $width / $oldDim['x'] * $oldDim['y'] ) : $oldDim['y'],
);
break;
case self::SCALE_DOWN:
$newDim = array(
'x' => min( $width, $oldDim['x'] ),
'y' => $width < $oldDim['x'] ? round( $width / $oldDim['x'] * $oldDim['y'] ) : $oldDim['y'],
);
break;
default:
throw new ezcBaseValueException( 'direction', $direction, 'self::SCALE_BOTH, self::SCALE_UP, self::SCALE_DOWN' );
break;
}
$this->performScale( $newDim["x"], $newDim["y"] );
}
/**
* Scale after height filter.
* Scales the image to a give height, measured in pixel. Scales the width
* automatically while keeping the ratio. The direction dictates, if an
* image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
* or if the scale may work in {@link self::SCALE_BOTH} directions.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
* which enables you to specify the image a filter is applied to.
*
* @param int $height Scale to height
* @param int $direction Scale to which direction
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scaleHeight( $height, $direction )
{
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
$resource = $this->getActiveResource();
$oldDim = array(
'x' => imagesx( $resource ),
'y' => imagesy( $resource ),
);
switch ( $direction )
{
case self::SCALE_BOTH:
$newDim = array(
'x' => $height / $oldDim['y'] * $oldDim['x'],
'y' => $height,
);
break;
case self::SCALE_UP:
$newDim = array(
'x' => $height > $oldDim['y'] ? round( $height / $oldDim['y'] * $oldDim['x'] ) : $oldDim['x'],
'y' => max( $height, $oldDim['y'] ),
);
break;
case self::SCALE_DOWN:
$newDim = array(
'x' => $height < $oldDim['y'] ? round( $height / $oldDim['y'] * $oldDim['x'] ) : $oldDim['x'],
'y' => min( $height, $oldDim['y'] ),
);
break;
default:
throw new ezcBaseValueException( 'direction', $direction, 'self::SCALE_BOTH, self::SCALE_UP, self::SCALE_DOWN' );
break;
}
$this->performScale( $newDim["x"], $newDim["y"] );
}
/**
* Scale percent measures filter.
* Scale an image to a given percentage value size.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
* which enables you to specify the image a filter is applied to.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scalePercent( $width, $height )
{
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
$resource = $this->getActiveResource();
$this->performScale( round( imagesx( $resource ) * $width / 100 ), round( imagesy( $resource ) * $height / 100 ) );
}
/**
* Scale exact filter.
* Scale the image to a fixed given pixel size, no matter to which
* direction.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
* which enables you to specify the image a filter is applied to.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scaleExact( $width, $height )
{
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
$this->performScale( $width, $height );
}
/**
* Crop filter.
* Crop an image to a given size. This takes cartesian coordinates of a
* rect area to crop from the image. The cropped area will replace the old
* image resource (not the input image immediately, if you use the
* {@link ezcImageConverter}). Coordinates are given as integer values and
* are measured from the top left corner.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
* which enables you to specify the image a filter is applied to.
*
* @param int $x X offset of the cropping area.
* @param int $y Y offset of the cropping area.
* @param int $width Width of cropping area.
* @param int $height Height of cropping area.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function crop( $x, $y, $width, $height )
{
if ( !is_int( $x ) )
{
throw new ezcBaseValueException( 'x', $x, 'int' );
}
if ( !is_int( $y ) )
{
throw new ezcBaseValueException( 'y', $y, 'int' );
}
if ( !is_int( $height ) )
{
throw new ezcBaseValueException( 'height', $height, 'int' );
}
if ( !is_int( $width ) )
{
throw new ezcBaseValueException( 'width', $width, 'int' );
}
$oldResource = $this->getActiveResource();
$sourceWidth = imagesx( $oldResource );
$sourceHeight = imagesy( $oldResource );
$x = ( $x >= 0 ) ? $x : $sourceWidth + $x;
$y = ( $y >= 0 ) ? $y : $sourceHeight + $y;
$x = abs( min( $x, $x + $width ) );
$y = abs( min( $y, $y + $height ) );
$width = abs( $width );
$height = abs( $height );
if ( $x + $width > $sourceWidth )
{
$width = $sourceWidth - $x;
}
if ( $y + $height > $sourceHeight )
{
$height = $sourceHeight - $y;
}
$this->performCrop( $x, $y, $width, $height );
}
/**
* Colorspace filter.
* Transform the colorspace of the picture. The following colorspaces are
* supported:
*
* - {@link self::COLORSPACE_GREY} - 255 grey colors
* - {@link self::COLORSPACE_SEPIA} - Sepia colors
* - {@link self::COLORSPACE_MONOCHROME} - 2 colors black and white
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
* which enables you to specify the image a filter is applied to.
*
* @param int $space Colorspace, one of self::COLORSPACE_* constants.
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcBaseValueException
* If the parameter submitted as the colorspace was not within the
* self::COLORSPACE_* constants.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
*/
public function colorspace( $space )
{
switch ( $space )
{
case self::COLORSPACE_GREY:
$this->luminanceColorScale( array( 1.0, 1.0, 1.0 ) );
break;
case self::COLORSPACE_MONOCHROME:
$this->thresholdColorScale(
array(
127 => array( 0, 0, 0 ),
255 => array( 255, 255, 255 ),
)
);
break;
return;
case self::COLORSPACE_SEPIA:
$this->luminanceColorScale( array( 1.0, 0.89, 0.74 ) );
break;
default:
throw new ezcBaseValueException( 'space', $space, 'self::COLORSPACE_GREY, self::COLORSPACE_SEPIA, self::COLORSPACE_MONOCHROME' );
break;
}
}
/**
* Watermark filter.
* Places a watermark on the image. The file to use as the watermark image
* is given as $image. The $posX, $posY and $size values are given in
* percent, related to the destination image. A $size value of 10 will make
* the watermark appear in 10% of the destination image size.
* $posX = $posY = 10 will make the watermark appear in the top left corner
* of the destination image, 10% of its size away from its borders. If
* $size is ommitted, the watermark image will not be resized.
*
* @param string $image The image file to use as the watermark
* @param int $posX X position in the destination image in percent.
* @param int $posY Y position in the destination image in percent.
* @param int|bool $size Percentage size of the watermark, false for none.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function watermarkPercent( $image, $posX, $posY, $size = false )
{
if ( !is_string( $image ) || !file_exists( $image ) || !is_readable( $image ) )
{
throw new ezcBaseValueException( 'image', $image, 'string, path to an image file' );
}
if ( !is_int( $posX ) || $posX < 0 || $posX > 100 )
{
throw new ezcBaseValueException( 'posX', $posX, 'int percentage value' );
}
if ( !is_int( $posY ) || $posY < 0 || $posY > 100 )
{
throw new ezcBaseValueException( 'posY', $posY, 'int percentage value' );
}
if ( !is_bool( $size ) && ( !is_int( $size ) || $size < 0 || $size > 100 ) )
{
throw new ezcBaseValueException( 'size', $size, 'int percentage value / bool' );
}
$imgWidth = imagesx( $this->getActiveResource() );
$imgHeight = imagesy( $this->getActiveResource() );
$watermarkWidth = false;
$watermarkHeight = false;
if ( $size !== false )
{
$watermarkWidth = (int) round( $imgWidth * $size / 100 );
$watermarkHeight = (int) round( $imgHeight * $size / 100 );
}
$watermarkPosX = (int) round( $imgWidth * $posX / 100 );
$watermarkPosY = (int) round( $imgHeight * $posY / 100 );
$this->watermarkAbsolute( $image, $watermarkPosX, $watermarkPosY, $watermarkWidth, $watermarkHeight );
}
/**
* Watermark filter.
* Places a watermark on the image. The file to use as the watermark image
* is given as $image. The $posX, $posY and $size values are given in
* pixel. The watermark appear at $posX, $posY in the destination image
* with a size of $size pixel. If $size is ommitted, the watermark image
* will not be resized.
*
* @param string $image The image file to use as the watermark
* @param int $posX X position in the destination image in pixel.
* @param int $posY Y position in the destination image in pixel.
* @param int|bool $width Pixel size of the watermark, false to keep size.
* @param int|bool $height Pixel size of the watermark, false to keep size.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
* @throws ezcImageFileNotProcessableException
* If the given watermark image could not be loaded.
*/
public function watermarkAbsolute( $image, $posX, $posY, $width = false, $height = false )
{
if ( !is_string( $image ) || !file_exists( $image ) || !is_readable( $image ) )
{
throw new ezcBaseValueException( 'image', $image, 'string, path to an image file' );
}
if ( !is_int( $posX ) )
{
throw new ezcBaseValueException( 'posX', $posX, 'int' );
}
if ( !is_int( $posY ) )
{
throw new ezcBaseValueException( 'posY', $posY, 'int' );
}
if ( !is_int( $width ) && !is_bool( $width ) )
{
throw new ezcBaseValueException( 'width', $width, 'int/bool' );
}
if ( !is_int( $height ) && !is_bool( $height ) )
{
throw new ezcBaseValueException( 'height', $height, 'int/bool' );
}
// Backup original image reference
$originalRef = $this->getActiveReference();
$originalWidth = imagesx( $this->getActiveResource() );
$originalHeight = imagesy( $this->getActiveResource() );
$watermarkRef = $this->load( $image );
if ( $width !== false && $height !== false && ( $originalWidth !== $width || $originalHeight !== $height ) )
{
$this->scale( $width, $height, ezcImageGeometryFilters::SCALE_BOTH );
}
// Negative offsets
$posX = ( $posX >= 0 ) ? $posX : $originalWidth + $posX;
$posY = ( $posY >= 0 ) ? $posY : $originalHeight + $posY;
imagecopy(
$this->getReferenceData( $originalRef, "resource" ), // resource $dst_im
$this->getReferenceData( $watermarkRef, "resource" ), // resource $src_im
$posX, // int $dst_x
$posY, // int $dst_y
0, // int $src_x
0, // int $src_y
imagesx( $this->getReferenceData( $watermarkRef, "resource" ) ), // int $src_w
imagesy( $this->getReferenceData( $watermarkRef, "resource" ) ) // int $src_h
);
$this->close( $watermarkRef );
// Restore original image reference
$this->setActiveReference( $originalRef );
}
/**
* Creates a thumbnail, and crops parts of the given image to fit the range best.
* This filter creates a thumbnail of the given image. The image is scaled
* down, keeping the original ratio and keeping the image larger as the
* given range, if necessary. Overhead for the target range is cropped from
* both sides equally.
*
* If you are looking for a filter that just resizes your image to
* thumbnail size, you should consider the {@link
* ezcImageGdHandler::scale()} filter.
*
* @param int $width Width of the thumbnail.
* @param int $height Height of the thumbnail.
*/
public function croppedThumbnail( $width, $height )
{
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
$resource = $this->getActiveResource();
$data[0] = imagesx( $resource );
$data[1] = imagesy( $resource );
$scaleRatio = max( $width / $data[0], $height / $data[1] );
$scaleWidth = round( $data[0] * $scaleRatio );
$scaleHeight = round( $data[1] * $scaleRatio );
$cropOffsetX = ( $scaleWidth > $width ) ? round( ( $scaleWidth - $width ) / 2 ) : 0;
$cropOffsetY = ( $scaleHeight > $height ) ? round( ( $scaleHeight - $height ) / 2 ) : 0;
$this->performScale( $scaleWidth, $scaleHeight );
$this->performCrop( $cropOffsetX, $cropOffsetY, $width, $height );
}
/**
* Creates a thumbnail, and fills up the image to fit the given range.
* This filter creates a thumbnail of the given image. The image is scaled
* down, keeping the original ratio and scaling the image smaller as the
* given range, if necessary. Overhead for the target range is filled with the given
* color on both sides equally.
*
* The color is defined by the following array format (integer values 0-255):
*
* <code>
* array(
* 0 => <red value>,
* 1 => <green value>,
* 2 => <blue value>,
* );
* </code>
*
* If you are looking for a filter that just resizes your image to
* thumbnail size, you should consider the {@link
* ezcImageGdHandler::scale()} filter.
*
* @param int $width Width of the thumbnail.
* @param int $height Height of the thumbnail.
* @param array $color Fill color.
*
* @return void
*/
public function filledThumbnail( $width, $height, $color = array() )
{
$i = 0;
foreach ( $color as $id => $colorVal )
{
if ( $i++ > 2 )
{
break;
}
if ( !is_int( $colorVal ) || $colorVal < 0 || $colorVal > 255 )
{
throw new ezcBaseValueException( "color[$id]", $color[$id], 'int > 0 and < 256' );
}
}
// Sanity checks for $width and $height performed by scale() method.
$this->scale( $width, $height, ezcImageGeometryFilters::SCALE_BOTH );
$oldResource = $this->getActiveResource();
$realWidth = imagesx( $oldResource );
$realHeight = imagesy( $oldResource );
$xOffset = ( $width > $realWidth ) ? round( ( $width - $realWidth ) / 2 ) : 0;
$yOffset = ( $height > $realHeight ) ? round( ( $height - $realHeight ) / 2 ) : 0;
$newResource = imagecreatetruecolor( $width, $height );
$bgColor = $this->getColor( $newResource, $color[0], $color[1], $color[2] );
if ( imagefill( $newResource, 0, 0, $bgColor ) === false )
{
throw new ezcImageFilterFailedException( "filledThumbnail", "Color fill failed." );
}
imagecopy(
$newResource,
$oldResource,
$xOffset,
$yOffset,
0,
0,
$realWidth,
$realHeight
);
$this->setActiveResource( $newResource );
imagedestroy( $oldResource );
}
// private
/**
* Retrieve luminance value for a specific pixel.
*
* @param resource(GD) $resource Image resource
* @param int $x Pixel x coordinate.
* @param int $y Pixel y coordinate.
* @return float Luminance value.
*/
private function getLuminanceAt( $resource, $x, $y )
{
$currentColor = imagecolorat( $resource, $x, $y );
$rgbValues = array(
'r' => ( $currentColor >> 16 ) & 0xff,
'g' => ( $currentColor >> 8 ) & 0xff,
'b' => $currentColor & 0xff,
);
return $rgbValues['r'] * 0.299 + $rgbValues['g'] * 0.587 + $rgbValues['b'] * 0.114;
}
/**
* Scale colors by threshold values.
* Thresholds are defined by the following array structures:
*
* <code>
* array(
* <int threshold value> => array(
* 0 => <int red value>,
* 1 => <int green value>,
* 2 => <int blue value>,
* ),
* )
* </code>
*
* @param array $thresholds
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
*
* @todo Optimization as described here: http://lists.ez.no/pipermail/components/2005-November/000566.html
*/
protected function thresholdColorScale( $thresholds )
{
$resource = $this->getActiveResource();
$dimensions = array( 'x' => imagesx( $resource ), 'y' => imagesy( $resource ) );
// Check for GIFs and convert them to work properly here.
if ( !imageistruecolor( $resource ) )
{
$resource = $this->paletteToTruecolor( $resource, $dimensions );
}
foreach ( $thresholds as $threshold => $colors )
{
$thresholds[$threshold] = array_merge(
$colors,
array( 'color' => $this->getColor( $resource, $colors[0], $colors[1], $colors[2] ) )
);
}
// Default
if ( !isset( $thresholds[255] ) )
{
$thresholds[255] = end( $thresholds );
reset( $thresholds );
}
$colorCache = array();
for ( $x = 0; $x < $dimensions['x']; $x++ )
{
for ( $y = 0; $y < $dimensions['y']; $y++ )
{
$luminance = $this->getLuminanceAt( $resource, $x, $y );
$color = end( $thresholds );
foreach ( $thresholds as $threshold => $colorValues )
{
if ( $luminance <= $threshold )
{
$color = $colorValues;
break;
}
}
imagesetpixel( $resource, $x, $y, $color['color'] );
}
}
$this->setActiveResource( $resource );
}
/**
* Perform luminance color scale.
*
* @param array $scale Array of RGB values (numeric index).
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed
*
* @todo Optimization as described here: http://lists.ez.no/pipermail/components/2005-November/000566.html
*/
protected function luminanceColorScale( $scale )
{
$resource = $this->getActiveResource();
$dimensions = array( 'x' => imagesx( $resource ), 'y' => imagesy( $resource ) );
// Check for GIFs and convert them to work properly here.
if ( !imageistruecolor( $resource ) )
{
$resource = $this->paletteToTruecolor( $resource, $dimensions );
}
for ( $x = 0; $x < $dimensions['x']; $x++ )
{
for ( $y = 0; $y < $dimensions['y']; $y++ )
{
$luminance = $this->getLuminanceAt( $resource, $x, $y );
$newRgbValues = array(
'r' => $luminance * $scale[0],
'g' => $luminance * $scale[1],
'b' => $luminance * $scale[2],
);
$color = $this->getColor( $resource, $newRgbValues['r'], $newRgbValues['g'], $newRgbValues['b'] );
imagesetpixel( $resource, $x, $y, $color );
}
}
$this->setActiveResource( $resource );
}
/**
* Convert a palette based image resource to a true color one.
* Takes a GD resource that does not represent a true color image and
* converts it to a true color based resource. Do not forget, to replace
* the actual resource in the handler, if you use this ,method!
*
* @param resource(GD) $resource The image resource to convert
* @param array(string=>int) $dimensions X and Y dimensions.
* @return resource(GD) The converted resource.
*/
protected function paletteToTruecolor( $resource, $dimensions )
{
$newResource = imagecreatetruecolor( $dimensions['x'], $dimensions['y'] );
imagecopy( $newResource, $resource, 0, 0, 0, 0, $dimensions['x'], $dimensions['y'] );
imagedestroy( $resource );
return $newResource;
}
/**
* Common color determination method.
* Returns a color identifier for an RGB value. Avoids problems with palette images.
*
* @param reource(GD) $resource The image resource to get a color for.
* @param int $r Red value.
* @param int $g Green value.
* @param int $b Blue value.
*
* @return int The color identifier.
*
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
*/
protected function getColor( $resource, $r, $g, $b )
{
if ( ( $res = imagecolorexact( $resource, $r, $g, $b ) ) !== -1 )
{
return $res;
}
if ( ( $res = imagecolorallocate( $resource, $r, $g, $b ) ) !== -1 )
{
return $res;
}
if ( ( $res = imagecolorclosest( $resource, $r, $g, $b ) ) !== -1 )
{
return $res;
}
throw new ezcImageFilterFailedException( 'allocatecolor', "Color allocation failed for color r: '{$r}', g: '{$g}', b: '{$b}'." );
}
/**
* General scaling method to perform actual scale to new dimensions.
*
* @param int $width Width.
* @param int $height Height.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException.
* If the operation performed by the the filter failed.
*/
protected function performScale( $width, $height )
{
$oldResource = $this->getActiveResource();
if ( imageistruecolor( $oldResource ) )
{
$newResource = imagecreatetruecolor( $width, $height );
}
else
{
$newResource = imagecreate( $width, $height );
}
// Save transparency, if image has it
$bgColor = imagecolorallocatealpha( $newResource, 255, 255, 255, 127 );
imagealphablending( $newResource, true );
imagesavealpha( $newResource, true );
imagefill( $newResource, 1, 1, $bgColor );
$res = imagecopyresampled(
$newResource,
$oldResource,
0, 0, 0, 0,
$width,
$height,
imagesx( $this->getActiveResource() ),
imagesy( $this->getActiveResource() )
);
if ( $res === false )
{
throw new ezcImageFilterFailedException( 'scale', 'Resampling of image failed.' );
}
imagedestroy( $oldResource );
$this->setActiveResource( $newResource );
}
/**
* General method to perform a crop operation.
*
* @param int $x
* @param int $y
* @param int $width
* @param int $height
* @return void
*/
private function performCrop( $x, $y, $width, $height )
{
$oldResource = $this->getActiveResource();
if ( imageistruecolor( $oldResource ) )
{
$newResource = imagecreatetruecolor( $width, $height );
}
else
{
$newResource = imagecreate( $width, $height );
}
// Save transparency, if image has it
$bgColor = imagecolorallocatealpha( $newResource, 255, 255, 255, 127 );
imagealphablending( $newResource, true );
imagesavealpha( $newResource, true );
imagefill( $newResource, 1, 1, $bgColor );
$res = imagecopyresampled(
$newResource, // destination resource
$oldResource, // source resource
0, // destination x coord
0, // destination y coord
$x, // source x coord
$y, // 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->setActiveResource( $newResource );
}
}
?>
@@ -0,0 +1,297 @@
<?php
/**
* This file contains the ezcImageGdBaseHandler class.
*
* @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
*/
/**
* 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 1.3.5
*/
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 ) ) === '' )
{
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' );
}
}
?>
@@ -0,0 +1,769 @@
<?php
/**
* This file contains the ezcImageImagemagickHandler class.
*
* @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
*/
/**
* ezcImageHandler implementation for ImageMagick.
*
* @see ezcImageConverter
* @see ezcImageHandler
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageImagemagickHandler extends ezcImageImagemagickBaseHandler
implements ezcImageGeometryFilters,
ezcImageColorspaceFilters,
ezcImageEffectFilters,
ezcImageWatermarkFilters,
ezcImageThumbnailFilters
{
/**
* Scale filter.
* General scale filter. Scales the image to fit into a given box size,
* determined by a given width and height value, measured in pixel. This
* method maintains the aspect ratio of the given image. Depending on the
* given direction value, this method performs the following scales:
*
* - ezcImageGeometryFilters::SCALE_BOTH:
* The image will be scaled to fit exactly into the given box
* dimensions, no matter if it was smaller or larger as the box
* before.
* - ezcImageGeometryFilters::SCALE_DOWN:
* The image will be scaled to fit exactly into the given box
* only if it was larger than the given box dimensions before. If it
* is smaller, the image will not be scaled at all.
* - ezcImageGeometryFilters::SCALE_UP:
* The image will be scaled to fit exactly into the given box
* only if it was smaller than the given box dimensions before. If it
* is larger, the image will not be scaled at all. ATTENTION:
* In this case, the image does not necessarily fit into the given box
* afterwards.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @param int $direction Scale to which direction.
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scale( $width, $height, $direction = ezcImageGeometryFilters::SCALE_BOTH )
{
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
$dirMod = $this->getDirectionModifier( $direction );
$this->addFilterOption(
$this->getActiveReference(),
'-resize',
$width.$dirMod.'x'.$height.$dirMod
);
}
/**
* Scale after width filter.
* Scales the image to a give width, measured in pixel. Scales the height
* automatically while keeping the ratio. The direction dictates, if an
* image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
* or if the scale may work in {@link self::SCALE_BOTH} directions.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $width Scale to width
* @param int $direction Scale to which direction
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scaleWidth( $width, $direction )
{
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
$dirMod = $this->getDirectionModifier( $direction );
$this->addFilterOption(
$this->getActiveReference(),
'-resize ',
$width.$dirMod
);
}
/**
* Scale after height filter.
* Scales the image to a give height, measured in pixel. Scales the width
* automatically while keeping the ratio. The direction dictates, if an
* image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
* or if the scale may work in {@link self::SCALE_BOTH} directions.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $height Scale to height
* @param int $direction Scale to which direction
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scaleHeight( $height, $direction )
{
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
$dirMod = $this->getDirectionModifier( $direction );
$this->addFilterOption(
$this->getActiveReference(),
'-resize ',
'x'.$height.$dirMod
);
}
/**
* Scale percent measures filter.
* Scale an image to a given percentage value size.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scalePercent( $width, $height )
{
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
if ( !is_int( $width ) || $width < 1 || $width > 100 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
$this->addFilterOption(
$this->getActiveReference(),
'-resize',
$width.'%x'.$height.'%'
);
}
/**
* Scale exact filter.
* Scale the image to a fixed given pixel size, no matter to which
* direction.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function scaleExact( $width, $height )
{
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
$this->addFilterOption(
$this->getActiveReference(),
'-resize',
$width.'!x'.$height.'!'
);
}
/**
* Crop filter.
* Crop an image to a given size. This takes cartesian coordinates of a
* rect area to crop from the image. The cropped area will replace the old
* image resource (not the input image immediately, if you use the
* {@link ezcImageConverter}). Coordinates are given as integer values and
* are measured from the top left corner.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $x X offset of the cropping area.
* @param int $y Y offset of the cropping area.
* @param int $width Width of cropping area.
* @param int $height Height of cropping area.
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function crop( $x, $y, $width, $height )
{
if ( !is_int( $x ) )
{
throw new ezcBaseValueException( 'x', $x, 'int' );
}
if ( !is_int( $y ) )
{
throw new ezcBaseValueException( 'y', $y, 'int' );
}
if ( !is_int( $height ) )
{
throw new ezcBaseValueException( 'height', $height, 'int' );
}
if ( !is_int( $width ) )
{
throw new ezcBaseValueException( 'width', $width, 'int' );
}
$data = getimagesize( $this->getActiveResource() );
$x = ( $x >= 0 ) ? $x : $data[0] + $x;
$y = ( $y >= 0 ) ? $y : $data[1] + $y;
$xStart = ( $xStart = min( $x, $x + $width ) ) >= 0 ? '+'.$xStart : $xStart;
$yStart = ( $yStart = min( $y, $y + $height ) ) >= 0 ? '+'.$yStart : $yStart;
$this->addFilterOption(
$this->getActiveReference(),
'-crop ',
abs( $width ).'x'.abs( $height ).$xStart.$yStart.'!'
);
}
/**
* Colorspace filter.
* Transform the color space of the picture. The following color space are
* supported:
*
* - {@link self::COLORSPACE_GREY} - 255 grey colors
* - {@link self::COLORSPACE_SEPIA} - Sepia colors
* - {@link self::COLORSPACE_MONOCHROME} - 2 colors black and white
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $space Colorspace, one of self::COLORSPACE_* constants.
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference
* @throws ezcBaseValueException
* If the parameter submitted as the colorspace was not within the
* self::COLORSPACE_* constants.
*/
public function colorspace( $space )
{
switch ( $space )
{
case self::COLORSPACE_GREY:
$this->addFilterOption(
$this->getActiveReference(),
'-colorspace',
'GRAY'
);
$this->addFilterOption(
$this->getActiveReference(),
'-colors',
'255'
);
break;
case self::COLORSPACE_MONOCHROME:
$this->addFilterOption(
$this->getActiveReference(),
'-monochrome'
);
break;
case self::COLORSPACE_SEPIA:
$this->addFilterOption(
$this->getActiveReference(),
'-sepia-tone',
'80%'
);
break;
return;
default:
throw new ezcBaseValueException( 'space', $space, 'self::COLORSPACE_GREY, self::COLORSPACE_SEPIA, self::COLORSPACE_MONOCHROME' );
break;
}
}
/**
* Noise filter.
* Apply a noise transformation to the image. Valid values are the following
* strings:
* - 'Uniform'
* - 'Gaussian'
* - 'Multiplicative'
* - 'Impulse'
* - 'Laplacian'
* - 'Poisson'
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param strings $value Noise value as described above.
* @return void
*
* @throws ezcBaseValueException
* If the noise value is out of range.
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
*/
public function noise( $value )
{
$value = ucfirst( strtolower( $value ) );
$possibleValues = array(
'Uniform',
'Gaussian',
'Multiplicative',
'Impulse',
'Laplacian',
'Poisson',
);
if ( !in_array( $value, $possibleValues ) )
{
throw new ezcBaseValueException( 'value', $value, 'Uniform, Gaussian, Multiplicative, Impulse, Laplacian, Poisson' );
}
$this->addFilterOption(
$this->getActiveReference(),
'+noise',
$value
);
}
/**
* Swirl filter.
* Applies a swirl with the given intense to the image.
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $value Intense of swirl.
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
* @throws ezcBaseValueException
* If the swirl value is out of range.
*/
public function swirl( $value )
{
if ( !is_int( $value ) || $value < 0 )
{
throw new ezcBaseValueException( 'value', $value, 'int >= 0' );
}
$this->addFilterOption(
$this->getActiveReference(),
'-swirl',
$value
);
}
/**
* Border filter.
* Adds a border to the image. The width is measured in pixel. The color is
* defined in an array of hex values:
*
* <code>
* array(
* 0 => <red value>,
* 1 => <green value>,
* 2 => <blue value>,
* );
* </code>
*
* ATTENTION: Using this filter method directly results in the filter being
* applied to the image which is internally marked as "active" (most
* commonly this is the last recently loaded one). It is highly recommended
* to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
* method, which enables you to specify the image a filter is applied to.
*
* @param int $width Width of the border.
* @param array(int) $color Color.
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function border( $width, array $color )
{
if ( !is_int( $width ) )
{
throw new ezcBaseValueException( 'width', $width, 'int' );
}
$colorString = $this->colorArrayToString( $color );
$this->addFilterOption(
$this->getActiveReference(),
'-bordercolor',
$colorString
);
$this->addFilterOption(
$this->getActiveReference(),
'-border',
$width
);
}
/**
* Watermark filter.
* Places a watermark on the image. The file to use as the watermark image
* is given as $image. The $posX, $posY and $size values are given in
* percent, related to the destination image. A $size value of 10 will make
* the watermark appear in 10% of the destination image size.
* $posX = $posY = 10 will make the watermark appear in the top left corner
* of the destination image, 10% of its size away from its borders. If
* $size is ommitted, the watermark image will not be resized.
*
* @param string $image The image file to use as the watermark
* @param int $posX X position in the destination image in percent.
* @param int $posY Y position in the destination image in percent.
* @param int|bool $size Percentage size of the watermark, false for none.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function watermarkPercent( $image, $posX, $posY, $size = false )
{
if ( !is_string( $image ) || !file_exists( $image ) || !is_readable( $image ) )
{
throw new ezcBaseValueException( 'image', $image, 'string, path to an image file' );
}
if ( !is_int( $posX ) || $posX < 0 || $posX > 100 )
{
throw new ezcBaseValueException( 'posX', $posX, 'int percentage value' );
}
if ( !is_int( $posY ) || $posY < 0 || $posY > 100 )
{
throw new ezcBaseValueException( 'posY', $posY, 'int percentage value' );
}
if ( !is_bool( $size ) && ( !is_int( $size ) || $size < 0 || $size > 100 ) )
{
throw new ezcBaseValueException( 'size', $size, 'int percentage value / bool' );
}
$data = getimagesize( $this->getReferenceData( $this->getActiveReference(), "resource" ) );
$originalWidth = $data[0];
$originalHeight = $data[1];
$watermarkWidth = false;
$watermarkHeight = false;
if ( $size !== false )
{
$watermarkWidth = (int) round( $originalWidth * $size / 100 );
$watermarkHeight = (int) round( $originalHeight * $size / 100 );
}
$watermarkPosX = (int) round( $originalWidth * $posX / 100 );
$watermarkPosY = (int) round( $originalHeight * $posY / 100 );
$this->watermarkAbsolute( $image, $watermarkPosX, $watermarkPosY, $watermarkWidth, $watermarkHeight );
}
/**
* Watermark filter.
* Places a watermark on the image. The file to use as the watermark image
* is given as $image. The $posX, $posY and $size values are given in
* pixel. The watermark appear at $posX, $posY in the destination image
* with a size of $size pixel. If $size is ommitted, the watermark image
* will not be resized.
*
* @param string $image The image file to use as the watermark
* @param int $posX X position in the destination image in pixel.
* @param int $posY Y position in the destination image in pixel.
* @param int|bool $width Pixel size of the watermark, false to keep size.
* @param int|bool $height Pixel size of the watermark, false to keep size.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function watermarkAbsolute( $image, $posX, $posY, $width = false, $height = false )
{
if ( !is_string( $image ) || !file_exists( $image ) || !is_readable( $image ) )
{
throw new ezcBaseValueException( 'image', $image, 'string, path to an image file' );
}
if ( !is_int( $posX ) )
{
throw new ezcBaseValueException( 'posX', $posX, 'int' );
}
if ( !is_int( $posY ) )
{
throw new ezcBaseValueException( 'posY', $posY, 'int' );
}
if ( !is_int( $width ) && !is_bool( $width ) )
{
throw new ezcBaseValueException( 'width', $width, 'int/bool' );
}
if ( !is_int( $height ) && !is_bool( $height ) )
{
throw new ezcBaseValueException( 'height', $height, 'int/bool' );
}
$data = getimagesize( $this->getActiveResource() );
// Negative offsets
$posX = ( $posX >= 0 ) ? $posX : $data[0] + $posX;
$posY = ( $posY >= 0 ) ? $posY : $data[1] + $posY;
$this->addFilterOption(
$this->getActiveReference(),
'-composite',
''
);
$this->addFilterOption(
$this->getActiveReference(),
'-geometry',
( $width !== false ? $width : "" ) . ( $height !== false ? "x$height" : "" ) . "+$posX+$posY"
);
$this->addCompositeImage( $this->getActiveReference(), $image );
}
/**
* Creates a thumbnail, and crops parts of the given image to fit the range best.
* This filter creates a thumbnail of the given image. The image is scaled
* down, keeping the original ratio and keeping the image larger as the
* given range, if necessary. Overhead for the target range is cropped from
* both sides equally.
*
* If you are looking for a filter that just resizes your image to
* thumbnail size, you should consider the {@link
* ezcImageImagemagickHandler::scale()} filter.
*
* @param int $width Width of the thumbnail.
* @param int $height Height of the thumbnail.
*/
public function croppedThumbnail( $width, $height )
{
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
$data = getimagesize( $this->getReferenceData( $this->getActiveReference(), "resource" ) );
$scaleRatio = max( $width / $data[0], $height / $data[1] );
$scaleWidth = round( $data[0] * $scaleRatio );
$scaleHeight = round( $data[1] * $scaleRatio );
$cropOffsetX = ( $scaleWidth > $width ) ? "+" . round( ( $scaleWidth - $width ) / 2 ) : "+0";
$cropOffsetY = ( $scaleHeight > $height ) ? "+" . round( ( $scaleHeight - $height ) / 2 ) : "+0";
$this->addFilterOption(
$this->getActiveReference(),
'-resize',
$scaleWidth . "x" . $scaleHeight
);
$this->addFilterOption(
$this->getActiveReference(),
'-crop',
$width . "x" . $height . $cropOffsetX . $cropOffsetY . "!"
);
}
/**
* Creates a thumbnail, and fills up the image to fit the given range.
* This filter creates a thumbnail of the given image. The image is scaled
* down, keeping the original ratio and scaling the image smaller as the
* given range, if necessary. Overhead for the target range is filled with the given
* color on both sides equally.
*
* The color is defined by the following array format (integer values 0-255):
*
* <code>
* array(
* 0 => <red value>,
* 1 => <green value>,
* 2 => <blue value>,
* );
* </code>
*
* If you are looking for a filter that just resizes your image to
* thumbnail size, you should consider the {@link
* ezcImageImagemagickHandler::scale()} filter.
*
* @param int $width Width of the thumbnail.
* @param int $height Height of the thumbnail.
* @param array $color Fill color.
* @return void
*/
public function filledThumbnail( $width, $height, $color = array() )
{
if ( !is_int( $width ) || $width < 1 )
{
throw new ezcBaseValueException( 'width', $width, 'int > 0' );
}
if ( !is_int( $height ) || $height < 1 )
{
throw new ezcBaseValueException( 'height', $height, 'int > 0' );
}
$data = getimagesize( $this->getReferenceData( $this->getActiveReference(), "resource" ) );
$scaleRatio = min( $width / $data[0], $height / $data[1] );
$scaleWidth = round( $data[0] * $scaleRatio );
$scaleHeight = round( $data[1] * $scaleRatio );
$cropOffsetX = ( $scaleWidth < $width ) ? "-" . round( ( $width - $scaleWidth ) / 2 ) : "+0";
$cropOffsetY = ( $scaleHeight < $height ) ? "-" . round( ( $height - $scaleHeight ) / 2 ) : "+0";
$colorString = '#';
$i = 0;
foreach ( $color as $id => $colorVal )
{
if ( $i++ > 2 )
{
break;
}
if ( !is_int( $colorVal ) || $colorVal < 0 || $colorVal > 255 )
{
throw new ezcBaseValueException( "color[$id]", $color[$id], 'int > 0 and < 256' );
}
$colorString .= sprintf( '%02x', $colorVal );
}
$this->addFilterOption(
$this->getActiveReference(),
'-resize',
$width . "x" . $height
);
$this->addFilterOption(
$this->getActiveReference(),
'-crop',
$width . "x" . $height . $cropOffsetX . $cropOffsetY . "!"
);
$this->addFilterOption(
$this->getActiveReference(),
'-background',
$colorString
);
$this->addFilterOption(
$this->getActiveReference(),
'-flatten'
);
}
/**
* Returns the ImageMagick direction modifier for a direction constant.
* ImageMagick supports the following modifiers to determine if an
* image should be scaled up only, down only or in both directions:
*
* <code>
* SCALE_UP: >
* SCALE_DOWN: <
* </code>
*
* This method returns the correct modifier for the internal direction
* constants.
*
* @param int $direction One of ezcImageGeometryFilters::SCALE_*
* @return string The correct modifier.
*
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
protected function getDirectionModifier( $direction )
{
$dirMod = '';
switch ( $direction )
{
case self::SCALE_DOWN:
$dirMod = '>';
break;
case self::SCALE_UP:
$dirMod = '<';
break;
case self::SCALE_BOTH:
$dirMod = '';
break;
default:
throw new ezcBaseValueException( 'direction', $direction, 'self::SCALE_BOTH, self::SCALE_UP, self::SCALE_DOWN' );
break;
}
return $dirMod;
}
}
?>
@@ -0,0 +1,471 @@
<?php
/**
* This file contains the ezcImageImagemagickBaseHandler class.
*
* @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
*/
/**
* 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.
*
* @see ezcImageConverter
* @see ezcImageHandler
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageImagemagickBaseHandler extends ezcImageMethodcallHandler
{
/**
* Path to the convert binary.
*
* @var string
*/
private $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
* ImageMagick).
*
* @throws ezcImageHandlerNotAvailableException
* If the ImageMagick binary is not found.
*
* @param ezcImageHandlerSettings $settings Settings for the handler.
*/
public function __construct( ezcImageHandlerSettings $settings )
{
// Check for ImageMagick
$this->checkImageMagick( $settings );
$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 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 );
// Atomic file operation
$fileTmp = tempnam( dirname( $file ) . DIRECTORY_SEPARATOR, '.' . basename( $file ) );
copy( $file, $fileTmp );
$this->setReferenceData( $ref, $fileTmp, '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 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 )
{
if ( $options === null )
{
$options = new ezcImageSaveOptions();
}
if ( $newFile !== null )
{
$this->checkFileName( $newFile );
}
// Check is transparency must be converted
if ( $this->needsTransparencyConversion( $this->getReferenceData( $image, 'mime' ), $mime ) && $options->transparencyReplacementColor !== null )
{
$this->addFilterOption( $image, '-background', $this->colorArrayToString( $options->transparencyReplacementColor ) );
$this->addFilterOption( $image, '-flatten' );
}
$this->saveCommon( $image, $newFile, $mime );
switch ( $this->getReferenceData( $image, 'mime' ) )
{
case "image/jpeg":
if ( $options->quality !== null )
{
$this->addFilterOption( $image, "-quality", $options->quality );
}
break;
case "image/png":
if ( $options->compression !== null )
{
// ImageMagick uses qualtiy options here and incorporates filter options
$this->addFilterOption( $image, "-quality", $options->compression * 10 );
}
break;
}
// 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' ) );
}
else
{
$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
$descriptors = array(
array( 'pipe', 'r' ),
array( 'pipe', 'w' ),
array( 'pipe', 'w' ),
);
// Open ImageMagick process
$imageProcess = proc_open( $command, $descriptors, $pipes );
// Close STDIN pipe
fclose( $pipes[0] );
$errorString = '';
$outputString = '';
// Read STDERR
do
{
$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
$status = proc_get_status( $imageProcess );
while ( $status['running'] === true )
{
// Sleep 1/100 second to wait for convert to exit
usleep( 10000 );
$status = proc_get_status( $imageProcess );
}
$return = proc_close( $imageProcess );
// Process potential errors
if ( $status['exitcode'] != 0 || strlen( $errorString ) > 0 )
{
// If this code is reached we have a bug in this component or in ImageMagick itself.
throw new Exception(
"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:
* <code>
* array(
* 255,
* 0,
* 0,
* )
* </code>
* 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
* would be '#FF0000'.
*
* @param array $color
* @return void
*
* @throws ezcBaseValueException
* if one of the color values in the array is invalid (not integer,
* smaller than 0 or larger than 255).
*/
protected function colorArrayToString( array $color )
{
$colorString = '#';
$i = 0;
foreach ( $color as $id => $colorVal )
{
if ( $i++ > 2 )
{
break;
}
if ( !is_int( $colorVal ) || $colorVal < 0 || $colorVal > 255 )
{
throw new ezcBaseValueException( "color[$id]", $color[$id], 'int > 0 and < 256' );
}
$colorString .= sprintf( '%02x', $colorVal );
}
return $colorString;
}
/**
* 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.
* @return void
*/
protected function addFilterOption( $reference, $name, $parameter = null )
{
$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.
* @return void
*/
protected function addCompositeImage( $reference, $file )
{
$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
* capable to process.
*
* @return void
*
* @apichange Faulty MIME type "image/svg" will be removed and replaced by
* correct MIME type image/svg+xml.
*/
private function determineTypes()
{
$tagMap = array(
'application/pcl' => 'PCL',
'application/pdf' => 'PDF',
'application/postscript' => 'PS',
'application/vnd.palm' => 'PDB',
'application/x-icb' => 'ICB',
'application/x-mif' => 'MIFF',
'image/bmp' => 'BMP3',
'image/dcx' => 'DCX',
'image/g3fax' => 'G3',
'image/gif' => 'GIF',
'image/jng' => 'JNG',
'image/jpeg' => 'JPG',
'image/pbm' => 'PBM',
'image/pcd' => 'PCD',
'image/pict' => 'PCT',
'image/pjpeg' => 'PJPEG',
'image/png' => 'PNG',
'image/ras' => 'RAS',
'image/sgi' => 'SGI',
'image/svg+xml' => 'SVG',
// Left over for BC reasons
'image/svg' => 'SVG',
'image/tga' => 'TGA',
'image/tiff' => 'TIF',
'image/vda' => 'VDA',
'image/vnd.wap.wbmp' => 'WBMP',
'image/vst' => 'VST',
'image/x-fits' => 'FITS',
'image/x-otb' => 'OTB',
'image/x-palm' => 'PALM',
'image/x-pcx' => 'PCX',
'image/x-pgm' => 'PGM',
'image/psd' => 'PSD',
'image/x-ppm' => 'PPM',
'image/x-ptiff' => 'PTIF',
'image/x-viff' => 'VIFF',
'image/x-xbitmap' => 'XPM',
'image/x-xv' => 'P7',
'image/xpm' => 'PICON',
'image/xwd' => 'XWD',
'text/plain' => 'TXT',
'video/mng' => 'MNG',
'video/mpeg' => 'MPEG',
'video/mpeg2' => 'M2V',
);
$types = array_keys( $tagMap );
$this->inputTypes = $types;
$this->outputTypes = $types;
$this->tagMap = $tagMap;
}
/**
* Checks for ImageMagick on the system.
*
* @param ezcImageHandlerSettings $settings The settings object of the current handler instance.
* @return void
*
* @throws ezcImageHandlerNotAvailableException
* If the ImageMagick binary is not found.
*/
private function checkImageMagick( ezcImageHandlerSettings $settings )
{
if ( !isset( $settings->options['binary'] ) )
{
// Try to use basic binary names only, if not provided (standard case
// on Unix, binary should be in the $PATH, so is accessable).
switch ( PHP_OS )
{
case 'Linux':
case 'Unix':
case 'FreeBSD':
case 'MacOS':
case 'Darwin':
$this->binary = 'convert';
break;
case 'Windows':
case 'WINNT':
case 'WIN32':
$this->binary = 'convert.exe';
break;
default:
throw new ezcImageHandlerNotAvailableException( 'ezcImageImagemagickHandler', "System '" . PHP_OS . "' not supported by handler 'ezcImageImagemagickHandler'." );
break;
}
}
else
{
$this->binary = $settings->options['binary'];
}
// Prepare to run ImageMagick command
$descriptors = array(
array( 'pipe', 'r' ),
array( 'pipe', 'w' ),
array( 'pipe', 'w' ),
);
// Open ImageMagick process
$imageProcess = proc_open( $this->binary, $descriptors, $pipes );
// Close STDIN pipe
fclose( $pipes[0] );
$outputString = '';
// Read STDOUT
do
{
$outputString .= rtrim( fgets( $pipes[1], 1024 ), "\n" );
} while ( !feof( $pipes[1] ) );
$errorString = '';
// Read STDERR
do
{
$errorString .= rtrim( fgets( $pipes[2], 1024 ), "\n" );
} while ( !feof( $pipes[2] ) );
// Wait for process to terminate and store return value
$return = proc_close( $imageProcess );
// Process potential errors
if ( $return != 0 || strlen( $errorString ) > 0 || strpos( $outputString, 'ImageMagick' ) === false )
{
throw new ezcImageHandlerNotAvailableException( 'ezcImageImagemagickHandler', 'ImageMagick not installed or not available in PATH variable.' );
}
}
/**
* Creates default settings for the handler and returns it.
* The reference name will be set to 'ImageMagick'.
*
* @return ezcImageHandlerSettings
*/
static public function defaultSettings()
{
return new ezcImageHandlerSettings( 'ImageMagick', 'ezcImageImagemagickHandler' );
}
}
?>
@@ -0,0 +1,69 @@
<?php
/**
* File containing the ezcImageColorspaceFilters interface.
*
* @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
*/
/**
* This interface has to implemented by ezcImageFilters classes to
* support colorspace filters.
*
* @see ezcImageHandler
* @see ezcImageTransformation
* @see ezcImageFiltersInterface
*
* @package ImageConversion
* @version 1.3.5
*/
interface ezcImageColorspaceFilters
{
/**
* Grey color space.
*
* @var int
*/
const COLORSPACE_GREY = 1;
/**
* Sepia color space.
*
* @var int
*/
const COLORSPACE_SEPIA = 2;
/**
* Monochrome color space.
*
* @var int
*/
const COLORSPACE_MONOCHROME = 3;
/**
* Colorspace filter.
* Transform the colorspace of the picture. The following colorspaces are
* supported:
*
* - {@link self::COLORSPACE_GREY} - 255 grey colors
* - {@link self::COLORSPACE_SEPIA} - Sepia colors
* - {@link self::COLORSPACE_MONOCHROME} - 2 colors black and white
*
* @param int $space Colorspace, one of self::COLORSPACE_* constants.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the parameter submitted as the colorspace was not within the
* self::COLORSPACE_* constants
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function colorspace( $space );
}
?>
@@ -0,0 +1,90 @@
<?php
/**
* File containing the ezcImageEffectFilters interface.
*
* @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
*/
/**
* This interface has to be implemented by ezcImageFilters classes to
* support effect filters.
*
* @see ezcImageHandler
* @see ezcImageTransformation
* @see ezcImageFiltersInterface
*
* @package ImageConversion
* @version 1.3.5
*/
interface ezcImageEffectFilters
{
/**
* Noise filter.
* Apply a noise transformation to the image. Valid values are the following
* strings:
* - 'Uniform'
* - 'Gaussian'
* - 'Multiplicative'
* - 'Impulse'
* - 'Laplacian'
* - 'Poisson'
*
* @param strings $value Noise value as described above.
* @return void
*
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
*/
function noise( $value );
/**
* Swirl filter.
* Applies a swirl with the given intense to the image.
*
* @param int $value Intense of swirl.
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function swirl( $value );
/**
* Border filter.
* Adds a border to the image. The width is measured in pixel. The color is
* defined in an array of hex values:
*
* <code>
* array(
* 0 => <red value>,
* 1 => <green value>,
* 2 => <blue value>,
* );
* </code>
*
* @param int $width Width of the border.
* @param array(int) $color Color.
* @return void
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function border( $width, array $color );
}
?>
@@ -0,0 +1,177 @@
<?php
/**
* File containing the ezcImageGeometryFilters interface.
*
* @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
*/
/**
* This interface has to implemented by ezcImageFilters classes to
* support geometry filters.
*
* @see ezcImageHandler
* @see ezcImageTransformation
* @see ezcImageFiltersInterface
*
* @package ImageConversion
* @version 1.3.5
*/
interface ezcImageGeometryFilters
{
/**
* Scale up and down, as fits
* @var int
*/
const SCALE_BOTH = 1;
/**
* Scale down only
* @var int
*/
const SCALE_DOWN = 2;
/**
* Scale up only
* @var int
*/
const SCALE_UP = 3;
/**
* Scale filter.
* General scale filter. Scales the image to fit into a given box size,
* determined by a given width and height value, measured in pixel. This
* method maintains the aspect ratio of the given image. Depending on the
* given direction value, this method performs the following scales:
*
* - ezcImageGeometryFilters::SCALE_BOTH:
* The image will be scaled to fit exactly into the given box
* dimensions, no matter if it was smaller or larger as the box
* before.
* - ezcImageGeometryFilters::SCALE_DOWN:
* The image will be scaled to fit exactly into the given box
* only if it was larger than the given box dimensions before. If it
* is smaller, the image will not be scaled at all.
* - ezcImageGeometryFilters::SCALE_UP:
* The image will be scaled to fit exactly into the given box
* only if it was smaller than the given box dimensions before. If it
* is larger, the image will not be scaled at all. ATTENTION:
* In this case, the image does not necessarily fit into the given box
* afterwards.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @param int $direction Scale to which direction.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function scale( $width, $height, $direction = ezcImageGeometryFilters::SCALE_BOTH );
/**
* Scale after width filter.
* Scales the image to a give width, measured in pixel. Scales the height
* automatically while keeping the ratio. The direction dictates, if an
* image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
* or if the scale may work in {@link self::SCALE_BOTH} directions.
*
* @param int $width Scale to width
* @param int $direction Scale to which direction
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function scaleWidth( $width, $direction );
/**
* Scale after height filter.
* Scales the image to a give height, measured in pixel. Scales the width
* automatically while keeping the ratio. The direction dictates, if an
* image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
* or if the scale may work in {@link self::SCALE_BOTH} directions.
*
* @param int $height Scale to height
* @param int $direction Scale to which direction
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function scaleHeight( $height, $direction );
/**
* Scale percent measures filter.
* Scale an image to a given percentage value size.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function scalePercent( $width, $height );
/**
* Scale exact filter.
* Scale the image to a fixed given pixel size, no matter to which
* direction.
*
* @param int $width Scale to width
* @param int $height Scale to height
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function scaleExact( $width, $height );
/**
* Crop filter.
* Crop an image to a given size. This takes cartesian coordinates of a
* rect area to crop from the image. The cropped area will replace the old
* image resource (not the input image immediately, if you use the
* {@link ezcImageConverter}). Coordinates are given as integer values and
* are measured from the top left corner.
*
* @param int $x Start cropping, x coordinate.
* @param int $y Start cropping, y coordinate.
* @param int $width Width of cropping area.
* @param int $height Height of cropping area.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
function crop( $x, $y, $width, $height );
}
?>
@@ -0,0 +1,280 @@
<?php
/**
* This file contains the ezcImageHandler interface.
*
* @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
*/
/**
* Driver interface to access different image manipulation backends of PHP.
* This interface has to be implemented by a handler class in order to be
* used with the ImageConversion package.
*
* @see ezcImageConverter
*
* @package ImageConversion
* @version 1.3.5
*/
abstract class ezcImageHandler
{
/**
* Container to hold the properties
*
* @var array(string=>mixed)
*/
protected $properties;
/**
* Settings of the handlers
*
* @var ezcImageHandlerSettings
*/
protected $settings;
/**
* 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. When overwriting
* the constructor.
*
* @param ezcImageHandlerSettings $settings
* Settings for the handler.
*/
public function __construct( ezcImageHandlerSettings $settings )
{
$this->properties['name'] = $settings->referenceName;
$this->settings = $settings;
}
/**
* Sets the property $name to $value.
*
* @throws ezcBasePropertyNotFoundException if the property does not exist.
* @throws ezcBasePropertyReadOnlyException if the property cannot be modified.
* @param string $name
* @param mixed $value
* @ignore
*/
public function __set( $name, $value )
{
switch ( $name )
{
case 'name':
throw new ezcBasePropertyPermissionException( $name, ezcBasePropertyPermissionException::READ );
default:
throw new ezcBasePropertyNotFoundException( $name );
}
}
/**
* Returns the property $name.
*
* @throws ezcBasePropertyNotFoundException if the property does not exist.
* @param string $name
* @return mixed
* @ignore
*/
public function __get( $name )
{
switch ( $name )
{
case 'name':
return $this->properties[$name];
default:
throw new ezcBasePropertyNotFoundException( $name );
}
}
/**
* Checks if the property $name exist and returns the result.
*
* @param string $name
* @return bool
* @ignore
*/
public function __isset( $name )
{
switch ( $name )
{
case 'name':
return true;
default:
return false;
}
}
/**
* Checks a file name for illegal characters.
* Checks if a file name contains illegal characters, which are ", ' and $.
*
* @param string $file The file name to check.
* @return void
*
* @throws ezcImageFileNameInvalidException
* If an invalid character (", ', $) is found in the file name.
*/
protected function checkFileName( $file )
{
if ( strpos( $file, "'" ) !== false || strpos( $file, "'" ) !== false || strpos( $file, '$' ) !== false )
{
throw new ezcImageFileNameInvalidException( $file );
}
}
/**
* Returns if a MIME conversion needs transparent color replacement.
*
* In case a transparency supporting MIME type (like image/png) is
* converted to one that does not support transparency, special steps need
* to be performed. This method returns if the given conversion from
* $inMime to $outMime is affected by this.
*
* @param string $inMime
* @param string $outMime
* @return bool
*/
protected function needsTransparencyConversion( $inMime, $outMime )
{
$transparencyMimes = array(
'image/gif' => true,
'image/png' => true,
);
return (
$outMime !== null
&& $inMime !== $outMime
&& isset( $transparencyMimes[$inMime] )
&& !isset( $transparencyMimes[$outMime] )
);
}
/**
* Load an image file.
* Loads an image file and returns a reference to it.
*
* For developers: The use of ezcImageHandler::loadCommon() is highly
* recommended for the implementation of this method!
*
* @param string $file File to load.
* @param string $mime The MIME type of the file.
* @return string Reference to the file in this handler.
*/
abstract public function load( $file, $mime = null );
/**
* Save an image file.
* Saves a given open file. Can optionally save to a new file name.
* The image reference is not freed automatically, so you need to call
* the close() method explicitly to free the referenced data.
*
* @see ezcImageHandler::load()
* @see ezcImageHandler::close()
*
* @param string $image File reference created through.
* @param string $newFile Filename to save the image to.
* @param string $mime New MIME type, if differs from
* initial one.
* @param ezcImageSaveOptions $options Options for saving.
* @return void
*/
abstract public function save( $image, $newFile = null, $mime = null, ezcImageSaveOptions $options = null );
/**
* Close the file referenced by $image.
* Frees the image reference. You should call close() before.
*
* @see ezcImageHandler::load()
* @see ezcImageHandler::save()
* @param string $reference The image reference.
* @return void
*/
abstract public function close( $reference );
/**
* Check wether a specific MIME type is allowed as input for this handler.
*
* @param string $mime MIME type to check if it's allowed.
* @return bool
*/
abstract public function allowsInput( $mime );
/**
* Checks wether a specific MIME type is allowed as output for this handler.
*
* @param string $mime MIME type to check if it's allowed.
* @return bool
*/
abstract public function allowsOutput( $mime );
/**
* Checks if a given filter is available in this handler.
*
* @param string $name Name of the filter to check for.
* @return bool
*
*/
abstract public function hasFilter( $name );
/**
* Returns a list of filters this handler provides.
* The list returned is in format:
*
* <code>
* array(
* 0 => <string filtername>,
* 1 => <string filtername>,
* ...
* )
* </code>
*
* @return array(string)
*/
abstract public function getFilterNames();
/**
* Applies a filter to a given image.
*
* @internal This method is the main one, which will dispatch the
* filter action to the specific function of the backend.
*
* @see ezcImageHandler::load()
* @see ezcImageHandler::save()
*
* @param string $image Image reference to apply the filter on.
* @param ezcImageFilter $filter Contains which filter operation to apply.
* @return void
*
* @throws ezcImageFilterNotAvailableException
* If the desired filter does not exist.
* @throws ezcImageMissingFilterParameterException
* If a parameter for the filter is missing.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a parameter was not within the expected range.
*/
abstract public function applyFilter( $image, ezcImageFilter $filter );
/**
* Converts an image to another MIME type.
*
* Use {@link ezcImageHandler::allowsOutput()} to determine,
* if the output MIME type is supported by this handler!
*
* @see ezcImageHandler::load()
* @see ezcImageHandler::save()
*
* @param string $image Image reference to convert.
* @param string $mime MIME type to convert to.
* @return void
*
* @throws ezcImageMimeTypeUnsupportedException
* If the given MIME type is not supported by the filter.
*/
abstract public function convert( $image, $mime );
}
?>
@@ -0,0 +1,573 @@
<?php
/**
* This file contains the ezcImageMethodcallHandler interface.
*
* @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
* @access private
*/
/**
* Special image handler which handles filters using method calls and keeps
* track of resources.
* This is a special abstract class which are extended by the ImageMagick and
* GD handlers and contains code which is common to both of them.
* It performs filter operations by keeping a filter object available and
* accesses the filter methods directly, this means the sub-classes only have
* to create the correct filter object.
*
* Implements all abstract methods of ezcImageHandler except load(), save()
* and close(). Instead it provides the {@link loadCommon()},
* {@link saveCommon()} and {@link closeCommon()} methods to simplify the code
* for sub-classes.
*
* @see ezcImageConverter
* @see ezcImageGdHandler
* @see ezcImageImagemagickHandler
* @see ezcImageFilters
*
* @package ImageConversion
* @version 1.3.5
* @access private
*/
abstract class ezcImageMethodcallHandler extends ezcImageHandler
{
/**
* Array of MIME types usable for input
*
* @var array
*/
protected $inputTypes;
/**
* Array of MIME types usable for output
*
* @var array
*/
protected $outputTypes;
/**
* Array of filter names cached from getFilterNames().
*
* @var array
*/
protected $filterNameCache;
/**
* Image references created through load().
* Format:
* array(
* 'id' => array(
* 'file' => <file name>,
* 'mime' => <MIME type>,
* 'resource' => <image resource>,
* )
* )
*
* @var array
*/
private $references = array();
/**
* Currently active image reference.
* This is used to determine by the filter, which image should be
* processed.
*
* @var string
*/
private $activeReference;
/**
* 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. When overwriting
* the constructor.
*
* The contents of the $settings parameter may change from handler to
* handler. For detailed information take a look at the specific handler
* classes.
*
* @param ezcImageHandlerSettings $settings Settings for the handler.
*/
public function __construct( ezcImageHandlerSettings $settings )
{
parent::__construct( $settings );
}
/**
* Destroyes the handler and closes all open references correctly.
*
* @return void
*/
public function __destruct()
{
foreach ( $this->references as $id => $data )
{
$this->close( $id );
}
}
/**
* Check wether a specific MIME type is allowed as input for this handler.
*
* @param string $mime MIME type to check if it's allowed.
* @return bool
*/
public function allowsInput( $mime )
{
return ( in_array( strtolower( $mime ), $this->inputTypes ) );
}
/**
* Checks wether a specific MIME type is allowed as output for this handler.
*
* @param string $mime MIME type to check if it's allowed.
* @return bool
*/
public function allowsOutput( $mime )
{
return ( in_array( strtolower( $mime ), $this->outputTypes ) );
}
/**
* Checks if a given filter is available in this handler.
*
* @param string $name Name of the filter to check for.
* @return bool
*
*/
public function hasFilter( $name )
{
return method_exists( $this, $name );
}
/**
* Returns a list of filters this handler provides.
* The list returned is in format:
*
* <code>
* array(
* 0 => <string filtername>,
* 1 => <string filtername>,
* ...
* )
* </code>
*
* @return array(string)
*/
public function getFilterNames()
{
if ( !isset( $this->filterNameCache ) || !is_array( $this->filterNameCache || sizeof( $this->filterNameCache ) === 0 ) )
{
$this->filterNameCache = array();
$excludeMethods = array(
'__construct',
'__destruct',
'__get',
'__set',
'__call',
'allowsInput',
'allowsOutput',
'hasFilter',
'getFilterNames',
'applyFilter',
'convert',
'load',
'save',
'close',
'defaultSettings',
);
$refClass = new ReflectionClass( get_class( $this ) );
foreach ( $refClass->getMethods() as $method )
{
if ( $method->isPublic() && !in_array( $method->getName(), $excludeMethods ) )
{
$this->filterNameCache[] = $method->getName();
}
}
}
return $this->filterNameCache;
}
/**
* Applies a filter to a given image.
*
* @internal This method is the main one, which will dispatch the
* filter action to the specific function of the backend.
*
* @see ezcImageMethodcallHandler::load()
* @see ezcImageMethodcallHandler::save()
*
* @param string $image Image reference to apply the filter on.
* @param ezcImageFilter $filter Contains which filter operation to apply.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
* @throws ezcImageFilterNotAvailableException
* If the desired filter does not exist.
* @throws ezcImageFiltersMissingFilterParameterException
* If a parameter for the filter is missing.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a parameter was not within the expected range.
*/
public function applyFilter( $image, ezcImageFilter $filter )
{
if ( !$this->hasFilter( $filter->name ) )
{
throw new ezcImageFilterNotAvailableException( $filter->name );
}
$reflectClass = new ReflectionClass( get_class( $this ) );
$reflectParameters = $reflectClass->getMethod( $filter->name )->getParameters();
$parameters = array();
foreach ( $reflectParameters as $id => $parameter )
{
$paramName = $parameter->getName();
if ( isset( $filter->options[$paramName] ) )
{
$parameters[] = $filter->options[$paramName];
}
else if ( $parameter->isOptional() === false )
{
throw new ezcImageMissingFilterParameterException( $filter->name, $paramName );
}
}
// Backup last active reference
$oldRef = $this->getActiveReference();
// Perform actual filtering on given image
$this->setActiveReference( $image );
call_user_func_array( array( $this, $filter->name ), $parameters );
// Restore last active reference
$this->setActiveReference( $oldRef );
}
/**
* Converts an image to another MIME type.
*
* Use {@link ezcImageMethodcallHandler::allowsOutput()} to determine,
* if the output MIME type is supported by this handler!
*
* @see ezcImageMethodcallHandler::load()
* @see ezcImageMethodcallHandler::save()
*
* @param string $image Image reference to convert.
* @param string $mime MIME type to convert to.
* @return void
*
* @throws ezcImageMimeTypeUnsupportedException
* If the given MIME type is not supported by the filter.
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
*/
public function convert( $image, $mime )
{
$oldMime = $this->getReferenceData( $image, 'mime' );
if ( !$this->allowsOutput( $mime ) )
{
throw new ezcImageMimeTypeUnsupportedException( $mime, 'output' );
}
$this->setReferenceData( $image, $mime, 'mime' );
}
/**
* Receive the resource of the active image reference.
* This method is utilized by the ezcImageFilters* class to receive the
* currently active resource for manipulations.
*
* @return resource The currently active resource.
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
*/
protected function getActiveResource()
{
$ref = $this->getActiveReference();
if ( ( $resource = $this->getReferenceData( $ref, 'resource' ) ) === false )
{
throw new ezcImageInvalidReferenceException( "No resource found for the active reference '{$ref}'." );
}
return $resource;
}
/**
* Replace the resource of an image reference with a new one.
* After filtering the current image resource might have to be replaced
* with a new version. This can be done using this method.
*
* @param resource(GD) $resource
* @return void
*/
protected function setActiveResource( $resource )
{
$this->setReferenceData(
$this->getActiveReference(),
$resource,
'resource'
);
}
/**
* Returns the currently active reference.
* Returns the reference which is currently marked as active. This happens
* either by loading a new file or by using the setActiveReference()
* method.
*
* @see ezcImageMethodcallHandler::setActiveReference()
* @see ezcImageMethodcallHandler::load()
* @see ezcImageMethodcallHandler::$references
*
* @throws ezcImageInvalidReferenceException
* No loaded file could be found or an error destroyed a loaded reference.
*
* @return string The active reference.
*/
protected function getActiveReference()
{
if ( !isset( $this->activeReference ) )
{
throw new ezcImageInvalidReferenceException( 'No reference is defined as active. Either no file is loeaded, yet or an internal error destroyed the reference.' );
}
return $this->activeReference;
}
/**
* Mark the submitted image reference as active.
* The image reference submitted is marked as active. All following
* filter operations are performed on this reference.
*
* @param string $image The image reference.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If the given reference is invalid.
*/
protected function setActiveReference( $image )
{
if ( !isset( $this->references[$image] ) )
{
throw new ezcImageInvalidReferenceException( 'Could not mark invalid reference as active.' );
}
$this->activeReference = $image;
}
/**
* Returns data about a reference.
* This gives you access to the data stored about a loaded image. You can
* either retrieve a certain detail (defined in the references array), with
* specifying it through the second parameter (the method then simply
* returns that detail) or retrieve all available details with leaving that
* parameter out.
*
* By default the following details are available:
* <code>
* 'file' => The file name of the image loaded.
* 'mime' => The mime type of the image loaded.
* 'resource' => A resource referencing it.
* </code>
*
* Of what type the resource is, may differ from handler to handler (e.g. a
* GD resource for the GD handler or a file path for the ImageMagick handler).
* You can simply store your own details be setting them and retreive them
* through this method.
*
* @param string $reference Reference string assigned.
* @param mixed $detail To receive a single detail, set to detail name.
* @return array Array of details if you specify $detail, else depending on
* the detail. If detail is not available, returns false.
*
* @throws ezcImageInvalidReferenceException
* If the given reference is invalid.
*
* @see ezcImageMethodcallHandler::setReferenceData()
*/
protected function getReferenceData( $reference, $detail = null )
{
if ( !isset( $this->references[$reference] ) )
{
throw new ezcImageInvalidReferenceException( "Inavlid image reference given: '{$reference}'." );
}
if ( isset( $detail ) )
{
return isset( $this->references[$reference][$detail] ) ? $this->references[$reference][$detail] : false;
}
return $this->references[$reference];
}
/**
* Set data for an image reference.
* This method allows you to set all data that can be retrieved through
* ezcImageMethodcallHandler::getReferenceData(). You can either set a single detail
* by providing the optional $detail parameter or submit an array containing
* all details at once as the value to set all details.
*
* @param string $reference Reference string of the image data.
* @param mixed $value The value to set.
* @param string $detail The name of the detail to set.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If the given reference is invalid.
* @throws ezcBaseValueException
* If the given detail is invalid.
*/
protected function setReferenceData( $reference, $value, $detail = null )
{
if ( !isset( $this->references[$reference] ) )
{
throw new ezcImage( "Invalid image reference given: '{$reference}'." );
}
if ( isset( $detail ) )
{
$this->references[$reference][$detail] = $value;
}
else
{
if ( !is_array( $value ) )
{
throw new ezcBaseValueException( 'value', $value, 'array' );
}
if ( !isset( $value['file'] ) )
{
throw new ezcBaseValueException( 'file', null, 'string' );
}
if ( !isset( $value['mime'] ) )
{
throw new ezcBaseValueException( 'mime', null, 'string' );
}
if ( !isset( $value['resource'] ) )
{
throw new ezcBaseValueException( 'resource', null, 'string' );
}
$this->references[$reference] = $value;
}
}
/**
* Create a reference entry for this file.
* Performs common operations on a specific file, like checking if the file
* exists, if it is loadable, if it's already loaded. Beside of that, it
* creates the reference internally, so you don't need to handle this
* stuff manually with the internal data structure of
* ezcImageMethodcallHandler::$references. It also cares for determining the MIME-
* type of the image and sets the newly created reference to be active.
*
* @param string $file The file to load.
* @param string $mime The MIME type of the file.
* @return string reference The reference string for this file.
*
* @throws ezcBaseFileNotFoundException
* If the desired file does not exist.
* @throws ezcBaseFilePermissionException
* If the desired file is not readable.
* @throws ezcBaseValueException
* If the given detail is invalid.
* @throws ezcImageMimeTypeUnsupportedException
* If the desired file has a not recognized type.
*/
protected function loadCommon( $file, $mime = null )
{
if ( !is_file( $file ) )
{
throw new ezcBaseFileNotFoundException( $file );
}
if ( !is_readable( $file ) )
{
throw new ezcBaseFilePermissionException( $file, ezcBaseFileException::READ );
}
$file = realpath( $file );
$ref = md5( $file );
if ( !isset( $mime ) )
{
$mime = '';
try
{
$analyzer = new ezcImageAnalyzer( $file );
$mime = $analyzer->mime;
}
catch ( ezcImageAnalyzerException $e )
{
throw new ezcImageMimeTypeUnsupportedException( 'unknown/unknown', 'input' );
}
}
$this->references[$ref] = array();
$this->setReferenceData(
$ref,
array(
'file' => $file,
'mime' => $mime,
'resource' => false,
)
);
$this->setActiveReference( $ref );
return $ref;
}
/**
* Performs common operations before saving a file.
* This method should/can be used while implementing the save method of an
* ezcImageMethodcallHandler. It performs several tasks, like setting the new file name,
* if it has been submitted, and the new MIME type. Beside that, it checks
* if one can write to the new file and if the handler is able to process
* the new MIME type.
*
* @param string $reference The image reference.
* @param string $newFile The new filename.
* @param string $mime The new MIME type.
* @return void
*
* @throws ezcBaseFilePermissionException
* If the desired file is not writeable.
* @throws ezcImageMimeTypeUnsupportedException
* If the desired MIME type is not recognized.
*/
protected function saveCommon( $reference, $newFile = null, $mime = null )
{
if ( isset( $newFile ) )
{
$this->setReferenceData( $reference, $newFile, 'file' );
}
$file = $this->getReferenceData( $reference, 'file' );
if ( file_exists( $file ) && !is_writeable( $file ) )
{
throw new ezcBaseFilePermissionException( $file, ezcBaseFileException::WRITE );
}
if ( isset( $mime ) )
{
$this->setReferenceData( $reference, $mime, 'mime' );
}
$mime = $this->getReferenceData( $reference, 'mime' );
if ( $this->allowsOutput( $mime ) === false )
{
throw new ezcImageMimeTypeUnsupportedException( $mime, 'output' );
}
}
/**
* Unsets the reference data for the given reference.
* This method _must_ be called in the implementation of the close() method
* in every ezcImageMethodcallHandler to finally remove the reference.
*
* @param string $reference The reference to free.
* @return void
*/
protected function closeCommon( $reference )
{
$data = $this->getReferenceData( $reference );
unset( $this->references[$reference] );
}
}
?>
@@ -0,0 +1,70 @@
<?php
/**
* File containing the ezcImageThumbnailFilters interface.
*
* @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
*/
/**
* This interface has to implemented by ezcImageFilters classes to
* support thumbnail filters.
*
* @see ezcImageHandler
* @see ezcImageTransformation
* @see ezcImageFiltersInterface
*
* @package ImageConversion
* @version 1.3.5
*/
interface ezcImageThumbnailFilters
{
/**
* Creates a thumbnail, and crops parts of the given image to fit the range best.
* This filter creates a thumbnail of the given image. The image is scaled
* down, keeping the original ratio and keeping the image larger as the
* given range, if necessary. Overhead for the target range is cropped from
* both sides equally.
*
* If you are looking for a filter that just resizes your image to
* thumbnail size, you should consider the {@link
* ezcImageGeometryFilters::scale()} filter.
*
* @param int $width Width of the thumbnail.
* @param int $height Height of the thumbnail.
*/
public function croppedThumbnail( $width, $height );
/**
* Creates a thumbnail, and fills up the image to fit the given range.
* This filter creates a thumbnail of the given image. The image is scaled
* down, keeping the original ratio and scaling the image smaller as the
* given range, if necessary. Overhead for the target range is filled with the given
* color on both sides equally.
*
* The color is defined by the following array format (integer values 0-255):
*
* <code>
* array(
* 0 => <red value>,
* 1 => <green value>,
* 2 => <blue value>,
* );
* </code>
*
* If you are looking for a filter that just resizes your image to
* thumbnail size, you should consider the {@link
* ezcImageGeometryFilters::scale()} filter.
*
* @param int $width Width of the thumbnail.
* @param int $height Height of the thumbnail.
* @param array $color Fill color.
* @return void
*/
public function filledThumbnail( $width, $height, $color = array() );
}
?>
@@ -0,0 +1,74 @@
<?php
/**
* File containing the ezcImageWatermarkFilters interface.
*
* @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
*/
/**
* This interface has to implemented by ezcImageFilters classes to
* support watermark filters.
*
* @see ezcImageHandler
* @see ezcImageTransformation
* @see ezcImageFiltersInterface
*
* @package ImageConversion
* @version 1.3.5
*/
interface ezcImageWatermarkFilters
{
/**
* Watermark filter.
* Places a watermark on the image. The file to use as the watermark image
* is given as $image. The $posX, $posY and $size values are given in
* percent, related to the destination image. A $size value of 10 will make
* the watermark appear in 10% of the destination image size.
* $posX = $posY = 10 will make the watermark appear in the top left corner
* of the destination image, 10% of its size away from its borders. If
* $size is ommitted, the watermark image will not be resized.
*
* @param string $image The image file to use as the watermark
* @param int $posX X position in the destination image in percent.
* @param int $posY Y position in the destination image in percent.
* @param int|bool $size Percentage size of the watermark, false for none.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function watermarkPercent( $image, $posX, $posY, $size = false );
/**
* Watermark filter.
* Places a watermark on the image. The file to use as the watermark image
* is given as $image. The $posX, $posY and $size values are given in
* pixel. The watermark appear at $posX, $posY in the destination image
* with a size of $size pixel. If $size is ommitted, the watermark image
* will not be resized.
*
* @param string $image The image file to use as the watermark
* @param int $posX X position in the destination image in pixel.
* @param int $posY Y position in the destination image in pixel.
* @param int|bool $width Pixel size of the watermark, false to keep size.
* @param int|bool $height Pixel size of the watermark, false to keep size.
* @return void
*
* @throws ezcImageInvalidReferenceException
* If no valid resource for the active reference could be found.
* @throws ezcImageFilterFailedException
* If the operation performed by the the filter failed.
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
*/
public function watermarkAbsolute( $image, $posX, $posY, $width = false, $height = false );
}
?>
@@ -0,0 +1,84 @@
<?php
/**
* This file contains the ezcImageGdHandler class.
*
* @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
* @access public
*/
/**
* Options class for ezcImageHandler->save() methods.
*
* @property int $compression
* The compression level to use, if compression is supported by the
* target format (e.g. TIFF). A value between 0 and 9 (incl.) is
* expected.
* @property int $quality A quality indicator used to determine the quality of
* the target image, if supported by the target format (e.g. JPEG). A
* value between 0 and 100 (incl.) is expected.
* @property array(int) $transparencyReplacementColor
* Only certain image formats support transparent backgrounds (e.g.
* GIF and PNG). If such images are converted to a format that does
* not support transparency, this color will be used as the new
* background. The color value is given as an array of integers, each
* representing a color value in RGB between 0 and 255.
* <code>array( 255, 0, 0 )</code> for example would be pure red.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageSaveOptions extends ezcBaseOptions
{
/**
* Properties.
*
* @var array(string=>mixed)
*/
protected $properties = array(
"compression" => null,
"quality" => null,
"transparencyReplacementColor" => null,
);
/**
* Property set access.
*
* @param string $propertyName
* @param string $propertyValue
* @ignore
* @return void
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case "compression":
if ( ( !is_int( $propertyValue ) || $propertyValue < 0 || $propertyValue > 9 ) && $propertyValue !== null )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, "int > 0 and < 10" );
}
break;
case "quality":
if ( ( !is_int( $propertyValue ) || $propertyValue < 0 || $propertyValue > 100 ) && $propertyValue !== null )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, "int > 0 and <= 100" );
}
break;
case "transparencyReplacementColor":
if ( ( !is_array( $propertyValue ) || count( $propertyValue ) < 3 || !isset( $propertyValue[0] ) || !isset( $propertyValue[1] ) || !isset( $propertyValue[2] ) ) && $propertyValue !== null )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, "array(int)" );
}
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
}
$this->properties[$propertyName] = $propertyValue;
}
}
?>
@@ -0,0 +1,71 @@
<?php
/**
* File containing the ezcImageConverterSettings struct.
*
* @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
*/
/**
* Struct to store the settings for objects of ezcImageConverter.
*
* This class is used as a struct for the settings of ezcImageConverter.
*
* @see ezcImageConverter
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageConverterSettings extends ezcBaseStruct
{
/**
* Array with {@link ezcImageHandlerSettings handler settings} objects.
* Each settings objects is consulted by the converter to figure out which
* {@link ezcImageHandler image handlers} to use.
*
* @see ezcImageHandler
* @see ezcImageGdHandler
* @see ezcImageImagemagickHandler
*
* @var array(ezcImageHandlerSettings)
*/
public $handlers = array();
/**
* Map of automatic MIME type conversions. The converter will automatically
* perform the defined conversions when a transformation is applied through
* it and the specific MIME type is recognized.
*
* The conversion map has the following structure:
* <code>
* array(
* 'image/gif' => 'image/png', // Note: lower case!
* 'image/bmp' => 'image/jpeg',
* )
* </code>
*
* @var array
*/
public $conversions = array();
/**
* Create a new instance of ezcImageConverterSettings.
* Create a new instance of ezcImageConverterSettings to be used with
* {@link ezcImageConverter} objects..
*
* @see ezcImageConverterSettings::$handlers
* @see ezcImageConverterSettings::$conversions
*
* @param array $handlers Array of {@link ezcImageHandlerSettings handler objects}.
* @param array $conversions Map of standard MIME type conversions.
*/
public function __construct( array $handlers = array(), array $conversions = array() )
{
$this->handlers = $handlers;
$this->conversions = $conversions;
}
}
?>
@@ -0,0 +1,81 @@
<?php
/**
* File containing the ezcImageFilter struct.
*
* @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
*/
/**
* Struct to store information about a filter operation.
*
* The struct contains the {@link self::name name} of the filter to use and
* which {@link self::options options} to use for it.
*
* Possible filter names are determined by the methods defined in the following
* filter interfaces:
*
* <ul>
* <li>{@link ezcImageGeometryFilters}</li>
* <li>{@link ezcImageColorspaceFilters}</li>
* <li>{@link ezcImageEffectFilters}</li>
* <li>{@link ezcImageWatermarkFilters}</li>
* <li>{@link ezcImageThumbnailFilters}</li>
* </ul>
*
* The options for each filter are represented by the parameters received by
* their corresponding method. You can determine if a certain {@link
* ezcImageHandler} implementation supports a filter by checking the interfaces
* this handler implements.
*
* @see ezcImageTransformation
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageFilter extends ezcBaseStruct
{
/**
* Name of filter operation to use.
*
* @see ezcImageEffectFilters
* @see ezcImageGeometryFilters
* @see ezcImageColorspaceFilters
*
* @var string
*/
public $name;
/**
* Associative array of options for the filter operation.
* The array key is the option name and the array entry is the value for
* the option.
* Consult each filter operation to see which names and values to use.
*
* @see ezcImageEffectFilters
* @see ezcImageGeometryFilters
* @see ezcImageColorspaceFilters
*
* @var array(string=>mixed)
*/
public $options;
/**
* Initialize with the filter name and options.
*
* @see ezcImageFilter::$name
* @see ezcImageFilter::$options
*
* @param array $name Name of filter operation.
* @param array $options Associative array of options for filter operation.
*/
public function __construct( $name, array $options = array() )
{
$this->name = $name;
$this->options = $options;
}
}
?>
@@ -0,0 +1,87 @@
<?php
/**
* File containing the ezcImageHandlerSettings struct.
*
* @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
*/
/**
* Struct to store the settings for objects of ezcImageHandler.
*
* This class is used as a struct for the settings of ezcImageHandler
* subclasses.
*
* @see ezcImageHandler
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageHandlerSettings extends ezcBaseStruct
{
/**
* The reference name for the handler.
* This name can be used when referencing the handler in certain operations
* in the {@link ezcImageConverter converter} class.
*
* e.g. 'GD' and 'ImageMagick'.
*
* @var string
*/
public $referenceName;
/**
* Name of the class to instantiate as image handler.
*
* Note: This class must be a subclass of the {@link ezcImageHandler} class.
*
* @var string
*/
public $className;
/**
* Associative array of misc options for the handler.
* These options will be read by the handler class and varies from handler
* to handler. Consult the handler class for the available settings.
*
* The options array has the following structure:
* <code>
* array(
* <optionName> => <optionValue>,
* [ <optionName> => <optionValue>, ...]
* )
* </code>
*
* @var array
*/
public $options = array();
/**
* Initialize settings to be used by image handler.
* The settings passed as parameter will be read by the
* {@link ezcImageConverter converter} to figure out which image handler to
* use and then passed to the {@link ezcImageHandler image handler objects}.
*
* @see ezcImageHandlerSettings::$referenceName
* @see ezcImageHandlerSettings::$className
* @see ezcImageHandlerSettings::$settings
*
* @param string $referenceName
* The reference name for the handler, e.g. 'GD' or 'ImageMagick'
* @param string $className
* The name of the handler class to instantiate, e.g.
* 'ezcImageGdHandler' or 'ezcImageImagemagickHandler'
* @param array $options
* Associative array of settings for the handler.
*/
public function __construct( $referenceName, $className, array $options = array() )
{
$this->referenceName = $referenceName;
$this->className = $className;
$this->options = $options;
}
}
?>
@@ -0,0 +1,401 @@
<?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;
}
}
?>
@@ -0,0 +1,614 @@
<?php
/**
* ezcImageConversionConverterTest
*
* @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
*/
require_once dirname( __FILE__ ) . "/test_case.php";
/**
* Test suite for ImageConverter class.
*
* @package ImageConversion
* @version 1.3.5
*/
class ezcImageConversionConverterTest extends ezcImageConversionTestCase
{
protected $converter;
public static function suite()
{
return new PHPUnit_Framework_TestSuite( "ezcImageConversionConverterTest" );
}
protected function setUp()
{
try
{
$conversionsIn = array(
"image/gif" => "image/png",
"image/xpm" => "image/jpeg",
"image/wbmp" => "image/jpeg",
);
if ( ezcBaseFeatures::os() === 'Windows' )
{
unset( $conversionsIn["image/xpm"] );
}
$settings = new ezcImageConverterSettings(
array( new ezcImageHandlerSettings( "GD", "ezcImageGdHandler" ) ),
$conversionsIn
);
$this->converter = new ezcImageConverter( $settings );
}
catch ( Exception $e )
{
$this->markTestSkipped( $e->getMessage() );
}
}
protected function tearDown()
{
unset( $this->converter );
}
// Constructor tests
public function testConstructSingleHandlerSuccess()
{
$conversionsIn = array(
"image/gif" => "image/png",
"image/xpm" => "image/jpeg",
"image/wbmp" => "image/jpeg",
);
if ( ezcBaseFeatures::os() === 'Windows' )
{
unset( $conversionsIn["image/xpm"] );
}
try
{
$settings = new ezcImageConverterSettings( array( new ezcImageHandlerSettings( "GD", "ezcImageGdHandler" ) ),
$conversionsIn );
$converter = new ezcImageConverter( $settings );
}
catch ( Exception $e )
{
$this->markTestSkipped();
}
$handlers = $this->readAttribute( $converter, "handlers" );
$settings = $this->readAttribute( $converter, "settings" );
$this->assertType(
"ezcImageGdHandler",
$handlers["GD"],
"Handler <GD> is not an instance of ezcImageGdHandler."
);
$this->assertEquals(
$conversionsIn,
$settings->conversions,
"Conversions not registered successfully."
);
}
public function testConstructFailureInvalidSettings()
{
$conversionsIn = array(
"image/gif" => "image/png",
"image/xpm" => "image/jpeg",
"image/wbmp" => "image/jpeg",
);
if ( ezcBaseFeatures::os() === 'Windows' )
{
unset( $conversionsIn["image/xpm"] );
}
try
{
$settings = new ezcImageConverterSettings(
array( new stdClass() ),
$conversionsIn
);
$converter = new ezcImageConverter( $settings );
$this->fail( 'Exception not thrown on invalid handler settings.' );
}
catch ( ezcImageHandlerSettingsInvalidException $e )
{}
}
public function testConstructSingleHandlerFailureOutputMimeTypeNotSupported()
{
$conversionsIn = array(
"image/gif" => "image/png",
"image/xpm" => "application/ezc",
"image/wbmp" => "image/jpeg",
);
$settings = new ezcImageConverterSettings(
array( new ezcImageHandlerSettings( "GD", "ezcImageGdHandler" ) ),
$conversionsIn
);
try
{
$converter = new ezcImageConverter( $settings );
}
catch ( ezcImageMimeTypeUnsupportedException $e )
{
return;
}
$this->fail( "Expected excption not thrown when creating ezcImageConverter with unsupported conversion." );
}
public function testConstructSingleHandlerFailureInputMimeTypeNotSupported()
{
$conversionsIn = array(
"image/gif" => "image/png",
"image/ezc" => "image/jpeg",
"image/wbmp" => "image/jpeg",
);
$settings = new ezcImageConverterSettings(
array( new ezcImageHandlerSettings( "GD", "ezcImageGdHandler" ) ),
$conversionsIn
);
try
{
$converter = new ezcImageConverter( $settings );
}
catch ( ezcImageMimeTypeUnsupportedException $e )
{
return;
}
$this->fail( "Expected excption not thrown when creating ezcImageConverter with unsupported conversion." );
}
public function testConstructSingleHandlerFailureHandlerNotAvailable()
{
$conversionsIn = array(
"image/gif" => "image/png",
"image/xpm" => "image/jpeg",
"image/wbmp" => "image/jpeg",
);
$settings = new ezcImageConverterSettings(
array( new ezcImageHandlerSettings( "Toby", "fooImageHandlerToby" ) ),
$conversionsIn
);
try
{
$converter = new ezcImageConverter( $settings );
}
catch ( ezcImageHandlerNotAvailableException $e )
{
return;
}
$this->fail( "Expected excption not thrown when creating ezcImageConverter with unsupported handler." );
}
// Transformation tests
public function testCreateTransformation()
{
$transformation = $this->converter->createTransformation( "thumbnail", array(), array() );
$this->assertType(
"ezcImageTransformation",
$transformation,
"Converter does not return created transformation."
);
}
// Issue #12667: ezcImageConverter doesn't pass saveOptions to
// ezcImageTransformation.'
public function testCreateTransformationWithSaveOptions()
{
$options = new ezcImageSaveOptions();
$transformation = $this->converter->createTransformation( "thumbnail", array(), array(), $options );
$this->assertAttributeSame(
$options,
'saveOptions',
$transformation,
"Converter did not pass save options correctly."
);
}
// MIME type tests
public function testAllowsInputSuccess()
{
$this->assertTrue(
$this->converter->allowsInput( "image/jpeg" ),
"Converter does not allow input MIME type <image/jpeg>. This sounds impossible..."
);
}
public function testAllowsInputFailure()
{
$this->assertFalse(
$this->converter->allowsInput( "application/ezc" ),
"Converter allows input MIME type <application/ezc>. This sounds impossible..."
);
}
public function testAllowsOutputSuccess()
{
$this->assertTrue(
$this->converter->allowsOutput( "image/jpeg" ),
"Converter does not allow output MIME type <image/jpeg>. This sounds impossible..."
);
}
public function testAllowsOutputFailure()
{
$this->assertFalse(
$this->converter->allowsOutput( "application/ezc" ),
"Converter allows output MIME type <application/ezc>. This sounds impossible..."
);
}
public function testGetMimeOutSuccessConversionPerformed()
{
$this->assertEquals(
"image/png",
$this->converter->getMimeOut( "image/gif" ),
"Converter converted MIME type incorrectly."
);
}
public function testGetMimeOutSuccessNoConversionPerformed()
{
$this->assertEquals(
"image/jpeg",
$this->converter->getMimeOut( "image/jpeg" ),
"Converter converted MIME type incorrectly."
);
}
public function testGetMimeOutFailure()
{
try
{
$this->converter->getMimeOut( "application/ezc" );
}
catch ( ezcImageMimeTypeUnsupportedException $e )
{
return;
}
$this->fail( "Expected exception not thrown when getting output MIME type for invalid input type." );
}
// Filter tests
public function testHasFilterSuccess()
{
$this->assertTrue(
$this->converter->hasFilter( "scale" ),
"Converter does not have filter <scale>. This sounds impossible..."
);
}
public function testHasFilterFailure()
{
$this->assertFalse(
$this->converter->hasFilter( "ezc" ),
"Converter has filter <ezc>. This sounds impossible..."
);
}
public function testGetFilterNamesIncluded()
{
$standardFilters = array(
"scale",
"scaleWidth",
"scaleHeight",
"scalePercent",
"scaleExact",
"crop",
"colorspace",
);
$this->assertEquals(
array_intersect( $standardFilters, $this->converter->getFilterNames() ),
$standardFilters,
"Converter seems not to support standard filters from GD."
);
}
public function testGetFilterNamesExcluded()
{
$impossibleFilters = array(
"__construct",
"__destruct",
"__get",
"__set",
"__call",
);
$this->assertEquals(
array_intersect( $impossibleFilters, $this->converter->getFilterNames() ),
array(),
"Converter seems to support impossible filters."
);
}
// Conversion tests
public function testApplyFilterSuccessScale()
{
$srcPath = $this->testFiles["jpeg"];
$dstPath = $this->getTempPath();
$this->converter->applyFilter(
new ezcImageFilter(
"scale",
array( "width" => 10, "height" => 10, "direction" => ezcImageGeometryFilters::SCALE_DOWN )
),
$srcPath,
$dstPath
);
$this->assertImageSimilar(
$this->getReferencePath(),
$dstPath,
"Image comparison failed.",
2000
);
}
public function testApplyFilterSuccessColorspace()
{
$srcPath = $this->testFiles["jpeg"];
$dstPath = $this->getTempPath();
$this->converter->applyFilter( new ezcImageFilter( "colorspace", array( "space" => ezcImageColorspaceFilters::COLORSPACE_MONOCHROME ) ),
$srcPath, $dstPath );
$this->assertImageSimilar(
$this->getReferencePath(),
$dstPath,
"Image comparison failed.",
2000
);
}
public function testApplyFilterSuccessColorspaceDefinedHandler()
{
$srcPath = $this->testFiles['jpeg'];
$dstPath = $this->getTempPath();
$this->converter->applyFilter(
new ezcImageFilter(
'colorspace',
array(
'space' => ezcImageColorspaceFilters::COLORSPACE_MONOCHROME
)
),
$srcPath,
$dstPath,
'GD'
);
$this->assertImageSimilar(
$this->getReferencePath(),
$dstPath,
"Image comparison failed.",
2000
);
}
public function testApplyFilterFailureHandlerNotAvailable()
{
$srcPath = $this->testFiles["jpeg"];
$dstPath = $this->getTempPath();
try
{
$this->converter->applyFilter(
new ezcImageFilter( "colorspace", array( "space" => ezcImageColorspaceFilters::COLORSPACE_MONOCHROME ) ),
$srcPath,
$dstPath,
"ezc"
);
}
catch ( ezcImageHandlerNotAvailableException $e )
{
return;
}
$this->fail( "Converter did not throw exception on not available handler while applying filter." );
}
public function testApplyFilterFailurewFilterNotAvailable()
{
$srcPath = $this->testFiles["jpeg"];
$dstPath = $this->getTempPath();
try
{
$this->converter->applyFilter(
new ezcImageFilter( "ezc", array() ),
$srcPath,
$dstPath
);
}
catch ( ezcImageFilterNotAvailableException $e )
{
return;
}
$this->fail( "Converter did not throw exception on not available filter while applying filter." );
}
// Handler retrieval tests
public function testGetHandlerSuccessNoFilterNoInNoOut()
{
$this->assertType(
"ezcImageHandler",
$this->converter->getHandler(),
"Returned object is not an ezcImageHandler."
);
}
public function testGetHandlerSuccessFilterNoInNoOut()
{
$this->assertType(
"ezcImageHandler",
$this->converter->getHandler( "scale" ),
"Returned object is not an ezcImageHandler."
);
}
public function testGetHandlerSuccessNoFilterInNoOut()
{
$this->assertType(
"ezcImageHandler",
$this->converter->getHandler( null, "image/jpeg" ),
"Returned object is not an ezcImageHandler."
);
}
public function testGetHandlerSuccessNoFilterNoInOut()
{
$this->assertType(
"ezcImageHandler",
$this->converter->getHandler( null, null, "image/jpeg" ),
"Returned object is not an ezcImageHandler."
);
}
public function testGetHandlerSuccessFilterInOut()
{
$this->assertType(
"ezcImageHandler",
$this->converter->getHandler( "scale", "image/jpeg", "image/jpeg" ),
"Returned object is not an ezcImageHandler."
);
}
public function testGetHandlerFailureFilterNoInNoOut()
{
try
{
$this->converter->getHandler( "ezc" );
}
catch ( ezcImageHandlerNotAvailableException $e )
{
return;
}
$this->fail( "Converter did not throw exception on request of impossible handler." );
}
public function testGetHandlerFailureNoFilterInNoOut()
{
try
{
$this->converter->getHandler( null, "application/ezc" );
}
catch ( ezcImageHandlerNotAvailableException $e )
{
return;
}
$this->fail( "Converter did not throw exception on request of impossible handler." );
}
public function testGetHandlerFailureNoFilterNoInOut()
{
try
{
$this->converter->getHandler( null, null, "application/ezc" );
}
catch ( ezcImageHandlerNotAvailableException $e )
{
return;
}
$this->fail( "Converter did not throw exception on request of impossible handler." );
}
public function testGetHandlerFailureNotAvailableFilterInOut()
{
try
{
$this->converter->getHandler( "ezc", "application/ezc", "application/ezc" );
}
catch ( ezcImageHandlerNotAvailableException $e )
{
return;
}
$this->fail( "Converter did not throw exception on request of impossible handler." );
}
public function testCreateTransformationFailureCreatedTwice()
{
$this->converter->createTransformation( 'foo', array(), array() );
try
{
$this->converter->createTransformation( 'foo', array(), array() );
$this->fail( 'Expected not thrown on double created transformation.' );
}
catch ( ezcImageTransformationAlreadyExistsException $e )
{}
}
public function testRemoveTransformationSuccess()
{
$this->converter->createTransformation( 'foo', array(), array() );
$transformations = $this->readAttribute( $this->converter, "transformations" );
$this->assertEquals(
1,
count( $transformations )
);
$this->converter->removeTransformation( 'foo' );
$transformations = $this->readAttribute( $this->converter, "transformations" );
$this->assertEquals(
0,
count( $transformations )
);
}
public function testRemoveTransformationFailureNotExists()
{
try
{
$this->converter->removeTransformation( 'foo' );
$this->fail( 'Expected not thrown on remove of non-existent transformation.' );
}
catch ( ezcImageTransformationNotAvailableException $e )
{}
}
public function testApplyTransformationSuccess()
{
$srcPath = $this->testFiles["jpeg"];
$dstPath = $this->getTempPath();
$this->converter->createTransformation(
'foo',
array(
new ezcImageFilter(
"colorspace",
array(
"space" => ezcImageColorspaceFilters::COLORSPACE_MONOCHROME
)
),
),
array( 'image/jpeg' )
);
$this->converter->transform( 'foo', $srcPath, $dstPath );
}
public function testApplyTransformationFailureNonExistent()
{
try
{
$this->converter->transform( 'foo', '', '' );
$this->fail( 'Expected not thrown when non-existent transformation should be applied.' );
}
catch ( ezcImageTransformationNotAvailableException $e )
{}
}
}
?>
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Some files were not shown because too many files have changed in this diff Show More