[ Index ]
 

Code source de Typo3 4.1.3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/t3lib/ -> class.t3lib_stdgraphic.php (source)

   1  <?php
   2  /***************************************************************
   3  *  Copyright notice
   4  *
   5  *  (c) 1999-2007 Kasper Skaarhoj (kasperYYYY@typo3.com)
   6  *  All rights reserved
   7  *
   8  *  This script is part of the TYPO3 project. The TYPO3 project is
   9  *  free software; you can redistribute it and/or modify
  10  *  it under the terms of the GNU General Public License as published by
  11  *  the Free Software Foundation; either version 2 of the License, or
  12  *  (at your option) any later version.
  13  *
  14  *  The GNU General Public License can be found at
  15  *  http://www.gnu.org/copyleft/gpl.html.
  16  *  A copy is found in the textfile GPL.txt and important notices to the license
  17  *  from the author is found in LICENSE.txt distributed with these scripts.
  18  *
  19  *
  20  *  This script is distributed in the hope that it will be useful,
  21  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  22  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23  *  GNU General Public License for more details.
  24  *
  25  *  This copyright notice MUST APPEAR in all copies of the script!
  26  ***************************************************************/
  27  /**
  28   * Standard graphical functions
  29   *
  30   * $Id: class.t3lib_stdgraphic.php 2572 2007-10-16 16:07:41Z mundaun $
  31   * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
  32   *
  33   * @author    Kasper Skaarhoj <kasperYYYY@typo3.com>
  34   */
  35  /**
  36   * [CLASS/FUNCTION INDEX of SCRIPT]
  37   *
  38   *
  39   *
  40   *  155: class t3lib_stdGraphic
  41   *  236:     function init()
  42   *
  43   *              SECTION: Layering images / "IMAGE" GIFBUILDER object
  44   *  366:     function maskImageOntoImage(&$im,$conf,$workArea)
  45   *  436:     function copyImageOntoImage(&$im,$conf,$workArea)
  46   *  458:     function copyGifOntoGif(&$im,$cpImg,$conf,$workArea)
  47   *  537:     function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h)
  48   *
  49   *              SECTION: Text / "TEXT" GIFBUILDER object
  50   *  587:     function makeText(&$im,$conf,$workArea)
  51   *  707:     function txtPosition($conf,$workArea,$BB)
  52   *  761:     function calcBBox($conf)
  53   *  820:     function addToMap($cords,$conf)
  54   *  843:     function calcTextCordsForMap($cords,$offset, $conf)
  55   *  878:     function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1)
  56   *  915:     function fontResize($conf)
  57   *  958:     function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1)
  58   * 1005:     function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1)
  59   * 1058:     function splitString($string,$splitRendering,$fontSize,$fontFile)
  60   * 1208:     function calcWordSpacing($conf, $scaleFactor=1)
  61   * 1227:     function getTextScalFactor($conf)
  62   *
  63   *              SECTION: Other GIFBUILDER objects related to TEXT
  64   * 1262:     function makeOutline(&$im,$conf,$workArea,$txtConf)
  65   * 1291:     function circleOffset($distance, $iterations)
  66   * 1315:     function makeEmboss(&$im,$conf,$workArea,$txtConf)
  67   * 1337:     function makeShadow(&$im,$conf,$workArea,$txtConf)
  68   *
  69   *              SECTION: Other GIFBUILDER objects
  70   * 1469:     function makeBox(&$im,$conf,$workArea)
  71   * 1491:     function makeEffect(&$im, $conf)
  72   * 1506:     function IMparams($setup)
  73   * 1589:     function adjust(&$im, $conf)
  74   * 1621:     function crop(&$im,$conf)
  75   * 1652:     function scale(&$im,$conf)
  76   * 1684:     function setWorkArea($workArea)
  77   *
  78   *              SECTION: Adjustment functions
  79   * 1725:     function autolevels(&$im)
  80   * 1756:     function outputLevels(&$im,$low,$high,$swap='')
  81   * 1788:     function inputLevels(&$im,$low,$high,$swap='')
  82   * 1819:     function reduceColors(&$im,$limit, $cols)
  83   * 1832:     function IMreduceColors($file, $cols)
  84   *
  85   *              SECTION: GIFBUILDER Helper functions
  86   * 1875:     function prependAbsolutePath($fontFile)
  87   * 1889:     function v5_sharpen($factor)
  88   * 1908:     function v5_blur($factor)
  89   * 1925:     function randomName()
  90   * 1938:     function applyOffset($cords,$OFFSET)
  91   * 1951:     function convertColor($string)
  92   * 2001:     function recodeString($string)
  93   * 2023:     function singleChars($theText,$returnUnicodeNumber=FALSE)
  94   * 2046:     function objPosition($conf,$workArea,$BB)
  95   *
  96   *              SECTION: Scaling, Dimensions of images
  97   * 2125:     function imageMagickConvert($imagefile,$newExt='',$w='',$h='',$params='',$frame='',$options='',$mustCreate=0)
  98   * 2238:     function getImageDimensions($imageFile)
  99   * 2266:     function cacheImageDimensions($identifyResult)
 100   * 2298:     function getCachedImageDimensions($imageFile)
 101   * 2332:     function getImageScale($info,$w,$h,$options)
 102   * 2438:     function file_exists_typo3temp_file($output,$orig='')
 103   *
 104   *              SECTION: ImageMagick API functions
 105   * 2499:     function imageMagickIdentify($imagefile)
 106   * 2534:     function imageMagickExec($input,$output,$params)
 107   * 2557:     function combineExec($input,$overlay,$mask,$output, $handleNegation = false)
 108   * 2588:     function wrapFileName($inputName)
 109   *
 110   *              SECTION: Various IO functions
 111   * 2629:     function checkFile($file)
 112   * 2643:     function createTempSubDir($dirName)
 113   * 2665:     function applyImageMagickToPHPGif(&$im, $command)
 114   * 2691:     function gif_or_jpg($type,$w,$h)
 115   * 2708:     function output($file)
 116   * 2748:     function destroy()
 117   * 2758:     function imgTag ($imgInfo)
 118   * 2770:     function ImageWrite($destImg, $theImage)
 119   * 2808:     function imageGif($destImg, $theImage)
 120   * 2820:     function imageCreateFromGif($sourceImg)
 121   * 2831:     function imageCreateFromFile($sourceImg)
 122   * 2870:     function imagecreate($w, $h)
 123   * 2885:     function hexColor($col)
 124   * 2903:     function unifyColors(&$img, $colArr, $closest = false)
 125   *
 126   * TOTAL FUNCTIONS: 66
 127   * (This index is automatically created/updated by the extension "extdeveval")
 128   *
 129   */
 130  
 131  
 132  
 133  
 134  
 135  
 136  
 137  
 138  
 139  
 140  
 141  
 142  
 143  
 144  
 145  
 146  /**
 147   * Class contains a bunch of cool functions for manipulating graphics with GDlib/Freetype and ImageMagick
 148   * VERY OFTEN used with gifbuilder that extends this class and provides a TypoScript API to using these functions
 149   *
 150   * @author    Kasper Skaarhoj <kasperYYYY@typo3.com>
 151   * @package TYPO3
 152   * @subpackage t3lib
 153   * @see tslib_gifBuilder
 154   */
 155  class t3lib_stdGraphic    {
 156  
 157          // Internal configuration, set in init()
 158      var $combineScript = 'combine';                // The ImageMagick filename used for combining two images. This name changed during the versions.
 159      var $noFramePrepended=0;                    // If set, there is no frame pointer prepended to the filenames.
 160      var $GD2=0;                                    // Set, if the GDlib used is version 2.
 161      var $imagecopyresized_fix=0;                // If set, imagecopyresized will not be called directly. For GD2 (some PHP installs?)
 162      var $gifExtension = 'gif';                    // This should be changed to 'png' if you want this class to read/make PNG-files instead!
 163      var $gdlibExtensions = '';            // File formats supported by gdlib. This variable get's filled in "init" method
 164      var $truecolor = true;                    // Internal variable which get's used to determine wheter GDlib should use function truecolor pendants
 165      var $png_truecolor = false;                    // Set to true if generated png's should be truecolor by default
 166      var $truecolorColors = 0xffffff;            // 16777216 Colors is the maximum value for PNG, JPEG truecolor images (24-bit, 8-bit / Channel)
 167      var $TTFLocaleConv = '';                    // Used to recode input to TTF-functions for other charsets.
 168      var $enable_typo3temp_db_tracking = 0;        // If set, then all files in typo3temp will be logged in a database table. In addition to being a log of the files with original filenames, it also serves to secure that the same image is not rendered simultaneously by two different processes.
 169      var $imageFileExt = 'gif,jpg,jpeg,png,tif,bmp,tga,pcx,ai,pdf';    // Commalist of file extensions perceived as images by TYPO3. List should be set to 'gif,png,jpeg,jpg' if IM is not available. Lowercase and no spaces between!
 170      var $webImageExt = 'gif,jpg,jpeg,png';        // Commalist of web image extensions (can be shown by a webbrowser)
 171      var $maskNegate = '';                        // Will be ' -negate' if ImageMagick ver 5.2+. See init();
 172      var $NO_IM_EFFECTS = '';
 173      var $cmds = Array (
 174          'jpg' => '',
 175          'jpeg' => '',
 176          'gif' => '-colors 64',
 177          'png' => '-colors 64'
 178      );
 179      var $NO_IMAGE_MAGICK = '';
 180      var $V5_EFFECTS = 0;
 181      var $im_version_4 = 0;
 182      var $mayScaleUp = 1;
 183  
 184          // Variables for testing, alternative usage etc.
 185      var $filenamePrefix='';                                // Filename prefix for images scaled in imageMagickConvert()
 186      var $imageMagickConvert_forceFileNameBody='';        // Forcing the output filename of imageMagickConvert() to this value. However after calling imageMagickConvert() it will be set blank again.
 187      var $dontCheckForExistingTempFile = 0;                // This flag should always be false. If set true, imageMagickConvert will always write a new file to the tempdir! Used for debugging.
 188      var $dontCompress=0;                                // Prevents imageMagickConvert() from compressing the gif-files with t3lib_div::gif_compress()
 189      var $dontUnlinkTempFiles=0;                            // For debugging ONLY!
 190      var $alternativeOutputKey='';                        // For debugging only. Filenames will not be based on mtime and only filename (not path) will be used. This key is also included in the hash of the filename...
 191  
 192          // Internal:
 193      var $IM_commands = Array();                            // All ImageMagick commands executed is stored in this array for tracking. Used by the Install Tools Image section
 194      var $workArea = Array();
 195  
 196          // Constants:
 197      var $tempPath = 'typo3temp/';                        // The temp-directory where to store the files. Normally relative to PATH_site but is allowed to be the absolute path AS LONG AS it is a subdir to PATH_site.
 198      var $absPrefix = '';                                // Prefix for relative paths. Used in "show_item.php" script. Is prefixed the output file name IN imageMagickConvert()
 199      var $scalecmd = '-geometry';                        // ImageMagick scaling command; "-geometry" eller "-sample". Used in makeText() and imageMagickConvert()
 200      var $im5fx_blurSteps='1x2,2x2,3x2,4x3,5x3,5x4,6x4,7x5,8x5,9x5';            // Used by v5_blur() to simulate 10 continuous steps of blurring
 201      var $im5fx_sharpenSteps='1x2,2x2,3x2,2x3,3x3,4x3,3x4,4x4,4x5,5x5';        // Used by v5_sharpen() to simulate 10 continuous steps of sharpening.
 202      var $pixelLimitGif = 10000;                            // This is the limit for the number of pixels in an image before it will be rendered as JPG instead of GIF/PNG
 203      var $colMap = Array (                                // Array mapping HTML color names to RGB values.
 204          'aqua' => Array(0,255,255),
 205          'black' => Array(0,0,0),
 206          'blue' => Array(0,0,255),
 207          'fuchsia' => Array(255,0,255),
 208          'gray' => Array(128,128,128),
 209          'green' => Array(0,128,0),
 210          'lime' => Array(0,255,0),
 211          'maroon' => Array(128,0,0),
 212          'navy' => Array(0,0,128),
 213          'olive' => Array(128,128,0),
 214          'purple' => Array(128,0,128),
 215          'red' => Array(255,0,0),
 216          'silver' => Array(192,192,192),
 217          'teal' => Array(0,128,128),
 218          'yellow' => Array(255,255,0),
 219          'white' => Array(255,255,255)
 220      );
 221  
 222          // Charset conversion object:
 223      var $csConvObj;
 224      var $nativeCharset='';        // Is set to the native character set of the input strings.
 225  
 226  
 227  
 228  
 229  
 230      /**
 231       * Init function. Must always call this when using the class.
 232       * This function will read the configuration information from $GLOBALS['TYPO3_CONF_VARS']['GFX'] can set some values in internal variables.
 233       *
 234       * @return    void
 235       */
 236  	function init()    {
 237          $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
 238  
 239          if (function_exists('imagecreatefromjpeg')&&function_exists('imagejpeg'))    {
 240              $this->gdlibExtensions .= ',jpg,jpeg';
 241          }
 242          if (function_exists('imagecreatefrompng')&&function_exists('imagepng'))    {
 243              $this->gdlibExtensions .= ',png';
 244          }
 245          if (function_exists('imagecreatefromgif')&&function_exists('imagegif'))    {
 246              $this->gdlibExtensions .= ',gif';
 247          }
 248          if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['png_truecolor'])    {
 249              $this->png_truecolor = true;
 250          }
 251          if (!$gfxConf['gdlib_2'] || !function_exists('imagecreatetruecolor'))    {
 252              $this->truecolor = false;
 253          }
 254          if (!$gfxConf['im_version_5'])    {
 255              $this->im_version_4 = true;
 256          }
 257  
 258              // When GIFBUILDER gets used in truecolor mode (GD2 required)
 259          if ($this->truecolor)    {
 260              if ($this->png_truecolor)    {
 261                  $this->cmds['png'] = '';    // No colors parameter if we generate truecolor images.
 262              }
 263              $this->cmds['gif'] = '';    // No colors parameter if we generate truecolor images.
 264          }
 265  
 266              // Setting default JPG parameters:
 267          $this->jpegQuality = t3lib_div::intInRange($gfxConf['jpg_quality'], 10, 100, 75);
 268          $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -sharpen 50 -quality '.$this->jpegQuality;
 269  
 270          if ($gfxConf['im_combine_filename'])    $this->combineScript=$gfxConf['im_combine_filename'];
 271          if ($gfxConf['im_noFramePrepended'])    $this->noFramePrepended=1;
 272  
 273          if ($gfxConf['gdlib_2'])    {
 274              $this->GD2 = 1;
 275              $this->imagecopyresized_fix = $gfxConf['gdlib_2']==='no_imagecopyresized_fix' ? 0 : 1;
 276          }
 277          if ($gfxConf['gdlib_png'])    {
 278              $this->gifExtension='png';
 279          }
 280          if ($gfxConf['TTFLocaleConv']) {
 281              $this->TTFLocaleConv = $gfxConf['TTFLocaleConv'];
 282          }
 283          if ($gfxConf['enable_typo3temp_db_tracking']) {
 284              $this->enable_typo3temp_db_tracking = $gfxConf['enable_typo3temp_db_tracking'];
 285          }
 286  
 287          $this->imageFileExt = $gfxConf['imagefile_ext'];
 288  
 289              // This should be set if ImageMagick ver. 5+ is used.
 290          if ($gfxConf['im_negate_mask'])    {
 291                  // Boolean. Indicates if the mask images should be inverted first.
 292                  // This depends of the ImageMagick version. Below ver. 5.1 this should be false.
 293                  // Above ImageMagick version 5.2+ it should be true.
 294                  // Just set the flag if the masks works opposite the intension!
 295              $this->maskNegate = ' -negate';
 296          }
 297          if ($gfxConf['im_no_effects'])    {
 298                  // Boolean. This is necessary if using ImageMagick 5+.
 299                  // Approved version for using effects is version 4.2.9.
 300                  // Effects in Imagemagick 5+ tends to render very slowly!!
 301                  // - therefore must be disabled in order not to perform sharpen, blurring and such.
 302              $this->NO_IM_EFFECTS = 1;
 303  
 304              $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.$this->jpegQuality;
 305          }
 306              // ... but if 'im_v5effects' is set, don't care about 'im_no_effects'
 307          if ($gfxConf['im_v5effects'])    {
 308              $this->NO_IM_EFFECTS = 0;
 309              $this->V5_EFFECTS = 1;
 310  
 311              if ($gfxConf['im_v5effects']>0)    {
 312                  $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['jpg_quality']).$this->v5_sharpen(10);
 313              }
 314          }
 315  
 316          if (!$gfxConf['im'])    {
 317              $this->NO_IMAGE_MAGICK = 1;
 318          }
 319              // Secures that images are not scaled up.
 320          if ($gfxConf['im_noScaleUp']) {
 321              $this->mayScaleUp=0;
 322          }
 323  
 324          if (TYPO3_MODE=='FE')    {
 325              $this->csConvObj = &$GLOBALS['TSFE']->csConvObj;
 326          } elseif(is_object($GLOBALS['LANG']))    {    // BE assumed:
 327              $this->csConvObj = &$GLOBALS['LANG']->csConvObj;
 328          } else    {    // The object may not exist yet, so we need to create it now. Happens in the Install Tool for example.
 329              $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
 330          }
 331          $this->nativeCharset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'];
 332      }
 333  
 334  
 335  
 336  
 337  
 338  
 339  
 340  
 341  
 342  
 343  
 344  
 345  
 346  
 347  
 348  
 349      /*************************************************
 350       *
 351       * Layering images / "IMAGE" GIFBUILDER object
 352       *
 353       *************************************************/
 354  
 355      /**
 356       * Implements the "IMAGE" GIFBUILDER object, when the "mask" property is true.
 357       * It reads the two images defined by $conf['file'] and $conf['mask'] and copies the $conf['file'] onto the input image pointer image using the $conf['mask'] as a grayscale mask
 358       * The operation involves ImageMagick for combining.
 359       *
 360       * @param    pointer        GDlib image pointer
 361       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
 362       * @param    array        The current working area coordinates.
 363       * @return    void
 364       * @see tslib_gifBuilder::make()
 365       */
 366  	function maskImageOntoImage(&$im,$conf,$workArea)    {
 367          if ($conf['file'] && $conf['mask'])    {
 368              $imgInf = pathinfo($conf['file']);
 369              $imgExt = strtolower($imgInf['extension']);
 370              if (!t3lib_div::inList($this->gdlibExtensions, $imgExt))    {
 371                  $BBimage = $this->imageMagickConvert($conf['file'],$this->gifExtension,'','','','','');
 372              } else    {
 373                  $BBimage = $this->getImageDimensions($conf['file']);
 374              }
 375              $maskInf = pathinfo($conf['mask']);
 376              $maskExt = strtolower($maskInf['extension']);
 377              if (!t3lib_div::inList($this->gdlibExtensions, $maskExt))    {
 378                  $BBmask = $this->imageMagickConvert($conf['mask'],$this->gifExtension,'','','','','');
 379              } else    {
 380                  $BBmask = $this->getImageDimensions($conf['mask']);
 381              }
 382              if ($BBimage && $BBmask)    {
 383                  $w = imagesx($im);
 384                  $h = imagesy($im);
 385                  $tmpStr = $this->randomName();
 386                  $theImage = $tmpStr.'_img.'.$this->gifExtension;
 387                  $theDest = $tmpStr.'_dest.'.$this->gifExtension;
 388                  $theMask = $tmpStr.'_mask.'.$this->gifExtension;
 389                          // prepare overlay image
 390                  $cpImg = $this->imageCreateFromFile($BBimage[3]);
 391                  $destImg = $this->imagecreate($w,$h);
 392                  $Bcolor = ImageColorAllocate($destImg, 0,0,0);
 393                  ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor);
 394                  $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
 395                  $this->ImageWrite($destImg, $theImage);
 396                  imageDestroy($cpImg);
 397                  imageDestroy($destImg);
 398                          // prepare mask image
 399                  $cpImg = $this->imageCreateFromFile($BBmask[3]);
 400                  $destImg = $this->imagecreate($w,$h);
 401                  $Bcolor = ImageColorAllocate($destImg, 0, 0, 0);
 402                  ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor);
 403                  $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
 404                  $this->ImageWrite($destImg, $theMask);
 405                  imageDestroy($cpImg);
 406                  imageDestroy($destImg);
 407                      // mask the images
 408                  $this->ImageWrite($im, $theDest);
 409  
 410                  $this->combineExec($theDest,$theImage,$theMask,$theDest, true);        // Let combineExec handle maskNegation
 411  
 412                  $backIm = $this->imageCreateFromFile($theDest);    // The main image is loaded again...
 413                  if ($backIm)    {    // ... and if nothing went wrong we load it onto the old one.
 414                      ImageColorTransparent($backIm,-1);
 415                      $im = $backIm;
 416                  }
 417                      // unlink files from process
 418                  if (!$this->dontUnlinkTempFiles)    {
 419                      unlink($theDest);
 420                      unlink($theImage);
 421                      unlink($theMask);
 422                  }
 423              }
 424          }
 425      }
 426  
 427      /**
 428       * Implements the "IMAGE" GIFBUILDER object, when the "mask" property is false (using only $conf['file'])
 429       *
 430       * @param    pointer        GDlib image pointer
 431       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
 432       * @param    array        The current working area coordinates.
 433       * @return    void
 434       * @see tslib_gifBuilder::make(), maskImageOntoImage()
 435       */
 436  	function copyImageOntoImage(&$im,$conf,$workArea)    {
 437          if ($conf['file'])    {
 438              if (!t3lib_div::inList($this->gdlibExtensions, $conf['BBOX'][2]))    {
 439                  $conf['BBOX']=$this->imageMagickConvert($conf['BBOX'][3],$this->gifExtension,'','','','','');
 440                  $conf['file']=$conf['BBOX'][3];
 441              }
 442              $cpImg = $this->imageCreateFromFile($conf['file']);
 443              $this->copyGifOntoGif($im,$cpImg,$conf,$workArea);
 444              imageDestroy($cpImg);
 445          }
 446      }
 447  
 448      /**
 449       * Copies two GDlib image pointers onto each other, using TypoScript configuration from $conf and the input $workArea definition.
 450       *
 451       * @param    pointer        GDlib image pointer, destination (bottom image)
 452       * @param    pointer        GDlib image pointer, source (top image)
 453       * @param    array        TypoScript array with the properties for the IMAGE GIFBUILDER object. Only used for the "tile" property value.
 454       * @param    array        Work area
 455       * @return    void        Works on the $im image pointer
 456       * @access private
 457       */
 458  	function copyGifOntoGif(&$im,$cpImg,$conf,$workArea)    {
 459          $cpW = imagesx($cpImg);
 460          $cpH = imagesy($cpImg);
 461          $tile = t3lib_div::intExplode(',',$conf['tile']);
 462          $tile[0] = t3lib_div::intInRange($tile[0],1,20);
 463          $tile[1] = t3lib_div::intInRange($tile[1],1,20);
 464          $cpOff = $this->objPosition($conf,$workArea,Array($cpW*$tile[0],$cpH*$tile[1]));
 465  
 466          for ($xt=0;$xt<$tile[0];$xt++)    {
 467              $Xstart=$cpOff[0]+$cpW*$xt;
 468              if ($Xstart+$cpW > $workArea[0])    {    // if this image is inside of the workArea, then go on
 469                      // X:
 470                  if ($Xstart < $workArea[0])    {
 471                      $cpImgCutX = $workArea[0]-$Xstart;
 472                      $Xstart = $workArea[0];
 473                  } else {
 474                      $cpImgCutX = 0;
 475                  }
 476                  $w = $cpW-$cpImgCutX;
 477                  if ($Xstart > $workArea[0]+$workArea[2]-$w)    {
 478                      $w = $workArea[0]+$workArea[2]-$Xstart;
 479                  }
 480                  if ($Xstart < $workArea[0]+$workArea[2])    {    // if this image is inside of the workArea, then go on
 481                          // Y:
 482                      for ($yt=0;$yt<$tile[1];$yt++)    {
 483                          $Ystart=$cpOff[1]+$cpH*$yt;
 484                          if ($Ystart+$cpH > $workArea[1])    {    // if this image is inside of the workArea, then go on
 485                              if ($Ystart < $workArea[1])    {
 486                                  $cpImgCutY = $workArea[1]-$Ystart;
 487                                  $Ystart = $workArea[1];
 488                              } else {
 489                                  $cpImgCutY = 0;
 490                              }
 491                              $h = $cpH-$cpImgCutY;
 492                              if ($Ystart > $workArea[1]+$workArea[3]-$h)    {
 493                                  $h = $workArea[1]+$workArea[3]-$Ystart;
 494                              }
 495                              if ($Ystart < $workArea[1]+$workArea[3])    {    // if this image is inside of the workArea, then go on
 496                                  $this->imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
 497                              }
 498                          }
 499                      }  // Y:
 500                  }
 501              }
 502          }
 503      }
 504  
 505      /**
 506       * Alternative function for using the similar PHP function imagecopyresized(). Used for GD2 only.
 507       *
 508       * OK, the reason for this stupid fix is the following story:
 509       * GD1.x was capable of copying two images together and combining their palettes! GD2 is apparently not.
 510       * With GD2 only the palette of the dest-image is used which mostly results in totally black images when trying to
 511       * copy a color-ful image onto the destination.
 512       * The GD2-fix is to
 513       *         1) Create a blank TRUE-COLOR image
 514       *         2) Copy the destination image onto that one
 515       *         3) Then do the actual operation; Copying the source (top image) onto that
 516       *         4) ... and return the result pointer.
 517       *         5) Reduce colors (if we do not, the result may become strange!)
 518       * It works, but the resulting images is now a true-color PNG which may be very large.
 519       * So, why not use 'imagetruecolortopalette ($im, TRUE, 256)' - well because it does NOT WORK! So simple is that.
 520       *
 521       * For parameters, see PHP function "imagecopyresized()"
 522       *
 523       * @param    pointer        see PHP function "imagecopyresized()"
 524       * @param    pointer        see PHP function "imagecopyresized()"
 525       * @param    integer        see PHP function "imagecopyresized()"
 526       * @param    integer        see PHP function "imagecopyresized()"
 527       * @param    integer        see PHP function "imagecopyresized()"
 528       * @param    integer        see PHP function "imagecopyresized()"
 529       * @param    integer        see PHP function "imagecopyresized()"
 530       * @param    integer        see PHP function "imagecopyresized()"
 531       * @param    integer        see PHP function "imagecopyresized()"
 532       * @param    integer        see PHP function "imagecopyresized()"
 533       * @return    void
 534       * @access private
 535       * @see t3lib_iconWorks::imagecopyresized()
 536       */
 537  	function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h)    {
 538          if ($this->imagecopyresized_fix)    {
 539              $im_base = $this->imagecreate(imagesx($im), imagesy($im));    // Make true color image
 540              imagecopyresized($im_base, $im, 0,0,0,0, imagesx($im),imagesy($im),imagesx($im),imagesy($im));    // Copy the source image onto that
 541              imagecopyresized($im_base, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);    // Then copy the $cpImg onto that (the actual operation!)
 542              $im = $im_base;    // Set pointer
 543              if (!$this->truecolor)    {
 544                  $this->makeEffect($im, Array('value'=>'colors='.t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256)));        // Reduce to "reduceColors" colors - make SURE that IM is working then!
 545              }
 546          } else {
 547              imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
 548          }
 549      }
 550  
 551  
 552  
 553  
 554  
 555  
 556  
 557  
 558  
 559  
 560  
 561  
 562  
 563  
 564  
 565  
 566  
 567  
 568  
 569  
 570  
 571  
 572      /********************************
 573       *
 574       * Text / "TEXT" GIFBUILDER object
 575       *
 576       ********************************/
 577  
 578      /**
 579       * Implements the "TEXT" GIFBUILDER object
 580       *
 581       * @param    pointer        GDlib image pointer
 582       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
 583       * @param    array        The current working area coordinates.
 584       * @return    void
 585       * @see tslib_gifBuilder::make()
 586       */
 587  	function makeText(&$im,$conf,$workArea)    {
 588              // Spacing
 589          list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
 590              // Position
 591          $txtPos = $this->txtPosition($conf,$workArea,$conf['BBOX']);
 592          $theText = $this->recodeString($conf['text']);
 593  
 594          if ($conf['imgMap'] && is_array($conf['imgMap.']))    {
 595              $this->addToMap($this->calcTextCordsForMap($conf['BBOX'][2],$txtPos, $conf['imgMap.']), $conf['imgMap.']);
 596          }
 597          if (!$conf['hideButCreateMap'])    {
 598                  // Font Color:
 599              $cols=$this->convertColor($conf['fontColor']);
 600                  // NiceText is calculated
 601              if (!$conf['niceText']) {
 602                      // Font Color is reserved:
 603                  if (!$this->truecolor)    {
 604                      $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256);
 605                      $this->reduceColors($im, $reduce-49, $reduce-50);    // If "reduce-49" colors (or more) are used reduce them to "reduce-50"
 606                  }
 607                  $Fcolor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
 608                      // antiAliasing is setup:
 609                  $Fcolor = ($conf['antiAlias']) ? $Fcolor : -$Fcolor;
 610  
 611                  for ($a=0; $a<$conf['iterations']; $a++)    {
 612                      if ($spacing || $wordSpacing)    {        // If any kind of spacing applys, we use this function:
 613                          $this->SpacedImageTTFText($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.']);
 614                      } else {
 615                          $this->ImageTTFTextWrapper($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.']);
 616                      }
 617                  }
 618              } else {        // NICETEXT::
 619                      // options anti_aliased and iterations is NOT available when doing this!!
 620                  $w = imagesx($im);
 621                  $h = imagesy($im);
 622                  $tmpStr = $this->randomName();
 623  
 624                  $fileMenu = $tmpStr.'_menuNT.'.$this->gifExtension;
 625                  $fileColor = $tmpStr.'_colorNT.'.$this->gifExtension;
 626                  $fileMask = $tmpStr.'_maskNT.'.$this->gifExtension;
 627                      // Scalefactor
 628                  $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
 629                  $newW = ceil($sF*imagesx($im));
 630                  $newH = ceil($sF*imagesy($im));
 631  
 632                      // Make mask
 633                  $maskImg = $this->imagecreate($newW, $newH);
 634                  $Bcolor = ImageColorAllocate($maskImg, 255,255,255);
 635                  ImageFilledRectangle($maskImg, 0, 0, $newW, $newH, $Bcolor);
 636                  $Fcolor = ImageColorAllocate($maskImg, 0,0,0);
 637                  if ($spacing || $wordSpacing)    {        // If any kind of spacing applys, we use this function:
 638                      $this->SpacedImageTTFText($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.'],$sF);
 639                  } else {
 640                      $this->ImageTTFTextWrapper($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
 641                  }
 642                  $this->ImageWrite($maskImg, $fileMask);
 643                  ImageDestroy($maskImg);
 644  
 645                      // Downscales the mask
 646                  if ($this->NO_IM_EFFECTS)    {
 647                      if ($this->maskNegate)    {
 648                          $command = trim($this->scalecmd.' '.$w.'x'.$h.'!');        // Negate 2 times makes no negate...
 649                      } else {
 650                          $command = trim($this->scalecmd.' '.$w.'x'.$h.'! -negate');
 651                      }
 652                  } else {
 653                      if ($this->maskNegate)    {
 654                          $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after']);
 655                      } else {
 656                          $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after'].' -negate');
 657                      }
 658                      if ($conf['niceText.']['sharpen']) {
 659                          if ($this->V5_EFFECTS)    {
 660                              $command.=$this->v5_sharpen($conf['niceText.']['sharpen']);
 661                          } else {
 662                              $command.=' -sharpen '.t3lib_div::intInRange($conf['niceText.']['sharpen'],1,99);
 663                          }
 664                      }
 665                  }
 666  
 667                  $this->imageMagickExec($fileMask,$fileMask,$command);
 668  
 669                      // Make the color-file
 670                  $colorImg = $this->imagecreate($w,$h);
 671                  $Ccolor = ImageColorAllocate($colorImg, $cols[0],$cols[1],$cols[2]);
 672                  ImageFilledRectangle($colorImg, 0, 0, $w, $h, $Ccolor);
 673                  $this->ImageWrite($colorImg, $fileColor);
 674                  ImageDestroy($colorImg);
 675  
 676                      // The mask is applied
 677                  $this->ImageWrite($im, $fileMenu);    // The main pictures is saved temporarily
 678  
 679                  $this->combineExec($fileMenu,$fileColor,$fileMask, $fileMenu);
 680  
 681                  $backIm = $this->imageCreateFromFile($fileMenu);    // The main image is loaded again...
 682                  if ($backIm)    {    // ... and if nothing went wrong we load it onto the old one.
 683                      ImageColorTransparent($backIm,-1);
 684                      $im = $backIm;
 685                  }
 686  
 687                      // Deleting temporary files;
 688                  if (!$this->dontUnlinkTempFiles)    {
 689                      unlink($fileMenu);
 690                      unlink($fileColor);
 691                      unlink($fileMask);
 692                  }
 693              }
 694          }
 695      }
 696  
 697      /**
 698       * Calculates text position for printing the text onto the image based on configuration like alignment and workarea.
 699       *
 700       * @param    array        TypoScript array for the TEXT GIFBUILDER object
 701       * @param    array        Workarea definition
 702       * @param    array        Bounding box information, was set in tslib_gifBuilder::start()
 703       * @return    array        [0]=x, [1]=y, [2]=w, [3]=h
 704       * @access private
 705       * @see makeText()
 706       */
 707  	function txtPosition($conf,$workArea,$BB) {
 708          $bbox = $BB[2];
 709          $angle=intval($conf['angle'])/180*pi();
 710          $conf['angle']=0;
 711          $straightBB = $this->calcBBox($conf);
 712  
 713              // offset, align, valign, workarea
 714          $result=Array();    // [0]=x, [1]=y, [2]=w, [3]=h
 715          $result[2] = $BB[0];
 716          $result[3] = $BB[1];
 717          $w=$workArea[2];
 718          $h=$workArea[3];
 719  
 720          switch($conf['align'])    {
 721              case 'right':
 722              case 'center':
 723                  $factor=abs(cos($angle));
 724                  $sign=(cos($angle)<0)?-1:1;
 725                  $len1 = $sign*$factor*$straightBB[0];
 726                  $len2= $sign*$BB[0];
 727                  $result[0] = $w-ceil($len2*$factor+(1-$factor)*$len1);
 728  
 729                  $factor=abs(sin($angle));
 730                  $sign=(sin($angle)<0)?-1:1;
 731                  $len1= $sign*$factor*$straightBB[0];
 732                  $len2= $sign*$BB[1];
 733                  $result[1]=ceil($len2*$factor+(1-$factor)*$len1);
 734              break;
 735          }
 736          switch($conf['align'])    {
 737              case 'right':
 738              break;
 739              case 'center':
 740                  $result[0] = round(($result[0])/2);
 741                  $result[1] = round(($result[1])/2);
 742              break;
 743              default:
 744                  $result[0]=0;
 745                  $result[1]=0;
 746              break;
 747          }
 748          $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset']));
 749          $result = $this->applyOffset($result,$workArea);
 750          return $result;
 751      }
 752  
 753      /**
 754       * Calculates bounding box information for the TEXT GIFBUILDER object.
 755       *
 756       * @param    array        TypoScript array for the TEXT GIFBUILDER object
 757       * @return    array        Array with three keys [0]/[1] being x/y and [2] being the bounding box array
 758       * @access private
 759       * @see txtPosition(), tslib_gifBuilder::start()
 760       */
 761  	function calcBBox($conf)    {
 762          $sF = $this->getTextScalFactor($conf);
 763          list($spacing,$wordSpacing) = $this->calcWordSpacing($conf, $sF);
 764          $theText = $this->recodeString($conf['text']);
 765  
 766          $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
 767          $theBBoxInfo = $charInf;
 768          if ($conf['angle'])    {
 769              $xArr = Array($charInf[0],$charInf[2],$charInf[4],$charInf[6]);
 770              $yArr = Array($charInf[1],$charInf[3],$charInf[5],$charInf[7]);
 771              $x=max($xArr)-min($xArr);
 772              $y=max($yArr)-min($yArr);
 773          } else {
 774              $x = ($charInf[2]-$charInf[0]);
 775              $y = ($charInf[1]-$charInf[7]);
 776          }
 777          if ($spacing || $wordSpacing)    {        // If any kind of spacing applys, we use this function:
 778              $x=0;
 779              if (!$spacing && $wordSpacing)    {
 780                  $bits = explode(' ',$theText);
 781                  while(list(,$word)=each($bits))    {
 782                      $word.=' ';
 783                      $wordInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $word, $conf['splitRendering.'],$sF);
 784                      $wordW = ($wordInf[2]-$wordInf[0]);
 785                      $x+=$wordW+$wordSpacing;
 786                  }
 787              } else {
 788                  $utf8Chars = $this->singleChars($theText);
 789                      // For each UTF-8 char, do:
 790                  foreach($utf8Chars as $char)    {
 791                      $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $char, $conf['splitRendering.'],$sF);
 792                      $charW = ($charInf[2]-$charInf[0]);
 793                      $x+=$charW+(($char==' ')?$wordSpacing:$spacing);
 794                  }
 795              }
 796          }
 797  
 798          if ($sF>1) {
 799              $x = ceil($x/$sF);
 800              $y = ceil($y/$sF);
 801              if (is_array($theBBoxInfo))    {
 802                  reset($theBBoxInfo);
 803                  while(list($key,$val)=each($theBBoxInfo))    {
 804                      $theBBoxInfo[$key]=ceil($theBBoxInfo[$key]/$sF);
 805                  }
 806              }
 807          }
 808          return array($x,$y,$theBBoxInfo);
 809      }
 810  
 811      /**
 812       * Adds an <area> tag to the internal variable $this->map which is used to accumulate the content for an ImageMap
 813       *
 814       * @param    array        Coordinates for a polygon image map as created by ->calcTextCordsForMap()
 815       * @param    array        Configuration for "imgMap." property of a TEXT GIFBUILDER object.
 816       * @return    void
 817       * @access private
 818       * @see makeText(), calcTextCordsForMap()
 819       */
 820  	function addToMap($cords,$conf)    {
 821          $JS = $conf['noBlur'] ? '' : ' onfocus="blurLink(this);"';
 822  
 823          $this->map.='<area'.
 824                  ' shape="poly"'.
 825                  ' coords="'.implode(',',$cords).'"'.
 826                  ' href="'.htmlspecialchars($conf['url']).'"'.
 827                  ($conf['target'] ? ' target="'.htmlspecialchars($conf['target']).'"' : '').
 828                  $JS.
 829                  (strlen($conf['titleText']) ? ' title="'.htmlspecialchars($conf['titleText']).'"' : '').
 830                  ' alt="'.htmlspecialchars($conf['altText']).'" />';
 831      }
 832  
 833      /**
 834       * Calculating the coordinates for a TEXT string on an image map. Used in an <area> tag
 835       *
 836       * @param    array        Coordinates (from BBOX array)
 837       * @param    array        Offset array
 838       * @param    array        Configuration for "imgMap." property of a TEXT GIFBUILDER object.
 839       * @return    array
 840       * @access private
 841       * @see makeText(), calcTextCordsForMap()
 842       */
 843  	function calcTextCordsForMap($cords,$offset, $conf)    {
 844          $pars = t3lib_div::intExplode(',',$conf['explode'].',');
 845  
 846          $newCords[0] = $cords[0]+$offset[0]-$pars[0];
 847          $newCords[1] = $cords[1]+$offset[1]+$pars[1];
 848          $newCords[2] = $cords[2]+$offset[0]+$pars[0];
 849          $newCords[3] = $cords[3]+$offset[1]+$pars[1];
 850          $newCords[4] = $cords[4]+$offset[0]+$pars[0];
 851          $newCords[5] = $cords[5]+$offset[1]-$pars[1];
 852          $newCords[6] = $cords[6]+$offset[0]-$pars[0];
 853          $newCords[7] = $cords[7]+$offset[1]-$pars[1];
 854  
 855          return $newCords;
 856      }
 857  
 858      /**
 859       * Printing text onto an image like the PHP function imageTTFText does but in addition it offers options for spacing of letters and words.
 860       * Spacing is done by printing one char at a time and this means that the spacing is rather uneven and probably not very nice.
 861       * See
 862       *
 863       * @param    pointer        (See argument for PHP function imageTTFtext())
 864       * @param    integer        (See argument for PHP function imageTTFtext())
 865       * @param    integer        (See argument for PHP function imageTTFtext())
 866       * @param    integer        (See argument for PHP function imageTTFtext())
 867       * @param    integer        (See argument for PHP function imageTTFtext())
 868       * @param    integer        (See argument for PHP function imageTTFtext())
 869       * @param    string        (See argument for PHP function imageTTFtext())
 870       * @param    string        (See argument for PHP function imageTTFtext()). UTF-8 string, possibly with entities in.
 871       * @param    integer        The spacing of letters in pixels
 872       * @param    integer        The spacing of words in pixels
 873       * @param    array        $splitRenderingConf array
 874       * @param    integer        Scale factor
 875       * @return    void
 876       * @access private
 877       */
 878  	function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1)    {
 879  
 880          $spacing*=$sF;
 881          $wordSpacing*=$sF;
 882  
 883          if (!$spacing && $wordSpacing)    {
 884              $bits = explode(' ',$text);
 885              reset($bits);
 886              while(list(,$word)=each($bits))    {
 887                  $word.=' ';
 888                  $word = $word;
 889                  $wordInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $word, $splitRenderingConf ,$sF);
 890                  $wordW = ($wordInf[2]-$wordInf[0]);
 891                  $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $word, $splitRenderingConf, $sF);
 892                  $x+=$wordW+$wordSpacing;
 893              }
 894          } else {
 895              $utf8Chars = $this->singleChars($text);
 896                  // For each UTF-8 char, do:
 897              foreach($utf8Chars as $char)    {
 898                  $charInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $char, $splitRenderingConf, $sF);
 899                  $charW = ($charInf[2]-$charInf[0]);
 900                  $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $char, $splitRenderingConf, $sF);
 901                  $x+=$charW+(($char==' ')?$wordSpacing:$spacing);
 902              }
 903          }
 904      }
 905  
 906      /**
 907       * Function that finds the right fontsize that will render the textstring within a certain width
 908       *
 909       * @param    array        The TypoScript properties of the TEXT GIFBUILDER object
 910       * @return    integer        The new fontSize
 911       * @access private
 912       * @author Rene Fritz <r.fritz@colorcube.de>
 913       * @see tslib_gifBuilder::start()
 914       */
 915  	function fontResize($conf) {
 916          // you have to use +calc options like [10.h] in 'offset' to get the right position of your text-image, if you use +calc in XY height!!!!
 917          $maxWidth = intval($conf['maxWidth']);
 918          list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
 919          if ($maxWidth)    {
 920              if ($spacing || $wordSpacing)    {        // If any kind of spacing applys, we use this function:
 921                  return $conf['fontSize'];
 922                  //  ################ no calc for spacing yet !!!!!!
 923              } else {
 924                  do {
 925                          // determine bounding box.
 926                      $bounds = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $this->recodeString($conf['text']), $conf['splitRendering.']);
 927                      if ($conf['angle']< 0) {
 928                          $pixelWidth = abs($bounds[4]-$bounds[0]);
 929                      } elseif ($conf['angle'] > 0) {
 930                          $pixelWidth = abs($bounds[2]-$bounds[6]);
 931                      } else {
 932                          $pixelWidth = abs($bounds[4]-$bounds[6]);
 933                      }
 934  
 935                          // Size is fine, exit:
 936                      if ($pixelWidth <= $maxWidth)    {
 937                          break;
 938                      } else {
 939                          $conf['fontSize']--;
 940                      }
 941                  } while ($conf['fontSize']>1);
 942              }//if spacing
 943          }
 944          return $conf['fontSize'];
 945      }
 946  
 947      /**
 948       * Wrapper for ImageTTFBBox
 949       *
 950       * @param    integer        (See argument for PHP function ImageTTFBBox())
 951       * @param    integer        (See argument for PHP function ImageTTFBBox())
 952       * @param    string        (See argument for PHP function ImageTTFBBox())
 953       * @param    string        (See argument for PHP function ImageTTFBBox())
 954       * @param    array        Split-rendering configuration
 955       * @param    integer        Scale factor
 956       * @return    array        Information array.
 957       */
 958  	function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1)    {
 959  
 960              // Initialize:
 961          $offsetInfo = array();
 962          $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
 963  
 964              // Traverse string parts:
 965          foreach($stringParts as $strCfg)    {
 966              $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
 967              if (is_readable($fontFile)) {
 968  
 969                      // Calculate Bounding Box for part:
 970                  $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $fontFile, $strCfg['str']);
 971  
 972                      // Calculate offsets:
 973                  if (!count($offsetInfo))    {
 974                      $offsetInfo = $calc;    // First run, just copy over.
 975                  } else {
 976                      $offsetInfo[2]+=$calc[2]-$calc[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
 977                      $offsetInfo[3]+=$calc[3]-$calc[1]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
 978                      $offsetInfo[4]+=$calc[4]-$calc[6]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
 979                      $offsetInfo[5]+=$calc[5]-$calc[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
 980                  }
 981  
 982              } else {
 983                  debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFBBoxWrapper()');
 984              }
 985          }
 986  
 987          return $offsetInfo;
 988      }
 989  
 990      /**
 991       * Wrapper for ImageTTFText
 992       *
 993       * @param    pointer        (See argument for PHP function imageTTFtext())
 994       * @param    integer        (See argument for PHP function imageTTFtext())
 995       * @param    integer        (See argument for PHP function imageTTFtext())
 996       * @param    integer        (See argument for PHP function imageTTFtext())
 997       * @param    integer        (See argument for PHP function imageTTFtext())
 998       * @param    integer        (See argument for PHP function imageTTFtext())
 999       * @param    string        (See argument for PHP function imageTTFtext())
1000       * @param    string        (See argument for PHP function imageTTFtext()). UTF-8 string, possibly with entities in.
1001       * @param    array        Split-rendering configuration
1002       * @param    integer        Scale factor
1003       * @return    void
1004       */
1005  	function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1)    {
1006  
1007              // Initialize:
1008          $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
1009          $x = ceil($sF*$x);
1010          $y = ceil($sF*$y);
1011  
1012              // Traverse string parts:
1013          foreach($stringParts as $i => $strCfg)    {
1014  
1015                  // Initialize:
1016              $colorIndex = $color;
1017  
1018                  // Set custom color if any (only when niceText is off):
1019              if ($strCfg['color'] && $sF==1)    {
1020                  $cols = $this->convertColor($strCfg['color']);
1021                  $colorIndex = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
1022                  $colorIndex = $color >= 0 ? $colorIndex : -$colorIndex;
1023              }
1024  
1025                  // Setting xSpaceBefore
1026              if ($i)    {
1027                  $x+= intval($strCfg['xSpaceBefore']);
1028                  $y-= intval($strCfg['ySpaceBefore']);
1029              }
1030  
1031              $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
1032              if (is_readable($fontFile)) {
1033  
1034                      // Render part:
1035                  ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, $fontFile, $strCfg['str']);
1036  
1037                      // Calculate offset to apply:
1038                  $wordInf = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
1039                  $x+= $wordInf[2]-$wordInf[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceAfter']);
1040                  $y+= $wordInf[5]-$wordInf[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceAfter']);
1041  
1042              } else {
1043                  debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFTextWrapper()');
1044              }
1045  
1046          }
1047      }
1048  
1049      /**
1050       * Splitting a string for ImageTTFBBox up into an array where each part has its own configuration options.
1051       *
1052       * @param    string        UTF-8 string
1053       * @param    array        Split-rendering configuration from GIFBUILDER TEXT object.
1054       * @param    integer        Current fontsize
1055       * @param    string        Current font file
1056       * @return    array        Array with input string splitted according to configuration
1057       */
1058  	function splitString($string,$splitRendering,$fontSize,$fontFile)    {
1059  
1060              // Initialize by setting the whole string and default configuration as the first entry.
1061          $result = array();
1062          $result[] = array(
1063              'str' => $string,
1064              'fontSize' => $fontSize,
1065              'fontFile' => $fontFile
1066          );
1067  
1068              // Traverse the split-rendering configuration:
1069              // Splitting will create more entries in $result with individual configurations.
1070          if (is_array($splitRendering))    {
1071              $sKeyArray = t3lib_TStemplate::sortedKeyList($splitRendering);
1072  
1073                  // Traverse configured options:
1074              foreach($sKeyArray as $key)    {
1075                  $cfg = $splitRendering[$key.'.'];
1076  
1077                      // Process each type of split rendering keyword:
1078                  switch((string)$splitRendering[$key])    {
1079                      case 'highlightWord':
1080                          if (strlen($cfg['value']))    {
1081                              $newResult = array();
1082  
1083                                  // Traverse the current parts of the result array:
1084                              foreach($result as $part)    {
1085                                      // Explode the string value by the word value to highlight:
1086                                  $explodedParts = explode($cfg['value'],$part['str']);
1087                                  foreach($explodedParts as $c => $expValue)    {
1088                                      if (strlen($expValue))    {
1089                                          $newResult[] = array_merge($part,array('str' => $expValue));
1090                                      }
1091                                      if ($c+1 < count($explodedParts))    {
1092                                          $newResult[] = array(
1093                                              'str' => $cfg['value'],
1094                                              'fontSize' => $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
1095                                              'fontFile' => $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
1096                                              'color' => $cfg['color'],
1097                                              'xSpaceBefore' => $cfg['xSpaceBefore'],
1098                                              'xSpaceAfter' => $cfg['xSpaceAfter'],
1099                                              'ySpaceBefore' => $cfg['ySpaceBefore'],
1100                                              'ySpaceAfter' => $cfg['ySpaceAfter'],
1101                                          );
1102                                      }
1103                                  }
1104                              }
1105  
1106                                  // Set the new result as result array:
1107                              if (count($newResult))    {
1108                                  $result = $newResult;
1109                              }
1110                          }
1111                      break;
1112                      case 'charRange':
1113                          if (strlen($cfg['value']))    {
1114  
1115                                  // Initialize range:
1116                              $ranges = t3lib_div::trimExplode(',',$cfg['value'],1);
1117                              foreach($ranges as $i => $rangeDef)    {
1118                                  $ranges[$i] = t3lib_div::intExplode('-',$ranges[$i]);
1119                                  if (!isset($ranges[$i][1]))    $ranges[$i][1] = $ranges[$i][0];
1120                              }
1121                              $newResult = array();
1122  
1123                                  // Traverse the current parts of the result array:
1124                              foreach($result as $part)    {
1125  
1126                                      // Initialize:
1127                                  $currentState = -1;
1128                                  $bankAccum = '';
1129  
1130                                      // Explode the string value by the word value to highlight:
1131                                  $utf8Chars = $this->singleChars($part['str']);
1132                                  foreach($utf8Chars as $utfChar)    {
1133  
1134                                          // Find number and evaluate position:
1135                                      $uNumber = $this->csConvObj->utf8CharToUnumber($utfChar);
1136                                      $inRange = 0;
1137                                      foreach($ranges as $rangeDef)    {
1138                                          if ($uNumber >= $rangeDef[0] && (!$rangeDef[1] || $uNumber <= $rangeDef[1])) {
1139                                              $inRange = 1;
1140                                              break;
1141                                          }
1142                                      }
1143                                      if ($currentState==-1)    $currentState = $inRange;    // Initialize first char
1144  
1145                                          // Switch bank:
1146                                      if ($inRange != $currentState && !t3lib_div::inList('32,10,13,9',$uNumber))    {
1147  
1148                                              // Set result:
1149                                          if (strlen($bankAccum))    {
1150                                              $newResult[] = array(
1151                                                  'str' => $bankAccum,
1152                                                  'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
1153                                                  'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
1154                                                  'color' => $currentState ? $cfg['color'] : '',
1155                                                  'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
1156                                                  'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
1157                                                  'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
1158                                                  'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
1159                                              );
1160                                          }
1161  
1162                                              // Initialize new settings:
1163                                          $currentState = $inRange;
1164                                          $bankAccum = '';
1165                                      }
1166  
1167                                          // Add char to bank:
1168                                      $bankAccum.=$utfChar;
1169                                  }
1170  
1171                                      // Set result for FINAL part:
1172                                  if (strlen($bankAccum))    {
1173                                      $newResult[] = array(
1174                                          'str' => $bankAccum,
1175                                          'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
1176                                          'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
1177                                          'color' => $currentState ? $cfg['color'] : '',
1178                                          'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
1179                                          'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
1180                                          'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
1181                                          'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
1182                                      );
1183                                  }
1184                              }
1185  
1186                                  // Set the new result as result array:
1187                              if (count($newResult))    {
1188                                  $result = $newResult;
1189                              }
1190                          }
1191                      break;
1192                  }
1193              }
1194          }
1195  
1196          return $result;
1197      }
1198  
1199      /**
1200       * Calculates the spacing and wordSpacing values
1201       *
1202       * @param    array        TypoScript array for the TEXT GIFBUILDER object
1203       * @param    integer        TypoScript value from eg $conf['niceText.']['scaleFactor']
1204       * @return    array        Array with two keys [0]/[1] being array($spacing,$wordSpacing)
1205       * @access private
1206       * @see calcBBox()
1207       */
1208  	function calcWordSpacing($conf, $scaleFactor=1) {
1209  
1210          $spacing = intval($conf['spacing']);
1211          $wordSpacing = intval($conf['wordSpacing']);
1212          $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2;
1213  
1214          $spacing*=$scaleFactor;
1215          $wordSpacing*=$scaleFactor;
1216  
1217          return array($spacing,$wordSpacing);
1218      }
1219  
1220      /**
1221       * Calculates and returns the niceText.scaleFactor
1222       *
1223       * @param    array        TypoScript array for the TEXT GIFBUILDER object
1224       * @return    integer        TypoScript value from eg $conf['niceText.']['scaleFactor']
1225       * @access private
1226       */
1227  	function getTextScalFactor($conf) {
1228          if (!$conf['niceText']) {
1229              $sF = 1;
1230          } else {        // NICETEXT::
1231              $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
1232          }
1233          return $sF;
1234      }
1235  
1236  
1237  
1238  
1239  
1240  
1241  
1242  
1243  
1244  
1245  
1246      /*********************************************
1247       *
1248       * Other GIFBUILDER objects related to TEXT
1249       *
1250       *********************************************/
1251  
1252      /**
1253       * Implements the "OUTLINE" GIFBUILDER object / property for the TEXT object
1254       *
1255       * @param    pointer        GDlib image pointer
1256       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
1257       * @param    array        The current working area coordinates.
1258       * @param    array        TypoScript array with configuration for the associated TEXT GIFBUILDER object.
1259       * @return    void
1260       * @see tslib_gifBuilder::make(), makeText()
1261       */
1262  	function makeOutline(&$im,$conf,$workArea,$txtConf)    {
1263          $thickness = intval($conf['thickness']);
1264          if ($thickness)    {
1265              $txtConf['fontColor'] = $conf['color'];
1266              $outLineDist = t3lib_div::intInRange($thickness,1,2);
1267              for ($b=1;$b<=$outLineDist;$b++)    {
1268                  if ($b==1)    {
1269                      $it = 8;
1270                  } else {
1271                      $it = 16;
1272                  }
1273                  $outL = $this->circleOffset($b, $it);
1274                  for ($a=0;$a<$it;$a++)    {
1275                      $this->makeText($im,$txtConf,$this->applyOffset($workArea,$outL[$a]));
1276                  }
1277              }
1278          }
1279      }
1280  
1281      /**
1282       * Creates some offset values in an array used to simulate a circularly applied outline around TEXT
1283       *
1284       * access private
1285       *
1286       * @param    integer        Distance
1287       * @param    integer        Iterations.
1288       * @return    array
1289       * @see makeOutline()
1290       */
1291  	function circleOffset($distance, $iterations)    {
1292          $res = Array();
1293          if ($distance && $iterations)    {
1294              for ($a=0;$a<$iterations;$a++)    {
1295                  $yOff = round(sin(2*pi()/$iterations*($a+1))*100*$distance);
1296                  if ($yOff)    {$yOff = intval(ceil(abs($yOff/100))*($yOff/abs($yOff)));}
1297                  $xOff = round(cos(2*pi()/$iterations*($a+1))*100*$distance);
1298                  if ($xOff)    {$xOff = intval(ceil(abs($xOff/100))*($xOff/abs($xOff)));}
1299                  $res[$a] = Array($xOff,$yOff);
1300              }
1301          }
1302          return $res;
1303      }
1304  
1305      /**
1306       * Implements the "EMBOSS" GIFBUILDER object / property for the TEXT object
1307       *
1308       * @param    pointer        GDlib image pointer
1309       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
1310       * @param    array        The current working area coordinates.
1311       * @param    array        TypoScript array with configuration for the associated TEXT GIFBUILDER object.
1312       * @return    void
1313       * @see tslib_gifBuilder::make(), makeShadow()
1314       */
1315  	function makeEmboss(&$im,$conf,$workArea,$txtConf)    {
1316          $conf['color']=$conf['highColor'];
1317          $this->makeShadow($im,$conf,$workArea,$txtConf);
1318          $newOffset = t3lib_div::intExplode(',',$conf['offset']);
1319          $newOffset[0]*=-1;
1320          $newOffset[1]*=-1;
1321          $conf['offset']=implode(',',$newOffset);
1322          $conf['color']=$conf['lowColor'];
1323          $this->makeShadow($im,$conf,$workArea,$txtConf);
1324      }
1325  
1326      /**
1327       * Implements the "SHADOW" GIFBUILDER object / property for the TEXT object
1328       * The operation involves ImageMagick for combining.
1329       *
1330       * @param    pointer        GDlib image pointer
1331       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
1332       * @param    array        The current working area coordinates.
1333       * @param    array        TypoScript array with configuration for the associated TEXT GIFBUILDER object.
1334       * @return    void
1335       * @see tslib_gifBuilder::make(), makeText(), makeEmboss()
1336       */
1337  	function makeShadow(&$im,$conf,$workArea,$txtConf)    {
1338          $workArea = $this->applyOffset($workArea,t3lib_div::intExplode(',',$conf['offset']));
1339          $blurRate = t3lib_div::intInRange(intval($conf['blur']),0,99);
1340  
1341          if (!$blurRate || $this->NO_IM_EFFECTS)    {        // No effects if ImageMagick ver. 5+
1342              $txtConf['fontColor'] = $conf['color'];
1343              $this->makeText($im,$txtConf,$workArea);
1344          } else {
1345              $w = imagesx($im);
1346              $h = imagesy($im);
1347              $blurBorder= 3;    // area around the blur used for cropping something
1348              $tmpStr = $this->randomName();
1349              $fileMenu = $tmpStr.'_menu.'.$this->gifExtension;
1350              $fileColor = $tmpStr.'_color.'.$this->gifExtension;
1351              $fileMask = $tmpStr.'_mask.'.$this->gifExtension;
1352  
1353                  // BlurColor Image laves
1354              $blurColImg = $this->imagecreate($w,$h);
1355              $bcols=$this->convertColor($conf['color']);
1356              $Bcolor = ImageColorAllocate($blurColImg, $bcols[0],$bcols[1],$bcols[2]);
1357              ImageFilledRectangle($blurColImg, 0, 0, $w, $h, $Bcolor);
1358              $this->ImageWrite($blurColImg, $fileColor);
1359              ImageDestroy($blurColImg);
1360  
1361                  // The mask is made: BlurTextImage
1362              $blurTextImg = $this->imagecreate($w+$blurBorder*2,$h+$blurBorder*2);
1363              $Bcolor = ImageColorAllocate($blurTextImg, 0,0,0);        // black background
1364              ImageFilledRectangle($blurTextImg, 0, 0, $w+$blurBorder*2, $h+$blurBorder*2, $Bcolor);
1365              $txtConf['fontColor'] = 'white';
1366              $blurBordArr = Array($blurBorder,$blurBorder);
1367              $this->makeText($blurTextImg,$txtConf,  $this->applyOffset($workArea,$blurBordArr));
1368              $this->ImageWrite($blurTextImg, $fileMask);    // dump to temporary file
1369              ImageDestroy($blurTextImg);    // destroy
1370  
1371  
1372              $command='';
1373              $command.=$this->maskNegate;
1374  
1375              if ($this->V5_EFFECTS)    {
1376                  $command.=$this->v5_blur($blurRate+1);
1377              } else {
1378                      // Blurring of the mask
1379                  $times = ceil($blurRate/10);    // How many blur-commands that is executed. Min = 1;
1380                  $newBlurRate = $blurRate*4;        // Here I boost the blur-rate so that it is 100 already at 25. The rest is done by up to 99 iterations of the blur-command.
1381                  $newBlurRate = t3lib_div::intInRange($newBlurRate,1,99);
1382                  for ($a=0;$a<$times;$a++)    {        // Building blur-command
1383                      $command.=' -blur '.$blurRate;
1384                  }
1385              }
1386  
1387              $this->imageMagickExec($fileMask,$fileMask,$command.' +matte');
1388  
1389              $blurTextImg_tmp = $this->imageCreateFromFile($fileMask);    // the mask is loaded again
1390              if ($blurTextImg_tmp)    {    // if nothing went wrong we continue with the blurred mask
1391  
1392                      // cropping the border from the mask
1393                  $blurTextImg = $this->imagecreate($w,$h);
1394                  $this->imagecopyresized($blurTextImg, $blurTextImg_tmp, 0, 0, $blurBorder, $blurBorder, $w, $h, $w, $h);
1395                  ImageDestroy($blurTextImg_tmp);    // Destroy the temporary mask
1396  
1397                      // adjust the mask
1398                  $intensity = 40;
1399                  if ($conf['intensity'])    {
1400                      $intensity = t3lib_div::intInRange($conf['intensity'],0,100);
1401                  }
1402                  $intensity = ceil(255-($intensity/100*255));
1403                  $this->inputLevels($blurTextImg,0,$intensity,$this->maskNegate);
1404  
1405                  $opacity = t3lib_div::intInRange(intval($conf['opacity']),0,100);
1406                  if ($opacity && $opacity<100)    {
1407                      $high = ceil(255*$opacity/100);
1408                      $this->outputLevels($blurTextImg,0,$high,$this->maskNegate);    // reducing levels as the opacity demands
1409                  }
1410  
1411                  $this->ImageWrite($blurTextImg, $fileMask);    // Dump the mask again
1412                  ImageDestroy($blurTextImg);    // Destroy the mask
1413  
1414                      // The pictures are combined
1415                  $this->ImageWrite($im, $fileMenu);    // The main pictures is saved temporarily
1416  
1417                  $this->combineExec($fileMenu,$fileColor,$fileMask,$fileMenu);
1418  
1419                  $backIm = $this->imageCreateFromFile($fileMenu);    // The main image is loaded again...
1420                  if ($backIm)    {    // ... and if nothing went wrong we load it onto the old one.
1421                      ImageColorTransparent($backIm,-1);
1422                      $im = $backIm;
1423                  }
1424              }
1425                  // Deleting temporary files;
1426              if (!$this->dontUnlinkTempFiles)    {
1427                  unlink($fileMenu);
1428                  unlink($fileColor);
1429                  unlink($fileMask);
1430              }
1431          }
1432      }
1433  
1434  
1435  
1436  
1437  
1438  
1439  
1440  
1441  
1442  
1443  
1444  
1445  
1446  
1447  
1448  
1449  
1450  
1451  
1452  
1453  
1454      /****************************
1455       *
1456       * Other GIFBUILDER objects
1457       *
1458       ****************************/
1459  
1460      /**
1461       * Implements the "BOX" GIFBUILDER object
1462       *
1463       * @param    pointer        GDlib image pointer
1464       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
1465       * @param    array        The current working area coordinates.
1466       * @return    void
1467       * @see tslib_gifBuilder::make()
1468       */
1469  	function makeBox(&$im,$conf,$workArea)    {
1470          $cords = t3lib_div::intExplode(',',$conf['dimensions'].',,,');
1471          $conf['offset']=$cords[0].','.$cords[1];
1472          $cords = $this->objPosition($conf,$workArea,Array($cords[2],$cords[3]));
1473          $cols=$this->convertColor($conf['color']);
1474          if (!$this->truecolor)    {
1475              $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256);
1476              $this->reduceColors($im, $reduce-1, $reduce-2);    // If "reduce-1" colors (or more) are used reduce them to "reduce-2"
1477          }
1478          $tmpColor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
1479          imagefilledrectangle($im, $cords[0], $cords[1], $cords[0]+$cords[2]-1, $cords[1]+$cords[3]-1, $tmpColor);
1480      }
1481  
1482      /**
1483       * Implements the "EFFECT" GIFBUILDER object
1484       * The operation involves ImageMagick for applying effects
1485       *
1486       * @param    pointer        GDlib image pointer
1487       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
1488       * @return    void
1489       * @see tslib_gifBuilder::make(), applyImageMagickToPHPGif()
1490       */
1491  	function makeEffect(&$im, $conf)    {
1492          $commands = $this->IMparams($conf['value']);
1493          if ($commands)    {
1494              $this->applyImageMagickToPHPGif($im, $commands);
1495          }
1496      }
1497  
1498      /**
1499       * Creating ImageMagick paramters from TypoScript property
1500       *
1501       * @param    string        A string with effect keywords=value pairs separated by "|"
1502       * @return    string        ImageMagick prepared parameters.
1503       * @access private
1504       * @see makeEffect()
1505       */
1506  	function IMparams($setup)    {
1507          if (!trim($setup)){return '';}
1508          $effects = explode('|', $setup);
1509          $commands = '';
1510          while(list(,$val)=each($effects))    {
1511              $pairs=explode('=',$val,2);
1512              $value = trim($pairs[1]);
1513              $effect = strtolower(trim($pairs[0]));
1514              switch($effect)    {
1515                  case 'gamma':
1516                      $commands.=' -gamma '.doubleval($value);
1517                  break;
1518                  case 'blur':
1519                      if (!$this->NO_IM_EFFECTS)    {
1520                          if ($this->V5_EFFECTS)    {
1521                              $commands.=$this->v5_blur($value);
1522                          } else {
1523                              $commands.=' -blur '.t3lib_div::intInRange($value,1,99);
1524                          }
1525                      }
1526                  break;
1527                  case 'sharpen':
1528                      if (!$this->NO_IM_EFFECTS)    {
1529                          if ($this->V5_EFFECTS)    {
1530                              $commands.=$this->v5_sharpen($value);
1531                          } else {
1532                              $commands.=' -sharpen '.t3lib_div::intInRange($value,1,99);
1533                          }
1534                      }
1535                  break;
1536                  case 'rotate':
1537                      $commands.=' -rotate '.t3lib_div::intInRange($value,0,360);
1538                  break;
1539                  case 'solarize':
1540                      $commands.=' -solarize '.t3lib_div::intInRange($value,0,99);
1541                  break;
1542                  case 'swirl':
1543                      $commands.=' -swirl '.t3lib_div::intInRange($value,0,1000);
1544                  break;
1545                  case 'wave':
1546                      $params = t3lib_div::intExplode(',',$value);
1547                      $commands.=' -wave '.t3lib_div::intInRange($params[0],0,99).'x'.t3lib_div::intInRange($params[1],0,99);
1548                  break;
1549                  case 'charcoal':
1550                      $commands.=' -charcoal '.t3lib_div::intInRange($value,0,100);
1551                  break;
1552                  case 'gray':
1553                      $commands.=' -colorspace GRAY';
1554                  break;
1555                  case 'edge':
1556                      $commands.=' -edge '.t3lib_div::intInRange($value,0,99);
1557                  break;
1558                  case 'emboss':
1559                      $commands.=' -emboss';
1560                  break;
1561                  case 'flip':
1562                      $commands.=' -flip';
1563                  break;
1564                  case 'flop':
1565                      $commands.=' -flop';
1566                  break;
1567                  case 'colors':
1568                      $commands.=' -colors '.t3lib_div::intInRange($value,2,255);
1569                  break;
1570                  case 'shear':
1571                      $commands.=' -shear '.t3lib_div::intInRange($value,-90,90);
1572                  break;
1573                  case 'invert':
1574                      $commands.=' -negate';
1575                  break;
1576              }
1577          }
1578          return $commands;
1579      }
1580  
1581      /**
1582       * Implements the "ADJUST" GIFBUILDER object
1583       *
1584       * @param    pointer        GDlib image pointer
1585       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
1586       * @return    void
1587       * @see tslib_gifBuilder::make(), autoLevels(), outputLevels(), inputLevels()
1588       */
1589  	function adjust(&$im, $conf)    {
1590          $setup = $conf['value'];
1591          if (!trim($setup)){return '';}
1592          $effects = explode('|', $setup);
1593          while(list(,$val)=each($effects))    {
1594              $pairs=explode('=',$val,2);
1595              $value = trim($pairs[1]);
1596              $effect = strtolower(trim($pairs[0]));
1597              switch($effect)    {
1598                  case 'inputlevels':    // low,high
1599                      $params = t3lib_div::intExplode(',',$value);
1600                      $this->inputLevels($im,$params[0],$params[1]);
1601                  break;
1602                  case 'outputlevels':
1603                      $params = t3lib_div::intExplode(',',$value);
1604                      $this->outputLevels($im,$params[0],$params[1]);
1605                  break;
1606                  case 'autolevels':
1607                      $this->autoLevels($im);
1608                  break;
1609              }
1610          }
1611      }
1612  
1613      /**
1614       * Implements the "CROP" GIFBUILDER object
1615       *
1616       * @param    pointer        GDlib image pointer
1617       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
1618       * @return    void
1619       * @see tslib_gifBuilder::make()
1620       */
1621  	function crop(&$im,$conf)    {
1622          $this->setWorkArea('');    // clears workArea to total image
1623          $cords = t3lib_div::intExplode(',',$conf['crop'].',,,');
1624          $conf['offset']=$cords[0].','.$cords[1];
1625          $cords = $this->objPosition($conf,$this->workArea,Array($cords[2],$cords[3]));
1626  
1627          $newIm = $this->imagecreate($cords[2],$cords[3]);
1628          $cols=$this->convertColor($conf['backColor']?$conf['backColor']:$this->setup['backColor']);
1629          $Bcolor = ImageColorAllocate($newIm, $cols[0],$cols[1],$cols[2]);
1630          ImageFilledRectangle($newIm, 0, 0, $cords[2], $cords[3], $Bcolor);
1631  
1632          $newConf = Array();
1633          $workArea = Array(0,0,$cords[2],$cords[3]);
1634          if ($cords[0]<0) {$workArea[0]=abs($cords[0]);} else {$newConf['offset']=-$cords[0];}
1635          if ($cords[1]<0) {$workArea[1]=abs($cords[1]);} else {$newConf['offset'].=','.-$cords[1];}
1636  
1637          $this->copyGifOntoGif($newIm,$im,$newConf,$workArea);
1638          $im = $newIm;
1639          $this->w = imagesx($im);
1640          $this->h = imagesy($im);
1641          $this->setWorkArea('');    // clears workArea to total image
1642      }
1643  
1644      /**
1645       * Implements the "SCALE" GIFBUILDER object
1646       *
1647       * @param    pointer        GDlib image pointer
1648       * @param    array        TypoScript array with configuration for the GIFBUILDER object.
1649       * @return    void
1650       * @see tslib_gifBuilder::make()
1651       */
1652  	function scale(&$im,$conf)    {
1653          if ($conf['width'] || $conf['height'] || $conf['params'])    {
1654              $tmpStr = $this->randomName();
1655              $theFile = $tmpStr.'.'.$this->gifExtension;
1656              $this->ImageWrite($im, $theFile);
1657              $theNewFile = $this->imageMagickConvert($theFile,$this->gifExtension,$conf['width'],$conf['height'],$conf['params'],'','');
1658              $tmpImg = $this->imageCreateFromFile($theNewFile[3]);
1659              if ($tmpImg)    {
1660                  ImageDestroy($im);
1661                  $im = $tmpImg;
1662                  $this->w = imagesx($im);
1663                  $this->h = imagesy($im);
1664                  $this->setWorkArea('');    // clears workArea to total image
1665              }
1666              if (!$this->dontUnlinkTempFiles)    {
1667                  unlink($theFile);
1668                  if ($theNewFile[3] && $theNewFile[3]!=$theFile)    {
1669                      unlink($theNewFile[3]);
1670                  }
1671              }
1672          }
1673      }
1674  
1675      /**
1676       * Implements the "WORKAREA" GIFBUILDER object when setting it
1677       * Setting internal working area boundaries (->workArea)
1678       *
1679       * @param    string        Working area dimensions, comma separated
1680       * @return    void
1681       * @access private
1682       * @see tslib_gifBuilder::make()
1683       */
1684  	function setWorkArea($workArea)    {
1685          $this->workArea = t3lib_div::intExplode(',',$workArea);
1686          $this->workArea = $this->applyOffset($this->workArea,$this->OFFSET);
1687          if (!$this->workArea[2])    {$this->workArea[2]=$this->w;}
1688          if (!$this->workArea[3])    {$this->workArea[3]=$this->h;}
1689      }
1690  
1691  
1692  
1693  
1694  
1695  
1696  
1697  
1698  
1699  
1700  
1701  
1702  
1703  
1704  
1705  
1706  
1707  
1708  
1709  
1710  
1711  
1712  
1713      /*************************
1714       *
1715       * Adjustment functions
1716       *
1717       ************************/
1718  
1719      /**
1720       * Apply auto-levels to input image pointer
1721       *
1722       * @param    integer        GDlib Image Pointer
1723       * @return    void
1724       */
1725  	function autolevels(&$im)    {
1726          $totalCols = ImageColorsTotal($im);
1727          $min=255;
1728          $max=0;
1729          for ($c=0; $c<$totalCols; $c++)    {
1730              $cols = ImageColorsForIndex($im,$c);
1731              $grayArr[] = round(($cols['red']+$cols['green']+$cols['blue'])/3);
1732          }
1733          $min=min($grayArr);
1734          $max=max($grayArr);
1735          $delta = $max-$min;
1736          if ($delta)    {
1737              for ($c=0; $c<$totalCols; $c++)    {
1738                  $cols = ImageColorsForIndex($im,$c);
1739                  $cols['red'] = floor(($cols['red']-$min)/$delta*255);
1740                  $cols['green'] = floor(($cols['green']-$min)/$delta*255);
1741                  $cols['blue'] = floor(($cols['blue']-$min)/$delta*255);
1742                  ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']);
1743              }
1744          }
1745      }
1746  
1747      /**
1748       * Apply output levels to input image pointer (decreasing contrast)
1749       *
1750       * @param    integer        GDlib Image Pointer
1751       * @param    integer        The "low" value (close to 0)
1752       * @param    integer        The "high" value (close to 255)
1753       * @param    boolean        If swap, then low and high are swapped. (Useful for negated masks...)
1754       * @return    void
1755       */
1756  	function outputLevels(&$im,$low,$high,$swap='')    {
1757          if ($low<$high){
1758              $low = t3lib_div::intInRange($low,0,255);
1759              $high = t3lib_div::intInRange($high,0,255);
1760  
1761              if ($swap)    {
1762                  $temp = $low;
1763                  $low = 255-$high;
1764                  $high = 255-$temp;
1765              }
1766  
1767              $delta = $high-$low;
1768              $totalCols = ImageColorsTotal($im);
1769              for ($c=0; $c<$totalCols; $c++)    {
1770                  $cols = ImageColorsForIndex($im,$c);
1771                  $cols['red'] = $low+floor($cols['red']/255*$delta);
1772                  $cols['green'] = $low+floor($cols['green']/255*$delta);
1773                  $cols['blue'] = $low+floor($cols['blue']/255*$delta);
1774                  ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']);
1775              }
1776          }
1777      }
1778  
1779      /**
1780       * Apply input levels to input image pointer (increasing contrast)
1781       *
1782       * @param    integer        GDlib Image Pointer
1783       * @param    integer        The "low" value (close to 0)
1784       * @param    integer        The "high" value (close to 255)
1785       * @param    boolean        If swap, then low and high are swapped. (Useful for negated masks...)
1786       * @return    void
1787       */
1788  	function inputLevels(&$im,$low,$high,$swap='')    {
1789          if ($low<$high){
1790              $low = t3lib_div::intInRange($low,0,255);
1791              $high = t3lib_div::intInRange($high,0,255);
1792  
1793              if ($swap)    {
1794                  $temp = $low;
1795                  $low = 255-$high;
1796                  $high = 255-$temp;
1797              }
1798  
1799              $delta = $high-$low;
1800              $totalCols = ImageColorsTotal($im);
1801              for ($c=0; $c<$totalCols; $c++)    {
1802                  $cols = ImageColorsForIndex($im,$c);
1803                  $cols['red'] = t3lib_div::intInRange(($cols['red']-$low)/$delta*255, 0,255);
1804                  $cols['green'] = t3lib_div::intInRange(($cols['green']-$low)/$delta*255, 0,255);
1805                  $cols['blue'] = t3lib_div::intInRange(($cols['blue']-$low)/$delta*255, 0,255);
1806                  ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']);
1807              }
1808          }
1809      }
1810  
1811      /**
1812       * Reduce colors in image dependend on the actual amount of colors (Only works if we are not in truecolor mode)
1813       *
1814       * @param    integer        GDlib Image Pointer
1815       * @param    integer        The max number of colors in the image before a reduction will happen; basically this means that IF the GD image current has the same amount or more colors than $limit define, THEN a reduction is performed.
1816       * @param    integer        Number of colors to reduce the image to.
1817       * @return    void
1818       */
1819  	function reduceColors(&$im,$limit, $cols)    {
1820          if (!$this->truecolor && ImageColorsTotal($im)>=$limit)    {
1821              $this->makeEffect($im, Array('value'=>'colors='.$cols) );
1822          }
1823      }
1824  
1825      /**
1826       * Reduce colors in image using IM and create a palette based image if possible (<=256 colors)
1827       *
1828       * @param    string        Image file to reduce
1829       * @param    integer        Number of colors to reduce the image to.
1830       * @return    string        Reduced file
1831       */
1832  	function IMreduceColors($file, $cols)    {
1833          $fI = t3lib_div::split_fileref($file);
1834          $ext = strtolower($fI['fileext']);
1835          $result = $this->randomName().'.'.$ext;
1836          if (($reduce = t3lib_div::intInRange($cols, 0, ($ext=='gif'?256:$this->truecolorColors), 0))>0)    {
1837              $params = ' -colors '.$reduce;
1838              if (!$this->im_version_4)    {
1839                      // IM4 doesn't have this options but forces them automatically if applicaple (<256 colors in image)
1840                  if ($reduce<=256)    { $params .= ' -type Palette'; }
1841                  if ($ext=='png' && $reduce<=256)    { $prefix = 'png8:'; }
1842              }
1843              $this->imageMagickExec($file, $prefix.$result, $params);
1844              if ($result)    {
1845                  return $result;
1846              }
1847          }
1848          return '';
1849      }
1850  
1851  
1852  
1853  
1854  
1855  
1856  
1857  
1858  
1859  
1860  
1861      /*********************************
1862       *
1863       * GIFBUILDER Helper functions
1864       *
1865       *********************************/
1866  
1867      /**
1868       * Checks if the $fontFile is already at an absolute path and if not, prepends the correct path.
1869       * Use PATH_site unless we are in the backend.
1870       * Call it by t3lib_stdGraphic::prependAbsolutePath()
1871       *
1872       * @param    string        The font file
1873       * @return    string        The font file with absolute path.
1874       */
1875  	function prependAbsolutePath($fontFile)    {
1876          $absPath = defined('PATH_typo3') ? dirname(PATH_thisScript).'/' :PATH_site;
1877          $fontFile = t3lib_div::isAbsPath($fontFile) ? $fontFile : t3lib_div::resolveBackPath($absPath.$fontFile);
1878          return $fontFile;
1879      }
1880  
1881      /**
1882       * Returns the IM command for sharpening with ImageMagick 5 (when $this->V5_EFFECTS is set).
1883       * Uses $this->im5fx_sharpenSteps for translation of the factor to an actual command.
1884       *
1885       * @param    integer        The sharpening factor, 0-100 (effectively in 10 steps)
1886       * @return    string        The sharpening command, eg. " -sharpen 3x4"
1887       * @see makeText(), IMparams(), v5_blur()
1888       */
1889  	function v5_sharpen($factor)    {
1890          $factor = t3lib_div::intInRange(ceil($factor/10),0,10);
1891  
1892          $sharpenArr=explode(',',','.$this->im5fx_sharpenSteps);
1893          $sharpenF= trim($sharpenArr[$factor]);
1894          if ($sharpenF)    {
1895              $cmd = ' -sharpen '.$sharpenF;
1896              return $cmd;
1897          }
1898      }
1899  
1900      /**
1901       * Returns the IM command for blurring with ImageMagick 5 (when $this->V5_EFFECTS is set).
1902       * Uses $this->im5fx_blurSteps for translation of the factor to an actual command.
1903       *
1904       * @param    integer        The blurring factor, 0-100 (effectively in 10 steps)
1905       * @return    string        The blurring command, eg. " -blur 3x4"
1906       * @see makeText(), IMparams(), v5_sharpen()
1907       */
1908  	function v5_blur($factor)    {
1909          $factor = t3lib_div::intInRange(ceil($factor/10),0,10);
1910  
1911          $blurArr=explode(',',','.$this->im5fx_blurSteps);
1912          $blurF= trim($blurArr[$factor]);
1913          if ($blurF)    {
1914              $cmd=' -blur '.$blurF;
1915              return $cmd;
1916          }
1917      }
1918  
1919      /**
1920       * Returns a random filename prefixed with "temp_" and then 32 char md5 hash (without extension) from $this->tempPath.
1921       * Used by functions in this class to create truely temporary files for the on-the-fly processing. These files will most likely be deleted right away.
1922       *
1923       * @return    string
1924       */
1925  	function randomName()    {
1926          $this->createTempSubDir('temp/');
1927          return $this->tempPath.'temp/'.md5(uniqid(''));
1928      }
1929  
1930      /**
1931       * Applies offset value to coordinated in $cords.
1932       * Basically the value of key 0/1 of $OFFSET is added to keys 0/1 of $cords
1933       *
1934       * @param    array        Integer coordinates in key 0/1
1935       * @param    array        Offset values in key 0/1
1936       * @return    array        Modified $cords array
1937       */
1938  	function applyOffset($cords,$OFFSET)    {
1939          $cords[0] = intval($cords[0])+intval($OFFSET[0]);
1940          $cords[1] = intval($cords[1])+intval($OFFSET[1]);
1941          return $cords;
1942      }
1943  
1944      /**
1945       * Converts a "HTML-color" TypoScript datatype to RGB-values.
1946       * Default is 0,0,0
1947       *
1948       * @param    string        "HTML-color" data type string, eg. 'red', '#ffeedd' or '255,0,255'. You can also add a modifying operator afterwards. There are two options: "255,0,255 : 20" - will add 20 to values, result is "255,20,255". Or "255,0,255 : *1.23" which will multiply all RGB values with 1.23
1949       * @return    array        RGB values in key 0/1/2 of the array
1950       */
1951  	function convertColor($string)    {
1952          $col=array();
1953          $cParts = explode(':',$string,2);
1954  
1955              // Finding the RGB definitions of the color:
1956          $string=$cParts[0];
1957          if (strstr($string,'#'))    {
1958              $string = ereg_replace('[^A-Fa-f0-9]*','',$string);
1959              $col[]=HexDec(substr($string,0,2));
1960              $col[]=HexDec(substr($string,2,2));
1961              $col[]=HexDec(substr($string,4,2));
1962          } elseif (strstr($string,','))    {
1963              $string = ereg_replace('[^,0-9]*','',$string);
1964              $strArr = explode(',',$string);
1965              $col[]=intval($strArr[0]);
1966              $col[]=intval($strArr[1]);
1967              $col[]=intval($strArr[2]);
1968          } else {
1969              $string = strtolower(trim($string));
1970              if ($this->colMap[$string])    {
1971                  $col = $this->colMap[$string];
1972              } else {
1973                  $col = Array(0,0,0);
1974              }
1975          }
1976              // ... and possibly recalculating the value
1977          if (trim($cParts[1]))    {
1978              $cParts[1]=trim($cParts[1]);
1979              if (substr($cParts[1],0,1)=='*')    {
1980                  $val=doubleval(substr($cParts[1],1));
1981                  $col[0]=t3lib_div::intInRange($col[0]*$val,0,255);
1982                  $col[1]=t3lib_div::intInRange($col[1]*$val,0,255);
1983                  $col[2]=t3lib_div::intInRange($col[2]*$val,0,255);
1984              } else {
1985                  $val=intval($cParts[1]);
1986                  $col[0]=t3lib_div::intInRange($col[0]+$val,0,255);
1987                  $col[1]=t3lib_div::intInRange($col[1]+$val,0,255);
1988                  $col[2]=t3lib_div::intInRange($col[2]+$val,0,255);
1989              }
1990          }
1991          return $col;
1992      }
1993  
1994      /**
1995       * Recode string
1996       * Used with text strings for fonts when languages has other character sets.
1997       *
1998       * @param    string        The text to recode
1999       * @return    string        The recoded string. Should be UTF-8 output. MAY contain entities (eg. &#123; or &#quot; which should render as real chars).
2000       */
2001  	function recodeString($string)    {
2002              // Recode string to UTF-8 from $this->nativeCharset:
2003          if ($this->nativeCharset && $this->nativeCharset!='utf-8')    {
2004              $string = $this->csConvObj->utf8_encode($string,$this->nativeCharset);    // Convert to UTF-8
2005          }
2006  
2007              // Recode string accoding to TTFLocaleConv. Deprecated.
2008          if ($this->TTFLocaleConv)    {
2009              $string = recode_string($this->TTFLocaleConv,$string);
2010          }
2011  
2012          return $string;
2013      }
2014  
2015      /**
2016       * Split a string into an array of individual characters
2017       * The function will look at $this->nativeCharset and if that is set, the input string is expected to be UTF-8 encoded, possibly with entities in it. Otherwise the string is supposed to be a single-byte charset which is just splitted by a for-loop.
2018       *
2019       * @param    string        The text string to split
2020       * @param    boolean        Return Unicode numbers instead of chars.
2021       * @return    array        Numerical array with a char as each value.
2022       */
2023  	function singleChars($theText,$returnUnicodeNumber=FALSE)    {
2024          if ($this->nativeCharset)    {
2025              return $this->csConvObj->utf8_to_numberarray($theText,1,$returnUnicodeNumber ? 0 : 1);    // Get an array of separated UTF-8 chars
2026          } else {
2027              $output=array();
2028              $c=strlen($theText);
2029              for($a=0;$a<$c;$a++)    {
2030                  $output[]=substr($theText,$a,1);
2031              }
2032              return $output;
2033          }
2034      }
2035  
2036      /**
2037       * Create an array with object position/boundaries based on input TypoScript configuration (such as the "align" property is used), the work area definition and $BB array
2038       *
2039       * @param    array        TypoScript configuration for a GIFBUILDER object
2040       * @param    array        Workarea definition
2041       * @param    array        BB (Bounding box) array. Not just used for TEXT objects but also for others
2042       * @return    array        [0]=x, [1]=y, [2]=w, [3]=h
2043       * @access private
2044       * @see copyGifOntoGif(), makeBox(), crop()
2045       */
2046  	function objPosition($conf,$workArea,$BB) {
2047              // offset, align, valign, workarea
2048          $result=Array();
2049          $result[2] = $BB[0];
2050          $result[3] = $BB[1];
2051          $w=$workArea[2];
2052          $h=$workArea[3];
2053  
2054          $align = explode(',',$conf['align']);
2055          $align[0] = strtolower(substr(trim($align[0]),0,1));
2056          $align[1] = strtolower(substr(trim($align[1]),0,1));
2057  
2058          switch($align[0])    {
2059              case 'r':
2060                  $result[0]=$w-$result[2];
2061              break;
2062              case 'c':
2063                  $result[0] = round(($w-$result[2])/2);
2064              break;
2065              default:
2066                  $result[0] = 0;
2067              break;
2068          }
2069          switch($align[1])    {
2070              case 'b':
2071                  $result[1] = $h-$result[3];    // y pos
2072              break;
2073              case 'c':
2074                  $result[1] = round(($h-$result[3])/2);
2075              break;
2076              default:
2077                  $result[1]=0;
2078              break;
2079          }
2080          $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset']));
2081          $result = $this->applyOffset($result,$workArea);
2082          return $result;
2083      }
2084  
2085  
2086  
2087  
2088  
2089  
2090  
2091  
2092  
2093  
2094  
2095  
2096  
2097  
2098  
2099  
2100  
2101  
2102  
2103  
2104  
2105      /***********************************
2106       *
2107       * Scaling, Dimensions of images
2108       *
2109       ***********************************/
2110  
2111      /**
2112       * Converts $imagefile to another file in temp-dir of type $newExt (extension).
2113       *
2114       * @param    string        The image filepath
2115       * @param    string        New extension, eg. "gif", "png", "jpg", "tif". If $newExt is NOT set, the new imagefile will be of the original format. If newExt = 'WEB' then one of the web-formats is applied.
2116       * @param    string        Width. $w / $h is optional. If only one is given the image is scaled proportionally. If an 'm' exists in the $w or $h and if both are present the $w and $h is regarded as the Maximum w/h and the proportions will be kept
2117       * @param    string        Height. See $w
2118       * @param    string        Additional ImageMagick parameters.
2119       * @param    string        Refers to which frame-number to select in the image. '' or 0 will select the first frame, 1 will select the next and so on...
2120       * @param    array        An array with options passed to getImageScale (see this function).
2121       * @param    boolean        If set, then another image than the input imagefile MUST be returned. Otherwise you can risk that the input image is good enough regarding messures etc and is of course not rendered to a new, temporary file in typo3temp/. But this option will force it to.
2122       * @return    array        [0]/[1] is w/h, [2] is file extension and [3] is the filename.
2123       * @see getImageScale(), typo3/show_item.php, fileList_ext::renderImage(), tslib_cObj::getImgResource(), SC_tslib_showpic::show(), maskImageOntoImage(), copyImageOntoImage(), scale()
2124       */
2125  	function imageMagickConvert($imagefile,$newExt='',$w='',$h='',$params='',$frame='',$options='',$mustCreate=0)    {
2126          if ($this->NO_IMAGE_MAGICK)    {
2127                  // Returning file info right away
2128              return $this->getImageDimensions($imagefile);
2129          }
2130  
2131          if($info=$this->getImageDimensions($imagefile))    {
2132              $newExt=strtolower(trim($newExt));
2133              if (!$newExt)    {    // If no extension is given the original extension is used
2134                  $newExt = $info[2];
2135              }
2136              if ($newExt=='web')    {
2137                  if (t3lib_div::inList($this->webImageExt,$info[2]))    {
2138                      $newExt = $info[2];
2139                  } else {
2140                      $newExt = $this->gif_or_jpg($info[2],$info[0],$info[1]);
2141                      if (!$params)    {
2142                          $params = $this->cmds[$newExt];
2143                      }
2144                  }
2145              }
2146              if (t3lib_div::inList($this->imageFileExt,$newExt))    {
2147                  if (strstr($w.$h, 'm')) {$max=1;} else {$max=0;}
2148  
2149                  $data = $this->getImageScale($info,$w,$h,$options);
2150                  $w=$data['origW'];
2151                  $h=$data['origH'];
2152  
2153                      // if no convertion should be performed
2154                  $wh_noscale = (!$w && !$h) || ($data[0]==$info[0] && $data[1]==$info[1]);        // this flag is true if the width / height does NOT dictate the image to be scaled!! (that is if no w/h is given or if the destination w/h matches the original image-dimensions....
2155  
2156                  if ($wh_noscale && !$data['crs'] && !$params && !$frame && $newExt==$info[2] && !$mustCreate) {
2157                      $info[3] = $imagefile;
2158                      return $info;
2159                  }
2160                  $info[0]=$data[0];
2161                  $info[1]=$data[1];
2162  
2163                  $frame = $this->noFramePrepended ? '' : '['.intval($frame).']';
2164  
2165                  if (!$params)    {
2166                      $params = $this->cmds[$newExt];
2167                  }
2168  
2169                  $command = $this->scalecmd.' '.$info[0].'x'.$info[1].'! '.$params.' ';
2170                  $cropscale = ($data['crs'] ? 'crs-V'.$data['cropV'].'H'.$data['cropH'] : '');
2171  
2172                  if ($this->alternativeOutputKey)    {
2173                      $theOutputName = t3lib_div::shortMD5($command.$cropscale.basename($imagefile).$this->alternativeOutputKey.$frame);
2174                  } else {
2175                      $theOutputName = t3lib_div::shortMD5($command.$cropscale.$imagefile.filemtime($imagefile).$frame);
2176                  }
2177                  if ($this->imageMagickConvert_forceFileNameBody)    {
2178                      $theOutputName = $this->imageMagickConvert_forceFileNameBody;
2179                      $this->imageMagickConvert_forceFileNameBody='';
2180                  }
2181  
2182                      // Making the temporary filename:
2183                  $this->createTempSubDir('pics/');
2184                  $output = $this->absPrefix.$this->tempPath.'pics/'.$this->filenamePrefix.$theOutputName.'.'.$newExt;
2185  
2186                      // Register temporary filename:
2187                  $GLOBALS['TEMP_IMAGES_ON_PAGE'][] = $output;
2188  
2189                      // Cropscaling:
2190                  if ($data['crs'])    {
2191                      if ($this->dontCheckForExistingTempFile || !$this->file_exists_typo3temp_file($output, $imagefile))    {
2192                          $crsOutput = str_replace('pics/', 'pics/crs-', $output);
2193                          $this->imageMagickExec($imagefile.$frame, $crsOutput, $command);
2194                          $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
2195                          $gifCreator->init();
2196                          if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'] !== 0)    {
2197                              if (!$data['origW']) { $data['origW'] = $data[0]; }
2198                              if (!$data['origH']) { $data['origH'] = $data[1]; }
2199                              $ofX = intval(($data['origW'] - $data[0]) * ($data['cropH']+100)/200);
2200                              $ofY = intval(($data['origH'] - $data[1]) * ($data['cropV']+100)/200);
2201                              $tmpParm = Array('XY' => intval($data['origW']).','.intval($data['origH']),
2202                                      '10' => 'IMAGE',
2203                                      '10.' => array('file'=> $crsOutput, 'offset'=> $ofX.','.$ofY),
2204                              );
2205                              $gifCreator->start($tmpParm, array());
2206                              $newoutput = $gifCreator->gifBuild();
2207                              if (!copy($newoutput,$output)) {
2208                                  $output = $newoutput;
2209                              }
2210                          } else {
2211                              $output = $crsOutput;
2212                          }
2213                      }
2214                  } elseif ($this->dontCheckForExistingTempFile || !$this->file_exists_typo3temp_file($output,$imagefile)) {
2215                      $this->imageMagickExec($imagefile.$frame,$output,$command);
2216                  }
2217                  if (@file_exists($output))    {
2218                      $info[3] = $output;
2219                      $info[2] = $newExt;
2220                      if ($params)    {    // params could realisticly change some imagedata!
2221                          $info=$this->getImageDimensions($info[3]);
2222                      }
2223                      if ($info[2]==$this->gifExtension && !$this->dontCompress)    {
2224                          t3lib_div::gif_compress($info[3],'');        // Compress with IM (lzw) or GD (rle)  (Workaround for the absence of lzw-compression in GD)
2225                      }
2226                      return $info;
2227                  }
2228              }
2229          }
2230      }
2231  
2232      /**
2233       * Gets the input image dimensions.
2234       *
2235       * @param    string        The image filepath
2236       * @return    array        Returns an array where [0]/[1] is w/h, [2] is extension and [3] is the filename.
2237       * @see imageMagickConvert(), tslib_cObj::getImgResource()
2238       */
2239  	function getImageDimensions($imageFile)    {
2240          ereg('([^\.]*)$',$imageFile,$reg);
2241          if (@file_exists($imageFile) && t3lib_div::inList($this->imageFileExt,strtolower($reg[0])))    {
2242              if ($returnArr = $this->getCachedImageDimensions($imageFile))    {
2243                  return $returnArr;
2244              } else {
2245                  if ($temp = @getImageSize($imageFile))    {
2246                      $returnArr = Array($temp[0], $temp[1], strtolower($reg[0]), $imageFile);
2247                  } else {
2248                      $returnArr = $this->imageMagickIdentify($imageFile);
2249                  }
2250                  if ($returnArr) {
2251                      $this->cacheImageDimensions($returnArr);
2252                      return $returnArr;
2253                  }
2254              }
2255          }
2256          return false;
2257      }
2258  
2259      /**
2260       * Cache the result of the getImageDimensions function into the database. Does not check if the
2261       * file exists!
2262       *
2263       * @param    array        $identifyResult: Result of the getImageDimensions function
2264       * @return    boolean        True if operation was successful
2265       * @author    Michael Stucki <michael@typo3.org> / Robert Lemke <rl@robertlemke.de>
2266       */
2267  	function cacheImageDimensions($identifyResult)    {
2268          global $TYPO3_DB;
2269              // Create a md5 hash of the filename
2270          $md5Hash = md5_file($identifyResult[3]);
2271          if ($md5Hash) {
2272              $fieldArr = array (
2273                  'md5hash' => $md5Hash,
2274                  'md5filename' => md5($identifyResult[3]),
2275                  'tstamp' => time(),
2276                  'filename' => $identifyResult[3],
2277                  'imagewidth' => $identifyResult[0],
2278                  'imageheight' => $identifyResult[1],
2279              );
2280              $TYPO3_DB->exec_INSERTquery('cache_imagesizes', $fieldArr);
2281              if (!$err = $TYPO3_DB->sql_error())    {
2282                  return true;
2283              }
2284          }
2285          return false;
2286      }
2287  
2288      /**
2289       * Fetch the cached imageDimensions from the MySQL database. Does not check if the image file exists!
2290       *
2291       * @param    string        The image filepath
2292       * @return    array        Returns an array where [0]/[1] is w/h, [2] is extension and [3] is the filename.
2293       * @author    Michael Stucki <michael@typo3.org> / Robert Lemke <rl@robertlemke.de>
2294       */
2295  	function getCachedImageDimensions($imageFile)    {
2296          global $TYPO3_DB;
2297              // Create a md5 hash of the filename
2298          $md5Hash = md5_file($imageFile);
2299          ereg('([^\.]*)$',$imageFile,$reg);
2300          $res = $TYPO3_DB->exec_SELECTquery ('md5hash, imagewidth, imageheight', 'cache_imagesizes', 'md5filename='.$TYPO3_DB->fullQuoteStr(md5($imageFile),'cache_imagesizes'));
2301          if ($res) {
2302              if ($row = $TYPO3_DB->sql_fetch_assoc($res)) {
2303                  if ($row['md5hash']!=$md5Hash) {
2304                          // file has changed, delete the row
2305                      $TYPO3_DB->exec_DELETEquery ('cache_imagesizes', 'md5hash='.$TYPO3_DB->fullQuoteStr($row['md5hash'],'cache_imagesizes'));
2306                  } else {
2307                      return (array($row['imagewidth'], $row['imageheight'], strtolower($reg[0]), $imageFile));
2308                  }
2309              }
2310          }
2311          return false;
2312      }
2313  
2314      /**
2315       * Get numbers for scaling the image based on input
2316       *
2317       * @param    array        Current image information: Width, Height etc.
2318       * @param    integer        "required" width
2319       * @param    integer        "required" height
2320       * @param    array        Options: Keys are like "maxW", "maxH", "minW", "minH"
2321       * @return    array
2322       * @access private
2323       * @see imageMagickConvert()
2324       */
2325  	function getImageScale($info,$w,$h,$options) {
2326          if (strstr($w.$h, 'm')) {$max=1;} else {$max=0;}
2327  
2328          if (strstr($w.$h, 'c')) {
2329              $out['cropH'] = intval(substr(strstr($w, 'c'), 1));
2330              $out['cropV'] = intval(substr(strstr($h, 'c'), 1));
2331              $crs = true;
2332          } else {
2333              $crs = false;
2334          }
2335          $out['crs'] = $crs;
2336  
2337          $w=intval($w);
2338          $h=intval($h);
2339              // if there are max-values...
2340          if ($options['maxW'])    {
2341              if ($w) {    // if width is given...
2342                  if ($w>$options['maxW']) {
2343                      $w=$options['maxW'];
2344                      $max=1;    // height should follow
2345                  }
2346              } else {
2347                  if ($info[0]>$options['maxW']) {
2348                      $w=$options['maxW'];
2349                      $max=1; // height should follow
2350                  }
2351              }
2352          }
2353          if ($options['maxH'])    {
2354              if ($h) {    // if height is given...
2355                  if ($h>$options['maxH']) {
2356                      $h=$options['maxH'];
2357                      $max=1;    // height should follow
2358                  }
2359              } else {
2360                  if ($info[1]>$options['maxH']) {    // Changed [0] to [1] 290801
2361                      $h=$options['maxH'];
2362                      $max=1; // height should follow
2363                  }
2364              }
2365          }
2366          $out['origW']=$w;
2367          $out['origH']=$h;
2368          $out['max'] = $max;
2369  
2370          if (!$this->mayScaleUp) {
2371              if ($w>$info[0]){$w=$info[0];}
2372              if ($h>$info[1]){$h=$info[1];}
2373          }
2374          if ($w || $h)    {    // if scaling should be performed
2375              if ($w && !$h)    {
2376                  $info[1] = ceil($info[1]*($w/$info[0]));
2377                  $info[0] = $w;
2378              }
2379              if (!$w && $h)    {
2380                  $info[0] = ceil($info[0]*($h/$info[1]));
2381                  $info[1] = $h;
2382              }
2383              if ($w && $h)    {
2384                  if ($max)    {
2385                      $ratio = $info[0]/$info[1];
2386                      if ($h*$ratio > $w) {
2387                          $h = round($w/$ratio);
2388                      } else {
2389                          $w = round($h*$ratio);
2390                      }
2391                  }
2392                  if ($crs)    {
2393                      $ratio = $info[0] / $info[1];
2394                      if ($h * $ratio < $w) {
2395                          $h = round($w / $ratio);
2396                      } else {
2397                          $w = round($h * $ratio);
2398                      }
2399                  }
2400                  $info[0] = $w;
2401                  $info[1] = $h;
2402              }
2403          }
2404          $out[0]=$info[0];
2405          $out[1]=$info[1];
2406              // Set minimum-measures!
2407          if ($options['minW'] && $out[0]<$options['minW'])    {
2408              if (($max || $crs) && $out[0])    {
2409                  $out[1]= round($out[1]*$options['minW']/$out[0]);
2410              }
2411              $out[0]=$options['minW'];
2412          }
2413          if ($options['minH'] && $out[1]<$options['minH'])    {
2414              if (($max || $crs) && $out[1])    {
2415                  $out[0]= round($out[0]*$options['minH']/$out[1]);
2416              }
2417              $out[1]=$options['minH'];
2418          }
2419  
2420          return $out;
2421      }
2422  
2423      /**
2424       * Used to check if a certain process of scaling an image is already being carried out (can be logged in the SQL database)
2425       *
2426       * @param    string        Output imagefile
2427       * @param    string        Original basis file
2428       * @return    boolean        Returns true if the file is already being made; thus "true" means "Don't render the image again"
2429       * @access private
2430       */
2431  	function file_exists_typo3temp_file($output,$orig='')    {
2432          if ($this->enable_typo3temp_db_tracking)    {
2433              if (@file_exists($output))    {    // If file exists, then we return immediately
2434                  return 1;
2435              } else {    // If not, we look up in the cache_typo3temp_log table to see if there is a image being rendered right now.
2436                  $md5Hash=md5($output);
2437                  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('md5hash', 'cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log').' AND tstamp>'.(time()-30));
2438                  if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))    {    // If there was a record, the image is being generated by another proces (we assume)
2439                      if (is_object($GLOBALS['TSFE']))    $GLOBALS['TSFE']->set_no_cache();    // ...so we set no_cache, because we dont want this page (which will NOT display an image...!) to be cached! (Only a page with the correct image on...)
2440                      if (is_object($GLOBALS['TT']))    $GLOBALS['TT']->setTSlogMessage('typo3temp_log: Assume this file is being rendered now: '.$output);
2441                      return 2;    // Return 'success - 2'
2442                  } else {        // If the current time is more than 30 seconds since this record was written, we clear the record, write a new and render the image.
2443  
2444                      $insertFields = array(
2445                          'md5hash' => $md5Hash,
2446                          'tstamp' => time(),
2447                          'filename' => $output,
2448                          'orig_filename' => $orig
2449                      );
2450                      $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log'));
2451                      $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_typo3temp_log', $insertFields);
2452  
2453                      if (is_object($GLOBALS['TT']))    $GLOBALS['TT']->setTSlogMessage('typo3temp_log: The row did not exist, so a new is written and file is being processed: '.$output);
2454                      return 0;
2455                  }
2456              }
2457          } else {
2458              return @file_exists($output);
2459          }
2460      }
2461  
2462  
2463  
2464  
2465  
2466  
2467  
2468  
2469  
2470  
2471  
2472  
2473  
2474  
2475  
2476  
2477  
2478  
2479      /***********************************
2480       *
2481       * ImageMagick API functions
2482       *
2483       ***********************************/
2484  
2485      /**
2486       * Returns an array where [0]/[1] is w/h, [2] is extension and [3] is the filename.
2487       * Using ImageMagick
2488       *
2489       * @param    string        The relative (to PATH_site) image filepath
2490       * @return    array
2491       */
2492  	function imageMagickIdentify($imagefile)    {
2493          if (!$this->NO_IMAGE_MAGICK)    {
2494              $frame = $this->noFramePrepended?'':'[0]';
2495              $cmd = t3lib_div::imageMagickCommand('identify', $this->wrapFileName($imagefile).$frame);
2496              $returnVal = array();
2497              exec($cmd, $returnVal);
2498              $splitstring=$returnVal[0];
2499              $this->IM_commands[] = Array ('identify',$cmd,$returnVal[0]);
2500              if ($splitstring)    {
2501                  ereg('([^\.]*)$',$imagefile,$reg);
2502                  $splitinfo = explode(' ', $splitstring);
2503                  while (list($key,$val) = each($splitinfo))    {
2504                      $temp = '';
2505                      if ($val) {$temp = explode('x', $val);}
2506                      if (intval($temp[0]) && intval($temp[1]))    {
2507                          $dim=$temp;
2508                          break;
2509                      }
2510                  }
2511                  if ($dim[0] && $dim[1])    {
2512                      return Array($dim[0], $dim[1], strtolower($reg[0]), $imagefile);
2513                  }
2514              }
2515          }
2516      }
2517  
2518      /**
2519       * Executes a ImageMagick "convert" on two filenames, $input and $output using $params before them.
2520       * Can be used for many things, mostly scaling and effects.
2521       *
2522       * @param    string        The relative (to PATH_site) image filepath, input file (read from)
2523       * @param    string        The relative (to PATH_site) image filepath, output filename (written to)
2524       * @param    string        ImageMagick parameters
2525       * @return    string        The result of a call to PHP function "exec()"
2526       */
2527  	function imageMagickExec($input,$output,$params)    {
2528          if (!$this->NO_IMAGE_MAGICK)    {
2529              $cmd = t3lib_div::imageMagickCommand('convert', $params.' '.$this->wrapFileName($input).' '.$this->wrapFileName($output));
2530              $this->IM_commands[] = array($output,$cmd);
2531  
2532              $ret = exec($cmd);
2533              t3lib_div::fixPermissions($this->wrapFileName($output));    // Change the permissions of the file
2534  
2535              return $ret;
2536          }
2537      }
2538  
2539      /**
2540       * Executes a ImageMagick "combine" (or composite in newer times) on four filenames - $input, $overlay and $mask as input files and $output as the output filename (written to)
2541       * Can be used for many things, mostly scaling and effects.
2542       *
2543       * @param    string        The relative (to PATH_site) image filepath, bottom file
2544       * @param    string        The relative (to PATH_site) image filepath, overlay file (top)
2545       * @param    string        The relative (to PATH_site) image filepath, the mask file (grayscale)
2546       * @param    string        The relative (to PATH_site) image filepath, output filename (written to)
2547       * @param    [type]        $handleNegation: ...
2548       * @return    void
2549       */
2550  	function combineExec($input,$overlay,$mask,$output, $handleNegation = false)    {
2551          if (!$this->NO_IMAGE_MAGICK)    {
2552              $params = '-colorspace GRAY +matte';
2553              if ($handleNegation)    {
2554                  if ($this->maskNegate)    {
2555                      $params .= ' '.$this->maskNegate;
2556                  }
2557              }
2558              $theMask = $this->randomName().'.'.$this->gifExtension;
2559              $this->imageMagickExec($mask, $theMask, $params);
2560              $cmd = t3lib_div::imageMagickCommand('combine', '-compose over +matte '.$this->wrapFileName($input).' '.$this->wrapFileName($overlay).' '.$this->wrapFileName($theMask).' '.$this->wrapFileName($output));        // +matte = no alpha layer in output
2561              $this->IM_commands[] = Array ($output,$cmd);
2562  
2563              $ret = exec($cmd);
2564              t3lib_div::fixPermissions($this->wrapFileName($output));    // Change the permissions of the file
2565  
2566              if (is_file($theMask))    {
2567                  @unlink($theMask);
2568              }
2569  
2570              return $ret;
2571          }
2572      }
2573  
2574      /**
2575       * Wrapping the input filename in double-quotes
2576       *
2577       * @param    string        Input filename
2578       * @return    string        The output wrapped in "" (if there are spaces in the filepath)
2579       * @access private
2580       */
2581  	function wrapFileName($inputName)    {
2582          if (strstr($inputName,' '))    {
2583              $inputName='"'.$inputName.'"';
2584          }
2585          return $inputName;
2586      }
2587  
2588  
2589  
2590  
2591  
2592  
2593  
2594  
2595  
2596  
2597  
2598  
2599  
2600  
2601  
2602  
2603  
2604  
2605  
2606  
2607  
2608  
2609  
2610      /***********************************
2611       *
2612       * Various IO functions
2613       *
2614       ***********************************/
2615  
2616      /**
2617       * Returns true if the input file existed
2618       *
2619       * @param    string        Input file to check
2620       * @return    string        Returns the filename if the file existed, otherwise empty.
2621       */
2622  	function checkFile($file)    {
2623          if (@is_file($file))    {
2624              return $file;
2625          } else {
2626              return '';
2627          }
2628      }
2629  
2630      /**
2631       * Creates subdirectory in typo3temp/ if not already found.
2632       *
2633       * @param    string        Name of sub directory
2634       * @return    boolean        Result of t3lib_div::mkdir(), true if it went well.
2635       */
2636  	function createTempSubDir($dirName)    {
2637  
2638              // Checking if the this->tempPath is already prefixed with PATH_site and if not, prefix it with that constant.
2639          if (t3lib_div::isFirstPartOfStr($this->tempPath,PATH_site))    {
2640              $tmpPath = $this->tempPath;
2641          } else {
2642              $tmpPath = PATH_site.$this->tempPath;
2643          }
2644  
2645              // Making the temporary filename:
2646          if (!@is_dir($tmpPath.$dirName))     {
2647              return t3lib_div::mkdir($tmpPath.$dirName);
2648          }
2649      }
2650  
2651      /**
2652       * Applies an ImageMagick parameter to a GDlib image pointer resource by writing the resource to file, performing an IM operation upon it and reading back the result into the ImagePointer.
2653       *
2654       * @param    pointer        The image pointer (reference)
2655       * @param    string        The ImageMagick parameters. Like effects, scaling etc.
2656       * @return    void
2657       */
2658  	function applyImageMagickToPHPGif(&$im, $command)    {
2659          $tmpStr = $this->randomName();
2660          $theFile = $tmpStr.'.'.$this->gifExtension;
2661          $this->ImageWrite($im, $theFile);
2662          $this->imageMagickExec($theFile,$theFile,$command);
2663          $tmpImg = $this->imageCreateFromFile($theFile);
2664          if ($tmpImg)    {
2665              ImageDestroy($im);
2666              $im = $tmpImg;
2667              $this->w = imagesx($im);
2668              $this->h = imagesy($im);
2669          }
2670          if (!$this->dontUnlinkTempFiles)    {
2671              unlink($theFile);
2672          }
2673      }
2674  
2675      /**
2676       * Returns an image extension for an output image based on the number of pixels of the output and the file extension of the original file.
2677       * For example: If the number of pixels exceeds $this->pixelLimitGif (normally 10000) then it will be a "jpg" string in return.
2678       *
2679       * @param    string        The file extension, lowercase.
2680       * @param    integer        The width of the output image.
2681       * @param    integer        The height of the output image.
2682       * @return    string        The filename, either "jpg" or "gif"/"png" (whatever $this->gifExtension is set to.)
2683       */
2684  	function gif_or_jpg($type,$w,$h)    {
2685          if ($type=='ai' || $w*$h < $this->pixelLimitGif)    {
2686              return $this->gifExtension;
2687          } else {
2688              return 'jpg';
2689          }
2690      }
2691  
2692      /**
2693       * Writing the internal image pointer, $this->im, to file based on the extension of the input filename
2694       * Used in GIFBUILDER
2695       * Uses $this->setup['reduceColors'] for gif/png images and $this->setup['quality'] for jpg images to reduce size/quality if needed.
2696       *
2697       * @param    string        The filename to write to.
2698       * @return    string        Returns input filename
2699       * @see tslib_gifBuilder::gifBuild()
2700       */
2701  	function output($file)    {
2702          if ($file)    {
2703              $reg = array();
2704              ereg('([^\.]*)$',$file,$reg);
2705              $ext=strtolower($reg[0]);
2706              switch($ext)    {
2707                  case 'gif':
2708                  case 'png':
2709                      if ($this->ImageWrite($this->im, $file))    {
2710                              // ImageMagick operations
2711                          if ($this->setup['reduceColors'] || (!$this->png_truecolor && $this->truecolor))    {
2712                              $reduced = $this->IMreduceColors($file, t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256));
2713                              if ($reduced)    {
2714                                  @copy($reduced, $file);
2715                                  @unlink($reduced);
2716                              }
2717                          }
2718                          t3lib_div::gif_compress($file, 'IM');        // Compress with IM! (adds extra compression, LZW from ImageMagick)     (Workaround for the absence of lzw-compression in GD)
2719                      }
2720                  break;
2721                  case 'jpg':
2722                  case 'jpeg':
2723                      $quality = 0;    // Use the default
2724                      if($this->setup['quality'])    {
2725                          $quality = t3lib_div::intInRange($this->setup['quality'],10,100);
2726                      }
2727                      if ($this->ImageWrite($this->im, $file, $quality));
2728                  break;
2729              }
2730              $GLOBALS['TEMP_IMAGES_ON_PAGE'][]=$file;
2731          }
2732          return $file;
2733      }
2734  
2735      /**
2736       * Destroy internal image pointer, $this->im
2737       *
2738       * @return    void
2739       * @see tslib_gifBuilder::gifBuild()
2740       */
2741  	function destroy()    {
2742          ImageDestroy($this->im);
2743      }
2744  
2745      /**
2746       * Returns Image Tag for input image information array.
2747       *
2748       * @param    array        Image information array, key 0/1 is width/height and key 3 is the src value
2749       * @return    string        Image tag for the input image information array.
2750       */
2751  	function imgTag ($imgInfo) {
2752          return '<img src="'.$imgInfo[3].'" width="'.$imgInfo[0].'" height="'.$imgInfo[1].'" border="0" alt="" />';
2753      }
2754  
2755      /**
2756       * Writes the input GDlib image pointer to file
2757       *
2758       * @param    pointer        The GDlib image resource pointer
2759       * @param    string        The filename to write to
2760       * @param    integer        The image quality (for JPEGs)
2761       * @return    mixed        The output of either imageGif, imagePng or imageJpeg based on the filename to write
2762       * @see maskImageOntoImage(), scale(), output()
2763       */
2764  	function ImageWrite($destImg, $theImage, $quality=0)    {
2765          imageinterlace ($destImg,0);
2766           $ext = strtolower(substr($theImage, strrpos($theImage, '.')+1));
2767           switch ($ext)    {
2768               case 'jpg':
2769               case 'jpeg':
2770                   if (function_exists('imageJpeg'))    {
2771                      if ($quality == 0)    {
2772                          $quality = $this->jpegQuality;
2773                      }
2774                       return imageJpeg($destImg, $theImage, $quality);
2775                   }
2776               break;
2777               case 'gif':
2778                   if (function_exists('imageGif'))    {
2779                      if ($this->truecolor)    {
2780                          imagetruecolortopalette($destImg, true, 256);
2781                      }
2782                       return imageGif($destImg, $theImage);
2783                   }
2784               break;
2785               case 'png':
2786                   if (function_exists('imagePng'))    {
2787                       return ImagePng($destImg, $theImage);
2788                   }
2789               break;
2790           }
2791           return false;        // Extension invalid or write-function does not exist
2792       }
2793  
2794  
2795  
2796       /**
2797   * Writes the input GDlib image pointer to file. Now just a wrapper to ImageWrite.
2798   *
2799   * @param    pointer        The GDlib image resource pointer
2800   * @param    string        The filename to write to
2801   * @return    mixed        The output of either imageGif, imagePng or imageJpeg based on the filename to write
2802   * @see imageWrite()
2803   * @deprecated
2804   */
2805   	function imageGif($destImg, $theImage)    {
2806           return $this->imageWrite($destImg, $theImage);
2807      }
2808  
2809      /**
2810       * This function has been renamed and only exists for providing backwards compatibility.
2811       * Please use $this->imageCreateFromFile() instead.
2812       *
2813       * @param    string        Image filename
2814       * @return    pointer        Image Resource pointer
2815       * @deprecated
2816       */
2817  	function imageCreateFromGif($sourceImg)    {
2818          return $this->imageCreateFromFile($sourceImg);
2819      }
2820  
2821      /**
2822       * Creates a new GDlib image resource based on the input image filename.
2823       * If it fails creating a image from the input file a blank gray image with the dimensions of the input image will be created instead.
2824       *
2825       * @param    string        Image filename
2826       * @return    pointer        Image Resource pointer
2827       */
2828  	function imageCreateFromFile($sourceImg)    {
2829          $imgInf = pathinfo($sourceImg);
2830          $ext = strtolower($imgInf['extension']);
2831  
2832          switch ($ext)    {
2833              case 'gif':
2834                  if (function_exists('imagecreatefromgif'))    {
2835                      return imageCreateFromGif($sourceImg);
2836                  }
2837              break;
2838              case 'png':
2839                  if (function_exists('imagecreatefrompng'))    {
2840                      return imageCreateFromPng($sourceImg);
2841                  }
2842              break;
2843              case 'jpg':
2844              case 'jpeg':
2845                  if (function_exists('imagecreatefromjpeg'))    {
2846                      return imageCreateFromJpeg($sourceImg);
2847                  }
2848              break;
2849          }
2850  
2851          // If non of the above:
2852          $i = @getimagesize($sourceImg);
2853          $im = $this->imagecreate($i[0],$i[1]);
2854          $Bcolor = ImageColorAllocate($im, 128,128,128);
2855          ImageFilledRectangle($im, 0, 0, $i[0], $i[1], $Bcolor);
2856          return $im;
2857      }
2858  
2859  
2860      /**
2861       * Creates a new GD image resource. Wrapper for imagecreate(truecolor) depended if GD2 is used.
2862       *
2863       * @param    integer        Width of image
2864       * @param    integer        Height of image
2865       * @return    pointer        Image Resource pointer
2866       */
2867  	function imagecreate($w, $h)    {
2868          if($this->truecolor && function_exists('imagecreatetruecolor'))    {
2869              return imagecreatetruecolor($w, $h);
2870          } else    {
2871              return imagecreate($w, $h);
2872          }
2873  
2874      }
2875  
2876      /**
2877       * Returns the HEX color value for an RGB color array
2878       *
2879       * @param    array        RGB color array
2880       * @return    string        HEX color value
2881       */
2882  	function hexColor($col)    {
2883          $r = dechex($col[0]);
2884          if (strlen($r)<2)    { $r = '0'.$r; }
2885          $g = dechex($col[1]);
2886          if (strlen($g)<2)    { $g = '0'.$g; }
2887          $b = dechex($col[2]);
2888          if (strlen($b)<2)    { $b = '0'.$b; }
2889          return '#'.$r.$g.$b;
2890      }
2891  
2892      /**
2893       * Unifies all colors given in the colArr color array to the first color in the array.
2894       *
2895       * @param    pointer        Image resource
2896       * @param    array        Array containing RGB color arrays
2897       * @param    [type]        $closest: ...
2898       * @return    integer        The index of the unified color
2899       */
2900  	function unifyColors(&$img, $colArr, $closest = false)    {
2901          $retCol = -1;
2902          if (is_array($colArr) && count($colArr) && function_exists('imagepng') && function_exists('imagecreatefrompng'))    {
2903              $firstCol = array_shift($colArr);
2904              $firstColArr = $this->convertColor($firstCol);
2905              if (count($colArr)>1)    {
2906                  $origName = $preName = $this->randomName().'.png';
2907                  $postName = $this->randomName().'.png';
2908                  $this->imageWrite($img, $preName);
2909                  $firstCol = $this->hexColor($firstColArr);
2910                  foreach ($colArr as $transparentColor)    {
2911                      $transparentColor = $this->convertColor($transparentColor);
2912                      $transparentColor = $this->hexColor($transparentColor);
2913                      $cmd = '-fill "'.$firstCol.'" -opaque "'.$transparentColor.'"';
2914                      $this->imageMagickExec($preName, $postName, $cmd);
2915                      $preName = $postName;
2916                  }
2917                  $this->imageMagickExec($postName, $origName, '');
2918                  if (@is_file($origName))    {
2919                      $tmpImg = $this->imageCreateFromFile($origName);
2920                  }
2921              } else    {
2922                  $tmpImg = $img;
2923              }
2924              if ($tmpImg)    {
2925                  $img = $tmpImg;
2926                  if ($closest)    {
2927                      $retCol = ImageColorClosest ($img, $firstColArr[0], $firstColArr[1], $firstColArr[2]);
2928                  } else    {
2929                      $retCol = ImageColorExact ($img, $firstColArr[0], $firstColArr[1], $firstColArr[2]);
2930                  }
2931              }
2932                  // unlink files from process
2933              if (!$this->dontUnlinkTempFiles)    {
2934                  if ($origName)    {
2935                      @unlink($origName);
2936                  }
2937                  if ($postName)    {
2938                      @unlink($postName);
2939                  }
2940              }
2941          }
2942          return $retCol;
2943      }
2944  
2945  
2946  }
2947  
2948  if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php'])    {
2949      include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']);
2950  }
2951  ?>


Généré le : Sun Nov 25 17:13:16 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics