Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2007 Kasper Skaarhoj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00155 class t3lib_stdGraphic { 00156 00157 // Internal configuration, set in init() 00158 var $combineScript = 'combine'; // The ImageMagick filename used for combining two images. This name changed during the versions. 00159 var $noFramePrepended=0; // If set, there is no frame pointer prepended to the filenames. 00160 var $GD2=0; // Set, if the GDlib used is version 2. 00161 var $imagecopyresized_fix=0; // If set, imagecopyresized will not be called directly. For GD2 (some PHP installs?) 00162 var $gifExtension = 'gif'; // This should be changed to 'png' if you want this class to read/make PNG-files instead! 00163 var $gdlibExtensions = ''; // File formats supported by gdlib. This variable get's filled in "init" method 00164 var $truecolor = true; // Internal variable which get's used to determine wheter GDlib should use function truecolor pendants 00165 var $png_truecolor = false; // Set to true if generated png's should be truecolor by default 00166 var $truecolorColors = 0xffffff; // 16777216 Colors is the maximum value for PNG, JPEG truecolor images (24-bit, 8-bit / Channel) 00167 var $TTFLocaleConv = ''; // Used to recode input to TTF-functions for other charsets. 00168 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. 00169 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! 00170 var $webImageExt = 'gif,jpg,jpeg,png'; // Commalist of web image extensions (can be shown by a webbrowser) 00171 var $maskNegate = ''; // Will be ' -negate' if ImageMagick ver 5.2+. See init(); 00172 var $NO_IM_EFFECTS = ''; 00173 var $cmds = Array ( 00174 'jpg' => '', 00175 'jpeg' => '', 00176 'gif' => '-colors 64', 00177 'png' => '-colors 64' 00178 ); 00179 var $NO_IMAGE_MAGICK = ''; 00180 var $V5_EFFECTS = 0; 00181 var $im_version_4 = 0; 00182 var $mayScaleUp = 1; 00183 00184 // Variables for testing, alternative usage etc. 00185 var $filenamePrefix=''; // Filename prefix for images scaled in imageMagickConvert() 00186 var $imageMagickConvert_forceFileNameBody=''; // Forcing the output filename of imageMagickConvert() to this value. However after calling imageMagickConvert() it will be set blank again. 00187 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. 00188 var $dontCompress=0; // Prevents imageMagickConvert() from compressing the gif-files with t3lib_div::gif_compress() 00189 var $dontUnlinkTempFiles=0; // For debugging ONLY! 00190 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... 00191 00192 // Internal: 00193 var $IM_commands = Array(); // All ImageMagick commands executed is stored in this array for tracking. Used by the Install Tools Image section 00194 var $workArea = Array(); 00195 00196 // Constants: 00197 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. 00198 var $absPrefix = ''; // Prefix for relative paths. Used in "show_item.php" script. Is prefixed the output file name IN imageMagickConvert() 00199 var $scalecmd = '-geometry'; // ImageMagick scaling command; "-geometry" eller "-sample". Used in makeText() and imageMagickConvert() 00200 var $im5fx_blurSteps='1x2,2x2,3x2,4x3,5x3,5x4,6x4,7x5,8x5,9x5'; // Used by v5_blur() to simulate 10 continuous steps of blurring 00201 var $im5fx_sharpenSteps='1x2,2x2,3x2,2x3,3x3,4x3,3x4,4x4,4x5,5x5'; // Used by v5_sharpen() to simulate 10 continuous steps of sharpening. 00202 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 00203 var $colMap = Array ( // Array mapping HTML color names to RGB values. 00204 'aqua' => Array(0,255,255), 00205 'black' => Array(0,0,0), 00206 'blue' => Array(0,0,255), 00207 'fuchsia' => Array(255,0,255), 00208 'gray' => Array(128,128,128), 00209 'green' => Array(0,128,0), 00210 'lime' => Array(0,255,0), 00211 'maroon' => Array(128,0,0), 00212 'navy' => Array(0,0,128), 00213 'olive' => Array(128,128,0), 00214 'purple' => Array(128,0,128), 00215 'red' => Array(255,0,0), 00216 'silver' => Array(192,192,192), 00217 'teal' => Array(0,128,128), 00218 'yellow' => Array(255,255,0), 00219 'white' => Array(255,255,255) 00220 ); 00221 00222 // Charset conversion object: 00223 var $csConvObj; 00224 var $nativeCharset=''; // Is set to the native character set of the input strings. 00225 00226 00227 00228 00229 00236 function init() { 00237 $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX']; 00238 00239 if (function_exists('imagecreatefromjpeg')&&function_exists('imagejpeg')) { 00240 $this->gdlibExtensions .= ',jpg,jpeg'; 00241 } 00242 if (function_exists('imagecreatefrompng')&&function_exists('imagepng')) { 00243 $this->gdlibExtensions .= ',png'; 00244 } 00245 if (function_exists('imagecreatefromgif')&&function_exists('imagegif')) { 00246 $this->gdlibExtensions .= ',gif'; 00247 } 00248 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['png_truecolor']) { 00249 $this->png_truecolor = true; 00250 } 00251 if (!$gfxConf['gdlib_2'] || !function_exists('imagecreatetruecolor')) { 00252 $this->truecolor = false; 00253 } 00254 if (!$gfxConf['im_version_5']) { 00255 $this->im_version_4 = true; 00256 } 00257 00258 // When GIFBUILDER gets used in truecolor mode (GD2 required) 00259 if ($this->truecolor) { 00260 if ($this->png_truecolor) { 00261 $this->cmds['png'] = ''; // No colors parameter if we generate truecolor images. 00262 } 00263 $this->cmds['gif'] = ''; // No colors parameter if we generate truecolor images. 00264 } 00265 00266 // Setting default JPG parameters: 00267 $this->jpegQuality = t3lib_div::intInRange($gfxConf['jpg_quality'], 10, 100, 75); 00268 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -sharpen 50 -quality '.$this->jpegQuality; 00269 00270 if ($gfxConf['im_combine_filename']) $this->combineScript=$gfxConf['im_combine_filename']; 00271 if ($gfxConf['im_noFramePrepended']) $this->noFramePrepended=1; 00272 00273 if ($gfxConf['gdlib_2']) { 00274 $this->GD2 = 1; 00275 $this->imagecopyresized_fix = $gfxConf['gdlib_2']==='no_imagecopyresized_fix' ? 0 : 1; 00276 } 00277 if ($gfxConf['gdlib_png']) { 00278 $this->gifExtension='png'; 00279 } 00280 if ($gfxConf['TTFLocaleConv']) { 00281 $this->TTFLocaleConv = $gfxConf['TTFLocaleConv']; 00282 } 00283 if ($gfxConf['enable_typo3temp_db_tracking']) { 00284 $this->enable_typo3temp_db_tracking = $gfxConf['enable_typo3temp_db_tracking']; 00285 } 00286 00287 $this->imageFileExt = $gfxConf['imagefile_ext']; 00288 00289 // This should be set if ImageMagick ver. 5+ is used. 00290 if ($gfxConf['im_negate_mask']) { 00291 // Boolean. Indicates if the mask images should be inverted first. 00292 // This depends of the ImageMagick version. Below ver. 5.1 this should be false. 00293 // Above ImageMagick version 5.2+ it should be true. 00294 // Just set the flag if the masks works opposite the intension! 00295 $this->maskNegate = ' -negate'; 00296 } 00297 if ($gfxConf['im_no_effects']) { 00298 // Boolean. This is necessary if using ImageMagick 5+. 00299 // Approved version for using effects is version 4.2.9. 00300 // Effects in Imagemagick 5+ tends to render very slowly!! 00301 // - therefore must be disabled in order not to perform sharpen, blurring and such. 00302 $this->NO_IM_EFFECTS = 1; 00303 00304 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.$this->jpegQuality; 00305 } 00306 // ... but if 'im_v5effects' is set, don't care about 'im_no_effects' 00307 if ($gfxConf['im_v5effects']) { 00308 $this->NO_IM_EFFECTS = 0; 00309 $this->V5_EFFECTS = 1; 00310 00311 if ($gfxConf['im_v5effects']>0) { 00312 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['jpg_quality']).$this->v5_sharpen(10); 00313 } 00314 } 00315 00316 if (!$gfxConf['im']) { 00317 $this->NO_IMAGE_MAGICK = 1; 00318 } 00319 // Secures that images are not scaled up. 00320 if ($gfxConf['im_noScaleUp']) { 00321 $this->mayScaleUp=0; 00322 } 00323 00324 if (TYPO3_MODE=='FE') { 00325 $this->csConvObj = &$GLOBALS['TSFE']->csConvObj; 00326 } elseif(is_object($GLOBALS['LANG'])) { // BE assumed: 00327 $this->csConvObj = &$GLOBALS['LANG']->csConvObj; 00328 } else { // The object may not exist yet, so we need to create it now. Happens in the Install Tool for example. 00329 $this->csConvObj = t3lib_div::makeInstance('t3lib_cs'); 00330 } 00331 $this->nativeCharset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']; 00332 } 00333 00334 00335 00336 00337 00338 00339 00340 00341 00342 00343 00344 00345 00346 00347 00348 00349 /************************************************* 00350 * 00351 * Layering images / "IMAGE" GIFBUILDER object 00352 * 00353 *************************************************/ 00354 00366 function maskImageOntoImage(&$im,$conf,$workArea) { 00367 if ($conf['file'] && $conf['mask']) { 00368 $imgInf = pathinfo($conf['file']); 00369 $imgExt = strtolower($imgInf['extension']); 00370 if (!t3lib_div::inList($this->gdlibExtensions, $imgExt)) { 00371 $BBimage = $this->imageMagickConvert($conf['file'],$this->gifExtension,'','','','',''); 00372 } else { 00373 $BBimage = $this->getImageDimensions($conf['file']); 00374 } 00375 $maskInf = pathinfo($conf['mask']); 00376 $maskExt = strtolower($maskInf['extension']); 00377 if (!t3lib_div::inList($this->gdlibExtensions, $maskExt)) { 00378 $BBmask = $this->imageMagickConvert($conf['mask'],$this->gifExtension,'','','','',''); 00379 } else { 00380 $BBmask = $this->getImageDimensions($conf['mask']); 00381 } 00382 if ($BBimage && $BBmask) { 00383 $w = imagesx($im); 00384 $h = imagesy($im); 00385 $tmpStr = $this->randomName(); 00386 $theImage = $tmpStr.'_img.'.$this->gifExtension; 00387 $theDest = $tmpStr.'_dest.'.$this->gifExtension; 00388 $theMask = $tmpStr.'_mask.'.$this->gifExtension; 00389 // prepare overlay image 00390 $cpImg = $this->imageCreateFromFile($BBimage[3]); 00391 $destImg = $this->imagecreate($w,$h); 00392 $Bcolor = ImageColorAllocate($destImg, 0,0,0); 00393 ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor); 00394 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea); 00395 $this->ImageWrite($destImg, $theImage); 00396 imageDestroy($cpImg); 00397 imageDestroy($destImg); 00398 // prepare mask image 00399 $cpImg = $this->imageCreateFromFile($BBmask[3]); 00400 $destImg = $this->imagecreate($w,$h); 00401 $Bcolor = ImageColorAllocate($destImg, 0, 0, 0); 00402 ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor); 00403 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea); 00404 $this->ImageWrite($destImg, $theMask); 00405 imageDestroy($cpImg); 00406 imageDestroy($destImg); 00407 // mask the images 00408 $this->ImageWrite($im, $theDest); 00409 00410 $this->combineExec($theDest,$theImage,$theMask,$theDest, true); // Let combineExec handle maskNegation 00411 00412 $backIm = $this->imageCreateFromFile($theDest); // The main image is loaded again... 00413 if ($backIm) { // ... and if nothing went wrong we load it onto the old one. 00414 ImageColorTransparent($backIm,-1); 00415 $im = $backIm; 00416 } 00417 // unlink files from process 00418 if (!$this->dontUnlinkTempFiles) { 00419 unlink($theDest); 00420 unlink($theImage); 00421 unlink($theMask); 00422 } 00423 } 00424 } 00425 } 00426 00436 function copyImageOntoImage(&$im,$conf,$workArea) { 00437 if ($conf['file']) { 00438 if (!t3lib_div::inList($this->gdlibExtensions, $conf['BBOX'][2])) { 00439 $conf['BBOX']=$this->imageMagickConvert($conf['BBOX'][3],$this->gifExtension,'','','','',''); 00440 $conf['file']=$conf['BBOX'][3]; 00441 } 00442 $cpImg = $this->imageCreateFromFile($conf['file']); 00443 $this->copyGifOntoGif($im,$cpImg,$conf,$workArea); 00444 imageDestroy($cpImg); 00445 } 00446 } 00447 00458 function copyGifOntoGif(&$im,$cpImg,$conf,$workArea) { 00459 $cpW = imagesx($cpImg); 00460 $cpH = imagesy($cpImg); 00461 $tile = t3lib_div::intExplode(',',$conf['tile']); 00462 $tile[0] = t3lib_div::intInRange($tile[0],1,20); 00463 $tile[1] = t3lib_div::intInRange($tile[1],1,20); 00464 $cpOff = $this->objPosition($conf,$workArea,Array($cpW*$tile[0],$cpH*$tile[1])); 00465 00466 for ($xt=0;$xt<$tile[0];$xt++) { 00467 $Xstart=$cpOff[0]+$cpW*$xt; 00468 if ($Xstart+$cpW > $workArea[0]) { // if this image is inside of the workArea, then go on 00469 // X: 00470 if ($Xstart < $workArea[0]) { 00471 $cpImgCutX = $workArea[0]-$Xstart; 00472 $Xstart = $workArea[0]; 00473 } else { 00474 $cpImgCutX = 0; 00475 } 00476 $w = $cpW-$cpImgCutX; 00477 if ($Xstart > $workArea[0]+$workArea[2]-$w) { 00478 $w = $workArea[0]+$workArea[2]-$Xstart; 00479 } 00480 if ($Xstart < $workArea[0]+$workArea[2]) { // if this image is inside of the workArea, then go on 00481 // Y: 00482 for ($yt=0;$yt<$tile[1];$yt++) { 00483 $Ystart=$cpOff[1]+$cpH*$yt; 00484 if ($Ystart+$cpH > $workArea[1]) { // if this image is inside of the workArea, then go on 00485 if ($Ystart < $workArea[1]) { 00486 $cpImgCutY = $workArea[1]-$Ystart; 00487 $Ystart = $workArea[1]; 00488 } else { 00489 $cpImgCutY = 0; 00490 } 00491 $h = $cpH-$cpImgCutY; 00492 if ($Ystart > $workArea[1]+$workArea[3]-$h) { 00493 $h = $workArea[1]+$workArea[3]-$Ystart; 00494 } 00495 if ($Ystart < $workArea[1]+$workArea[3]) { // if this image is inside of the workArea, then go on 00496 $this->imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h); 00497 } 00498 } 00499 } // Y: 00500 } 00501 } 00502 } 00503 } 00504 00537 function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h) { 00538 if ($this->imagecopyresized_fix) { 00539 $im_base = $this->imagecreate(imagesx($im), imagesy($im)); // Make true color image 00540 imagecopyresized($im_base, $im, 0,0,0,0, imagesx($im),imagesy($im),imagesx($im),imagesy($im)); // Copy the source image onto that 00541 imagecopyresized($im_base, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h); // Then copy the $cpImg onto that (the actual operation!) 00542 $im = $im_base; // Set pointer 00543 if (!$this->truecolor) { 00544 $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! 00545 } 00546 } else { 00547 imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h); 00548 } 00549 } 00550 00551 00552 00553 00554 00555 00556 00557 00558 00559 00560 00561 00562 00563 00564 00565 00566 00567 00568 00569 00570 00571 00572 /******************************** 00573 * 00574 * Text / "TEXT" GIFBUILDER object 00575 * 00576 ********************************/ 00577 00587 function makeText(&$im,$conf,$workArea) { 00588 // Spacing 00589 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf); 00590 // Position 00591 $txtPos = $this->txtPosition($conf,$workArea,$conf['BBOX']); 00592 $theText = $this->recodeString($conf['text']); 00593 00594 if ($conf['imgMap'] && is_array($conf['imgMap.'])) { 00595 $this->addToMap($this->calcTextCordsForMap($conf['BBOX'][2],$txtPos, $conf['imgMap.']), $conf['imgMap.']); 00596 } 00597 if (!$conf['hideButCreateMap']) { 00598 // Font Color: 00599 $cols=$this->convertColor($conf['fontColor']); 00600 // NiceText is calculated 00601 if (!$conf['niceText']) { 00602 // Font Color is reserved: 00603 if (!$this->truecolor) { 00604 $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256); 00605 $this->reduceColors($im, $reduce-49, $reduce-50); // If "reduce-49" colors (or more) are used reduce them to "reduce-50" 00606 } 00607 $Fcolor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]); 00608 // antiAliasing is setup: 00609 $Fcolor = ($conf['antiAlias']) ? $Fcolor : -$Fcolor; 00610 00611 for ($a=0; $a<$conf['iterations']; $a++) { 00612 if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function: 00613 $this->SpacedImageTTFText($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.']); 00614 } else { 00615 $this->ImageTTFTextWrapper($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.']); 00616 } 00617 } 00618 } else { // NICETEXT:: 00619 // options anti_aliased and iterations is NOT available when doing this!! 00620 $w = imagesx($im); 00621 $h = imagesy($im); 00622 $tmpStr = $this->randomName(); 00623 00624 $fileMenu = $tmpStr.'_menuNT.'.$this->gifExtension; 00625 $fileColor = $tmpStr.'_colorNT.'.$this->gifExtension; 00626 $fileMask = $tmpStr.'_maskNT.'.$this->gifExtension; 00627 // Scalefactor 00628 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5); 00629 $newW = ceil($sF*imagesx($im)); 00630 $newH = ceil($sF*imagesy($im)); 00631 00632 // Make mask 00633 $maskImg = $this->imagecreate($newW, $newH); 00634 $Bcolor = ImageColorAllocate($maskImg, 255,255,255); 00635 ImageFilledRectangle($maskImg, 0, 0, $newW, $newH, $Bcolor); 00636 $Fcolor = ImageColorAllocate($maskImg, 0,0,0); 00637 if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function: 00638 $this->SpacedImageTTFText($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.'],$sF); 00639 } else { 00640 $this->ImageTTFTextWrapper($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'],$sF); 00641 } 00642 $this->ImageWrite($maskImg, $fileMask); 00643 ImageDestroy($maskImg); 00644 00645 // Downscales the mask 00646 if ($this->NO_IM_EFFECTS) { 00647 if ($this->maskNegate) { 00648 $command = trim($this->scalecmd.' '.$w.'x'.$h.'!'); // Negate 2 times makes no negate... 00649 } else { 00650 $command = trim($this->scalecmd.' '.$w.'x'.$h.'! -negate'); 00651 } 00652 } else { 00653 if ($this->maskNegate) { 00654 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after']); 00655 } else { 00656 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after'].' -negate'); 00657 } 00658 if ($conf['niceText.']['sharpen']) { 00659 if ($this->V5_EFFECTS) { 00660 $command.=$this->v5_sharpen($conf['niceText.']['sharpen']); 00661 } else { 00662 $command.=' -sharpen '.t3lib_div::intInRange($conf['niceText.']['sharpen'],1,99); 00663 } 00664 } 00665 } 00666 00667 $this->imageMagickExec($fileMask,$fileMask,$command); 00668 00669 // Make the color-file 00670 $colorImg = $this->imagecreate($w,$h); 00671 $Ccolor = ImageColorAllocate($colorImg, $cols[0],$cols[1],$cols[2]); 00672 ImageFilledRectangle($colorImg, 0, 0, $w, $h, $Ccolor); 00673 $this->ImageWrite($colorImg, $fileColor); 00674 ImageDestroy($colorImg); 00675 00676 // The mask is applied 00677 $this->ImageWrite($im, $fileMenu); // The main pictures is saved temporarily 00678 00679 $this->combineExec($fileMenu,$fileColor,$fileMask, $fileMenu); 00680 00681 $backIm = $this->imageCreateFromFile($fileMenu); // The main image is loaded again... 00682 if ($backIm) { // ... and if nothing went wrong we load it onto the old one. 00683 ImageColorTransparent($backIm,-1); 00684 $im = $backIm; 00685 } 00686 00687 // Deleting temporary files; 00688 if (!$this->dontUnlinkTempFiles) { 00689 unlink($fileMenu); 00690 unlink($fileColor); 00691 unlink($fileMask); 00692 } 00693 } 00694 } 00695 } 00696 00707 function txtPosition($conf,$workArea,$BB) { 00708 $bbox = $BB[2]; 00709 $angle=intval($conf['angle'])/180*pi(); 00710 $conf['angle']=0; 00711 $straightBB = $this->calcBBox($conf); 00712 00713 // offset, align, valign, workarea 00714 $result=Array(); // [0]=x, [1]=y, [2]=w, [3]=h 00715 $result[2] = $BB[0]; 00716 $result[3] = $BB[1]; 00717 $w=$workArea[2]; 00718 $h=$workArea[3]; 00719 00720 switch($conf['align']) { 00721 case 'right': 00722 case 'center': 00723 $factor=abs(cos($angle)); 00724 $sign=(cos($angle)<0)?-1:1; 00725 $len1 = $sign*$factor*$straightBB[0]; 00726 $len2= $sign*$BB[0]; 00727 $result[0] = $w-ceil($len2*$factor+(1-$factor)*$len1); 00728 00729 $factor=abs(sin($angle)); 00730 $sign=(sin($angle)<0)?-1:1; 00731 $len1= $sign*$factor*$straightBB[0]; 00732 $len2= $sign*$BB[1]; 00733 $result[1]=ceil($len2*$factor+(1-$factor)*$len1); 00734 break; 00735 } 00736 switch($conf['align']) { 00737 case 'right': 00738 break; 00739 case 'center': 00740 $result[0] = round(($result[0])/2); 00741 $result[1] = round(($result[1])/2); 00742 break; 00743 default: 00744 $result[0]=0; 00745 $result[1]=0; 00746 break; 00747 } 00748 $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset'])); 00749 $result = $this->applyOffset($result,$workArea); 00750 return $result; 00751 } 00752 00761 function calcBBox($conf) { 00762 $sF = $this->getTextScalFactor($conf); 00763 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf, $sF); 00764 $theText = $this->recodeString($conf['text']); 00765 00766 $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $theText, $conf['splitRendering.'],$sF); 00767 $theBBoxInfo = $charInf; 00768 if ($conf['angle']) { 00769 $xArr = Array($charInf[0],$charInf[2],$charInf[4],$charInf[6]); 00770 $yArr = Array($charInf[1],$charInf[3],$charInf[5],$charInf[7]); 00771 $x=max($xArr)-min($xArr); 00772 $y=max($yArr)-min($yArr); 00773 } else { 00774 $x = ($charInf[2]-$charInf[0]); 00775 $y = ($charInf[1]-$charInf[7]); 00776 } 00777 if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function: 00778 $x=0; 00779 if (!$spacing && $wordSpacing) { 00780 $bits = explode(' ',$theText); 00781 while(list(,$word)=each($bits)) { 00782 $word.=' '; 00783 $wordInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $word, $conf['splitRendering.'],$sF); 00784 $wordW = ($wordInf[2]-$wordInf[0]); 00785 $x+=$wordW+$wordSpacing; 00786 } 00787 } else { 00788 $utf8Chars = $this->singleChars($theText); 00789 // For each UTF-8 char, do: 00790 foreach($utf8Chars as $char) { 00791 $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $char, $conf['splitRendering.'],$sF); 00792 $charW = ($charInf[2]-$charInf[0]); 00793 $x+=$charW+(($char==' ')?$wordSpacing:$spacing); 00794 } 00795 } 00796 } 00797 00798 if ($sF>1) { 00799 $x = ceil($x/$sF); 00800 $y = ceil($y/$sF); 00801 if (is_array($theBBoxInfo)) { 00802 reset($theBBoxInfo); 00803 while(list($key,$val)=each($theBBoxInfo)) { 00804 $theBBoxInfo[$key]=ceil($theBBoxInfo[$key]/$sF); 00805 } 00806 } 00807 } 00808 return array($x,$y,$theBBoxInfo); 00809 } 00810 00820 function addToMap($cords,$conf) { 00821 $JS = $conf['noBlur'] ? '' : ' onfocus="blurLink(this);"'; 00822 00823 $this->map.='<area'. 00824 ' shape="poly"'. 00825 ' coords="'.implode(',',$cords).'"'. 00826 ' href="'.htmlspecialchars($conf['url']).'"'. 00827 ($conf['target'] ? ' target="'.htmlspecialchars($conf['target']).'"' : ''). 00828 $JS. 00829 (strlen($conf['titleText']) ? ' title="'.htmlspecialchars($conf['titleText']).'"' : ''). 00830 ' alt="'.htmlspecialchars($conf['altText']).'" />'; 00831 } 00832 00843 function calcTextCordsForMap($cords,$offset, $conf) { 00844 $pars = t3lib_div::intExplode(',',$conf['explode'].','); 00845 00846 $newCords[0] = $cords[0]+$offset[0]-$pars[0]; 00847 $newCords[1] = $cords[1]+$offset[1]+$pars[1]; 00848 $newCords[2] = $cords[2]+$offset[0]+$pars[0]; 00849 $newCords[3] = $cords[3]+$offset[1]+$pars[1]; 00850 $newCords[4] = $cords[4]+$offset[0]+$pars[0]; 00851 $newCords[5] = $cords[5]+$offset[1]-$pars[1]; 00852 $newCords[6] = $cords[6]+$offset[0]-$pars[0]; 00853 $newCords[7] = $cords[7]+$offset[1]-$pars[1]; 00854 00855 return $newCords; 00856 } 00857 00878 function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1) { 00879 00880 $spacing*=$sF; 00881 $wordSpacing*=$sF; 00882 00883 if (!$spacing && $wordSpacing) { 00884 $bits = explode(' ',$text); 00885 reset($bits); 00886 while(list(,$word)=each($bits)) { 00887 $word.=' '; 00888 $word = $word; 00889 $wordInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $word, $splitRenderingConf ,$sF); 00890 $wordW = ($wordInf[2]-$wordInf[0]); 00891 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $word, $splitRenderingConf, $sF); 00892 $x+=$wordW+$wordSpacing; 00893 } 00894 } else { 00895 $utf8Chars = $this->singleChars($text); 00896 // For each UTF-8 char, do: 00897 foreach($utf8Chars as $char) { 00898 $charInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $char, $splitRenderingConf, $sF); 00899 $charW = ($charInf[2]-$charInf[0]); 00900 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $char, $splitRenderingConf, $sF); 00901 $x+=$charW+(($char==' ')?$wordSpacing:$spacing); 00902 } 00903 } 00904 } 00905 00915 function fontResize($conf) { 00916 // 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!!!! 00917 $maxWidth = intval($conf['maxWidth']); 00918 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf); 00919 if ($maxWidth) { 00920 if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function: 00921 return $conf['fontSize']; 00922 // ################ no calc for spacing yet !!!!!! 00923 } else { 00924 do { 00925 // determine bounding box. 00926 $bounds = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $this->recodeString($conf['text']), $conf['splitRendering.']); 00927 if ($conf['angle']< 0) { 00928 $pixelWidth = abs($bounds[4]-$bounds[0]); 00929 } elseif ($conf['angle'] > 0) { 00930 $pixelWidth = abs($bounds[2]-$bounds[6]); 00931 } else { 00932 $pixelWidth = abs($bounds[4]-$bounds[6]); 00933 } 00934 00935 // Size is fine, exit: 00936 if ($pixelWidth <= $maxWidth) { 00937 break; 00938 } else { 00939 $conf['fontSize']--; 00940 } 00941 } while ($conf['fontSize']>1); 00942 }//if spacing 00943 } 00944 return $conf['fontSize']; 00945 } 00946 00958 function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1) { 00959 00960 // Initialize: 00961 $offsetInfo = array(); 00962 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile); 00963 00964 // Traverse string parts: 00965 foreach($stringParts as $strCfg) { 00966 $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']); 00967 if (is_readable($fontFile)) { 00968 00969 // Calculate Bounding Box for part: 00970 $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $fontFile, $strCfg['str']); 00971 00972 // Calculate offsets: 00973 if (!count($offsetInfo)) { 00974 $offsetInfo = $calc; // First run, just copy over. 00975 } else { 00976 $offsetInfo[2]+=$calc[2]-$calc[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']); 00977 $offsetInfo[3]+=$calc[3]-$calc[1]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']); 00978 $offsetInfo[4]+=$calc[4]-$calc[6]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']); 00979 $offsetInfo[5]+=$calc[5]-$calc[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']); 00980 } 00981 00982 } else { 00983 debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFBBoxWrapper()'); 00984 } 00985 } 00986 00987 return $offsetInfo; 00988 } 00989 01005 function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1) { 01006 01007 // Initialize: 01008 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile); 01009 $x = ceil($sF*$x); 01010 $y = ceil($sF*$y); 01011 01012 // Traverse string parts: 01013 foreach($stringParts as $i => $strCfg) { 01014 01015 // Initialize: 01016 $colorIndex = $color; 01017 01018 // Set custom color if any (only when niceText is off): 01019 if ($strCfg['color'] && $sF==1) { 01020 $cols = $this->convertColor($strCfg['color']); 01021 $colorIndex = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]); 01022 $colorIndex = $color >= 0 ? $colorIndex : -$colorIndex; 01023 } 01024 01025 // Setting xSpaceBefore 01026 if ($i) { 01027 $x+= intval($strCfg['xSpaceBefore']); 01028 $y-= intval($strCfg['ySpaceBefore']); 01029 } 01030 01031 $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']); 01032 if (is_readable($fontFile)) { 01033 01034 // Render part: 01035 ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, $fontFile, $strCfg['str']); 01036 01037 // Calculate offset to apply: 01038 $wordInf = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']); 01039 $x+= $wordInf[2]-$wordInf[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceAfter']); 01040 $y+= $wordInf[5]-$wordInf[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceAfter']); 01041 01042 } else { 01043 debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFTextWrapper()'); 01044 } 01045 01046 } 01047 } 01048 01058 function splitString($string,$splitRendering,$fontSize,$fontFile) { 01059 01060 // Initialize by setting the whole string and default configuration as the first entry. 01061 $result = array(); 01062 $result[] = array( 01063 'str' => $string, 01064 'fontSize' => $fontSize, 01065 'fontFile' => $fontFile 01066 ); 01067 01068 // Traverse the split-rendering configuration: 01069 // Splitting will create more entries in $result with individual configurations. 01070 if (is_array($splitRendering)) { 01071 $sKeyArray = t3lib_TStemplate::sortedKeyList($splitRendering); 01072 01073 // Traverse configured options: 01074 foreach($sKeyArray as $key) { 01075 $cfg = $splitRendering[$key.'.']; 01076 01077 // Process each type of split rendering keyword: 01078 switch((string)$splitRendering[$key]) { 01079 case 'highlightWord': 01080 if (strlen($cfg['value'])) { 01081 $newResult = array(); 01082 01083 // Traverse the current parts of the result array: 01084 foreach($result as $part) { 01085 // Explode the string value by the word value to highlight: 01086 $explodedParts = explode($cfg['value'],$part['str']); 01087 foreach($explodedParts as $c => $expValue) { 01088 if (strlen($expValue)) { 01089 $newResult[] = array_merge($part,array('str' => $expValue)); 01090 } 01091 if ($c+1 < count($explodedParts)) { 01092 $newResult[] = array( 01093 'str' => $cfg['value'], 01094 'fontSize' => $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'], 01095 'fontFile' => $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'], 01096 'color' => $cfg['color'], 01097 'xSpaceBefore' => $cfg['xSpaceBefore'], 01098 'xSpaceAfter' => $cfg['xSpaceAfter'], 01099 'ySpaceBefore' => $cfg['ySpaceBefore'], 01100 'ySpaceAfter' => $cfg['ySpaceAfter'], 01101 ); 01102 } 01103 } 01104 } 01105 01106 // Set the new result as result array: 01107 if (count($newResult)) { 01108 $result = $newResult; 01109 } 01110 } 01111 break; 01112 case 'charRange': 01113 if (strlen($cfg['value'])) { 01114 01115 // Initialize range: 01116 $ranges = t3lib_div::trimExplode(',',$cfg['value'],1); 01117 foreach($ranges as $i => $rangeDef) { 01118 $ranges[$i] = t3lib_div::intExplode('-',$ranges[$i]); 01119 if (!isset($ranges[$i][1])) $ranges[$i][1] = $ranges[$i][0]; 01120 } 01121 $newResult = array(); 01122 01123 // Traverse the current parts of the result array: 01124 foreach($result as $part) { 01125 01126 // Initialize: 01127 $currentState = -1; 01128 $bankAccum = ''; 01129 01130 // Explode the string value by the word value to highlight: 01131 $utf8Chars = $this->singleChars($part['str']); 01132 foreach($utf8Chars as $utfChar) { 01133 01134 // Find number and evaluate position: 01135 $uNumber = $this->csConvObj->utf8CharToUnumber($utfChar); 01136 $inRange = 0; 01137 foreach($ranges as $rangeDef) { 01138 if ($uNumber >= $rangeDef[0] && (!$rangeDef[1] || $uNumber <= $rangeDef[1])) { 01139 $inRange = 1; 01140 break; 01141 } 01142 } 01143 if ($currentState==-1) $currentState = $inRange; // Initialize first char 01144 01145 // Switch bank: 01146 if ($inRange != $currentState && !t3lib_div::inList('32,10,13,9',$uNumber)) { 01147 01148 // Set result: 01149 if (strlen($bankAccum)) { 01150 $newResult[] = array( 01151 'str' => $bankAccum, 01152 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'], 01153 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'], 01154 'color' => $currentState ? $cfg['color'] : '', 01155 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '', 01156 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '', 01157 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '', 01158 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '', 01159 ); 01160 } 01161 01162 // Initialize new settings: 01163 $currentState = $inRange; 01164 $bankAccum = ''; 01165 } 01166 01167 // Add char to bank: 01168 $bankAccum.=$utfChar; 01169 } 01170 01171 // Set result for FINAL part: 01172 if (strlen($bankAccum)) { 01173 $newResult[] = array( 01174 'str' => $bankAccum, 01175 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'], 01176 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'], 01177 'color' => $currentState ? $cfg['color'] : '', 01178 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '', 01179 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '', 01180 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '', 01181 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '', 01182 ); 01183 } 01184 } 01185 01186 // Set the new result as result array: 01187 if (count($newResult)) { 01188 $result = $newResult; 01189 } 01190 } 01191 break; 01192 } 01193 } 01194 } 01195 01196 return $result; 01197 } 01198 01208 function calcWordSpacing($conf, $scaleFactor=1) { 01209 01210 $spacing = intval($conf['spacing']); 01211 $wordSpacing = intval($conf['wordSpacing']); 01212 $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2; 01213 01214 $spacing*=$scaleFactor; 01215 $wordSpacing*=$scaleFactor; 01216 01217 return array($spacing,$wordSpacing); 01218 } 01219 01227 function getTextScalFactor($conf) { 01228 if (!$conf['niceText']) { 01229 $sF = 1; 01230 } else { // NICETEXT:: 01231 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5); 01232 } 01233 return $sF; 01234 } 01235 01236 01237 01238 01239 01240 01241 01242 01243 01244 01245 01246 /********************************************* 01247 * 01248 * Other GIFBUILDER objects related to TEXT 01249 * 01250 *********************************************/ 01251 01262 function makeOutline(&$im,$conf,$workArea,$txtConf) { 01263 $thickness = intval($conf['thickness']); 01264 if ($thickness) { 01265 $txtConf['fontColor'] = $conf['color']; 01266 $outLineDist = t3lib_div::intInRange($thickness,1,2); 01267 for ($b=1;$b<=$outLineDist;$b++) { 01268 if ($b==1) { 01269 $it = 8; 01270 } else { 01271 $it = 16; 01272 } 01273 $outL = $this->circleOffset($b, $it); 01274 for ($a=0;$a<$it;$a++) { 01275 $this->makeText($im,$txtConf,$this->applyOffset($workArea,$outL[$a])); 01276 } 01277 } 01278 } 01279 } 01280 01291 function circleOffset($distance, $iterations) { 01292 $res = Array(); 01293 if ($distance && $iterations) { 01294 for ($a=0;$a<$iterations;$a++) { 01295 $yOff = round(sin(2*pi()/$iterations*($a+1))*100*$distance); 01296 if ($yOff) {$yOff = intval(ceil(abs($yOff/100))*($yOff/abs($yOff)));} 01297 $xOff = round(cos(2*pi()/$iterations*($a+1))*100*$distance); 01298 if ($xOff) {$xOff = intval(ceil(abs($xOff/100))*($xOff/abs($xOff)));} 01299 $res[$a] = Array($xOff,$yOff); 01300 } 01301 } 01302 return $res; 01303 } 01304 01315 function makeEmboss(&$im,$conf,$workArea,$txtConf) { 01316 $conf['color']=$conf['highColor']; 01317 $this->makeShadow($im,$conf,$workArea,$txtConf); 01318 $newOffset = t3lib_div::intExplode(',',$conf['offset']); 01319 $newOffset[0]*=-1; 01320 $newOffset[1]*=-1; 01321 $conf['offset']=implode(',',$newOffset); 01322 $conf['color']=$conf['lowColor']; 01323 $this->makeShadow($im,$conf,$workArea,$txtConf); 01324 } 01325 01337 function makeShadow(&$im,$conf,$workArea,$txtConf) { 01338 $workArea = $this->applyOffset($workArea,t3lib_div::intExplode(',',$conf['offset'])); 01339 $blurRate = t3lib_div::intInRange(intval($conf['blur']),0,99); 01340 01341 if (!$blurRate || $this->NO_IM_EFFECTS) { // No effects if ImageMagick ver. 5+ 01342 $txtConf['fontColor'] = $conf['color']; 01343 $this->makeText($im,$txtConf,$workArea); 01344 } else { 01345 $w = imagesx($im); 01346 $h = imagesy($im); 01347 $blurBorder= 3; // area around the blur used for cropping something 01348 $tmpStr = $this->randomName(); 01349 $fileMenu = $tmpStr.'_menu.'.$this->gifExtension; 01350 $fileColor = $tmpStr.'_color.'.$this->gifExtension; 01351 $fileMask = $tmpStr.'_mask.'.$this->gifExtension; 01352 01353 // BlurColor Image laves 01354 $blurColImg = $this->imagecreate($w,$h); 01355 $bcols=$this->convertColor($conf['color']); 01356 $Bcolor = ImageColorAllocate($blurColImg, $bcols[0],$bcols[1],$bcols[2]); 01357 ImageFilledRectangle($blurColImg, 0, 0, $w, $h, $Bcolor); 01358 $this->ImageWrite($blurColImg, $fileColor); 01359 ImageDestroy($blurColImg); 01360 01361 // The mask is made: BlurTextImage 01362 $blurTextImg = $this->imagecreate($w+$blurBorder*2,$h+$blurBorder*2); 01363 $Bcolor = ImageColorAllocate($blurTextImg, 0,0,0); // black background 01364 ImageFilledRectangle($blurTextImg, 0, 0, $w+$blurBorder*2, $h+$blurBorder*2, $Bcolor); 01365 $txtConf['fontColor'] = 'white'; 01366 $blurBordArr = Array($blurBorder,$blurBorder); 01367 $this->makeText($blurTextImg,$txtConf, $this->applyOffset($workArea,$blurBordArr)); 01368 $this->ImageWrite($blurTextImg, $fileMask); // dump to temporary file 01369 ImageDestroy($blurTextImg); // destroy 01370 01371 01372 $command=''; 01373 $command.=$this->maskNegate; 01374 01375 if ($this->V5_EFFECTS) { 01376 $command.=$this->v5_blur($blurRate+1); 01377 } else { 01378 // Blurring of the mask 01379 $times = ceil($blurRate/10); // How many blur-commands that is executed. Min = 1; 01380 $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. 01381 $newBlurRate = t3lib_div::intInRange($newBlurRate,1,99); 01382 for ($a=0;$a<$times;$a++) { // Building blur-command 01383 $command.=' -blur '.$blurRate; 01384 } 01385 } 01386 01387 $this->imageMagickExec($fileMask,$fileMask,$command.' +matte'); 01388 01389 $blurTextImg_tmp = $this->imageCreateFromFile($fileMask); // the mask is loaded again 01390 if ($blurTextImg_tmp) { // if nothing went wrong we continue with the blurred mask 01391 01392 // cropping the border from the mask 01393 $blurTextImg = $this->imagecreate($w,$h); 01394 $this->imagecopyresized($blurTextImg, $blurTextImg_tmp, 0, 0, $blurBorder, $blurBorder, $w, $h, $w, $h); 01395 ImageDestroy($blurTextImg_tmp); // Destroy the temporary mask 01396 01397 // adjust the mask 01398 $intensity = 40; 01399 if ($conf['intensity']) { 01400 $intensity = t3lib_div::intInRange($conf['intensity'],0,100); 01401 } 01402 $intensity = ceil(255-($intensity/100*255)); 01403 $this->inputLevels($blurTextImg,0,$intensity,$this->maskNegate); 01404 01405 $opacity = t3lib_div::intInRange(intval($conf['opacity']),0,100); 01406 if ($opacity && $opacity<100) { 01407 $high = ceil(255*$opacity/100); 01408 $this->outputLevels($blurTextImg,0,$high,$this->maskNegate); // reducing levels as the opacity demands 01409 } 01410 01411 $this->ImageWrite($blurTextImg, $fileMask); // Dump the mask again 01412 ImageDestroy($blurTextImg); // Destroy the mask 01413 01414 // The pictures are combined 01415 $this->ImageWrite($im, $fileMenu); // The main pictures is saved temporarily 01416 01417 $this->combineExec($fileMenu,$fileColor,$fileMask,$fileMenu); 01418 01419 $backIm = $this->imageCreateFromFile($fileMenu); // The main image is loaded again... 01420 if ($backIm) { // ... and if nothing went wrong we load it onto the old one. 01421 ImageColorTransparent($backIm,-1); 01422 $im = $backIm; 01423 } 01424 } 01425 // Deleting temporary files; 01426 if (!$this->dontUnlinkTempFiles) { 01427 unlink($fileMenu); 01428 unlink($fileColor); 01429 unlink($fileMask); 01430 } 01431 } 01432 } 01433 01434 01435 01436 01437 01438 01439 01440 01441 01442 01443 01444 01445 01446 01447 01448 01449 01450 01451 01452 01453 01454 /**************************** 01455 * 01456 * Other GIFBUILDER objects 01457 * 01458 ****************************/ 01459 01469 function makeBox(&$im,$conf,$workArea) { 01470 $cords = t3lib_div::intExplode(',',$conf['dimensions'].',,,'); 01471 $conf['offset']=$cords[0].','.$cords[1]; 01472 $cords = $this->objPosition($conf,$workArea,Array($cords[2],$cords[3])); 01473 $cols=$this->convertColor($conf['color']); 01474 if (!$this->truecolor) { 01475 $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256); 01476 $this->reduceColors($im, $reduce-1, $reduce-2); // If "reduce-1" colors (or more) are used reduce them to "reduce-2" 01477 } 01478 $tmpColor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]); 01479 imagefilledrectangle($im, $cords[0], $cords[1], $cords[0]+$cords[2]-1, $cords[1]+$cords[3]-1, $tmpColor); 01480 } 01481 01491 function makeEffect(&$im, $conf) { 01492 $commands = $this->IMparams($conf['value']); 01493 if ($commands) { 01494 $this->applyImageMagickToPHPGif($im, $commands); 01495 } 01496 } 01497 01506 function IMparams($setup) { 01507 if (!trim($setup)){return '';} 01508 $effects = explode('|', $setup); 01509 $commands = ''; 01510 while(list(,$val)=each($effects)) { 01511 $pairs=explode('=',$val,2); 01512 $value = trim($pairs[1]); 01513 $effect = strtolower(trim($pairs[0])); 01514 switch($effect) { 01515 case 'gamma': 01516 $commands.=' -gamma '.doubleval($value); 01517 break; 01518 case 'blur': 01519 if (!$this->NO_IM_EFFECTS) { 01520 if ($this->V5_EFFECTS) { 01521 $commands.=$this->v5_blur($value); 01522 } else { 01523 $commands.=' -blur '.t3lib_div::intInRange($value,1,99); 01524 } 01525 } 01526 break; 01527 case 'sharpen': 01528 if (!$this->NO_IM_EFFECTS) { 01529 if ($this->V5_EFFECTS) { 01530 $commands.=$this->v5_sharpen($value); 01531 } else { 01532 $commands.=' -sharpen '.t3lib_div::intInRange($value,1,99); 01533 } 01534 } 01535 break; 01536 case 'rotate': 01537 $commands.=' -rotate '.t3lib_div::intInRange($value,0,360); 01538 break; 01539 case 'solarize': 01540 $commands.=' -solarize '.t3lib_div::intInRange($value,0,99); 01541 break; 01542 case 'swirl': 01543 $commands.=' -swirl '.t3lib_div::intInRange($value,0,1000); 01544 break; 01545 case 'wave': 01546 $params = t3lib_div::intExplode(',',$value); 01547 $commands.=' -wave '.t3lib_div::intInRange($params[0],0,99).'x'.t3lib_div::intInRange($params[1],0,99); 01548 break; 01549 case 'charcoal': 01550 $commands.=' -charcoal '.t3lib_div::intInRange($value,0,100); 01551 break; 01552 case 'gray': 01553 $commands.=' -colorspace GRAY'; 01554 break; 01555 case 'edge': 01556 $commands.=' -edge '.t3lib_div::intInRange($value,0,99); 01557 break; 01558 case 'emboss': 01559 $commands.=' -emboss'; 01560 break; 01561 case 'flip': 01562 $commands.=' -flip'; 01563 break; 01564 case 'flop': 01565 $commands.=' -flop'; 01566 break; 01567 case 'colors': 01568 $commands.=' -colors '.t3lib_div::intInRange($value,2,255); 01569 break; 01570 case 'shear': 01571 $commands.=' -shear '.t3lib_div::intInRange($value,-90,90); 01572 break; 01573 case 'invert': 01574 $commands.=' -negate'; 01575 break; 01576 } 01577 } 01578 return $commands; 01579 } 01580 01589 function adjust(&$im, $conf) { 01590 $setup = $conf['value']; 01591 if (!trim($setup)){return '';} 01592 $effects = explode('|', $setup); 01593 while(list(,$val)=each($effects)) { 01594 $pairs=explode('=',$val,2); 01595 $value = trim($pairs[1]); 01596 $effect = strtolower(trim($pairs[0])); 01597 switch($effect) { 01598 case 'inputlevels': // low,high 01599 $params = t3lib_div::intExplode(',',$value); 01600 $this->inputLevels($im,$params[0],$params[1]); 01601 break; 01602 case 'outputlevels': 01603 $params = t3lib_div::intExplode(',',$value); 01604 $this->outputLevels($im,$params[0],$params[1]); 01605 break; 01606 case 'autolevels': 01607 $this->autoLevels($im); 01608 break; 01609 } 01610 } 01611 } 01612 01621 function crop(&$im,$conf) { 01622 $this->setWorkArea(''); // clears workArea to total image 01623 $cords = t3lib_div::intExplode(',',$conf['crop'].',,,'); 01624 $conf['offset']=$cords[0].','.$cords[1]; 01625 $cords = $this->objPosition($conf,$this->workArea,Array($cords[2],$cords[3])); 01626 01627 $newIm = $this->imagecreate($cords[2],$cords[3]); 01628 $cols=$this->convertColor($conf['backColor']?$conf['backColor']:$this->setup['backColor']); 01629 $Bcolor = ImageColorAllocate($newIm, $cols[0],$cols[1],$cols[2]); 01630 ImageFilledRectangle($newIm, 0, 0, $cords[2], $cords[3], $Bcolor); 01631 01632 $newConf = Array(); 01633 $workArea = Array(0,0,$cords[2],$cords[3]); 01634 if ($cords[0]<0) {$workArea[0]=abs($cords[0]);} else {$newConf['offset']=-$cords[0];} 01635 if ($cords[1]<0) {$workArea[1]=abs($cords[1]);} else {$newConf['offset'].=','.-$cords[1];} 01636 01637 $this->copyGifOntoGif($newIm,$im,$newConf,$workArea); 01638 $im = $newIm; 01639 $this->w = imagesx($im); 01640 $this->h = imagesy($im); 01641 $this->setWorkArea(''); // clears workArea to total image 01642 } 01643 01652 function scale(&$im,$conf) { 01653 if ($conf['width'] || $conf['height'] || $conf['params']) { 01654 $tmpStr = $this->randomName(); 01655 $theFile = $tmpStr.'.'.$this->gifExtension; 01656 $this->ImageWrite($im, $theFile); 01657 $theNewFile = $this->imageMagickConvert($theFile,$this->gifExtension,$conf['width'],$conf['height'],$conf['params'],'',''); 01658 $tmpImg = $this->imageCreateFromFile($theNewFile[3]); 01659 if ($tmpImg) { 01660 ImageDestroy($im); 01661 $im = $tmpImg; 01662 $this->w = imagesx($im); 01663 $this->h = imagesy($im); 01664 $this->setWorkArea(''); // clears workArea to total image 01665 } 01666 if (!$this->dontUnlinkTempFiles) { 01667 unlink($theFile); 01668 if ($theNewFile[3] && $theNewFile[3]!=$theFile) { 01669 unlink($theNewFile[3]); 01670 } 01671 } 01672 } 01673 } 01674 01684 function setWorkArea($workArea) { 01685 $this->workArea = t3lib_div::intExplode(',',$workArea); 01686 $this->workArea = $this->applyOffset($this->workArea,$this->OFFSET); 01687 if (!$this->workArea[2]) {$this->workArea[2]=$this->w;} 01688 if (!$this->workArea[3]) {$this->workArea[3]=$this->h;} 01689 } 01690 01691 01692 01693 01694 01695 01696 01697 01698 01699 01700 01701 01702 01703 01704 01705 01706 01707 01708 01709 01710 01711 01712 01713 /************************* 01714 * 01715 * Adjustment functions 01716 * 01717 ************************/ 01718 01725 function autolevels(&$im) { 01726 $totalCols = ImageColorsTotal($im); 01727 $min=255; 01728 $max=0; 01729 for ($c=0; $c<$totalCols; $c++) { 01730 $cols = ImageColorsForIndex($im,$c); 01731 $grayArr[] = round(($cols['red']+$cols['green']+$cols['blue'])/3); 01732 } 01733 $min=min($grayArr); 01734 $max=max($grayArr); 01735 $delta = $max-$min; 01736 if ($delta) { 01737 for ($c=0; $c<$totalCols; $c++) { 01738 $cols = ImageColorsForIndex($im,$c); 01739 $cols['red'] = floor(($cols['red']-$min)/$delta*255); 01740 $cols['green'] = floor(($cols['green']-$min)/$delta*255); 01741 $cols['blue'] = floor(($cols['blue']-$min)/$delta*255); 01742 ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']); 01743 } 01744 } 01745 } 01746 01756 function outputLevels(&$im,$low,$high,$swap='') { 01757 if ($low<$high){ 01758 $low = t3lib_div::intInRange($low,0,255); 01759 $high = t3lib_div::intInRange($high,0,255); 01760 01761 if ($swap) { 01762 $temp = $low; 01763 $low = 255-$high; 01764 $high = 255-$temp; 01765 } 01766 01767 $delta = $high-$low; 01768 $totalCols = ImageColorsTotal($im); 01769 for ($c=0; $c<$totalCols; $c++) { 01770 $cols = ImageColorsForIndex($im,$c); 01771 $cols['red'] = $low+floor($cols['red']/255*$delta); 01772 $cols['green'] = $low+floor($cols['green']/255*$delta); 01773 $cols['blue'] = $low+floor($cols['blue']/255*$delta); 01774 ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']); 01775 } 01776 } 01777 } 01778 01788 function inputLevels(&$im,$low,$high,$swap='') { 01789 if ($low<$high){ 01790 $low = t3lib_div::intInRange($low,0,255); 01791 $high = t3lib_div::intInRange($high,0,255); 01792 01793 if ($swap) { 01794 $temp = $low; 01795 $low = 255-$high; 01796 $high = 255-$temp; 01797 } 01798 01799 $delta = $high-$low; 01800 $totalCols = ImageColorsTotal($im); 01801 for ($c=0; $c<$totalCols; $c++) { 01802 $cols = ImageColorsForIndex($im,$c); 01803 $cols['red'] = t3lib_div::intInRange(($cols['red']-$low)/$delta*255, 0,255); 01804 $cols['green'] = t3lib_div::intInRange(($cols['green']-$low)/$delta*255, 0,255); 01805 $cols['blue'] = t3lib_div::intInRange(($cols['blue']-$low)/$delta*255, 0,255); 01806 ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']); 01807 } 01808 } 01809 } 01810 01819 function reduceColors(&$im,$limit, $cols) { 01820 if (!$this->truecolor && ImageColorsTotal($im)>=$limit) { 01821 $this->makeEffect($im, Array('value'=>'colors='.$cols) ); 01822 } 01823 } 01824 01832 function IMreduceColors($file, $cols) { 01833 $fI = t3lib_div::split_fileref($file); 01834 $ext = strtolower($fI['fileext']); 01835 $result = $this->randomName().'.'.$ext; 01836 if (($reduce = t3lib_div::intInRange($cols, 0, ($ext=='gif'?256:$this->truecolorColors), 0))>0) { 01837 $params = ' -colors '.$reduce; 01838 if (!$this->im_version_4) { 01839 // IM4 doesn't have this options but forces them automatically if applicaple (<256 colors in image) 01840 if ($reduce<=256) { $params .= ' -type Palette'; } 01841 if ($ext=='png' && $reduce<=256) { $prefix = 'png8:'; } 01842 } 01843 $this->imageMagickExec($file, $prefix.$result, $params); 01844 if ($result) { 01845 return $result; 01846 } 01847 } 01848 return ''; 01849 } 01850 01851 01852 01853 01854 01855 01856 01857 01858 01859 01860 01861 /********************************* 01862 * 01863 * GIFBUILDER Helper functions 01864 * 01865 *********************************/ 01866 01875 function prependAbsolutePath($fontFile) { 01876 $absPath = defined('PATH_typo3') ? dirname(PATH_thisScript).'/' :PATH_site; 01877 $fontFile = t3lib_div::isAbsPath($fontFile) ? $fontFile : t3lib_div::resolveBackPath($absPath.$fontFile); 01878 return $fontFile; 01879 } 01880 01889 function v5_sharpen($factor) { 01890 $factor = t3lib_div::intInRange(ceil($factor/10),0,10); 01891 01892 $sharpenArr=explode(',',','.$this->im5fx_sharpenSteps); 01893 $sharpenF= trim($sharpenArr[$factor]); 01894 if ($sharpenF) { 01895 $cmd = ' -sharpen '.$sharpenF; 01896 return $cmd; 01897 } 01898 } 01899 01908 function v5_blur($factor) { 01909 $factor = t3lib_div::intInRange(ceil($factor/10),0,10); 01910 01911 $blurArr=explode(',',','.$this->im5fx_blurSteps); 01912 $blurF= trim($blurArr[$factor]); 01913 if ($blurF) { 01914 $cmd=' -blur '.$blurF; 01915 return $cmd; 01916 } 01917 } 01918 01925 function randomName() { 01926 $this->createTempSubDir('temp/'); 01927 return $this->tempPath.'temp/'.md5(uniqid('')); 01928 } 01929 01938 function applyOffset($cords,$OFFSET) { 01939 $cords[0] = intval($cords[0])+intval($OFFSET[0]); 01940 $cords[1] = intval($cords[1])+intval($OFFSET[1]); 01941 return $cords; 01942 } 01943 01951 function convertColor($string) { 01952 $col=array(); 01953 $cParts = explode(':',$string,2); 01954 01955 // Finding the RGB definitions of the color: 01956 $string=$cParts[0]; 01957 if (strstr($string,'#')) { 01958 $string = ereg_replace('[^A-Fa-f0-9]*','',$string); 01959 $col[]=HexDec(substr($string,0,2)); 01960 $col[]=HexDec(substr($string,2,2)); 01961 $col[]=HexDec(substr($string,4,2)); 01962 } elseif (strstr($string,',')) { 01963 $string = ereg_replace('[^,0-9]*','',$string); 01964 $strArr = explode(',',$string); 01965 $col[]=intval($strArr[0]); 01966 $col[]=intval($strArr[1]); 01967 $col[]=intval($strArr[2]); 01968 } else { 01969 $string = strtolower(trim($string)); 01970 if ($this->colMap[$string]) { 01971 $col = $this->colMap[$string]; 01972 } else { 01973 $col = Array(0,0,0); 01974 } 01975 } 01976 // ... and possibly recalculating the value 01977 if (trim($cParts[1])) { 01978 $cParts[1]=trim($cParts[1]); 01979 if (substr($cParts[1],0,1)=='*') { 01980 $val=doubleval(substr($cParts[1],1)); 01981 $col[0]=t3lib_div::intInRange($col[0]*$val,0,255); 01982 $col[1]=t3lib_div::intInRange($col[1]*$val,0,255); 01983 $col[2]=t3lib_div::intInRange($col[2]*$val,0,255); 01984 } else { 01985 $val=intval($cParts[1]); 01986 $col[0]=t3lib_div::intInRange($col[0]+$val,0,255); 01987 $col[1]=t3lib_div::intInRange($col[1]+$val,0,255); 01988 $col[2]=t3lib_div::intInRange($col[2]+$val,0,255); 01989 } 01990 } 01991 return $col; 01992 } 01993 02001 function recodeString($string) { 02002 // Recode string to UTF-8 from $this->nativeCharset: 02003 if ($this->nativeCharset && $this->nativeCharset!='utf-8') { 02004 $string = $this->csConvObj->utf8_encode($string,$this->nativeCharset); // Convert to UTF-8 02005 } 02006 02007 // Recode string accoding to TTFLocaleConv. Deprecated. 02008 if ($this->TTFLocaleConv) { 02009 $string = recode_string($this->TTFLocaleConv,$string); 02010 } 02011 02012 return $string; 02013 } 02014 02023 function singleChars($theText,$returnUnicodeNumber=FALSE) { 02024 if ($this->nativeCharset) { 02025 return $this->csConvObj->utf8_to_numberarray($theText,1,$returnUnicodeNumber ? 0 : 1); // Get an array of separated UTF-8 chars 02026 } else { 02027 $output=array(); 02028 $c=strlen($theText); 02029 for($a=0;$a<$c;$a++) { 02030 $output[]=substr($theText,$a,1); 02031 } 02032 return $output; 02033 } 02034 } 02035 02046 function objPosition($conf,$workArea,$BB) { 02047 // offset, align, valign, workarea 02048 $result=Array(); 02049 $result[2] = $BB[0]; 02050 $result[3] = $BB[1]; 02051 $w=$workArea[2]; 02052 $h=$workArea[3]; 02053 02054 $align = explode(',',$conf['align']); 02055 $align[0] = strtolower(substr(trim($align[0]),0,1)); 02056 $align[1] = strtolower(substr(trim($align[1]),0,1)); 02057 02058 switch($align[0]) { 02059 case 'r': 02060 $result[0]=$w-$result[2]; 02061 break; 02062 case 'c': 02063 $result[0] = round(($w-$result[2])/2); 02064 break; 02065 default: 02066 $result[0] = 0; 02067 break; 02068 } 02069 switch($align[1]) { 02070 case 'b': 02071 $result[1] = $h-$result[3]; // y pos 02072 break; 02073 case 'c': 02074 $result[1] = round(($h-$result[3])/2); 02075 break; 02076 default: 02077 $result[1]=0; 02078 break; 02079 } 02080 $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset'])); 02081 $result = $this->applyOffset($result,$workArea); 02082 return $result; 02083 } 02084 02085 02086 02087 02088 02089 02090 02091 02092 02093 02094 02095 02096 02097 02098 02099 02100 02101 02102 02103 02104 02105 /*********************************** 02106 * 02107 * Scaling, Dimensions of images 02108 * 02109 ***********************************/ 02110 02125 function imageMagickConvert($imagefile,$newExt='',$w='',$h='',$params='',$frame='',$options='',$mustCreate=0) { 02126 if ($this->NO_IMAGE_MAGICK) { 02127 // Returning file info right away 02128 return $this->getImageDimensions($imagefile); 02129 } 02130 02131 if($info=$this->getImageDimensions($imagefile)) { 02132 $newExt=strtolower(trim($newExt)); 02133 if (!$newExt) { // If no extension is given the original extension is used 02134 $newExt = $info[2]; 02135 } 02136 if ($newExt=='web') { 02137 if (t3lib_div::inList($this->webImageExt,$info[2])) { 02138 $newExt = $info[2]; 02139 } else { 02140 $newExt = $this->gif_or_jpg($info[2],$info[0],$info[1]); 02141 if (!$params) { 02142 $params = $this->cmds[$newExt]; 02143 } 02144 } 02145 } 02146 if (t3lib_div::inList($this->imageFileExt,$newExt)) { 02147 if (strstr($w.$h, 'm')) {$max=1;} else {$max=0;} 02148 02149 $data = $this->getImageScale($info,$w,$h,$options); 02150 $w=$data['origW']; 02151 $h=$data['origH']; 02152 02153 // if no convertion should be performed 02154 $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.... 02155 02156 if ($wh_noscale && !$data['crs'] && !$params && !$frame && $newExt==$info[2] && !$mustCreate) { 02157 $info[3] = $imagefile; 02158 return $info; 02159 } 02160 $info[0]=$data[0]; 02161 $info[1]=$data[1]; 02162 02163 $frame = $this->noFramePrepended ? '' : '['.intval($frame).']'; 02164 02165 if (!$params) { 02166 $params = $this->cmds[$newExt]; 02167 } 02168 02169 $command = $this->scalecmd.' '.$info[0].'x'.$info[1].'! '.$params.' '; 02170 $cropscale = ($data['crs'] ? 'crs-V'.$data['cropV'].'H'.$data['cropH'] : ''); 02171 02172 if ($this->alternativeOutputKey) { 02173 $theOutputName = t3lib_div::shortMD5($command.$cropscale.basename($imagefile).$this->alternativeOutputKey.$frame); 02174 } else { 02175 $theOutputName = t3lib_div::shortMD5($command.$cropscale.$imagefile.filemtime($imagefile).$frame); 02176 } 02177 if ($this->imageMagickConvert_forceFileNameBody) { 02178 $theOutputName = $this->imageMagickConvert_forceFileNameBody; 02179 $this->imageMagickConvert_forceFileNameBody=''; 02180 } 02181 02182 // Making the temporary filename: 02183 $this->createTempSubDir('pics/'); 02184 $output = $this->absPrefix.$this->tempPath.'pics/'.$this->filenamePrefix.$theOutputName.'.'.$newExt; 02185 02186 // Register temporary filename: 02187 $GLOBALS['TEMP_IMAGES_ON_PAGE'][] = $output; 02188 02189 // Cropscaling: 02190 if ($data['crs']) { 02191 if ($this->dontCheckForExistingTempFile || !$this->file_exists_typo3temp_file($output, $imagefile)) { 02192 $crsOutput = str_replace('pics/', 'pics/crs-', $output); 02193 $this->imageMagickExec($imagefile.$frame, $crsOutput, $command); 02194 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder'); 02195 $gifCreator->init(); 02196 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'] !== 0) { 02197 if (!$data['origW']) { $data['origW'] = $data[0]; } 02198 if (!$data['origH']) { $data['origH'] = $data[1]; } 02199 $ofX = intval(($data['origW'] - $data[0]) * ($data['cropH']+100)/200); 02200 $ofY = intval(($data['origH'] - $data[1]) * ($data['cropV']+100)/200); 02201 $tmpParm = Array('XY' => intval($data['origW']).','.intval($data['origH']), 02202 '10' => 'IMAGE', 02203 '10.' => array('file'=> $crsOutput, 'offset'=> $ofX.','.$ofY), 02204 ); 02205 $gifCreator->start($tmpParm, array()); 02206 $newoutput = $gifCreator->gifBuild(); 02207 if (!copy($newoutput,$output)) { 02208 $output = $newoutput; 02209 } 02210 } else { 02211 $output = $crsOutput; 02212 } 02213 } 02214 } elseif ($this->dontCheckForExistingTempFile || !$this->file_exists_typo3temp_file($output,$imagefile)) { 02215 $this->imageMagickExec($imagefile.$frame,$output,$command); 02216 } 02217 if (@file_exists($output)) { 02218 $info[3] = $output; 02219 $info[2] = $newExt; 02220 if ($params) { // params could realisticly change some imagedata! 02221 $info=$this->getImageDimensions($info[3]); 02222 } 02223 if ($info[2]==$this->gifExtension && !$this->dontCompress) { 02224 t3lib_div::gif_compress($info[3],''); // Compress with IM (lzw) or GD (rle) (Workaround for the absence of lzw-compression in GD) 02225 } 02226 return $info; 02227 } 02228 } 02229 } 02230 } 02231 02239 function getImageDimensions($imageFile) { 02240 ereg('([^\.]*)$',$imageFile,$reg); 02241 if (@file_exists($imageFile) && t3lib_div::inList($this->imageFileExt,strtolower($reg[0]))) { 02242 if ($returnArr = $this->getCachedImageDimensions($imageFile)) { 02243 return $returnArr; 02244 } else { 02245 if ($temp = @getImageSize($imageFile)) { 02246 $returnArr = Array($temp[0], $temp[1], strtolower($reg[0]), $imageFile); 02247 } else { 02248 $returnArr = $this->imageMagickIdentify($imageFile); 02249 } 02250 if ($returnArr) { 02251 $this->cacheImageDimensions($returnArr); 02252 return $returnArr; 02253 } 02254 } 02255 } 02256 return false; 02257 } 02258 02267 function cacheImageDimensions($identifyResult) { 02268 global $TYPO3_DB; 02269 // Create a md5 hash of the filename 02270 $md5Hash = md5_file($identifyResult[3]); 02271 if ($md5Hash) { 02272 $fieldArr = array ( 02273 'md5hash' => $md5Hash, 02274 'md5filename' => md5($identifyResult[3]), 02275 'tstamp' => time(), 02276 'filename' => $identifyResult[3], 02277 'imagewidth' => $identifyResult[0], 02278 'imageheight' => $identifyResult[1], 02279 ); 02280 $TYPO3_DB->exec_INSERTquery('cache_imagesizes', $fieldArr); 02281 if (!$err = $TYPO3_DB->sql_error()) { 02282 return true; 02283 } 02284 } 02285 return false; 02286 } 02287 02295 function getCachedImageDimensions($imageFile) { 02296 global $TYPO3_DB; 02297 // Create a md5 hash of the filename 02298 $md5Hash = md5_file($imageFile); 02299 ereg('([^\.]*)$',$imageFile,$reg); 02300 $res = $TYPO3_DB->exec_SELECTquery ('md5hash, imagewidth, imageheight', 'cache_imagesizes', 'md5filename='.$TYPO3_DB->fullQuoteStr(md5($imageFile),'cache_imagesizes')); 02301 if ($res) { 02302 if ($row = $TYPO3_DB->sql_fetch_assoc($res)) { 02303 if ($row['md5hash']!=$md5Hash) { 02304 // file has changed, delete the row 02305 $TYPO3_DB->exec_DELETEquery ('cache_imagesizes', 'md5hash='.$TYPO3_DB->fullQuoteStr($row['md5hash'],'cache_imagesizes')); 02306 } else { 02307 return (array($row['imagewidth'], $row['imageheight'], strtolower($reg[0]), $imageFile)); 02308 } 02309 } 02310 } 02311 return false; 02312 } 02313 02325 function getImageScale($info,$w,$h,$options) { 02326 if (strstr($w.$h, 'm')) {$max=1;} else {$max=0;} 02327 02328 if (strstr($w.$h, 'c')) { 02329 $out['cropH'] = intval(substr(strstr($w, 'c'), 1)); 02330 $out['cropV'] = intval(substr(strstr($h, 'c'), 1)); 02331 $crs = true; 02332 } else { 02333 $crs = false; 02334 } 02335 $out['crs'] = $crs; 02336 02337 $w=intval($w); 02338 $h=intval($h); 02339 // if there are max-values... 02340 if ($options['maxW']) { 02341 if ($w) { // if width is given... 02342 if ($w>$options['maxW']) { 02343 $w=$options['maxW']; 02344 $max=1; // height should follow 02345 } 02346 } else { 02347 if ($info[0]>$options['maxW']) { 02348 $w=$options['maxW']; 02349 $max=1; // height should follow 02350 } 02351 } 02352 } 02353 if ($options['maxH']) { 02354 if ($h) { // if height is given... 02355 if ($h>$options['maxH']) { 02356 $h=$options['maxH']; 02357 $max=1; // height should follow 02358 } 02359 } else { 02360 if ($info[1]>$options['maxH']) { // Changed [0] to [1] 290801 02361 $h=$options['maxH']; 02362 $max=1; // height should follow 02363 } 02364 } 02365 } 02366 $out['origW']=$w; 02367 $out['origH']=$h; 02368 $out['max'] = $max; 02369 02370 if (!$this->mayScaleUp) { 02371 if ($w>$info[0]){$w=$info[0];} 02372 if ($h>$info[1]){$h=$info[1];} 02373 } 02374 if ($w || $h) { // if scaling should be performed 02375 if ($w && !$h) { 02376 $info[1] = ceil($info[1]*($w/$info[0])); 02377 $info[0] = $w; 02378 } 02379 if (!$w && $h) { 02380 $info[0] = ceil($info[0]*($h/$info[1])); 02381 $info[1] = $h; 02382 } 02383 if ($w && $h) { 02384 if ($max) { 02385 $ratio = $info[0]/$info[1]; 02386 if ($h*$ratio > $w) { 02387 $h = round($w/$ratio); 02388 } else { 02389 $w = round($h*$ratio); 02390 } 02391 } 02392 if ($crs) { 02393 $ratio = $info[0] / $info[1]; 02394 if ($h * $ratio < $w) { 02395 $h = round($w / $ratio); 02396 } else { 02397 $w = round($h * $ratio); 02398 } 02399 } 02400 $info[0] = $w; 02401 $info[1] = $h; 02402 } 02403 } 02404 $out[0]=$info[0]; 02405 $out[1]=$info[1]; 02406 // Set minimum-measures! 02407 if ($options['minW'] && $out[0]<$options['minW']) { 02408 if (($max || $crs) && $out[0]) { 02409 $out[1]= round($out[1]*$options['minW']/$out[0]); 02410 } 02411 $out[0]=$options['minW']; 02412 } 02413 if ($options['minH'] && $out[1]<$options['minH']) { 02414 if (($max || $crs) && $out[1]) { 02415 $out[0]= round($out[0]*$options['minH']/$out[1]); 02416 } 02417 $out[1]=$options['minH']; 02418 } 02419 02420 return $out; 02421 } 02422 02431 function file_exists_typo3temp_file($output,$orig='') { 02432 if ($this->enable_typo3temp_db_tracking) { 02433 if (@file_exists($output)) { // If file exists, then we return immediately 02434 return 1; 02435 } else { // If not, we look up in the cache_typo3temp_log table to see if there is a image being rendered right now. 02436 $md5Hash=md5($output); 02437 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('md5hash', 'cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log').' AND tstamp>'.(time()-30)); 02438 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { // If there was a record, the image is being generated by another proces (we assume) 02439 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...) 02440 if (is_object($GLOBALS['TT'])) $GLOBALS['TT']->setTSlogMessage('typo3temp_log: Assume this file is being rendered now: '.$output); 02441 return 2; // Return 'success - 2' 02442 } 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. 02443 02444 $insertFields = array( 02445 'md5hash' => $md5Hash, 02446 'tstamp' => time(), 02447 'filename' => $output, 02448 'orig_filename' => $orig 02449 ); 02450 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log')); 02451 $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_typo3temp_log', $insertFields); 02452 02453 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); 02454 return 0; 02455 } 02456 } 02457 } else { 02458 return @file_exists($output); 02459 } 02460 } 02461 02462 02463 02464 02465 02466 02467 02468 02469 02470 02471 02472 02473 02474 02475 02476 02477 02478 02479 /*********************************** 02480 * 02481 * ImageMagick API functions 02482 * 02483 ***********************************/ 02484 02492 function imageMagickIdentify($imagefile) { 02493 if (!$this->NO_IMAGE_MAGICK) { 02494 $frame = $this->noFramePrepended?'':'[0]'; 02495 $cmd = t3lib_div::imageMagickCommand('identify', $this->wrapFileName($imagefile).$frame); 02496 $returnVal = array(); 02497 exec($cmd, $returnVal); 02498 $splitstring=$returnVal[0]; 02499 $this->IM_commands[] = Array ('identify',$cmd,$returnVal[0]); 02500 if ($splitstring) { 02501 ereg('([^\.]*)$',$imagefile,$reg); 02502 $splitinfo = explode(' ', $splitstring); 02503 while (list($key,$val) = each($splitinfo)) { 02504 $temp = ''; 02505 if ($val) {$temp = explode('x', $val);} 02506 if (intval($temp[0]) && intval($temp[1])) { 02507 $dim=$temp; 02508 break; 02509 } 02510 } 02511 if ($dim[0] && $dim[1]) { 02512 return Array($dim[0], $dim[1], strtolower($reg[0]), $imagefile); 02513 } 02514 } 02515 } 02516 } 02517 02527 function imageMagickExec($input,$output,$params) { 02528 if (!$this->NO_IMAGE_MAGICK) { 02529 $cmd = t3lib_div::imageMagickCommand('convert', $params.' '.$this->wrapFileName($input).' '.$this->wrapFileName($output)); 02530 $this->IM_commands[] = array($output,$cmd); 02531 02532 $ret = exec($cmd); 02533 t3lib_div::fixPermissions($this->wrapFileName($output)); // Change the permissions of the file 02534 02535 return $ret; 02536 } 02537 } 02538 02550 function combineExec($input,$overlay,$mask,$output, $handleNegation = false) { 02551 if (!$this->NO_IMAGE_MAGICK) { 02552 $params = '-colorspace GRAY +matte'; 02553 if ($handleNegation) { 02554 if ($this->maskNegate) { 02555 $params .= ' '.$this->maskNegate; 02556 } 02557 } 02558 $theMask = $this->randomName().'.'.$this->gifExtension; 02559 $this->imageMagickExec($mask, $theMask, $params); 02560 $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 02561 $this->IM_commands[] = Array ($output,$cmd); 02562 02563 $ret = exec($cmd); 02564 t3lib_div::fixPermissions($this->wrapFileName($output)); // Change the permissions of the file 02565 02566 if (is_file($theMask)) { 02567 @unlink($theMask); 02568 } 02569 02570 return $ret; 02571 } 02572 } 02573 02581 function wrapFileName($inputName) { 02582 if (strstr($inputName,' ')) { 02583 $inputName='"'.$inputName.'"'; 02584 } 02585 return $inputName; 02586 } 02587 02588 02589 02590 02591 02592 02593 02594 02595 02596 02597 02598 02599 02600 02601 02602 02603 02604 02605 02606 02607 02608 02609 02610 /*********************************** 02611 * 02612 * Various IO functions 02613 * 02614 ***********************************/ 02615 02622 function checkFile($file) { 02623 if (@is_file($file)) { 02624 return $file; 02625 } else { 02626 return ''; 02627 } 02628 } 02629 02636 function createTempSubDir($dirName) { 02637 02638 // Checking if the this->tempPath is already prefixed with PATH_site and if not, prefix it with that constant. 02639 if (t3lib_div::isFirstPartOfStr($this->tempPath,PATH_site)) { 02640 $tmpPath = $this->tempPath; 02641 } else { 02642 $tmpPath = PATH_site.$this->tempPath; 02643 } 02644 02645 // Making the temporary filename: 02646 if (!@is_dir($tmpPath.$dirName)) { 02647 return t3lib_div::mkdir($tmpPath.$dirName); 02648 } 02649 } 02650 02658 function applyImageMagickToPHPGif(&$im, $command) { 02659 $tmpStr = $this->randomName(); 02660 $theFile = $tmpStr.'.'.$this->gifExtension; 02661 $this->ImageWrite($im, $theFile); 02662 $this->imageMagickExec($theFile,$theFile,$command); 02663 $tmpImg = $this->imageCreateFromFile($theFile); 02664 if ($tmpImg) { 02665 ImageDestroy($im); 02666 $im = $tmpImg; 02667 $this->w = imagesx($im); 02668 $this->h = imagesy($im); 02669 } 02670 if (!$this->dontUnlinkTempFiles) { 02671 unlink($theFile); 02672 } 02673 } 02674 02684 function gif_or_jpg($type,$w,$h) { 02685 if ($type=='ai' || $w*$h < $this->pixelLimitGif) { 02686 return $this->gifExtension; 02687 } else { 02688 return 'jpg'; 02689 } 02690 } 02691 02701 function output($file) { 02702 if ($file) { 02703 $reg = array(); 02704 ereg('([^\.]*)$',$file,$reg); 02705 $ext=strtolower($reg[0]); 02706 switch($ext) { 02707 case 'gif': 02708 case 'png': 02709 if ($this->ImageWrite($this->im, $file)) { 02710 // ImageMagick operations 02711 if ($this->setup['reduceColors'] || (!$this->png_truecolor && $this->truecolor)) { 02712 $reduced = $this->IMreduceColors($file, t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256)); 02713 if ($reduced) { 02714 @copy($reduced, $file); 02715 @unlink($reduced); 02716 } 02717 } 02718 t3lib_div::gif_compress($file, 'IM'); // Compress with IM! (adds extra compression, LZW from ImageMagick) (Workaround for the absence of lzw-compression in GD) 02719 } 02720 break; 02721 case 'jpg': 02722 case 'jpeg': 02723 $quality = 0; // Use the default 02724 if($this->setup['quality']) { 02725 $quality = t3lib_div::intInRange($this->setup['quality'],10,100); 02726 } 02727 if ($this->ImageWrite($this->im, $file, $quality)); 02728 break; 02729 } 02730 $GLOBALS['TEMP_IMAGES_ON_PAGE'][]=$file; 02731 } 02732 return $file; 02733 } 02734 02741 function destroy() { 02742 ImageDestroy($this->im); 02743 } 02744 02751 function imgTag ($imgInfo) { 02752 return '<img src="'.$imgInfo[3].'" width="'.$imgInfo[0].'" height="'.$imgInfo[1].'" border="0" alt="" />'; 02753 } 02754 02763 function ImageWrite($destImg, $theImage) { 02764 imageinterlace ($destImg,0); 02765 $ext = strtolower(substr($theImage, strrpos($theImage, '.')+1)); 02766 switch ($ext) { 02767 case 'jpg': 02768 case 'jpeg': 02769 if (function_exists('imageJpeg')) { 02770 return imageJpeg($destImg, $theImage, $this->jpegQuality); 02771 } 02772 break; 02773 case 'gif': 02774 if (function_exists('imageGif')) { 02775 if ($this->truecolor) { 02776 imagetruecolortopalette($destImg, true, 256); 02777 } 02778 return imageGif($destImg, $theImage); 02779 } 02780 break; 02781 case 'png': 02782 if (function_exists('imagePng')) { 02783 return ImagePng($destImg, $theImage); 02784 } 02785 break; 02786 } 02787 return false; // Extension invalid or write-function does not exist 02788 } 02789 02790 02791 02801 function imageGif($destImg, $theImage) { 02802 return $this->imageWrite($destImg, $theImage); 02803 } 02804 02813 function imageCreateFromGif($sourceImg) { 02814 return $this->imageCreateFromFile($sourceImg); 02815 } 02816 02824 function imageCreateFromFile($sourceImg) { 02825 $imgInf = pathinfo($sourceImg); 02826 $ext = strtolower($imgInf['extension']); 02827 02828 switch ($ext) { 02829 case 'gif': 02830 if (function_exists('imagecreatefromgif')) { 02831 return imageCreateFromGif($sourceImg); 02832 } 02833 break; 02834 case 'png': 02835 if (function_exists('imagecreatefrompng')) { 02836 return imageCreateFromPng($sourceImg); 02837 } 02838 break; 02839 case 'jpg': 02840 case 'jpeg': 02841 if (function_exists('imagecreatefromjpeg')) { 02842 return imageCreateFromJpeg($sourceImg); 02843 } 02844 break; 02845 } 02846 02847 // If non of the above: 02848 $i = @getimagesize($sourceImg); 02849 $im = $this->imagecreate($i[0],$i[1]); 02850 $Bcolor = ImageColorAllocate($im, 128,128,128); 02851 ImageFilledRectangle($im, 0, 0, $i[0], $i[1], $Bcolor); 02852 return $im; 02853 } 02854 02855 02863 function imagecreate($w, $h) { 02864 if($this->truecolor && function_exists('imagecreatetruecolor')) { 02865 return imagecreatetruecolor($w, $h); 02866 } else { 02867 return imagecreate($w, $h); 02868 } 02869 02870 } 02871 02878 function hexColor($col) { 02879 $r = dechex($col[0]); 02880 if (strlen($r)<2) { $r = '0'.$r; } 02881 $g = dechex($col[1]); 02882 if (strlen($g)<2) { $g = '0'.$g; } 02883 $b = dechex($col[2]); 02884 if (strlen($b)<2) { $b = '0'.$b; } 02885 return '#'.$r.$g.$b; 02886 } 02887 02896 function unifyColors(&$img, $colArr, $closest = false) { 02897 $retCol = -1; 02898 if (is_array($colArr) && count($colArr) && function_exists('imagepng') && function_exists('imagecreatefrompng')) { 02899 $firstCol = array_shift($colArr); 02900 $firstColArr = $this->convertColor($firstCol); 02901 if (count($colArr)>1) { 02902 $origName = $preName = $this->randomName().'.png'; 02903 $postName = $this->randomName().'.png'; 02904 $this->imageWrite($img, $preName); 02905 $firstCol = $this->hexColor($firstColArr); 02906 foreach ($colArr as $transparentColor) { 02907 $transparentColor = $this->convertColor($transparentColor); 02908 $transparentColor = $this->hexColor($transparentColor); 02909 $cmd = '-fill "'.$firstCol.'" -opaque "'.$transparentColor.'"'; 02910 $this->imageMagickExec($preName, $postName, $cmd); 02911 $preName = $postName; 02912 } 02913 $this->imageMagickExec($postName, $origName, ''); 02914 if (@is_file($origName)) { 02915 $tmpImg = $this->imageCreateFromFile($origName); 02916 } 02917 } else { 02918 $tmpImg = $img; 02919 } 02920 if ($tmpImg) { 02921 $img = $tmpImg; 02922 if ($closest) { 02923 $retCol = ImageColorClosest ($img, $firstColArr[0], $firstColArr[1], $firstColArr[2]); 02924 } else { 02925 $retCol = ImageColorExact ($img, $firstColArr[0], $firstColArr[1], $firstColArr[2]); 02926 } 02927 } 02928 // unlink files from process 02929 if (!$this->dontUnlinkTempFiles) { 02930 if ($origName) { 02931 @unlink($origName); 02932 } 02933 if ($postName) { 02934 @unlink($postName); 02935 } 02936 } 02937 } 02938 return $retCol; 02939 } 02940 02941 02942 } 02943 02944 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']) { 02945 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']); 02946 } 02947 ?>