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