eZ Publish  [4.0]
ezimagegdhandler.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZImageGDHandler class
00004 //
00005 // Created on: <16-Oct-2003 14:22:43 amos>
00006 //
00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00008 // SOFTWARE NAME: eZ Publish
00009 // SOFTWARE RELEASE: 4.0.x
00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00011 // SOFTWARE LICENSE: GNU General Public License v2.0
00012 // NOTICE: >
00013 //   This program is free software; you can redistribute it and/or
00014 //   modify it under the terms of version 2.0  of the GNU General
00015 //   Public License as published by the Free Software Foundation.
00016 //
00017 //   This program is distributed in the hope that it will be useful,
00018 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //   GNU General Public License for more details.
00021 //
00022 //   You should have received a copy of version 2.0 of the GNU General
00023 //   Public License along with this program; if not, write to the Free
00024 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 //   MA 02110-1301, USA.
00026 //
00027 //
00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00029 //
00030 
00031 /*! \file ezimagegdhandler.php
00032 */
00033 
00034 /*!
00035   \class eZImageGDHandler ezimagegdhandler.php
00036   \ingroup eZImage
00037   \brief The class eZImageGDHandler does
00038 
00039   A geometry array has the following entries.
00040   - x - The x position
00041   - y - The y position
00042   - width - The width
00043   - height - The height
00044 */
00045 
00046 //include_once( 'lib/ezimage/classes/ezimagehandler.php' );
00047 
00048 class eZImageGDHandler extends eZImageHandler
00049 {
00050     /*!
00051      Constructor
00052     */
00053     function eZImageGDHandler( $handlerName, $isGloballyEnabled,
00054                                $outputRewriteType = self::REPLACE_SUFFIX,
00055                                $conversionRules = false )
00056     {
00057         $supportedInputMIMETypes = array();
00058         $supportedOutputMIMETypes = array();
00059         $this->InputMap = array();
00060         $this->OutputMap = array();
00061         $this->OutputQualityMap = array();
00062         $isEnabled = false;
00063         if ( function_exists( "imagetypes" ) )
00064         {
00065             $gdFunctions = array( array( 'mimetype' => 'image/gif',
00066                                          'input' => 'imagecreatefromgif',
00067                                          'output' => 'imagegif' ),
00068                                   array( 'mimetype' => 'image/vnd.wap.wbmp',
00069                                          'input' => 'imagecreatefromwbmp',
00070                                          'output' => 'imagewbmp' ),
00071                                   array( 'mimetype' => 'image/png',
00072                                          'input' => 'imagecreatefrompng',
00073                                          'output' => 'imagepng' ),
00074                                   array( 'mimetype' => 'image/jpeg',
00075                                          'input' => 'imagecreatefromjpeg',
00076                                          'output' => 'imagejpeg',
00077                                          'qualityparameter' => true ) );
00078             foreach ( $gdFunctions as $gdFunction )
00079             {
00080                 $inputFunction = $gdFunction['input'];
00081                 $outputFunction = $gdFunction['output'];
00082                 if ( function_exists( $inputFunction ) or function_exists( $outputFunction ) )
00083                 {
00084                     $isEnabled = true;
00085                     $mimeType = $gdFunction['mimetype'];
00086                     if ( function_exists( $inputFunction ) )
00087                     {
00088                         $supportedInputMIMETypes[] = $mimeType;
00089                         $this->InputMap[$mimeType] = $inputFunction;
00090                     }
00091                     if ( function_exists( $outputFunction ) )
00092                     {
00093                         $this->OutputMap[$mimeType] = $outputFunction;
00094                         $supportedOutputMIMETypes[] = $mimeType;
00095                     }
00096                     if ( isset( $gdFunction['qualityparameter'] ) )
00097                         $this->OutputQualityMap[$mimeType] = $gdFunction['qualityparameter'];
00098                     else
00099                         $this->OutputQualityMap[$mimeType] = false;
00100                 }
00101             }
00102         }
00103         if ( !$isGloballyEnabled )
00104             $isEnabled = false;
00105         $this->FilterFunctionMap = array( 'geometry/scale' => 'scaleImage',
00106                                           'geometry/scalewidth' => 'scaleImageWidth',
00107                                           'geometry/scaleheight' => 'scaleImageHeight',
00108                                           'geometry/scaledownonly' => 'scaleImageDownOnly',
00109                                           'geometry/scalewidthdownonly' => 'scaleImageWidthDownOnly',
00110                                           'geometry/scaleheightdownonly' => 'scaleImageHeightDownOnly',
00111                                           'geometry/scaleexact' => 'scaleImageExact',
00112                                           'geometry/scalepercent' => 'scaleImagePercent',
00113                                           'geometry/crop' => 'cropImage',
00114                                           'colorspace/gray' => 'setImageColorspaceGray',
00115                                           'luminance' => 'setImageLuminance',
00116                                           'luminance/gray' => 'setImageLuminanceNamed',
00117                                           'luminance/sepia' => 'setImageLuminanceNamed',
00118                                           'color/monochrome' => 'setImageColorThresholdName',
00119                                           'border' => 'createImageBorder',
00120                                           'border/color' => 'setImageBorderColor',
00121                                           'border/width' => 'setImageBorderWidth' );
00122         $this->LuminanceColorScales = array( 'luminance/gray' => array( 1.0, 1.0, 1.0 ),
00123                                              'luminance/sepia' => array( 1.0, 0.89, 0.74 ) );
00124         $this->ThresholdList = array( 'color/monochrome' => array( array( 'threshold' => 127,
00125                                                                           'rgb' => array( 0, 0, 0 ) ),
00126                                                                    array( 'threshold' => 255,
00127                                                                           'rgb' => array( 255, 255, 255 ) ) ) );
00128 
00129         $filters = array();
00130         foreach ( $this->FilterFunctionMap as $filterName => $filterFunction )
00131         {
00132             $filters[] = array( 'name' => $filterName );
00133         }
00134         $this->eZImageHandler( $handlerName, $isEnabled,
00135                                $outputRewriteType,
00136                                $supportedInputMIMETypes, $supportedOutputMIMETypes,
00137                                $conversionRules, $filters );
00138     }
00139 
00140     /*!
00141      Creates the shell string and runs the executable.
00142     */
00143     function convert( $manager, $sourceMimeData, &$destinationMimeData, $filters = false )
00144     {
00145         $sourceMimeType = $sourceMimeData['name'];
00146         $destinationMimeType = $destinationMimeData['name'];
00147         if ( !isset( $this->InputMap[$sourceMimeType] ) )
00148         {
00149             eZDebug::writeError( "MIME-Type $sourceMimeType is not supported as input by GD converter",
00150                                  'eZImageGDHandler::convert' );
00151             return false;
00152         }
00153         if ( !isset( $this->OutputMap[$destinationMimeType] ) )
00154         {
00155             eZDebug::writeError( "MIME-Type $destinationMimeType is not supported as output by GD converter",
00156                                  'eZImageGDHandler::convert' );
00157             return false;
00158         }
00159 
00160         $inputFunction = $this->InputMap[$sourceMimeType];
00161         $outputFunction = $this->OutputMap[$destinationMimeType];
00162         $outputQualityParameter = $this->OutputQualityMap[$destinationMimeType];
00163         $inputFile = $sourceMimeData['url'];
00164         $outputFile = $destinationMimeData['url'];
00165 
00166         if ( !file_exists( $inputFile ) )
00167         {
00168             eZDebug::writeError( "Source image $inputFile does not exist, cannot convert",
00169                                  'eZImageGDHandler::convert' );
00170             return false;
00171         }
00172 
00173         $currentImage = $inputFunction( $inputFile );
00174 
00175         $filterVariables = array( 'border-color' => array( 127, 127, 127 ),
00176                                   'border-size' => array( 0, 0 ) );
00177 
00178         if ( $filters !== false )
00179         {
00180             foreach ( $filters as $filterData )
00181             {
00182                 $filterName = $filterData['name'];
00183                 if ( isset( $this->FilterFunctionMap[$filterName] ) )
00184                 {
00185                     $filterFunction = $this->FilterFunctionMap[$filterName];
00186                     $filteredImage = $this->$filterFunction( $currentImage, $filterData, $filterVariables, $sourceMimeData, $destinationMimeData );
00187                     if ( $filteredImage !== false )
00188                     {
00189                         if ( $filteredImage != $currentImage )
00190                         {
00191                             ImageDestroy( $currentImage );
00192                         }
00193                         $currentImage = $filteredImage;
00194                     }
00195                 }
00196             }
00197         }
00198 
00199         $outputImage = $currentImage;
00200 
00201         if ( $outputImage )
00202         {
00203             $outputQuality = false;
00204             if ( $outputQualityParameter )
00205                 $outputQuality = $manager->qualityValue( $destinationMimeType );
00206             if ( $outputQuality !== false )
00207             {
00208                 $returnCode = $outputFunction( $outputImage, $outputFile, $outputQuality );
00209             }
00210             else
00211             {
00212                 $returnCode = $outputFunction( $outputImage, $outputFile );
00213             }
00214 
00215             ImageDestroy( $outputImage );
00216         }
00217         else
00218             $returnCode = false;
00219 
00220         if ( $returnCode )
00221         {
00222             if ( !file_exists( $destinationMimeData['url'] ) )
00223             {
00224                 eZDebug::writeError( "Unknown destination file: " . $destinationMimeData['url'], "eZImageGDHandler(" . $this->HandlerName . ")" );
00225                 return false;
00226             }
00227             $this->changeFilePermissions( $destinationMimeData['url'] );
00228             return true;
00229         }
00230         else
00231         {
00232             eZDebug::writeWarning( "Failed converting $inputFile ($sourceMimeType) to $outputFile ($destinationMimeType)", 'eZImageGDHandler::convert' );
00233             return false;
00234         }
00235     }
00236 
00237     static function setImageBorderColor( &$imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00238     {
00239         $filterVariables['border-color'] = $filterData['data'];
00240         return false;
00241     }
00242 
00243     function setImageBorderWidth( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00244     {
00245         $filterVariables['border-size'] = array( $filterData['data'][0], $filterData['data'][0] );
00246         return $this->createImageBorder( $imageObject, $filterData, $filterVariables, $sourceMimeData, $destinationMimeData );
00247     }
00248 
00249     function setImageBorder( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00250     {
00251         $filterVariables['border-size'] = array( $filterData['data'][0], $filterData['data'][1] );
00252         return $this->createImageBorder( $imageObject, $filterData, $filterVariables, $sourceMimeData, $destinationMimeData );
00253     }
00254 
00255     static function createImageBorder( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00256     {
00257         $width = ImageSX( $imageObject );
00258         $height = ImageSY( $imageObject );
00259         $borderWidth = $filterVariables['border-size'][0];
00260         $borderHeight = $filterVariables['border-size'][1];
00261         $borderColor = $filterVariables['border-color'];
00262         $newWidth = $width + $borderWidth*2;
00263         $newHeight = $height + $borderHeight*2;
00264 
00265         $temporaryImageObject = $this->imageCopy( $imageObject,
00266                                                   $this->createGeometry( $newWidth, $newHeight, $borderWidth, $borderHeight ),
00267                                                   $this->createGeometry( $width, $height, 0, 0 ),
00268                                                   $sourceMimeData, $destinationMimeData );
00269         $color = ImageColorAllocate( $temporaryImageObject, $borderColor[0], $borderColor[1], $borderColor[2] );
00270         ImageFilledRectangle( $temporaryImageObject, 0, 0, $newWidth, $borderHeight, $color );
00271         ImageFilledRectangle( $temporaryImageObject, $newWidth - $borderWidth, 0, $newWidth, $newHeight, $color );
00272         ImageFilledRectangle( $temporaryImageObject, 0, $newHeight - $borderHeight, $newWidth, $newHeight, $color );
00273         ImageFilledRectangle( $temporaryImageObject, 0, 0, $borderWidth, $newHeight, $color );
00274         return $temporaryImageObject;
00275     }
00276 
00277     /*!
00278      Converts the image to grayscale.
00279     */
00280     function setImageColorspaceGray( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00281     {
00282         $colorScale = array( 1.0, 1.0, 1.0 );
00283         return $this->setImageLuminanceColorScale( $imageObject, $filterData, $sourceMimeData, $destinationMimeData,
00284                                                    $colorScale );
00285     }
00286 
00287     /*!
00288      Changes the colors of the image based on the luminance.
00289      The new scale for the colors are taken from the filter parameters, the parameters must contain three values.
00290     */
00291     function setImageLuminance( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00292     {
00293         $colorScale = $filterData['data'];
00294         return $this->setImageLuminanceColorScale( $imageObject, $filterData, $sourceMimeData, $destinationMimeData,
00295                                                    $colorScale );
00296     }
00297 
00298     /*!
00299      Changes the colors of the image based on the luminance.
00300      The new scale for the colors are based on the name of the filters.
00301     */
00302     function setImageLuminanceNamed( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00303     {
00304         if ( isset( $this->LuminanceColorScales[$filterData['name']] ) )
00305         {
00306             $colorScale = $this->LuminanceColorScales[$filterData['name']];
00307         }
00308         else
00309         {
00310             eZDebug::writeDebug( "No luminance scale named " . $filterData['name'] . ", applying gray scales",
00311                                  'eZImageGDHandler::setImageLuminanceName' );
00312             $colorScale = array( 1.0, 1.0, 1.0 );
00313         }
00314         return $this->setImageLuminanceColorScale( $imageObject, $filterData, $sourceMimeData, $destinationMimeData,
00315                                                    $colorScale );
00316     }
00317 
00318     /*!
00319      Changes the colors of the image based on the luminance.
00320      \param $colorScale is an array with three float elements in range 0 to 1 that define the new color scale.
00321     */
00322     function setImageLuminanceColorScale( $imageObject, $filterData, $sourceMimeData, $destinationMimeData,
00323                                           $colorScale )
00324     {
00325         $white = ImageColorAllocate( $imageObject, 255, 255, 255 );
00326         $black = ImageColorAllocate( $imageObject, 0, 0, 0 );
00327 
00328         $rmod = $colorScale[0];
00329         $gmod = $colorScale[1];
00330         $bmod = $colorScale[2];
00331 
00332         $width = ImageSX( $imageObject );
00333         $height = ImageSY( $imageObject );
00334         for ( $y = 0; $y < $height; ++$y )
00335         {
00336             for ( $x = 0; $x < $width; ++$x )
00337             {
00338                 $rgb = ImageColorAt( $imageObject, $x, $y );
00339 
00340                 $r = ( $rgb >> 16 ) & 0xff;
00341                 $g = ( $rgb >> 8 ) & 0x0ff;
00342                 $b = ( $rgb ) & 0x0ff;
00343 
00344                 $luminance = ( $r * 0.3 ) + ( $g * 0.59 ) + ( $b * 0.11 );
00345 
00346                 $r = $luminance * $rmod;
00347                 $g = $luminance * $gmod;
00348                 $b = $luminance * $bmod;
00349 
00350                 $color = ImageColorAllocate( $imageObject, $r, $g, $b );
00351 
00352                 ImageSetPixel( $imageObject, $x, $y, $color );
00353             }
00354         }
00355         return $imageObject;
00356     }
00357 
00358     /*!
00359      Changes the colors of the image based on threshold values.
00360      The threshold values are based on the filter name.
00361     */
00362     function setImageColorThresholdName( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00363     {
00364         if ( isset( $this->ThresholdList[$filterData['name']] ) )
00365         {
00366             $thresholdList = $this->ThresholdList[$filterData['name']];
00367         }
00368         else
00369         {
00370             eZDebug::writeDebug( "No threshold values named " . $filterData['name'] . ", applying black/white (monochrome) threshold",
00371                                  'eZImageGDHandler::setImageLuminanceName' );
00372             $thresholdList = array( array( 'threshold' => 127,
00373                                            'rgb' => array( 0, 0, 0 ) ),
00374                                     array( 'threshold' => 255,
00375                                            'rgb' => array( 255, 255, 255 ) ) );
00376         }
00377         return $this->setImageColorThreshold( $imageObject, $filterData, $sourceMimeData, $destinationMimeData,
00378                                               $thresholdList );
00379     }
00380 
00381     /*!
00382      Changes the colors of the image based on threshold values. The luminance will be calculated and if it is
00383      in a threshold range it will use the specified color for the range.
00384     */
00385     static function setImageColorThreshold( $imageObject, $filterData, $sourceMimeData, $destinationMimeData,
00386                                             $thresholdList )
00387     {
00388         foreach ( array_keys( $thresholdList ) as $thresholdKey )
00389         {
00390             $thresholdList[$thresholdKey]['color'] = ImageColorAllocate( $imageObject, $thresholdItem['rgb'][0], $thresholdItem['rgb'][1], $thresholdItem['rgb'][2] );
00391         }
00392         $defaultColor = $thresholdList[count( $thresholdList ) - 1]['color'];
00393 
00394         $width = ImageSX( $imageObject );
00395         $height = ImageSY( $imageObject );
00396         for ( $y = 0; $y < $height; ++$y )
00397         {
00398             for ( $x = 0; $x < $width; ++$x )
00399             {
00400                 $rgb = ImageColorAt( $imageObject, $x, $y );
00401 
00402                 $r = ( $rgb >> 16 ) & 0xff;
00403                 $g = ( $rgb >> 8 ) & 0x0ff;
00404                 $b = ( $rgb ) & 0x0ff;
00405 
00406                 $luminance = ( $r * 0.3 ) + ( $g * 0.59 ) + ( $b * 0.11 );
00407 
00408                 $color = false;
00409                 foreach ( $thresholdList as $thresholdItem )
00410                 {
00411                     if ( $luminance <= $thresholdItem['threshold'] )
00412                     {
00413                         $color = $thresholdItem['color'];
00414                         break;
00415                     }
00416                 }
00417                 if ( $color === false )
00418                     $color = $defaultColor;
00419 
00420                 ImageSetPixel( $imageObject, $x, $y, $color );
00421             }
00422         }
00423         return $imageObject;
00424     }
00425 
00426     /*!
00427       Crops a portion of the image from the filter parameters.
00428     */
00429     function cropImage( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00430     {
00431         $width = $filterData['data'][0];
00432         $height = $filterData['data'][1];
00433         $x = $filterData['data'][2];
00434         $y = $filterData['data'][3];
00435         $imageWidth = ImageSX( $imageObject );
00436         $imageHeight = ImageSY( $imageObject );
00437         $width = max( min( $width, $imageWidth - $x ), 0 );
00438         $height = max( min( $height, $imageHeight - $y ), 0 );
00439         $destinationGeometry = $this->createGeometry( $width, $height, 0, 0 );
00440         $geometry = $this->createGeometry( $width, $height, $x, $y );
00441         return $this->imageCopy( $imageObject,
00442                                  $destinationGeometry,
00443                                  $geometry,
00444                                  $sourceMimeData, $destinationMimeData );
00445     }
00446 
00447     /*!
00448      Scales the image \a $imageObject to the size specified in \a $filterData with aspect ration maintained.
00449      This means that image will not be exactly the image size.
00450      \sa scaleImageExact
00451     */
00452     function scaleImage( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00453     {
00454         $geometry = $this->calculateScaledAspectGeometry( ImageSX( $imageObject ), ImageSY( $imageObject ),
00455                                                           $filterData['data'][0], $filterData['data'][1], true );
00456         return $this->scaleImageCopy( $imageObject,
00457                                       $geometry,
00458                                       $sourceMimeData, $destinationMimeData );
00459     }
00460 
00461     /*!
00462      Scales the image \a $imageObject to the size specified in \a $filterData with aspect ration maintained.
00463      This means that image will not be exactly the image size.
00464      \note The image will not be scaled if the source size is smaller than the destination size.
00465      \sa scaleImageExact
00466     */
00467     function scaleImageDownOnly( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00468     {
00469         $geometry = $this->calculateScaledAspectGeometry( ImageSX( $imageObject ), ImageSY( $imageObject ),
00470                                                           $filterData['data'][0], $filterData['data'][1], false );
00471         return $this->scaleImageCopy( $imageObject,
00472                                       $geometry,
00473                                       $sourceMimeData, $destinationMimeData );
00474     }
00475 
00476     /*!
00477      Scales the image \a $imageObject to the size specified in \a $filterData with aspect ration maintained.
00478      This means that image will not be exactly the image size.
00479      \sa scaleImageExact
00480     */
00481     function scaleImageWidth( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00482     {
00483         $geometry = $this->calculateFixedWidthAspectGeometry( ImageSX( $imageObject ), ImageSY( $imageObject ),
00484                                                               $filterData['data'][0], true );
00485         return $this->scaleImageCopy( $imageObject,
00486                                       $geometry,
00487                                       $sourceMimeData, $destinationMimeData );
00488     }
00489 
00490     /*!
00491      Scales the image \a $imageObject to the size specified in \a $filterData with aspect ration maintained.
00492      This means that image will not be exactly the image size.
00493      \sa scaleImageExact
00494     */
00495     function scaleImageHeight( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00496     {
00497         $geometry = $this->calculateFixedHeightAspectGeometry( ImageSX( $imageObject ), ImageSY( $imageObject ),
00498                                                                $filterData['data'][0], true );
00499         return $this->scaleImageCopy( $imageObject,
00500                                       $geometry,
00501                                       $sourceMimeData, $destinationMimeData );
00502     }
00503 
00504     /*!
00505      Scales the image \a $imageObject to the size specified in \a $filterData with aspect ration maintained.
00506      This means that image will not be exactly the image size.
00507      \note The image will not be scaled if the source size is smaller than the destination size.
00508      \sa scaleImageExact
00509     */
00510     function scaleImageWidthDownOnly( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00511     {
00512         $geometry = $this->calculateFixedWidthAspectGeometry( ImageSX( $imageObject ), ImageSY( $imageObject ),
00513                                                               $filterData['data'][0], false );
00514         return $this->scaleImageCopy( $imageObject,
00515                                       $geometry,
00516                                       $sourceMimeData, $destinationMimeData );
00517     }
00518 
00519     /*!
00520      Scales the image \a $imageObject to the size specified in \a $filterData with aspect ration maintained.
00521      This means that image will not be exactly the image size.
00522      \note The image will not be scaled if the source size is smaller than the destination size.
00523      \sa scaleImageExact
00524     */
00525     function scaleImageHeightDownOnly( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00526     {
00527         $geometry = $this->calculateFixedHeightAspectGeometry( ImageSX( $imageObject ), ImageSY( $imageObject ),
00528                                                                $filterData['data'][0], false );
00529         return $this->scaleImageCopy( $imageObject,
00530                                       $geometry,
00531                                       $sourceMimeData, $destinationMimeData );
00532     }
00533 
00534     /*!
00535      Scales the image \a $imageObject to the size specified in \a $filterData without caring about aspect ratio.
00536     */
00537     function scaleImageExact( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00538     {
00539         return $this->scaleImageCopy( $imageObject,
00540                                       $this->createGeometry( $filterData['data'][0], $filterData['data'][1] ),
00541                                       $sourceMimeData, $destinationMimeData );
00542     }
00543 
00544     /*!
00545      Scales the image \a $imageObject to the size specified in \a $filterData with aspect ratio maintained.
00546     */
00547     function scaleImagePercent( $imageObject, $filterData, &$filterVariables, $sourceMimeData, $destinationMimeData )
00548     {
00549         $geometry = $this->calculateScaledPercentAspectGeometry( ImageSX( $imageObject ), ImageSY( $imageObject ),
00550                                                                  $filterData['data'][0] / 100.0, $filterData['data'][1] / 100.0, true );
00551         return $this->scaleImageCopy( $imageObject,
00552                                       $geometry,
00553                                       $sourceMimeData, $destinationMimeData );
00554     }
00555 
00556     /*!
00557      Calculates the geometry for the scaled image while maintaining the aspect ratio.
00558      \param $allowUpScale If this is true images will be scaled up as well, if not they will keep their source size.
00559      \return a geometry array.
00560      \sa createGeometry
00561     */
00562     function calculateScaledAspectGeometry( $sourceWidth, $sourceHeight,
00563                                             $destinationWidth, $destinationHeight,
00564                                             $allowUpScale )
00565     {
00566         $widthScale = $sourceWidth / $destinationWidth;
00567         $heightScale = $sourceHeight / $destinationHeight;
00568 
00569         $scale = $heightScale;
00570         if ( $heightScale != $widthScale )
00571             $scale = max( $heightScale, $widthScale );
00572 
00573         if ( $scale < 1.0 and !$allowUpScale )
00574         {
00575             $destinationWidth = $sourceWidth;
00576             $destinationHeight = $sourceHeight;
00577         }
00578         else
00579         {
00580             $destinationWidth = (int) ( $sourceWidth / $scale );
00581             $destinationHeight = (int) ( $sourceHeight / $scale );
00582         }
00583         return $this->createGeometry( $destinationWidth, $destinationHeight );
00584     }
00585 
00586     /*!
00587      Calculates the geometry for the scaled image in terms of percent while maintaining the aspect ratio.
00588      \param $allowUpScale If this is true images will be scaled up as well, if not they will keep their source size.
00589      \note Percentage must be given as a float value, e.g. 50% is 0.5 and 200% is 2.0
00590      \return a geometry array.
00591      \sa createGeometry
00592     */
00593     function calculateScaledPercentAspectGeometry( $sourceWidth, $sourceHeight,
00594                                                    $destinationWidthPercent, $destinationHeightPercent,
00595                                                    $allowUpScale )
00596     {
00597         $destinationWidth = $sourceWidth * $destinationWidthPercent;
00598         $destinationHeight = $sourceHeight * $destinationHeightPercent;
00599         return $this->calculateScaledAspectGeometry( $sourceWidth, $sourceHeight,
00600                                                      $destinationWidth, $destinationHeight,
00601                                                      $allowUpScale );
00602     }
00603 
00604     /*!
00605      Calculates the geometry for the scaled image with a fixed width while maintaining the aspect ratio.
00606      \param $allowUpScale If this is true images will be scaled up as well, if not they will keep their source size.
00607      \return a geometry array.
00608      \sa createGeometry
00609     */
00610     function calculateFixedWidthAspectGeometry( $sourceWidth, $sourceHeight,
00611                                                 $destinationWidth,
00612                                                 $allowUpScale )
00613     {
00614         $scale = $sourceWidth / $destinationWidth;
00615 
00616         if ( $scale < 1.0 and !$allowUpScale )
00617         {
00618             $destinationWidth = $sourceWidth;
00619             $destinationHeight = $sourceHeight;
00620         }
00621         else
00622         {
00623             $destinationWidth = (int) ( $sourceWidth / $scale );
00624             $destinationHeight = (int) ( $sourceHeight / $scale );
00625         }
00626         return $this->createGeometry( $destinationWidth, $destinationHeight );
00627     }
00628 
00629     /*!
00630      Calculates the geometry for the scaled image with a fixed height while maintaining the aspect ratio.
00631      \param $allowUpScale If this is true images will be scaled up as well, if not they will keep their source size.
00632      \return a geometry array.
00633      \sa createGeometry
00634     */
00635     function calculateFixedHeightAspectGeometry( $sourceWidth, $sourceHeight,
00636                                                  $destinationHeight,
00637                                                  $allowUpScale )
00638     {
00639         $scale = $sourceHeight / $destinationHeight;
00640 
00641         if ( $scale < 1.0 and !$allowUpScale )
00642         {
00643             $destinationWidth = $sourceWidth;
00644             $destinationHeight = $sourceHeight;
00645         }
00646         else
00647         {
00648             $destinationWidth = (int) ( $sourceWidth / $scale );
00649             $destinationHeight = (int) ( $sourceHeight / $scale );
00650         }
00651         return $this->createGeometry( $destinationWidth, $destinationHeight );
00652     }
00653 
00654     /*!
00655      Scales the image \a $imageObject to the size specified in \a $filterData.
00656     */
00657     static function scaleImageCopy( $imageObject,
00658                                     $geometry,
00659                                     $sourceMimeData, $destinationMimeData )
00660     {
00661         $destinationWidth = $geometry['width'];
00662         $destinationHeight = $geometry['height'];
00663         $sourceWidth = ImageSX( $imageObject );
00664         $sourceHeight = ImageSY( $imageObject );
00665 
00666         $temporaryImageObject = eZImageGDHandler::imageCreate( $destinationWidth, $destinationHeight, eZImageGDHandler::isImageTrueColor( $imageObject, $sourceMimeData ) );
00667         ImageCopyResampled( $temporaryImageObject, $imageObject,
00668                             0, 0, 0, 0,
00669                             $destinationWidth, $destinationHeight, $sourceWidth, $sourceHeight );
00670         return $temporaryImageObject;
00671     }
00672 
00673     /*!
00674       Copies a portion of the source image \a $imageObject to a new image.
00675     */
00676     static function imageCopy( $imageObject, $destinationGeometry, $sourceGeometry,
00677                                $sourceMimeData, $destinationMimeData )
00678     {
00679         $destinationWidth = $destinationGeometry['width'];
00680         $destinationHeight = $destinationGeometry['height'];
00681 
00682         $temporaryImageObject = eZImageGDHandler::imageCreate( $destinationWidth, $destinationHeight, eZImageGDHandler::isImageTrueColor( $imageObject, $sourceMimeData ) );
00683         ImageCopy( $temporaryImageObject, $imageObject,
00684                    $destinationGeometry['x'], $destinationGeometry['y'],
00685                    $sourceGeometry['x'], $sourceGeometry['y'], $sourceGeometry['width'], $sourceGeometry['height'] );
00686         return $temporaryImageObject;
00687     }
00688 
00689     /*!
00690      \static
00691      \return \c true if the image object \a $imageObject is in true color format.
00692     */
00693     static function isImageTrueColor( &$imageObject, $mimeData )
00694     {
00695         if ( eZSys::isPHPVersionSufficient( array( 4, 3, 2 ) ) )
00696             return ImageIsTrueColor( $imageObject );
00697         $nonTrueColorMimeTypes = array( 'image/gif' );
00698         if ( in_array( $sourceMimeData['name'], $nonTrueColorMimeTypes ) )
00699             return false;
00700         return true;
00701     }
00702 
00703     /*!
00704      Creates a new GD image and returns it.
00705      \param $isTrueColor determines if a true color image is created, if false an indexed image is created.
00706     */
00707     static function imageCreate( $width, $height, $isTrueColor = true )
00708     {
00709         if ( $isTrueColor )
00710             return ImageCreateTrueColor( $width, $height );
00711         else
00712             return ImageCreate( $width, $height );
00713     }
00714 
00715     /*!
00716      Creates a geometry array with width \a $width, height \a $height, x position \a $x and y position \a $y and returns it.
00717     */
00718     static function createGeometry( $width, $height, $x = 0, $y = 0 )
00719     {
00720         return array( 'x' => $x,
00721                       'y' => $y,
00722                       'width' => $width,
00723                       'height' => $height );
00724     }
00725 
00726     /*!
00727      Creates a new image handler for shell executable from INI settings.
00728      The INI settings are read from ini file \a $iniFilename and group \a $iniGroup.
00729      If \a $iniFilename is not supplied \c image.ini is used.
00730     */
00731     static function createFromINI( $iniGroup, $iniFilename = false )
00732     {
00733         if ( !$iniFilename )
00734             $iniFilename = 'image.ini';
00735 
00736         $handler = false;
00737         //include_once( 'lib/ezutils/classes/ezini.php' );
00738         $ini = eZINI::instance( $iniFilename );
00739         if ( !$ini )
00740         {
00741             eZDebug::writeError( "Failed loading ini file $iniFilename",
00742                                  'eZImageGDHandler::createFromINI' );
00743             return $handler;
00744         }
00745 
00746         if ( $ini->hasGroup( $iniGroup ) )
00747         {
00748             $name = $iniGroup;
00749             if ( $ini->hasVariable( $iniGroup, 'Name' ) )
00750                 $name = $ini->variable( $iniGroup, 'Name' );
00751             $conversionRules = false;
00752             if ( $ini->hasVariable( $iniGroup, 'ConversionRules' ) )
00753             {
00754                 $conversionRules = array();
00755                 $rules = $ini->variable( $iniGroup, 'ConversionRules' );
00756                 foreach ( $rules as $ruleString )
00757                 {
00758                     $ruleItems = explode( ';', $ruleString );
00759                     if ( count( $ruleItems ) >= 2 )
00760                     {
00761                         $conversionRules[] = array( 'from' => $ruleItems[0],
00762                                                     'to' => $ruleItems[1] );
00763                     }
00764                 }
00765             }
00766             $isEnabled = $ini->variable( $iniGroup, 'IsEnabled' ) == 'true';
00767             $outputRewriteType = self::REPLACE_SUFFIX;
00768             $handler = new eZImageGDHandler( $name, $isEnabled,
00769                                              $outputRewriteType,
00770                                              $conversionRules );
00771             return $handler;
00772         }
00773         return $handler;
00774     }
00775 
00776     /// \privatesection
00777     public $Path;
00778     public $Executable;
00779     public $PreParameters;
00780     public $PostParameters;
00781 }
00782 
00783 ?>